Skip to content

Commit f99b273

Browse files
implement consider_assumption
1 parent b84b1da commit f99b273

File tree

3 files changed

+70
-10
lines changed

3 files changed

+70
-10
lines changed

compiler/rustc_trait_selection/src/solve/infcx_ext.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ pub(super) trait InferCtxtExt<'tcx> {
2525
lhs: T,
2626
rhs: T,
2727
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>;
28+
29+
fn sup<T: ToTrace<'tcx>>(
30+
&self,
31+
param_env: ty::ParamEnv<'tcx>,
32+
lhs: T,
33+
rhs: T,
34+
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>;
2835
}
2936

3037
impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
@@ -59,4 +66,23 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
5966
NoSolution
6067
})
6168
}
69+
70+
#[instrument(level = "debug", skip(self, param_env), ret)]
71+
fn sup<T: ToTrace<'tcx>>(
72+
&self,
73+
param_env: ty::ParamEnv<'tcx>,
74+
lhs: T,
75+
rhs: T,
76+
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
77+
self.at(&ObligationCause::dummy(), param_env)
78+
.define_opaque_types(false)
79+
.sup(lhs, rhs)
80+
.map(|InferOk { value: (), obligations }| {
81+
obligations.into_iter().map(|o| o.into()).collect()
82+
})
83+
.map_err(|e| {
84+
debug!(?e, "failed to sup");
85+
NoSolution
86+
})
87+
}
6288
}

compiler/rustc_trait_selection/src/solve/project_goals.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::DefId;
9-
use rustc_infer::infer::InferCtxt;
9+
use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
1010
use rustc_infer::traits::query::NoSolution;
1111
use rustc_infer::traits::specialization_graph::LeafDef;
1212
use rustc_infer::traits::Reveal;
@@ -298,12 +298,37 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
298298
}
299299

300300
fn consider_assumption(
301-
_ecx: &mut EvalCtxt<'_, 'tcx>,
302-
_goal: Goal<'tcx, Self>,
301+
ecx: &mut EvalCtxt<'_, 'tcx>,
302+
goal: Goal<'tcx, Self>,
303303
assumption: ty::Predicate<'tcx>,
304304
) -> QueryResult<'tcx> {
305-
if let Some(_poly_projection_pred) = assumption.to_opt_poly_projection_pred() {
306-
unimplemented!()
305+
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() {
306+
ecx.infcx.probe(|_| {
307+
let assumption_projection_pred = ecx.infcx.replace_bound_vars_with_fresh_vars(
308+
DUMMY_SP,
309+
LateBoundRegionConversionTime::HigherRankedType,
310+
poly_projection_pred,
311+
);
312+
let nested_goals = ecx.infcx.sup(
313+
goal.param_env,
314+
goal.predicate.projection_ty,
315+
assumption_projection_pred.projection_ty,
316+
)?;
317+
let subst_certainty = ecx.evaluate_all(nested_goals)?;
318+
319+
// The term of our goal should be fully unconstrained, so this should never fail.
320+
//
321+
// It can however be ambiguous when the resolved type is a projection.
322+
let nested_goals = ecx
323+
.infcx
324+
.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
325+
.expect("failed to unify with unconstrained term");
326+
let rhs_certainty = ecx
327+
.evaluate_all(nested_goals)
328+
.expect("failed to unify with unconstrained term");
329+
330+
ecx.make_canonical_response(subst_certainty.unify_and(rhs_certainty))
331+
})
307332
} else {
308333
Err(NoSolution)
309334
}

compiler/rustc_trait_selection/src/solve/trait_goals.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use super::assembly::{self, Candidate, CandidateSource};
66
use super::infcx_ext::InferCtxtExt;
77
use super::{EvalCtxt, Goal, QueryResult};
88
use rustc_hir::def_id::DefId;
9+
use rustc_infer::infer::LateBoundRegionConversionTime;
910
use rustc_infer::traits::query::NoSolution;
1011
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
11-
use rustc_middle::ty::TraitPredicate;
1212
use rustc_middle::ty::{self, Ty, TyCtxt};
13+
use rustc_middle::ty::{ToPolyTraitRef, TraitPredicate};
1314
use rustc_span::DUMMY_SP;
1415

1516
impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
@@ -65,12 +66,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
6566
}
6667

6768
fn consider_assumption(
68-
_ecx: &mut EvalCtxt<'_, 'tcx>,
69-
_goal: Goal<'tcx, Self>,
69+
ecx: &mut EvalCtxt<'_, 'tcx>,
70+
goal: Goal<'tcx, Self>,
7071
assumption: ty::Predicate<'tcx>,
7172
) -> QueryResult<'tcx> {
72-
if let Some(_poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
73-
unimplemented!()
73+
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
74+
// FIXME: Constness and polarity
75+
ecx.infcx.probe(|_| {
76+
let nested_goals = ecx.infcx.sup(
77+
goal.param_env,
78+
ty::Binder::dummy(goal.predicate.trait_ref),
79+
poly_trait_pred.to_poly_trait_ref(),
80+
)?;
81+
ecx.evaluate_all_and_make_canonical_response(nested_goals)
82+
})
7483
} else {
7584
Err(NoSolution)
7685
}

0 commit comments

Comments
 (0)