Skip to content

Commit 34cefbe

Browse files
committed
Differentiate between tuple structs and tuple variants
1 parent cd0f785 commit 34cefbe

File tree

5 files changed

+62
-22
lines changed

5 files changed

+62
-22
lines changed

src/librustc/hir/map/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'hir> Map<'hir> {
287287
self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
288288
}
289289

290-
fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
290+
pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
291291
let node = if let Some(node) = self.find(hir_id) {
292292
node
293293
} else {

src/librustc_typeck/check/mod.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,6 +3839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38393839
ty::FnDef(..) | ty::FnPtr(_) => {}
38403840
_ => return false,
38413841
}
3842+
let hir = self.tcx.hir();
38423843

38433844
let sig = found.fn_sig(self.tcx);
38443845
let sig = self
@@ -3849,25 +3850,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38493850
let (mut sugg_call, applicability) = if sig.inputs().is_empty() {
38503851
(String::new(), Applicability::MachineApplicable)
38513852
} else {
3852-
("...".to_owned(), Applicability::HasPlaceholders)
3853+
("...".to_string(), Applicability::HasPlaceholders)
38533854
};
38543855
let mut msg = "call this function";
38553856
if let ty::FnDef(def_id, ..) = found.sty {
3856-
match self.tcx.hir().get_if_local(def_id) {
3857+
match hir.get_if_local(def_id) {
38573858
Some(Node::Item(hir::Item {
38583859
node: ItemKind::Fn(.., body_id),
38593860
..
38603861
})) => {
3861-
let body = self.tcx.hir().body(*body_id);
3862+
let body = hir.body(*body_id);
38623863
sugg_call = body.arguments.iter()
3863-
.map(|arg| hir::print::to_string(
3864-
hir::print::NO_ANN,
3865-
|s| s.print_pat(&arg.pat),
3866-
)).collect::<Vec<_>>().join(", ");
3864+
.map(|arg| match &arg.pat.node {
3865+
hir::PatKind::Binding(_, _, ident, None) => ident.to_string(),
3866+
_ => "_".to_string(),
3867+
}).collect::<Vec<_>>().join(", ");
38673868
}
3868-
Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => {
3869-
sugg_call = field.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
3870-
msg = "instatiate this tuple struct";
3869+
Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
3870+
sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
3871+
match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) {
3872+
Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
3873+
msg = "instatiate this tuple variant";
3874+
}
3875+
Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => {
3876+
msg = "instatiate this tuple struct";
3877+
}
3878+
_ => {}
3879+
}
38713880
}
38723881
_ => {}
38733882
}

src/test/ui/resolve/privacy-enum-ctor.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn;
202202
| ^^^^^
203203
| |
204204
| expected enum `m::n::Z`, found fn item
205-
| help: use parentheses to instatiate this tuple struct: `Z::Fn(_)`
205+
| help: use parentheses to instatiate this tuple variant: `Z::Fn(_)`
206206
|
207207
= note: expected type `m::n::Z`
208208
found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
@@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn;
232232
| ^^^^^^^^
233233
| |
234234
| expected enum `m::E`, found fn item
235-
| help: use parentheses to instatiate this tuple struct: `m::E::Fn(_)`
235+
| help: use parentheses to instatiate this tuple variant: `m::E::Fn(_)`
236236
|
237237
= note: expected type `m::E`
238238
found type `fn(u8) -> m::E {m::E::Fn}`
@@ -262,7 +262,7 @@ LL | let _: E = E::Fn;
262262
| ^^^^^
263263
| |
264264
| expected enum `m::E`, found fn item
265-
| help: use parentheses to instatiate this tuple struct: `E::Fn(_)`
265+
| help: use parentheses to instatiate this tuple variant: `E::Fn(_)`
266266
|
267267
= note: expected type `m::E`
268268
found type `fn(u8) -> m::E {m::E::Fn}`

src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ fn foo(a: usize, b: usize) -> usize { a }
33
fn bar() -> usize { 42 }
44

55
struct S(usize, usize);
6+
enum E {
7+
A(usize),
8+
B { a: usize },
9+
}
610
struct V();
711

