Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,9 +743,12 @@ pub(crate) struct DiagMetadata<'ast> {
/// they are used (in a `break` or `continue` statement)
unused_labels: FxIndexMap<NodeId, Span>,

/// Only used for better errors on `let <pat>: <expr, not type>;`.
/// Used for better errors on `let <pat>: <expr, not type>;`.
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,

/// Only used for better errors on `let <pat> = val{}` when the user forget `else`.
struct_field_parse_failed: bool,

current_pat: Option<&'ast Pat>,

/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
Expand Down Expand Up @@ -4593,6 +4596,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
| PathSource::PreciseCapturingArg(..) = source
{
this.suggest_adding_generic_parameter(path, source)
} else if let Some(Res::Local(_)) = &res
&& this.diag_metadata.struct_field_parse_failed
&& this.diag_metadata.current_let_binding.is_some()
{
let span = path[0].ident.span.shrink_to_hi();
(
Some((
span,
"try adding `else` here:",
" else ".to_string(),
Applicability::MaybeIncorrect,
)),
None,
)
} else {
(None, None)
};
Expand Down Expand Up @@ -5192,7 +5209,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}

ExprKind::Struct(ref se) => {
if let StructRest::NoneWithError(_) = &se.rest
&& se.fields.is_empty()
{
self.diag_metadata.struct_field_parse_failed = true;
}
self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct(parent));
self.diag_metadata.struct_field_parse_failed = false;
// This is the same as `visit::walk_expr(self, expr);`, but we want to pass the
// parent in for accurate suggestions when encountering `Foo { bar }` that should
// have been `Foo { bar: self.bar }`.
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/resolve/detect-missing-else-in-let.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// detect missing else in let statement. (issue #135857)
fn main() {
let foo = Some(1);
let Some(a) = foo{return;}; //~ ERROR E0574
//~| HELP try adding `else` here:
//~| HELP escape `return` to use it as an identifier
//~| ERROR expected identifier, found keyword `return`
let Some(b) = foo{todo!()}; //~ ERROR E0574
//~| HELP try adding `else` here:
//~| ERROR expected one of `,`, `:`, or `}`, found `!`
}
47 changes: 47 additions & 0 deletions tests/ui/resolve/detect-missing-else-in-let.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error: expected identifier, found keyword `return`
--> $DIR/detect-missing-else-in-let.rs:4:23
|
LL | let Some(a) = foo{return;};
| --- ^^^^^^ expected identifier, found keyword
| |
| while parsing this struct
|
help: escape `return` to use it as an identifier
|
LL | let Some(a) = foo{r#return;};
| ++

error: expected one of `,`, `:`, or `}`, found `!`
--> $DIR/detect-missing-else-in-let.rs:8:27
|
LL | let Some(b) = foo{todo!()};
| --- ----^ expected one of `,`, `:`, or `}`
| | |
| | while parsing this struct field
| while parsing this struct

error[E0574]: expected struct, variant or union type, found local variable `foo`
--> $DIR/detect-missing-else-in-let.rs:4:19
|
LL | let Some(a) = foo{return;};
| ^^^ not a struct, variant or union type
|
help: try adding `else` here:
|
LL | let Some(a) = foo else {return;};
| ++++

error[E0574]: expected struct, variant or union type, found local variable `foo`
--> $DIR/detect-missing-else-in-let.rs:8:19
|
LL | let Some(b) = foo{todo!()};
| ^^^ not a struct, variant or union type
|
help: try adding `else` here:
|
LL | let Some(b) = foo else {todo!()};
| ++++

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0574`.
Loading