1
Fork 0

Suggest to replace tuple constructor through projection

This commit is contained in:
Michael Goulet 2025-01-04 00:13:49 +00:00
parent 243d2ca4db
commit 304ccf45d1
4 changed files with 83 additions and 1 deletions

View file

@ -14,7 +14,7 @@ use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items::LangItem;
@ -690,6 +690,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
// Check if we wrote `Self::Assoc(1)` as if it were a tuple ctor.
if let SelfSource::QPath(ty) = source
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
&& let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res
&& let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id)
&& let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
self.tcx,
item_name,
ty::AssocKind::Type,
impl_def_id,
)
&& let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
&& adt_def.is_struct()
&& adt_def.non_enum_variant().ctor_kind() == Some(CtorKind::Fn)
{
let def_path = tcx.def_path_str(adt_def.did());
err.span_suggestion(
ty.span.to(item_name.span),
format!("to construct a value of type `{}`, use the explicit path", def_path),
def_path,
Applicability::MachineApplicable,
);
}
err
};
if tcx.sess.source_map().is_multiline(sugg_span) {

View file

@ -0,0 +1,22 @@
//@ run-rustfix
#![allow(unused)]
struct Constructor(i32);
trait Trait {
type Out;
fn mk() -> Self::Out;
}
impl Trait for () {
type Out = Constructor;
fn mk() -> Self::Out {
Constructor(1)
//~^ ERROR no associated item named `Out` found for unit type `()`
}
}
fn main() {}

View file

@ -0,0 +1,22 @@
//@ run-rustfix
#![allow(unused)]
struct Constructor(i32);
trait Trait {
type Out;
fn mk() -> Self::Out;
}
impl Trait for () {
type Out = Constructor;
fn mk() -> Self::Out {
Self::Out(1)
//~^ ERROR no associated item named `Out` found for unit type `()`
}
}
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0599]: no associated item named `Out` found for unit type `()` in the current scope
--> $DIR/invalid-ctor.rs:17:15
|
LL | Self::Out(1)
| ^^^ associated item not found in `()`
|
help: to construct a value of type `Constructor`, use the explicit path
|
LL | Constructor(1)
| ~~~~~~~~~~~
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0599`.