812
trait T {
@@ -17,4 +21,6 @@ fn main() {
1721
let _: V = V; //~ ERROR mismatched types
1822
let _: usize = T::baz; //~ ERROR mismatched types
1923
let _: usize = T::bat; //~ ERROR mismatched types
24+
let _: E = E::A; //~ ERROR mismatched types
25+
let _: E = E::B; //~ ERROR expected value, found struct variant `E::B`
2026
}

src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
error[E0423]: expected value, found struct variant `E::B`
2+
--> $DIR/fn-or-tuple-struct-without-args.rs:25:16
3+
|
4+
LL | let _: E = E::B;
5+
| ^^^-
6+
| | |
7+
| | help: a tuple variant with a similar name exists: `A`
8+
| did you mean `E::B { /* fields */ }`?
9+
110
error[E0308]: mismatched types
2-
--> $DIR/fn-or-tuple-struct-without-args.rs:14:20
11+
--> $DIR/fn-or-tuple-struct-without-args.rs:18:20
312
|
413
LL | fn foo(a: usize, b: usize) -> usize { a }
514
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here
@@ -14,7 +23,7 @@ LL | let _: usize = foo;
1423
found type `fn(usize, usize) -> usize {foo}`
1524

1625
error[E0308]: mismatched types
17-
--> $DIR/fn-or-tuple-struct-without-args.rs:15:16
26+
--> $DIR/fn-or-tuple-struct-without-args.rs:19:16
1827
|
1928
LL | struct S(usize, usize);
2029
| ----------------------- fn(usize, usize) -> S {S} defined here
@@ -29,7 +38,7 @@ LL | let _: S = S;
2938
found type `fn(usize, usize) -> S {S}`
3039

3140
error[E0308]: mismatched types
32-
--> $DIR/fn-or-tuple-struct-without-args.rs:16:20
41+
--> $DIR/fn-or-tuple-struct-without-args.rs:20:20
3342
|
3443
LL | fn bar() -> usize { 42 }
3544
| ----------------- fn() -> usize {bar} defined here
@@ -44,7 +53,7 @@ LL | let _: usize = bar;
4453
found type `fn() -> usize {bar}`
4554

4655
error[E0308]: mismatched types
47-
--> $DIR/fn-or-tuple-struct-without-args.rs:17:16
56+
--> $DIR/fn-or-tuple-struct-without-args.rs:21:16
4857
|
4958
LL | struct V();
5059
| ----------- fn() -> V {V} defined here
@@ -59,7 +68,7 @@ LL | let _: V = V;
5968
found type `fn() -> V {V}`
6069

6170
error[E0308]: mismatched types
62-
--> $DIR/fn-or-tuple-struct-without-args.rs:18:20
71+
--> $DIR/fn-or-tuple-struct-without-args.rs:22:20
6372
|
6473
LL | fn baz(x: usize, y: usize) -> usize { x }
6574
| ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here
@@ -74,7 +83,7 @@ LL | let _: usize = T::baz;
7483
found type `fn(usize, usize) -> usize {<_ as T>::baz}`
7584

7685
error[E0308]: mismatched types
77-
--> $DIR/fn-or-tuple-struct-without-args.rs:19:20
86+
--> $DIR/fn-or-tuple-struct-without-args.rs:23:20
7887
|
7988
LL | fn bat() -> usize { 42 }
8089
| ----------------- fn() -> usize {<_ as T>::bat} defined here
@@ -88,6 +97,22 @@ LL | let _: usize = T::bat;
8897
= note: expected type `usize`
8998
found type `fn() -> usize {<_ as T>::bat}`
9099

91-
error: aborting due to 6 previous errors
100+
error[E0308]: mismatched types
101+
--> $DIR/fn-or-tuple-struct-without-args.rs:24:16
102+
|
103+
LL | A(usize),
104+
| -------- fn(usize) -> E {E::A} defined here
105+
...
106+
LL | let _: E = E::A;
107+
| ^^^^
108+
| |
109+
| expected enum `E`, found fn item
110+
| help: use parentheses to instatiate this tuple variant: `E::A(_)`
111+
|
112+
= note: expected type `E`
113+
found type `fn(usize) -> E {E::A}`
114+
115+
error: aborting due to 8 previous errors
92116

93-
For more information about this error, try `rustc --explain E0308`.
117+
Some errors have detailed explanations: E0308, E0423.
118+
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)