Auto merge of #94453 - matthiaskrgr:rollup-xv9y98j, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #92399 (fix typo in btree/vec doc: Self -> self)
 - #92823 (Tweak diagnostics)
 - #94248 (Fix ICE when passing block to while-loop condition)
 - #94414 (Fix ICE when using Box<T, A> with large A)
 - #94445 (4 - Make more use of `let_chains`)
 - #94449 (Add long explanation for E0726)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-02-28 21:17:11 +00:00
commit 4ce3749235
47 changed files with 590 additions and 320 deletions

View File

@ -453,7 +453,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}; };
for elem in place_ref.projection[base..].iter() { for elem in place_ref.projection[base..].iter() {
cg_base = match elem.clone() { cg_base = match elem.clone() {
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()), mir::ProjectionElem::Deref => {
// custom allocators can change box's abi, making it unable to be derefed directly
if cg_base.layout.ty.is_box()
&& matches!(cg_base.layout.abi, Abi::Aggregate { .. } | Abi::Uninhabited)
{
let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
bx.load_operand(ptr).deref(bx.cx())
} else {
bx.load_operand(cg_base).deref(bx.cx())
}
}
mir::ProjectionElem::Field(ref field, _) => { mir::ProjectionElem::Field(ref field, _) => {
cg_base.project_field(bx, field.index()) cg_base.project_field(bx, field.index())
} }

View File

@ -429,6 +429,7 @@ E0720: include_str!("./error_codes/E0720.md"),
E0722: include_str!("./error_codes/E0722.md"), E0722: include_str!("./error_codes/E0722.md"),
E0724: include_str!("./error_codes/E0724.md"), E0724: include_str!("./error_codes/E0724.md"),
E0725: include_str!("./error_codes/E0725.md"), E0725: include_str!("./error_codes/E0725.md"),
E0726: include_str!("./error_codes/E0726.md"),
E0727: include_str!("./error_codes/E0727.md"), E0727: include_str!("./error_codes/E0727.md"),
E0728: include_str!("./error_codes/E0728.md"), E0728: include_str!("./error_codes/E0728.md"),
E0729: include_str!("./error_codes/E0729.md"), E0729: include_str!("./error_codes/E0729.md"),
@ -641,6 +642,5 @@ E0787: include_str!("./error_codes/E0787.md"),
E0717, // rustc_promotable without stability attribute E0717, // rustc_promotable without stability attribute
// E0721, // `await` keyword // E0721, // `await` keyword
// E0723, // unstable feature in `const` context // E0723, // unstable feature in `const` context
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
} }

View File

@ -0,0 +1,46 @@
An argument lifetime was elided in an async function.
Erroneous code example:
When a struct or a type is bound/declared with a lifetime it is important for
the Rust compiler to know, on usage, the lifespan of the type. When the
lifetime is not explicitly mentioned and the Rust Compiler cannot determine
the lifetime of your type, the following error occurs.
```compile_fail,E0726
use futures::executor::block_on;
struct Content<'a> {
title: &'a str,
body: &'a str,
}
async fn create(content: Content) { // error: implicit elided
// lifetime not allowed here
println!("title: {}", content.title);
println!("body: {}", content.body);
}
let content = Content { title: "Rust", body: "is great!" };
let future = create(content);
block_on(future);
```
Specify desired lifetime of parameter `content` or indicate the anonymous
lifetime like `content: Content<'_>`. The anonymous lifetime tells the Rust
compiler that `content` is only needed until create function is done with
it's execution.
The `implicit elision` meaning the omission of suggested lifetime that is
`pub async fn create<'a>(content: Content<'a>) {}` is not allowed here as
lifetime of the `content` can differ from current context:
```ignore (needs futures dependency)
async fn create(content: Content<'_>) { // ok!
println!("title: {}", content.title);
println!("body: {}", content.body);
}
```
Know more about lifetime elision in this [chapter][lifetime-elision] and a
chapter on lifetimes can be found [here][lifetimes].
[lifetime-elision]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision
[lifetimes]: https://doc.rust-lang.org/rust-by-example/scope/lifetime.html

View File

@ -20,7 +20,7 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, PResult}; use rustc_errors::{Applicability, PResult};
use rustc_feature::Features; use rustc_feature::Features;
use rustc_parse::parser::{ use rustc_parse::parser::{
AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
}; };
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
@ -911,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
None, None,
RecoverComma::No, RecoverComma::No,
RecoverColon::Yes, RecoverColon::Yes,
CommaRecoveryMode::LikelyTuple,
)?), )?),
AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?), AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
AstFragmentKind::Arms AstFragmentKind::Arms

View File

