Rollup merge of #69760 - Centril:parse-expr-improve, r=estebank

Improve expression & attribute parsing

This PR includes misc improvements to expression and attribute parsing.

1. Some code simplifications
2. Better recovery for various block forms, e.g. `loop statements }` (missing `{` after `loop`). (See e.g., `block-no-opening-brace.rs` among others for examples.)
3. Added recovery for e.g., `unsafe $b` where `$b` refers to a `block` macro fragment. (See `bad-interpolated-block.rs` for examples.)
4. ^--- These are done so that code sharing in block parsing is increased.
5. Added recovery for e.g., `'label: loop { ... }` (See `labeled-no-colon-expr.rs`.)
6. Added recovery for e.g., `&'lifetime expr` (See `regions-out-of-scope-slice.rs`.)
7. Added recovery for e.g., `fn foo() = expr;` (See `fn-body-eq-expr-semi.rs`.)
8. Simplified attribute parsing code & slightly improved diagnostics.
9. Added recovery for e.g., `Box<('a) + Trait>`.
10. Added recovery for e.g, `if true #[attr] {} else #[attr] {} else #[attr] if true {}`.

r? @estebank
This commit is contained in:
Mazdak Farrokhzad 2020-03-11 14:03:45 +01:00 committed by GitHub
commit 9674c09ae9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 926 additions and 401 deletions

View File

@ -535,6 +535,16 @@ impl Token {
false
}
// Is the token an interpolated block (`$b:block`)?
pub fn is_whole_block(&self) -> bool {
if let Interpolated(ref nt) = self.kind {
if let NtBlock(..) = **nt {
return true;
}
}
false
}
/// Returns `true` if the token is either the `mut` or `const` keyword.
pub fn is_mutability(&self) -> bool {
self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)

View File

@ -2,6 +2,7 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(bindings_after_at)]
use rustc_ast::ast;
use rustc_ast::token::{self, Nonterminal};

View File

