@@ -105,21 +105,30 @@ impl AstRewriter {
105105 // - `item_span` is set to `expr.span()` so that any errors reported
106106 // for the spec item will be reported on the span of the expression
107107 // written by the user
108- // - `let ... : bool = #expr ` syntax is used to report type errors in the
108+ // - `((#expr) : bool) ` syntax is used to report type errors in the
109109 // expression with the correct error message, i.e. that the expected
110110 // type is `bool`, not that the expected *return* type is `bool`
111- let return_type = match & spec_type {
112- SpecItemType :: Termination => quote_spanned ! { item_span => Int } ,
113- SpecItemType :: Predicate ( return_type) => return_type. clone ( ) ,
114- _ => quote_spanned ! { item_span => bool } ,
111+ // - `!!(...)` is used to fix an edge-case when the expression consists
112+ // of a single identifier; without the double negation, the `Return`
113+ // terminator in MIR has a span set to the one character just after
114+ // the identifier
115+ let ( return_type, return_modifier) = match & spec_type {
116+ SpecItemType :: Termination => (
117+ quote_spanned ! { item_span => Int } ,
118+ quote_spanned ! { item_span => Int :: new( 0 ) + } ,
119+ ) ,
120+ SpecItemType :: Predicate ( return_type) => ( return_type. clone ( ) , TokenStream :: new ( ) ) ,
121+ _ => (
122+ quote_spanned ! { item_span => bool } ,
123+ quote_spanned ! { item_span => !!} ,
124+ ) ,
115125 } ;
116126 let mut spec_item: syn:: ItemFn = parse_quote_spanned ! { item_span=>
117127 #[ allow( unused_must_use, unused_parens, unused_variables, dead_code, non_snake_case) ]
118128 #[ prusti:: spec_only]
119129 #[ prusti:: spec_id = #spec_id_str]
120130 fn #item_name( ) -> #return_type {
121- let prusti_result: #return_type = #expr;
122- prusti_result
131+ #return_modifier ( ( #expr) : #return_type)
123132 }
124133 } ;
125134
0 commit comments