Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Label struct/enum constructor instead of fn item, mention that it should be called on type mismatch #106524

Merged
merged 2 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
Expand Down Expand Up @@ -417,10 +417,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
return true;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind()
&& let Some(sp) = self.tcx.hir().span_if_local(*def_id)
&& let ty::FnDef(def_id, ..) = *found.kind()
&& let Some(sp) = self.tcx.hir().span_if_local(def_id)
{
err.span_label(sp, format!("{found} defined here"));
let name = self.tcx.item_name(def_id);
let kind = self.tcx.def_kind(def_id);
if let DefKind::Ctor(of, CtorKind::Fn) = kind {
err.span_label(sp, format!("`{name}` defines {} constructor here, which should be called", match of {
CtorOf::Struct => "a struct",
CtorOf::Variant => "an enum variant",
}));
} else {
let descr = kind.descr(def_id);
err.span_label(sp, format!("{descr} `{name}` defined here"));
}
return true;
} else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
return true;
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::diagnostics::suggest_constraining_type_param;
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use hir::def::DefKind;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
Expand Down Expand Up @@ -319,7 +319,11 @@ impl<'tcx> Ty<'tcx> {
.into()
}
}
ty::FnDef(..) => "fn item".into(),
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
Comment on lines +322 to +326
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the existing descr method? The output is a bit different, but also more uniform with other diags.

