mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
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.
This commit is contained in:
parent
215f2d3294
commit
730c6f3e57
@ -1000,12 +1000,11 @@ trait InferCtxtPrivExt<'tcx> {
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
);
|
||||
|
||||
fn mk_obligation_for_def_id(
|
||||
fn mk_trait_obligation_with_new_self_ty(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
output_ty: Ty<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
new_self_ty: Ty<'tcx>,
|
||||
) -> PredicateObligation<'tcx>;
|
||||
|
||||
fn maybe_report_ambiguity(
|
||||
@ -1380,16 +1379,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_obligation_for_def_id(
|
||||
fn mk_trait_obligation_with_new_self_ty(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
output_ty: Ty<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
new_self_ty: Ty<'tcx>,
|
||||
) -> PredicateObligation<'tcx> {
|
||||
let new_trait_ref =
|
||||
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
|
||||
Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate(self.tcx))
|
||||
let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef {
|
||||
substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]),
|
||||
..*tr
|
||||
});
|
||||
|
||||
Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
trait_ref.without_const().to_predicate(self.tcx),
|
||||
)
|
||||
}
|
||||
|
||||
fn maybe_report_ambiguity(
|
||||
|
@ -532,14 +532,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
let msg = format!("use parentheses to call the {}", callable);
|
||||
|
||||
let obligation = self.mk_obligation_for_def_id(
|
||||
trait_ref.def_id(),
|
||||
output_ty.skip_binder(),
|
||||
obligation.cause.clone(),
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
output_ty.skip_binder(),
|
||||
);
|
||||
|
||||
match self.evaluate_obligation(&obligation) {
|
||||
match self.evaluate_obligation(&new_obligation) {
|
||||
Ok(
|
||||
EvaluationResult::EvaluatedToOk
|
||||
| EvaluationResult::EvaluatedToOkModuloRegions
|
||||
@ -694,7 +693,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
|
||||
) {
|
||||
let trait_ref = trait_ref.skip_binder();
|
||||
let span = obligation.cause.span;
|
||||
|
||||
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> {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut trait_type = trait_ref.self_ty();
|
||||
let mut suggested_ty = trait_ref.self_ty();
|
||||
|
||||
for refs_remaining in 0..refs_number {
|
||||
if let ty::Ref(_, t_type, _) = trait_type.kind {
|
||||
trait_type = t_type;
|
||||
if let ty::Ref(_, inner_ty, _) = suggested_ty.kind {
|
||||
suggested_ty = inner_ty;
|
||||
|
||||
let new_obligation = self.mk_obligation_for_def_id(
|
||||
trait_ref.def_id,
|
||||
trait_type,
|
||||
ObligationCause::dummy(),
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
suggested_ty,
|
||||
);
|
||||
|
||||
if self.predicate_may_hold(&new_obligation) {
|
||||
@ -782,20 +779,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let trait_type = match mutability {
|
||||
let suggested_ty = match mutability {
|
||||
hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
|
||||
hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
|
||||
};
|
||||
|
||||
let new_obligation = self.mk_obligation_for_def_id(
|
||||
trait_ref.skip_binder().def_id,
|
||||
trait_type,
|
||||
ObligationCause::dummy(),
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
&trait_ref,
|
||||
suggested_ty,
|
||||
);
|
||||
|
||||
if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
|
||||
{
|
||||
let suggested_ty_would_satisfy_obligation = self
|
||||
.evaluate_obligation_no_overflow(&new_obligation)
|
||||
.must_apply_modulo_regions();
|
||||
if suggested_ty_would_satisfy_obligation {
|
||||
let sp = self
|
||||
.tcx
|
||||
.sess
|
||||
@ -812,7 +809,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
err.note(&format!(
|
||||
"`{}` is implemented for `{:?}`, but not for `{:?}`",
|
||||
trait_ref.print_only_trait_path(),
|
||||
trait_type,
|
||||
suggested_ty,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user