@ -282,15 +282,14 @@ struct TokenStreamBuilder {
impl TokenStreamBuilder { impl TokenStreamBuilder {
fn push(&mut self, (tree, joint): TreeAndSpacing) { fn push(&mut self, (tree, joint): TreeAndSpacing) {
if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() { if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last()
if let TokenTree::Token(token) = &tree { && let TokenTree::Token(token) = &tree
if let Some(glued) = prev_token.glue(token) { && let Some(glued) = prev_token.glue(token)
{
self.buf.pop(); self.buf.pop();
self.buf.push((TokenTree::Token(glued), joint)); self.buf.push((TokenTree::Token(glued), joint));
return; return;
} }
}
}
self.buf.push((tree, joint)) self.buf.push((tree, joint))
} }

View File

@ -1,9 +1,10 @@
//! The main parser interface. //! The main parser interface.
#![feature(array_windows)] #![feature(array_windows)]
#![feature(box_patterns)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(box_patterns)] #![feature(let_chains)]
#![feature(let_else)] #![feature(let_else)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -1,8 +1,8 @@
use super::pat::Expected; use super::pat::Expected;
use super::ty::{AllowPlus, IsAsCast}; use super::ty::{AllowPlus, IsAsCast};
use super::{ use super::{
BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep, BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
TokenExpectType, TokenType, SemiColonMode, SeqSep, TokenExpectType, TokenType,
}; };
use rustc_ast as ast; use rustc_ast as ast;
@ -732,9 +732,10 @@ impl<'a> Parser<'a> {
mut e: DiagnosticBuilder<'a, ErrorReported>, mut e: DiagnosticBuilder<'a, ErrorReported>,
expr: &mut P<Expr>, expr: &mut P<Expr>,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
if let ExprKind::Binary(binop, _, _) = &expr.kind { if let ExprKind::Binary(binop, _, _) = &expr.kind
if let ast::BinOpKind::Lt = binop.node { && let ast::BinOpKind::Lt = binop.node
if self.eat(&token::Comma) { && self.eat(&token::Comma)
{
let x = self.parse_seq_to_before_end( let x = self.parse_seq_to_before_end(
&token::Gt, &token::Gt,
SeqSep::trailing_allowed(token::Comma), SeqSep::trailing_allowed(token::Comma),
@ -769,8 +770,6 @@ impl<'a> Parser<'a> {
_ => {} _ => {}
} }
} }
}
}
Err(e) Err(e)
} }
@ -784,13 +783,14 @@ impl<'a> Parser<'a> {
outer_op: &Spanned<AssocOp>, outer_op: &Spanned<AssocOp>,
) -> bool /* advanced the cursor */ { ) -> bool /* advanced the cursor */ {
if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind { if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
if let ExprKind::Field(_, ident) = l1.kind { if let ExprKind::Field(_, ident) = l1.kind
if ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) { && ident.as_str().parse::<i32>().is_err()
&& !matches!(r1.kind, ExprKind::Lit(_))
{
// The parser has encountered `foo.bar<baz`, the likelihood of the turbofish // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
// suggestion being the only one to apply is high. // suggestion being the only one to apply is high.
return false; return false;
} }
}
let mut enclose = |left: Span, right: Span| { let mut enclose = |left: Span, right: Span| {
err.multipart_suggestion( err.multipart_suggestion(
"parenthesize the comparison", "parenthesize the comparison",
@ -2245,12 +2245,32 @@ impl<'a> Parser<'a> {
first_pat first_pat
} }
crate fn maybe_recover_unexpected_block_label(&mut self) -> bool {
let Some(label) = self.eat_label().filter(|_| {
self.eat(&token::Colon) && self.token.kind == token::OpenDelim(token::Brace)
}) else {
return false;
};
let span = label.ident.span.to(self.prev_token.span);
let mut err = self.struct_span_err(span, "block label not supported here");
err.span_label(span, "not supported here");
err.tool_only_span_suggestion(
label.ident.span.until(self.token.span),
"remove this block label",
String::new(),
Applicability::MachineApplicable,
);
err.emit();
true
}
/// Some special error handling for the "top-level" patterns in a match arm, /// Some special error handling for the "top-level" patterns in a match arm,
/// `for` loop, `let`, &c. (in contrast to subpatterns within such). /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
crate fn maybe_recover_unexpected_comma( crate fn maybe_recover_unexpected_comma(
&mut self, &mut self,
lo: Span, lo: Span,
rc: RecoverComma, rc: RecoverComma,
rt: CommaRecoveryMode,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
if rc == RecoverComma::No || self.token != token::Comma { if rc == RecoverComma::No || self.token != token::Comma {
return Ok(()); return Ok(());
@ -2270,14 +2290,18 @@ impl<'a> Parser<'a> {
let seq_span = lo.to(self.prev_token.span); let seq_span = lo.to(self.prev_token.span);
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
const MSG: &str = "try adding parentheses to match on a tuple..."; err.multipart_suggestion(
&format!(
err.span_suggestion( "try adding parentheses to match on a tuple{}",
seq_span, if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
MSG, ),
format!("({})", seq_snippet), vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion( err.span_suggestion(
seq_span, seq_span,
"...or a vertical bar to match on multiple alternatives", "...or a vertical bar to match on multiple alternatives",
@ -2285,6 +2309,7 @@ impl<'a> Parser<'a> {
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} }
}
Err(err) Err(err)
} }

View File

@ -1,4 +1,4 @@
use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{ use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType, AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
@ -1286,18 +1286,27 @@ impl<'a> Parser<'a> {
} else if let Some(label) = self.eat_label() { } else if let Some(label) = self.eat_label() {
self.parse_labeled_expr(label, attrs, true) self.parse_labeled_expr(label, attrs, true)
} else if self.eat_keyword(kw::Loop) { } else if self.eat_keyword(kw::Loop) {
self.parse_loop_expr(None, self.prev_token.span, attrs) let sp = self.prev_token.span;
self.parse_loop_expr(None, self.prev_token.span, attrs).map_err(|mut err| {
err.span_label(sp, "while parsing this `loop` expression");
err
})
} else if self.eat_keyword(kw::Continue) { } else if self.eat_keyword(kw::Continue) {
let kind = ExprKind::Continue(self.eat_label()); let kind = ExprKind::Continue(self.eat_label());
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs))
} else if self.eat_keyword(kw::Match) { } else if self.eat_keyword(kw::Match) {
let match_sp = self.prev_token.span; let match_sp = self.prev_token.span;
self.parse_match_expr(attrs).map_err(|mut err| { self.parse_match_expr(attrs).map_err(|mut err| {
err.span_label(match_sp, "while parsing this match expression"); err.span_label(match_sp, "while parsing this `match` expression");
err err
}) })
} else if self.eat_keyword(kw::Unsafe) { } else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span;
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
.map_err(|mut err| {
err.span_label(sp, "while parsing this `unsafe` expression");
err
})
} else if self.check_inline_const(0) { } else if self.check_inline_const(0) {
self.parse_const_block(lo.to(self.token.span), false) self.parse_const_block(lo.to(self.token.span), false)
} else if self.is_do_catch_block() { } else if self.is_do_catch_block() {
@ -2160,7 +2169,12 @@ impl<'a> Parser<'a> {
/// The `let` token has already been eaten. /// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; let pat = self.parse_pat_allow_top_alt(
None,
RecoverComma::Yes,
RecoverColon::Yes,
CommaRecoveryMode::LikelyTuple,
)?;
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@ -2223,7 +2237,12 @@ impl<'a> Parser<'a> {
_ => None, _ => None,
}; };
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; let pat = self.parse_pat_allow_top_alt(
None,
RecoverComma::Yes,
RecoverColon::Yes,
CommaRecoveryMode::LikelyTuple,
)?;
if !self.eat_keyword(kw::In) { if !self.eat_keyword(kw::In) {
self.error_missing_in_for_loop(); self.error_missing_in_for_loop();
} }
@ -2266,8 +2285,15 @@ impl<'a> Parser<'a> {
lo: Span, lo: Span,
mut attrs: AttrVec, mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr()?; let cond = self.parse_cond_expr().map_err(|mut err| {
let (iattrs, body) = self.parse_inner_attrs_and_block()?; err.span_label(lo, "while parsing the condition of this `while` expression");
err
})?;
let (iattrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| {
err.span_label(lo, "while parsing the body of this `while` expression");
err.span_label(cond.span, "this `while` condition successfully parsed");
err
})?;
attrs.extend(iattrs); attrs.extend(iattrs);
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs)) Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs))
} }
@ -2284,7 +2310,7 @@ impl<'a> Parser<'a> {
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::Loop(body, opt_label), attrs)) Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::Loop(body, opt_label), attrs))
} }
fn eat_label(&mut self) -> Option<Label> { crate fn eat_label(&mut self) -> Option<Label> {
self.token.lifetime().map(|ident| { self.token.lifetime().map(|ident| {
self.bump(); self.bump();
Label { ident } Label { ident }
@ -2305,8 +2331,13 @@ impl<'a> Parser<'a> {
Applicability::MaybeIncorrect, // speculative Applicability::MaybeIncorrect, // speculative
); );
} }
if self.maybe_recover_unexpected_block_label() {
e.cancel();
self.bump();
} else {
return Err(e); return Err(e);
} }
}
attrs.extend(self.parse_inner_attributes()?); attrs.extend(self.parse_inner_attributes()?);
let mut arms: Vec<Arm> = Vec::new(); let mut arms: Vec<Arm> = Vec::new();
@ -2441,7 +2472,12 @@ impl<'a> Parser<'a> {
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span; let lo = this.token.span;
let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; let pat = this.parse_pat_allow_top_alt(
None,
RecoverComma::Yes,
RecoverColon::Yes,
CommaRecoveryMode::EitherTupleOrPipe,
)?;
let guard = if this.eat_keyword(kw::If) { let guard = if this.eat_keyword(kw::If) {
let if_span = this.prev_token.span; let if_span = this.prev_token.span;
let cond = this.parse_expr()?; let cond = this.parse_expr()?;

View File

@ -102,14 +102,12 @@ impl<'a> Parser<'a> {
) -> PResult<'a, Option<Item>> { ) -> PResult<'a, Option<Item>> {
// Don't use `maybe_whole` so that we have precise control // Don't use `maybe_whole` so that we have precise control
// over when we bump the parser // over when we bump the parser
if let token::Interpolated(nt) = &self.token.kind { if let token::Interpolated(nt) = &self.token.kind && let token::NtItem(item) = &**nt {
if let token::NtItem(item) = &**nt {
let mut item = item.clone(); let mut item = item.clone();
self.bump(); self.bump();
attrs.prepend_to_nt_inner(&mut item.attrs); attrs.prepend_to_nt_inner(&mut item.attrs);
return Ok(Some(item.into_inner())); return Ok(Some(item.into_inner()));
}
}; };
let mut unclosed_delims = vec![]; let mut unclosed_delims = vec![];

View File

@ -15,7 +15,7 @@ pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery; pub use diagnostics::AttemptLocalParseRecovery;
use diagnostics::Error; use diagnostics::Error;
pub(crate) use item::FnParseMode; pub(crate) use item::FnParseMode;
pub use pat::{RecoverColon, RecoverComma}; pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
pub use path::PathStyle; pub use path::PathStyle;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
@ -97,15 +97,15 @@ macro_rules! maybe_whole {
#[macro_export] #[macro_export]
macro_rules! maybe_recover_from_interpolated_ty_qpath { macro_rules! maybe_recover_from_interpolated_ty_qpath {
($self: expr, $allow_qpath_recovery: expr) => { ($self: expr, $allow_qpath_recovery: expr) => {
if $allow_qpath_recovery && $self.look_ahead(1, |t| t == &token::ModSep) { if $allow_qpath_recovery
if let token::Interpolated(nt) = &$self.token.kind { && $self.look_ahead(1, |t| t == &token::ModSep)
if let token::NtTy(ty) = &**nt { && let token::Interpolated(nt) = &$self.token.kind
&& let token::NtTy(ty) = &**nt
{
let ty = ty.clone(); let ty = ty.clone();
$self.bump(); $self.bump();
return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty); return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
} }
}
}
}; };
} }

View File

@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident}; use rustc_span::symbol::{kw, Ident};
use crate::parser::pat::{RecoverColon, RecoverComma}; use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle}; use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
token::NtPat(self.collect_tokens_no_attrs(|this| match kind { token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None), NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
NonterminalKind::PatWithOr { .. } => { NonterminalKind::PatWithOr { .. } => {
this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe)
} }
_ => unreachable!(), _ => unreachable!(),
})?) })?)

