Skip to content

Commit d711394

Browse files
Rollup merge of #106524 - compiler-errors:constructor-note, r=cjgillot
Label `struct/enum constructor` instead of `fn item`, mention that it should be called on type mismatch Fixes #106516
2 parents 54f6fea + d375440 commit d711394

14 files changed

+78
-60
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
55
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
66
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
77
use rustc_hir as hir;
8-
use rustc_hir::def::{CtorOf, DefKind};
8+
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
99
use rustc_hir::lang_items::LangItem;
1010
use rustc_hir::{
1111
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
@@ -417,10 +417,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
417417
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
418418
return true;
419419
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
420-
&& let ty::FnDef(def_id, ..) = &found.kind()
421-
&& let Some(sp) = self.tcx.hir().span_if_local(*def_id)
420+
&& let ty::FnDef(def_id, ..) = *found.kind()
421+
&& let Some(sp) = self.tcx.hir().span_if_local(def_id)
422422
{
423-
err.span_label(sp, format!("{found} defined here"));
423+
let name = self.tcx.item_name(def_id);
424+
let kind = self.tcx.def_kind(def_id);
425+
if let DefKind::Ctor(of, CtorKind::Fn) = kind {
426+
err.span_label(sp, format!("`{name}` defines {} constructor here, which should be called", match of {
427+
CtorOf::Struct => "a struct",
428+
CtorOf::Variant => "an enum variant",
429+
}));
430+
} else {
431+
let descr = kind.descr(def_id);
432+
err.span_label(sp, format!("{descr} `{name}` defined here"));
433+
}
424434
return true;
425435
} else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
426436
return true;

compiler/rustc_middle/src/ty/error.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
22
use crate::ty::diagnostics::suggest_constraining_type_param;
33
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
44
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
5-
use hir::def::DefKind;
65
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
76
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
87
use rustc_hir as hir;
8+
use rustc_hir::def::{CtorOf, DefKind};
99
use rustc_hir::def_id::DefId;
1010
use rustc_span::symbol::{sym, Symbol};
1111
use rustc_span::{BytePos, Span};
@@ -319,7 +319,11 @@ impl<'tcx> Ty<'tcx> {
319319
.into()
320320
}
321321
}
322-
ty::FnDef(..) => "fn item".into(),
322+
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
323+
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
324+
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
325+
_ => "fn item".into(),
326+
},
323327
ty::FnPtr(_) => "fn pointer".into(),
324328
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
325329
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
@@ -366,7 +370,11 @@ impl<'tcx> Ty<'tcx> {
366370
_ => "reference",
367371
}
368372
.into(),
369-
ty::FnDef(..) => "fn item".into(),
373+
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
374+
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
375+
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
376+
_ => "fn item".into(),
377+
},
370378
ty::FnPtr(_) => "fn pointer".into(),
371379
ty::Dynamic(..) => "trait object".into(),
372380
ty::Closure(..) => "closure".into(),

