From 77d974ae6b73f8b733f12e18d220fa8c4fc1ee38 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 17:40:56 +0200 Subject: Replace all the types by their Chalk versions --- crates/hir_ty/src/lib.rs | 35 ++- crates/hir_ty/src/types.rs | 549 --------------------------------------------- crates/hir_ty/src/walk.rs | 2 +- 3 files changed, 32 insertions(+), 554 deletions(-) delete mode 100644 crates/hir_ty/src/types.rs (limited to 'crates') diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 87f10e9d5..3378015ca 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -17,7 +17,6 @@ mod chalk_cast; mod chalk_ext; mod builder; mod walk; -mod types; pub mod display; pub mod db; @@ -48,7 +47,6 @@ pub use lower::{ TyDefId, TyLoweringContext, ValueTyDefId, }; pub use traits::{chalk::Interner, TraitEnvironment}; -pub use types::*; pub use walk::TypeWalk; pub use chalk_ir::{ @@ -65,6 +63,21 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; pub type VariableKind = chalk_ir::VariableKind; pub type VariableKinds = chalk_ir::VariableKinds; pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds; +pub type Binders = chalk_ir::Binders; +pub type Substitution = chalk_ir::Substitution; +pub type GenericArg = chalk_ir::GenericArg; +pub type GenericArgData = chalk_ir::GenericArgData; + +pub type Ty = chalk_ir::Ty; +pub type TyKind = chalk_ir::TyKind; +pub type DynTy = chalk_ir::DynTy; +pub type FnPointer = chalk_ir::FnPointer; +// pub type FnSubst = chalk_ir::FnSubst; +pub use chalk_ir::FnSubst; +pub type ProjectionTy = chalk_ir::ProjectionTy; +pub type AliasTy = chalk_ir::AliasTy; +pub type OpaqueTy = chalk_ir::OpaqueTy; +pub type InferenceVar = chalk_ir::InferenceVar; pub type Lifetime = chalk_ir::Lifetime; pub type LifetimeData = chalk_ir::LifetimeData; @@ -79,6 +92,14 @@ pub type ChalkTraitId = chalk_ir::TraitId; pub type FnSig = chalk_ir::FnSig; +pub type InEnvironment = chalk_ir::InEnvironment; +pub type DomainGoal = chalk_ir::DomainGoal; +pub type AliasEq = chalk_ir::AliasEq; +pub type Solution = chalk_solve::Solution; +pub type ConstrainedSubst = chalk_ir::ConstrainedSubst; +pub type Guidance = chalk_solve::Guidance; +pub type WhereClause = chalk_ir::WhereClause; + // FIXME: get rid of this pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution { Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into()) @@ -121,6 +142,14 @@ pub fn make_canonical( Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } } +pub type TraitRef = chalk_ir::TraitRef; + +pub type QuantifiedWhereClause = Binders; + +pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses; + +pub type Canonical = chalk_ir::Canonical; + /// A function signature as seen by type inference: Several parameter types and /// one return type. #[derive(Clone, PartialEq, Eq, Debug)] @@ -164,8 +193,6 @@ impl CallableSig { } } -impl Ty {} - #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum ImplTraitId { ReturnTypeImplTrait(hir_def::FunctionId, u16), diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs deleted file mode 100644 index 89adad108..000000000 --- a/crates/hir_ty/src/types.rs +++ /dev/null @@ -1,549 +0,0 @@ -//! This is the home of `Ty` etc. until they get replaced by their chalk_ir -//! equivalents. - -use std::sync::Arc; - -use chalk_ir::{ - cast::{Cast, CastTo, Caster}, - BoundVar, Mutability, Scalar, TyVariableKind, -}; -use smallvec::SmallVec; - -use crate::{ - AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId, - Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, VariableKinds, -}; - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct OpaqueTy { - pub opaque_ty_id: OpaqueTyId, - pub substitution: Substitution, -} - -/// A "projection" type corresponds to an (unnormalized) -/// projection like `>::Foo`. Note that the -/// trait and all its parameters are fully known. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct ProjectionTy { - pub associated_ty_id: AssocTypeId, - pub substitution: Substitution, -} - -impl ProjectionTy { - pub fn self_type_parameter(&self, interner: &Interner) -> Ty { - self.substitution.interned()[0].assert_ty_ref(interner).clone() - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct DynTy { - /// The unknown self type. - pub bounds: Binders, - pub lifetime: Lifetime, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct FnPointer { - pub num_binders: usize, - pub sig: FnSig, - pub substitution: FnSubst, -} -/// A wrapper for the substs on a Fn. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct FnSubst(pub Substitution); - -impl FnPointer { - /// Represent the current `Fn` as if it was wrapped in `Binders` - pub fn into_binders(self, interner: &Interner) -> Binders { - Binders::new( - VariableKinds::from_iter( - interner, - (0..self.num_binders).map(|_| VariableKind::Lifetime), - ), - self.substitution, - ) - } - - /// Represent the current `Fn` as if it was wrapped in `Binders` - pub fn as_binders(&self, interner: &Interner) -> Binders<&FnSubst> { - Binders::new( - VariableKinds::from_iter( - interner, - (0..self.num_binders).map(|_| VariableKind::Lifetime), - ), - &self.substitution, - ) - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum AliasTy { - /// A "projection" type corresponds to an (unnormalized) - /// projection like `>::Foo`. Note that the - /// trait and all its parameters are fully known. - Projection(ProjectionTy), - /// An opaque type (`impl Trait`). - /// - /// This is currently only used for return type impl trait; each instance of - /// `impl Trait` in a return type gets its own ID. - Opaque(OpaqueTy), -} - -/// A type. -/// -/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents -/// the same thing (but in a different way). -/// -/// This should be cheap to clone. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum TyKind { - /// Structures, enumerations and unions. - Adt(chalk_ir::AdtId, Substitution), - - /// Represents an associated item like `Iterator::Item`. This is used - /// when we have tried to normalize a projection like `T::Item` but - /// couldn't find a better representation. In that case, we generate - /// an **application type** like `(Iterator::Item)`. - AssociatedType(AssocTypeId, Substitution), - - /// a scalar type like `bool` or `u32` - Scalar(Scalar), - - /// A tuple type. For example, `(i32, bool)`. - Tuple(usize, Substitution), - - /// An array with the given length. Written as `[T; n]`. - Array(Ty, Const), - - /// The pointee of an array slice. Written as `[T]`. - Slice(Ty), - - /// A raw pointer. Written as `*mut T` or `*const T` - Raw(Mutability, Ty), - - /// A reference; a pointer with an associated lifetime. Written as - /// `&'a mut T` or `&'a T`. - Ref(Mutability, Lifetime, Ty), - - /// This represents a placeholder for an opaque type in situations where we - /// don't know the hidden type (i.e. currently almost always). This is - /// analogous to the `AssociatedType` type constructor. - /// It is also used as the type of async block, with one type parameter - /// representing the Future::Output type. - OpaqueType(OpaqueTyId, Substitution), - - /// The anonymous type of a function declaration/definition. Each - /// function has a unique type, which is output (for a function - /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. - /// - /// This includes tuple struct / enum variant constructors as well. - /// - /// For example the type of `bar` here: - /// - /// ``` - /// fn foo() -> i32 { 1 } - /// let bar = foo; // bar: fn() -> i32 {foo} - /// ``` - FnDef(FnDefId, Substitution), - - /// The pointee of a string slice. Written as `str`. - Str, - - /// The never type `!`. - Never, - - /// The type of a specific closure. - /// - /// The closure signature is stored in a `FnPtr` type in the first type - /// parameter. - Closure(ClosureId, Substitution), - - /// Represents a foreign type declared in external blocks. - Foreign(ForeignDefId), - - /// A pointer to a function. Written as `fn() -> i32`. - /// - /// For example the type of `bar` here: - /// - /// ``` - /// fn foo() -> i32 { 1 } - /// let bar: fn() -> i32 = foo; - /// ``` - Function(FnPointer), - - /// An "alias" type represents some form of type alias, such as: - /// - An associated type projection like `::Item` - /// - `impl Trait` types - /// - Named type aliases like `type Foo = Vec` - Alias(AliasTy), - - /// A placeholder for a type parameter; for example, `T` in `fn f(x: T) - /// {}` when we're type-checking the body of that function. In this - /// situation, we know this stands for *some* type, but don't know the exact - /// type. - Placeholder(PlaceholderIndex), - - /// A bound type variable. This is used in various places: when representing - /// some polymorphic type like the type of function `fn f`, the type - /// parameters get turned into variables; during trait resolution, inference - /// variables get turned into bound variables and back; and in `Dyn` the - /// `Self` type is represented with a bound variable as well. - BoundVar(BoundVar), - - /// A type variable used during type checking. - InferenceVar(InferenceVar, TyVariableKind), - - /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). - /// - /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` - /// represents the `Self` type inside the bounds. This is currently - /// implicit; Chalk has the `Binders` struct to make it explicit, but it - /// didn't seem worth the overhead yet. - Dyn(DynTy), - - /// A placeholder for a type which could not be computed; this is propagated - /// to avoid useless error messages. Doubles as a placeholder where type - /// variables are inserted before type checking, since we want to try to - /// infer a better type here anyway -- for the IDE use case, we want to try - /// to infer as much as possible even in the presence of type errors. - Error, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Ty(Arc); - -impl TyKind { - pub fn intern(self, _interner: &Interner) -> Ty { - Ty(Arc::new(self)) - } -} - -impl Ty { - pub fn kind(&self, _interner: &Interner) -> &TyKind { - &self.0 - } - - pub fn interned_mut(&mut self) -> &mut TyKind { - Arc::make_mut(&mut self.0) - } - - pub fn into_inner(self) -> TyKind { - Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct GenericArg { - interned: GenericArgData, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum GenericArgData { - Ty(Ty), -} - -impl GenericArg { - /// Constructs a generic argument using `GenericArgData`. - pub fn new(_interner: &Interner, data: GenericArgData) -> Self { - GenericArg { interned: data } - } - - /// Gets the interned value. - pub fn interned(&self) -> &GenericArgData { - &self.interned - } - - /// Asserts that this is a type argument. - pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { - self.ty(interner).unwrap() - } - - /// Checks whether the generic argument is a type. - pub fn is_ty(&self, _interner: &Interner) -> bool { - match self.interned() { - GenericArgData::Ty(_) => true, - } - } - - /// Returns the type if it is one, `None` otherwise. - pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { - match self.interned() { - GenericArgData::Ty(t) => Some(t), - } - } - - pub fn interned_mut(&mut self) -> &mut GenericArgData { - &mut self.interned - } -} - -/// A list of substitutions for generic parameters. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Substitution(SmallVec<[GenericArg; 2]>); - -impl Substitution { - pub fn interned(&self) -> &SmallVec<[GenericArg; 2]> { - &self.0 - } - - pub fn len(&self, _: &Interner) -> usize { - self.0.len() - } - - pub fn is_empty(&self, _: &Interner) -> bool { - self.0.is_empty() - } - - pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { - &self.0[i] - } - - pub fn empty(_: &Interner) -> Substitution { - Substitution(SmallVec::new()) - } - - pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { - self.0.iter() - } - - pub fn from1(_interner: &Interner, ty: Ty) -> Substitution { - Substitution::intern({ - let mut v = SmallVec::new(); - v.push(ty.cast(&Interner)); - v - }) - } - - pub fn from_iter( - interner: &Interner, - elements: impl IntoIterator>, - ) -> Self { - Substitution(elements.into_iter().casted(interner).collect()) - } - - pub fn apply(&self, value: T, _interner: &Interner) -> T { - value.subst_bound_vars(self) - } - - // Temporary helper functions, to be removed - pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution { - Substitution(interned) - } - - pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> { - &mut self.0 - } -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Binders { - /// The binders that quantify over the value. - pub binders: VariableKinds, - value: T, -} - -impl Binders { - pub fn new(binders: VariableKinds, value: T) -> Self { - Self { binders, value } - } - - pub fn empty(_interner: &Interner, value: T) -> Self { - crate::make_only_type_binders(0, value) - } - - pub fn as_ref(&self) -> Binders<&T> { - Binders { binders: self.binders.clone(), value: &self.value } - } - - pub fn map(self, f: impl FnOnce(T) -> U) -> Binders { - Binders { binders: self.binders, value: f(self.value) } - } - - pub fn filter_map(self, f: impl FnOnce(T) -> Option) -> Option> { - Some(Binders { binders: self.binders, value: f(self.value)? }) - } - - pub fn skip_binders(&self) -> &T { - &self.value - } - - pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds) { - (self.value, self.binders) - } - - /// Returns the number of binders. - pub fn len(&self, interner: &Interner) -> usize { - self.binders.len(interner) - } - - // Temporary helper function, to be removed - pub fn skip_binders_mut(&mut self) -> &mut T { - &mut self.value - } -} - -impl Binders<&T> { - pub fn cloned(&self) -> Binders { - Binders::new(self.binders.clone(), self.value.clone()) - } -} - -impl Binders { - /// Substitutes all variables. - pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T { - let (value, binders) = self.into_value_and_skipped_binders(); - assert_eq!(subst.len(interner), binders.len(interner)); - value.subst_bound_vars(subst) - } -} - -impl std::fmt::Debug for Binders { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - let Binders { ref binders, ref value } = *self; - write!(fmt, "for{:?} ", binders.inner_debug(&Interner))?; - std::fmt::Debug::fmt(value, fmt) - } -} - -/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct TraitRef { - pub trait_id: ChalkTraitId, - pub substitution: Substitution, -} - -impl TraitRef { - pub fn self_type_parameter(&self, interner: &Interner) -> Ty { - self.substitution.at(interner, 0).assert_ty_ref(interner).clone() - } -} - -/// Like `generics::WherePredicate`, but with resolved types: A condition on the -/// parameters of a generic item. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum WhereClause { - /// The given trait needs to be implemented for its type parameters. - Implemented(TraitRef), - /// An associated type bindings like in `Iterator`. - AliasEq(AliasEq), -} - -pub type QuantifiedWhereClause = Binders; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); - -impl QuantifiedWhereClauses { - pub fn from_iter( - _interner: &Interner, - elements: impl IntoIterator, - ) -> Self { - QuantifiedWhereClauses(elements.into_iter().collect()) - } - - pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { - &self.0 - } - - pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> { - &mut self.0 - } -} - -/// Basically a claim (currently not validated / checked) that the contained -/// type / trait ref contains no inference variables; any inference variables it -/// contained have been replaced by bound variables, and `kinds` tells us how -/// many there are and whether they were normal or float/int variables. This is -/// used to erase irrelevant differences between types before using them in -/// queries. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Canonical { - pub value: T, - pub binders: CanonicalVarKinds, -} - -/// Something (usually a goal), along with an environment. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct InEnvironment { - pub environment: chalk_ir::Environment, - pub goal: T, -} - -impl InEnvironment { - pub fn new(environment: &chalk_ir::Environment, value: T) -> InEnvironment { - InEnvironment { environment: environment.clone(), goal: value } - } -} - -/// Something that needs to be proven (by Chalk) during type checking, e.g. that -/// a certain type implements a certain trait. Proving the Obligation might -/// result in additional information about inference variables. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum DomainGoal { - Holds(WhereClause), -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct AliasEq { - pub alias: AliasTy, - pub ty: Ty, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ConstrainedSubst { - pub subst: Substitution, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -/// A (possible) solution for a proposed goal. -pub enum Solution { - /// The goal indeed holds, and there is a unique value for all existential - /// variables. - Unique(Canonical), - - /// The goal may be provable in multiple ways, but regardless we may have some guidance - /// for type inference. In this case, we don't return any lifetime - /// constraints, since we have not "committed" to any particular solution - /// yet. - Ambig(Guidance), -} - -#[derive(Clone, Debug, PartialEq, Eq)] -/// When a goal holds ambiguously (e.g., because there are multiple possible -/// solutions), we issue a set of *guidance* back to type inference. -pub enum Guidance { - /// The existential variables *must* have the given values if the goal is - /// ever to hold, but that alone isn't enough to guarantee the goal will - /// actually hold. - Definite(Canonical), - - /// There are multiple plausible values for the existentials, but the ones - /// here are suggested as the preferred choice heuristically. These should - /// be used for inference fallback only. - Suggested(Canonical), - - /// There's no useful information to feed back to type inference - Unknown, -} - -/// The kinds of placeholders we need during type inference. There's separate -/// values for general types, and for integer and float variables. The latter -/// two are used for inference of literal values (e.g. `100` could be one of -/// several integer types). -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct InferenceVar { - index: u32, -} - -impl From for InferenceVar { - fn from(index: u32) -> InferenceVar { - InferenceVar { index } - } -} - -impl InferenceVar { - /// Gets the underlying index value. - pub fn index(self) -> u32 { - self.index - } -} diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs index 91116dcda..873d563c0 100644 --- a/crates/hir_ty/src/walk.rs +++ b/crates/hir_ty/src/walk.rs @@ -408,7 +408,7 @@ impl TypeWalk for AliasEq { } } -impl TypeWalk for FnSubst { +impl TypeWalk for FnSubst { fn walk(&self, f: &mut impl FnMut(&Ty)) { self.0.walk(f) } -- cgit v1.2.3