Skip to content

Commit 67698aa

Browse files
Move some solver stuff to middle
1 parent ff4b772 commit 67698aa

File tree

10 files changed

+118
-103
lines changed

10 files changed

+118
-103
lines changed

compiler/rustc_infer/src/traits/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ pub struct Obligation<'tcx, T> {
5353
pub recursion_depth: usize,
5454
}
5555

56+
impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
57+
fn from(value: Obligation<'tcx, P>) -> Self {
58+
solve::Goal { param_env: value.param_env, predicate: value.predicate }
59+
}
60+
}
61+
5662
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
5763
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
5864

compiler/rustc_middle/src/traits/solve.rs

+94-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,104 @@
11
use std::ops::ControlFlow;
22

33
use rustc_data_structures::intern::Interned;
4+
use rustc_query_system::cache::Cache;
45

5-
use crate::infer::canonical::QueryRegionConstraints;
6+
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
7+
use crate::traits::query::NoSolution;
8+
use crate::traits::Canonical;
69
use crate::ty::{
7-
FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
10+
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
11+
TypeVisitor,
812
};
913

14+
pub type EvaluationCache<'tcx> = Cache<CanonicalGoal<'tcx>, QueryResult<'tcx>>;
15+
16+
/// A goal is a statement, i.e. `predicate`, we want to prove
17+
/// given some assumptions, i.e. `param_env`.
18+
///
19+
/// Most of the time the `param_env` contains the `where`-bounds of the function
20+
/// we're currently typechecking while the `predicate` is some trait bound.
21+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
22+
pub struct Goal<'tcx, P> {
23+
pub param_env: ty::ParamEnv<'tcx>,
24+
pub predicate: P,
25+
}
26+
27+
impl<'tcx, P> Goal<'tcx, P> {
28+
pub fn new(
29+
tcx: TyCtxt<'tcx>,
30+
param_env: ty::ParamEnv<'tcx>,
31+
predicate: impl ToPredicate<'tcx, P>,
32+
) -> Goal<'tcx, P> {
33+
Goal { param_env, predicate: predicate.to_predicate(tcx) }
34+
}
35+
36+
/// Updates the goal to one with a different `predicate` but the same `param_env`.
37+
pub fn with<Q>(self, tcx: TyCtxt<'tcx>, predicate: impl ToPredicate<'tcx, Q>) -> Goal<'tcx, Q> {
38+
Goal { param_env: self.param_env, predicate: predicate.to_predicate(tcx) }
39+
}
40+
}
41+
42+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
43+
pub struct Response<'tcx> {
44+
pub var_values: CanonicalVarValues<'tcx>,
45+
/// Additional constraints returned by this query.
46+
pub external_constraints: ExternalConstraints<'tcx>,
47+
pub certainty: Certainty,
48+
}
49+
50+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
51+
pub enum Certainty {
52+
Yes,
53+
Maybe(MaybeCause),
54+
}
55+
56+
impl Certainty {
57+
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
58+
59+
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
60+
/// use this function to unify the certainty of these goals
61+
pub fn unify_and(self, other: Certainty) -> Certainty {
62+
match (self, other) {
63+
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
64+
(Certainty::Yes, Certainty::Maybe(_)) => other,
65+
(Certainty::Maybe(_), Certainty::Yes) => self,
66+
(Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Overflow)) => {
67+
Certainty::Maybe(MaybeCause::Overflow)
68+
}
69+
// If at least one of the goals is ambiguous, hide the overflow as the ambiguous goal
70+
// may still result in failure.
71+
(Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(_))
72+
| (Certainty::Maybe(_), Certainty::Maybe(MaybeCause::Ambiguity)) => {
73+
Certainty::Maybe(MaybeCause::Ambiguity)
74+
}
75+
}
76+
}
77+
}
78+
79+
/// Why we failed to evaluate a goal.
80+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
81+
pub enum MaybeCause {
82+
/// We failed due to ambiguity. This ambiguity can either
83+
/// be a true ambiguity, i.e. there are multiple different answers,
84+
/// or we hit a case where we just don't bother, e.g. `?x: Trait` goals.
85+
Ambiguity,
86+
/// We gave up due to an overflow, most often by hitting the recursion limit.
87+
Overflow,
88+
}
89+
90+
pub type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
91+
92+
pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
93+
94+
/// The result of evaluating a canonical query.
95+
///
96+
/// FIXME: We use a different type than the existing canonical queries. This is because
97+
/// we need to add a `Certainty` for `overflow` and may want to restructure this code without
98+
/// having to worry about changes to currently used code. Once we've made progress on this
99+
/// solver, merge the two responses again.
100+
pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
101+
10102
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
11103
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
12104

