about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-07-11 16:23:03 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-07-18 18:20:35 +0000
commitec7a188f16a6ec1f2e29f5d721f8ee5b92e2c99f (patch)
treeb3d1b81b7218790072486cdd8407b860ad809055 /compiler/rustc_hir_analysis/src
parent2259db6af0d20dbc3496ec566bf37456d2ca7b36 (diff)
downloadrust-ec7a188f16a6ec1f2e29f5d721f8ee5b92e2c99f.tar.gz
rust-ec7a188f16a6ec1f2e29f5d721f8ee5b92e2c99f.zip
More accurate suggestions when writing wrong style of enum variant literal
```
error[E0533]: expected value, found struct variant `E::Empty3`
  --> $DIR/empty-struct-braces-expr.rs:18:14
   |
LL |     let e3 = E::Empty3;
   |              ^^^^^^^^^ not a value
   |
help: you might have meant to create a new value of the struct
   |
LL |     let e3 = E::Empty3 {};
   |                        ++
```
```
error[E0533]: expected value, found struct variant `E::V`
  --> $DIR/struct-literal-variant-in-if.rs:10:13
   |
LL |     if x == E::V { field } {}
   |             ^^^^ not a value
   |
help: you might have meant to create a new value of the struct
   |
LL |     if x == (E::V { field }) {}
   |             +              +
```
```
error[E0618]: expected function, found enum variant `Enum::Unit`
  --> $DIR/suggestion-highlights.rs:15:5
   |
LL |     Unit,
   |     ---- enum variant `Enum::Unit` defined here
...
LL |     Enum::Unit();
   |     ^^^^^^^^^^--
   |     |
   |     call expression requires function
   |
help: `Enum::Unit` is a unit enum variant, and does not take parentheses to be constructed
   |
LL -     Enum::Unit();
LL +     Enum::Unit;
   |
```
```
error[E0599]: no variant or associated item named `tuple` found for enum `Enum` in the current scope
  --> $DIR/suggestion-highlights.rs:36:11
   |
LL | enum Enum {
   | --------- variant or associated item `tuple` not found for this enum
...
LL |     Enum::tuple;
   |           ^^^^^ variant or associated item not found in `Enum`
   |
help: there is a variant with a similar name
   |
LL |     Enum::Tuple(/* i32 */);
   |           ~~~~~~~~~~~~~~~~;
   |
```
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs66
1 files changed, 60 insertions, 6 deletions
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a665306f2c6..44a46951459 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1087,7 +1087,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     );
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
-                    if let Some(suggested_name) = find_best_match_for_name(
+                    if let Some(variant_name) = find_best_match_for_name(
                         &adt_def
                             .variants()
                             .iter()
@@ -1095,12 +1095,66 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             .collect::<Vec<Symbol>>(),
                         assoc_ident.name,
                         None,
-                    ) {
-                        err.span_suggestion(
-                            assoc_ident.span,
+                    ) && let Some(variant) =
+                        adt_def.variants().iter().find(|s| s.name == variant_name)
+                    {
+                        let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())];
+                        if let hir::Node::Stmt(hir::Stmt {
+                            kind: hir::StmtKind::Semi(ref expr),
+                            ..
+                        })
+                        | hir::Node::Expr(ref expr) = tcx.parent_hir_node(hir_ref_id)
+                            && let hir::ExprKind::Struct(..) = expr.kind
+                        {
+                            match variant.ctor {
+                                None => {
+                                    // struct
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        if variant.fields.is_empty() {
+                                            format!("{variant_name} {{}}")
+                                        } else {
+                                            format!(
+                                                "{variant_name} {{ {} }}",
+                                                variant
+                                                    .fields
+                                                    .iter()
+                                                    .map(|f| format!("{}: /* value */", f.name))
+                                                    .collect::<Vec<_>>()
+                                                    .join(", ")
+                                            )
+                                        },
+                                    )];
+                                }
+                                Some((hir::def::CtorKind::Fn, def_id)) => {
+                                    // tuple
+                                    let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
+                                    let inputs = fn_sig.inputs().skip_binder();
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        format!(
+                                            "{variant_name}({})",
+                                            inputs
+                                                .iter()
+                                                .map(|i| format!("/* {i} */"))
+                                                .collect::<Vec<_>>()
+                                                .join(", ")
+                                        ),
+                                    )];
+                                }
+                                Some((hir::def::CtorKind::Const, _)) => {
+                                    // unit
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        variant_name.to_string(),
+                                    )];
+                                }
+                            }
+                        }
+                        err.multipart_suggestion_verbose(
                             "there is a variant with a similar name",
-                            suggested_name,
-                            Applicability::MaybeIncorrect,
+                            suggestion,
+                            Applicability::HasPlaceholders,
                         );
                     } else {
                         err.span_label(