mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 19:17:43 +00:00
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:
commit
4ce3749235
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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" { ... }`.
|
||||||
}
|
}
|
||||||
|
46
compiler/rustc_error_codes/src/error_codes/E0726.md
Normal file
46
compiler/rustc_error_codes/src/error_codes/E0726.md
Normal 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
|
@ -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
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"]
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()?;
|
||||||
|
@ -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![];
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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!(),
|
||||||
})?)
|
})?)
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
|
@ -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();
|
||||||
}
|
})
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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]) {
|
||||||
|
@ -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`.
|
||||||
|
@ -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
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
// check-pass
|
|
||||||
#![feature(allocator_api)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
Box::new_in((), &std::alloc::Global);
|
|
||||||
}
|
|
23
src/test/ui/box/large-allocator-ice.rs
Normal file
23
src/test/ui/box/large-allocator-ice.rs
Normal 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]));
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
@ -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`.
|
||||||
|
@ -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`.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
30
src/test/ui/label/label_break_value_illegal_uses.fixed
Normal file
30
src/test/ui/label/label_break_value_illegal_uses.fixed
Normal 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();
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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 ~ } };
|
||||||
|
|
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
13
src/test/ui/parser/while-if-let-without-body.rs
Normal file
13
src/test/ui/parser/while-if-let-without-body.rs
Normal 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 `{`
|
18
src/test/ui/parser/while-if-let-without-body.stderr
Normal file
18
src/test/ui/parser/while-if-let-without-body.stderr
Normal 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
|
||||||
|
|
4
src/test/ui/typeck/while-loop-block-cond.rs
Normal file
4
src/test/ui/typeck/while-loop-block-cond.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() {
|
||||||
|
while {} {}
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
}
|
9
src/test/ui/typeck/while-loop-block-cond.stderr
Normal file
9
src/test/ui/typeck/while-loop-block-cond.stderr
Normal 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`.
|
@ -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
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
Loading…
Reference in New Issue
Block a user