compiler/rustc_trait_selection/src/solve/assembly.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
33
#[cfg(doc)]
44
use super::trait_goals::structural_traits::*;
5-
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
5+
use super::EvalCtxt;
66
use itertools::Itertools;
77
use rustc_hir::def_id::DefId;
88
use rustc_infer::traits::query::NoSolution;
99
use rustc_infer::traits::util::elaborate_predicates;
10+
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
1011
use rustc_middle::ty::TypeFoldable;
1112
use rustc_middle::ty::{self, Ty, TyCtxt};
1213
use std::fmt::Debug;

compiler/rustc_trait_selection/src/solve/mod.rs

+5-92
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ use rustc_hir::def_id::DefId;
2121
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
2222
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
2323
use rustc_infer::traits::query::NoSolution;
24-
use rustc_infer::traits::Obligation;
25-
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
24+
use rustc_middle::traits::solve::{
25+
CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData,
26+
Goal, MaybeCause, QueryResult, Response,
27+
};
2628
use rustc_middle::ty::{self, Ty, TyCtxt};
2729
use rustc_middle::ty::{
28-
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
30+
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
2931
};
3032
use rustc_span::DUMMY_SP;
3133

@@ -43,45 +45,6 @@ mod trait_goals;
4345
pub use eval_ctxt::EvalCtxt;
4446
pub use fulfill::FulfillmentCtxt;
4547

46-
/// A goal is a statement, i.e. `predicate`, we want to prove
47-
/// given some assumptions, i.e. `param_env`.
48-
///
49-
/// Most of the time the `param_env` contains the `where`-bounds of the function
50-
/// we're currently typechecking while the `predicate` is some trait bound.
51-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
52-
pub struct Goal<'tcx, P> {
53-
param_env: ty::ParamEnv<'tcx>,
54-
predicate: P,
55-
}
56-
57-
impl<'tcx, P> Goal<'tcx, P> {
58-
pub fn new(
59-
tcx: TyCtxt<'tcx>,
60-
param_env: ty::ParamEnv<'tcx>,
61-
predicate: impl ToPredicate<'tcx, P>,
62-
) -> Goal<'tcx, P> {
63-
Goal { param_env, predicate: predicate.to_predicate(tcx) }
64-
}
65-
66-
/// Updates the goal to one with a different `predicate` but the same `param_env`.
67-
fn with<Q>(self, tcx: TyCtxt<'tcx>, predicate: impl ToPredicate<'tcx, Q>) -> Goal<'tcx, Q> {
68-
Goal { param_env: self.param_env, predicate: predicate.to_predicate(tcx) }
69-
}
70-
}
71-
72-
impl<'tcx, P> From<Obligation<'tcx, P>> for Goal<'tcx, P> {
73-
fn from(obligation: Obligation<'tcx, P>) -> Goal<'tcx, P> {
74-
Goal { param_env: obligation.param_env, predicate: obligation.predicate }
75-
}
76-
}
77-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
78-
pub struct Response<'tcx> {
79-
pub var_values: CanonicalVarValues<'tcx>,
80-
/// Additional constraints returned by this query.
81-
pub external_constraints: ExternalConstraints<'tcx>,
82-
pub certainty: Certainty,
83-
}
84-
8548
trait CanonicalResponseExt {
8649
fn has_no_inference_or_external_constraints(&self) -> bool;
8750
}
@@ -94,56 +57,6 @@ impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
9457
}
9558
}
9659

97-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
98-
pub enum Certainty {
99-
Yes,
100-
Maybe(MaybeCause),
101-
}
102-
103-
impl Certainty {
104-
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
105-
106-
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
107-
/// use this function to unify the certainty of these goals
108-
pub fn unify_and(self, other: Certainty) -> Certainty {
109-
match (self, other) {
110-
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
111-
(Certainty::Yes, Certainty::Maybe(_)) => other,
112-
(Certainty::Maybe(_), Certainty::Yes) => self,
113-
(Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Overflow)) => {
114-
Certainty::Maybe(MaybeCause::Overflow)
115-
}
116-
// If at least one of the goals is ambiguous, hide the overflow as the ambiguous goal
117-
// may still result in failure.
118-
(Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(_))
119-
| (Certainty::Maybe(_), Certainty::Maybe(MaybeCause::Ambiguity)) => {
120-
Certainty::Maybe(MaybeCause::Ambiguity)
121-
}
122-
}
123-
}
124-
}
125-
126-
/// Why we failed to evaluate a goal.
127-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
128-
pub enum MaybeCause {
129-
/// We failed due to ambiguity. This ambiguity can either
130-
/// be a true ambiguity, i.e. there are multiple different answers,
131-
/// or we hit a case where we just don't bother, e.g. `?x: Trait` goals.
132-
Ambiguity,
133-
/// We gave up due to an overflow, most often by hitting the recursion limit.
134-
Overflow,
135-
}
136-
137-
type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
138-
type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
139-
/// The result of evaluating a canonical query.
140-
///
141-
/// FIXME: We use a different type than the existing canonical queries. This is because
142-
/// we need to add a `Certainty` for `overflow` and may want to restructure this code without
143-
/// having to worry about changes to currently used code. Once we've made progress on this
144-
/// solver, merge the two responses again.
145-
pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
146-
14760
pub trait InferCtxtEvalExt<'tcx> {
14861
/// Evaluates a goal from **outside** of the trait solver.
14962
///

