Here are some simple examples of where you'll run into this error:
```compile_fail,E0106
-struct Foo { x: &bool } // error
-struct Foo<'a> { x: &'a bool } // correct
+struct Foo1 { x: &bool }
+ // ^ expected lifetime parameter
+struct Foo2<'a> { x: &'a bool } // correct
-struct Bar { x: Foo }
- ^^^ expected lifetime parameter
-struct Bar<'a> { x: Foo<'a> } // correct
+struct Bar1 { x: Foo2 }
+ // ^^^^ expected lifetime parameter
+struct Bar2<'a> { x: Foo2<'a> } // correct
-enum Bar { A(u8), B(&bool), } // error
-enum Bar<'a> { A(u8), B(&'a bool), } // correct
+enum Baz1 { A(u8), B(&bool), }
+ // ^ expected lifetime parameter
+enum Baz2<'a> { A(u8), B(&'a bool), } // correct
-type MyStr = &str; // error
-type MyStr<'a> = &'a str; // correct
+type MyStr1 = &str;
+ // ^ expected lifetime parameter
+type MyStr2<'a> = &'a str; // correct
```
Lifetime elision is a special, limited kind of inference for lifetimes in
rules: self.lower_block_check_mode(&b.rules),
span: b.span,
targeted_by_break,
+ recovered: b.recovered,
})
}
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
+ recovered: blk.recovered,
});
P(self.expr_block(blk, ThinVec::new()))
}
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
+ recovered: false,
}
}
stmts,
expr: Some(expr),
targeted_by_break: false,
+ recovered: false,
});
self.expr_block(block, attrs)
}
/// currently permitted in Rust itself, but it is generated as
/// part of `catch` statements.
pub targeted_by_break: bool,
+ /// If true, don't emit return value type errors as the parser had
+ /// to recover from a parse error so this block will not have an
+ /// appropriate type. A parse error will have been emitted so the
+ /// compilation will never succeed if this is true.
+ pub recovered: bool,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
rules,
span,
targeted_by_break,
+ recovered,
} = *self;
stmts.hash_stable(hcx, hasher);
expr.hash_stable(hcx, hasher);
rules.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
+ recovered.hash_stable(hcx, hasher);
targeted_by_break.hash_stable(hcx, hasher);
}
}
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
fn expr_to_block(rules: ast::BlockCheckMode,
+ recovered: bool,
e: Option<P<ast::Expr>>,
sess: &Session) -> P<ast::Block> {
P(ast::Block {
rules,
id: sess.next_node_id(),
span: syntax_pos::DUMMY_SP,
+ recovered,
})
}
if !self.within_static_or_const {
- let empty_block = expr_to_block(BlockCheckMode::Default, None, self.sess);
+ let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess);
let loop_expr = P(ast::Expr {
node: ast::ExprKind::Loop(empty_block, None),
id: self.sess.next_node_id(),
attrs: ast::ThinVec::new(),
});
- expr_to_block(b.rules, Some(loop_expr), self.sess)
+ expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess)
} else {
fold::noop_fold_block(b, self)
//
// #41425 -- label the implicit `()` as being the
// "found type" here, rather than the "expected type".
- if !self.diverges.get().always() {
+ //
+ // #44579 -- if the block was recovered during parsing,
+ // the type would be nonsensical and it is not worth it
+ // to perform the type check, so we avoid generating the
+ // diagnostic output.
+ if !self.diverges.get().always() && !blk.recovered {
coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
if let Some(expected_ty) = expected.only_has_type(self) {
self.consider_hint_about_removing_semicolon(blk,
/// Distinguishes between `unsafe { ... }` and `{ ... }`
pub rules: BlockCheckMode,
pub span: Span,
+ pub recovered: bool,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
id: ast::DUMMY_NODE_ID,
rules: BlockCheckMode::Default,
span,
+ recovered: false,
})
}
}
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
- b.map(|Block {id, stmts, rules, span}| Block {
+ b.map(|Block {id, stmts, rules, span, recovered}| Block {
id: folder.new_id(id),
stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
rules,
span: folder.new_span(span),
+ recovered,
})
}
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default, // no idea
span: sp(15,21),
+ recovered: false,
})),
vis: ast::Visibility::Inherited,
span: sp(0,21)})));
/// Precondition: already parsed the '{'.
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
let mut stmts = vec![];
+ let mut recovered = false;
while !self.eat(&token::CloseDelim(token::Brace)) {
let stmt = match self.parse_full_stmt(false) {
Err(mut err) => {
err.emit();
- self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Break);
+ self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
self.eat(&token::CloseDelim(token::Brace));
+ recovered = true;
break;
}
Ok(stmt) => stmt,
id: ast::DUMMY_NODE_ID,
rules: s,
span: lo.to(self.prev_span),
+ recovered,
}))
}
/// Parse a statement, including the trailing semicolon.
pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
- let mut stmt = match self.parse_stmt_(macro_legacy_warnings) {
+ let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
Some(stmt) => stmt,
None => return Ok(None),
};
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
span,
+ recovered: false,
}))
}
fn main () {
let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `,` or `>`, found `=`
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
- //~^ ERROR cannot find value `sr` in this scope
}
println!("Y {}",x);
return x;
};
- //~^ ERROR expected item, found `;`
caller(bar_handler);
}
// compile-flags: -Z parse-only
fn main() {
- struct::foo(); //~ ERROR expected identifier
- mut::baz(); //~ ERROR expected expression, found keyword `mut`
+ struct::foo();
+ //~^ ERROR expected identifier
+}
+fn bar() {
+ mut::baz();
+ //~^ ERROR expected expression, found keyword `mut`
}
pub fn main() {
struct Foo { x: isize }
let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{`
- //~^ ERROR expected item, found `=`
}
id: DUMMY_NODE_ID,
rules: BlockCheckMode::Default,
span: DUMMY_SP,
+ recovered: false,
});
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
},
0..;
..1;
0..1;
-
..=; //~ERROR inclusive range with no end
- 0..=; //~ERROR inclusive range with no end
+ //~^HELP bounded at the end
+}
+
+fn _foo1() {
..=1;
0..=1;
+ 0..=; //~ERROR inclusive range with no end
+ //~^HELP bounded at the end
}
-
-
error[E0586]: inclusive range with no end
- --> $DIR/impossible_range.rs:21:8
+ --> $DIR/impossible_range.rs:20:8
|
-21 | ..=; //~ERROR inclusive range with no end
+20 | ..=; //~ERROR inclusive range with no end
| ^
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/impossible_range.rs:22:9
+ --> $DIR/impossible_range.rs:27:9
|
-22 | 0..=; //~ERROR inclusive range with no end
+27 | 0..=; //~ERROR inclusive range with no end
| ^
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
18 | foo!(true); //~ ERROR expected type, found keyword
| ^^^^ expecting a type here because of type ascription
-error: aborting due to 2 previous errors
-
26 | m!();
| ----- in this macro invocation
-error: aborting due to 4 previous errors
-
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::env;
+
+pub struct Foo {
+ text: String
+}
+
+pub fn foo() -> Foo {
+ let args: Vec<String> = env::args().collect();
+ let text = args[1].clone();
+
+ pub Foo { text }
+}
+//~^^ ERROR missing `struct` for struct definition
+
+pub fn bar() -> Foo {
+ fn
+ Foo { text: "".to_string() }
+}
+//~^^ ERROR expected one of `(` or `<`, found `{`
+
+fn main() {}
--- /dev/null
+error: missing `struct` for struct definition
+ --> $DIR/recovered-block.rs:21:8
+ |
+21 | pub Foo { text }
+ | ^
+help: add `struct` here to parse `Foo` as a public struct
+ |
+21 | pub struct Foo { text }
+ | ^^^^^^
+
+error: expected one of `(` or `<`, found `{`
+ --> $DIR/recovered-block.rs:27:9
+ |
+27 | Foo { text: "".to_string() }
+ | ^ expected one of `(` or `<` here
+
+error: aborting due to 2 previous errors
+
}
//~^ ERROR: incorrect close delimiter: `}`
//~| ERROR: incorrect close delimiter: `}`
-//~| ERROR: expected expression, found `)`
14 | foo(bar(;
| ^
-error: expected expression, found `)`
- --> $DIR/token-error-correct.rs:16:1
- |
-16 | }
- | ^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors