Skip to content

Commit 3a863e5

Browse files
Consolidate the 'match assumption' type methods in GoalKind
1 parent 0dbaae4 commit 3a863e5

File tree

3 files changed

+47
-140
lines changed

3 files changed

+47
-140
lines changed

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ pub(super) trait GoalKind<'tcx>:
9999

100100
fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
101101

102+
// Try equating an assumption predicate against a goal's predicate. If it
103+
// holds, then execute the `then` callback, which should do any additional
104+
// work, then produce a response (typically by executing
105+
// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
106+
fn probe_and_match_goal_against_assumption(
107+
ecx: &mut EvalCtxt<'_, 'tcx>,
108+
goal: Goal<'tcx, Self>,
109+
assumption: ty::Predicate<'tcx>,
110+
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
111+
) -> QueryResult<'tcx>;
112+
102113
// Consider a clause, which consists of a "assumption" and some "requirements",
103114
// to satisfy a goal. If the requirements hold, then attempt to satisfy our
104115
// goal by equating it with the assumption.
@@ -107,7 +118,12 @@ pub(super) trait GoalKind<'tcx>:
107118
goal: Goal<'tcx, Self>,
108119
assumption: ty::Predicate<'tcx>,
109120
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
110-
) -> QueryResult<'tcx>;
121+
) -> QueryResult<'tcx> {
122+
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
123+
ecx.add_goals(requirements);
124+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
125+
})
126+
}
111127

112128
/// Consider a bound originating from the item bounds of an alias. For this we
113129
/// require that the well-formed requirements of the self type of the goal
@@ -117,7 +133,11 @@ pub(super) trait GoalKind<'tcx>:
117133
ecx: &mut EvalCtxt<'_, 'tcx>,
118134
goal: Goal<'tcx, Self>,
119135
assumption: ty::Predicate<'tcx>,
120-
) -> QueryResult<'tcx>;
136+
) -> QueryResult<'tcx> {
137+
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
138+
ecx.validate_alias_bound_self_from_param_env(goal)
139+
})
140+
}
121141

122142
// Consider a clause specifically for a `dyn Trait` self type. This requires
123143
// additionally checking all of the supertraits and object bounds to hold,
@@ -126,7 +146,25 @@ pub(super) trait GoalKind<'tcx>:
126146
ecx: &mut EvalCtxt<'_, 'tcx>,
127147
goal: Goal<'tcx, Self>,
128148
assumption: ty::Predicate<'tcx>,
129-
) -> QueryResult<'tcx>;
149+
) -> QueryResult<'tcx> {
150+
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
151+
let tcx = ecx.tcx();
152+
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
153+
bug!("expected object type in `consider_object_bound_candidate`");
154+
};
155+
ecx.add_goals(
156+
structural_traits::predicates_for_object_candidate(
157+
&ecx,
158+
goal.param_env,
159+
goal.predicate.trait_ref(tcx),
160+
bounds,
161+
)
162+
.into_iter()
163+
.map(|pred| goal.with(tcx, pred)),
164+
);
165+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
166+
})
167+
}
130168

131169
fn consider_impl_candidate(
132170
ecx: &mut EvalCtxt<'_, 'tcx>,

compiler/rustc_trait_selection/src/solve/project_goals.rs

+3-69
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
5656
self.trait_def_id(tcx)
5757
}
5858

