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 @@ pub fn codegen_place(
};
for elem in place_ref.projection[base..].iter() {
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, _) => {
cg_base.project_field(bx, field.index())
}

View file

@ -429,6 +429,7 @@
E0722: include_str!("./error_codes/E0722.md"),
E0724: include_str!("./error_codes/E0724.md"),
E0725: include_str!("./error_codes/E0725.md"),
E0726: include_str!("./error_codes/E0726.md"),
E0727: include_str!("./error_codes/E0727.md"),
E0728: include_str!("./error_codes/E0728.md"),
E0729: include_str!("./error_codes/E0729.md"),
@ -641,6 +642,5 @@
E0717, // rustc_promotable without stability attribute
// E0721, // `await` keyword
// 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" { ... }`.
}

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

View file

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

View file

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

View file

@ -1,8 +1,8 @@
use super::pat::Expected;
use super::ty::{AllowPlus, IsAsCast};
use super::{
BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
TokenExpectType, TokenType,
BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType,
};
use rustc_ast as ast;
@ -732,43 +732,42 @@ pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
mut e: DiagnosticBuilder<'a, ErrorReported>,
expr: &mut P<Expr>,
) -> PResult<'a, ()> {
if let ExprKind::Binary(binop, _, _) = &expr.kind {
if let ast::BinOpKind::Lt = binop.node {
if self.eat(&token::Comma) {
let x = self.parse_seq_to_before_end(
&token::Gt,
SeqSep::trailing_allowed(token::Comma),
|p| p.parse_generic_arg(None),
);
match x {
Ok((_, _, false)) => {
if self.eat(&token::Gt) {
e.span_suggestion_verbose(
binop.span.shrink_to_lo(),
TURBOFISH_SUGGESTION_STR,
"::".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
match self.parse_expr() {
Ok(_) => {
*expr =
self.mk_expr_err(expr.span.to(self.prev_token.span));
return Ok(());
}
Err(err) => {
*expr = self.mk_expr_err(expr.span);
err.cancel();
}
}
if let ExprKind::Binary(binop, _, _) = &expr.kind
&& let ast::BinOpKind::Lt = binop.node
&& self.eat(&token::Comma)
{
let x = self.parse_seq_to_before_end(
&token::Gt,
SeqSep::trailing_allowed(token::Comma),
|p| p.parse_generic_arg(None),
);
match x {
Ok((_, _, false)) => {
if self.eat(&token::Gt) {
e.span_suggestion_verbose(
binop.span.shrink_to_lo(),
TURBOFISH_SUGGESTION_STR,
"::".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
match self.parse_expr() {
Ok(_) => {
*expr =
self.mk_expr_err(expr.span.to(self.prev_token.span));
return Ok(());
}
Err(err) => {
*expr = self.mk_expr_err(expr.span);
err.cancel();
}
}
Err(err) => {
err.cancel();
}
_ => {}
}
}
Err(err) => {
err.cancel();
}
_ => {}
}
}
Err(e)
@ -784,12 +783,13 @@ fn attempt_chained_comparison_suggestion(
outer_op: &Spanned<AssocOp>,
) -> bool /* advanced the cursor */ {
if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
if let ExprKind::Field(_, ident) = l1.kind {
if ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) {
// The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
// suggestion being the only one to apply is high.
return false;
}
if let ExprKind::Field(_, ident) = l1.kind
&& ident.as_str().parse::<i32>().is_err()
&& !matches!(r1.kind, ExprKind::Lit(_))
{
// The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
// suggestion being the only one to apply is high.
return false;
}
let mut enclose = |left: Span, right: Span| {
err.multipart_suggestion(
@ -2245,12 +2245,32 @@ pub(super) fn incorrect_move_async_order_found(
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,
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
crate fn maybe_recover_unexpected_comma(
&mut self,
lo: Span,
rc: RecoverComma,
rt: CommaRecoveryMode,
) -> PResult<'a, ()> {
if rc == RecoverComma::No || self.token != token::Comma {
return Ok(());
@ -2270,20 +2290,25 @@ pub(super) fn incorrect_move_async_order_found(
let seq_span = lo.to(self.prev_token.span);
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
const MSG: &str = "try adding parentheses to match on a tuple...";
err.span_suggestion(
seq_span,
MSG,
format!("({})", seq_snippet),
Applicability::MachineApplicable,
);
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
err.multipart_suggestion(
&format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
Applicability::MachineApplicable,
);
}
}
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::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
@ -1286,18 +1286,27 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
} else if let Some(label) = self.eat_label() {
self.parse_labeled_expr(label, attrs, true)
} 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) {
let kind = ExprKind::Continue(self.eat_label());
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs))
} else if self.eat_keyword(kw::Match) {
let match_sp = self.prev_token.span;
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
})
} else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span;
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) {
self.parse_const_block(lo.to(self.token.span), false)
} else if self.is_do_catch_block() {
@ -2160,7 +2169,12 @@ fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
/// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
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)?;
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())
@ -2223,7 +2237,12 @@ fn parse_for_expr(
_ => 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) {
self.error_missing_in_for_loop();
}
@ -2266,8 +2285,15 @@ fn parse_while_expr(
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr()?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
let cond = self.parse_cond_expr().map_err(|mut err| {
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);
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs))
}
@ -2284,7 +2310,7 @@ fn parse_loop_expr(
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.bump();
Label { ident }
@ -2305,7 +2331,12 @@ fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
Applicability::MaybeIncorrect, // speculative
);
}
return Err(e);
if self.maybe_recover_unexpected_block_label() {
e.cancel();
self.bump();
} else {
return Err(e);
}
}
attrs.extend(self.parse_inner_attributes()?);
@ -2441,7 +2472,12 @@ fn check_let_expr(expr: &Expr) -> (bool, bool) {
let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
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 if_span = this.prev_token.span;
let cond = this.parse_expr()?;

View file

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

View file

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

View file

@ -5,7 +5,7 @@
use rustc_errors::PResult;
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};
impl<'a> Parser<'a> {
@ -125,7 +125,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
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!(),
})?)