@ -1,4 +1,4 @@
use super::{Parser, PathStyle, TokenType};
use super::{Parser, PathStyle};
use rustc_ast::ast;
use rustc_ast::attr;
use rustc_ast::token::{self, Nonterminal};
@ -10,14 +10,20 @@ use rustc_span::{Span, Symbol};
use log::debug;
#[derive(Debug)]
enum InnerAttributeParsePolicy<'a> {
pub(super) enum InnerAttrPolicy<'a> {
Permitted,
NotPermitted { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
}
const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
permitted in this context";
pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
saw_doc_comment: false,
prev_attr_sp: None,
};
impl<'a> Parser<'a> {
/// Parses attributes that appear before an item.
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
@ -25,48 +31,44 @@ impl<'a> Parser<'a> {
let mut just_parsed_doc_comment = false;
loop {
debug!("parse_outer_attributes: self.token={:?}", self.token);
match self.token.kind {
token::Pound => {
let inner_error_reason = if just_parsed_doc_comment {
"an inner attribute is not permitted following an outer doc comment"
} else if !attrs.is_empty() {
"an inner attribute is not permitted following an outer attribute"
} else {
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
};
let inner_parse_policy = InnerAttributeParsePolicy::NotPermitted {
reason: inner_error_reason,
saw_doc_comment: just_parsed_doc_comment,
prev_attr_sp: attrs.last().map(|a| a.span),
};
let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
attrs.push(attr);
just_parsed_doc_comment = false;
}
token::DocComment(s) => {
let attr = self.mk_doc_comment(s);
if attr.style != ast::AttrStyle::Outer {
let span = self.token.span;
let mut err = self.struct_span_err(span, "expected outer doc comment");
err.note(
if self.check(&token::Pound) {
let inner_error_reason = if just_parsed_doc_comment {
"an inner attribute is not permitted following an outer doc comment"
} else if !attrs.is_empty() {
"an inner attribute is not permitted following an outer attribute"
} else {
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
};
let inner_parse_policy = InnerAttrPolicy::Forbidden {
reason: inner_error_reason,
saw_doc_comment: just_parsed_doc_comment,
prev_attr_sp: attrs.last().map(|a| a.span),
};
let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
attrs.push(attr);
just_parsed_doc_comment = false;
} else if let token::DocComment(s) = self.token.kind {
let attr = self.mk_doc_comment(s);
if attr.style != ast::AttrStyle::Outer {
self.struct_span_err(self.token.span, "expected outer doc comment")
.note(
"inner doc comments like this (starting with \
`//!` or `/*!`) can only appear before items",
);
return Err(err);
}
attrs.push(attr);
self.bump();
just_parsed_doc_comment = true;
`//!` or `/*!`) can only appear before items",
)
.emit();
}
_ => break,
attrs.push(attr);
self.bump();
just_parsed_doc_comment = true;
} else {
break;
}
}
Ok(attrs)
}
fn mk_doc_comment(&self, s: Symbol) -> ast::Attribute {
let style = comments::doc_comment_style(&s.as_str());
attr::mk_doc_comment(style, s, self.token.span)
attr::mk_doc_comment(comments::doc_comment_style(&s.as_str()), s, self.token.span)
}
/// Matches `attribute = # ! [ meta_item ]`.
@ -75,96 +77,67 @@ impl<'a> Parser<'a> {
/// attribute.
pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, self.token);
let inner_parse_policy = if permit_inner {
InnerAttributeParsePolicy::Permitted
} else {
InnerAttributeParsePolicy::NotPermitted {
reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
saw_doc_comment: false,
prev_attr_sp: None,
}
};
let inner_parse_policy =
if permit_inner { InnerAttrPolicy::Permitted } else { DEFAULT_INNER_ATTR_FORBIDDEN };
self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
}
/// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy`
/// The same as `parse_attribute`, except it takes in an `InnerAttrPolicy`
/// that prescribes how to handle inner attributes.
fn parse_attribute_with_inner_parse_policy(
&mut self,
inner_parse_policy: InnerAttributeParsePolicy<'_>,
inner_parse_policy: InnerAttrPolicy<'_>,
) -> PResult<'a, ast::Attribute> {
debug!(
"parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
inner_parse_policy, self.token
);
let (span, item, style) = match self.token.kind {
token::Pound => {
let lo = self.token.span;
self.bump();
let lo = self.token.span;
let (span, item, style) = if self.eat(&token::Pound) {
let style =
if self.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
self.expected_tokens.push(TokenType::Token(token::Not));
}
self.expect(&token::OpenDelim(token::Bracket))?;
let item = self.parse_attr_item()?;
self.expect(&token::CloseDelim(token::Bracket))?;
let attr_sp = lo.to(self.prev_token.span);
let style = if self.token == token::Not {
self.bump();
ast::AttrStyle::Inner
} else {
ast::AttrStyle::Outer
};
self.expect(&token::OpenDelim(token::Bracket))?;
let item = self.parse_attr_item()?;
self.expect(&token::CloseDelim(token::Bracket))?;
let hi = self.prev_token.span;
let attr_sp = lo.to(hi);
// Emit error if inner attribute is encountered and not permitted
if style == ast::AttrStyle::Inner {
if let InnerAttributeParsePolicy::NotPermitted {
reason,
saw_doc_comment,
prev_attr_sp,
} = inner_parse_policy
{
let prev_attr_note = if saw_doc_comment {
"previous doc comment"
} else {
"previous outer attribute"
};
let mut diagnostic = self.struct_span_err(attr_sp, reason);
if let Some(prev_attr_sp) = prev_attr_sp {
diagnostic
.span_label(attr_sp, "not permitted following an outer attribute")
.span_label(prev_attr_sp, prev_attr_note);
}
diagnostic
.note(
"inner attributes, like `#![no_std]`, annotate the item \
enclosing them, and are usually found at the beginning of \
source files. Outer attributes, like `#[test]`, annotate the \
item following them.",
)
.emit();
}
}
(attr_sp, item, style)
}
_ => {
let token_str = pprust::token_to_string(&self.token);
let msg = &format!("expected `#`, found `{}`", token_str);
return Err(self.struct_span_err(self.token.span, msg));
// Emit error if inner attribute is encountered and forbidden.
if style == ast::AttrStyle::Inner {
self.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
}
(attr_sp, item, style)
} else {
let token_str = pprust::token_to_string(&self.token);
let msg = &format!("expected `#`, found `{}`", token_str);
return Err(self.struct_span_err(self.token.span, msg));
};
Ok(attr::mk_attr_from_item(style, item, span))
}
pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
let prev_attr_note =
if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" };
let mut diag = self.struct_span_err(attr_sp, reason);
if let Some(prev_attr_sp) = prev_attr_sp {
diag.span_label(attr_sp, "not permitted following an outer attribute")
.span_label(prev_attr_sp, prev_attr_note);
}
diag.note(
"inner attributes, like `#![no_std]`, annotate the item enclosing them, \
and are usually found at the beginning of source files. \
Outer attributes, like `#[test]`, annotate the item following them.",
)
.emit();
}
}
/// Parses an inner part of an attribute (the path and following tokens).
/// The tokens must be either a delimited token stream, or empty token stream,
/// or the "legacy" key-value form.
@ -200,28 +173,22 @@ impl<'a> Parser<'a> {
crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = vec![];
loop {
match self.token.kind {
token::Pound => {
// Don't even try to parse if it's not an inner attribute.
if !self.look_ahead(1, |t| t == &token::Not) {
break;
}
let attr = self.parse_attribute(true)?;
assert_eq!(attr.style, ast::AttrStyle::Inner);
// Only try to parse if it is an inner attribute (has `!`).
if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) {
let attr = self.parse_attribute(true)?;
assert_eq!(attr.style, ast::AttrStyle::Inner);
attrs.push(attr);
} else if let token::DocComment(s) = self.token.kind {
// We need to get the position of this token before we bump.
let attr = self.mk_doc_comment(s);
if attr.style == ast::AttrStyle::Inner {
attrs.push(attr);
self.bump();
} else {
break;
}
token::DocComment(s) => {
// We need to get the position of this token before we bump.
let attr = self.mk_doc_comment(s);
if attr.style == ast::AttrStyle::Inner {
attrs.push(attr);
self.bump();
} else {
break;
}
}
_ => break,
} else {
break;
}
}
Ok(attrs)
@ -232,12 +199,10 @@ impl<'a> Parser<'a> {
debug!("checking if {:?} is unusuffixed", lit);
if !lit.kind.is_unsuffixed() {
let msg = "suffixed literals are not allowed in attributes";
self.struct_span_err(lit.span, msg)
self.struct_span_err(lit.span, "suffixed literals are not allowed in attributes")
.help(
"instead of using a suffixed literal \
(`1u8`, `1.0f32`, etc.), use an unsuffixed version \
(`1`, `1.0`, etc.)",
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
use an unsuffixed version (`1`, `1.0`, etc.)",
)
.emit();
}

View File

@ -673,10 +673,28 @@ impl<'a> Parser<'a> {
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.expect_and()?;
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
let expr = self.parse_prefix_expr(None);
let (span, expr) = self.interpolated_or_expr_span(expr)?;
Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr)))
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
let span = lo.to(hi);
if let Some(lt) = lifetime {
self.error_remove_borrow_lifetime(span, lt.ident.span);
}
Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
}
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
.span_label(lt_span, "annotated with lifetime here")
.span_suggestion(
lt_span,
"remove the lifetime annotation",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
/// Parse `mut?` or `raw [ const | mut ]`.
@ -901,7 +919,7 @@ impl<'a> Parser<'a> {
} else if self.eat_lt() {
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
} else if self.token.is_path_start() {
} else if self.check_path() {
self.parse_path_start_expr(attrs)
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
self.parse_closure_expr(attrs)
@ -1067,26 +1085,44 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr, true)
}
/// Parse `'label: $expr`. The label is already parsed.
fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = label.ident.span;
self.expect(&token::Colon)?;
if self.eat_keyword(kw::While) {
return self.parse_while_expr(Some(label), lo, attrs);
}
if self.eat_keyword(kw::For) {
return self.parse_for_expr(Some(label), lo, attrs);
}
if self.eat_keyword(kw::Loop) {
return self.parse_loop_expr(Some(label), lo, attrs);
}
if self.token == token::OpenDelim(token::Brace) {
return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs);
let label = Some(label);
let ate_colon = self.eat(&token::Colon);
let expr = if self.eat_keyword(kw::While) {
self.parse_while_expr(label, lo, attrs)
} else if self.eat_keyword(kw::For) {
self.parse_for_expr(label, lo, attrs)
} else if self.eat_keyword(kw::Loop) {
self.parse_loop_expr(label, lo, attrs)
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
} else {
let msg = "expected `while`, `for`, `loop` or `{` after a label";
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
self.parse_expr()
}?;
if !ate_colon {
self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
}
let msg = "expected `while`, `for`, `loop` or `{` after a label";
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
self.parse_expr()
Ok(expr)
}
fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
self.struct_span_err(span, "labeled expression must be followed by `:`")
.span_label(lo, "the label")
.span_suggestion_short(
lo.shrink_to_hi(),
"add `:` after the label",
": ".to_string(),
Applicability::MachineApplicable,
)
.note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
.emit();
}
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
@ -1363,18 +1399,20 @@ impl<'a> Parser<'a> {
opt_label: Option<Label>,
lo: Span,
blk_mode: BlockCheckMode,
outer_attrs: AttrVec,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
if let Some(label) = opt_label {
self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
}
self.expect(&token::OpenDelim(token::Brace))?;
if self.token.is_whole_block() {
self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
.span_label(lo.to(self.token.span), "the `block` fragment is within this context")
.emit();
}
let mut attrs = outer_attrs;
attrs.extend(self.parse_inner_attributes()?);
let blk = self.parse_block_tail(lo, blk_mode)?;
let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?;
attrs.extend(inner_attrs);
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
}
@ -1476,13 +1514,16 @@ impl<'a> Parser<'a> {
let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
self.error_missing_if_cond(lo, cond.span)
} else {
let attrs = self.parse_outer_attributes()?; // For recovery.
let not_block = self.token != token::OpenDelim(token::Brace);
self.parse_block().map_err(|mut err| {
let block = self.parse_block().map_err(|mut err| {
if not_block {
err.span_label(lo, "this `if` expression has a condition, but no block");
}
err
})?
})?;
self.error_on_if_block_attrs(lo, false, block.span, &attrs);
block
};
let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs))
@ -1524,12 +1565,40 @@ impl<'a> Parser<'a> {
/// Parses an `else { ... }` expression (`else` token already eaten).
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
if self.eat_keyword(kw::If) {
self.parse_if_expr(AttrVec::new())
let ctx_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?; // For recovery.
let expr = if self.eat_keyword(kw::If) {
self.parse_if_expr(AttrVec::new())?
} else {
let blk = self.parse_block()?;
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
}
self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())
};
self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs);
Ok(expr)
}
fn error_on_if_block_attrs(
&self,
ctx_span: Span,
is_ctx_else: bool,
branch_span: Span,
attrs: &[ast::Attribute],
) {
let (span, last) = match attrs {
[] => return,
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
};
let ctx = if is_ctx_else { "else" } else { "if" };
self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
.span_label(branch_span, "the attributes are attached to this branch")
.span_label(ctx_span, format!("the branch belongs to this `{}`", ctx))
.span_suggestion(
span,
"remove the attributes",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).

View File

@ -218,7 +218,7 @@ impl<'a> Parser<'a> {
} else if vis.node.is_pub() && self.isnt_macro_invocation() {
self.recover_missing_kw_before_item()?;
return Ok(None);
} else if macros_allowed && self.token.is_path_start() {
} else if macros_allowed && self.check_path() {
// MACRO INVOCATION ITEM
(Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?))
} else {
@ -352,8 +352,7 @@ impl<'a> Parser<'a> {
fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
let (start, end) = match attrs {
[] => return Ok(()),
[x0] => (x0, x0),
[x0, .., xn] => (x0, xn),
[x0 @ xn] | [x0, .., xn] => (x0, xn),
};
let msg = if end.is_doc_comment() {
"expected item after doc comment"
@ -1411,23 +1410,28 @@ impl<'a> Parser<'a> {
/// This can either be `;` when there's no body,
/// or e.g. a block when the function is a provided one.
fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
let (inner_attrs, body) = match self.token.kind {
token::Semi => {
self.bump();
(Vec::new(), None)
}
token::OpenDelim(token::Brace) => {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
(attrs, Some(body))
}
token::Interpolated(ref nt) => match **nt {
token::NtBlock(..) => {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
(attrs, Some(body))
}
_ => return self.expected_semi_or_open_brace(),
},
_ => return self.expected_semi_or_open_brace(),
let (inner_attrs, body) = if self.check(&token::Semi) {
self.bump(); // `;`
(Vec::new(), None)
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
} else if self.token.kind == token::Eq {
// Recover `fn foo() = $expr;`.
self.bump(); // `=`
let eq_sp = self.prev_token.span;
let _ = self.parse_expr()?;
self.expect_semi()?; // `;`
let span = eq_sp.to(self.prev_token.span);
self.struct_span_err(span, "function body cannot be `= expression;`")
.multipart_suggestion(
"surround the expression with `{` and `}` instead of `=` and `;`",
vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
Applicability::MachineApplicable,
)
.emit();
(Vec::new(), Some(self.mk_block_err(span)))
} else {
return self.expected_semi_or_open_brace();
};
attrs.extend(inner_attrs);
Ok(body)

View File

@ -704,7 +704,7 @@ impl<'a> Parser<'a> {
}
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
if self.token.is_path_start() {
if self.check_path() {
let lo = self.token.span;
let (qself, path) = if self.eat_lt() {
// Parse a qualified path

View File

@ -1,3 +1,4 @@
use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
use super::diagnostics::Error;
use super::expr::LhsExpr;
use super::pat::GateOr;
@ -47,10 +48,7 @@ impl<'a> Parser<'a> {
self.bump(); // `var`
let msg = "write `let` instead of `var` to introduce a new variable";
self.recover_stmt_local(lo, attrs.into(), msg, "let")?
} else if self.token.is_path_start()
&& !self.token.is_qpath_start()
&& !self.is_path_start_item()
{
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
// that starts like a path (1 token), but it fact not a path.
@ -238,15 +236,11 @@ impl<'a> Parser<'a> {
/// Parses a block. No inner attributes are allowed.
pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
maybe_whole!(self, NtBlock, |x| x);
let lo = self.token.span;
if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace();
let (attrs, block) = self.parse_inner_attrs_and_block()?;
if let [.., last] = &*attrs {
self.error_on_forbidden_inner_attr(last.span, DEFAULT_INNER_ATTR_FORBIDDEN);
}
self.parse_block_tail(lo, BlockCheckMode::Default)
Ok(block)
}
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
@ -262,16 +256,14 @@ impl<'a> Parser<'a> {
//
// which is valid in other languages, but not Rust.
match self.parse_stmt_without_recovery() {
Ok(Some(stmt)) => {
// If the next token is an open brace (e.g., `if a b {`), the place-
// inside-a-block suggestion would be more likely wrong than right.
Ok(Some(_))
if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|| do_not_suggest_help
{
// If the next token is an open brace (e.g., `if a b {`), the place-
// inside-a-block suggestion would be more likely wrong than right.
e.span_label(sp, "expected `{`");
return Err(e);
}
let stmt_span = if self.eat(&token::Semi) {
|| do_not_suggest_help => {}
Ok(Some(stmt)) => {
let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp);
let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
// Expand the span to include the semicolon.
stmt.span.with_hi(self.prev_token.span.hi())
} else {
@ -300,21 +292,28 @@ impl<'a> Parser<'a> {
/// Parses a block. Inner attributes are allowed.
pub(super) fn parse_inner_attrs_and_block(
&mut self,
) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
self.parse_block_common(self.token.span, BlockCheckMode::Default)
}
/// Parses a block. Inner attributes are allowed.
pub(super) fn parse_block_common(
&mut self,
lo: Span,
blk_mode: BlockCheckMode,
) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
let lo = self.token.span;
self.expect(&token::OpenDelim(token::Brace))?;
Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?))
if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace();
}
Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, blk_mode)?))
}
/// Parses the rest of a block expression or function body.
/// Precondition: already parsed the '{'.
pub(super) fn parse_block_tail(
&mut self,
lo: Span,
s: BlockCheckMode,
) -> PResult<'a, P<Block>> {
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
let mut stmts = vec![];
while !self.eat(&token::CloseDelim(token::Brace)) {
if self.token == token::Eof {

View File

@ -142,24 +142,20 @@ impl<'a> Parser<'a> {
} else {
let path = self.parse_path(PathStyle::Type)?;
let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
}
} else if self.eat_keyword(kw::Impl) {
self.parse_impl_ty(&mut impl_dyn_multi)?
} else if self.is_explicit_dyn_type() {
self.parse_dyn_ty(&mut impl_dyn_multi)?
} else if self.check(&token::Question)
|| self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus())
{
// Bound list (trait object type)
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
TyKind::TraitObject(bounds, TraitObjectSyntax::None)
} else if self.eat_lt() {
// Qualified path
let (qself, path) = self.parse_qpath(PathStyle::Type)?;
TyKind::Path(Some(qself), path)
} else if self.token.is_path_start() {
} else if self.check_path() {
self.parse_path_start_ty(lo, allow_plus)?
} else if self.can_begin_bound() {
self.parse_bare_trait_object(lo, allow_plus)?
} else if self.eat(&token::DotDotDot) {
if allow_c_variadic == AllowCVariadic::Yes {
TyKind::CVarArgs
@ -203,21 +199,12 @@ impl<'a> Parser<'a> {
match ty.kind {
// `(TY_BOUND_NOPAREN) + BOUND + ...`.
TyKind::Path(None, path) if maybe_bounds => {
self.parse_remaining_bounds(Vec::new(), path, lo, true)
self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
}
TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)
TyKind::TraitObject(bounds, TraitObjectSyntax::None)
if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
{
let path = match bounds.remove(0) {
GenericBound::Trait(pt, ..) => pt.trait_ref.path,
GenericBound::Outlives(..) => {
return Err(self.struct_span_err(
ty.span,
"expected trait bound, not lifetime bound",
));
}
};
self.parse_remaining_bounds(Vec::new(), path, lo, true)
self.parse_remaining_bounds(bounds, true)
}
// `(TYPE)`
_ => Ok(TyKind::Paren(P(ty))),
@ -227,18 +214,35 @@ impl<'a> Parser<'a> {
}
}
fn parse_remaining_bounds(
fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
if lt_no_plus {
self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`").emit()
}
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
}
fn parse_remaining_bounds_path(
&mut self,
generic_params: Vec<GenericParam>,
path: ast::Path,
lo: Span,
parse_plus: bool,
) -> PResult<'a, TyKind> {
assert_ne!(self.token, token::Question);
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
if parse_plus {
let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
self.parse_remaining_bounds(bounds, parse_plus)
}
/// Parse the remainder of a bare trait object type given an already parsed list.
fn parse_remaining_bounds(
&mut self,
mut bounds: GenericBounds,
plus: bool,
) -> PResult<'a, TyKind> {
assert_ne!(self.token, token::Question);
if plus {
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
}
@ -358,7 +362,7 @@ impl<'a> Parser<'a> {
}))
} else if allow_plus == AllowPlus::Yes && self.check_plus() {
// `Trait1 + Trait2 + 'a`
self.parse_remaining_bounds(Vec::new(), path, lo, true)
self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
} else {
// Just a type path.
Ok(TyKind::Path(None, path))

View File

@ -517,6 +517,13 @@ impl SourceMap {
Ok((lo, hi))
}
pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
match self.span_to_prev_source(sp) {
Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false),
Err(_) => false,
}
}
pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
debug!("span_to_lines(sp={:?})", sp);
let (lo, hi) = self.is_valid_span(sp)?;

View File

@ -32,11 +32,11 @@ LL | X() {}
LL | }
| - the item list ends here
error: expected `[`, found `#`
error: expected one of `!` or `[`, found `#`
--> $DIR/issue-40006.rs:19:17
|
LL | fn xxx() { ### }
| ^ expected `[`
| ^ expected one of `!` or `[`
error: expected one of `!` or `::`, found `=`
--> $DIR/issue-40006.rs:22:7

View File

@ -3,7 +3,7 @@
trait Foo {
type Bar<,>;
//~^ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
//~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
}
fn main() {}

View File

@ -1,10 +1,10 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,`
error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/empty_generics.rs:5:14
|
LL | trait Foo {
| - while parsing this item list starting here
LL | type Bar<,>;
| ^ expected one of `>`, `const`, identifier, or lifetime
| ^ expected one of `#`, `>`, `const`, identifier, or lifetime
LL |
LL | }
| - the item list ends here

View File

@ -8,7 +8,7 @@ fn if_else_parse_error() {
#[cfg(FALSE)]
fn else_attr_ifparse_error() {
if true {
} else #[attr] if false { //~ ERROR expected
} else #[attr] if false { //~ ERROR outer attributes are not allowed
} else {
}
}

View File

@ -4,18 +4,17 @@ error: expected expression, found keyword `else`
LL | } #[attr] else if false {
| ^^^^ expected expression
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/else-attrs.rs:11:12
|
LL | } else #[attr] if false {
| ^ expected `{`
|
help: try placing this code inside a block
|
LL | } else #[attr] { if false {
LL | } else {
LL | } }
|
LL | } else #[attr] if false {
| _______----_^^^^^^^_-
| | | |
| | | help: remove the attributes
| | the branch belongs to this `else`
LL | | } else {
LL | | }
| |_____- the attributes are attached to this branch
error: expected expression, found keyword `else`
--> $DIR/else-attrs.rs:20:15

