From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/chalk-ir-0.80.0/src/interner.rs | 702 +++++++++++++++++++++++++++++++++ 1 file changed, 702 insertions(+) create mode 100644 vendor/chalk-ir-0.80.0/src/interner.rs (limited to 'vendor/chalk-ir-0.80.0/src/interner.rs') diff --git a/vendor/chalk-ir-0.80.0/src/interner.rs b/vendor/chalk-ir-0.80.0/src/interner.rs new file mode 100644 index 000000000..8a3f88cc4 --- /dev/null +++ b/vendor/chalk-ir-0.80.0/src/interner.rs @@ -0,0 +1,702 @@ +//! Encapsulates the concrete representation of core types such as types and goals. +use crate::AliasTy; +use crate::AssocTypeId; +use crate::CanonicalVarKind; +use crate::CanonicalVarKinds; +use crate::ClosureId; +use crate::Constraint; +use crate::Constraints; +use crate::FnDefId; +use crate::ForeignDefId; +use crate::GeneratorId; +use crate::GenericArg; +use crate::GenericArgData; +use crate::Goal; +use crate::GoalData; +use crate::Goals; +use crate::InEnvironment; +use crate::Lifetime; +use crate::LifetimeData; +use crate::OpaqueTy; +use crate::OpaqueTyId; +use crate::ProgramClause; +use crate::ProgramClauseData; +use crate::ProgramClauseImplication; +use crate::ProgramClauses; +use crate::ProjectionTy; +use crate::QuantifiedWhereClause; +use crate::QuantifiedWhereClauses; +use crate::SeparatorTraitRef; +use crate::Substitution; +use crate::TraitId; +use crate::Ty; +use crate::TyData; +use crate::VariableKind; +use crate::VariableKinds; +use crate::Variance; +use crate::Variances; +use crate::{AdtId, TyKind}; +use crate::{Const, ConstData}; +use std::fmt::{self, Debug}; +use std::hash::Hash; +use std::marker::PhantomData; +use std::sync::Arc; + +/// A "interner" encapsulates the concrete representation of +/// certain "core types" from chalk-ir. All the types in chalk-ir are +/// parameterized by a `I: Interner`, and so (e.g.) if they want to +/// store a type, they don't store a `Ty` instance directly, but +/// rather prefer a `Ty`. You can think of `I::Type` as the +/// interned representation (and, indeed, it may well be an interned +/// pointer, e.g. in rustc). +/// +/// Type families allow chalk to be embedded in different contexts +/// where the concrete representation of core types varies. They also +/// allow us to write generic code that reasons about multiple +/// distinct sets of types by using distinct generic type parameters +/// (e.g., `SourceI` and `TargetI`) -- even if those type parameters +/// wind up being mapped to the same underlying type families in the +/// end. +pub trait Interner: Debug + Copy + Eq + Hash + Sized { + /// "Interned" representation of types. In normal user code, + /// `Self::InternedType` is not referenced. Instead, we refer to + /// `Ty`, which wraps this type. + /// + /// An `InternedType` must be something that can be created from a + /// `TyKind` (by the [`intern_ty`][Self::intern_ty] method) and then later + /// converted back (by the [`ty_data`][Self::ty_data] method). The interned form + /// must also introduce indirection, either via a `Box`, `&`, or + /// other pointer type. + type InternedType: Debug + Clone + Eq + Hash; + + /// "Interned" representation of lifetimes. In normal user code, + /// `Self::InternedLifetime` is not referenced. Instead, we refer to + /// `Lifetime`, which wraps this type. + /// + /// An `InternedLifetime` must be something that can be created + /// from a `LifetimeData` (by the [`intern_lifetime`][Self::intern_lifetime] method) and + /// then later converted back (by the [`lifetime_data`][Self::lifetime_data] method). + type InternedLifetime: Debug + Clone + Eq + Hash; + + /// "Interned" representation of const expressions. In normal user code, + /// `Self::InternedConst` is not referenced. Instead, we refer to + /// `Const`, which wraps this type. + /// + /// An `InternedConst` must be something that can be created + /// from a `ConstData` (by the [`intern_const`][Self::intern_const] method) and + /// then later converted back (by the [`const_data`][Self::const_data] method). + type InternedConst: Debug + Clone + Eq + Hash; + + /// "Interned" representation of an evaluated const value. + /// `Self::InternedConcreteConst` is not referenced. Instead, + /// we refer to `ConcreteConst`, which wraps this type. + /// + /// `InternedConcreteConst` instances are not created by chalk, + /// it can only make a query asking about equality of two + /// evaluated consts. + type InternedConcreteConst: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a "generic parameter", which can + /// be either a type or a lifetime. In normal user code, + /// `Self::InternedGenericArg` is not referenced. Instead, we refer to + /// `GenericArg`, which wraps this type. + /// + /// An `InternedType` is created by `intern_generic_arg` and can be + /// converted back to its underlying data via `generic_arg_data`. + type InternedGenericArg: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a "goal". In normal user code, + /// `Self::InternedGoal` is not referenced. Instead, we refer to + /// `Goal`, which wraps this type. + /// + /// An `InternedGoal` is created by `intern_goal` and can be + /// converted back to its underlying data via `goal_data`. + type InternedGoal: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of goals. In normal user code, + /// `Self::InternedGoals` is not referenced. Instead, we refer to + /// `Goals`, which wraps this type. + /// + /// An `InternedGoals` is created by `intern_goals` and can be + /// converted back to its underlying data via `goals_data`. + type InternedGoals: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a "substitution". In normal user code, + /// `Self::InternedSubstitution` is not referenced. Instead, we refer to + /// `Substitution`, which wraps this type. + /// + /// An `InternedSubstitution` is created by `intern_substitution` and can be + /// converted back to its underlying data via `substitution_data`. + type InternedSubstitution: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of program clauses. In normal user code, + /// `Self::InternedProgramClauses` is not referenced. Instead, we refer to + /// `ProgramClauses`, which wraps this type. + /// + /// An `InternedProgramClauses` is created by `intern_program_clauses` and can be + /// converted back to its underlying data via `program_clauses_data`. + type InternedProgramClauses: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a "program clause". In normal user code, + /// `Self::InternedProgramClause` is not referenced. Instead, we refer to + /// `ProgramClause`, which wraps this type. + /// + /// An `InternedProgramClause` is created by `intern_program_clause` and can be + /// converted back to its underlying data via `program_clause_data`. + type InternedProgramClause: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of quantified where clauses. + /// In normal user code, `Self::InternedQuantifiedWhereClauses` is not referenced. + /// Instead, we refer to `QuantifiedWhereClauses`, which wraps this type. + /// + /// An `InternedQuantifiedWhereClauses` is created by `intern_quantified_where_clauses` + /// and can be converted back to its underlying data via `quantified_where_clauses_data`. + type InternedQuantifiedWhereClauses: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of variable kinds. + /// In normal user code, `Self::InternedVariableKinds` is not referenced. + /// Instead, we refer to `VariableKinds`, which wraps this type. + /// + /// An `InternedVariableKinds` is created by `intern_generic_arg_kinds` + /// and can be converted back to its underlying data via `variable_kinds_data`. + type InternedVariableKinds: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of variable kinds with universe index. + /// In normal user code, `Self::InternedCanonicalVarKinds` is not referenced. + /// Instead, we refer to `CanonicalVarKinds`, which wraps this type. + /// + /// An `InternedCanonicalVarKinds` is created by + /// `intern_canonical_var_kinds` and can be converted back + /// to its underlying data via `canonical_var_kinds_data`. + type InternedCanonicalVarKinds: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of region constraints. + /// In normal user code, `Self::InternedConstraints` is not referenced. + /// Instead, we refer to `Constraints`, which wraps this type. + /// + /// An `InternedConstraints` is created by `intern_constraints` + /// and can be converted back to its underlying data via `constraints_data`. + type InternedConstraints: Debug + Clone + Eq + Hash; + + /// "Interned" representation of a list of `chalk_ir::Variance`. + /// In normal user code, `Self::InternedVariances` is not referenced. + /// Instead, we refer to `Variances`, which wraps this type. + /// + /// An `InternedVariances` is created by + /// `intern_variances` and can be converted back + /// to its underlying data via `variances_data`. + type InternedVariances: Debug + Clone + Eq + Hash; + + /// The core "id" type used for trait-ids and the like. + type DefId: Debug + Copy + Eq + Hash; + + /// The ID type for ADTs + type InternedAdtId: Debug + Copy + Eq + Hash; + + /// Representation of identifiers. + type Identifier: Debug + Clone + Eq + Hash; + + /// Representation of function ABI (e.g. calling convention). + type FnAbi: Debug + Copy + Eq + Hash; + + /// Prints the debug representation of a type-kind-id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_adt_id(adt_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of a type-kind-id. + /// Returns `None` to fallback to the default debug output (e.g., + /// if no info about current program is available from TLS). + #[allow(unused_variables)] + fn debug_trait_id( + trait_id: TraitId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a type-kind-id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_assoc_type_id( + type_id: AssocTypeId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an opaque type. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_opaque_ty_id( + opaque_ty_id: OpaqueTyId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a function-def-id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_fn_def_id( + fn_def_id: FnDefId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a closure id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_closure_id( + fn_def_id: ClosureId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a foreign-def-id. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_foreign_def_id( + foreign_def_id: ForeignDefId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an alias. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_generator_id( + generator_id: GeneratorId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an alias. To get good + /// results, this requires inspecting TLS, and is difficult to + /// code without reference to a specific interner (and hence + /// fully known types). + /// + /// Returns `None` to fallback to the default debug output (e.g., + /// if no info about current program is available from TLS). + #[allow(unused_variables)] + fn debug_alias(alias: &AliasTy, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of a ProjectionTy. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_projection_ty( + projection_ty: &ProjectionTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an OpaqueTy. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_opaque_ty( + opaque_ty: &OpaqueTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a type. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_ty(ty: &Ty, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of a lifetime. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_lifetime( + lifetime: &Lifetime, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a const. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_const(constant: &Const, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of an parameter. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_generic_arg( + generic_arg: &GenericArg, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a parameter kinds list. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_variable_kinds( + variable_kinds: &VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a parameter kinds list, with angle brackets. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_variable_kinds_with_angles( + variable_kinds: &VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an parameter kinds list with universe index. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_canonical_var_kinds( + canonical_var_kinds: &CanonicalVarKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of an goal. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of a list of goals. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_goals(goals: &Goals, fmt: &mut fmt::Formatter<'_>) -> Option { + None + } + + /// Prints the debug representation of a ProgramClauseImplication. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_program_clause_implication( + pci: &ProgramClauseImplication, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a ProgramClause. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_program_clause( + clause: &ProgramClause, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a ProgramClauses. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_program_clauses( + clauses: &ProgramClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a Substitution. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_substitution( + substitution: &Substitution, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a SeparatorTraitRef. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_separator_trait_ref( + separator_trait_ref: &SeparatorTraitRef<'_, Self>, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a QuantifiedWhereClauses. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_quantified_where_clauses( + clauses: &QuantifiedWhereClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a Constraints. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_constraints( + clauses: &Constraints, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Prints the debug representation of a Variances. + /// Returns `None` to fallback to the default debug output. + #[allow(unused_variables)] + fn debug_variances( + variances: &Variances, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + /// Create an "interned" type from `ty`. This is not normally + /// invoked directly; instead, you invoke `TyKind::intern` (which + /// will ultimately call this method). + fn intern_ty(self, kind: TyKind) -> Self::InternedType; + + /// Lookup the `TyKind` from an interned type. + fn ty_data(self, ty: &Self::InternedType) -> &TyData; + + /// Create an "interned" lifetime from `lifetime`. This is not + /// normally invoked directly; instead, you invoke + /// `LifetimeData::intern` (which will ultimately call this + /// method). + fn intern_lifetime(self, lifetime: LifetimeData) -> Self::InternedLifetime; + + /// Lookup the `LifetimeData` that was interned to create a `InternedLifetime`. + fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &LifetimeData; + + /// Create an "interned" const from `const`. This is not + /// normally invoked directly; instead, you invoke + /// `ConstData::intern` (which will ultimately call this + /// method). + fn intern_const(self, constant: ConstData) -> Self::InternedConst; + + /// Lookup the `ConstData` that was interned to create a `InternedConst`. + fn const_data(self, constant: &Self::InternedConst) -> &ConstData; + + /// Determine whether two concrete const values are equal. + fn const_eq( + self, + ty: &Self::InternedType, + c1: &Self::InternedConcreteConst, + c2: &Self::InternedConcreteConst, + ) -> bool; + + /// Create an "interned" parameter from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `GenericArgData::intern` (which will ultimately call this + /// method). + fn intern_generic_arg(self, data: GenericArgData) -> Self::InternedGenericArg; + + /// Lookup the `LifetimeData` that was interned to create a `InternedLifetime`. + fn generic_arg_data(self, lifetime: &Self::InternedGenericArg) -> &GenericArgData; + + /// Create an "interned" goal from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `GoalData::intern` (which will ultimately call this + /// method). + fn intern_goal(self, data: GoalData) -> Self::InternedGoal; + + /// Lookup the `GoalData` that was interned to create a `InternedGoal`. + fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData; + + /// Create an "interned" goals from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `GoalsData::intern` (which will ultimately call this + /// method). + fn intern_goals( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the `GoalsData` that was interned to create a `InternedGoals`. + fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal]; + + /// Create an "interned" substitution from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `SubstitutionData::intern` (which will ultimately call this + /// method). + fn intern_substitution( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the `SubstitutionData` that was interned to create a `InternedSubstitution`. + fn substitution_data(self, substitution: &Self::InternedSubstitution) -> &[GenericArg]; + + /// Create an "interned" program clause from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `ProgramClauseData::intern` (which will ultimately call this + /// method). + fn intern_program_clause(self, data: ProgramClauseData) -> Self::InternedProgramClause; + + /// Lookup the `ProgramClauseData` that was interned to create a `ProgramClause`. + fn program_clause_data(self, clause: &Self::InternedProgramClause) -> &ProgramClauseData; + + /// Create an "interned" program clauses from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `ProgramClauses::from_iter` (which will ultimately call this + /// method). + fn intern_program_clauses( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the `ProgramClauseData` that was interned to create a `ProgramClause`. + fn program_clauses_data(self, clauses: &Self::InternedProgramClauses) + -> &[ProgramClause]; + + /// Create an "interned" quantified where clauses from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `QuantifiedWhereClauses::from_iter` (which will ultimately call this + /// method). + fn intern_quantified_where_clauses( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the slice of `QuantifiedWhereClause` that was interned to + /// create a `QuantifiedWhereClauses`. + fn quantified_where_clauses_data( + self, + clauses: &Self::InternedQuantifiedWhereClauses, + ) -> &[QuantifiedWhereClause]; + + /// Create an "interned" parameter kinds from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `VariableKinds::from_iter` (which will ultimately call this + /// method). + fn intern_generic_arg_kinds( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the slice of `VariableKinds` that was interned to + /// create a `VariableKinds`. + fn variable_kinds_data( + self, + variable_kinds: &Self::InternedVariableKinds, + ) -> &[VariableKind]; + + /// Create "interned" variable kinds with universe index from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `CanonicalVarKinds::from_iter` (which will ultimately call this + /// method). + fn intern_canonical_var_kinds( + self, + data: impl IntoIterator, E>>, + ) -> Result; + + /// Lookup the slice of `CanonicalVariableKind` that was interned to + /// create a `CanonicalVariableKinds`. + fn canonical_var_kinds_data( + self, + canonical_var_kinds: &Self::InternedCanonicalVarKinds, + ) -> &[CanonicalVarKind]; + + /// Create "interned" constraints from `data`. This is not + /// normally invoked dirctly; instead, you invoke + /// `Constraints::from_iter` (which will ultimately call this + /// method). + fn intern_constraints( + self, + data: impl IntoIterator>, E>>, + ) -> Result; + + /// Lookup the slice of `Constraint` that was interned to + /// create a `Constraints`. + fn constraints_data( + self, + constraints: &Self::InternedConstraints, + ) -> &[InEnvironment>]; + + /// Create "interned" variances from `data`. This is not + /// normally invoked directly; instead, you invoke + /// `Variances::from` (which will ultimately call this + /// method). + fn intern_variances( + self, + data: impl IntoIterator>, + ) -> Result; + + /// Lookup the slice of `Variance` that was interned to + /// create a `Variances`. + fn variances_data(self, variances: &Self::InternedVariances) -> &[Variance]; +} + +/// Implemented by types that have an associated interner (which +/// are virtually all of the types in chalk-ir, for example). +/// This lets us map from a type like `Ty` to the parameter `I`. +/// +/// It's particularly useful for writing `Fold` impls for generic types like +/// `Binder`, since it allows us to figure out the interner of `T`. +pub trait HasInterner { + /// The interner associated with the type. + type Interner: Interner; +} + +impl HasInterner for [T] { + type Interner = T::Interner; +} + +impl HasInterner for Vec { + type Interner = T::Interner; +} + +impl HasInterner for Box { + type Interner = T::Interner; +} + +impl HasInterner for Arc { + type Interner = T::Interner; +} + +impl HasInterner for &T { + type Interner = T::Interner; +} + +impl HasInterner for PhantomData { + type Interner = I; +} + +impl HasInterner for (A, B) +where + A: HasInterner, + B: HasInterner, + I: Interner, +{ + type Interner = I; +} + +impl HasInterner for (A, B, C) +where + A: HasInterner, + B: HasInterner, + C: HasInterner, + I: Interner, +{ + type Interner = I; +} + +impl<'a, T: HasInterner> HasInterner for std::slice::Iter<'a, T> { + type Interner = T::Interner; +} -- cgit v1.2.3