mirror of https://github.com/rust-lang/rust.git
Uplift Canonical to rustc_type_ir
This commit is contained in:
parent
b66fe58f68
commit
024ca99de5
|
@ -207,7 +207,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
debug!("fcx {}", self.tag());
|
debug!("fcx {}", self.tag());
|
||||||
|
|
||||||
if !canonical_user_type_annotation.is_identity() {
|
// FIXME: is_identity being on `UserType` and not `Canonical<UserType>` is awkward
|
||||||
|
if !canonical_user_type_annotation.value.is_identity() {
|
||||||
self.typeck_results
|
self.typeck_results
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.user_provided_types_mut()
|
.user_provided_types_mut()
|
||||||
|
|
|
@ -21,35 +21,17 @@
|
||||||
//!
|
//!
|
||||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||||
|
|
||||||
|
use rustc_macros::HashStable;
|
||||||
|
use rustc_type_ir::Canonical as IrCanonical;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
use crate::infer::MemberConstraint;
|
use crate::infer::MemberConstraint;
|
||||||
use crate::mir::ConstraintCategory;
|
use crate::mir::ConstraintCategory;
|
||||||
use crate::ty::GenericArg;
|
use crate::ty::GenericArg;
|
||||||
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
|
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
|
||||||
use rustc_macros::HashStable;
|
|
||||||
use smallvec::SmallVec;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::ops::Index;
|
|
||||||
|
|
||||||
/// A "canonicalized" type `V` is one where all free inference
|
pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>;
|
||||||
/// variables have been rewritten to "canonical vars". These are
|
|
||||||
/// numbered starting from 0 in order of first appearance.
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
|
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable)]
|
|
||||||
pub struct Canonical<'tcx, V> {
|
|
||||||
pub value: V,
|
|
||||||
pub max_universe: ty::UniverseIndex,
|
|
||||||
pub variables: CanonicalVarInfos<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, V: Display> std::fmt::Display for Canonical<'tcx, V> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Canonical {{ value: {}, max_universe: {:?}, variables: {:?} }}",
|
|
||||||
self.value, self.max_universe, self.variables
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
|
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
|
||||||
|
|
||||||
|
@ -379,56 +361,6 @@ impl<'tcx, R> QueryResponse<'tcx, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
|
|
||||||
pub fn is_proven(&self) -> bool {
|
|
||||||
self.value.is_proven()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_ambiguous(&self) -> bool {
|
|
||||||
!self.is_proven()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, V> Canonical<'tcx, 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<'_, T> = ...;
|
|
||||||
/// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// An example of an **incorrect** use of this:
|
|
||||||
///
|
|
||||||
/// ```rust,ignore (not real code)
|
|
||||||
/// let a: Canonical<'tcx, T> = ...;
|
|
||||||
/// let ty: Ty<'tcx> = ...;
|
|
||||||
/// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
|
|
||||||
/// ```
|
|
||||||
pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, 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<'tcx, W> {
|
|
||||||
let Canonical { max_universe, variables, value: _ } = self;
|
|
||||||
Canonical { max_universe, variables, value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type QueryOutlivesConstraint<'tcx> =
|
pub type QueryOutlivesConstraint<'tcx> =
|
||||||
(ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
|
(ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub mod tls;
|
||||||
|
|
||||||
use crate::arena::Arena;
|
use crate::arena::Arena;
|
||||||
use crate::dep_graph::{DepGraph, DepKindStruct};
|
use crate::dep_graph::{DepGraph, DepKindStruct};
|
||||||
use crate::infer::canonical::CanonicalVarInfo;
|
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
|
||||||
use crate::lint::struct_lint_level;
|
use crate::lint::struct_lint_level;
|
||||||
use crate::metadata::ModChild;
|
use crate::metadata::ModChild;
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
|
@ -88,6 +88,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
|
|
||||||
type Binder<T> = Binder<'tcx, T>;
|
type Binder<T> = Binder<'tcx, T>;
|
||||||
type TypeAndMut = TypeAndMut<'tcx>;
|
type TypeAndMut = TypeAndMut<'tcx>;
|
||||||
|
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
||||||
|
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type Tys = &'tcx List<Ty<'tcx>>;
|
type Tys = &'tcx List<Ty<'tcx>>;
|
||||||
|
|
|
@ -449,7 +449,6 @@ TrivialTypeTraversalImpls! {
|
||||||
crate::ty::IntVarValue,
|
crate::ty::IntVarValue,
|
||||||
crate::ty::adjustment::PointerCoercion,
|
crate::ty::adjustment::PointerCoercion,
|
||||||
crate::ty::RegionVid,
|
crate::ty::RegionVid,
|
||||||
crate::ty::UniverseIndex,
|
|
||||||
crate::ty::Variance,
|
crate::ty::Variance,
|
||||||
::rustc_span::Span,
|
::rustc_span::Span,
|
||||||
::rustc_span::symbol::Ident,
|
::rustc_span::symbol::Ident,
|
||||||
|
|
|
@ -594,11 +594,24 @@ pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||||
/// Canonical user type annotation.
|
/// Canonical user type annotation.
|
||||||
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> CanonicalUserType<'tcx> {
|
/// A user-given type annotation attached to a constant. These arise
|
||||||
|
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||||
|
/// so forth.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||||
|
#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
|
pub enum UserType<'tcx> {
|
||||||
|
Ty(Ty<'tcx>),
|
||||||
|
|
||||||
|
/// The canonical type is the result of `type_of(def_id)` with the
|
||||||
|
/// given substitutions applied.
|
||||||
|
TypeOf(DefId, UserArgs<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> UserType<'tcx> {
|
||||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||||
pub fn is_identity(&self) -> bool {
|
pub fn is_identity(&self) -> bool {
|
||||||
match self.value {
|
match self {
|
||||||
UserType::Ty(_) => false,
|
UserType::Ty(_) => false,
|
||||||
UserType::TypeOf(_, user_args) => {
|
UserType::TypeOf(_, user_args) => {
|
||||||
if user_args.user_self_ty.is_some() {
|
if user_args.user_self_ty.is_some() {
|
||||||
|
@ -640,19 +653,6 @@ impl<'tcx> CanonicalUserType<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A user-given type annotation attached to a constant. These arise
|
|
||||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
|
||||||
/// so forth.
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
|
||||||
#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
|
||||||
pub enum UserType<'tcx> {
|
|
||||||
Ty(Ty<'tcx>),
|
|
||||||
|
|
||||||
/// The canonical type is the result of `type_of(def_id)` with the
|
|
||||||
/// given substitutions applied.
|
|
||||||
TypeOf(DefId, UserArgs<'tcx>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> std::fmt::Display for UserType<'tcx> {
|
impl<'tcx> std::fmt::Display for UserType<'tcx> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -293,7 +293,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}?;
|
}?;
|
||||||
// We don't expect ambiguity.
|
// We don't expect ambiguity.
|
||||||
if result.is_ambiguous() {
|
if !result.value.is_proven() {
|
||||||
// Rustdoc normalizes possibly not well-formed types, so only
|
// Rustdoc normalizes possibly not well-formed types, so only
|
||||||
// treat this as a bug if we're not in rustdoc.
|
// treat this as a bug if we're not in rustdoc.
|
||||||
if !tcx.sess.opts.actually_rustdoc {
|
if !tcx.sess.opts.actually_rustdoc {
|
||||||
|
|
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ pub trait Interner: Sized {
|
||||||
|
|
||||||
type Binder<T>;
|
type Binder<T>;
|
||||||
type TypeAndMut: Clone + Debug + Hash + Ord;
|
type TypeAndMut: Clone + Debug + Hash + Ord;
|
||||||
|
type CanonicalVars: Clone + Debug + Hash + Eq;
|
||||||
|
|
||||||
// Kinds of tys
|
// Kinds of tys
|
||||||
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub mod visit;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod canonical;
|
||||||
mod const_kind;
|
mod const_kind;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod flags;
|
mod flags;
|
||||||
|
@ -33,6 +34,7 @@ mod interner;
|
||||||
mod predicate_kind;
|
mod predicate_kind;
|
||||||
mod region_kind;
|
mod region_kind;
|
||||||
|
|
||||||
|
pub use canonical::*;
|
||||||
pub use codec::*;
|
pub use codec::*;
|
||||||
pub use const_kind::*;
|
pub use const_kind::*;
|
||||||
pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||||
|
|
|
@ -50,4 +50,5 @@ TrivialTypeTraversalImpls! {
|
||||||
String,
|
String,
|
||||||
crate::DebruijnIndex,
|
crate::DebruijnIndex,
|
||||||
crate::AliasRelationDirection,
|
crate::AliasRelationDirection,
|
||||||
|
crate::UniverseIndex,
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,7 +307,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is manually implemented because a derive would require `I: Encodable`
|
// This is manually implemented because a derive would require `I: Encodable`
|
||||||
impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
|
impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for RegionKind<I>
|
||||||
where
|
where
|
||||||
I::EarlyBoundRegion: Encodable<E>,
|
I::EarlyBoundRegion: Encodable<E>,
|
||||||
I::BoundRegion: Encodable<E>,
|
I::BoundRegion: Encodable<E>,
|
||||||
|
|
|
@ -622,7 +622,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is manually implemented because a derive would require `I: Encodable`
|
// This is manually implemented because a derive would require `I: Encodable`
|
||||||
impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
|
impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for TyKind<I>
|
||||||
where
|
where
|
||||||
I::ErrorGuaranteed: Encodable<E>,
|
I::ErrorGuaranteed: Encodable<E>,
|
||||||
I::AdtDef: Encodable<E>,
|
I::AdtDef: Encodable<E>,
|
||||||
|
|
Loading…
Reference in New Issue