forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#117008 - compiler-errors:canonical, r=lcnr Uplift `Canonical` to `rustc_type_ir` I plan on moving the new trait solver's canonicalizer into either `rustc_type_ir` or a child crate. One dependency on this is lifting `Canonical<V>` to `rustc_type_ir` so we can actually name the canonicalized values. I may also later lift `CanonicalVarInfo` into the new trait solver. I can't really tell what other changes need to be done, but I'm just putting this up sooner than later since I'm almost certain it'll need to be done regardless of other design choices. There are a couple of warts introduced by this PR, since we no longer can define inherent `Canonical` impls in `rustc_middle` -- see the changes to: * `compiler/rustc_trait_selection/src/traits/query/normalize.rs` * `compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs` r? lcnr
- Loading branch information
Showing
13 changed files
with
207 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
use std::fmt; | ||
use std::hash; | ||
use std::ops::ControlFlow; | ||
|
||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; | ||
use rustc_serialize::{Decodable, Encodable}; | ||
|
||
use crate::fold::{FallibleTypeFolder, TypeFoldable}; | ||
use crate::visit::{TypeVisitable, TypeVisitor}; | ||
use crate::TyDecoder; | ||
use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex}; | ||
|
||
/// A "canonicalized" type `V` is one where all free inference | ||
/// variables have been rewritten to "canonical vars". These are | ||
/// numbered starting from 0 in order of first appearance. | ||
pub struct Canonical<I: Interner, V> { | ||
pub value: V, | ||
pub max_universe: UniverseIndex, | ||
pub variables: I::CanonicalVars, | ||
} | ||
|
||
impl<I: Interner, V> Canonical<I, V> { | ||
/// Allows you to map the `value` of a canonical while keeping the | ||
/// same set of bound variables. | ||
/// | ||
/// **WARNING:** This function is very easy to mis-use, hence the | ||
/// name! In particular, the new value `W` must use all **the | ||
/// same type/region variables** in **precisely the same order** | ||
/// as the original! (The ordering is defined by the | ||
/// `TypeFoldable` implementation of the type in question.) | ||
/// | ||
/// An example of a **correct** use of this: | ||
/// | ||
/// ```rust,ignore (not real code) | ||
/// let a: Canonical<I, T> = ...; | ||
/// let b: Canonical<I, (T,)> = a.unchecked_map(|v| (v, )); | ||
/// ``` | ||
/// | ||
/// An example of an **incorrect** use of this: | ||
/// | ||
/// ```rust,ignore (not real code) | ||
/// let a: Canonical<I, T> = ...; | ||
/// let ty: Ty<I> = ...; | ||
/// let b: Canonical<I, (T, Ty<I>)> = a.unchecked_map(|v| (v, ty)); | ||
/// ``` | ||
pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<I, W> { | ||
let Canonical { max_universe, variables, value } = self; | ||
Canonical { max_universe, variables, value: map_op(value) } | ||
} | ||
|
||
/// Allows you to map the `value` of a canonical while keeping the same set of | ||
/// bound variables. | ||
/// | ||
/// **WARNING:** This function is very easy to mis-use, hence the name! See | ||
/// the comment of [Canonical::unchecked_map] for more details. | ||
pub fn unchecked_rebind<W>(self, value: W) -> Canonical<I, W> { | ||
let Canonical { max_universe, variables, value: _ } = self; | ||
Canonical { max_universe, variables, value } | ||
} | ||
} | ||
|
||
impl<I: Interner, V: hash::Hash> hash::Hash for Canonical<I, V> { | ||
fn hash<H: hash::Hasher>(&self, state: &mut H) { | ||
self.value.hash(state); | ||
self.max_universe.hash(state); | ||
self.variables.hash(state); | ||
} | ||
} | ||
|
||
impl<CTX: HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX> for Canonical<I, V> | ||
where | ||
I::CanonicalVars: HashStable<CTX>, | ||
{ | ||
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { | ||
self.value.hash_stable(hcx, hasher); | ||
self.max_universe.hash_stable(hcx, hasher); | ||
self.variables.hash_stable(hcx, hasher); | ||
} | ||
} | ||
|
||
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {} | ||
|
||
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> { | ||
fn eq(&self, other: &Self) -> bool { | ||
self.value == other.value | ||
&& self.max_universe == other.max_universe | ||
&& self.variables == other.variables | ||
} | ||
} | ||
|
||
impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!( | ||
f, | ||
"Canonical {{ value: {}, max_universe: {:?}, variables: {:?} }}", | ||
self.value, self.max_universe, self.variables | ||
) | ||
} | ||
} | ||
|
||
impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("Canonical") | ||
.field("value", &self.value) | ||
.field("max_universe", &self.max_universe) | ||
.field("variables", &self.variables) | ||
.finish() | ||
} | ||
} | ||
|
||
impl<I: Interner, V: Clone> Clone for Canonical<I, V> { | ||
fn clone(&self) -> Self { | ||
Canonical { | ||
value: self.value.clone(), | ||
max_universe: self.max_universe.clone(), | ||
variables: self.variables.clone(), | ||
} | ||
} | ||
} | ||
|
||
impl<I: Interner, V: Copy> Copy for Canonical<I, V> where I::CanonicalVars: Copy {} | ||
|
||
impl<I: Interner, V: TypeFoldable<I>> TypeFoldable<I> for Canonical<I, V> | ||
where | ||
I::CanonicalVars: TypeFoldable<I>, | ||
{ | ||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> { | ||
Ok(Canonical { | ||
value: self.value.try_fold_with(folder)?, | ||
max_universe: self.max_universe.try_fold_with(folder)?, | ||
variables: self.variables.try_fold_with(folder)?, | ||
}) | ||
} | ||
} | ||
|
||
impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V> | ||
where | ||
I::CanonicalVars: TypeVisitable<I>, | ||
{ | ||
fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> ControlFlow<F::BreakTy> { | ||
self.value.visit_with(folder)?; | ||
self.max_universe.visit_with(folder)?; | ||
self.variables.visit_with(folder) | ||
} | ||
} | ||
|
||
impl<I: Interner, E: TyEncoder<I = I>, V: Encodable<E>> Encodable<E> for Canonical<I, V> | ||
where | ||
I::CanonicalVars: Encodable<E>, | ||
{ | ||
fn encode(&self, s: &mut E) { | ||
self.value.encode(s); | ||
self.max_universe.encode(s); | ||
self.variables.encode(s); | ||
} | ||
} | ||
|
||
impl<I: Interner, D: TyDecoder<I = I>, V: Decodable<D>> Decodable<D> for Canonical<I, V> | ||
where | ||
I::CanonicalVars: Decodable<D>, | ||
{ | ||
fn decode(d: &mut D) -> Self { | ||
Canonical { | ||
value: Decodable::decode(d), | ||
max_universe: Decodable::decode(d), | ||
variables: Decodable::decode(d), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.