Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 730c6f3

Browse files
Preserve substitutions when trying to prove trait obligation
`mk_obligation_for_def_id` is only correct if the trait and self type do not have any substitutions. Use a different method, `mk_trait_obligation_with_new_self_ty` that is more clear about what is happening.
1 parent 215f2d3 commit 730c6f3

File tree

2 files changed

+35
-33
lines changed

2 files changed

+35
-33
lines changed

src/librustc_trait_selection/traits/error_reporting/mod.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,12 +1000,11 @@ trait InferCtxtPrivExt<'tcx> {
10001000
trait_ref: &ty::PolyTraitRef<'tcx>,
10011001
);
10021002

1003-
fn mk_obligation_for_def_id(
1003+
fn mk_trait_obligation_with_new_self_ty(
10041004
&self,
1005-
def_id: DefId,
1006-
output_ty: Ty<'tcx>,
1007-
cause: ObligationCause<'tcx>,
10081005
param_env: ty::ParamEnv<'tcx>,
1006+
trait_ref: &ty::PolyTraitRef<'tcx>,
1007+
new_self_ty: Ty<'tcx>,
10091008
) -> PredicateObligation<'tcx>;
10101009

10111010
fn maybe_report_ambiguity(
@@ -1380,16 +1379,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
13801379
}
13811380
}
13821381

1383-
fn mk_obligation_for_def_id(
1382+
fn mk_trait_obligation_with_new_self_ty(
13841383
&self,
1385-
def_id: DefId,
1386-
output_ty: Ty<'tcx>,
1387-
cause: ObligationCause<'tcx>,
13881384
param_env: ty::ParamEnv<'tcx>,
1385+
trait_ref: &ty::PolyTraitRef<'tcx>,
1386+
new_self_ty: Ty<'tcx>,
13891387
) -> PredicateObligation<'tcx> {
1390-
let new_trait_ref =
1391-
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
1392-
Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate(self.tcx))
1388+
let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef {
1389+
substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]),
1390+
..*tr
1391+
});
1392+
1393+
Obligation::new(
1394+
ObligationCause::dummy(),
1395+
param_env,
1396+
trait_ref.without_const().to_predicate(self.tcx),
1397+
)
13931398
}
13941399

13951400
fn maybe_report_ambiguity(

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -532,14 +532,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
532532
};
533533
let msg = format!("use parentheses to call the {}", callable);
534534

535-
let obligation = self.mk_obligation_for_def_id(
536-
trait_ref.def_id(),
537-
output_ty.skip_binder(),
538-
obligation.cause.clone(),
535+
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
539536
obligation.param_env,
537+
trait_ref,
538+
output_ty.skip_binder(),
540539
);
541540

542-
match self.evaluate_obligation(&obligation) {
541+
match self.evaluate_obligation(&new_obligation) {
543542
Ok(
544543
EvaluationResult::EvaluatedToOk
545544
| EvaluationResult::EvaluatedToOkModuloRegions
@@ -694,7 +693,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
694693
err: &mut DiagnosticBuilder<'_>,
695694
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
696695
) {
697-
let trait_ref = trait_ref.skip_binder();
698696
let span = obligation.cause.span;
699697

700698
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -705,17 +703,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
705703
return;
706704
}
707705

708-
let mut trait_type = trait_ref.self_ty();
706+
let mut suggested_ty = trait_ref.self_ty();
709707

710708
for refs_remaining in 0..refs_number {
711-
if let ty::Ref(_, t_type, _) = trait_type.kind {
712-
trait_type = t_type;
709+
if let ty::Ref(_, inner_ty, _) = suggested_ty.kind {
710+
suggested_ty = inner_ty;
713711

714-
let new_obligation = self.mk_obligation_for_def_id(
715-
trait_ref.def_id,
716-
trait_type,
717-
ObligationCause::dummy(),
712+
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
718713
obligation.param_env,
714+
trait_ref,
715+
suggested_ty,
719716
);
720717

721718
if self.predicate_may_hold(&new_obligation) {
@@ -782,20 +779,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
782779
return;
783780
}
784781

785-
let trait_type = match mutability {
782+
let suggested_ty = match mutability {
786783
hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
787784
hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
788785
};
789786

790-
let new_obligation = self.mk_obligation_for_def_id(
791-
trait_ref.skip_binder().def_id,
792-
trait_type,
793-
ObligationCause::dummy(),
787+
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
794788
obligation.param_env,
789+
&trait_ref,
790+
suggested_ty,
795791
);
796-
797-
if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
798-
{
792+
let suggested_ty_would_satisfy_obligation = self
793+
.evaluate_obligation_no_overflow(&new_obligation)
794+
.must_apply_modulo_regions();
795+
if suggested_ty_would_satisfy_obligation {
799796
let sp = self
800797
.tcx
801798
.sess
@@ -812,7 +809,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
812809
err.note(&format!(
813810
"`{}` is implemented for `{:?}`, but not for `{:?}`",
814811
trait_ref.print_only_trait_path(),
815-
trait_type,
812+
suggested_ty,
816813
trait_ref.skip_binder().self_ty(),
817814
));
818815
}

0 commit comments

Comments
 (0)