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

Commit 4fb097a

Browse files
Instantiate binders when checking supertrait upcasting
1 parent d4ee408 commit 4fb097a

File tree

4 files changed

+132
-48
lines changed

4 files changed

+132
-48
lines changed

compiler/rustc_infer/src/infer/at.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,24 @@ impl<'a, 'tcx> At<'a, 'tcx> {
159159
ToTrace::to_trace(self.cause, true, expected, actual),
160160
self.param_env,
161161
define_opaque_types,
162-
);
162+
ToTrace::to_trace(self.cause, expected, actual),
163+
expected,
164+
actual,
165+
)
166+
}
167+
168+
/// Makes `expected == actual`.
169+
pub fn eq_trace<T>(
170+
self,
171+
define_opaque_types: DefineOpaqueTypes,
172+
trace: TypeTrace<'tcx>,
173+
expected: T,
174+
actual: T,
175+
) -> InferResult<'tcx, ()>
176+
where
177+
T: Relate<TyCtxt<'tcx>>,
178+
{
179+
let mut fields = CombineFields::new(self.infcx, trace, self.param_env, define_opaque_types);
163180
fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?;
164181
Ok(InferOk {
165182
value: (),

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -448,10 +448,10 @@ where
448448
}
449449
}
450450
} else {
451-
self.delegate.enter_forall(kind, |kind| {
452-
let goal = goal.with(self.cx(), ty::Binder::dummy(kind));
453-
self.add_goal(GoalSource::InstantiateHigherRanked, goal);
454-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
451+
self.enter_forall(kind, |ecx, kind| {
452+
let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind));
453+
ecx.add_goal(GoalSource::InstantiateHigherRanked, goal);
454+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
455455
})
456456
}
457457
}
@@ -840,12 +840,14 @@ where
840840
self.delegate.instantiate_binder_with_infer(value)
841841
}
842842

843+
/// `enter_forall`, but takes `&mut self` and passes it back through the
844+
/// callback since it can't be aliased during the call.
843845
pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
844-
&self,
846+
&mut self,
845847
value: ty::Binder<I, T>,
846-
f: impl FnOnce(T) -> U,
848+
f: impl FnOnce(&mut Self, T) -> U,
847849
) -> U {
848-
self.delegate.enter_forall(value, f)
850+
self.delegate.enter_forall(value, |value| f(self, value))
849851
}
850852

