From 52da091ee687f3d065713626a10b4cc961f04f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2019 14:59:24 -0700 Subject: [PATCH] Differentiate between tuple structs and tuple variants --- src/librustc/hir/map/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 29 ++++++++----- src/test/ui/resolve/privacy-enum-ctor.stderr | 6 +-- .../fn-or-tuple-struct-without-args.rs | 6 +++ .../fn-or-tuple-struct-without-args.stderr | 41 +++++++++++++++---- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 0d477ae7968..b85738dd29a 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -287,7 +287,7 @@ impl<'hir> Map<'hir> { self.definitions.def_index_to_hir_id(def_id.to_def_id().index) } - fn def_kind(&self, hir_id: HirId) -> Option { + pub fn def_kind(&self, hir_id: HirId) -> Option { let node = if let Some(node) = self.find(hir_id) { node } else { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 726922c8e53..629b8da355e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3839,6 +3839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::FnDef(..) | ty::FnPtr(_) => {} _ => return false, } + let hir = self.tcx.hir(); let sig = found.fn_sig(self.tcx); let sig = self @@ -3849,25 +3850,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (mut sugg_call, applicability) = if sig.inputs().is_empty() { (String::new(), Applicability::MachineApplicable) } else { - ("...".to_owned(), Applicability::HasPlaceholders) + ("...".to_string(), Applicability::HasPlaceholders) }; let mut msg = "call this function"; if let ty::FnDef(def_id, ..) = found.sty { - match self.tcx.hir().get_if_local(def_id) { + match hir.get_if_local(def_id) { Some(Node::Item(hir::Item { node: ItemKind::Fn(.., body_id), .. })) => { - let body = self.tcx.hir().body(*body_id); + let body = hir.body(*body_id); sugg_call = body.arguments.iter() - .map(|arg| hir::print::to_string( - hir::print::NO_ANN, - |s| s.print_pat(&arg.pat), - )).collect::>().join(", "); + .map(|arg| match &arg.pat.node { + hir::PatKind::Binding(_, _, ident, None) => ident.to_string(), + _ => "_".to_string(), + }).collect::>().join(", "); } - Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => { - sugg_call = field.iter().map(|_| "_").collect::>().join(", "); - msg = "instatiate this tuple struct"; + Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { + sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); + match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) { + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { + msg = "instatiate this tuple variant"; + } + Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => { + msg = "instatiate this tuple struct"; + } + _ => {} + } } _ => {} } diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 49092562fee..3e924f7d161 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn; | ^^^^^ | | | expected enum `m::n::Z`, found fn item - | help: use parentheses to instatiate this tuple struct: `Z::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `Z::Fn(_)` | = note: expected type `m::n::Z` found type `fn(u8) -> m::n::Z {m::n::Z::Fn}` @@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn; | ^^^^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple struct: `m::E::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `m::E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` @@ -262,7 +262,7 @@ LL | let _: E = E::Fn; | ^^^^^ | | | expected enum `m::E`, found fn item - | help: use parentheses to instatiate this tuple struct: `E::Fn(_)` + | help: use parentheses to instatiate this tuple variant: `E::Fn(_)` | = note: expected type `m::E` found type `fn(u8) -> m::E {m::E::Fn}` diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs index 6758c1d5f23..838ef78e4fd 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -3,6 +3,10 @@ fn foo(a: usize, b: usize) -> usize { a } fn bar() -> usize { 42 } struct S(usize, usize); +enum E { + A(usize), + B { a: usize }, +} struct V(); trait T { @@ -17,4 +21,6 @@ fn main() { let _: V = V; //~ ERROR mismatched types let _: usize = T::baz; //~ ERROR mismatched types let _: usize = T::bat; //~ ERROR mismatched types + let _: E = E::A; //~ ERROR mismatched types + let _: E = E::B; //~ ERROR expected value, found struct variant `E::B` } diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 524c779979e..cb128822fcc 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -1,5 +1,14 @@ +error[E0423]: expected value, found struct variant `E::B` + --> $DIR/fn-or-tuple-struct-without-args.rs:25:16 + | +LL | let _: E = E::B; + | ^^^- + | | | + | | help: a tuple variant with a similar name exists: `A` + | did you mean `E::B { /* fields */ }`? + error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:14:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 | LL | fn foo(a: usize, b: usize) -> usize { a } | ----------------------------------- fn(usize, usize) -> usize {foo} defined here @@ -14,7 +23,7 @@ LL | let _: usize = foo; found type `fn(usize, usize) -> usize {foo}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:15:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:19:16 | LL | struct S(usize, usize); | ----------------------- fn(usize, usize) -> S {S} defined here @@ -29,7 +38,7 @@ LL | let _: S = S; found type `fn(usize, usize) -> S {S}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:16:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:20:20 | LL | fn bar() -> usize { 42 } | ----------------- fn() -> usize {bar} defined here @@ -44,7 +53,7 @@ LL | let _: usize = bar; found type `fn() -> usize {bar}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:17:16 + --> $DIR/fn-or-tuple-struct-without-args.rs:21:16 | LL | struct V(); | ----------- fn() -> V {V} defined here @@ -59,7 +68,7 @@ LL | let _: V = V; found type `fn() -> V {V}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:18:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:22:20 | LL | fn baz(x: usize, y: usize) -> usize { x } | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here @@ -74,7 +83,7 @@ LL | let _: usize = T::baz; found type `fn(usize, usize) -> usize {<_ as T>::baz}` error[E0308]: mismatched types - --> $DIR/fn-or-tuple-struct-without-args.rs:19:20 + --> $DIR/fn-or-tuple-struct-without-args.rs:23:20 | LL | fn bat() -> usize { 42 } | ----------------- fn() -> usize {<_ as T>::bat} defined here @@ -88,6 +97,22 @@ LL | let _: usize = T::bat; = note: expected type `usize` found type `fn() -> usize {<_ as T>::bat}` -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:24:16 + | +LL | A(usize), + | -------- fn(usize) -> E {E::A} defined here +... +LL | let _: E = E::A; + | ^^^^ + | | + | expected enum `E`, found fn item + | help: use parentheses to instatiate this tuple variant: `E::A(_)` + | + = note: expected type `E` + found type `fn(usize) -> E {E::A}` -For more information about this error, try `rustc --explain E0308`. +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0423. +For more information about an error, try `rustc --explain E0308`.