Skip to content

Commit 7d04655

Browse files
authored
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.
2 parents f2321ec + f362f6e commit 7d04655

16 files changed

+100
-62
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ fn check_impl_items_against_trait<'tcx>(
863863
if !missing_items.is_empty() {
864864
let full_impl_span =
865865
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
866-
missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
866+
missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
867867
}
868868

869869
if let Some(missing_items) = must_implement_one_of {

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_imp
198198

199199
fn missing_items_err(
200200
tcx: TyCtxt<'_>,
201-
impl_span: Span,
201+
impl_def_id: LocalDefId,
202202
missing_items: &[ty::AssocItem],
203203
full_impl_span: Span,
204204
) {
@@ -211,6 +211,7 @@ fn missing_items_err(
211211
.collect::<Vec<_>>()
212212
.join("`, `");
213213

214+
let impl_span = tcx.def_span(impl_def_id);
214215
let mut err = struct_span_err!(
215216
tcx.sess,
216217
impl_span,
@@ -229,7 +230,11 @@ fn missing_items_err(
229230
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
230231

231232
for &trait_item in missing_items {
232-
let snippet = suggestion_signature(trait_item, tcx);
233+
let snippet = suggestion_signature(
234+
tcx,
235+
trait_item,
236+
tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
237+
);
233238
let code = format!("{}{}\n{}", padding, snippet, padding);
234239
let msg = format!("implement the missing item: `{snippet}`");
235240
let appl = Applicability::HasPlaceholders;
@@ -301,11 +306,11 @@ fn default_body_is_unstable(
301306
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
302307
fn bounds_from_generic_predicates<'tcx>(
303308
tcx: TyCtxt<'tcx>,
304-
predicates: ty::GenericPredicates<'tcx>,
309+
predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
305310
) -> (String, String) {
306311
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
307312
let mut projections = vec![];
308-
for (predicate, _) in predicates.predicates {
313+
for (predicate, _) in predicates {
309314
debug!("predicate {:?}", predicate);
310315
let bound_predicate = predicate.kind();
311316
match bound_predicate.skip_binder() {
@@ -367,7 +372,7 @@ fn fn_sig_suggestion<'tcx>(
367372
tcx: TyCtxt<'tcx>,
368373
sig: ty::FnSig<'tcx>,
369374
ident: Ident,
370-
predicates: ty::GenericPredicates<'tcx>,
375+
predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
371376
assoc: ty::AssocItem,
372377
) -> String {
373378
let args = sig
@@ -436,7 +441,17 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
436441
/// Return placeholder code for the given associated item.
437442
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
438443
/// structured suggestion.
439-
fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
444+
fn suggestion_signature<'tcx>(
445+
tcx: TyCtxt<'tcx>,
446+
assoc: ty::AssocItem,
447+
impl_trait_ref: ty::TraitRef<'tcx>,
448+
) -> String {
449+
let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
450+
tcx,
451+
assoc.container_id(tcx),
452+
impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
453+
);
454+
440455
match assoc.kind {
441456
ty::AssocKind::Fn => {
442457
// We skip the binder here because the binder would deanonymize all
@@ -445,16 +460,22 @@ fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
445460
// regions just fine, showing `fn(&MyType)`.
446461
fn_sig_suggestion(
447462
tcx,
448-
tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
463+
tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
449464
assoc.ident(tcx),
450-
tcx.predicates_of(assoc.def_id),
465+
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
451466
assoc,
452467
)
453468
}
454-
ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
469+
ty::AssocKind::Type => {
470+
let (generics, where_clauses) = bounds_from_generic_predicates(
471+
tcx,
472+
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
473+
);
474+
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
475+
}
455476
ty::AssocKind::Const => {
456477
let ty = tcx.type_of(assoc.def_id).subst_identity();
457-
let val = ty_kind_suggestion(ty).unwrap_or("value");
478+
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
458479
format!("const {}: {} = {};", assoc.name, ty, val)
459480
}
460481
}

tests/ui/async-await/issue-74047.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ error[E0046]: not all trait items implemented, missing: `Error`, `try_from`
44
LL | impl TryFrom<OtherStream> for MyStream {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation
66
|
7-
= help: implement the missing item: `type Error = Type;`
8-
= help: implement the missing item: `fn try_from(_: T) -> Result<Self, <Self as TryFrom<T>>::Error> { todo!() }`
7+
= help: implement the missing item: `type Error = /* Type */;`
8+
= help: implement the missing item: `fn try_from(_: OtherStream) -> Result<Self, <Self as TryFrom<OtherStream>>::Error> { todo!() }`
99

1010
error: aborting due to previous error
1111

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub trait Foo {
2+
type Gat<T>
3+
where
4+
T: std::fmt::Display;
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// aux-build:missing-item-sugg.rs
2+
3+
extern crate missing_item_sugg;
4+
5+
struct Local;
6+
impl missing_item_sugg::Foo for Local {
7+
//~^ ERROR not all trait items implemented, missing: `Gat`
8+
}
9+
//~^ HELP implement the missing item: `type Gat<T> = /* Type */ where T: std::fmt::Display;`
10+
11+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0046]: not all trait items implemented, missing: `Gat`
2+
--> $DIR/missing-item-sugg.rs:6:1
3+
|
4+
LL | impl missing_item_sugg::Foo for Local {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Gat` in implementation
6+
|
7+
= help: implement the missing item: `type Gat<T> = /* Type */ where T: std::fmt::Display;`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0046`.

tests/ui/issues/issue-3344.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `partial_cmp`
44
LL | impl PartialOrd for Thing {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation
66
|
7-
= help: implement the missing item: `fn partial_cmp(&self, _: &Rhs) -> Option<std::cmp::Ordering> { todo!() }`
7+
= help: implement the missing item: `fn partial_cmp(&self, _: &Thing) -> Option<std::cmp::Ordering> { todo!() }`
88

99
error: aborting due to previous error
1010

tests/ui/missing/missing-items/m2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | impl m1::X for X {
55
| ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` in implementation
66
|
77
= help: implement the missing item: `const CONSTANT: u32 = 42;`
8-
= help: implement the missing item: `type Type = Type;`
8+
= help: implement the missing item: `type Type = /* Type */;`
99
= help: implement the missing item: `fn method(&self, _: String) -> <Self as m1::X>::Type { todo!() }`
1010
= help: implement the missing item: `fn method2(self: Box<Self>, _: String) -> <Self as m1::X>::Type { todo!() }`
1111
= help: implement the missing item: `fn method3(_: &Self, _: String) -> <Self as m1::X>::Type { todo!() }`

tests/ui/span/issue-23729.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Item`
44
LL | impl Iterator for Recurrence {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation
66
|
7-
= help: implement the missing item: `type Item = Type;`
7+
= help: implement the missing item: `type Item = /* Type */;`
88

99
error: aborting due to previous error
1010

tests/ui/span/issue-23827.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Output`
44
LL | impl<C: Component> FnOnce<(C,)> for Prototype {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation
66
|
7-
= help: implement the missing item: `type Output = Type;`
7+
= help: implement the missing item: `type Output = /* Type */;`
88

99
error: aborting due to previous error
1010

tests/ui/span/issue-24356.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Target`
44
LL | impl Deref for Thing {
55
| ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation
66
|
7-
= help: implement the missing item: `type Target = Type;`
7+
= help: implement the missing item: `type Target = /* Type */;`
88

99
error: aborting due to previous error
1010

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
pub trait TraitB {
2+
type Item;
3+
}
4+
5+
pub trait TraitA<A> {
6+
type Type;
7+
8+
fn bar<T>(_: T) -> Self;
9+
10+
fn baz<T>(_: T) -> Self
11+
where
12+
T: TraitB,
13+
<T as TraitB>::Item: Copy;
14+
15+
const A: usize;
16+
}

tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
// run-rustfix
2-
trait TraitB {
3-
type Item;
4-
}
1+
// aux-build:missing-assoc-fn-applicable-suggestions.rs
52

6-
trait TraitA<A> {
7-
type Type;
8-
fn bar<T>(_: T) -> Self;
9-
fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
10-
}
3+
extern crate missing_assoc_fn_applicable_suggestions;
4+
use missing_assoc_fn_applicable_suggestions::TraitA;
115

126
struct S;
13-
struct Type;
14-
15-
impl TraitA<()> for S { //~ ERROR not all trait items implemented
7+
impl TraitA<()> for S {
8+
//~^ ERROR not all trait items implemented
169
}
10+
//~^ HELP implement the missing item: `type Type = /* Type */;`
11+
//~| HELP implement the missing item: `fn bar<T>(_: T) -> Self { todo!() }`
12+
//~| HELP implement the missing item: `fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }`
13+
//~| HELP implement the missing item: `const A: usize = 42;`
1714

1815
fn main() {}

tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz`
2-
--> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1
1+
error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz`, `A`
2+
--> $DIR/missing-assoc-fn-applicable-suggestions.rs:7:1
33
|
4-
LL | type Type;
5-
| --------- `Type` from trait
6-
LL | fn bar<T>(_: T) -> Self;
7-
| ------------------------ `bar` from trait
8-
LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
9-
| ------------------------------------------------------------------- `baz` from trait
10-
...
114
LL | impl TraitA<()> for S {
12-
| ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz` in implementation
5+
| ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz`, `A` in implementation
6+
|
7+
= help: implement the missing item: `type Type = /* Type */;`
8+
= help: implement the missing item: `fn bar<T>(_: T) -> Self { todo!() }`
9+
= help: implement the missing item: `fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }`
10+
= help: implement the missing item: `const A: usize = 42;`
1311

1412
error: aborting due to previous error
1513

tests/ui/suggestions/missing-assoc-fn.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter`
2828
LL | impl FromIterator<()> for X {
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation
3030
|
31-
= help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = A { todo!() }`
31+
= help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = () { todo!() }`
3232

3333
error: aborting due to 3 previous errors
3434

0 commit comments

Comments
 (0)