View file

@ -33,6 +33,13 @@ pub enum RecoverColon {
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
/// emitting duplicate diagnostics.
#[derive(Debug, Clone, Copy)]
@ -68,8 +75,9 @@ pub fn parse_pat_allow_top_alt(
expected: Expected,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
) -> 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 =
@ -79,6 +87,7 @@ fn parse_pat_allow_top_alt_inner(
expected: Expected,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
) -> PResult<'a, (P<Pat>, bool)> {
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
// suggestions (which bothers rustfix).
@ -92,7 +101,7 @@ fn parse_pat_allow_top_alt_inner(
// Parse the first pattern (`p_0`).
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 `|`,
// this is not an or-pattern and we should exit here.
@ -130,7 +139,7 @@ fn parse_pat_allow_top_alt_inner(
err.span_label(lo, WHILE_PARSING_OR_MSG);
err
})?;
self.maybe_recover_unexpected_comma(pat.span, rc)?;
self.maybe_recover_unexpected_comma(pat.span, rc, rt)?;
pats.push(pat);
}
let or_pattern_span = lo.to(self.prev_token.span);
@ -155,8 +164,12 @@ pub(super) fn parse_pat_before_ty(
// 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
// better error message.
let (pat, trailing_vert) =
self.parse_pat_allow_top_alt_inner(expected, rc, RecoverColon::No)?;
let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(
expected,
rc,
RecoverColon::No,
CommaRecoveryMode::LikelyTuple,
)?;
let colon = self.eat(&token::Colon);
if let PatKind::Or(pats) = &pat.kind {
@ -315,7 +328,12 @@ fn parse_pat_with_range_pat(
} else if self.check(&token::OpenDelim(token::Bracket)) {
// Parse `[pat, pat,...]` as a slice pattern.
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)
} else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
@ -529,7 +547,12 @@ fn recover_lifetime_in_deref_pat(&mut self) {
/// Parse a tuple or parenthesis pattern.
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
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.
@ -873,7 +896,12 @@ fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a,
/// 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> {
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() {
self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
@ -1033,7 +1061,12 @@ fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Pa
// Parsing a pattern of the form `fieldname: pat`.
let fieldname = self.parse_field_name()?;
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;
(pat, fieldname, false)
} else {

View file

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

View file

@ -48,15 +48,13 @@ pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<
// Don't use `maybe_whole` so that we have precise control
// over when we bump the parser
if let token::Interpolated(nt) = &self.token.kind {
if let token::NtStmt(stmt) = &**nt {
let mut stmt = stmt.clone();
self.bump();
stmt.visit_attrs(|stmt_attrs| {
attrs.prepend_to_nt_inner(stmt_attrs);
});
return Ok(Some(stmt));
}
if let token::Interpolated(nt) = &self.token.kind && let token::NtStmt(stmt) = &**nt {
let mut stmt = stmt.clone();
self.bump();
stmt.visit_attrs(|stmt_attrs| {
attrs.prepend_to_nt_inner(stmt_attrs);
});
return Ok(Some(stmt));
}
Ok(Some(if self.token.is_keyword(kw::Let) {
@ -434,6 +432,8 @@ fn error_block_no_opening_brace_msg(
Ok(Some(_))
if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|| 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)) => {
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) {
@ -442,15 +442,15 @@ fn error_block_no_opening_brace_msg(
} else {
stmt.span
};
if let Ok(snippet) = self.span_to_snippet(stmt_span) {
e.span_suggestion(
stmt_span,
"try placing this code inside a block",
format!("{{ {} }}", snippet),
// Speculative; has been misleading in the past (#46836).
Applicability::MaybeIncorrect,
);
}
e.multipart_suggestion(
"try placing this code inside a block",
vec![
(stmt_span.shrink_to_lo(), "{ ".to_string()),
(stmt_span.shrink_to_hi(), " }".to_string()),
],
// Speculative; has been misleading in the past (#46836).
Applicability::MaybeIncorrect,
);
}
Err(e) => {
self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
@ -483,15 +483,15 @@ pub(super) fn parse_block_common(
) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
self.maybe_recover_unexpected_block_label();
if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace();
}
let attrs = self.parse_inner_attributes()?;
let tail = if let Some(tail) = self.maybe_suggest_struct_literal(lo, blk_mode) {
tail?
} else {
self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?
let tail = match self.maybe_suggest_struct_literal(lo, blk_mode) {
Some(tail) => tail?,
None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
};
Ok((attrs, tail))
}
@ -587,11 +587,11 @@ pub fn parse_full_stmt(
// We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
match &mut local.kind {
LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
// We found `foo<bar, baz>`, have we fully recovered?
self.expect_semi()?;
}
LocalKind::Decl => return Err(e),
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
// We found `foo<bar, baz>`, have we fully recovered?
self.expect_semi()?;
}
LocalKind::Decl => return Err(e),
}
eat_semi = false;
}

View file

@ -840,7 +840,27 @@ pub(crate) fn check_lhs_assignable(
);
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) {
match node {
hir::Node::Expr(hir::Expr {
@ -861,8 +881,8 @@ pub(crate) fn check_lhs_assignable(
),
..
}) => {
// Check if our lhs is a child of the condition of a while loop
let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| {
// Check if our original expression is a child of the condition of a while loop
let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| {
self.tcx.hir().find_parent_node(*id)
})
.take_while(|id| *id != parent)
@ -870,12 +890,7 @@ pub(crate) fn check_lhs_assignable(
// if it is, then we have a situation like `while Some(0) = value.get(0) {`,
// where `while let` was more likely intended.
if expr_is_ancestor {
err.span_suggestion_verbose(
expr.span.shrink_to_lo(),
"you might have meant to use pattern destructuring",
"let ".to_string(),
Applicability::MachineApplicable,
);
then(expr);
}
break;
}
@ -888,8 +903,6 @@ pub(crate) fn check_lhs_assignable(
}
}
}
err.emit();
}
// A generic function for checking the 'then' and 'else' clauses in an 'if'

View file

@ -768,55 +768,57 @@ pub(in super::super) fn check_block_with_expected(
let prev_diverges = self.diverges.get();
let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
for (pos, s) in blk.stmts.iter().enumerate() {
self.check_stmt(s, blk.stmts.len() - 1 == pos);
}
let (ctxt, ()) =
self.with_breakable_ctxt(blk.hir_id, ctxt, || {
for (pos, s) in blk.stmts.iter().enumerate() {
self.check_stmt(s, blk.stmts.len() - 1 == pos);
}
// check the tail expression **without** holding the
// `enclosing_breakables` lock below.
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
// check the tail expression **without** holding the
// `enclosing_breakables` lock below.
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
let coerce = ctxt.coerce.as_mut().unwrap();
if let Some(tail_expr_ty) = tail_expr_ty {
let tail_expr = tail_expr.unwrap();
let span = self.get_expr_coercion_span(tail_expr);
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
} else {
// Subtle: if there is no explicit tail expression,
// that is typically equivalent to a tail expression
// of `()` -- except if the block diverges. In that
// case, there is no value supplied from the tail
// expression (assuming there are no other breaks,
// this implies that the type of the block will be
// `!`).
//
// #41425 -- label the implicit `()` as being the
// "found type" here, rather than the "expected type".
if !self.diverges.get().is_always() {
// #50009 -- Do not point at the entire fn block span, point at the return type
// span, as it is the cause of the requirement, and
// `consider_hint_about_removing_semicolon` will point at the last expression
// if it were a relevant part of the error. This improves usability in editors
// that highlight errors inline.
let mut sp = blk.span;
let mut fn_span = None;
if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
let ret_sp = decl.output.span();
if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
// HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
// output would otherwise be incorrect and even misleading. Make sure
// the span we're aiming at correspond to a `fn` body.
if block_sp == blk.span {
sp = ret_sp;
fn_span = Some(ident.span);
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
let coerce = ctxt.coerce.as_mut().unwrap();
if let Some(tail_expr_ty) = tail_expr_ty {
let tail_expr = tail_expr.unwrap();
let span = self.get_expr_coercion_span(tail_expr);
let cause =
self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
} else {
// Subtle: if there is no explicit tail expression,
// that is typically equivalent to a tail expression
// of `()` -- except if the block diverges. In that
// case, there is no value supplied from the tail
// expression (assuming there are no other breaks,
// this implies that the type of the block will be
// `!`).
//
// #41425 -- label the implicit `()` as being the
// "found type" here, rather than the "expected type".
if !self.diverges.get().is_always() {
// #50009 -- Do not point at the entire fn block span, point at the return type
// span, as it is the cause of the requirement, and
// `consider_hint_about_removing_semicolon` will point at the last expression
// if it were a relevant part of the error. This improves usability in editors
// that highlight errors inline.
let mut sp = blk.span;
let mut fn_span = None;
if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
let ret_sp = decl.output.span();
if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
// HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
// output would otherwise be incorrect and even misleading. Make sure
// the span we're aiming at correspond to a `fn` body.
if block_sp == blk.span {
sp = ret_sp;
fn_span = Some(ident.span);
}
}
}
}
coerce.coerce_forced_unit(
coerce.coerce_forced_unit(
self,
&self.misc(sp),
&mut |err| {
@ -825,19 +827,31 @@ pub(in super::super) fn check_block_with_expected(
if expected_ty == self.tcx.types.bool {
// If this is caused by a missing `let` in a `while let`,
// 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);
let parent = self.tcx.hir().get_parent_node(parent);
let parent = self.tcx.hir().get_parent_node(parent);
let parent = self.tcx.hir().get_parent_node(parent);
match self.tcx.hir().find(parent) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
..
})) => {
// Our block must be a `assign desugar local; assignment`
if let Some(hir::Node::Block(hir::Block {
stmts:
[hir::Stmt {
kind:
hir::StmtKind::Local(hir::Local {
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();
}
_ => {}
})
}
}
}
@ -851,9 +865,9 @@ pub(in super::super) fn check_block_with_expected(
},
false,
);
}
}
}
});
});
if ctxt.may_break {
// If we can break from the block, then the block's exit is always reachable

View file

@ -986,7 +986,7 @@ pub fn retain<F>(&mut self, mut f: F)
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
///

View file

@ -895,7 +895,7 @@ pub fn retain<F>(&mut self, mut f: F)
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
///

View file

@ -1763,7 +1763,7 @@ pub fn pop(&mut self) -> Option<T> {
}
}
/// Moves all the elements of `other` into `Self`, leaving `other` empty.
/// Moves all the elements of `other` into `self`, leaving `other` empty.
///
/// # Panics
///
@ -1788,7 +1788,7 @@ pub fn append(&mut self, other: &mut Self) {
}
}
/// Appends elements to `Self` from other buffer.
/// Appends elements to `self` from other buffer.
#[cfg(not(no_global_oom_handling))]
#[inline]
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
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 => () }
| ----- - expected one of `.`, `?`, `{`, or an operator
| |
| while parsing this match expression
| while parsing this `match` expression
...
LL | }
| ^ 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]
| -- this `if` expression has a condition, but no block
LL | println!("Then when?");
| ^
| |
| expected `{`
| help: try placing this code inside a block: `{ ; }`
| ^ expected `{`
error: unexpected `2` after identifier
--> $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
|
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") {
| ~~~~~~~~~~~~
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
--> $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() {
| ^
|
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() {
| ~~~~~~~~~~~~
help: ...or a vertical bar to match on multiple alternatives
|
LL | if let b1 | b2 | b3 = reading_frame.next().unwrap() {
| ~~~~~~~~~~~~
| + +
error: unexpected `,` in pattern
--> $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...
|
LL | (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| + +
help: ...or a vertical bar to match on multiple alternatives
|
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()) {
| ^
|
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()) {
| ~~~~~~~~~~~~~~~
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
--> $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()) {
| ^
|
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()) {
| ~~~~~~~~~~~~~~~~~~~~~~~
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
--> $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()
| ^
|
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()
| ~~~~~~~~~~~~
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

View file

@ -8,3 +8,4 @@ LL | impl MyTrait for Foo {
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
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
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
|
LL | if $tgt.has_$field() {}
| -- ^^^^^^--
| | |
| | expected `{`
| | help: try placing this code inside a block: `{ $field() }`
| -- ^^^^^^ expected `{`
| |
| this `if` expression has a condition, but no block
...
LL | get_opt!(bar, foo);
| ------------------ in this macro invocation
|
= 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

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)]
// These are forbidden occurrences of label-break-value
#[allow(unused_unsafe)]
fn labeled_unsafe() {
unsafe 'b: {} //~ ERROR expected `{`, found `'b`
unsafe 'b: {} //~ ERROR block label not supported here
}
fn labeled_if() {
if true 'b: {} //~ ERROR expected `{`, found `'b`
if true 'b: {} //~ ERROR block label not supported here
}
fn labeled_else() {
if true {} else 'b: {} //~ ERROR expected `{`, found `'b`
if true {} else 'b: {} //~ ERROR block label not supported here
}
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`
--> $DIR/label_break_value_illegal_uses.rs:6:12
error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:8:12
|
LL | unsafe 'b: {}
| ^^----
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
| ^^^ not supported here
error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:10:13
error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:12:13
|
LL | if true 'b: {}
| -- ^^----
| | |
| | expected `{`
| | help: try placing this code inside a block: `{ 'b: {} }`
| this `if` expression has a condition, but no block
| ^^^ not supported here
error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:14:21
error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:16:21
|
LL | if true {} else 'b: {}
| ^^----
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
| ^^^ not supported here
error: expected one of `.`, `?`, `{`, or an operator, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:18:17
error: block label not supported here
--> $DIR/label_break_value_illegal_uses.rs:20:17
|
LL | match false 'b: {}
| ----- ^^ expected one of `.`, `?`, `{`, or an operator
| |
| while parsing this match expression
LL | match false 'b: {
| ^^^ not supported here
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
|
LL ~ let Some(_) = Some(()) else { if true {
LL +
LL + return;
LL + } else {
LL + return;
LL |
LL | return;
LL | } else {
LL | return;
LL ~ } };
|

View file

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

View file

@ -1,29 +1,41 @@
error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:9:9
|
LL | loop
| ---- while parsing this `loop` expression
LL | let x = 0;
| ^^^-------
| |
| expected `{`
| help: try placing this code inside a block: `{ let x = 0; }`
| ^^^ expected `{`
|
help: try placing this code inside a block
|
LL | { let x = 0; }
| + +
error: expected `{`, found keyword `let`
--> $DIR/block-no-opening-brace.rs:15:9
|
LL | while true
| ----- ---- this `while` condition successfully parsed
| |
| while parsing the body of this `while` expression
LL | let x = 0;
| ^^^-------
| |
| expected `{`
| help: try placing this code inside a block: `{ let x = 0; }`
| ^^^ expected `{`
|
help: try placing this code inside a block
|
LL | { 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; }`
| ^^^ expected `{`
|
help: try placing this code inside a block
|
LL | { let x = 0; }
| + +
error: expected expression, found reserved keyword `try`
--> $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
|
LL | let x = || -> i32 22;
| ^^
| |
| expected `{`
| help: try placing this code inside a block: `{ 22 }`
| ^^ expected `{`
|
help: try placing this code inside a block
|
LL | let x = || -> i32 { 22 };
| + +
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
|
LL ~ fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
LL + }
|
LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { }
| + +
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
|
LL | fn p() { match s { v, E { [) {) }
| ----- while parsing this match expression
| ----- while parsing this `match` expression
LL |
LL |
| ^ expected one of `.`, `?`, `{`, or an operator

View file

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

View file

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

View file

@ -4,7 +4,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `;`
LL | match
| -----
| |
| while parsing this match expression
| while parsing this `match` expression
| help: try removing this `match`
LL | Some(4).unwrap_or(5)
| - 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`
--> $DIR/unsafe-block-without-braces.rs:3:9
|
LL | unsafe //{
| ------ while parsing this `unsafe` expression
LL | std::mem::transmute::<f32, u32>(1.0);
| ^^^----------------------------------
| |
| expected `{`
| help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
| ^^^ expected `{`
|
help: try placing this code inside a block
|
LL | { std::mem::transmute::<f32, u32>(1.0); }
| + +
error: aborting due to previous error

View file

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