Suggested change
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnDef(def_id, ..) => tcx.def_kind(def_id).descr(def_id).into(),

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly because descr is pretty verbose here.. I didn't like how it sounded for these ctor DefKinds, but I don't have a particularly strong opinion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, also, I'm not really a fan of renaming functions from "fn item" to their descr "function".

ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
Expand Down Expand Up @@ -366,7 +370,11 @@ impl<'tcx> Ty<'tcx> {
_ => "reference",
}
.into(),
ty::FnDef(..) => "fn item".into(),
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/associated-types/substs-ppaux.normal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:16:17
|
LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>} defined here
| --------------------------- associated function `bar` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17
|
LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>} defined here
| --------------------------- associated function `bar` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:33:17
|
LL | fn baz() {}
| -------- fn() {<i8 as Foo<'static, 'static, u8>>::baz} defined here
| -------- associated function `baz` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:41:17
|
LL | fn foo<'z>() where &'z (): Sized {
| -------------------------------- fn() {foo::<'static>} defined here
| -------------------------------- function `foo` defined here
...
LL | let x: () = foo::<'static>;
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/associated-types/substs-ppaux.verbose.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:16:17
|
LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>} defined here
| --------------------------- associated function `bar` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17
|
LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here
| --------------------------- associated function `bar` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:33:17
|
LL | fn baz() {}
| -------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz} defined here
| -------- associated function `baz` defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u8>>::baz;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
Expand All @@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:41:17
|
LL | fn foo<'z>() where &'z (): Sized {
| -------------------------------- fn() {foo::<ReStatic>} defined here
| -------------------------------- function `foo` defined here
...
LL | let x: () = foo::<'static>;
| -- ^^^^^^^^^^^^^^ expected `()`, found fn item
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/issues/issue-35241.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ error[E0308]: mismatched types
--> $DIR/issue-35241.rs:3:20
|
LL | struct Foo(u32);
| ---------- fn(u32) -> Foo {Foo} defined here
| ---------- `Foo` defines a struct constructor here, which should be called
LL |
LL | fn test() -> Foo { Foo }
| --- ^^^ expected struct `Foo`, found fn item
| --- ^^^ expected struct `Foo`, found struct constructor
| |
| expected `Foo` because of return type
|
= note: expected struct `Foo`
found fn item `fn(u32) -> Foo {Foo}`
= note: expected struct `Foo`
found struct constructor `fn(u32) -> Foo {Foo}`
help: use parentheses to construct this tuple struct
|
LL | fn test() -> Foo { Foo(/* u32 */) }
Expand Down
24 changes: 12 additions & 12 deletions tests/ui/resolve/privacy-enum-ctor.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:27:20
|
LL | Fn(u8),
| -- fn(u8) -> Z {Z::Fn} defined here
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: Z = Z::Fn;
| - ^^^^^ expected enum `Z`, found fn item
| - ^^^^^ expected enum `Z`, found enum constructor
| |
| expected due to this
|
= note: expected enum `Z`
found fn item `fn(u8) -> Z {Z::Fn}`
= note: expected enum `Z`
found enum constructor `fn(u8) -> Z {Z::Fn}`
help: use parentheses to construct this tuple variant
|
LL | let _: Z = Z::Fn(/* u8 */);
Expand Down Expand Up @@ -305,15 +305,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:43:16
|
LL | Fn(u8),
| -- fn(u8) -> E {E::Fn} defined here
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = m::E::Fn;
| - ^^^^^^^^ expected enum `E`, found fn item
| - ^^^^^^^^ expected enum `E`, found enum constructor
| |
| expected due to this
|
= note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}`
= note: expected enum `E`
found enum constructor `fn(u8) -> E {E::Fn}`
help: use parentheses to construct this tuple variant
|
LL | let _: E = m::E::Fn(/* u8 */);
Expand Down Expand Up @@ -346,15 +346,15 @@ error[E0308]: mismatched types
--> $DIR/privacy-enum-ctor.rs:51:16
|
LL | Fn(u8),
| -- fn(u8) -> E {E::Fn} defined here
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::Fn;
| - ^^^^^ expected enum `E`, found fn item
| - ^^^^^ expected enum `E`, found enum constructor
| |
| expected due to this
|
= note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}`
= note: expected enum `E`
found enum constructor `fn(u8) -> E {E::Fn}`
help: use parentheses to construct this tuple variant
|
LL | let _: E = E::Fn(/* u8 */);
Expand Down
44 changes: 22 additions & 22 deletions tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:29:20
|
LL | fn foo(a: usize, b: usize) -> usize { a }
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here
| ----------------------------------- function `foo` defined here
...
LL | let _: usize = foo;
| ----- ^^^ expected `usize`, found fn item
Expand All @@ -20,15 +20,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:30:16
|
LL | struct S(usize, usize);
| -------- fn(usize, usize) -> S {S} defined here
| -------- `S` defines a struct constructor here, which should be called
...
LL | let _: S = S;
| - ^ expected struct `S`, found fn item
| - ^ expected struct `S`, found struct constructor
| |
| expected due to this
|
= note: expected struct `S`
found fn item `fn(usize, usize) -> S {S}`
= note: expected struct `S`
found struct constructor `fn(usize, usize) -> S {S}`
help: use parentheses to construct this tuple struct
|
LL | let _: S = S(/* usize */, /* usize */);
Expand All @@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:31:20
|
LL | fn bar() -> usize { 42 }
| ----------------- fn() -> usize {bar} defined here
| ----------------- function `bar` defined here
...
LL | let _: usize = bar;
| ----- ^^^ expected `usize`, found fn item
Expand All @@ -56,15 +56,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:32:16
|
LL | struct V();
| -------- fn() -> V {V} defined here
| -------- `V` defines a struct constructor here, which should be called
...
LL | let _: V = V;
| - ^ expected struct `V`, found fn item
| - ^ expected struct `V`, found struct constructor
| |
| expected due to this
|
= note: expected struct `V`
found fn item `fn() -> V {V}`
= note: expected struct `V`
found struct constructor `fn() -> V {V}`
help: use parentheses to construct this tuple struct
|
LL | let _: V = V();
Expand All @@ -74,7 +74,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:33:20
|
LL | fn baz(x: usize, y: usize) -> usize { x }
| ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here
| ----------------------------------- associated function `baz` defined here
...
LL | let _: usize = T::baz;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -92,7 +92,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:34:20
|
LL | fn bat(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here
| ------------------------- associated function `bat` defined here
...
LL | let _: usize = T::bat;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -110,15 +110,15 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:35:16
|
LL | A(usize),
| - fn(usize) -> E {E::A} defined here
| - `A` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::A;
| - ^^^^ expected enum `E`, found fn item
| - ^^^^ expected enum `E`, found enum constructor
| |
| expected due to this
|
= note: expected enum `E`
found fn item `fn(usize) -> E {E::A}`
= note: expected enum `E`
found enum constructor `fn(usize) -> E {E::A}`
help: use parentheses to construct this tuple variant
|
LL | let _: E = E::A(/* usize */);
Expand All @@ -134,7 +134,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:37:20
|
LL | fn baz(x: usize, y: usize) -> usize { x }
| ----------------------------------- fn(usize, usize) -> usize {<X as T>::baz} defined here
| ----------------------------------- associated function `baz` defined here
...
LL | let _: usize = X::baz;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -152,7 +152,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:38:20
|
LL | fn bat(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<X as T>::bat} defined here
| ------------------------- associated function `bat` defined here
...
LL | let _: usize = X::bat;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -170,7 +170,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:39:20
|
LL | fn bax(x: usize) -> usize { 42 }
| ------------------------- fn(usize) -> usize {<X as T>::bax} defined here
| ------------------------- associated function `bax` defined here
...
LL | let _: usize = X::bax;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -188,7 +188,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:40:20
|
LL | fn bach(x: usize) -> usize;
| --------------------------- fn(usize) -> usize {<X as T>::bach} defined here
| --------------------------- associated function `bach` defined here
...
LL | let _: usize = X::bach;
| ----- ^^^^^^^ expected `usize`, found fn item
Expand All @@ -206,7 +206,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20
|
LL | fn ban(&self) -> usize { 42 }
| ---------------------- for<'a> fn(&'a X) -> usize {<X as T>::ban} defined here
| ---------------------- associated function `ban` defined here
...
LL | let _: usize = X::ban;
| ----- ^^^^^^ expected `usize`, found fn item
Expand All @@ -224,7 +224,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20
|
LL | fn bal(&self) -> usize;
| ----------------------- for<'a> fn(&'a X) -> usize {<X as T>::bal} defined here
| ----------------------- associated function `bal` defined here
...
LL | let _: usize = X::bal;
| ----- ^^^^^^ expected `usize`, found fn item
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-87181/empty-tuple-method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ impl Foo {
fn main() {
let thing = Bar { bar: Foo };
thing.bar.foo();
//~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope [E0599]
//~^ ERROR no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope [E0599]
}
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-87181/empty-tuple-method.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope
error[E0599]: no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope
--> $DIR/empty-tuple-method.rs:12:15
|
LL | thing.bar.foo();
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-87181/enum-variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ impl Foo {
fn main() {
let thing = Bar { bar: Foo::Tup };
thing.bar.foo();
//~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
//~^ ERROR no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
}
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-87181/enum-variant.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope
error[E0599]: no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope
--> $DIR/enum-variant.rs:14:15
|
LL | thing.bar.foo();
Expand Down
Loading