compiler/rustc_trait_selection/src/solve/project_goals.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::traits::{specialization_graph, translate_substs};
22

33
use super::assembly;
44
use super::trait_goals::structural_traits;
5-
use super::{Certainty, EvalCtxt, Goal, QueryResult};
5+
use super::EvalCtxt;
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::DefId;
@@ -11,6 +11,7 @@ use rustc_infer::infer::InferCtxt;
1111
use rustc_infer::traits::query::NoSolution;
1212
use rustc_infer::traits::specialization_graph::LeafDef;
1313
use rustc_infer::traits::Reveal;
14+
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
1415
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1516
use rustc_middle::ty::ProjectionPredicate;
1617
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -512,7 +513,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
512513
fn consider_builtin_dyn_upcast_candidates(
513514
_ecx: &mut EvalCtxt<'_, 'tcx>,
514515
goal: Goal<'tcx, Self>,
515-
) -> Vec<super::CanonicalResponse<'tcx>> {
516+
) -> Vec<CanonicalResponse<'tcx>> {
516517
bug!("`Unsize` does not have an associated type: {:?}", goal);
517518
}
518519

compiler/rustc_trait_selection/src/solve/search_graph/cache.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
//! before then or if I still haven't done that before January 2023.
1111
use super::overflow::OverflowData;
1212
use super::StackDepth;
13-
use crate::solve::{CanonicalGoal, QueryResult};
1413
use rustc_data_structures::fx::FxHashMap;
1514
use rustc_index::vec::IndexVec;
15+
use rustc_middle::traits::solve::{CanonicalGoal, QueryResult};
1616
use rustc_middle::ty::TyCtxt;
1717

1818
rustc_index::newtype_index! {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ mod cache;
22
mod overflow;
33

44
use self::cache::ProvisionalEntry;
5-
use super::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
65
pub(super) use crate::solve::search_graph::overflow::OverflowHandler;
76
use cache::ProvisionalCache;
87
use overflow::OverflowData;
98
use rustc_index::vec::IndexVec;
9+
use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
1010
use rustc_middle::ty::TyCtxt;
1111
use std::{collections::hash_map::Entry, mem};
1212

compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use rustc_infer::infer::canonical::Canonical;
22
use rustc_infer::traits::query::NoSolution;
3+
use rustc_middle::traits::solve::{Certainty, MaybeCause, QueryResult};
34
use rustc_middle::ty::TyCtxt;
45
use rustc_session::Limit;
56

67
use super::SearchGraph;
7-
use crate::solve::{response_no_constraints, Certainty, EvalCtxt, MaybeCause, QueryResult};
8+
use crate::solve::{response_no_constraints, EvalCtxt};
89

910
/// When detecting a solver overflow, we return ambiguity. Overflow can be
1011
/// *hidden* by either a fatal error in an **AND** or a trivial success in an **OR**.

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
33
use std::iter;
44

5-
use super::assembly;
6-
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
5+
use super::{assembly, EvalCtxt};
76
use rustc_hir::def_id::DefId;
87
use rustc_hir::LangItem;
98
use rustc_infer::traits::query::NoSolution;
109
use rustc_infer::traits::util::supertraits;
10+
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
1111
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1212
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
1313
use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};

compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause};
12
use rustc_middle::ty;
23
use rustc_session::config::TraitSolver;
34

45
use crate::infer::canonical::OriginalQueryValues;
56
use crate::infer::InferCtxt;
6-
use crate::solve::{Certainty, Goal, InferCtxtEvalExt, MaybeCause};
7+
use crate::solve::InferCtxtEvalExt;
78
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
89

910
pub trait InferCtxtExt<'tcx> {

0 commit comments

Comments
 (0)