Skip to content

Commit

Permalink
Fix unwrap error when compiled with stable
Browse files Browse the repository at this point in the history
JonasAlaif committed Sep 29, 2022
1 parent a3e7b37 commit 5888f0c
Showing 3 changed files with 21 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -32,8 +32,7 @@ fn rewrite_extern_spec_internal(item_impl: &syn::ItemImpl) -> syn::Result<Rewrit
#struct_ident #generic_args
};

if item_impl.trait_.is_some() {
let (_, trait_path, _) = item_impl.trait_.as_ref().unwrap();
if let Some((_, trait_path, _)) = &item_impl.trait_ {
if has_generic_arguments(trait_path) {
return Err(syn::Error::new(
item_impl.generics.params.span(),
Original file line number Diff line number Diff line change
@@ -66,9 +66,8 @@ fn generate_new_struct(item_trait: &syn::ItemTrait) -> syn::Result<GeneratedStru
};

// Add a where clause which restricts this self type parameter to the trait
if item_trait.generics.where_clause.as_ref().is_some() {
let span = item_trait.generics.where_clause.as_ref().unwrap().span();
return Err(syn::Error::new(span, "Where clauses for extern traits specs are not supported"));
if let Some(where_clause) = &item_trait.generics.where_clause {
return Err(syn::Error::new(where_clause.span(), "Where clauses for extern traits specs are not supported"));
}
let self_where_clause: syn::WhereClause = parse_quote! {
where #self_type_ident: #self_type_trait
@@ -140,9 +139,9 @@ impl<'a> GeneratedStruct<'a> {
));
}
syn::TraitItem::Method(trait_method) => {
if trait_method.default.is_some() {
if let Some(default) = &trait_method.default {
return Err(syn::Error::new(
trait_method.default.as_ref().unwrap().span(),
default.span(),
"Default methods in external trait specs are invalid",
));
}
31 changes: 16 additions & 15 deletions prusti-contracts/prusti-specs/src/specifications/preparser.rs
Original file line number Diff line number Diff line change
@@ -172,12 +172,10 @@ impl PrustiTokenStream {
{
let result = f(&mut self)?;
if !self.is_empty() {
let start = self.tokens.front().unwrap().span();
let end = self.tokens.back().unwrap().span();
let span = start.join(end);
// this is None if the spans are not combinable, which seems to happen when running the cfg(tests) via cargo
let error_span = span.unwrap_or(start);
return err(error_span, "unexpected extra tokens");
let start = self.tokens.front().expect("unreachable").span();
let end = self.tokens.back().expect("unreachable").span();
let span = join_spans(start, end);
return err(span, "unexpected extra tokens");
}
Ok(result)
}
@@ -227,12 +225,10 @@ impl PrustiTokenStream {
TokenStream
)> {
let mut pledge_ops = self.split(PrustiBinaryOp::Rust(RustOp::Arrow), false);
let (reference, body) = if pledge_ops.len() == 1 {
(None, pledge_ops.pop().unwrap())
} else if pledge_ops.len() == 2 {
(Some(pledge_ops[0].expr_bp(0)?), pledge_ops.pop().unwrap())
} else {
return err(Span::call_site(), "too many arrows in assert_on_expiry");
let (reference, body) = match (pledge_ops.pop(), pledge_ops.pop(), pledge_ops.pop()) {
(Some(body), None, _) => (None, body),
(Some(body), Some(mut reference), None) => (Some(reference.expr_bp(0)?), body),
_ => return err(Span::call_site(), "too many arrows in assert_on_expiry"),
};
let mut body_parts = body.split(PrustiBinaryOp::Rust(RustOp::Comma), false);
if body_parts.len() == 2 {
@@ -507,7 +503,7 @@ impl Parse for GhostConstraint {
Ok(GhostConstraint {
trait_bounds: parse_trait_bounds(input)?,
comma: input.parse().map_err(with_ghost_constraint_example)?,
specs: PrustiTokenStream::new(input.parse().unwrap())
specs: PrustiTokenStream::new(input.parse().expect("Failed to parse GhostConstraint"))
.parse_rest(|pts| pts.pop_group_of_nested_specs(input.span()))?,
})
}
@@ -745,7 +741,7 @@ impl PrustiToken {
p1: &Punct,
p2: &Punct,
) -> Option<Self> {
let span = p1.span().join(p2.span()).unwrap();
let span = join_spans(p1.span(), p2.span());
Some(Self::BinOp(span, if operator2("&&", p1, p2) {
PrustiBinaryOp::And
} else if operator2("||", p1, p2) {
@@ -786,7 +782,7 @@ impl PrustiToken {
p2: &Punct,
p3: &Punct,
) -> Option<Self> {
let span = p1.span().join(p2.span()).unwrap().join(p3.span()).unwrap();
let span = join_spans(join_spans(p1.span(), p2.span()), p3.span());
Some(Self::BinOp(span, if operator3("==>", p1, p2, p3) {
PrustiBinaryOp::Implies
} else if operator3("===", p1, p2, p3) {
@@ -908,6 +904,11 @@ impl RustOp {
}
}

fn join_spans(s1: Span, s2: Span) -> Span {
// This works even when compiled with stable, compared to `s1.join(s2)`
s1.unwrap().join(s2.unwrap()).expect("Failed to join spans!").into()
}

#[cfg(test)]
mod tests {
use super::*;

0 comments on commit 5888f0c

Please sign in to comment.