]>
git.proxmox.com Git - rustc.git/blob - vendor/chalk-solve-0.14.0/src/infer.rs
1 use chalk_ir
::interner
::{HasInterner, Interner}
;
3 use chalk_ir
::{cast::Cast, fold::Fold}
;
4 use tracing
::{debug, instrument}
;
6 pub(crate) mod canonicalize
;
7 pub(crate) mod instantiate
;
11 pub(crate) mod ucanonicalize
;
18 pub(crate) struct InferenceTable
<I
: Interner
> {
19 unify
: ena
::unify
::InPlaceUnificationTable
<EnaVariable
<I
>>,
20 vars
: Vec
<EnaVariable
<I
>>,
21 max_universe
: UniverseIndex
,
24 pub(crate) struct InferenceSnapshot
<I
: Interner
> {
25 unify_snapshot
: ena
::unify
::Snapshot
<ena
::unify
::InPlace
<EnaVariable
<I
>>>,
26 max_universe
: UniverseIndex
,
27 vars
: Vec
<EnaVariable
<I
>>,
30 #[allow(type_alias_bounds)]
31 pub(crate) type ParameterEnaVariable
<I
: Interner
> = WithKind
<I
, EnaVariable
<I
>>;
33 impl<I
: Interner
> InferenceTable
<I
> {
34 /// Create an empty inference table with no variables.
35 pub(crate) fn new() -> Self {
37 unify
: ena
::unify
::UnificationTable
::new(),
39 max_universe
: UniverseIndex
::root(),
43 /// Creates a new inference table, pre-populated with
44 /// `num_universes` fresh universes. Instantiates the canonical
45 /// value `canonical` within those universes (which must not
46 /// reference any universe greater than `num_universes`). Returns
47 /// the substitution mapping from each canonical binder to its
48 /// corresponding existential variable, along with the
49 /// instantiated result.
50 pub(crate) fn from_canonical
<T
>(
53 canonical
: &Canonical
<T
>,
54 ) -> (Self, Substitution
<I
>, T
)
56 T
: HasInterner
<Interner
= I
> + Fold
<I
, Result
= T
> + Clone
,
58 let mut table
= InferenceTable
::new();
60 assert
!(num_universes
>= 1); // always have U0
61 for _
in 1..num_universes
{
65 let subst
= table
.fresh_subst(interner
, canonical
.binders
.as_slice(interner
));
66 let value
= subst
.apply(&canonical
.value
, interner
);
67 // let value = canonical.value.fold_with(&mut &subst, 0).unwrap();
72 /// Creates and returns a fresh universe that is distinct from all
73 /// others created within this inference table. This universe is
74 /// able to see all previously created universes (though hopefully
75 /// it is only brought into contact with its logical *parents*).
76 pub(crate) fn new_universe(&mut self) -> UniverseIndex
{
77 let u
= self.max_universe
.next();
78 self.max_universe
= u
;
79 debug
!("new_universe: {:?}", u
);
83 /// Creates a new inference variable and returns its index. The
84 /// kind of the variable should be known by the caller, but is not
85 /// tracked directly by the inference table.
86 pub(crate) fn new_variable(&mut self, ui
: UniverseIndex
) -> EnaVariable
<I
> {
87 let var
= self.unify
.new_key(InferenceValue
::Unbound(ui
));
89 debug
!("new_variable: var={:?} ui={:?}", var
, ui
);
93 /// Takes a "snapshot" of the current state of the inference
94 /// table. Later, you must invoke either `rollback_to` or
95 /// `commit` with that snapshot. Snapshots can be nested, but you
96 /// must respect a stack discipline (i.e., rollback or commit
97 /// snapshots in reverse order of that with which they were
99 pub(crate) fn snapshot(&mut self) -> InferenceSnapshot
<I
> {
100 let unify_snapshot
= self.unify
.snapshot();
101 let vars
= self.vars
.clone();
102 let max_universe
= self.max_universe
;
110 /// Restore the table to the state it had when the snapshot was taken.
111 pub(crate) fn rollback_to(&mut self, snapshot
: InferenceSnapshot
<I
>) {
112 self.unify
.rollback_to(snapshot
.unify_snapshot
);
113 self.vars
= snapshot
.vars
;
114 self.max_universe
= snapshot
.max_universe
;
117 /// Make permanent the changes made since the snapshot was taken.
118 pub(crate) fn commit(&mut self, snapshot
: InferenceSnapshot
<I
>) {
119 self.unify
.commit(snapshot
.unify_snapshot
);
122 pub(crate) fn normalize_ty_shallow(&mut self, interner
: &I
, leaf
: &Ty
<I
>) -> Option
<Ty
<I
>> {
123 self.probe_var(leaf
.inference_var(interner
)?
)
124 .map(|p
| p
.assert_ty_ref(interner
).clone())
127 pub(crate) fn normalize_lifetime_shallow(
131 ) -> Option
<Lifetime
<I
>> {
132 self.probe_var(leaf
.inference_var(interner
)?
)
133 .map(|p
| p
.assert_lifetime_ref(interner
).clone())
136 pub(crate) fn normalize_const_shallow(
140 ) -> Option
<Const
<I
>> {
141 self.probe_var(leaf
.inference_var(interner
)?
)
142 .map(|p
| p
.assert_const_ref(interner
).clone())
145 /// If type `leaf` is a free inference variable, and that variable has been
146 /// bound, returns `Some(P)` where `P` is the parameter to which it has been bound.
147 pub(crate) fn probe_var(&mut self, leaf
: InferenceVar
) -> Option
<GenericArg
<I
>> {
148 match self.unify
.probe_value(EnaVariable
::from(leaf
)) {
149 InferenceValue
::Unbound(_
) => None
,
150 InferenceValue
::Bound(val
) => Some(val
),
154 /// Given an unbound variable, returns its universe.
158 /// Panics if the variable is bound.
159 fn universe_of_unbound_var(&mut self, var
: EnaVariable
<I
>) -> UniverseIndex
{
160 match self.unify
.probe_value(var
) {
161 InferenceValue
::Unbound(ui
) => ui
,
162 InferenceValue
::Bound(_
) => panic
!("var_universe invoked on bound variable"),
167 pub(crate) trait ParameterEnaVariableExt
<I
: Interner
> {
168 fn to_generic_arg(&self, interner
: &I
) -> GenericArg
<I
>;
171 impl<I
: Interner
> ParameterEnaVariableExt
<I
> for ParameterEnaVariable
<I
> {
172 fn to_generic_arg(&self, interner
: &I
) -> GenericArg
<I
> {
173 // we are matching on kind, so skipping it is fine
174 let ena_variable
= self.skip_kind();
176 VariableKind
::Ty(kind
) => ena_variable
.to_ty_with_kind(interner
, *kind
).cast(interner
),
177 VariableKind
::Lifetime
=> ena_variable
.to_lifetime(interner
).cast(interner
),
178 VariableKind
::Const(ty
) => ena_variable
.to_const(interner
, ty
.clone()).cast(interner
),