View File

@ -29,7 +29,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
type Type_8<'a,,> = &'a ();
//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
//type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`

View File

@ -1,8 +1,8 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,`
error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/issue-20616-8.rs:31:16
|
LL | type Type_8<'a,,> = &'a ();
| ^ expected one of `>`, `const`, identifier, or lifetime
| ^ expected one of `#`, `>`, `const`, identifier, or lifetime
error: aborting due to previous error

View File

@ -32,4 +32,4 @@ type Type_5_<'a> = Type_1_<'a, ()>;
type Type_9<T,,> = Box<T>;
//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`

View File

@ -1,8 +1,8 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,`
error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/issue-20616-9.rs:34:15
|
LL | type Type_9<T,,> = Box<T>;
| ^ expected one of `>`, `const`, identifier, or lifetime
| ^ expected one of `#`, `>`, `const`, identifier, or lifetime
error: aborting due to previous error

Binary file not shown.

View File

@ -2,7 +2,10 @@ error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:6:12
|
LL | unsafe 'b: {}
| ^^ expected `{`
| ^^----
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:10:13

View File

@ -39,35 +39,35 @@ fn main() {}
#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
//~^ ERROR expected one of
#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
//~^ ERROR expected one of
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
//~^ ERROR expected `{`, found `#`
//~^ ERROR outer attributes are not allowed on `if`
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context

