about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBadel2 <2badel2@gmail.com>2022-05-08 19:57:47 +0200
committerBadel2 <2badel2@gmail.com>2022-05-08 19:57:47 +0200
commit84adf0d8dd5fa68050ef0f3684ab701f5fc5a4cf (patch)
treed1229ae506a0b95454154d0a240b9d307a6db009
parented3164baf010592dda34da57c28fa8ae5e6c2ca6 (diff)
downloadrust-84adf0d8dd5fa68050ef0f3684ab701f5fc5a4cf.tar.gz
rust-84adf0d8dd5fa68050ef0f3684ab701f5fc5a4cf.zip
Actually fix ICE from #96583
PR #96746 fixed a very similar bug, so the same logic is used in a
different place.
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs31
-rw-r--r--src/test/ui/typeck/issue-96738.rs1
-rw-r--r--src/test/ui/typeck/issue-96738.stderr18
3 files changed, 37 insertions, 13 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index a1e8d2040dd..f3a5b9f13dd 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -44,7 +44,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeFoldable};
 use rustc_session::parse::feature_err;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -2034,17 +2034,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base: &'tcx hir::Expr<'tcx>,
         def_id: DefId,
     ) {
-        let local_id = def_id.expect_local();
-        let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_id);
-        let node = self.tcx.hir().get(hir_id);
-
-        if let Some(fields) = node.tuple_fields() {
-            let kind = match self.tcx.opt_def_kind(local_id) {
-                Some(DefKind::Ctor(of, _)) => of,
-                _ => return,
-            };
+        if let Some(local_id) = def_id.as_local() {
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_id);
+            let node = self.tcx.hir().get(hir_id);
+
+            if let Some(fields) = node.tuple_fields() {
+                let kind = match self.tcx.opt_def_kind(local_id) {
+                    Some(DefKind::Ctor(of, _)) => of,
+                    _ => return,
+                };
 
-            suggest_call_constructor(base.span, kind, fields.len(), err);
+                suggest_call_constructor(base.span, kind, fields.len(), err);
+            }
+        } else {
+            // The logic here isn't smart but `associated_item_def_ids`
+            // doesn't work nicely on local.
+            if let DefKind::Ctor(of, _) = self.tcx.def_kind(def_id) {
+                let parent_def_id = self.tcx.parent(def_id);
+                let fields = self.tcx.associated_item_def_ids(parent_def_id);
+                suggest_call_constructor(base.span, of, fields.len(), err);
+            }
         }
     }
 
diff --git a/src/test/ui/typeck/issue-96738.rs b/src/test/ui/typeck/issue-96738.rs
index 7f1d1428eb9..ce2556f869c 100644
--- a/src/test/ui/typeck/issue-96738.rs
+++ b/src/test/ui/typeck/issue-96738.rs
@@ -1,3 +1,4 @@
 fn main() {
     Some.nonexistent_method(); //~ ERROR: no method named `nonexistent_method` found
+    Some.nonexistent_field; //~ ERROR: no field `nonexistent_field`
 }
diff --git a/src/test/ui/typeck/issue-96738.stderr b/src/test/ui/typeck/issue-96738.stderr
index 58c83a36a3b..32f53849848 100644
--- a/src/test/ui/typeck/issue-96738.stderr
+++ b/src/test/ui/typeck/issue-96738.stderr
@@ -11,6 +11,20 @@ help: call the constructor
 LL |     (Some)(_).nonexistent_method();
    |     +    ++++
 
-error: aborting due to previous error
+error[E0609]: no field `nonexistent_field` on type `fn(_) -> Option<_> {Option::<_>::Some}`
+  --> $DIR/issue-96738.rs:3:10
+   |
+LL |     Some.nonexistent_field;
+   |     ---- ^^^^^^^^^^^^^^^^^
+   |     |
+   |     this is the constructor of an enum variant
+   |
+help: call the constructor
+   |
+LL |     (Some)(_).nonexistent_field;
+   |     +    ++++
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0609.
+For more information about an error, try `rustc --explain E0599`.