From 4946c868b029e010593c3a3d916c3bc3e87e15ac Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Tue, 26 May 2026 14:21:18 +0000 Subject: [PATCH] fix issue-156949 --- compiler/rustc_resolve/src/late.rs | 25 +++++++++- .../ui/resolve/detect-missing-else-in-let.rs | 11 +++++ .../resolve/detect-missing-else-in-let.stderr | 47 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/ui/resolve/detect-missing-else-in-let.rs create mode 100644 tests/ui/resolve/detect-missing-else-in-let.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fb8de90d28aca..ec7e7ca8ac30a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -743,9 +743,12 @@ pub(crate) struct DiagMetadata<'ast> { /// they are used (in a `break` or `continue` statement) unused_labels: FxIndexMap, - /// Only used for better errors on `let : ;`. + /// Used for better errors on `let : ;`. current_let_binding: Option<(Span, Option, Option)>, + /// Only used for better errors on `let = 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. @@ -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) }; @@ -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 }`. diff --git a/tests/ui/resolve/detect-missing-else-in-let.rs b/tests/ui/resolve/detect-missing-else-in-let.rs new file mode 100644 index 0000000000000..c7472f5e4dffd --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let.rs @@ -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 `!` +} diff --git a/tests/ui/resolve/detect-missing-else-in-let.stderr b/tests/ui/resolve/detect-missing-else-in-let.stderr new file mode 100644 index 0000000000000..48ea7cf96a824 --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let.stderr @@ -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`.