View File

@ -136,14 +136,14 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:41:37
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
| -- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | expected `{`
| this `if` expression has a condition, but no block
| | help: remove the attributes
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:43:38
@ -159,13 +159,14 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:47:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
| ^ --- help: try placing this code inside a block: `{ {}; }`
| |
| expected `{`
| ---- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | help: remove the attributes
| the branch belongs to this `else`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:49:46
@ -175,22 +176,23 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:51:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| ^ -------- help: try placing this code inside a block: `{ if 0 {}; }`
| |
| expected `{`
| ---- ^^^^^^^ ------- the attributes are attached to this branch
| | |
| | help: remove the attributes
| the branch belongs to this `else`
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:53:50
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
| -- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | expected `{`
| this `if` expression has a condition, but no block
| | help: remove the attributes
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:55:51
@ -200,14 +202,14 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:57:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
| -- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | expected `{`
| this `if` expression has a condition, but no block
| | help: remove the attributes
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:59:46
@ -223,13 +225,14 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:63:53
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| ^ --- help: try placing this code inside a block: `{ {}; }`
| |
| expected `{`
| ---- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | help: remove the attributes
| the branch belongs to this `else`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:65:54
@ -239,22 +242,23 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:67:53
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
| ^ ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
| |
| expected `{`
| ---- ^^^^^^^ --------------- the attributes are attached to this branch
| | |
| | help: remove the attributes
| the branch belongs to this `else`
error: expected `{`, found `#`
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:69:66
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
| -- ^^^^^^^ -- the attributes are attached to this branch
| | |
| | expected `{`
| this `if` expression has a condition, but no block
| | help: remove the attributes
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:71:67