View File

@ -33,6 +33,13 @@ pub enum RecoverColon {
No, No,
} }
/// Whether or not to recover a `a, b` when parsing patterns as `(a, b)` or that *and* `a | b`.
#[derive(PartialEq, Copy, Clone)]
pub enum CommaRecoveryMode {
LikelyTuple,
EitherTupleOrPipe,
}
/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid /// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
/// emitting duplicate diagnostics. /// emitting duplicate diagnostics.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -68,8 +75,9 @@ impl<'a> Parser<'a> {
expected: Expected, expected: Expected,
rc: RecoverComma, rc: RecoverComma,
ra: RecoverColon, ra: RecoverColon,
rt: CommaRecoveryMode,
) -> PResult<'a, P<Pat>> { ) -> PResult<'a, P<Pat>> {
self.parse_pat_allow_top_alt_inner(expected, rc, ra).map(|(pat, _)| pat) self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt).map(|(pat, _)| pat)
} }
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@ -79,6 +87,7 @@ impl<'a> Parser<'a> {
expected: Expected, expected: Expected,
rc: RecoverComma, rc: RecoverComma,
ra: RecoverColon, ra: RecoverColon,
rt: CommaRecoveryMode,
) -> PResult<'a, (P<Pat>, bool)> { ) -> PResult<'a, (P<Pat>, bool)> {
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
// suggestions (which bothers rustfix). // suggestions (which bothers rustfix).
@ -92,7 +101,7 @@ impl<'a> Parser<'a> {
// Parse the first pattern (`p_0`). // Parse the first pattern (`p_0`).
let first_pat = self.parse_pat_no_top_alt(expected)?; let first_pat = self.parse_pat_no_top_alt(expected)?;
self.maybe_recover_unexpected_comma(first_pat.span, rc)?; self.maybe_recover_unexpected_comma(first_pat.span, rc, rt)?;
// If the next token is not a `|`, // If the next token is not a `|`,
// this is not an or-pattern and we should exit here. // this is not an or-pattern and we should exit here.
@ -130,7 +139,7 @@ impl<'a> Parser<'a> {
err.span_label(lo, WHILE_PARSING_OR_MSG); err.span_label(lo, WHILE_PARSING_OR_MSG);
err err
})?; })?;
self.maybe_recover_unexpected_comma(pat.span, rc)?; self.maybe_recover_unexpected_comma(pat.span, rc, rt)?;
pats.push(pat); pats.push(pat);
} }
let or_pattern_span = lo.to(self.prev_token.span); let or_pattern_span = lo.to(self.prev_token.span);
@ -155,8 +164,12 @@ impl<'a> Parser<'a> {
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
// or-patterns so that we can detect when a user tries to use it. This allows us to print a // or-patterns so that we can detect when a user tries to use it. This allows us to print a
// better error message. // better error message.
let (pat, trailing_vert) = let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(
self.parse_pat_allow_top_alt_inner(expected, rc, RecoverColon::No)?; expected,
rc,
RecoverColon::No,
CommaRecoveryMode::LikelyTuple,
)?;
let colon = self.eat(&token::Colon); let colon = self.eat(&token::Colon);
if let PatKind::Or(pats) = &pat.kind { if let PatKind::Or(pats) = &pat.kind {
@ -315,7 +328,12 @@ impl<'a> Parser<'a> {
} else if self.check(&token::OpenDelim(token::Bracket)) { } else if self.check(&token::OpenDelim(token::Bracket)) {
// Parse `[pat, pat,...]` as a slice pattern. // Parse `[pat, pat,...]` as a slice pattern.
let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| { let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) p.parse_pat_allow_top_alt(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
)
})?; })?;
PatKind::Slice(pats) PatKind::Slice(pats)
} else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
@ -529,7 +547,12 @@ impl<'a> Parser<'a> {
/// Parse a tuple or parenthesis pattern. /// Parse a tuple or parenthesis pattern.
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) p.parse_pat_allow_top_alt(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::LikelyTuple,
)
})?; })?;
// Here, `(pat,)` is a tuple pattern. // Here, `(pat,)` is a tuple pattern.
@ -873,7 +896,12 @@ impl<'a> Parser<'a> {
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`). /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> { fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
let (fields, _) = self.parse_paren_comma_seq(|p| { let (fields, _) = self.parse_paren_comma_seq(|p| {
p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) p.parse_pat_allow_top_alt(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
)
})?; })?;
if qself.is_some() { if qself.is_some() {
self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
@ -1033,7 +1061,12 @@ impl<'a> Parser<'a> {
// Parsing a pattern of the form `fieldname: pat`. // Parsing a pattern of the form `fieldname: pat`.
let fieldname = self.parse_field_name()?; let fieldname = self.parse_field_name()?;
self.bump(); self.bump();
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)?; let pat = self.parse_pat_allow_top_alt(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
)?;
hi = pat.span; hi = pat.span;
(pat, fieldname, false) (pat, fieldname, false)
} else { } else {

View File

@ -658,14 +658,14 @@ impl<'a> Parser<'a> {
&self, &self,
gen_arg: GenericArg, gen_arg: GenericArg,
) -> Result<(Ident, Option<GenericArgs>), GenericArg> { ) -> Result<(Ident, Option<GenericArgs>), GenericArg> {
if let GenericArg::Type(ty) = &gen_arg { if let GenericArg::Type(ty) = &gen_arg
if let ast::TyKind::Path(qself, path) = &ty.kind { && let ast::TyKind::Path(qself, path) = &ty.kind
if qself.is_none() && path.segments.len() == 1 { && qself.is_none()
&& path.segments.len() == 1
{
let seg = &path.segments[0]; let seg = &path.segments[0];
return Ok((seg.ident, seg.args.as_deref().cloned())); return Ok((seg.ident, seg.args.as_deref().cloned()));
} }
}
}
Err(gen_arg) Err(gen_arg)
} }
} }

View File

@ -48,8 +48,7 @@ impl<'a> Parser<'a> {
// Don't use `maybe_whole` so that we have precise control // Don't use `maybe_whole` so that we have precise control
// over when we bump the parser // over when we bump the parser
if let token::Interpolated(nt) = &self.token.kind { if let token::Interpolated(nt) = &self.token.kind && let token::NtStmt(stmt) = &**nt {
if let token::NtStmt(stmt) = &**nt {
let mut stmt = stmt.clone(); let mut stmt = stmt.clone();
self.bump(); self.bump();
stmt.visit_attrs(|stmt_attrs| { stmt.visit_attrs(|stmt_attrs| {
@ -57,7 +56,6 @@ impl<'a> Parser<'a> {
}); });
return Ok(Some(stmt)); return Ok(Some(stmt));
} }
}
Ok(Some(if self.token.is_keyword(kw::Let) { Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)? self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
@ -434,6 +432,8 @@ impl<'a> Parser<'a> {
Ok(Some(_)) Ok(Some(_))
if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|| do_not_suggest_help => {} || do_not_suggest_help => {}
// Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
Ok(Some(stmt)) => { Ok(Some(stmt)) => {
let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp); 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) { let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
@ -442,16 +442,16 @@ impl<'a> Parser<'a> {
} else { } else {
stmt.span stmt.span
}; };
if let Ok(snippet) = self.span_to_snippet(stmt_span) { e.multipart_suggestion(
e.span_suggestion(
stmt_span,
"try placing this code inside a block", "try placing this code inside a block",
format!("{{ {} }}", snippet), vec![
(stmt_span.shrink_to_lo(), "{ ".to_string()),
(stmt_span.shrink_to_hi(), " }".to_string()),
],
// Speculative; has been misleading in the past (#46836). // Speculative; has been misleading in the past (#46836).
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
}
Err(e) => { Err(e) => {
self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
e.cancel(); e.cancel();
@ -483,15 +483,15 @@ impl<'a> Parser<'a> {
) -> PResult<'a, (Vec<Attribute>, P<Block>)> { ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
self.maybe_recover_unexpected_block_label();
if !self.eat(&token::OpenDelim(token::Brace)) { if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace(); return self.error_block_no_opening_brace();
} }
let attrs = self.parse_inner_attributes()?; let attrs = self.parse_inner_attributes()?;
let tail = if let Some(tail) = self.maybe_suggest_struct_literal(lo, blk_mode) { let tail = match self.maybe_suggest_struct_literal(lo, blk_mode) {
tail? Some(tail) => tail?,
} else { None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?
}; };
Ok((attrs, tail)) Ok((attrs, tail))
} }

View File

@ -840,7 +840,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
err.span_label(lhs.span, "cannot assign to this expression"); err.span_label(lhs.span, "cannot assign to this expression");
let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id); self.comes_from_while_condition(lhs.hir_id, |expr| {
err.span_suggestion_verbose(
expr.span.shrink_to_lo(),
"you might have meant to use pattern destructuring",
"let ".to_string(),
Applicability::MachineApplicable,
);
});
err.emit();
}
// Check if an expression `original_expr_id` comes from the condition of a while loop,
// as opposed from the body of a while loop, which we can naively check by iterating
// parents until we find a loop...
pub(super) fn comes_from_while_condition(
&self,
original_expr_id: HirId,
then: impl FnOnce(&hir::Expr<'_>),
) {
let mut parent = self.tcx.hir().get_parent_node(original_expr_id);
while let Some(node) = self.tcx.hir().find(parent) { while let Some(node) = self.tcx.hir().find(parent) {
match node { match node {
hir::Node::Expr(hir::Expr { hir::Node::Expr(hir::Expr {
@ -861,8 +881,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
), ),
.. ..
}) => { }) => {
// Check if our lhs is a child of the condition of a while loop // Check if our original expression is a child of the condition of a while loop
let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| { let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| {
self.tcx.hir().find_parent_node(*id) self.tcx.hir().find_parent_node(*id)
}) })
.take_while(|id| *id != parent) .take_while(|id| *id != parent)
@ -870,12 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// if it is, then we have a situation like `while Some(0) = value.get(0) {`, // if it is, then we have a situation like `while Some(0) = value.get(0) {`,
// where `while let` was more likely intended. // where `while let` was more likely intended.
if expr_is_ancestor { if expr_is_ancestor {
err.span_suggestion_verbose( then(expr);
expr.span.shrink_to_lo(),
"you might have meant to use pattern destructuring",
"let ".to_string(),
Applicability::MachineApplicable,
);
} }
break; break;
} }
@ -888,8 +903,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
} }
err.emit();
} }
// A generic function for checking the 'then' and 'else' clauses in an 'if' // A generic function for checking the 'then' and 'else' clauses in an 'if'

View File

@ -768,7 +768,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let prev_diverges = self.diverges.get(); let prev_diverges = self.diverges.get();
let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false }; let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || { let (ctxt, ()) =
self.with_breakable_ctxt(blk.hir_id, ctxt, || {
for (pos, s) in blk.stmts.iter().enumerate() { for (pos, s) in blk.stmts.iter().enumerate() {
self.check_stmt(s, blk.stmts.len() - 1 == pos); self.check_stmt(s, blk.stmts.len() - 1 == pos);
} }
@ -783,7 +784,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(tail_expr_ty) = tail_expr_ty { if let Some(tail_expr_ty) = tail_expr_ty {
let tail_expr = tail_expr.unwrap(); let tail_expr = tail_expr.unwrap();
let span = self.get_expr_coercion_span(tail_expr); let span = self.get_expr_coercion_span(tail_expr);
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); let cause =
self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
coerce.coerce(self, &cause, tail_expr, tail_expr_ty); coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
} else { } else {
// Subtle: if there is no explicit tail expression, // Subtle: if there is no explicit tail expression,
@ -825,19 +827,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if expected_ty == self.tcx.types.bool { if expected_ty == self.tcx.types.bool {
// If this is caused by a missing `let` in a `while let`, // If this is caused by a missing `let` in a `while let`,
// silence this redundant error, as we already emit E0070. // silence this redundant error, as we already emit E0070.
let parent = self.tcx.hir().get_parent_node(blk.hir_id);
let parent = self.tcx.hir().get_parent_node(parent); // Our block must be a `assign desugar local; assignment`
let parent = self.tcx.hir().get_parent_node(parent); if let Some(hir::Node::Block(hir::Block {
let parent = self.tcx.hir().get_parent_node(parent); stmts:
let parent = self.tcx.hir().get_parent_node(parent); [hir::Stmt {
match self.tcx.hir().find(parent) { kind:
Some(hir::Node::Expr(hir::Expr { hir::StmtKind::Local(hir::Local {
kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), source: hir::LocalSource::AssignDesugar(_),
.. ..
})) => { }),
..
}, hir::Stmt {
kind:
hir::StmtKind::Expr(hir::Expr {
kind: hir::ExprKind::Assign(..),
..
}),
..
}],
..
})) = self.tcx.hir().find(blk.hir_id)
{
self.comes_from_while_condition(blk.hir_id, |_| {
err.downgrade_to_delayed_bug(); err.downgrade_to_delayed_bug();
} })
_ => {}
} }
} }
} }

View File

@ -986,7 +986,7 @@ impl<K, V> BTreeMap<K, V> {
self.drain_filter(|k, v| !f(k, v)); self.drain_filter(|k, v| !f(k, v));
} }
/// Moves all elements from `other` into `Self`, leaving `other` empty. /// Moves all elements from `other` into `self`, leaving `other` empty.
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -895,7 +895,7 @@ impl<T> BTreeSet<T> {
self.drain_filter(|v| !f(v)); self.drain_filter(|v| !f(v));
} }
/// Moves all elements from `other` into `Self`, leaving `other` empty. /// Moves all elements from `other` into `self`, leaving `other` empty.
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -1763,7 +1763,7 @@ impl<T, A: Allocator> Vec<T, A> {
} }
} }
/// Moves all the elements of `other` into `Self`, leaving `other` empty. /// Moves all the elements of `other` into `self`, leaving `other` empty.
/// ///
/// # Panics /// # Panics
/// ///
@ -1788,7 +1788,7 @@ impl<T, A: Allocator> Vec<T, A> {
} }
} }
/// Appends elements to `Self` from other buffer. /// Appends elements to `self` from other buffer.
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[inline] #[inline]
unsafe fn append_elements(&mut self, other: *const [T]) { unsafe fn append_elements(&mut self, other: *const [T]) {

View File

@ -8,3 +8,4 @@ LL | async fn error(lt: HasLifetime) {
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0726`.

View File

@ -132,7 +132,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `}`
LL | match await { await => () } LL | match await { await => () }
| ----- - expected one of `.`, `?`, `{`, or an operator | ----- - expected one of `.`, `?`, `{`, or an operator
| | | |
| while parsing this match expression | while parsing this `match` expression
... ...
LL | } LL | }
| ^ unexpected token | ^ unexpected token

View File

@ -1,6 +0,0 @@
// check-pass
#![feature(allocator_api)]
fn main() {
Box::new_in((), &std::alloc::Global);
}

View File

@ -0,0 +1,23 @@
// build-pass
#![feature(allocator_api)]
use std::alloc::Allocator;
struct BigAllocator([usize; 2]);
unsafe impl Allocator for BigAllocator {
fn allocate(
&self,
_: std::alloc::Layout,
) -> Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError> {
todo!()
}
unsafe fn deallocate(&self, _: std::ptr::NonNull<u8>, _: std::alloc::Layout) {
todo!()
}
}
fn main() {
Box::new_in((), &std::alloc::Global);
Box::new_in((), BigAllocator([0; 2]));
}

View File

@ -28,10 +28,7 @@ error: expected `{`, found `;`
LL | if not // lack of braces is [sic] LL | if not // lack of braces is [sic]
| -- this `if` expression has a condition, but no block | -- this `if` expression has a condition, but no block
LL | println!("Then when?"); LL | println!("Then when?");
| ^ | ^ expected `{`
| |
| expected `{`
| help: try placing this code inside a block: `{ ; }`
error: unexpected `2` after identifier error: unexpected `2` after identifier
--> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24

View File

@ -2,16 +2,14 @@ error: unexpected `,` in pattern
--> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17 --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17
| |
LL | while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") { LL | while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
| ^ | ----- ^
| |
| while parsing the condition of this `while` expression
| |
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple
| |
LL | while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") { LL | while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") {
| ~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | while let b1 | b2 | b3 = reading_frame.next().expect("there should be a start codon") {
| ~~~~~~~~~~~~
error: unexpected `,` in pattern error: unexpected `,` in pattern
--> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14 --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14
@ -19,14 +17,10 @@ error: unexpected `,` in pattern
LL | if let b1, b2, b3 = reading_frame.next().unwrap() { LL | if let b1, b2, b3 = reading_frame.next().unwrap() {
| ^ | ^
| |
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple
| |
LL | if let (b1, b2, b3) = reading_frame.next().unwrap() { LL | if let (b1, b2, b3) = reading_frame.next().unwrap() {
| ~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | if let b1 | b2 | b3 = reading_frame.next().unwrap() {
| ~~~~~~~~~~~~
error: unexpected `,` in pattern error: unexpected `,` in pattern
--> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28 --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28
@ -37,7 +31,7 @@ LL | Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple...
| |
LL | (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true LL | (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives help: ...or a vertical bar to match on multiple alternatives
| |
LL | Nucleotide::Adenine | Nucleotide::Cytosine | _ => true LL | Nucleotide::Adenine | Nucleotide::Cytosine | _ => true
@ -49,14 +43,10 @@ error: unexpected `,` in pattern
LL | for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) { LL | for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
| ^ | ^
| |
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple
| |
LL | for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) { LL | for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) {
| ~~~~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
| ~~~~~~~~~~~~~~
error: unexpected `,` in pattern error: unexpected `,` in pattern
--> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10 --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10
@ -64,14 +54,10 @@ error: unexpected `,` in pattern
LL | for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) { LL | for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
| ^ | ^
| |
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple
| |
LL | for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) { LL | for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) {
| ~~~~~~~~~~~~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
| ~~~~~~~~~~~~~~~~~~~~~~
error: unexpected `,` in pattern error: unexpected `,` in pattern
--> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14 --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14
@ -79,14 +65,10 @@ error: unexpected `,` in pattern
LL | let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned() LL | let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
| ^ | ^
| |
help: try adding parentheses to match on a tuple... help: try adding parentheses to match on a tuple
| |
LL | let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned() LL | let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
| ~~~~~~~~~~~~ | + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
| ~~~~~~~~~~~
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View File

@ -8,3 +8,4 @@ LL | impl MyTrait for Foo {
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0726`.

View File

@ -8,3 +8,4 @@ LL | impl MyTrait for u32 {
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0726`.

View File

@ -67,4 +67,5 @@ LL | trait Serializable<'self, T: ?Sized> {
error: aborting due to 9 previous errors error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0277`. Some errors have detailed explanations: E0277, E0726.
For more information about an error, try `rustc --explain E0277`.

View File

@ -2,16 +2,18 @@ error: expected `{`, found `foo`
--> $DIR/issue-39848.rs:3:21 --> $DIR/issue-39848.rs:3:21
| |
LL | if $tgt.has_$field() {} LL | if $tgt.has_$field() {}
| -- ^^^^^^-- | -- ^^^^^^ expected `{`
| | | | |
| | expected `{`
| | help: try placing this code inside a block: `{ $field() }`
| this `if` expression has a condition, but no block | this `if` expression has a condition, but no block
... ...
LL | get_opt!(bar, foo); LL | get_opt!(bar, foo);
| ------------------ in this macro invocation | ------------------ in this macro invocation
| |
= note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info)
help: try placing this code inside a block
|
LL | if $tgt.has_{ $field() } {}
| + +
error: aborting due to previous error error: aborting due to previous error

View File

@ -0,0 +1,30 @@
// run-rustfix
#![feature(label_break_value)]
// These are forbidden occurrences of label-break-value
#[allow(unused_unsafe)]
fn labeled_unsafe() {
unsafe {} //~ ERROR block label not supported here
}
fn labeled_if() {
if true {} //~ ERROR block label not supported here
}
fn labeled_else() {
if true {} else {} //~ ERROR block label not supported here
}
fn labeled_match() {
match false { //~ ERROR block label not supported here
_ => {}
}
}
fn main() {
labeled_unsafe();
labeled_if();
labeled_else();
labeled_match();
}

View File

@ -1,21 +1,30 @@
// run-rustfix
#![feature(label_break_value)] #![feature(label_break_value)]
// These are forbidden occurrences of label-break-value // These are forbidden occurrences of label-break-value
#[allow(unused_unsafe)]
fn labeled_unsafe() { fn labeled_unsafe() {
unsafe 'b: {} //~ ERROR expected `{`, found `'b` unsafe 'b: {} //~ ERROR block label not supported here
} }
fn labeled_if() { fn labeled_if() {
if true 'b: {} //~ ERROR expected `{`, found `'b` if true 'b: {} //~ ERROR block label not supported here
} }
fn labeled_else() { fn labeled_else() {
if true {} else 'b: {} //~ ERROR expected `{`, found `'b` if true {} else 'b: {} //~ ERROR block label not supported here
} }
fn labeled_match() { fn labeled_match() {
match false 'b: {} //~ ERROR expected one of `.`, `?`, `{`, or an operator match false 'b: { //~ ERROR block label not supported here
_ => {}
}
} }
pub fn main() {} fn main() {
labeled_unsafe();
labeled_if();
labeled_else();
labeled_match();
}

View File

@ -1,38 +1,26 @@
error: expected `{`, found `'b` error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:6:12 --> $DIR/label_break_value_illegal_uses.rs:8:12
| |
LL | unsafe 'b: {} LL | unsafe 'b: {}
| ^^---- | ^^^ not supported here
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
error: expected `{`, found `'b` error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:10:13 --> $DIR/label_break_value_illegal_uses.rs:12:13
| |
LL | if true 'b: {} LL | if true 'b: {}
| -- ^^---- | ^^^ not supported here
| | |
| | expected `{`
| | help: try placing this code inside a block: `{ 'b: {} }`
| this `if` expression has a condition, but no block
error: expected `{`, found `'b` error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:14:21 --> $DIR/label_break_value_illegal_uses.rs:16:21
| |
LL | if true {} else 'b: {} LL | if true {} else 'b: {}
| ^^---- | ^^^ not supported here
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
error: expected one of `.`, `?`, `{`, or an operator, found `'b` error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:18:17 --> $DIR/label_break_value_illegal_uses.rs:20:17
| |
LL | match false 'b: {} LL | match false 'b: {
| ----- ^^ expected one of `.`, `?`, `{`, or an operator | ^^^ not supported here
| |
| while parsing this match expression
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View File

@ -7,10 +7,10 @@ LL | let Some(_) = Some(()) else if true {
help: try placing this code inside a block help: try placing this code inside a block
| |
LL ~ let Some(_) = Some(()) else { if true { LL ~ let Some(_) = Some(()) else { if true {
LL + LL |
LL + return; LL | return;
LL + } else { LL | } else {
LL + return; LL | return;
LL ~ } }; LL ~ } };
| |

View File

@ -12,10 +12,12 @@ error: expected `{`, found `bar`
LL | if (foo) LL | if (foo)
| -- this `if` expression has a condition, but no block | -- this `if` expression has a condition, but no block
LL | bar; LL | bar;
| ^^^- | ^^^ expected `{`
| | |
| expected `{` help: try placing this code inside a block
| help: try placing this code inside a block: `{ bar; }` |
LL | { bar; }
| + +
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -1,29 +1,41 @@
error: expected `{`, found keyword `let` error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:9:9 --> $DIR/block-no-opening-brace.rs:9:9
| |
LL | loop
| ---- while parsing this `loop` expression
LL | let x = 0; LL | let x = 0;
| ^^^------- | ^^^ expected `{`
| | |
| expected `{` help: try placing this code inside a block
| help: try placing this code inside a block: `{ let x = 0; }` |
LL | { let x = 0; }
| + +
error: expected `{`, found keyword `let` error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:15:9 --> $DIR/block-no-opening-brace.rs:15:9
| |
LL | let x = 0; LL | while true
| ^^^------- | ----- ---- this `while` condition successfully parsed
| | | |
| expected `{` | while parsing the body of this `while` expression
| help: try placing this code inside a block: `{ let x = 0; }` LL | let x = 0;
| ^^^ expected `{`
|
help: try placing this code inside a block
|
LL | { let x = 0; }
| + +
error: expected `{`, found keyword `let` error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:20:9 --> $DIR/block-no-opening-brace.rs:20:9
| |
LL | let x = 0; LL | let x = 0;
| ^^^------- | ^^^ expected `{`
| | |
| expected `{` help: try placing this code inside a block
| help: try placing this code inside a block: `{ let x = 0; }` |
LL | { let x = 0; }
| + +
error: expected expression, found reserved keyword `try` error: expected expression, found reserved keyword `try`
--> $DIR/block-no-opening-brace.rs:24:5 --> $DIR/block-no-opening-brace.rs:24:5

View File

@ -2,10 +2,12 @@ error: expected `{`, found `22`
--> $DIR/closure-return-syntax.rs:5:23 --> $DIR/closure-return-syntax.rs:5:23
| |
LL | let x = || -> i32 22; LL | let x = || -> i32 22;
| ^^ | ^^ expected `{`
| | |
| expected `{` help: try placing this code inside a block
| help: try placing this code inside a block: `{ 22 }` |
LL | let x = || -> i32 { 22 };
| + +
error: aborting due to previous error error: aborting due to previous error

View File

@ -63,9 +63,8 @@ LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s
| |
help: try placing this code inside a block help: try placing this code inside a block
| |
LL ~ fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { }
LL + } | + +
|
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View File

@ -50,7 +50,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `}`
--> $DIR/issue-62973.rs:8:2 --> $DIR/issue-62973.rs:8:2
| |
LL | fn p() { match s { v, E { [) {) } LL | fn p() { match s { v, E { [) {) }
| ----- while parsing this match expression | ----- while parsing this `match` expression
LL | LL |
LL | LL |
| ^ expected one of `.`, `?`, `{`, or an operator | ^ expected one of `.`, `?`, `{`, or an operator

View File

@ -2,7 +2,7 @@
fn main() { fn main() {
let foo = let foo =
//~ NOTE while parsing this match expression //~ NOTE while parsing this `match` expression
Some(4).unwrap_or(5) Some(4).unwrap_or(5)
//~^ NOTE expected one of `.`, `?`, `{`, or an operator //~^ NOTE expected one of `.`, `?`, `{`, or an operator
; //~ NOTE unexpected token ; //~ NOTE unexpected token

View File

@ -2,7 +2,7 @@
fn main() { fn main() {
let foo = let foo =
match //~ NOTE while parsing this match expression match //~ NOTE while parsing this `match` expression
Some(4).unwrap_or(5) Some(4).unwrap_or(5)
//~^ NOTE expected one of `.`, `?`, `{`, or an operator //~^ NOTE expected one of `.`, `?`, `{`, or an operator
; //~ NOTE unexpected token ; //~ NOTE unexpected token

View File

@ -4,7 +4,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `;`
LL | match LL | match
| ----- | -----
| | | |
| while parsing this match expression | while parsing this `match` expression
| help: try removing this `match` | help: try removing this `match`
LL | Some(4).unwrap_or(5) LL | Some(4).unwrap_or(5)
| - expected one of `.`, `?`, `{`, or an operator | - expected one of `.`, `?`, `{`, or an operator

View File

@ -0,0 +1,13 @@
fn main() {
let container = vec![Some(1), Some(2), None];
let mut i = 0;
while if let Some(thing) = container.get(i) {
//~^ NOTE while parsing the body of this `while` expression
//~| NOTE this `while` condition successfully parsed
println!("{:?}", thing);
i += 1;
}
}
//~^ ERROR expected `{`, found `}`
//~| NOTE expected `{`

View File

@ -0,0 +1,18 @@
error: expected `{`, found `}`
--> $DIR/while-if-let-without-body.rs:11:1
|
LL | while if let Some(thing) = container.get(i) {
| _____-----_-
| | |
| | while parsing the body of this `while` expression
LL | |
LL | |
LL | | println!("{:?}", thing);
LL | | i += 1;
LL | | }
| |_____- this `while` condition successfully parsed
LL | }
| ^ expected `{`
error: aborting due to previous error

View File

@ -0,0 +1,4 @@
fn main() {
while {} {}
//~^ ERROR mismatched types [E0308]
}

View File

@ -0,0 +1,9 @@
error[E0308]: mismatched types
--> $DIR/while-loop-block-cond.rs:2:11
|
LL | while {} {}
| ^^ expected `bool`, found `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

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

View File

@ -30,3 +30,4 @@ LL | impl Trait for Ref {}
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0726`.