Rollup merge of #110555 - compiler-errors:subst-missing-trait-items, r=cjgillot
Substitute missing trait items suggestion correctly Properly substitute missing item suggestions, so that when they reference generics from their parent trait they actually have the right time for the impl. Also, some other minor tweaks like using `/* Type */` to signify a GAT's type is actually missing, and fixing generic arg suggestions for GATs in general.
This commit is contained in:
commit
7d046551a7
@ -863,7 +863,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||
if !missing_items.is_empty() {
|
||||
let full_impl_span =
|
||||
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
|
||||
missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
|
||||
missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
|
||||
}
|
||||
|
||||
if let Some(missing_items) = must_implement_one_of {
|
||||
|
@ -198,7 +198,7 @@ fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_imp
|
||||
|
||||
fn missing_items_err(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl_span: Span,
|
||||
impl_def_id: LocalDefId,
|
||||
missing_items: &[ty::AssocItem],
|
||||
full_impl_span: Span,
|
||||
) {
|
||||
@ -211,6 +211,7 @@ fn missing_items_err(
|
||||
.collect::<Vec<_>>()
|
||||
.join("`, `");
|
||||
|
||||
let impl_span = tcx.def_span(impl_def_id);
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_span,
|
||||
@ -229,7 +230,11 @@ fn missing_items_err(
|
||||
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
|
||||
|
||||
for &trait_item in missing_items {
|
||||
let snippet = suggestion_signature(trait_item, tcx);
|
||||
let snippet = suggestion_signature(
|
||||
tcx,
|
||||
trait_item,
|
||||
tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
|
||||
);
|
||||
let code = format!("{}{}\n{}", padding, snippet, padding);
|
||||
let msg = format!("implement the missing item: `{snippet}`");
|
||||
let appl = Applicability::HasPlaceholders;
|
||||
@ -301,11 +306,11 @@ fn default_body_is_unstable(
|
||||
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
|
||||
fn bounds_from_generic_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
|
||||
) -> (String, String) {
|
||||
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
|
||||
let mut projections = vec![];
|
||||
for (predicate, _) in predicates.predicates {
|
||||
for (predicate, _) in predicates {
|
||||
debug!("predicate {:?}", predicate);
|
||||
let bound_predicate = predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
@ -367,7 +372,7 @@ fn fn_sig_suggestion<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sig: ty::FnSig<'tcx>,
|
||||
ident: Ident,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
|
||||
assoc: ty::AssocItem,
|
||||
) -> String {
|
||||
let args = sig
|
||||
@ -436,7 +441,17 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
|
||||
/// Return placeholder code for the given associated item.
|
||||
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
|
||||
/// structured suggestion.
|
||||
fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
|
||||
fn suggestion_signature<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
assoc: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> String {
|
||||
let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
|
||||
tcx,
|
||||
assoc.container_id(tcx),
|
||||
impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
|
||||
);
|
||||
|
||||
match assoc.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
// We skip the binder here because the binder would deanonymize all
|
||||
@ -445,16 +460,22 @@ fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
|
||||
// regions just fine, showing `fn(&MyType)`.
|
||||
fn_sig_suggestion(
|
||||
tcx,
|
||||
tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
|
||||
tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
|
||||
assoc.ident(tcx),
|
||||
tcx.predicates_of(assoc.def_id),
|
||||
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
|
||||
assoc,
|
||||
)
|
||||
}
|
||||
ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
|
||||
ty::AssocKind::Type => {
|
||||
let (generics, where_clauses) = bounds_from_generic_predicates(
|
||||
tcx,
|
||||
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
|
||||
);
|
||||
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
|
||||
}
|
||||
ty::AssocKind::Const => {
|
||||
let ty = tcx.type_of(assoc.def_id).subst_identity();
|
||||
let val = ty_kind_suggestion(ty).unwrap_or("value");
|
||||
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
|
||||
format!("const {}: {} = {};", assoc.name, ty, val)
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ error[E0046]: not all trait items implemented, missing: `Error`, `try_from`
|
||||
LL | impl TryFrom<OtherStream> for MyStream {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Error = Type;`
|
||||
= help: implement the missing item: `fn try_from(_: T) -> Result<Self, <Self as TryFrom<T>>::Error> { todo!() }`
|
||||
= help: implement the missing item: `type Error = /* Type */;`
|
||||
= help: implement the missing item: `fn try_from(_: OtherStream) -> Result<Self, <Self as TryFrom<OtherStream>>::Error> { todo!() }`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
pub trait Foo {
|
||||
type Gat<T>
|
||||
where
|
||||
T: std::fmt::Display;
|
||||
}
|
11
tests/ui/generic-associated-types/missing-item-sugg.rs
Normal file
11
tests/ui/generic-associated-types/missing-item-sugg.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// aux-build:missing-item-sugg.rs
|
||||
|
||||
extern crate missing_item_sugg;
|
||||
|
||||
struct Local;
|
||||
impl missing_item_sugg::Foo for Local {
|
||||
//~^ ERROR not all trait items implemented, missing: `Gat`
|
||||
}
|
||||
//~^ HELP implement the missing item: `type Gat<T> = /* Type */ where T: std::fmt::Display;`
|
||||
|
||||
fn main() {}
|
11
tests/ui/generic-associated-types/missing-item-sugg.stderr
Normal file
11
tests/ui/generic-associated-types/missing-item-sugg.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0046]: not all trait items implemented, missing: `Gat`
|
||||
--> $DIR/missing-item-sugg.rs:6:1
|
||||
|
|
||||
LL | impl missing_item_sugg::Foo for Local {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Gat` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Gat<T> = /* Type */ where T: std::fmt::Display;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0046`.
|
@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `partial_cmp`
|
||||
LL | impl PartialOrd for Thing {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn partial_cmp(&self, _: &Rhs) -> Option<std::cmp::Ordering> { todo!() }`
|
||||
= help: implement the missing item: `fn partial_cmp(&self, _: &Thing) -> Option<std::cmp::Ordering> { todo!() }`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | impl m1::X for X {
|
||||
| ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` in implementation
|
||||
|
|
||||
= help: implement the missing item: `const CONSTANT: u32 = 42;`
|
||||
= help: implement the missing item: `type Type = Type;`
|
||||
= help: implement the missing item: `type Type = /* Type */;`
|
||||
= help: implement the missing item: `fn method(&self, _: String) -> <Self as m1::X>::Type { todo!() }`
|
||||
= help: implement the missing item: `fn method2(self: Box<Self>, _: String) -> <Self as m1::X>::Type { todo!() }`
|
||||
= help: implement the missing item: `fn method3(_: &Self, _: String) -> <Self as m1::X>::Type { todo!() }`
|
||||
|
@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Item`
|
||||
LL | impl Iterator for Recurrence {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Item = Type;`
|
||||
= help: implement the missing item: `type Item = /* Type */;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Output`
|
||||
LL | impl<C: Component> FnOnce<(C,)> for Prototype {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Output = Type;`
|
||||
= help: implement the missing item: `type Output = /* Type */;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Target`
|
||||
LL | impl Deref for Thing {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Target = Type;`
|
||||
= help: implement the missing item: `type Target = /* Type */;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
pub trait TraitB {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait TraitA<A> {
|
||||
type Type;
|
||||
|
||||
fn bar<T>(_: T) -> Self;
|
||||
|
||||
fn baz<T>(_: T) -> Self
|
||||
where
|
||||
T: TraitB,
|
||||
<T as TraitB>::Item: Copy;
|
||||
|
||||
const A: usize;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// run-rustfix
|
||||
trait TraitB {
|
||||
type Item;
|
||||
}
|
||||
|
||||
trait TraitA<A> {
|
||||
type Type;
|
||||
fn bar<T>(_: T) -> Self;
|
||||
fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
|
||||
}
|
||||
|
||||
struct S;
|
||||
struct Type;
|
||||
|
||||
impl TraitA<()> for S { //~ ERROR not all trait items implemented
|
||||
fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }
|
||||
fn bar<T>(_: T) -> Self { todo!() }
|
||||
type Type = Type;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,18 +1,15 @@
|
||||
// run-rustfix
|
||||
trait TraitB {
|
||||
type Item;
|
||||
}
|
||||
// aux-build:missing-assoc-fn-applicable-suggestions.rs
|
||||
|
||||
trait TraitA<A> {
|
||||
type Type;
|
||||
fn bar<T>(_: T) -> Self;
|
||||
fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
|
||||
}
|
||||
extern crate missing_assoc_fn_applicable_suggestions;
|
||||
use missing_assoc_fn_applicable_suggestions::TraitA;
|
||||
|
||||
struct S;
|
||||
struct Type;
|
||||
|
||||
impl TraitA<()> for S { //~ ERROR not all trait items implemented
|
||||
impl TraitA<()> for S {
|
||||
//~^ ERROR not all trait items implemented
|
||||
}
|
||||
//~^ HELP implement the missing item: `type Type = /* Type */;`
|
||||
//~| HELP implement the missing item: `fn bar<T>(_: T) -> Self { todo!() }`
|
||||
//~| HELP implement the missing item: `fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }`
|
||||
//~| HELP implement the missing item: `const A: usize = 42;`
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,15 +1,13 @@
|
||||
error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz`
|
||||
--> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1
|
||||
error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz`, `A`
|
||||
--> $DIR/missing-assoc-fn-applicable-suggestions.rs:7:1
|
||||
|
|
||||
LL | type Type;
|
||||
| --------- `Type` from trait
|
||||
LL | fn bar<T>(_: T) -> Self;
|
||||
| ------------------------ `bar` from trait
|
||||
LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
|
||||
| ------------------------------------------------------------------- `baz` from trait
|
||||
...
|
||||
LL | impl TraitA<()> for S {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz` in implementation
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz`, `A` in implementation
|
||||
|
|
||||
= help: implement the missing item: `type Type = /* Type */;`
|
||||
= help: implement the missing item: `fn bar<T>(_: T) -> Self { todo!() }`
|
||||
= help: implement the missing item: `fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }`
|
||||
= help: implement the missing item: `const A: usize = 42;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter`
|
||||
LL | impl FromIterator<()> for X {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = A { todo!() }`
|
||||
= help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = () { todo!() }`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user