Skip to content

Commit 304ccf4

Browse files
Suggest to replace tuple constructor through projection
1 parent 243d2ca commit 304ccf4

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_data_structures::sorted_map::SortedMap;
1414
use rustc_data_structures::unord::UnordSet;
1515
use rustc_errors::codes::*;
1616
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};
1818
use rustc_hir::def_id::DefId;
1919
use rustc_hir::intravisit::{self, Visitor};
2020
use rustc_hir::lang_items::LangItem;
@@ -690,6 +690,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
690690
);
691691
}
692692

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+
693717
err
694718
};
695719
if tcx.sess.source_map().is_multiline(sugg_span) {
Original file line numberDiff line numberDiff 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() {}
+22
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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`.

0 commit comments

Comments
 (0)