Skip to content

Commit 204c516

Browse files
Substitute missing item suggestion correctly
1 parent de96f3d commit 204c516

File tree

5 files changed

+27
-12
lines changed

5 files changed

+27
-12
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: 23 additions & 8 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,9 +460,9 @@ 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
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | impl TryFrom<OtherStream> for MyStream {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation
66
|
77
= 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!() }`
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

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/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)