Suggest to replace tuple constructor through projection · rust-lang/rust@304ccf4 (original) (raw)

File tree

4 files changed

lines changed

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ use rustc_data_structures::sorted_map::SortedMap;
14 14 use rustc_data_structures::unord::UnordSet;
15 15 use rustc_errors::codes::*;
16 16 use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
17 -use rustc_hir::def::DefKind;
17 +use rustc_hir::def::{CtorKind, DefKind, Res};
18 18 use rustc_hir::def_id::DefId;
19 19 use rustc_hir::intravisit::{self, Visitor};
20 20 use rustc_hir::lang_items::LangItem;
@@ -690,6 +690,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
690 690 );
691 691 }
692 692
693 +// Check if we wrote `Self::Assoc(1)` as if it were a tuple ctor.
694 +if let SelfSource::QPath(ty) = source
695 + && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
696 + && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res
697 + && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id)
698 + && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
699 +self.tcx,
700 + item_name,
701 + ty::AssocKind::Type,
702 + impl_def_id,
703 +)
704 + && let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
705 + && adt_def.is_struct()
706 + && adt_def.non_enum_variant().ctor_kind() == Some(CtorKind::Fn)
707 +{
708 +let def_path = tcx.def_path_str(adt_def.did());
709 + err.span_suggestion(
710 + ty.span.to(item_name.span),
711 +format!("to construct a value of type `{}`, use the explicit path", def_path),
712 + def_path,
713 +Applicability::MachineApplicable,
714 +);
715 +}
716 +
693 717 err
694 718 };
695 719 if tcx.sess.source_map().is_multiline(sugg_span) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
1 +//@ run-rustfix
2 +
3 +#![allow(unused)]
4 +
5 +struct Constructor(i32);
6 +
7 +trait Trait {
8 + type Out;
9 +
10 + fn mk() -> Self::Out;
11 +}
12 +
13 +impl Trait for () {
14 + type Out = Constructor;
15 +
16 + fn mk() -> Self::Out {
17 + Constructor(1)
18 + //~^ ERROR no associated item named `Out` found for unit type `()`
19 + }
20 +}
21 +
22 +fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
1 +//@ run-rustfix
2 +
3 +#![allow(unused)]
4 +
5 +struct Constructor(i32);
6 +
7 +trait Trait {
8 +type Out;
9 +
10 +fn mk() -> Self::Out;
11 +}
12 +
13 +impl Trait for () {
14 +type Out = Constructor;
15 +
16 +fn mk() -> Self::Out {
17 +Self::Out(1)
18 +//~^ ERROR no associated item named `Out` found for unit type `()`
19 +}
20 +}
21 +
22 +fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
1 +error[E0599]: no associated item named `Out` found for unit type `()` in the current scope
2 + --> $DIR/invalid-ctor.rs:17:15
3 + |
4 +LL | Self::Out(1)
5 + | ^^^ associated item not found in `()`
6 + |
7 +help: to construct a value of type `Constructor`, use the explicit path
8 + |
9 +LL | Constructor(1)
10 + | ~~~~~~~~~~~
11 +
12 +error: aborting due to 1 previous error
13 +
14 +For more information about this error, try `rustc --explain E0599`.