tests/ui/associated-types/substs-ppaux.normal.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
22
--> $DIR/substs-ppaux.rs:16:17
33
|
44
LL | fn bar<'a, T>() where T: 'a {}
5-
| --------------------------- fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>} defined here
5+
| --------------------------- associated function `bar` defined here
66
...
77
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
88
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
2020
--> $DIR/substs-ppaux.rs:25:17
2121
|
2222
LL | fn bar<'a, T>() where T: 'a {}
23-
| --------------------------- fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>} defined here
23+
| --------------------------- associated function `bar` defined here
2424
...
2525
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
2626
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
3838
--> $DIR/substs-ppaux.rs:33:17
3939
|
4040
LL | fn baz() {}
41-
| -------- fn() {<i8 as Foo<'static, 'static, u8>>::baz} defined here
41+
| -------- associated function `baz` defined here
4242
...
4343
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
4444
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
5656
--> $DIR/substs-ppaux.rs:41:17
5757
|
5858
LL | fn foo<'z>() where &'z (): Sized {
59-
| -------------------------------- fn() {foo::<'static>} defined here
59+
| -------------------------------- function `foo` defined here
6060
...
6161
LL | let x: () = foo::<'static>;
6262
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item

tests/ui/associated-types/substs-ppaux.verbose.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
22
--> $DIR/substs-ppaux.rs:16:17
33
|
44
LL | fn bar<'a, T>() where T: 'a {}
5-
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>} defined here
5+
| --------------------------- associated function `bar` defined here
66
...
77
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
88
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
2020
--> $DIR/substs-ppaux.rs:25:17
2121
|
2222
LL | fn bar<'a, T>() where T: 'a {}
23-
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here
23+
| --------------------------- associated function `bar` defined here
2424
...
2525
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
2626
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
3838
--> $DIR/substs-ppaux.rs:33:17
3939
|
4040
LL | fn baz() {}
41-
| -------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz} defined here
41+
| -------- associated function `baz` defined here
4242
...
4343
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
4444
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
5656
--> $DIR/substs-ppaux.rs:41:17
5757
|
5858
LL | fn foo<'z>() where &'z (): Sized {
59-
| -------------------------------- fn() {foo::<ReStatic>} defined here
59+
| -------------------------------- function `foo` defined here
6060
...
6161
LL | let x: () = foo::<'static>;
6262
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item

tests/ui/issues/issue-35241.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ error[E0308]: mismatched types
22
--> $DIR/issue-35241.rs:3:20
33
|
44
LL | struct Foo(u32);
5-
| ---------- fn(u32) -> Foo {Foo} defined here
5+
| ---------- `Foo` defines a struct constructor here, which should be called
66
LL |
77
LL | fn test() -> Foo { Foo }
8-
| --- ^^^ expected struct `Foo`, found fn item
8+
| --- ^^^ expected struct `Foo`, found struct constructor
99
| |
1010
| expected `Foo` because of return type
1111
|
12-
= note: expected struct `Foo`
13-
found fn item `fn(u32) -> Foo {Foo}`
12+
= note: expected struct `Foo`
13+
found struct constructor `fn(u32) -> Foo {Foo}`
1414
help: use parentheses to construct this tuple struct
1515
|
1616
LL | fn test() -> Foo { Foo(/* u32 */) }

tests/ui/resolve/privacy-enum-ctor.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,15 @@ error[E0308]: mismatched types
264264
--> $DIR/privacy-enum-ctor.rs:27:20
265265
|
266266
LL | Fn(u8),
267-
| -- fn(u8) -> Z {Z::Fn} defined here
267+
| -- `Fn` defines an enum variant constructor here, which should be called
268268
...
269269
LL | let _: Z = Z::Fn;
270-
| - ^^^^^ expected enum `Z`, found fn item
270+
| - ^^^^^ expected enum `Z`, found enum constructor
271271
| |
272272
| expected due to this
273273
|
274-
= note: expected enum `Z`
275-
found fn item `fn(u8) -> Z {Z::Fn}`
274+
= note: expected enum `Z`
275+
found enum constructor `fn(u8) -> Z {Z::Fn}`
276276
help: use parentheses to construct this tuple variant
277277
|
278278
LL | let _: Z = Z::Fn(/* u8 */);
@@ -305,15 +305,15 @@ error[E0308]: mismatched types
305305
--> $DIR/privacy-enum-ctor.rs:43:16
306306
|
307307
LL | Fn(u8),
308-
| -- fn(u8) -> E {E::Fn} defined here
308+
| -- `Fn` defines an enum variant constructor here, which should be called
309309
...
310310
LL | let _: E = m::E::Fn;
311-
| - ^^^^^^^^ expected enum `E`, found fn item
311+
| - ^^^^^^^^ expected enum `E`, found enum constructor
312312
| |
313313
| expected due to this
314314
|
315-
= note: expected enum `E`
316-
found fn item `fn(u8) -> E {E::Fn}`
315+
= note: expected enum `E`
316+
found enum constructor `fn(u8) -> E {E::Fn}`
317317
help: use parentheses to construct this tuple variant
318318
|
319319
LL | let _: E = m::E::Fn(/* u8 */);
@@ -346,15 +346,15 @@ error[E0308]: mismatched types
346346
--> $DIR/privacy-enum-ctor.rs:51:16
347347
|
348348
LL | Fn(u8),
349-
| -- fn(u8) -> E {E::Fn} defined here
349+
| -- `Fn` defines an enum variant constructor here, which should be called
350350
...
351351
LL | let _: E = E::Fn;
352-
| - ^^^^^ expected enum `E`, found fn item
352+
| - ^^^^^ expected enum `E`, found enum constructor
353353
| |
354354
| expected due to this
355355
|
356-
= note: expected enum `E`
357-
found fn item `fn(u8) -> E {E::Fn}`
356+
= note: expected enum `E`
357+
found enum constructor `fn(u8) -> E {E::Fn}`
358358
help: use parentheses to construct this tuple variant
359359
|
360360
LL | let _: E = E::Fn(/* u8 */);

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

+22-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
22
--> $DIR/fn-or-tuple-struct-without-args.rs:29:20
33
|
44
LL | fn foo(a: usize, b: usize) -> usize { a }
5-
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here
5+
| ----------------------------------- function `foo` defined here
66
...
77
LL | let _: usize = foo;
88
| ----- ^^^ expected `usize`, found fn item
@@ -20,15 +20,15 @@ error[E0308]: mismatched types
2020
--> $DIR/fn-or-tuple-struct-without-args.rs:30:16
2121
|
2222
LL | struct S(usize, usize);
23-
| -------- fn(usize, usize) -> S {S} defined here
23+
| -------- `S` defines a struct constructor here, which should be called
2424
...
2525
LL | let _: S = S;
26-
| - ^ expected struct `S`, found fn item
26+
| - ^ expected struct `S`, found struct constructor
2727
| |
2828
| expected due to this
2929
|
30-
= note: expected struct `S`
31-
found fn item `fn(usize, usize) -> S {S}`
30+
= note: expected struct `S`
31+
found struct constructor `fn(usize, usize) -> S {S}`
3232
help: use parentheses to construct this tuple struct
3333
|
3434
LL | let _: S = S(/* usize */, /* usize */);
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
3838
--> $DIR/fn-or-tuple-struct-without-args.rs:31:20
3939
|
4040
LL | fn bar() -> usize { 42 }
41-
| ----------------- fn() -> usize {bar} defined here
41+
| ----------------- function `bar` defined here
4242
...
4343
LL | let _: usize = bar;
4444
| ----- ^^^ expected `usize`, found fn item
@@ -56,15 +56,15 @@ error[E0308]: mismatched types
5656
--> $DIR/fn-or-tuple-struct-without-args.rs:32:16
5757
|
5858
LL | struct V();
59-
| -------- fn() -> V {V} defined here
59+
| -------- `V` defines a struct constructor here, which should be called
6060
...
6161
LL | let _: V = V;
62-
| - ^ expected struct `V`, found fn item
62+
| - ^ expected struct `V`, found struct constructor
6363
| |
6464
| expected due to this
6565
|
66-
= note: expected struct `V`
67-
found fn item `fn() -> V {V}`
66+
= note: expected struct `V`
67+
found struct constructor `fn() -> V {V}`
6868
help: use parentheses to construct this tuple struct
6969
|
7070
LL | let _: V = V();
@@ -74,7 +74,7 @@ error[E0308]: mismatched types
7474
--> $DIR/fn-or-tuple-struct-without-args.rs:33:20
7575
|
7676
LL | fn baz(x: usize, y: usize) -> usize { x }
77-
| ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here
77+
| ----------------------------------- associated function `baz` defined here
7878
...
7979
LL | let _: usize = T::baz;
8080
| ----- ^^^^^^ expected `usize`, found fn item
@@ -92,7 +92,7 @@ error[E0308]: mismatched types
9292
--> $DIR/fn-or-tuple-struct-without-args.rs:34:20
9393
|
9494
LL | fn bat(x: usize) -> usize { 42 }
95-
| ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here
95+
| ------------------------- associated function `bat` defined here
9696
...
9797
LL | let _: usize = T::bat;
9898
| ----- ^^^^^^ expected `usize`, found fn item
@@ -110,15 +110,15 @@ error[E0308]: mismatched types
110110
--> $DIR/fn-or-tuple-struct-without-args.rs:35:16
111111
|
112112
LL | A(usize),
113-
| - fn(usize) -> E {E::A} defined here
113+
| - `A` defines an enum variant constructor here, which should be called
114114
...
115115
LL | let _: E = E::A;
116-
| - ^^^^ expected enum `E`, found fn item
116+
| - ^^^^ expected enum `E`, found enum constructor
117117
| |
118118
| expected due to this
119119
|
120-
= note: expected enum `E`
121-
found fn item `fn(usize) -> E {E::A}`
120+
= note: expected enum `E`
121+
found enum constructor `fn(usize) -> E {E::A}`
122122
help: use parentheses to construct this tuple variant
123123
|
124124
LL | let _: E = E::A(/* usize */);
@@ -134,7 +134,7 @@ error[E0308]: mismatched types
134134
--> $DIR/fn-or-tuple-struct-without-args.rs:37:20
135135
|
136136
LL | fn baz(x: usize, y: usize) -> usize { x }
137-
| ----------------------------------- fn(usize, usize) -> usize {<X as T>::baz} defined here
137+
| ----------------------------------- associated function `baz` defined here
138138
...
139139
LL | let _: usize = X::baz;
140140
| ----- ^^^^^^ expected `usize`, found fn item
@@ -152,7 +152,7 @@ error[E0308]: mismatched types
152152
--> $DIR/fn-or-tuple-struct-without-args.rs:38:20
153153
|
154154
LL | fn bat(x: usize) -> usize { 42 }
155-
| ------------------------- fn(usize) -> usize {<X as T>::bat} defined here
155+
| ------------------------- associated function `bat` defined here
156156
...
157157
LL | let _: usize = X::bat;
158158
| ----- ^^^^^^ expected `usize`, found fn item
@@ -170,7 +170,7 @@ error[E0308]: mismatched types
170170
--> $DIR/fn-or-tuple-struct-without-args.rs:39:20
171171
|
172172
LL | fn bax(x: usize) -> usize { 42 }
173-
| ------------------------- fn(usize) -> usize {<X as T>::bax} defined here
173+
| ------------------------- associated function `bax` defined here
174174
...
175175
LL | let _: usize = X::bax;
176176
| ----- ^^^^^^ expected `usize`, found fn item
@@ -188,7 +188,7 @@ error[E0308]: mismatched types
188188
--> $DIR/fn-or-tuple-struct-without-args.rs:40:20
189189
|
190190
LL | fn bach(x: usize) -> usize;
191-
| --------------------------- fn(usize) -> usize {<X as T>::bach} defined here
191+
| --------------------------- associated function `bach` defined here
192192
...
193193
LL | let _: usize = X::bach;
194194
| ----- ^^^^^^^ expected `usize`, found fn item
@@ -206,7 +206,7 @@ error[E0308]: mismatched types
206206
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20
207207
|
208208
LL | fn ban(&self) -> usize { 42 }
209-
| ---------------------- for<'a> fn(&'a X) -> usize {<X as T>::ban} defined here
209+
| ---------------------- associated function `ban` defined here
210210
...
211211
LL | let _: usize = X::ban;
212212
| ----- ^^^^^^ expected `usize`, found fn item
@@ -224,7 +224,7 @@ error[E0308]: mismatched types
224224
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20
225225
|
226226
LL | fn bal(&self) -> usize;
227-
| ----------------------- for<'a> fn(&'a X) -> usize {<X as T>::bal} defined here
227+
| ----------------------- associated function `bal` defined here
228228
...
229229
LL | let _: usize = X::bal;
230230
| ----- ^^^^^^ expected `usize`, found fn item

tests/ui/typeck/issue-87181/empty-tuple-method.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ impl Foo {
1010
fn main() {
1111
let thing = Bar { bar: Foo };
1212
thing.bar.foo();
13-
//~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope [E0599]
13+
//~^ ERROR no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope [E0599]
1414
}

tests/ui/typeck/issue-87181/empty-tuple-method.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope
1+
error[E0599]: no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope
22
--> $DIR/empty-tuple-method.rs:12:15
33
|
44
LL | thing.bar.foo();

tests/ui/typeck/issue-87181/enum-variant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ impl Foo {
1212
fn main() {
1313
let thing = Bar { bar: Foo::Tup };
1414
thing.bar.foo();
15-
//~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
15+
//~^ ERROR no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
1616
}

tests/ui/typeck/issue-87181/enum-variant.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope
1+
error[E0599]: no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope
22
--> $DIR/enum-variant.rs:14:15
33
|
44
LL | thing.bar.foo();

0 commit comments

Comments
 (0)