59-
fn consider_implied_clause(
59+
fn probe_and_match_goal_against_assumption(
6060
ecx: &mut EvalCtxt<'_, 'tcx>,
6161
goal: Goal<'tcx, Self>,
6262
assumption: ty::Predicate<'tcx>,
63-
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
63+
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
6464
) -> QueryResult<'tcx> {
6565
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
6666
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
@@ -75,73 +75,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
7575
)?;
7676
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
7777
.expect("expected goal term to be fully unconstrained");
78-
ecx.add_goals(requirements);
79-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
80-
})
81-
} else {
82-
Err(NoSolution)
83-
}
84-
}
85-
86-
fn consider_alias_bound_candidate(
87-
ecx: &mut EvalCtxt<'_, 'tcx>,
88-
goal: Goal<'tcx, Self>,
89-
assumption: ty::Predicate<'tcx>,
90-
) -> QueryResult<'tcx> {
91-
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
92-
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
93-
{
94-
ecx.probe(|ecx| {
95-
let assumption_projection_pred =
96-
ecx.instantiate_binder_with_infer(poly_projection_pred);
97-
ecx.eq(
98-
goal.param_env,
99-
goal.predicate.projection_ty,
100-
assumption_projection_pred.projection_ty,
101-
)?;
102-
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)?;
103-
ecx.validate_alias_bound_self_from_param_env(goal)
104-
})
105-
} else {
106-
Err(NoSolution)
107-
}
108-
}
109-
110-
fn consider_object_bound_candidate(
111-
ecx: &mut EvalCtxt<'_, 'tcx>,
112-
goal: Goal<'tcx, Self>,
113-
assumption: ty::Predicate<'tcx>,
114-
) -> QueryResult<'tcx> {
115-
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
116-
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
117-
{
118-
ecx.probe(|ecx| {
119-
let tcx = ecx.tcx();
120-
121-
let assumption_projection_pred =
122-
ecx.instantiate_binder_with_infer(poly_projection_pred);
123-
ecx.eq(
124-
goal.param_env,
125-
goal.predicate.projection_ty,
126-
assumption_projection_pred.projection_ty,
127-
)?;
128-
129-
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
130-
bug!("expected object type in `consider_object_bound_candidate`");
131-
};
132-
ecx.add_goals(
133-
structural_traits::predicates_for_object_candidate(
134-
&ecx,
135-
goal.param_env,
136-
goal.predicate.projection_ty.trait_ref(tcx),
137-
bounds,
138-
)
139-
.into_iter()
140-
.map(|pred| goal.with(tcx, pred)),
141-
);
142-
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
143-
.expect("expected goal term to be fully unconstrained");
144-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
78+
then(ecx)
14579
})
14680
} else {
14781
Err(NoSolution)

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+3-68
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
7878
})
7979
}
8080

81-
fn consider_implied_clause(
81+
fn probe_and_match_goal_against_assumption(
8282
ecx: &mut EvalCtxt<'_, 'tcx>,
8383
goal: Goal<'tcx, Self>,
8484
assumption: ty::Predicate<'tcx>,
85-
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
85+
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
8686
) -> QueryResult<'tcx> {
8787
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
8888
&& poly_trait_pred.def_id() == goal.predicate.def_id()
@@ -97,72 +97,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
9797
goal.predicate.trait_ref,
9898
assumption_trait_pred.trait_ref,
9999
)?;
100-
ecx.add_goals(requirements);
101-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
102-
})
103-
} else {
104-
Err(NoSolution)
105-
}
106-
}
107-
108-
fn consider_alias_bound_candidate(
109-
ecx: &mut EvalCtxt<'_, 'tcx>,
110-
goal: Goal<'tcx, Self>,
111-
assumption: ty::Predicate<'tcx>,
112-
) -> QueryResult<'tcx> {
113-
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
114-
&& poly_trait_pred.def_id() == goal.predicate.def_id()
115-
{
116-
// FIXME: Constness and polarity
117-
ecx.probe(|ecx| {
118-
let assumption_trait_pred =
119-
ecx.instantiate_binder_with_infer(poly_trait_pred);
120-
ecx.eq(
121-
goal.param_env,
122-
goal.predicate.trait_ref,
123-
assumption_trait_pred.trait_ref,
124-
)?;
125-
ecx.validate_alias_bound_self_from_param_env(goal)
126-
})
127-
} else {
128-
Err(NoSolution)
129-
}
130-
}
131-
132-
fn consider_object_bound_candidate(
133-
ecx: &mut EvalCtxt<'_, 'tcx>,
134-
goal: Goal<'tcx, Self>,
135-
assumption: ty::Predicate<'tcx>,
136-
) -> QueryResult<'tcx> {
137-
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
138-
&& poly_trait_pred.def_id() == goal.predicate.def_id()
139-
&& poly_trait_pred.polarity() == goal.predicate.polarity
140-
{
141-
// FIXME: Constness and polarity
142-
ecx.probe(|ecx| {
143-
let assumption_trait_pred =
144-
ecx.instantiate_binder_with_infer(poly_trait_pred);
145-
ecx.eq(
146-
goal.param_env,
147-
goal.predicate.trait_ref,
148-
assumption_trait_pred.trait_ref,
149-
)?;
150-
151-
let tcx = ecx.tcx();
152-
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
153-
bug!("expected object type in `consider_object_bound_candidate`");
154-
};
155-
ecx.add_goals(
156-
structural_traits::predicates_for_object_candidate(
157-
&ecx,
158-
goal.param_env,
159-
goal.predicate.trait_ref,
160-
bounds,
161-
)
162-
.into_iter()
163-
.map(|pred| goal.with(tcx, pred)),
164-
);
165-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
100+
then(ecx)
166101
})
167102
} else {
168103
Err(NoSolution)

0 commit comments

Comments
 (0)