851853
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -895,10 +895,13 @@ where
895895
source_projection.item_def_id() == target_projection.item_def_id()
896896
&& ecx
897897
.probe(|_| ProbeKind::UpcastProjectionCompatibility)
898-
.enter(|ecx| -> Result<(), NoSolution> {
899-
ecx.sub(param_env, source_projection, target_projection)?;
900-
let _ = ecx.try_evaluate_added_goals()?;
901-
Ok(())
898+
.enter(|ecx| -> Result<_, NoSolution> {
899+
ecx.enter_forall(target_projection, |ecx, target_projection| {
900+
let source_projection =
901+
ecx.instantiate_binder_with_infer(source_projection);
902+
ecx.eq(param_env, source_projection, target_projection)?;
903+
ecx.try_evaluate_added_goals()
904+
})
902905
})
903906
.is_ok()
904907
};
@@ -909,11 +912,14 @@ where
909912
// Check that a's supertrait (upcast_principal) is compatible
910913
// with the target (b_ty).
911914
ty::ExistentialPredicate::Trait(target_principal) => {
912-
ecx.sub(
913-
param_env,
914-
upcast_principal.unwrap(),
915-
bound.rebind(target_principal),
916-
)?;
915+
let source_principal = upcast_principal.unwrap();
916+
let target_principal = bound.rebind(target_principal);
917+
ecx.enter_forall(target_principal, |ecx, target_principal| {
918+
let source_principal =
919+
ecx.instantiate_binder_with_infer(source_principal);
920+
ecx.eq(param_env, source_principal, target_principal)?;
921+
ecx.try_evaluate_added_goals()
922+
})?;
917923
}
918924
// Check that b_ty's projection is satisfied by exactly one of
919925
// a_ty's projections. First, we look through the list to see if
@@ -934,7 +940,12 @@ where
934940
Certainty::AMBIGUOUS,
935941
);
936942
}
937-
ecx.sub(param_env, source_projection, target_projection)?;
943+
ecx.enter_forall(target_projection, |ecx, target_projection| {
944+
let source_projection =
945+
ecx.instantiate_binder_with_infer(source_projection);
946+
ecx.eq(param_env, source_projection, target_projection)?;
947+
ecx.try_evaluate_added_goals()
948+
})?;
938949
}
939950
// Check that b_ty's auto traits are present in a_ty's bounds.
940951
ty::ExistentialPredicate::AutoTrait(def_id) => {
@@ -1187,17 +1198,15 @@ where
11871198
) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>,
11881199
) -> Result<Candidate<I>, NoSolution> {
11891200
self.probe_trait_candidate(source).enter(|ecx| {
1190-
ecx.add_goals(
1191-
GoalSource::ImplWhereBound,
1192-
constituent_tys(ecx, goal.predicate.self_ty())?
1193-
.into_iter()
1194-
.map(|ty| {
1195-
ecx.enter_forall(ty, |ty| {
1196-
goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty))
1197-
})
1201+
let goals = constituent_tys(ecx, goal.predicate.self_ty())?
1202+
.into_iter()
1203+
.map(|ty| {
1204+
ecx.enter_forall(ty, |ecx, ty| {
1205+
goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty))
11981206
})
1199-
.collect::<Vec<_>>(),
1200-
);
1207+
})
1208+
.collect::<Vec<_>>();
1209+
ecx.add_goals(GoalSource::ImplWhereBound, goals);
12011210
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
12021211
})
12031212
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::LangItem;
1616
use rustc_hir::def_id::DefId;
1717
use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType};
1818
use rustc_infer::infer::DefineOpaqueTypes;
19+
use rustc_infer::infer::at::ToTrace;
1920
use rustc_infer::infer::relate::TypeRelation;
2021
use rustc_infer::traits::TraitObligation;
2122
use rustc_middle::bug;
@@ -44,7 +45,7 @@ use super::{
4445
TraitQueryMode, const_evaluatable, project, util, wf,
4546
};
4647
use crate::error_reporting::InferCtxtErrorExt;
47-
use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
48+
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
4849
use crate::solve::InferCtxtSelectExt as _;
4950
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
5051
use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
@@ -2579,16 +2580,32 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25792580
// Check that a_ty's supertrait (upcast_principal) is compatible
25802581
// with the target (b_ty).
25812582
ty::ExistentialPredicate::Trait(target_principal) => {
2583+
let hr_source_principal = upcast_principal.map_bound(|trait_ref| {
2584+
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
2585+
});
2586+
let hr_target_principal = bound.rebind(target_principal);
2587+
25822588
nested.extend(
25832589
self.infcx
2584-
.at(&obligation.cause, obligation.param_env)
2585-
.sup(
2586-
DefineOpaqueTypes::Yes,
2587-
bound.rebind(target_principal),
2588-
upcast_principal.map_bound(|trait_ref| {
2589-
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
2590-
}),
2591-
)
2590+
.enter_forall(hr_target_principal, |target_principal| {
2591+
let source_principal =
2592+
self.infcx.instantiate_binder_with_fresh_vars(
2593+
obligation.cause.span,
2594+
HigherRankedType,
2595+
hr_source_principal,
2596+
);
2597+
self.infcx.at(&obligation.cause, obligation.param_env).eq_trace(
2598+
DefineOpaqueTypes::Yes,
2599+
ToTrace::to_trace(
2600+
&obligation.cause,
2601+
true,
2602+
hr_target_principal,
2603+
hr_source_principal,
2604+
),
2605+
target_principal,
2606+
source_principal,
2607+
)
2608+
})
25922609
.map_err(|_| SelectionError::Unimplemented)?
25932610
.into_obligations(),
25942611
);
@@ -2599,28 +2616,67 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25992616
// return ambiguity. Otherwise, if exactly one matches, equate
26002617
// it with b_ty's projection.
26012618
ty::ExistentialPredicate::Projection(target_projection) => {
2602-
let target_projection = bound.rebind(target_projection);
2619+
let hr_target_projection = bound.rebind(target_projection);
2620+
26032621
let mut matching_projections =
2604-
a_data.projection_bounds().filter(|source_projection| {
2622+
a_data.projection_bounds().filter(|&hr_source_projection| {
26052623
// Eager normalization means that we can just use can_eq
26062624
// here instead of equating and processing obligations.
2607-
source_projection.item_def_id() == target_projection.item_def_id()
2608-
&& self.infcx.can_eq(
2609-
obligation.param_env,
2610-
*source_projection,
2611-
target_projection,
2612-
)
2625+
hr_source_projection.item_def_id() == hr_target_projection.item_def_id()
2626+
&& self.infcx.probe(|_| {
2627+
self.infcx
2628+
.enter_forall(hr_target_projection, |target_projection| {
2629+
let source_projection =
2630+
self.infcx.instantiate_binder_with_fresh_vars(
2631+
obligation.cause.span,
2632+
HigherRankedType,
2633+
hr_source_projection,
2634+
);
2635+
self.infcx
2636+
.at(&obligation.cause, obligation.param_env)
2637+
.eq_trace(
2638+
DefineOpaqueTypes::Yes,
2639+
ToTrace::to_trace(
2640+
&obligation.cause,
2641+
true,
2642+
hr_target_projection,
2643+
hr_source_projection,
2644+
),
2645+
target_projection,
2646+
source_projection,
2647+
)
2648+
})
2649+
.is_ok()
2650+
})
26132651
});
2614-
let Some(source_projection) = matching_projections.next() else {
2652+
2653+
let Some(hr_source_projection) = matching_projections.next() else {
26152654
return Err(SelectionError::Unimplemented);
26162655
};
26172656
if matching_projections.next().is_some() {
26182657
return Ok(None);
26192658
}
26202659
nested.extend(
26212660
self.infcx
2622-
.at(&obligation.cause, obligation.param_env)
2623-
.sup(DefineOpaqueTypes::Yes, target_projection, source_projection)
2661+
.enter_forall(hr_target_projection, |target_projection| {
2662+
let source_projection =
2663+
self.infcx.instantiate_binder_with_fresh_vars(
2664+
obligation.cause.span,
2665+
HigherRankedType,
2666+
hr_source_projection,
2667+
);
2668+
self.infcx.at(&obligation.cause, obligation.param_env).eq_trace(
2669+
DefineOpaqueTypes::Yes,
2670+
ToTrace::to_trace(
2671+
&obligation.cause,
2672+
true,
2673+
hr_target_projection,
2674+
hr_source_projection,
2675+
),
2676+
target_projection,
2677+
source_projection,
2678+
)
2679+
})
26242680
.map_err(|_| SelectionError::Unimplemented)?
26252681
.into_obligations(),
26262682
);

0 commit comments

Comments
 (0)