View File

@ -0,0 +1,15 @@
#![feature(label_break_value)]
fn main() {}
macro_rules! m {
($b:block) => {
'lab: $b; //~ ERROR cannot use a `block` macro fragment here
unsafe $b; //~ ERROR cannot use a `block` macro fragment here
|x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
}
}
fn foo() {
m!({});
}

View File

@ -0,0 +1,39 @@
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:7:15
|
LL | 'lab: $b;
| ------^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:8:16
|
LL | unsafe $b;
| -------^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:9:23
|
LL | |x: u8| -> () $b;
| ^^ the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -0,0 +1,31 @@
// edition:2018
#![feature(try_blocks)]
fn main() {}
fn f1() {
loop
let x = 0; //~ ERROR expected `{`, found keyword `let`
drop(0);
}
fn f2() {
while true
let x = 0; //~ ERROR expected `{`, found keyword `let`
}
fn f3() {
for x in 0..1
let x = 0; //~ ERROR expected `{`, found keyword `let`
}
fn f4() {
try //~ ERROR expected expression, found reserved keyword `try`
let x = 0;
}
fn f5() {
async //~ ERROR async closures are unstable
let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
}

View File

@ -0,0 +1,53 @@
error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:9:9
|
LL | let x = 0;
| ^^^-------
| |
| expected `{`
| help: try placing this code inside a block: `{ let x = 0; }`
error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:15:9
|
LL | let x = 0;
| ^^^-------
| |
| expected `{`
| help: try placing this code inside a block: `{ let x = 0; }`
error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:20:9
|
LL | let x = 0;
| ^^^-------
| |
| expected `{`
| help: try placing this code inside a block: `{ let x = 0; }`
error: expected expression, found reserved keyword `try`
--> $DIR/block-no-opening-brace.rs:24:5
|
LL | try
| ^^^ expected expression
error: expected one of `move`, `|`, or `||`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:30:9
|
LL | async
| - expected one of `move`, `|`, or `||`
LL | let x = 0;
| ^^^ unexpected token
error[E0658]: async closures are unstable
--> $DIR/block-no-opening-brace.rs:29:5
|
LL | async
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -6,6 +6,6 @@ type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation)
type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
type A = for<,> fn(); //~ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime
fn main() {}

