Skip to content

Commit

Permalink
Auto merge of rust-lang#94453 - matthiaskrgr:rollup-xv9y98j, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 6 pull requests

Successful merges:

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

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Feb 28, 2022
2 parents 97cde9f + 34657cc commit 4ce3749
Show file tree
Hide file tree
Showing 47 changed files with 591 additions and 321 deletions.
13 changes: 12 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
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())
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ E0720: include_str!("./error_codes/E0720.md"),
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"),
Expand Down Expand Up @@ -641,6 +642,5 @@ E0787: include_str!("./error_codes/E0787.md"),
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" { ... }`.
}
46 changes: 46 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0726.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_data_structures::sync::Lrc;
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};
Expand Down Expand Up @@ -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
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_parse/src/lexer/tokentrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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"]

Expand Down
131 changes: 78 additions & 53 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -732,43 +732,42 @@ impl<'a> Parser<'a> {
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)
Expand All @@ -784,12 +783,13 @@ impl<'a> Parser<'a> {
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(
Expand Down Expand Up @@ -2245,12 +2245,32 @@ impl<'a> Parser<'a> {
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(());
Expand All @@ -2270,20 +2290,25 @@ impl<'a> Parser<'a> {
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)
}
Expand Down
Loading

0 comments on commit 4ce3749

Please sign in to comment.