From 436c0e129ca535d249fbf8d61d3b9334e5cd6767 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 6 May 2022 07:15:35 +0900 Subject: [PATCH 1/2] Fix an ICE on #96738 --- compiler/rustc_typeck/src/check/method/suggest.rs | 3 +-- src/test/ui/typeck/issue-96738.rs | 3 +++ src/test/ui/typeck/issue-96738.stderr | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/typeck/issue-96738.rs create mode 100644 src/test/ui/typeck/issue-96738.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 634ba2baf9667..f36d249667314 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -367,8 +367,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.is_fn_ty(rcvr_ty, span) { if let SelfSource::MethodCall(expr) = source { - let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() { - let local_id = def_id.expect_local(); + let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() && let Some(local_id) = def_id.as_local() { let hir_id = tcx.hir().local_def_id_to_hir_id(local_id); let node = tcx.hir().get(hir_id); let fields = node.tuple_fields(); diff --git a/src/test/ui/typeck/issue-96738.rs b/src/test/ui/typeck/issue-96738.rs new file mode 100644 index 0000000000000..7f1d1428eb9b4 --- /dev/null +++ b/src/test/ui/typeck/issue-96738.rs @@ -0,0 +1,3 @@ +fn main() { + Some.nonexistent_method(); //~ ERROR: no method named `nonexistent_method` found +} diff --git a/src/test/ui/typeck/issue-96738.stderr b/src/test/ui/typeck/issue-96738.stderr new file mode 100644 index 0000000000000..6f9bffbb790c5 --- /dev/null +++ b/src/test/ui/typeck/issue-96738.stderr @@ -0,0 +1,11 @@ +error[E0599]: no method named `nonexistent_method` found for fn item `fn(_) -> Option<_> {Option::<_>::Some}` in the current scope + --> $DIR/issue-96738.rs:2:10 + | +LL | Some.nonexistent_method(); + | ---- ^^^^^^^^^^^^^^^^^^ method not found in `fn(_) -> Option<_> {Option::<_>::Some}` + | | + | this is a function, perhaps you wish to call it + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 35d77c17101852d17ebd27434c09b3652689e5c6 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 May 2022 00:43:50 +0900 Subject: [PATCH 2/2] Also suggest calling constructors for external DefIds --- .../rustc_typeck/src/check/method/suggest.rs | 30 ++++++++++++------- src/test/ui/typeck/issue-96738.stderr | 7 ++++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index f36d249667314..294a42a114804 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -367,16 +367,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.is_fn_ty(rcvr_ty, span) { if let SelfSource::MethodCall(expr) = source { - let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() && let Some(local_id) = def_id.as_local() { - let hir_id = tcx.hir().local_def_id_to_hir_id(local_id); - let node = tcx.hir().get(hir_id); - let fields = node.tuple_fields(); - - if let Some(fields) = fields - && let Some(DefKind::Ctor(of, _)) = self.tcx.opt_def_kind(local_id) { - Some((fields, of)) + let suggest = if let ty::FnDef(def_id, _) = rcvr_ty.kind() { + if let Some(local_id) = def_id.as_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(local_id); + let node = tcx.hir().get(hir_id); + let fields = node.tuple_fields(); + if let Some(fields) = fields + && let Some(DefKind::Ctor(of, _)) = self.tcx.opt_def_kind(local_id) { + Some((fields.len(), of)) + } else { + None + } } else { - None + // The logic here isn't smart but `associated_item_def_ids` + // doesn't work nicely on local. + if let DefKind::Ctor(of, _) = tcx.def_kind(def_id) { + let parent_def_id = tcx.parent(*def_id); + Some((tcx.associated_item_def_ids(parent_def_id).len(), of)) + } else { + None + } } } else { None @@ -384,7 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the function is a tuple constructor, we recommend that they call it if let Some((fields, kind)) = suggest { - suggest_call_constructor(expr.span, kind, fields.len(), &mut err); + suggest_call_constructor(expr.span, kind, fields, &mut err); } else { // General case err.span_label( diff --git a/src/test/ui/typeck/issue-96738.stderr b/src/test/ui/typeck/issue-96738.stderr index 6f9bffbb790c5..58c83a36a3bdc 100644 --- a/src/test/ui/typeck/issue-96738.stderr +++ b/src/test/ui/typeck/issue-96738.stderr @@ -4,7 +4,12 @@ error[E0599]: no method named `nonexistent_method` found for fn item `fn(_) -> O LL | Some.nonexistent_method(); | ---- ^^^^^^^^^^^^^^^^^^ method not found in `fn(_) -> Option<_> {Option::<_>::Some}` | | - | this is a function, perhaps you wish to call it + | this is the constructor of an enum variant + | +help: call the constructor + | +LL | (Some)(_).nonexistent_method(); + | + ++++ error: aborting due to previous error