View File

@ -1,8 +1,8 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,`
error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/bounds-lifetime.rs:9:14
|
LL | type A = for<,> fn();
| ^ expected one of `>`, `const`, identifier, or lifetime
| ^ expected one of `#`, `>`, `const`, identifier, or lifetime
error: aborting due to previous error

View File

@ -3,5 +3,5 @@
fn main() {
let x = || -> i32 22;
//~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
//~^ ERROR expected `{`, found `22`
}

View File

@ -1,8 +1,11 @@
error: expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
error: expected `{`, found `22`
--> $DIR/closure-return-syntax.rs:5:23
|
LL | let x = || -> i32 22;
| ^^ expected one of `!`, `(`, `+`, `::`, `<`, or `{`
| ^^
| |
| expected `{`
| help: try placing this code inside a block: `{ 22 }`
error: aborting due to previous error

View File

@ -1 +1 @@
# //~ ERROR expected `[`, found `<eof>`
# //~ ERROR expected one of `!` or `[`, found `<eof>`

View File

@ -1,8 +1,8 @@
error: expected `[`, found `<eof>`
error: expected one of `!` or `[`, found `<eof>`
--> $DIR/column-offset-1-based.rs:1:1
|
LL | #
| ^ expected `[`
| ^ expected one of `!` or `[`
error: aborting due to previous error

View File

@ -1,4 +1,5 @@
fn main() {
if true /*!*/ {}
//~^ ERROR expected `{`, found doc comment `/*!*/`
//~^ ERROR outer attributes are not allowed on
//~| ERROR expected outer doc comment
}

View File

@ -1,10 +1,19 @@
error: expected `{`, found doc comment `/*!*/`
error: expected outer doc comment
--> $DIR/doc-comment-in-if-statement.rs:2:13
|
LL | if true /*!*/ {}
| -- ^^^^^ expected `{`
| |
| this `if` expression has a condition, but no block
| ^^^^^
|
= note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
error: aborting due to previous error
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/doc-comment-in-if-statement.rs:2:13
|
LL | if true /*!*/ {}
| -- ^^^^^ -- the attributes are attached to this branch
| | |
| | help: remove the attributes
| the branch belongs to this `if`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,23 @@
fn main() {}
fn syntax() {
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
}
extern {
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
//~^ ERROR incorrect function inside `extern` block
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
//~^ ERROR incorrect function inside `extern` block
}
trait Foo {
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
}
impl Foo for () {
fn foo() = 42; //~ ERROR function body cannot be `= expression;`
fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
}

View File

