提交 b4e8596e 编写于 作者: B bors

Auto merge of #88598 - estebank:type-ascription-can-die-in-a-fire, r=wesleywiser

Detect bare blocks with type ascription that were meant to be a `struct` literal

Address part of #34255.

Potential improvement: silence the other knock down errors in `issue-34255-1.rs`.
......@@ -558,6 +558,14 @@ pub struct Block {
pub rules: BlockCheckMode,
pub span: Span,
pub tokens: Option<LazyTokenStream>,
/// The following *isn't* a parse error, but will cause multiple errors in following stages.
/// ```
/// let x = {
/// foo: var
/// };
/// ```
/// #34255
pub could_be_bare_literal: bool,
}
/// A match pattern.
......
......@@ -949,7 +949,7 @@ pub fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mu
}
pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
let Block { id, stmts, rules: _, span, tokens } = block.deref_mut();
let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
vis.visit_id(id);
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
vis.visit_span(span);
......
......@@ -102,6 +102,7 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
span,
tokens: None,
could_be_bare_literal: false,
}))
}
......
......@@ -867,6 +867,7 @@ fn into_expr(self) -> P<ast::Expr> {
rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
span: self.macsp,
tokens: None,
could_be_bare_literal: false,
}));
let ident = Ident::from_str_and_span("args", self.macsp);
......
......@@ -197,6 +197,7 @@ pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
rules: BlockCheckMode::Default,
span,
tokens: None,
could_be_bare_literal: false,
})
}
......
......@@ -810,6 +810,7 @@ fn stmt_to_block(
id: resolver.next_node_id(),
span: rustc_span::DUMMY_SP,
tokens: None,
could_be_bare_literal: false,
}
}
......
......@@ -446,11 +446,13 @@ pub fn maybe_suggest_struct_literal(
)
.emit();
*self = snapshot;
Ok(self.mk_block(
let mut tail = self.mk_block(
vec![self.mk_stmt_err(expr.span)],
s,
lo.to(self.prev_token.span),
))
);
tail.could_be_bare_literal = true;
Ok(tail)
}
(Err(mut err), Ok(tail)) => {
// We have a block tail that contains a somehow valid type ascription expr.
......@@ -463,7 +465,10 @@ pub fn maybe_suggest_struct_literal(
self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
Err(err)
}
(Ok(_), Ok(tail)) => Ok(tail),
(Ok(_), Ok(mut tail)) => {
tail.could_be_bare_literal = true;
Ok(tail)
}
});
}
None
......
......@@ -574,7 +574,14 @@ pub fn parse_full_stmt(
}
pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
P(Block {
stmts,
id: DUMMY_NODE_ID,
rules,
span,
tokens: None,
could_be_bare_literal: false,
})
}
pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
......
......@@ -383,6 +383,11 @@ struct DiagnosticMetadata<'ast> {
/// Only used for better errors on `fn(): fn()`.
current_type_ascription: Vec<Span>,
/// Only used for better errors on `let x = { foo: bar };`.
/// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only
/// needed for cases where this parses as a correct type ascription.
current_block_could_be_bare_struct_literal: Option<Span>,
/// Only used for better errors on `let <pat>: <expr, not type>;`.
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
......@@ -1871,6 +1876,7 @@ fn smart_resolve_path_fragment(
let instead = res.is_some();
let suggestion =
if res.is_none() { this.report_missing_type_error(path) } else { None };
// get_from_node_id
this.r.use_injections.push(UseError {
err,
......@@ -2254,6 +2260,15 @@ fn resolve_block(&mut self, block: &'ast Block) {
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
}
let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take();
if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
(block.could_be_bare_literal, &block.stmts[..])
{
if let ExprKind::Type(..) = expr.kind {
self.diagnostic_metadata.current_block_could_be_bare_struct_literal =
Some(block.span);
}
}
// Descend into the block.
for stmt in &block.stmts {
if let StmtKind::Item(ref item) = stmt.kind {
......@@ -2267,6 +2282,7 @@ fn resolve_block(&mut self, block: &'ast Block) {
self.visit_stmt(stmt);
}
self.diagnostic_metadata.current_block_could_be_bare_struct_literal = prev;
// Move back up.
self.parent_scope.module = orig_module;
......
......@@ -207,6 +207,16 @@ pub(crate) fn smart_resolve_report_errors(
let code = source.error_code(res.is_some());
let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal {
err.multipart_suggestion(
"you might have meant to write a `struct` literal",
vec![
(span.shrink_to_lo(), "{ SomeStruct ".to_string()),
(span.shrink_to_hi(), "}".to_string()),
],
Applicability::HasPlaceholders,
);
}
match (source, self.diagnostic_metadata.in_if_condition) {
(PathSource::Expr(_), Some(Expr { span, kind: ExprKind::Assign(..), .. })) => {
err.span_suggestion_verbose(
......
......@@ -106,6 +106,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
rules: BlockCheckMode::Default,
span: DUMMY_SP,
tokens: None,
could_be_bare_literal: false,
});
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
}
......
......@@ -3,6 +3,16 @@ error[E0425]: cannot find value `input_cells` in this scope
|
LL | input_cells: Vec::new()
| ^^^^^^^^^^^ a field by this name exists in `Self`
|
help: you might have meant to write a `struct` literal
|
LL ~ pub fn new() -> Self { SomeStruct {
LL | input_cells: Vec::new()
LL |
LL |
LL |
LL ~ }}
|
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-34255-1.rs:7:27
......
......@@ -160,6 +160,7 @@ fn rewrite_closure_with_block(
.first()
.map(|attr| attr.span.to(body.span))
.unwrap_or(body.span),
could_be_bare_literal: false,
};
let block = crate::expr::rewrite_block_with_visitor(
context,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册