@ -0,0 +1,117 @@
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:4:14
|
LL | fn foo() = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn foo() { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:5:20
|
LL | fn bar() -> u8 = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn bar() -> u8 { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:9:14
|
LL | fn foo() = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn foo() { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:11:20
|
LL | fn bar() -> u8 = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn bar() -> u8 { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:16:14
|
LL | fn foo() = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn foo() { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:17:20
|
LL | fn bar() -> u8 = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn bar() -> u8 { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:21:14
|
LL | fn foo() = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn foo() { 42 }
| ^ ^
error: function body cannot be `= expression;`
--> $DIR/fn-body-eq-expr-semi.rs:22:20
|
LL | fn bar() -> u8 = 42;
| ^^^^^
|
help: surround the expression with `{` and `}` instead of `=` and `;`
|
LL | fn bar() -> u8 { 42 }
| ^ ^
error: incorrect function inside `extern` block
--> $DIR/fn-body-eq-expr-semi.rs:9:8
|
LL | extern {
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
LL | fn foo() = 42;
| ^^^ ----- help: remove the invalid body: `;`
| |
| cannot have a body
|
= help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: incorrect function inside `extern` block
--> $DIR/fn-body-eq-expr-semi.rs:11:8
|
LL | extern {
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
...
LL | fn bar() -> u8 = 42;
| ^^^ ----- help: remove the invalid body: `;`
| |
| cannot have a body
|
= help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
error: aborting due to 10 previous errors

View File

@ -1,6 +1,5 @@
// error-pattern:expected `[`, found `vec`
mod blade_runner {
#vec[doc(
#vec[doc( //~ ERROR expected one of `!` or `[`, found `vec`
brief = "Blade Runner is probably the best movie ever",
desc = "I like that in the world of Blade Runner it is always
raining, and that it's always night time. And Aliens

View File

@ -1,8 +1,8 @@
error: expected `[`, found `vec`
--> $DIR/issue-1655.rs:3:6
error: expected one of `!` or `[`, found `vec`
--> $DIR/issue-1655.rs:2:6
|
LL | #vec[doc(
| ^^^ expected `[`
| ^^^ expected one of `!` or `[`
error: aborting due to previous error

View File

@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
LL | impl W <s(f;Y(;]
| ^ expected one of 7 possible tokens
error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, or lifetime, found `;`
error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
--> $DIR/issue-63116.rs:3:15
|
LL | impl W <s(f;Y(;]

View File

@ -1,3 +1,3 @@
// error-pattern: aborting due to 7 previous errors
// error-pattern: aborting due to 5 previous errors
fn i(n{...,f #

View File

@ -31,23 +31,11 @@ LL | fn i(n{...,f #
| | expected `}`
| `..` must be at the end and cannot have a trailing comma
error: expected `[`, found `}`
error: expected one of `!` or `[`, found `}`
--> $DIR/issue-63135.rs:3:16
|
LL | fn i(n{...,f #
| ^ expected `[`
| ^ expected one of `!` or `[`
error: expected one of `:` or `|`, found `)`
--> $DIR/issue-63135.rs:3:16
|
LL | fn i(n{...,f #
| ^ expected one of `:` or `|`
error: expected `;` or `{`, found `<eof>`
--> $DIR/issue-63135.rs:3:16
|
LL | fn i(n{...,f #
| ^ expected `;` or `{`
error: aborting due to 7 previous errors
error: aborting due to 5 previous errors

Binary file not shown.

View File

@ -0,0 +1,6 @@
fn main() {}
type X<'a> = (?'a) +;
//~^ ERROR `?` may only modify trait bounds, not lifetime bounds
//~| ERROR at least one trait is required for an object type
//~| WARN trait objects without an explicit `dyn` are deprecated

View File

@ -0,0 +1,22 @@
error: `?` may only modify trait bounds, not lifetime bounds
--> $DIR/issue-68890-2.rs:3:15
|
LL | type X<'a> = (?'a) +;
| ^
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/issue-68890-2.rs:3:14
|
LL | type X<'a> = (?'a) +;
| ^^^^^^^ help: use `dyn`: `dyn (?'a) +`
|
= note: `#[warn(bare_trait_objects)]` on by default
error[E0224]: at least one trait is required for an object type
--> $DIR/issue-68890-2.rs:3:14
|
LL | type X<'a> = (?'a) +;
| ^^^^^^^
error: aborting due to 2 previous errors

View File

@ -1,4 +1,4 @@
enum e{A((?'a a+?+l))}
//~^ ERROR `?` may only modify trait bounds, not lifetime bounds
//~| ERROR expected one of `)`, `+`, or `,`
//~| ERROR expected trait bound, not lifetime bound
//~| ERROR expected item, found `)`

View File

@ -10,11 +10,11 @@ error: expected one of `)`, `+`, or `,`, found `a`
LL | enum e{A((?'a a+?+l))}
| ^ expected one of `)`, `+`, or `,`
error: expected trait bound, not lifetime bound
--> $DIR/issue-68890.rs:1:11
error: expected item, found `)`
--> $DIR/issue-68890.rs:1:21
|
LL | enum e{A((?'a a+?+l))}
| ^^^
| ^ expected item
error: aborting due to 3 previous errors

View File

@ -0,0 +1,17 @@
#![feature(label_break_value)]
fn main() {
'l0 while false {} //~ ERROR labeled expression must be followed by `:`
'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:`
'l2 loop {} //~ ERROR labeled expression must be followed by `:`
'l3 {} //~ ERROR labeled expression must be followed by `:`
'l4 0; //~ ERROR labeled expression must be followed by `:`
//~^ ERROR expected `while`, `for`, `loop` or `{`
macro_rules! m {
($b:block) => {
'l5 $b; //~ ERROR cannot use a `block` macro fragment here
}
}
m!({}); //~ ERROR labeled expression must be followed by `:`
}

View File

@ -0,0 +1,89 @@
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:4:5
|
LL | 'l0 while false {}
| ----^^^^^^^^^^^^^^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:5:5
|
LL | 'l1 for _ in 0..1 {}
| ----^^^^^^^^^^^^^^^^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:6:5
|
LL | 'l2 loop {}
| ----^^^^^^^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:7:5
|
LL | 'l3 {}
| ----^^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/labeled-no-colon-expr.rs:8:9
|
LL | 'l4 0;
| ^ expected `while`, `for`, `loop` or `{` after a label
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:8:9
|
LL | 'l4 0;
| ----^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: cannot use a `block` macro fragment here
--> $DIR/labeled-no-colon-expr.rs:13:17
|
LL | 'l5 $b;
| ----^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:16:8
|
LL | 'l5 $b;
| ---- help: add `:` after the label
| |
| the label
...
LL | m!({});
| ^^
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
error: aborting due to 8 previous errors

View File

@ -2,9 +2,14 @@
// `ty` matcher in particular doesn't accept a single lifetime
macro_rules! m {
($t: ty) => ( let _: $t; )
($t: ty) => {
let _: $t;
};
}
fn main() {
m!('static); //~ ERROR expected type, found `'static`
m!('static);
//~^ ERROR lifetime in trait object type must be followed by `+`
//~| ERROR at least one trait is required for an object type
//~| WARN trait objects without an explicit `dyn` are deprecated
}

View File

@ -1,8 +1,22 @@
error: expected type, found `'static`
--> $DIR/trait-object-macro-matcher.rs:9:8
error: lifetime in trait object type must be followed by `+`
--> $DIR/trait-object-macro-matcher.rs:11:8
|
LL | m!('static);
| ^^^^^^^ expected type
| ^^^^^^^
error: aborting due to previous error
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-macro-matcher.rs:11:8
|
LL | m!('static);
| ^^^^^^^ help: use `dyn`: `dyn 'static`
|
= note: `#[warn(bare_trait_objects)]` on by default
error[E0224]: at least one trait is required for an object type
--> $DIR/trait-object-macro-matcher.rs:11:8
|
LL | m!('static);
| ^^^^^^^
error: aborting due to 2 previous errors

View File

@ -4,7 +4,7 @@ fn foo(cond: bool) {
let mut x;
if cond {
x = &'blk [1,2,3]; //~ ERROR expected `:`, found `[`
x = &'blk [1,2,3]; //~ ERROR borrow expressions cannot be annotated with lifetimes
}
}

View File

@ -1,8 +1,11 @@
error: expected `:`, found `[`
--> $DIR/regions-out-of-scope-slice.rs:7:19
error: borrow expressions cannot be annotated with lifetimes
--> $DIR/regions-out-of-scope-slice.rs:7:13
|
LL | x = &'blk [1,2,3];
| ^ expected `:`
| ^----^^^^^^^^
| |
| annotated with lifetime here
| help: remove the lifetime annotation
error: aborting due to previous error

View File

@ -6,9 +6,7 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s
fn check<'a>() {
let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
let _: Box<('a) + Trait>;
//~^ ERROR expected type, found `'a`
//~| ERROR expected `:`, found `)`
let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+`
}
fn main() {}

View File

@ -10,19 +10,11 @@ error: parenthesized lifetime bounds are not supported
LL | let _: Box<Trait + ('a)>;
| ^^^^ help: remove the parentheses
error: expected `:`, found `)`
--> $DIR/trait-object-lifetime-parens.rs:9:19
|
LL | let _: Box<('a) + Trait>;
| ^ expected `:`
error: expected type, found `'a`
error: lifetime in trait object type must be followed by `+`
--> $DIR/trait-object-lifetime-parens.rs:9:17
|
LL | let _: Box<('a) + Trait>;
| - ^^ expected type
| |
| while parsing the type for `_`
| ^^
error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

View File

@ -1,15 +1,20 @@
trait Trait<'a> {}
trait Obj {}
fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
fn main() {
let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
//~^ ERROR `?Trait` is not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
//~^ WARN trait objects without an explicit `dyn` are deprecated
let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
//~^ ERROR use of undeclared lifetime name `'a`
//~| ERROR `?Trait` is not permitted in trait object types
let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
//~^ ERROR `?Trait` is not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
//~^ ERROR `?Trait` is not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
}

View File

@ -1,44 +1,74 @@
error: `?Trait` is not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:6:25
--> $DIR/trait-object-trait-parens.rs:8:24
|
LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^
error: `?Trait` is not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:11:47
--> $DIR/trait-object-trait-parens.rs:12:17
|
LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
| ^^^^^^^^
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
| ^^^^^^
error: `?Trait` is not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:16:46
|
LL | let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
| ^^^^^^^^
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:6:16
--> $DIR/trait-object-trait-parens.rs:8:16
|
LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Copy) + (?Sized) + (for<'a> Trait<'a>)`
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)`
|
= note: `#[warn(bare_trait_objects)]` on by default
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:9:16
--> $DIR/trait-object-trait-parens.rs:12:16
|
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Copy)`
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Obj)`
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:11:16
--> $DIR/trait-object-trait-parens.rs:16:16
|
LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Copy) + (?Sized)`
LL | let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Obj) + (?Sized)`
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/trait-object-trait-parens.rs:11:31
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:8:35
|
LL | fn main() {
| - help: consider introducing lifetime `'a` here: `<'a>`
...
LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
| ^^ undeclared lifetime
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ----- ^^^^^^^^^^^^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| first non-auto trait
| trait alias used in trait object type (first use)
error: aborting due to 3 previous errors
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:12:49
|
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
| ------------------- ^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| first non-auto trait
| trait alias used in trait object type (first use)
For more information about this error, try `rustc --explain E0261`.
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:16:38
|
LL | let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
| ----------------- ^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| first non-auto trait
| trait alias used in trait object type (first use)
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0225`.

View File

@ -1,10 +1,11 @@
error: expected `{`, found `std`
--> $DIR/unsafe-block-without-braces.rs:3:9
|
LL | unsafe //{
| - expected `{`
LL | std::mem::transmute::<f32, u32>(1.0);
| ^^^ unexpected token
| ^^^----------------------------------
| |
| expected `{`
| help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
error: aborting due to previous error