]> git.lizzy.rs Git - rust.git/commitdiff
Separate `Ty` and `TyKind` like in Chalk
authorFlorian Diebold <flodiebold@gmail.com>
Sat, 13 Mar 2021 13:44:51 +0000 (14:44 +0100)
committerFlorian Diebold <flodiebold@gmail.com>
Sat, 13 Mar 2021 15:17:15 +0000 (16:17 +0100)
Currently `Ty` just wraps `TyKind`, but this allows us to change most
places to already use `intern` / `interned`.

20 files changed:
crates/hir/src/lib.rs
crates/hir_ty/src/autoderef.rs
crates/hir_ty/src/diagnostics/expr.rs
crates/hir_ty/src/diagnostics/match_check.rs
crates/hir_ty/src/diagnostics/unsafe_check.rs
crates/hir_ty/src/display.rs
crates/hir_ty/src/infer.rs
crates/hir_ty/src/infer/coerce.rs
crates/hir_ty/src/infer/expr.rs
crates/hir_ty/src/infer/pat.rs
crates/hir_ty/src/infer/path.rs
crates/hir_ty/src/infer/unify.rs
crates/hir_ty/src/lib.rs
crates/hir_ty/src/lower.rs
crates/hir_ty/src/method_resolution.rs
crates/hir_ty/src/op.rs
crates/hir_ty/src/traits.rs
crates/hir_ty/src/traits/chalk.rs
crates/hir_ty/src/traits/chalk/mapping.rs
crates/rust-analyzer/src/cli/analysis_stats.rs

index 58adc8fd386cb25215189f22d6aad32e4a630b29..7b9de11eddccb3ef801d5ae9abc155276149fb8c 100644 (file)
@@ -54,8 +54,8 @@
     method_resolution,
     traits::{FnTrait, Solution, SolutionVariables},
     AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
-    InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment,
-    Ty, TyDefId, TyVariableKind,
+    InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs,
+    TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind,
 };
 use rustc_hash::FxHashSet;
 use stdx::{format_to, impl_from};
@@ -677,7 +677,7 @@ pub enum Adt {
 impl Adt {
     pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
         let subst = db.generic_defaults(self.into());
-        subst.iter().any(|ty| &ty.value == &Ty::Unknown)
+        subst.iter().any(|ty| ty.value.is_unknown())
     }
 
     /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -1012,7 +1012,7 @@ pub struct TypeAlias {
 impl TypeAlias {
     pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
         let subst = db.generic_defaults(self.id.into());
-        subst.iter().any(|ty| &ty.value == &Ty::Unknown)
+        subst.iter().any(|ty| ty.value.is_unknown())
     }
 
     pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1384,7 +1384,7 @@ pub fn module(self, db: &dyn HirDatabase) -> Module {
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
         let resolver = self.id.parent.resolver(db.upcast());
         let krate = self.id.parent.module(db.upcast()).krate();
-        let ty = Ty::Placeholder(self.id);
+        let ty = TyKind::Placeholder(self.id).intern(&Interner);
         Type::new_with_resolver_inner(db, krate, &resolver, ty)
     }
 
@@ -1584,25 +1584,25 @@ fn from_def(
     }
 
     pub fn is_unit(&self) -> bool {
-        matches!(self.ty.value, Ty::Tuple(0, ..))
+        matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..))
     }
     pub fn is_bool(&self) -> bool {
-        matches!(self.ty.value, Ty::Scalar(Scalar::Bool))
+        matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool))
     }
 
     pub fn is_mutable_reference(&self) -> bool {
-        matches!(self.ty.value, Ty::Ref(hir_ty::Mutability::Mut, ..))
+        matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
     }
 
     pub fn remove_ref(&self) -> Option<Type> {
-        match &self.ty.value {
-            Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())),
+        match &self.ty.value.interned(&Interner) {
+            TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())),
             _ => None,
         }
     }
 
     pub fn is_unknown(&self) -> bool {
-        matches!(self.ty.value, Ty::Unknown)
+        self.ty.value.is_unknown()
     }
 
     /// Checks that particular type `ty` implements `std::future::Future`.
@@ -1684,7 +1684,7 @@ pub fn normalize_trait_assoc_type(
             .build();
         let predicate = ProjectionPredicate {
             projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst },
-            ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)),
+            ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner),
         };
         let goal = Canonical {
             value: InEnvironment::new(
@@ -1712,8 +1712,8 @@ pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
     }
 
     pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
-        let def = match self.ty.value {
-            Ty::FnDef(def, _) => Some(def),
+        let def = match self.ty.value.interned(&Interner) {
+            &TyKind::FnDef(def, _) => Some(def),
             _ => None,
         };
 
@@ -1722,16 +1722,16 @@ pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
     }
 
     pub fn is_closure(&self) -> bool {
-        matches!(&self.ty.value, Ty::Closure { .. })
+        matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. })
     }
 
     pub fn is_fn(&self) -> bool {
-        matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. })
+        matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
     }
 
     pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
-        let adt_id = match self.ty.value {
-            Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
+        let adt_id = match self.ty.value.interned(&Interner) {
+            &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
             _ => return false,
         };
 
@@ -1743,24 +1743,25 @@ pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
     }
 
     pub fn is_raw_ptr(&self) -> bool {
-        matches!(&self.ty.value, Ty::Raw(..))
+        matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..))
     }
 
     pub fn contains_unknown(&self) -> bool {
         return go(&self.ty.value);
 
         fn go(ty: &Ty) -> bool {
-            match ty {
-                Ty::Unknown => true,
-                _ => ty.substs().map_or(false, |substs| substs.iter().any(go)),
+            if ty.is_unknown() {
+                true
+            } else {
+                ty.substs().map_or(false, |substs| substs.iter().any(go))
             }
         }
     }
 
     pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
-        let (variant_id, substs) = match self.ty.value {
-            Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
-            Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
+        let (variant_id, substs) = match self.ty.value.interned(&Interner) {
+            &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
+            &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
             _ => return Vec::new(),
         };
 
@@ -1775,7 +1776,7 @@ pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
     }
 
     pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
-        if let Ty::Tuple(_, substs) = &self.ty.value {
+        if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) {
             substs.iter().map(|ty| self.derived(ty.clone())).collect()
         } else {
             Vec::new()
@@ -1957,33 +1958,33 @@ fn walk_bounds(
 
         fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
             let ty = type_.ty.value.strip_references();
-            match ty {
-                Ty::Adt(..) => {
+            match ty.interned(&Interner) {
+                TyKind::Adt(..) => {
                     cb(type_.derived(ty.clone()));
                 }
-                Ty::AssociatedType(..) => {
+                TyKind::AssociatedType(..) => {
                     if let Some(_) = ty.associated_type_parent_trait(db) {
                         cb(type_.derived(ty.clone()));
                     }
                 }
-                Ty::OpaqueType(..) => {
+                TyKind::OpaqueType(..) => {
                     if let Some(bounds) = ty.impl_trait_bounds(db) {
                         walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
                     }
                 }
-                Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
+                TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
                     if let Some(bounds) = ty.impl_trait_bounds(db) {
                         walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
                     }
 
                     walk_substs(db, type_, &opaque_ty.parameters, cb);
                 }
-                Ty::Placeholder(_) => {
+                TyKind::Placeholder(_) => {
                     if let Some(bounds) = ty.impl_trait_bounds(db) {
                         walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
                     }
                 }
-                Ty::Dyn(bounds) => {
+                TyKind::Dyn(bounds) => {
                     walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
                 }
 
index be1fd1f13d616e7e04cc61c55306278780677b9b..09009a3d8c54faa6169394abbec1180bf4da9301 100644 (file)
@@ -14,7 +14,7 @@
     db::HirDatabase,
     traits::{InEnvironment, Solution},
     utils::generics,
-    BoundVar, Canonical, DebruijnIndex, Obligation, Substs, TraitRef, Ty,
+    BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substs, TraitRef, Ty, TyKind,
 };
 
 const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -81,7 +81,8 @@ fn deref_by_trait(
 
     // Now do the assoc type projection
     let projection = super::traits::ProjectionPredicate {
-        ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())),
+        ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
+            .intern(&Interner),
         projection_ty: super::ProjectionTy { associated_ty: target, parameters },
     };
 
@@ -114,8 +115,8 @@ fn deref_by_trait(
             // new variables in that case
 
             for i in 1..vars.0.kinds.len() {
-                if vars.0.value[i - 1]
-                    != Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
+                if vars.0.value[i - 1].interned(&Interner)
+                    != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
                 {
                     warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
                     return None;
index 2751cd304a3c635f2dabe18c8f5faa5568303c01..b2bfd68d4e5c2ea833b492f7819570c6b0b8f7a6 100644 (file)
@@ -15,7 +15,7 @@
         MissingPatFields, RemoveThisSemicolon,
     },
     utils::variant_data,
-    AdtId, InferenceResult, Ty,
+    AdtId, InferenceResult, Interner, Ty, TyKind,
 };
 
 pub(crate) use hir_def::{
@@ -289,11 +289,10 @@ fn validate_match(
         let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
             db.body_with_source_map(self.owner.into());
 
-        let match_expr_ty = match infer.type_of_expr.get(match_expr) {
-            // If we can't resolve the type of the match expression
-            // we cannot perform exhaustiveness checks.
-            None | Some(Ty::Unknown) => return,
-            Some(ty) => ty,
+        let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
+            return;
+        } else {
+            &infer.type_of_expr[match_expr]
         };
 
         let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db };
@@ -379,14 +378,14 @@ fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dy
             _ => return,
         };
 
-        let (params, required) = match mismatch.expected {
-            Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
-                if enum_id == core_result_enum =>
+        let (params, required) = match mismatch.expected.interned(&Interner) {
+            TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
+                if *enum_id == core_result_enum =>
             {
                 (parameters, "Ok".to_string())
             }
-            Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
-                if enum_id == core_option_enum =>
+            TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
+                if *enum_id == core_option_enum =>
             {
                 (parameters, "Some".to_string())
             }
index 04d39c5714eda85c03a8975c8e109e599c21212e..5a5cdcbf3a5557710bfd9055b9cb1818ecb1ee94 100644 (file)
 use la_arena::Idx;
 use smallvec::{smallvec, SmallVec};
 
-use crate::{db::HirDatabase, AdtId, InferenceResult, Ty};
+use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind};
 
 #[derive(Debug, Clone, Copy)]
 /// Either a pattern from the source code being analyzed, represented as
@@ -626,13 +626,13 @@ pub(super) fn is_useful(
     // - enum with no variants
     // - `!` type
     // In those cases, no match arm is useful.
-    match cx.infer[cx.match_expr].strip_references() {
-        Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
+    match cx.infer[cx.match_expr].strip_references().interned(&Interner) {
+        TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
             if cx.db.enum_data(*enum_id).variants.is_empty() {
                 return Ok(Usefulness::NotUseful);
             }
         }
-        Ty::Never => return Ok(Usefulness::NotUseful),
+        TyKind::Never => return Ok(Usefulness::NotUseful),
         _ => (),
     }
 
index e77a20fea14625feffaed2582982179d08529026..e095bee28265753ebdf42f06eb52e5722fb21799 100644 (file)
@@ -11,7 +11,7 @@
 };
 use hir_expand::diagnostics::DiagnosticSink;
 
-use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty};
+use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind};
 
 pub(super) struct UnsafeValidator<'a, 'b: 'a> {
     owner: DefWithBodyId,
@@ -110,7 +110,7 @@ fn walk_unsafe(
             }
         }
         Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
-            if let Ty::Raw(..) = &infer[*expr] {
+            if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) {
                 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
             }
         }
index ab51cb0a6ee4b42ac939b7545d43179fb4d3dc80..ee15f4f52a7d79cdbd83ab57ea5e62c81268eb66 100644 (file)
@@ -12,8 +12,8 @@
 
 use crate::{
     db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig,
-    GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs,
-    TraitRef, Ty,
+    GenericPredicate, Interner, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar,
+    Substs, TraitRef, Ty, TyKind,
 };
 
 pub struct HirFormatter<'a> {
@@ -267,32 +267,32 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
 
-        match self {
-            Ty::Never => write!(f, "!")?,
-            Ty::Str => write!(f, "str")?,
-            Ty::Scalar(Scalar::Bool) => write!(f, "bool")?,
-            Ty::Scalar(Scalar::Char) => write!(f, "char")?,
-            &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
-            &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
-            &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
-            Ty::Slice(parameters) => {
+        match self.interned(&Interner) {
+            TyKind::Never => write!(f, "!")?,
+            TyKind::Str => write!(f, "str")?,
+            TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
+            TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
+            &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
+            &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
+            &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
+            TyKind::Slice(parameters) => {
                 let t = parameters.as_single();
                 write!(f, "[")?;
                 t.hir_fmt(f)?;
                 write!(f, "]")?;
             }
-            Ty::Array(parameters) => {
+            TyKind::Array(parameters) => {
                 let t = parameters.as_single();
                 write!(f, "[")?;
                 t.hir_fmt(f)?;
                 write!(f, "; _]")?;
             }
-            Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => {
+            TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => {
                 let t = parameters.as_single();
                 let ty_display =
                     t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
 
-                if matches!(self, Ty::Raw(..)) {
+                if matches!(self.interned(&Interner), TyKind::Raw(..)) {
                     write!(
                         f,
                         "*{}",
@@ -313,11 +313,11 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 }
 
                 let datas;
-                let predicates = match t {
-                    Ty::Dyn(predicates) if predicates.len() > 1 => {
+                let predicates = match t.interned(&Interner) {
+                    TyKind::Dyn(predicates) if predicates.len() > 1 => {
                         Cow::Borrowed(predicates.as_ref())
                     }
-                    &Ty::Alias(AliasTy::Opaque(OpaqueTy {
+                    &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
                         opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx),
                         ref parameters,
                     })) => {
@@ -347,7 +347,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     write!(f, "{}", ty_display)?;
                 }
             }
-            Ty::Tuple(_, substs) => {
+            TyKind::Tuple(_, substs) => {
                 if substs.len() == 1 {
                     write!(f, "(")?;
                     substs[0].hir_fmt(f)?;
@@ -358,11 +358,11 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     write!(f, ")")?;
                 }
             }
-            Ty::Function(fn_ptr) => {
+            TyKind::Function(fn_ptr) => {
                 let sig = CallableSig::from_fn_ptr(fn_ptr);
                 sig.hir_fmt(f)?;
             }
-            Ty::FnDef(def, parameters) => {
+            TyKind::FnDef(def, parameters) => {
                 let def = *def;
                 let sig = f.db.callable_item_signature(def).subst(parameters);
                 match def {
@@ -401,7 +401,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     write!(f, " -> {}", ret_display)?;
                 }
             }
-            Ty::Adt(AdtId(def_id), parameters) => {
+            TyKind::Adt(AdtId(def_id), parameters) => {
                 match f.display_target {
                     DisplayTarget::Diagnostics | DisplayTarget::Test => {
                         let name = match *def_id {
@@ -427,37 +427,39 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 }
 
                 if parameters.len() > 0 {
-                    let parameters_to_write =
-                        if f.display_target.is_source_code() || f.omit_verbose_types() {
-                            match self
-                                .as_generic_def()
-                                .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
-                                .filter(|defaults| !defaults.is_empty())
-                            {
-                                None => parameters.0.as_ref(),
-                                Some(default_parameters) => {
-                                    let mut default_from = 0;
-                                    for (i, parameter) in parameters.iter().enumerate() {
-                                        match (parameter, default_parameters.get(i)) {
-                                            (&Ty::Unknown, _) | (_, None) => {
+                    let parameters_to_write = if f.display_target.is_source_code()
+                        || f.omit_verbose_types()
+                    {
+                        match self
+                            .as_generic_def()
+                            .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
+                            .filter(|defaults| !defaults.is_empty())
+                        {
+                            None => parameters.0.as_ref(),
+                            Some(default_parameters) => {
+                                let mut default_from = 0;
+                                for (i, parameter) in parameters.iter().enumerate() {
+                                    match (parameter.interned(&Interner), default_parameters.get(i))
+                                    {
+                                        (&TyKind::Unknown, _) | (_, None) => {
+                                            default_from = i + 1;
+                                        }
+                                        (_, Some(default_parameter)) => {
+                                            let actual_default = default_parameter
+                                                .clone()
+                                                .subst(&parameters.prefix(i));
+                                            if parameter != &actual_default {
                                                 default_from = i + 1;
                                             }
-                                            (_, Some(default_parameter)) => {
-                                                let actual_default = default_parameter
-                                                    .clone()
-                                                    .subst(&parameters.prefix(i));
-                                                if parameter != &actual_default {
-                                                    default_from = i + 1;
-                                                }
-                                            }
                                         }
                                     }
-                                    &parameters.0[0..default_from]
                                 }
+                                &parameters.0[0..default_from]
                             }
-                        } else {
-                            parameters.0.as_ref()
-                        };
+                        }
+                    } else {
+                        parameters.0.as_ref()
+                    };
                     if !parameters_to_write.is_empty() {
                         write!(f, "<")?;
                         f.write_joined(parameters_to_write, ", ")?;
@@ -465,7 +467,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 }
             }
-            Ty::AssociatedType(type_alias, parameters) => {
+            TyKind::AssociatedType(type_alias, parameters) => {
                 let trait_ = match type_alias.lookup(f.db.upcast()).container {
                     AssocContainerId::TraitId(it) => it,
                     _ => panic!("not an associated type"),
@@ -488,11 +490,11 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     projection_ty.hir_fmt(f)?;
                 }
             }
-            Ty::ForeignType(type_alias) => {
+            TyKind::ForeignType(type_alias) => {
                 let type_alias = f.db.type_alias_data(*type_alias);
                 write!(f, "{}", type_alias.name)?;
             }
-            Ty::OpaqueType(opaque_ty_id, parameters) => {
+            TyKind::OpaqueType(opaque_ty_id, parameters) => {
                 match opaque_ty_id {
                     &OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
                         let datas =
@@ -511,7 +513,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 }
             }
-            Ty::Closure(.., substs) => {
+            TyKind::Closure(.., substs) => {
                 let sig = substs[0].callable_sig(f.db);
                 if let Some(sig) = sig {
                     if sig.params().is_empty() {
@@ -535,7 +537,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     write!(f, "{{closure}}")?;
                 }
             }
-            Ty::Placeholder(id) => {
+            TyKind::Placeholder(id) => {
                 let generics = generics(f.db.upcast(), id.parent);
                 let param_data = &generics.params.types[id.local_id];
                 match param_data.provenance {
@@ -553,12 +555,12 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 }
             }
-            Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
-            Ty::Dyn(predicates) => {
+            TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
+            TyKind::Dyn(predicates) => {
                 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
             }
-            Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
-            Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
+            TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
+            TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
                 match opaque_ty.opaque_ty_id {
                     OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
                         let datas =
@@ -574,7 +576,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 };
             }
-            Ty::Unknown => {
+            TyKind::Unknown => {
                 if f.display_target.is_source_code() {
                     return Err(HirDisplayError::DisplaySourceCodeError(
                         DisplaySourceCodeError::UnknownType,
@@ -582,7 +584,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 }
                 write!(f, "{{unknown}}")?;
             }
-            Ty::InferenceVar(..) => write!(f, "_")?,
+            TyKind::InferenceVar(..) => write!(f, "_")?,
         }
         Ok(())
     }
index 4d771a91e8d99e340d603103df28c7b574737653..acde99b04c3800927a0e5fdc427a8fb362506a5e 100644 (file)
@@ -41,7 +41,8 @@
     InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
 };
 use crate::{
-    db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy,
+    db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
+    AliasTy, Interner, TyKind,
 };
 
 pub(crate) use unify::unify;
@@ -169,7 +170,7 @@ impl Index<ExprId> for InferenceResult {
     type Output = Ty;
 
     fn index(&self, expr: ExprId) -> &Ty {
-        self.type_of_expr.get(expr).unwrap_or(&Ty::Unknown)
+        self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown))
     }
 }
 
@@ -177,7 +178,7 @@ impl Index<PatId> for InferenceResult {
     type Output = Ty;
 
     fn index(&self, pat: PatId) -> &Ty {
-        self.type_of_pat.get(pat).unwrap_or(&Ty::Unknown)
+        self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown))
     }
 }
 
@@ -226,7 +227,7 @@ fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Sel
             result: InferenceResult::default(),
             table: unify::InferenceTable::new(),
             obligations: Vec::default(),
-            return_ty: Ty::Unknown, // set in collect_fn_signature
+            return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature
             trait_env: TraitEnvironment::lower(db, &resolver),
             db,
             owner,
@@ -237,15 +238,19 @@ fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Sel
         }
     }
 
+    fn err_ty(&self) -> Ty {
+        TyKind::Unknown.intern(&Interner)
+    }
+
     fn resolve_all(mut self) -> InferenceResult {
         // FIXME resolve obligations as well (use Guidance if necessary)
         let mut result = std::mem::take(&mut self.result);
         for ty in result.type_of_expr.values_mut() {
-            let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
+            let resolved = self.table.resolve_ty_completely(ty.clone());
             *ty = resolved;
         }
         for ty in result.type_of_pat.values_mut() {
-            let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
+            let resolved = self.table.resolve_ty_completely(ty.clone());
             *ty = resolved;
         }
         result
@@ -298,8 +303,8 @@ fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
 
     /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
     fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
-        match ty {
-            Ty::Unknown => self.table.new_type_var(),
+        match ty.interned(&Interner) {
+            TyKind::Unknown => self.table.new_type_var(),
             _ => ty,
         }
     }
@@ -383,7 +388,7 @@ fn resolve_associated_type_with_params(
                 self.obligations.push(Obligation::Projection(projection));
                 self.resolve_ty_as_possible(ty)
             }
-            None => Ty::Unknown,
+            None => self.err_ty(),
         }
     }
 
@@ -395,8 +400,10 @@ fn resolve_associated_type_with_params(
     /// to do it as well.
     fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
         let ty = self.resolve_ty_as_possible(ty);
-        ty.fold(&mut |ty| match ty {
-            Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty),
+        ty.fold(&mut |ty| match ty.interned(&Interner) {
+            TyKind::Alias(AliasTy::Projection(proj_ty)) => {
+                self.normalize_projection_ty(proj_ty.clone())
+            }
             _ => ty,
         })
     }
@@ -412,7 +419,7 @@ fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
     fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
         let path = match path {
             Some(path) => path,
-            None => return (Ty::Unknown, None),
+            None => return (self.err_ty(), None),
         };
         let resolver = &self.resolver;
         let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
@@ -421,7 +428,7 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
         let (resolution, unresolved) =
             match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
                 Some(it) => it,
-                None => return (Ty::Unknown, None),
+                None => return (self.err_ty(), None),
             };
         return match resolution {
             TypeNs::AdtId(AdtId::StructId(strukt)) => {
@@ -462,11 +469,11 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
                             }
                         }
                         // FIXME potentially resolve assoc type
-                        (Ty::Unknown, None)
+                        (self.err_ty(), None)
                     }
                     Some(_) => {
                         // FIXME diagnostic
-                        (Ty::Unknown, None)
+                        (self.err_ty(), None)
                     }
                 }
             }
@@ -480,15 +487,15 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
             }
             TypeNs::AdtSelfType(_) => {
                 // FIXME this could happen in array size expressions, once we're checking them
-                (Ty::Unknown, None)
+                (self.err_ty(), None)
             }
             TypeNs::GenericParam(_) => {
                 // FIXME potentially resolve assoc type
-                (Ty::Unknown, None)
+                (self.err_ty(), None)
             }
             TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => {
                 // FIXME diagnostic
-                (Ty::Unknown, None)
+                (self.err_ty(), None)
             }
         };
 
@@ -500,7 +507,7 @@ fn forbid_unresolved_segments(
                 result
             } else {
                 // FIXME diagnostic
-                (Ty::Unknown, None)
+                (TyKind::Unknown.intern(&Interner), None)
             }
         }
 
@@ -711,12 +718,12 @@ fn rvalue_hint(ty: Ty) -> Self {
 
     /// This expresses no expectation on the type.
     fn none() -> Self {
-        Expectation { ty: Ty::Unknown, rvalue_hint: false }
+        Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false }
     }
 
     fn coercion_target(&self) -> &Ty {
         if self.rvalue_hint {
-            &Ty::Unknown
+            &Ty(TyKind::Unknown)
         } else {
             &self.ty
         }
index 7e8846f274c725f53830b5457b5f5cabced4e398..36670043aeaaa91eeffa0fe233e79034e3aad041 100644 (file)
@@ -7,7 +7,7 @@
 use chalk_ir::{Mutability, TyVariableKind};
 use hir_def::lang_item::LangItemTarget;
 
-use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty};
+use crate::{autoderef, traits::Solution, Interner, Obligation, Substs, TraitRef, Ty, TyKind};
 
 use super::{InEnvironment, InferenceContext};
 
@@ -33,7 +33,9 @@ pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
         } else if self.coerce(ty2, ty1) {
             ty1.clone()
         } else {
-            if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) {
+            if let (TyKind::FnDef(..), TyKind::FnDef(..)) =
+                (ty1.interned(&Interner), ty2.interned(&Interner))
+            {
                 cov_mark::hit!(coerce_fn_reification);
                 // Special case: two function types. Try to coerce both to
                 // pointers to have a chance at getting a match. See
@@ -51,13 +53,13 @@ pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
     }
 
     fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
-        match (&from_ty, to_ty) {
+        match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
             // Never type will make type variable to fallback to Never Type instead of Unknown.
-            (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => {
+            (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => {
                 self.table.type_variable_table.set_diverging(*tv, true);
                 return true;
             }
-            (Ty::Never, _) => return true,
+            (TyKind::Never, _) => return true,
 
             // Trivial cases, this should go after `never` check to
             // avoid infer result type to be never
@@ -69,33 +71,33 @@ fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
         }
 
         // Pointer weakening and function to pointer
-        match (&mut from_ty, to_ty) {
+        match (&mut from_ty.0, to_ty.interned(&Interner)) {
             // `*mut T` -> `*const T`
             // `&mut T` -> `&T`
-            (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..))
-            | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => {
+            (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
+            | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
                 *m1 = *m2;
             }
             // `&T` -> `*const T`
             // `&mut T` -> `*mut T`/`*const T`
-            (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..))
-            | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => {
-                from_ty = Ty::Raw(m2, substs.clone());
+            (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
+            | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => {
+                from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
             }
 
             // Illegal mutability conversion
-            (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..))
-            | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false,
+            (TyKind::Raw(Mutability::Not, ..), TyKind::Raw(Mutability::Mut, ..))
+            | (TyKind::Ref(Mutability::Not, ..), TyKind::Ref(Mutability::Mut, ..)) => return false,
 
             // `{function_type}` -> `fn()`
-            (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) {
+            (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) {
                 None => return false,
                 Some(sig) => {
                     from_ty = Ty::fn_ptr(sig);
                 }
             },
 
-            (Ty::Closure(.., substs), Ty::Function { .. }) => {
+            (TyKind::Closure(.., substs), TyKind::Function { .. }) => {
                 from_ty = substs[0].clone();
             }
 
@@ -107,9 +109,11 @@ fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
         }
 
         // Auto Deref if cannot coerce
-        match (&from_ty, to_ty) {
+        match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
             // FIXME: DerefMut
-            (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]),
+            (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => {
+                self.unify_autoderef_behind_ref(&st1[0], &st2[0])
+            }
 
             // Otherwise, normal unify
             _ => self.unify(&from_ty, to_ty),
index 262177ffbe11758bd6ae1ac62abbcb580fa0e2f3..4e77f22fdc37e276904f79e6e1ed32196163ba00 100644 (file)
@@ -20,8 +20,8 @@
     primitive::{self, UintTy},
     traits::{FnTrait, InEnvironment},
     utils::{generics, variant_data, Generics},
-    AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar,
-    Substs, TraitRef, Ty,
+    AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, OpaqueTyId, Rawness,
+    Scalar, Substs, TraitRef, Ty, TyKind,
 };
 
 use super::{
@@ -57,7 +57,7 @@ pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation)
             // Return actual type when type mismatch.
             // This is needed for diagnostic when return type mismatch.
             ty
-        } else if expected.coercion_target() == &Ty::Unknown {
+        } else if expected.coercion_target().is_unknown() {
             ty
         } else {
             expected.ty.clone()
@@ -84,7 +84,7 @@ fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Ve
             arg_tys.push(arg);
         }
         let parameters = param_builder.build();
-        let arg_ty = Ty::Tuple(num_args, parameters);
+        let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner);
         let substs =
             Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
 
@@ -116,10 +116,13 @@ pub(crate) fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<T
     fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
         let body = Arc::clone(&self.body); // avoid borrow checker problem
         let ty = match &body[tgt_expr] {
-            Expr::Missing => Ty::Unknown,
+            Expr::Missing => self.err_ty(),
             Expr::If { condition, then_branch, else_branch } => {
                 // if let is desugared to match, so this is always simple if
-                self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool)));
+                self.infer_expr(
+                    *condition,
+                    &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
+                );
 
                 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
                 let mut both_arms_diverge = Diverges::Always;
@@ -167,14 +170,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::TryBlock { body } => {
                 let _inner = self.infer_expr(*body, expected);
                 // FIXME should be std::result::Result<{inner}, _>
-                Ty::Unknown
+                self.err_ty()
             }
             Expr::Async { body } => {
                 // Use the first type parameter as the output type of future.
                 // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
                 let inner_ty = self.infer_expr(*body, &Expectation::none());
                 let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body);
-                Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty))
+                TyKind::OpaqueType(opaque_ty_id, Substs::single(inner_ty)).intern(&Interner)
             }
             Expr::Loop { body, label } => {
                 self.breakables.push(BreakableContext {
@@ -192,17 +195,20 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                 if ctxt.may_break {
                     ctxt.break_ty
                 } else {
-                    Ty::Never
+                    TyKind::Never.intern(&Interner)
                 }
             }
             Expr::While { condition, body, label } => {
                 self.breakables.push(BreakableContext {
                     may_break: false,
-                    break_ty: Ty::Unknown,
+                    break_ty: self.err_ty(),
                     label: label.map(|label| self.body[label].name.clone()),
                 });
                 // while let is desugared to a match loop, so this is always simple while
-                self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool)));
+                self.infer_expr(
+                    *condition,
+                    &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
+                );
                 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
                 let _ctxt = self.breakables.pop().expect("breakable stack broken");
                 // the body may not run, so it diverging doesn't mean we diverge
@@ -214,7 +220,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
 
                 self.breakables.push(BreakableContext {
                     may_break: false,
-                    break_ty: Ty::Unknown,
+                    break_ty: self.err_ty(),
                     label: label.map(|label| self.body[label].name.clone()),
                 });
                 let pat_ty =
@@ -249,12 +255,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     None => self.table.new_type_var(),
                 };
                 sig_tys.push(ret_ty.clone());
-                let sig_ty = Ty::Function(FnPointer {
+                let sig_ty = TyKind::Function(FnPointer {
                     num_args: sig_tys.len() - 1,
                     sig: FnSig { variadic: false },
                     substs: Substs(sig_tys.clone().into()),
-                });
-                let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty));
+                })
+                .intern(&Interner);
+                let closure_ty =
+                    TyKind::Closure(self.owner, tgt_expr, Substs::single(sig_ty)).intern(&Interner);
 
                 // Eagerly try to relate the closure type with the expected
                 // type, otherwise we often won't have enough information to
@@ -295,7 +303,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                             args.len(),
                         )
                     })
-                    .unwrap_or((Vec::new(), Ty::Unknown));
+                    .unwrap_or((Vec::new(), self.err_ty()));
                 self.register_obligations_for_call(&callee_ty);
                 self.check_call_arguments(args, &param_tys);
                 self.normalize_associated_types_in(ret_ty)
@@ -305,8 +313,11 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::Match { expr, arms } => {
                 let input_ty = self.infer_expr(*expr, &Expectation::none());
 
-                let mut result_ty =
-                    if arms.is_empty() { Ty::Never } else { self.table.new_type_var() };
+                let mut result_ty = if arms.is_empty() {
+                    TyKind::Never.intern(&Interner)
+                } else {
+                    self.table.new_type_var()
+                };
 
                 let matchee_diverges = self.diverges;
                 let mut all_arms_diverge = Diverges::Always;
@@ -317,7 +328,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     if let Some(guard_expr) = arm.guard {
                         self.infer_expr(
                             guard_expr,
-                            &Expectation::has_type(Ty::Scalar(Scalar::Bool)),
+                            &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
                         );
                     }
 
@@ -333,9 +344,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::Path(p) => {
                 // FIXME this could be more efficient...
                 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
-                self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
+                self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(self.err_ty())
             }
-            Expr::Continue { .. } => Ty::Never,
+            Expr::Continue { .. } => TyKind::Never.intern(&Interner),
             Expr::Break { expr, label } => {
                 let val_ty = if let Some(expr) = expr {
                     self.infer_expr(*expr, &Expectation::none())
@@ -347,7 +358,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
                         ctxt.break_ty.clone()
                     } else {
-                        Ty::Unknown
+                        self.err_ty()
                     };
 
                 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
@@ -360,7 +371,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                         expr: tgt_expr,
                     });
                 }
-                Ty::Never
+                TyKind::Never.intern(&Interner)
             }
             Expr::Return { expr } => {
                 if let Some(expr) = expr {
@@ -369,14 +380,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     let unit = Ty::unit();
                     self.coerce(&unit, &self.return_ty.clone());
                 }
-                Ty::Never
+                TyKind::Never.intern(&Interner)
             }
             Expr::Yield { expr } => {
                 // FIXME: track yield type for coercion
                 if let Some(expr) = expr {
                     self.infer_expr(*expr, &Expectation::none());
                 }
-                Ty::Never
+                TyKind::Never.intern(&Interner)
             }
             Expr::RecordLit { path, fields, spread } => {
                 let (ty, def_id) = self.resolve_variant(path.as_ref());
@@ -404,8 +415,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     if let Some(field_def) = field_def {
                         self.result.record_field_resolutions.insert(field.expr, field_def);
                     }
-                    let field_ty = field_def
-                        .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs));
+                    let field_ty = field_def.map_or(self.err_ty(), |it| {
+                        field_types[it.local_id].clone().subst(&substs)
+                    });
                     self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
                 }
                 if let Some(expr) = spread {
@@ -424,27 +436,33 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                         environment: self.trait_env.clone(),
                     },
                 )
-                .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
-                    Ty::Tuple(_, substs) => {
-                        name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned())
-                    }
-                    Ty::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
-                        self.db.struct_data(s).variant_data.field(name).map(|local_id| {
-                            let field = FieldId { parent: s.into(), local_id };
-                            self.write_field_resolution(tgt_expr, field);
-                            self.db.field_types(s.into())[field.local_id].clone().subst(&parameters)
-                        })
-                    }
-                    Ty::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => {
-                        self.db.union_data(u).variant_data.field(name).map(|local_id| {
-                            let field = FieldId { parent: u.into(), local_id };
-                            self.write_field_resolution(tgt_expr, field);
-                            self.db.field_types(u.into())[field.local_id].clone().subst(&parameters)
-                        })
+                .find_map(|derefed_ty| {
+                    match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) {
+                        TyKind::Tuple(_, substs) => {
+                            name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned())
+                        }
+                        TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
+                            self.db.struct_data(*s).variant_data.field(name).map(|local_id| {
+                                let field = FieldId { parent: (*s).into(), local_id };
+                                self.write_field_resolution(tgt_expr, field);
+                                self.db.field_types((*s).into())[field.local_id]
+                                    .clone()
+                                    .subst(&parameters)
+                            })
+                        }
+                        TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => {
+                            self.db.union_data(*u).variant_data.field(name).map(|local_id| {
+                                let field = FieldId { parent: (*u).into(), local_id };
+                                self.write_field_resolution(tgt_expr, field);
+                                self.db.field_types((*u).into())[field.local_id]
+                                    .clone()
+                                    .subst(&parameters)
+                            })
+                        }
+                        _ => None,
                     }
-                    _ => None,
                 })
-                .unwrap_or(Ty::Unknown);
+                .unwrap_or(self.err_ty());
                 let ty = self.insert_type_vars(ty);
                 self.normalize_associated_types_in(ty)
             }
@@ -481,9 +499,10 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                 };
                 let inner_ty = self.infer_expr_inner(*expr, &expectation);
                 match rawness {
-                    Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)),
-                    Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)),
+                    Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)),
+                    Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)),
                 }
+                .intern(&Interner)
             }
             Expr::Box { expr } => {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
@@ -499,7 +518,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     sb = sb.fill(repeat_with(|| self.table.new_type_var()));
                     Ty::adt_ty(box_, sb.build())
                 } else {
-                    Ty::Unknown
+                    self.err_ty()
                 }
             }
             Expr::UnaryOp { expr, op } => {
@@ -519,31 +538,31 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                                 Some(derefed_ty) => {
                                     canonicalized.decanonicalize_ty(derefed_ty.value)
                                 }
-                                None => Ty::Unknown,
+                                None => self.err_ty(),
                             }
                         }
-                        None => Ty::Unknown,
+                        None => self.err_ty(),
                     },
                     UnaryOp::Neg => {
-                        match &inner_ty {
+                        match inner_ty.interned(&Interner) {
                             // Fast path for builtins
-                            Ty::Scalar(Scalar::Int(_))
-                            | Ty::Scalar(Scalar::Uint(_))
-                            | Ty::Scalar(Scalar::Float(_))
-                            | Ty::InferenceVar(_, TyVariableKind::Integer)
-                            | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty,
+                            TyKind::Scalar(Scalar::Int(_))
+                            | TyKind::Scalar(Scalar::Uint(_))
+                            | TyKind::Scalar(Scalar::Float(_))
+                            | TyKind::InferenceVar(_, TyVariableKind::Integer)
+                            | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty,
                             // Otherwise we resolve via the std::ops::Neg trait
                             _ => self
                                 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
                         }
                     }
                     UnaryOp::Not => {
-                        match &inner_ty {
+                        match inner_ty.interned(&Interner) {
                             // Fast path for builtins
-                            Ty::Scalar(Scalar::Bool)
-                            | Ty::Scalar(Scalar::Int(_))
-                            | Ty::Scalar(Scalar::Uint(_))
-                            | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
+                            TyKind::Scalar(Scalar::Bool)
+                            | TyKind::Scalar(Scalar::Int(_))
+                            | TyKind::Scalar(Scalar::Uint(_))
+                            | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
                             // Otherwise we resolve via the std::ops::Not trait
                             _ => self
                                 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
@@ -554,7 +573,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::BinaryOp { lhs, rhs, op } => match op {
                 Some(op) => {
                     let lhs_expectation = match op {
-                        BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)),
+                        BinaryOp::LogicOp(..) => {
+                            Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner))
+                        }
                         _ => Expectation::none(),
                     };
                     let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
@@ -563,7 +584,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
 
                     let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
 
-                    if ret == Ty::Unknown {
+                    if ret.is_unknown() {
                         cov_mark::hit!(infer_expr_inner_binary_operator_overload);
 
                         self.resolve_associated_type_with_params(
@@ -575,7 +596,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                         ret
                     }
                 }
-                _ => Ty::Unknown,
+                _ => self.err_ty(),
             },
             Expr::Range { lhs, rhs, range_type } => {
                 let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
@@ -586,33 +607,33 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                 match (range_type, lhs_ty, rhs_ty) {
                     (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
                         Some(adt) => Ty::adt_ty(adt, Substs::empty()),
-                        None => Ty::Unknown,
+                        None => self.err_ty(),
                     },
                     (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
                         Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
-                        None => Ty::Unknown,
+                        None => self.err_ty(),
                     },
                     (RangeOp::Inclusive, None, Some(ty)) => {
                         match self.resolve_range_to_inclusive() {
                             Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
-                            None => Ty::Unknown,
+                            None => self.err_ty(),
                         }
                     }
                     (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
                         Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
-                        None => Ty::Unknown,
+                        None => self.err_ty(),
                     },
                     (RangeOp::Inclusive, Some(_), Some(ty)) => {
                         match self.resolve_range_inclusive() {
                             Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
-                            None => Ty::Unknown,
+                            None => self.err_ty(),
                         }
                     }
                     (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
                         Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
-                        None => Ty::Unknown,
+                        None => self.err_ty(),
                     },
-                    (RangeOp::Inclusive, _, None) => Ty::Unknown,
+                    (RangeOp::Inclusive, _, None) => self.err_ty(),
                 }
             }
             Expr::Index { base, index } => {
@@ -631,19 +652,19 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                         index_trait,
                     );
                     let self_ty =
-                        self_ty.map_or(Ty::Unknown, |t| canonicalized.decanonicalize_ty(t.value));
+                        self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value));
                     self.resolve_associated_type_with_params(
                         self_ty,
                         self.resolve_ops_index_output(),
                         &[index_ty],
                     )
                 } else {
-                    Ty::Unknown
+                    self.err_ty()
                 }
             }
             Expr::Tuple { exprs } => {
-                let mut tys = match &expected.ty {
-                    Ty::Tuple(_, substs) => substs
+                let mut tys = match expected.ty.interned(&Interner) {
+                    TyKind::Tuple(_, substs) => substs
                         .iter()
                         .cloned()
                         .chain(repeat_with(|| self.table.new_type_var()))
@@ -656,11 +677,11 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
                 }
 
-                Ty::Tuple(tys.len(), Substs(tys.into()))
+                TyKind::Tuple(tys.len(), Substs(tys.into())).intern(&Interner)
             }
             Expr::Array(array) => {
-                let elem_ty = match &expected.ty {
-                    Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(),
+                let elem_ty = match expected.ty.interned(&Interner) {
+                    TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(),
                     _ => self.table.new_type_var(),
                 };
 
@@ -677,43 +698,51 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                         );
                         self.infer_expr(
                             *repeat,
-                            &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))),
+                            &Expectation::has_type(
+                                TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
+                            ),
                         );
                     }
                 }
 
-                Ty::Array(Substs::single(elem_ty))
+                TyKind::Array(Substs::single(elem_ty)).intern(&Interner)
             }
             Expr::Literal(lit) => match lit {
-                Literal::Bool(..) => Ty::Scalar(Scalar::Bool),
-                Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)),
+                Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
+                Literal::String(..) => {
+                    TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner)))
+                        .intern(&Interner)
+                }
                 Literal::ByteString(..) => {
-                    let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8));
-                    let array_type = Ty::Array(Substs::single(byte_type));
-                    Ty::Ref(Mutability::Not, Substs::single(array_type))
+                    let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
+                    let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner);
+                    TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner)
                 }
-                Literal::Char(..) => Ty::Scalar(Scalar::Char),
+                Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
                 Literal::Int(_v, ty) => match ty {
                     Some(int_ty) => {
-                        Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
+                        TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
+                            .intern(&Interner)
                     }
                     None => self.table.new_integer_var(),
                 },
                 Literal::Uint(_v, ty) => match ty {
                     Some(int_ty) => {
-                        Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
+                        TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
+                            .intern(&Interner)
                     }
                     None => self.table.new_integer_var(),
                 },
                 Literal::Float(_v, ty) => match ty {
                     Some(float_ty) => {
-                        Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
+                        TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
+                            .intern(&Interner)
                     }
                     None => self.table.new_float_var(),
                 },
             },
         };
-        // use a new type variable if we got Ty::Unknown here
+        // use a new type variable if we got unknown here
         let ty = self.insert_type_vars_shallow(ty);
         let ty = self.resolve_ty_as_possible(ty);
         self.write_expr_ty(tgt_expr, ty.clone());
@@ -730,7 +759,7 @@ fn infer_block(
             match stmt {
                 Statement::Let { pat, type_ref, initializer } => {
                     let decl_ty =
-                        type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown);
+                        type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(self.err_ty());
 
                     // Always use the declared type when specified
                     let mut ty = decl_ty.clone();
@@ -738,7 +767,7 @@ fn infer_block(
                     if let Some(expr) = initializer {
                         let actual_ty =
                             self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()));
-                        if decl_ty == Ty::Unknown {
+                        if decl_ty.is_unknown() {
                             ty = actual_ty;
                         }
                     }
@@ -802,7 +831,7 @@ fn infer_method_call(
                 self.write_method_resolution(tgt_expr, func);
                 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
             }
-            None => (receiver_ty, Binders::new(0, Ty::Unknown), None),
+            None => (receiver_ty, Binders::new(0, self.err_ty()), None),
         };
         let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
         let method_ty = method_ty.subst(&substs);
@@ -813,15 +842,17 @@ fn infer_method_call(
                 if !sig.params().is_empty() {
                     (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
                 } else {
-                    (Ty::Unknown, Vec::new(), sig.ret().clone())
+                    (self.err_ty(), Vec::new(), sig.ret().clone())
                 }
             }
-            None => (Ty::Unknown, Vec::new(), Ty::Unknown),
+            None => (self.err_ty(), Vec::new(), self.err_ty()),
         };
         // Apply autoref so the below unification works correctly
         // FIXME: return correct autorefs from lookup_method
         let actual_receiver_ty = match expected_receiver_ty.as_reference() {
-            Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)),
+            Some((_, mutability)) => {
+                TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
+            }
             _ => derefed_receiver_ty,
         };
         self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -837,7 +868,7 @@ fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) {
         // that we have more information about the types of arguments when we
         // type-check the functions. This isn't really the right way to do this.
         for &check_closures in &[false, true] {
-            let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown));
+            let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
             for (&arg, param_ty) in args.iter().zip(param_iter) {
                 let is_closure = matches!(&self.body[arg], Expr::Lambda { .. });
                 if is_closure != check_closures {
@@ -867,7 +898,7 @@ fn substs_for_method_call(
                 if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf {
                     substs.push(receiver_ty.clone());
                 } else {
-                    substs.push(Ty::Unknown);
+                    substs.push(self.err_ty());
                 }
             }
         }
@@ -891,15 +922,15 @@ fn substs_for_method_call(
         };
         let supplied_params = substs.len();
         for _ in supplied_params..total_len {
-            substs.push(Ty::Unknown);
+            substs.push(self.err_ty());
         }
         assert_eq!(substs.len(), total_len);
         Substs(substs.into())
     }
 
     fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
-        if let &Ty::FnDef(def, ref parameters) = callable_ty {
-            let generic_predicates = self.db.generic_predicates(def.into());
+        if let TyKind::FnDef(def, parameters) = callable_ty.interned(&Interner) {
+            let generic_predicates = self.db.generic_predicates((*def).into());
             for predicate in generic_predicates.iter() {
                 let predicate = predicate.clone().subst(parameters);
                 if let Some(obligation) = Obligation::from_predicate(predicate) {
index a0ac8d80fdd76a990b9d0d5ab97e4fe514d6a5ad..a16755cda89bee40768494e6b4a199be72fda187 100644 (file)
@@ -12,7 +12,7 @@
 use hir_expand::name::Name;
 
 use super::{BindingMode, Expectation, InferenceContext};
-use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty};
+use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substs, Ty, TyKind};
 
 impl<'a> InferenceContext<'a> {
     fn infer_tuple_struct_pat(
@@ -46,7 +46,7 @@ fn infer_tuple_struct_pat(
             let expected_ty = var_data
                 .as_ref()
                 .and_then(|d| d.field(&Name::new_tuple_field(i)))
-                .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
+                .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
             let expected_ty = self.normalize_associated_types_in(expected_ty);
             self.infer_pat(subpat, &expected_ty, default_bm);
         }
@@ -80,8 +80,8 @@ fn infer_record_pat(
                 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
             }
 
-            let expected_ty =
-                matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
+            let expected_ty = matching_field
+                .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
             let expected_ty = self.normalize_associated_types_in(expected_ty);
             self.infer_pat(subpat.pat, &expected_ty, default_bm);
         }
@@ -129,7 +129,8 @@ pub(super) fn infer_pat(
                     None => (&args[..], &[][..]),
                 };
                 let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
-                let mut expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
+                let err_ty = self.err_ty();
+                let mut expectations_iter = expectations.iter().chain(repeat(&err_ty));
                 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
 
                 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
@@ -137,7 +138,7 @@ pub(super) fn infer_pat(
                 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
                 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
 
-                Ty::Tuple(inner_tys.len(), Substs(inner_tys.into()))
+                TyKind::Tuple(inner_tys.len(), Substs(inner_tys.into())).intern(&Interner)
             }
             Pat::Or(ref pats) => {
                 if let Some((first_pat, rest)) = pats.split_first() {
@@ -147,7 +148,7 @@ pub(super) fn infer_pat(
                     }
                     ty
                 } else {
-                    Ty::Unknown
+                    self.err_ty()
                 }
             }
             Pat::Ref { pat, mutability } => {
@@ -159,10 +160,10 @@ pub(super) fn infer_pat(
                         }
                         inner_ty
                     }
-                    _ => &Ty::Unknown,
+                    _ => &Ty(TyKind::Unknown),
                 };
                 let subty = self.infer_pat(*pat, expectation, default_bm);
-                Ty::Ref(mutability, Substs::single(subty))
+                TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner)
             }
             Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
                 p.as_ref(),
@@ -178,7 +179,7 @@ pub(super) fn infer_pat(
             Pat::Path(path) => {
                 // FIXME use correct resolver for the surrounding expression
                 let resolver = self.resolver.clone();
-                self.infer_path(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
+                self.infer_path(&resolver, &path, pat.into()).unwrap_or(self.err_ty())
             }
             Pat::Bind { mode, name: _, subpat } => {
                 let mode = if mode == &BindingAnnotation::Unannotated {
@@ -195,7 +196,7 @@ pub(super) fn infer_pat(
 
                 let bound_ty = match mode {
                     BindingMode::Ref(mutability) => {
-                        Ty::Ref(mutability, Substs::single(inner_ty.clone()))
+                        TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner)
                     }
                     BindingMode::Move => inner_ty.clone(),
                 };
@@ -204,17 +205,17 @@ pub(super) fn infer_pat(
                 return inner_ty;
             }
             Pat::Slice { prefix, slice, suffix } => {
-                let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected {
-                    Ty::Array(st) => (Ty::Array, st.as_single().clone()),
-                    Ty::Slice(st) => (Ty::Slice, st.as_single().clone()),
-                    _ => (Ty::Slice, Ty::Unknown),
+                let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
+                    TyKind::Array(st) => (TyKind::Array, st.as_single().clone()),
+                    TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()),
+                    _ => (TyKind::Slice, self.err_ty()),
                 };
 
                 for pat_id in prefix.iter().chain(suffix) {
                     self.infer_pat(*pat_id, &elem_ty, default_bm);
                 }
 
-                let pat_ty = container_ty(Substs::single(elem_ty));
+                let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner);
                 if let Some(slice_pat_id) = slice {
                     self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
                 }
@@ -232,20 +233,20 @@ pub(super) fn infer_pat(
                 Some(box_adt) => {
                     let inner_expected = match expected.as_adt() {
                         Some((adt, substs)) if adt == box_adt => substs.as_single(),
-                        _ => &Ty::Unknown,
+                        _ => &Ty(TyKind::Unknown),
                     };
 
                     let inner_ty = self.infer_pat(*inner, inner_expected, default_bm);
                     Ty::adt_ty(box_adt, Substs::single(inner_ty))
                 }
-                None => Ty::Unknown,
+                None => self.err_ty(),
             },
             Pat::ConstBlock(expr) => {
                 self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
             }
-            Pat::Missing => Ty::Unknown,
+            Pat::Missing => self.err_ty(),
         };
-        // use a new type variable if we got Ty::Unknown here
+        // use a new type variable if we got error type here
         let ty = self.insert_type_vars_shallow(ty);
         if !self.unify(&ty, expected) {
             // FIXME record mismatch, we need to change the type of self.type_mismatches for that
index ae3554bac89a9dda3bb489facb00eb86fffc9f58..3929521785801cc9595a5fe1a73cd24923a1eada 100644 (file)
@@ -9,7 +9,7 @@
 };
 use hir_expand::name::Name;
 
-use crate::{method_resolution, Substs, Ty, ValueTyDefId};
+use crate::{method_resolution, Interner, Substs, Ty, TyKind, ValueTyDefId};
 
 use super::{ExprOrPatId, InferenceContext, TraitRef};
 
@@ -144,7 +144,7 @@ fn resolve_assoc_item(
                     remaining_segments_for_ty,
                     true,
                 );
-                if let Ty::Unknown = ty {
+                if let TyKind::Unknown = ty.interned(&Interner) {
                     return None;
                 }
 
@@ -209,7 +209,7 @@ fn resolve_ty_assoc_item(
         name: &Name,
         id: ExprOrPatId,
     ) -> Option<(ValueNs, Option<Substs>)> {
-        if let Ty::Unknown = ty {
+        if let TyKind::Unknown = ty.interned(&Interner) {
             return None;
         }
 
index 54fcfed10891e43cdd35f252db82535c475061e3..16d89ed1bff7a909bacfefdd29bb0cad15d2fc1c 100644 (file)
@@ -7,8 +7,8 @@
 
 use super::{InferenceContext, Obligation};
 use crate::{
-    BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar,
-    Substs, Ty, TypeWalk,
+    BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner,
+    Scalar, Substs, Ty, TyKind, TypeWalk,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -49,8 +49,8 @@ fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize {
 
     fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
         t.fold_binders(
-            &mut |ty, binders| match ty {
-                Ty::InferenceVar(var, kind) => {
+            &mut |ty, binders| match ty.interned(&Interner) {
+                &TyKind::InferenceVar(var, kind) => {
                     let inner = var.to_inner();
                     if self.var_stack.contains(&inner) {
                         // recursive type
@@ -66,7 +66,7 @@ fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
                     } else {
                         let root = self.ctx.table.var_unification_table.find(inner);
                         let position = self.add(InferenceVar::from_inner(root), kind);
-                        Ty::BoundVar(BoundVar::new(binders, position))
+                        TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
                     }
                 }
                 _ => ty,
@@ -108,10 +108,10 @@ impl<T> Canonicalized<T> {
     pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
         ty.walk_mut_binders(
             &mut |ty, binders| {
-                if let &mut Ty::BoundVar(bound) = ty {
+                if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
                     if bound.debruijn >= binders {
                         let (v, k) = self.free_vars[bound.index];
-                        *ty = Ty::InferenceVar(v, k);
+                        *ty = TyKind::InferenceVar(v, k).intern(&Interner);
                     }
                 }
             },
@@ -142,7 +142,7 @@ pub(super) fn apply_solution(
             // eagerly replace projections in the type; we may be getting types
             // e.g. from where clauses where this hasn't happened yet
             let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
-            ctx.table.unify(&Ty::InferenceVar(v, k), &ty);
+            ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty);
         }
     }
 }
@@ -166,7 +166,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
     // (kind of hacky)
     for (i, var) in vars.iter().enumerate() {
         if &*table.resolve_ty_shallow(var) == var {
-            table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)));
+            table.unify(
+                var,
+                &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)).intern(&Interner),
+            );
         }
     }
     Some(
@@ -196,11 +199,12 @@ fn is_diverging(&mut self, iv: InferenceVar) -> bool {
 
     fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
         match kind {
-            _ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never,
-            TyVariableKind::General => Ty::Unknown,
-            TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)),
-            TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)),
+            _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never,
+            TyVariableKind::General => TyKind::Unknown,
+            TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
+            TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
         }
+        .intern(&Interner)
     }
 }
 
@@ -227,7 +231,7 @@ fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
         self.type_variable_table.push(TypeVariableData { diverging });
         let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
         assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
-        Ty::InferenceVar(InferenceVar::from_inner(key), kind)
+        TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner)
     }
 
     pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -290,12 +294,12 @@ fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
     }
 
     pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
-        match (ty1, ty2) {
-            (Ty::Unknown, _) | (_, Ty::Unknown) => true,
+        match (ty1.interned(&Interner), ty2.interned(&Interner)) {
+            (TyKind::Unknown, _) | (_, TyKind::Unknown) => true,
 
-            (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true,
+            (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true,
 
-            (Ty::Dyn(dyn1), Ty::Dyn(dyn2)) if dyn1.len() == dyn2.len() => {
+            (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => {
                 for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) {
                     if !self.unify_preds(pred1, pred2, depth + 1) {
                         return false;
@@ -305,16 +309,16 @@ pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -
             }
 
             (
-                Ty::InferenceVar(tv1, TyVariableKind::General),
-                Ty::InferenceVar(tv2, TyVariableKind::General),
+                TyKind::InferenceVar(tv1, TyVariableKind::General),
+                TyKind::InferenceVar(tv2, TyVariableKind::General),
             )
             | (
-                Ty::InferenceVar(tv1, TyVariableKind::Integer),
-                Ty::InferenceVar(tv2, TyVariableKind::Integer),
+                TyKind::InferenceVar(tv1, TyVariableKind::Integer),
+                TyKind::InferenceVar(tv2, TyVariableKind::Integer),
             )
             | (
-                Ty::InferenceVar(tv1, TyVariableKind::Float),
-                Ty::InferenceVar(tv2, TyVariableKind::Float),
+                TyKind::InferenceVar(tv1, TyVariableKind::Float),
+                TyKind::InferenceVar(tv2, TyVariableKind::Float),
             ) if self.type_variable_table.is_diverging(*tv1)
                 == self.type_variable_table.is_diverging(*tv2) =>
             {
@@ -326,24 +330,37 @@ pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -
             // The order of MaybeNeverTypeVar matters here.
             // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
             // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
-            (Ty::InferenceVar(tv, TyVariableKind::General), other)
-            | (other, Ty::InferenceVar(tv, TyVariableKind::General))
-            | (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_)))
-            | (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer))
+            (TyKind::InferenceVar(tv, TyVariableKind::General), other)
+            | (other, TyKind::InferenceVar(tv, TyVariableKind::General))
             | (
-                Ty::InferenceVar(tv, TyVariableKind::Integer),
-                other @ Ty::Scalar(Scalar::Uint(_)),
+                TyKind::InferenceVar(tv, TyVariableKind::Integer),
+                other @ TyKind::Scalar(Scalar::Int(_)),
             )
             | (
-                other @ Ty::Scalar(Scalar::Uint(_)),
-                Ty::InferenceVar(tv, TyVariableKind::Integer),
+                other @ TyKind::Scalar(Scalar::Int(_)),
+                TyKind::InferenceVar(tv, TyVariableKind::Integer),
             )
-            | (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_)))
-            | (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) =>
-            {
+            | (
+                TyKind::InferenceVar(tv, TyVariableKind::Integer),
+                other @ TyKind::Scalar(Scalar::Uint(_)),
+            )
+            | (
+                other @ TyKind::Scalar(Scalar::Uint(_)),
+                TyKind::InferenceVar(tv, TyVariableKind::Integer),
+            )
+            | (
+                TyKind::InferenceVar(tv, TyVariableKind::Float),
+                other @ TyKind::Scalar(Scalar::Float(_)),
+            )
+            | (
+                other @ TyKind::Scalar(Scalar::Float(_)),
+                TyKind::InferenceVar(tv, TyVariableKind::Float),
+            ) => {
                 // the type var is unknown since we tried to resolve it
-                self.var_unification_table
-                    .union_value(tv.to_inner(), TypeVarValue::Known(other.clone()));
+                self.var_unification_table.union_value(
+                    tv.to_inner(),
+                    TypeVarValue::Known(other.clone().intern(&Interner)),
+                );
                 true
             }
 
@@ -387,8 +404,8 @@ pub(crate) fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
             if i > 0 {
                 cov_mark::hit!(type_var_resolves_to_int_var);
             }
-            match &*ty {
-                Ty::InferenceVar(tv, _) => {
+            match &ty.0 {
+                TyKind::InferenceVar(tv, _) => {
                     let inner = tv.to_inner();
                     match self.var_unification_table.inlined_probe_value(inner).known() {
                         Some(known_ty) => {
@@ -410,8 +427,8 @@ pub(crate) fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
     /// be resolved as far as possible, i.e. contain no type variables with
     /// known type.
     fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
-        ty.fold(&mut |ty| match ty {
-            Ty::InferenceVar(tv, kind) => {
+        ty.fold(&mut |ty| match ty.interned(&Interner) {
+            &TyKind::InferenceVar(tv, kind) => {
                 let inner = tv.to_inner();
                 if tv_stack.contains(&inner) {
                     cov_mark::hit!(type_var_cycles_resolve_as_possible);
@@ -435,10 +452,10 @@ fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty
     }
 
     /// Resolves the type completely; type variables without known type are
-    /// replaced by Ty::Unknown.
+    /// replaced by TyKind::Unknown.
     fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
-        ty.fold(&mut |ty| match ty {
-            Ty::InferenceVar(tv, kind) => {
+        ty.fold(&mut |ty| match ty.interned(&Interner) {
+            &TyKind::InferenceVar(tv, kind) => {
                 let inner = tv.to_inner();
                 if tv_stack.contains(&inner) {
                     cov_mark::hit!(type_var_cycles_resolve_completely);
index e77f24e4edcf8ccb0825e32e5cf0a0bc3f00fcf0..2309db4922d1656770698a6101511a72d4aa06fa 100644 (file)
@@ -49,7 +49,7 @@ macro_rules! eprintln {
 
 pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind};
 
-pub(crate) use crate::traits::chalk::Interner;
+pub use crate::traits::chalk::Interner;
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum Lifetime {
@@ -131,7 +131,7 @@ pub enum AliasTy {
 ///
 /// This should be cheap to clone.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum Ty {
+pub enum TyKind {
     /// Structures, enumerations and unions.
     Adt(AdtId<Interner>, Substs),
 
@@ -244,6 +244,21 @@ pub enum Ty {
     Unknown,
 }
 
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct Ty(TyKind);
+
+impl TyKind {
+    pub fn intern(self, _interner: &Interner) -> Ty {
+        Ty(self)
+    }
+}
+
+impl Ty {
+    pub fn interned(&self, _interner: &Interner) -> &TyKind {
+        &self.0
+    }
+}
+
 /// A list of substitutions for generic parameters.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Substs(Arc<[Ty]>);
@@ -292,7 +307,12 @@ pub fn as_single(&self) -> &Ty {
 
     /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
     pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs {
-        Substs(generic_params.iter().map(|(id, _)| Ty::Placeholder(id)).collect())
+        Substs(
+            generic_params
+                .iter()
+                .map(|(id, _)| TyKind::Placeholder(id).intern(&Interner))
+                .collect(),
+        )
     }
 
     /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
@@ -307,7 +327,7 @@ pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) ->
             generic_params
                 .iter()
                 .enumerate()
-                .map(|(idx, _)| Ty::BoundVar(BoundVar::new(debruijn, idx)))
+                .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner))
                 .collect(),
         )
     }
@@ -355,11 +375,14 @@ fn remaining(&self) -> usize {
     }
 
     pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
-        self.fill((starting_from..).map(|idx| Ty::BoundVar(BoundVar::new(debruijn, idx))))
+        self.fill(
+            (starting_from..)
+                .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
+        )
     }
 
     pub fn fill_with_unknown(self) -> Self {
-        self.fill(iter::repeat(Ty::Unknown))
+        self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
     }
 
     pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
@@ -601,45 +624,52 @@ fn walk_mut_binders(
 
 impl Ty {
     pub fn unit() -> Self {
-        Ty::Tuple(0, Substs::empty())
+        TyKind::Tuple(0, Substs::empty()).intern(&Interner)
     }
 
     pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty {
-        Ty::Adt(AdtId(adt), substs)
+        TyKind::Adt(AdtId(adt), substs).intern(&Interner)
     }
 
     pub fn fn_ptr(sig: CallableSig) -> Self {
-        Ty::Function(FnPointer {
+        TyKind::Function(FnPointer {
             num_args: sig.params().len(),
             sig: FnSig { variadic: sig.is_varargs },
             substs: Substs(sig.params_and_return),
         })
+        .intern(&Interner)
     }
 
     pub fn builtin(builtin: BuiltinType) -> Self {
         match builtin {
-            BuiltinType::Char => Ty::Scalar(Scalar::Char),
-            BuiltinType::Bool => Ty::Scalar(Scalar::Bool),
-            BuiltinType::Str => Ty::Str,
-            BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))),
-            BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))),
-            BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))),
+            BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
+            BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
+            BuiltinType::Str => TyKind::Str.intern(&Interner),
+            BuiltinType::Int(t) => {
+                TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
+            }
+            BuiltinType::Uint(t) => {
+                TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
+            }
+            BuiltinType::Float(t) => {
+                TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
+            }
         }
     }
 
     pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
-        match self {
-            Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)),
+        match self.interned(&Interner) {
+            TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)),
             _ => None,
         }
     }
 
     pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
-        match self {
-            Ty::Ref(mutability, parameters) => {
+        match self.interned(&Interner) {
+            TyKind::Ref(mutability, parameters) => {
                 Some((parameters.as_single(), Rawness::Ref, *mutability))
             }
-            Ty::Raw(mutability, parameters) => {
+            TyKind::Raw(mutability, parameters) => {
                 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
             }
             _ => None,
@@ -649,7 +679,7 @@ pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
     pub fn strip_references(&self) -> &Ty {
         let mut t: &Ty = self;
 
-        while let Ty::Ref(_mutability, parameters) = t {
+        while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) {
             t = parameters.as_single();
         }
 
@@ -657,65 +687,69 @@ pub fn strip_references(&self) -> &Ty {
     }
 
     pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> {
-        match self {
-            Ty::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
+        match self.interned(&Interner) {
+            TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
             _ => None,
         }
     }
 
     pub fn as_tuple(&self) -> Option<&Substs> {
-        match self {
-            Ty::Tuple(_, substs) => Some(substs),
+        match self.interned(&Interner) {
+            TyKind::Tuple(_, substs) => Some(substs),
             _ => None,
         }
     }
 
     pub fn as_generic_def(&self) -> Option<GenericDefId> {
-        match *self {
-            Ty::Adt(AdtId(adt), ..) => Some(adt.into()),
-            Ty::FnDef(callable, ..) => Some(callable.into()),
-            Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()),
-            Ty::ForeignType(type_alias, ..) => Some(type_alias.into()),
+        match *self.interned(&Interner) {
+            TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
+            TyKind::FnDef(callable, ..) => Some(callable.into()),
+            TyKind::AssociatedType(type_alias, ..) => Some(type_alias.into()),
+            TyKind::ForeignType(type_alias, ..) => Some(type_alias.into()),
             _ => None,
         }
     }
 
     pub fn is_never(&self) -> bool {
-        matches!(self, Ty::Never)
+        matches!(self.interned(&Interner), TyKind::Never)
     }
 
     pub fn is_unknown(&self) -> bool {
-        matches!(self, Ty::Unknown)
+        matches!(self.interned(&Interner), TyKind::Unknown)
     }
 
     pub fn equals_ctor(&self, other: &Ty) -> bool {
-        match (self, other) {
-            (Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2,
-            (Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true,
-            (Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2,
-            (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
-            (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..))
-            | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2,
-            (Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => {
+        match (self.interned(&Interner), other.interned(&Interner)) {
+            (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
+            (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true,
+            (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
+            (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
+            (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..))
+            | (TyKind::ForeignType(ty_id, ..), TyKind::ForeignType(ty_id2, ..)) => ty_id == ty_id2,
+            (TyKind::Closure(def, expr, _), TyKind::Closure(def2, expr2, _)) => {
                 expr == expr2 && def == def2
             }
-            (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..))
-            | (Ty::Raw(mutability, ..), Ty::Raw(mutability2, ..)) => mutability == mutability2,
+            (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
+            | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
+                mutability == mutability2
+            }
             (
-                Ty::Function(FnPointer { num_args, sig, .. }),
-                Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
+                TyKind::Function(FnPointer { num_args, sig, .. }),
+                TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
             ) => num_args == num_args2 && sig == sig2,
-            (Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2,
-            (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true,
-            (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2,
+            (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
+                cardinality == cardinality2
+            }
+            (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
+            (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
             _ => false,
         }
     }
 
     /// If this is a `dyn Trait` type, this returns the `Trait` part.
     pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
-        match self {
-            Ty::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
+        match self.interned(&Interner) {
+            TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
                 GenericPredicate::Implemented(trait_ref) => Some(trait_ref),
                 _ => None,
             }),
@@ -729,28 +763,28 @@ pub fn dyn_trait(&self) -> Option<TraitId> {
     }
 
     fn builtin_deref(&self) -> Option<Ty> {
-        match self {
-            Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
-            Ty::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
+        match self.interned(&Interner) {
+            TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
+            TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
             _ => None,
         }
     }
 
     pub fn as_fn_def(&self) -> Option<FunctionId> {
-        match self {
-            &Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func),
+        match self.interned(&Interner) {
+            &TyKind::FnDef(CallableDefId::FunctionId(func), ..) => Some(func),
             _ => None,
         }
     }
 
     pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
-        match self {
-            Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
-            Ty::FnDef(def, parameters) => {
+        match self.interned(&Interner) {
+            TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
+            TyKind::FnDef(def, parameters) => {
                 let sig = db.callable_item_signature(*def);
                 Some(sig.subst(&parameters))
             }
-            Ty::Closure(.., substs) => {
+            TyKind::Closure(.., substs) => {
                 let sig_param = &substs[0];
                 sig_param.callable_sig(db)
             }
@@ -763,18 +797,18 @@ pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
     /// `self` is `Option<_>` and the substs contain `u32`, we'll have
     /// `Option<u32>` afterwards.)
     pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
-        match &mut self {
-            Ty::Adt(_, substs)
-            | Ty::Slice(substs)
-            | Ty::Array(substs)
-            | Ty::Raw(_, substs)
-            | Ty::Ref(_, substs)
-            | Ty::FnDef(_, substs)
-            | Ty::Function(FnPointer { substs, .. })
-            | Ty::Tuple(_, substs)
-            | Ty::OpaqueType(_, substs)
-            | Ty::AssociatedType(_, substs)
-            | Ty::Closure(.., substs) => {
+        match &mut self.0 {
+            TyKind::Adt(_, substs)
+            | TyKind::Slice(substs)
+            | TyKind::Array(substs)
+            | TyKind::Raw(_, substs)
+            | TyKind::Ref(_, substs)
+            | TyKind::FnDef(_, substs)
+            | TyKind::Function(FnPointer { substs, .. })
+            | TyKind::Tuple(_, substs)
+            | TyKind::OpaqueType(_, substs)
+            | TyKind::AssociatedType(_, substs)
+            | TyKind::Closure(.., substs) => {
                 assert_eq!(substs.len(), new_substs.len());
                 *substs = new_substs;
             }
@@ -786,42 +820,42 @@ pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
     /// Returns the type parameters of this type if it has some (i.e. is an ADT
     /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
     pub fn substs(&self) -> Option<&Substs> {
-        match self {
-            Ty::Adt(_, substs)
-            | Ty::Slice(substs)
-            | Ty::Array(substs)
-            | Ty::Raw(_, substs)
-            | Ty::Ref(_, substs)
-            | Ty::FnDef(_, substs)
-            | Ty::Function(FnPointer { substs, .. })
-            | Ty::Tuple(_, substs)
-            | Ty::OpaqueType(_, substs)
-            | Ty::AssociatedType(_, substs)
-            | Ty::Closure(.., substs) => Some(substs),
+        match self.interned(&Interner) {
+            TyKind::Adt(_, substs)
+            | TyKind::Slice(substs)
+            | TyKind::Array(substs)
+            | TyKind::Raw(_, substs)
+            | TyKind::Ref(_, substs)
+            | TyKind::FnDef(_, substs)
+            | TyKind::Function(FnPointer { substs, .. })
+            | TyKind::Tuple(_, substs)
+            | TyKind::OpaqueType(_, substs)
+            | TyKind::AssociatedType(_, substs)
+            | TyKind::Closure(.., substs) => Some(substs),
             _ => None,
         }
     }
 
     pub fn substs_mut(&mut self) -> Option<&mut Substs> {
-        match self {
-            Ty::Adt(_, substs)
-            | Ty::Slice(substs)
-            | Ty::Array(substs)
-            | Ty::Raw(_, substs)
-            | Ty::Ref(_, substs)
-            | Ty::FnDef(_, substs)
-            | Ty::Function(FnPointer { substs, .. })
-            | Ty::Tuple(_, substs)
-            | Ty::OpaqueType(_, substs)
-            | Ty::AssociatedType(_, substs)
-            | Ty::Closure(.., substs) => Some(substs),
+        match &mut self.0 {
+            TyKind::Adt(_, substs)
+            | TyKind::Slice(substs)
+            | TyKind::Array(substs)
+            | TyKind::Raw(_, substs)
+            | TyKind::Ref(_, substs)
+            | TyKind::FnDef(_, substs)
+            | TyKind::Function(FnPointer { substs, .. })
+            | TyKind::Tuple(_, substs)
+            | TyKind::OpaqueType(_, substs)
+            | TyKind::AssociatedType(_, substs)
+            | TyKind::Closure(.., substs) => Some(substs),
             _ => None,
         }
     }
 
     pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
-        match self {
-            Ty::OpaqueType(opaque_ty_id, ..) => {
+        match self.interned(&Interner) {
+            TyKind::OpaqueType(opaque_ty_id, ..) => {
                 match opaque_ty_id {
                     OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => {
                         let krate = def.module(db.upcast()).krate();
@@ -844,7 +878,7 @@ pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredi
                     OpaqueTyId::ReturnTypeImplTrait(..) => None,
                 }
             }
-            Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
+            TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
                 let predicates = match opaque_ty.opaque_ty_id {
                     OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
                         db.return_type_impl_traits(func).map(|it| {
@@ -860,7 +894,7 @@ pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredi
 
                 predicates.map(|it| it.value)
             }
-            Ty::Placeholder(id) => {
+            TyKind::Placeholder(id) => {
                 let generic_params = db.generic_params(id.parent);
                 let param_data = &generic_params.types[id.local_id];
                 match param_data.provenance {
@@ -881,14 +915,14 @@ pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredi
     }
 
     pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
-        match self {
-            Ty::AssociatedType(type_alias_id, ..) => {
+        match self.interned(&Interner) {
+            TyKind::AssociatedType(type_alias_id, ..) => {
                 match type_alias_id.lookup(db.upcast()).container {
                     AssocContainerId::TraitId(trait_id) => Some(trait_id),
                     _ => None,
                 }
             }
-            Ty::Alias(AliasTy::Projection(projection_ty)) => {
+            TyKind::Alias(AliasTy::Projection(projection_ty)) => {
                 match projection_ty.associated_ty.lookup(db.upcast()).container {
                     AssocContainerId::TraitId(trait_id) => Some(trait_id),
                     _ => None,
@@ -908,13 +942,13 @@ fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
     }
     /// Walk the type, counting entered binders.
     ///
-    /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers
+    /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
     /// to the innermost binder, 1 to the next, etc.. So when we want to
     /// substitute a certain bound variable, we can't just walk the whole type
     /// and blindly replace each instance of a certain index; when we 'enter'
     /// things that introduce new bound variables, we have to keep track of
     /// that. Currently, the only thing that introduces bound variables on our
-    /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
+    /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
     /// variable for the self type.
     fn walk_mut_binders(
         &mut self,
@@ -932,7 +966,7 @@ fn fold_binders(
     {
         self.walk_mut_binders(
             &mut |ty_mut, binders| {
-                let ty = mem::replace(ty_mut, Ty::Unknown);
+                let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
                 *ty_mut = f(ty, binders);
             },
             binders,
@@ -945,13 +979,13 @@ fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
         Self: Sized,
     {
         self.walk_mut(&mut |ty_mut| {
-            let ty = mem::replace(ty_mut, Ty::Unknown);
+            let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
             *ty_mut = f(ty);
         });
         self
     }
 
-    /// Substitutes `Ty::Bound` vars with the given substitution.
+    /// Substitutes `TyKind::Bound` vars with the given substitution.
     fn subst_bound_vars(self, substs: &Substs) -> Self
     where
         Self: Sized,
@@ -959,14 +993,14 @@ fn subst_bound_vars(self, substs: &Substs) -> Self
         self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
     }
 
-    /// Substitutes `Ty::Bound` vars with the given substitution.
+    /// Substitutes `TyKind::Bound` vars with the given substitution.
     fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
     where
         Self: Sized,
     {
         self.walk_mut_binders(
             &mut |ty, binders| {
-                if let &mut Ty::BoundVar(bound) = ty {
+                if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
                     if bound.debruijn >= binders {
                         *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
                     }
@@ -977,17 +1011,17 @@ fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) ->
         self
     }
 
-    /// Shifts up debruijn indices of `Ty::Bound` vars by `n`.
+    /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
     fn shift_bound_vars(self, n: DebruijnIndex) -> Self
     where
         Self: Sized,
     {
         self.fold_binders(
-            &mut |ty, binders| match ty {
-                Ty::BoundVar(bound) if bound.debruijn >= binders => {
-                    Ty::BoundVar(bound.shifted_in_from(n))
+            &mut |ty, binders| match &ty.0 {
+                TyKind::BoundVar(bound) if bound.debruijn >= binders => {
+                    TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
                 }
-                ty => ty,
+                _ => ty,
             },
             DebruijnIndex::INNERMOST,
         )
@@ -996,18 +1030,18 @@ fn shift_bound_vars(self, n: DebruijnIndex) -> Self
 
 impl TypeWalk for Ty {
     fn walk(&self, f: &mut impl FnMut(&Ty)) {
-        match self {
-            Ty::Alias(AliasTy::Projection(p_ty)) => {
+        match self.interned(&Interner) {
+            TyKind::Alias(AliasTy::Projection(p_ty)) => {
                 for t in p_ty.parameters.iter() {
                     t.walk(f);
                 }
             }
-            Ty::Alias(AliasTy::Opaque(o_ty)) => {
+            TyKind::Alias(AliasTy::Opaque(o_ty)) => {
                 for t in o_ty.parameters.iter() {
                     t.walk(f);
                 }
             }
-            Ty::Dyn(predicates) => {
+            TyKind::Dyn(predicates) => {
                 for p in predicates.iter() {
                     p.walk(f);
                 }
@@ -1028,16 +1062,16 @@ fn walk_mut_binders(
         f: &mut impl FnMut(&mut Ty, DebruijnIndex),
         binders: DebruijnIndex,
     ) {
-        match self {
-            Ty::Alias(AliasTy::Projection(p_ty)) => {
+        match &mut self.0 {
+            TyKind::Alias(AliasTy::Projection(p_ty)) => {
                 p_ty.parameters.walk_mut_binders(f, binders);
             }
-            Ty::Dyn(predicates) => {
+            TyKind::Dyn(predicates) => {
                 for p in make_mut_slice(predicates) {
                     p.walk_mut_binders(f, binders.shifted_in());
                 }
             }
-            Ty::Alias(AliasTy::Opaque(o_ty)) => {
+            TyKind::Alias(AliasTy::Opaque(o_ty)) => {
                 o_ty.parameters.walk_mut_binders(f, binders);
             }
             _ => {
index d84ec9b7a7a03a3a1c22595425b4d5f647585541..9fe7e3dce28aa146548e63d5ffc54a1632652f50 100644 (file)
@@ -34,7 +34,7 @@
     },
     AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
     OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
-    ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
+    ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
 };
 
 #[derive(Debug)]
@@ -146,10 +146,10 @@ pub fn from_hir(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Self {
     pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) {
         let mut res = None;
         let ty = match type_ref {
-            TypeRef::Never => Ty::Never,
+            TypeRef::Never => TyKind::Never.intern(&Interner),
             TypeRef::Tuple(inner) => {
                 let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect();
-                Ty::Tuple(inner_tys.len(), Substs(inner_tys))
+                TyKind::Tuple(inner_tys.len(), Substs(inner_tys)).intern(&Interner)
             }
             TypeRef::Path(path) => {
                 let (ty, res_) = Ty::from_hir_path(ctx, path);
@@ -158,38 +158,42 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O
             }
             TypeRef::RawPtr(inner, mutability) => {
                 let inner_ty = Ty::from_hir(ctx, inner);
-                Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
+                TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
+                    .intern(&Interner)
             }
             TypeRef::Array(inner) => {
                 let inner_ty = Ty::from_hir(ctx, inner);
-                Ty::Array(Substs::single(inner_ty))
+                TyKind::Array(Substs::single(inner_ty)).intern(&Interner)
             }
             TypeRef::Slice(inner) => {
                 let inner_ty = Ty::from_hir(ctx, inner);
-                Ty::Slice(Substs::single(inner_ty))
+                TyKind::Slice(Substs::single(inner_ty)).intern(&Interner)
             }
             TypeRef::Reference(inner, _, mutability) => {
                 let inner_ty = Ty::from_hir(ctx, inner);
-                Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
+                TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
+                    .intern(&Interner)
             }
-            TypeRef::Placeholder => Ty::Unknown,
+            TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
             TypeRef::Fn(params, is_varargs) => {
                 let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
-                Ty::Function(FnPointer {
+                TyKind::Function(FnPointer {
                     num_args: substs.len() - 1,
                     sig: FnSig { variadic: *is_varargs },
                     substs,
                 })
+                .intern(&Interner)
             }
             TypeRef::DynTrait(bounds) => {
-                let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0));
+                let self_ty =
+                    TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
                 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
                     bounds
                         .iter()
                         .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
                         .collect()
                 });
-                Ty::Dyn(predicates)
+                TyKind::Dyn(predicates).intern(&Interner)
             }
             TypeRef::ImplTrait(bounds) => {
                 match ctx.impl_trait_mode {
@@ -226,10 +230,11 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O
                         let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx);
                         let generics = generics(ctx.db.upcast(), func.into());
                         let parameters = Substs::bound_vars(&generics, ctx.in_binders);
-                        Ty::Alias(AliasTy::Opaque(OpaqueTy {
+                        TyKind::Alias(AliasTy::Opaque(OpaqueTy {
                             opaque_ty_id: impl_trait_id,
                             parameters,
                         }))
+                        .intern(&Interner)
                     }
                     ImplTraitLoweringMode::Param => {
                         let idx = ctx.impl_trait_counter.get();
@@ -243,10 +248,10 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O
                                     data.provenance == TypeParamProvenance::ArgumentImplTrait
                                 })
                                 .nth(idx as usize)
-                                .map_or(Ty::Unknown, |(id, _)| Ty::Placeholder(id));
-                            param
+                                .map_or(TyKind::Unknown, |(id, _)| TyKind::Placeholder(id));
+                            param.intern(&Interner)
                         } else {
-                            Ty::Unknown
+                            TyKind::Unknown.intern(&Interner)
                         }
                     }
                     ImplTraitLoweringMode::Variable => {
@@ -260,18 +265,19 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O
                             } else {
                                 (0, 0, 0, 0)
                             };
-                        Ty::BoundVar(BoundVar::new(
+                        TyKind::BoundVar(BoundVar::new(
                             ctx.in_binders,
                             idx as usize + parent_params + self_params + list_params,
                         ))
+                        .intern(&Interner)
                     }
                     ImplTraitLoweringMode::Disallowed => {
                         // FIXME: report error
-                        Ty::Unknown
+                        TyKind::Unknown.intern(&Interner)
                     }
                 }
             }
-            TypeRef::Error => Ty::Unknown,
+            TypeRef::Error => TyKind::Unknown.intern(&Interner),
         };
         (ty, res)
     }
@@ -315,7 +321,7 @@ pub(crate) fn from_type_relative_path(
             (Ty::select_associated_type(ctx, res, segment), None)
         } else if remaining_segments.len() > 1 {
             // FIXME report error (ambiguous associated type)
-            (Ty::Unknown, None)
+            (TyKind::Unknown.intern(&Interner), None)
         } else {
             (ty, res)
         }
@@ -332,7 +338,10 @@ pub(crate) fn from_partly_resolved_hir_path(
             TypeNs::TraitId(trait_) => {
                 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
                 let self_ty = if remaining_segments.len() == 0 {
-                    Some(Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
+                    Some(
+                        TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
+                            .intern(&Interner),
+                    )
                 } else {
                     None
                 };
@@ -348,21 +357,23 @@ pub(crate) fn from_partly_resolved_hir_path(
                     match found {
                         Some((super_trait_ref, associated_ty)) => {
                             // FIXME handle type parameters on the segment
-                            Ty::Alias(AliasTy::Projection(ProjectionTy {
+                            TyKind::Alias(AliasTy::Projection(ProjectionTy {
                                 associated_ty,
                                 parameters: super_trait_ref.substs,
                             }))
+                            .intern(&Interner)
                         }
                         None => {
                             // FIXME: report error (associated type not found)
-                            Ty::Unknown
+                            TyKind::Unknown.intern(&Interner)
                         }
                     }
                 } else if remaining_segments.len() > 1 {
                     // FIXME report error (ambiguous associated type)
-                    Ty::Unknown
+                    TyKind::Unknown.intern(&Interner)
                 } else {
-                    Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
+                    TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
+                        .intern(&Interner)
                 };
                 return (ty, None);
             }
@@ -372,12 +383,13 @@ pub(crate) fn from_partly_resolved_hir_path(
                     ctx.resolver.generic_def().expect("generics in scope"),
                 );
                 match ctx.type_param_mode {
-                    TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
+                    TypeParamLoweringMode::Placeholder => TyKind::Placeholder(param_id),
                     TypeParamLoweringMode::Variable => {
                         let idx = generics.param_idx(param_id).expect("matching generics");
-                        Ty::BoundVar(BoundVar::new(ctx.in_binders, idx))
+                        TyKind::BoundVar(BoundVar::new(ctx.in_binders, idx))
                     }
                 }
+                .intern(&Interner)
             }
             TypeNs::SelfType(impl_id) => {
                 let generics = generics(ctx.db.upcast(), impl_id.into());
@@ -414,7 +426,7 @@ pub(crate) fn from_partly_resolved_hir_path(
                 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
             }
             // FIXME: report error
-            TypeNs::EnumVariantId(_) => return (Ty::Unknown, None),
+            TypeNs::EnumVariantId(_) => return (TyKind::Unknown.intern(&Interner), None),
         };
         Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments)
     }
@@ -428,7 +440,7 @@ pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_>, path: &Path) -> (Ty, Op
         let (resolution, remaining_index) =
             match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) {
                 Some(it) => it,
-                None => return (Ty::Unknown, None),
+                None => return (TyKind::Unknown.intern(&Interner), None),
             };
         let (resolved_segment, remaining_segments) = match remaining_index {
             None => (
@@ -473,18 +485,21 @@ fn select_associated_type(
                         // associated_type_shorthand_candidates does not do that
                         let substs = substs.shift_bound_vars(ctx.in_binders);
                         // FIXME handle type parameters on the segment
-                        return Some(Ty::Alias(AliasTy::Projection(ProjectionTy {
-                            associated_ty,
-                            parameters: substs,
-                        })));
+                        return Some(
+                            TyKind::Alias(AliasTy::Projection(ProjectionTy {
+                                associated_ty,
+                                parameters: substs,
+                            }))
+                            .intern(&Interner),
+                        );
                     }
 
                     None
                 });
 
-            ty.unwrap_or(Ty::Unknown)
+            ty.unwrap_or(TyKind::Unknown.intern(&Interner))
         } else {
-            Ty::Unknown
+            TyKind::Unknown.intern(&Interner)
         }
     }
 
@@ -553,13 +568,13 @@ fn substs_from_path_segment(
         def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split());
     let total_len = parent_params + self_params + type_params + impl_trait_params;
 
-    substs.extend(iter::repeat(Ty::Unknown).take(parent_params));
+    substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params));
 
     let mut had_explicit_type_args = false;
 
     if let Some(generic_args) = &segment.args_and_bindings {
         if !generic_args.has_self_type {
-            substs.extend(iter::repeat(Ty::Unknown).take(self_params));
+            substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params));
         }
         let expected_num =
             if generic_args.has_self_type { self_params + type_params } else { type_params };
@@ -602,7 +617,7 @@ fn substs_from_path_segment(
     // add placeholders for args that were not provided
     // FIXME: emit diagnostics in contexts where this is not allowed
     for _ in substs.len()..total_len {
-        substs.push(Ty::Unknown);
+        substs.push(TyKind::Unknown.intern(&Interner));
     }
     assert_eq!(substs.len(), total_len);
 
@@ -674,12 +689,13 @@ pub(crate) fn from_where_predicate<'a>(
                         let param_id =
                             hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
                         match ctx.type_param_mode {
-                            TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
+                            TypeParamLoweringMode::Placeholder => TyKind::Placeholder(param_id),
                             TypeParamLoweringMode::Variable => {
                                 let idx = generics.param_idx(param_id).expect("matching generics");
-                                Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
+                                TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
                             }
                         }
+                        .intern(&Interner)
                     }
                 };
                 GenericPredicate::from_type_bound(ctx, bound, self_ty)
@@ -751,7 +767,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
                 preds.extend(GenericPredicate::from_type_bound(
                     ctx,
                     bound,
-                    Ty::Alias(AliasTy::Projection(projection_ty.clone())),
+                    TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner),
                 ));
             }
             preds
@@ -761,7 +777,8 @@ fn assoc_type_bindings_from_type_bound<'a>(
 impl ReturnTypeImplTrait {
     fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
         cov_mark::hit!(lower_rpit);
-        let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0));
+        let self_ty =
+            TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
         let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
             bounds
                 .iter()
@@ -994,17 +1011,20 @@ pub(crate) fn generic_defaults_query(
         .iter()
         .enumerate()
         .map(|(idx, (_, p))| {
-            let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t));
+            let mut ty = p
+                .default
+                .as_ref()
+                .map_or(TyKind::Unknown.intern(&Interner), |t| Ty::from_hir(&ctx, t));
 
             // Each default can only refer to previous parameters.
             ty.walk_mut_binders(
-                &mut |ty, binders| match ty {
-                    Ty::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
+                &mut |ty, binders| match &mut ty.0 {
+                    TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
                         if *index >= idx {
                             // type variable default referring to parameter coming
                             // after it. This is forbidden (FIXME: report
                             // diagnostic)
-                            *ty = Ty::Unknown;
+                            *ty = TyKind::Unknown.intern(&Interner);
                         }
                     }
                     _ => {}
@@ -1040,7 +1060,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
 fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
     let generics = generics(db.upcast(), def.into());
     let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
-    Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
+    Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
 }
 
 /// Build the declared type of a const.
@@ -1083,7 +1103,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
     }
     let generics = generics(db.upcast(), def.into());
     let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
-    Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
+    Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
 }
 
 fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
@@ -1108,7 +1128,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
     }
     let generics = generics(db.upcast(), def.parent.into());
     let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
-    Binders::new(substs.len(), Ty::FnDef(def.into(), substs))
+    Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
 }
 
 fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
@@ -1123,7 +1143,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
     let ctx =
         TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
     if db.type_alias_data(t).is_extern {
-        Binders::new(0, Ty::ForeignType(t))
+        Binders::new(0, TyKind::ForeignType(t).intern(&Interner))
     } else {
         let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
         let type_ref = &db.type_alias_data(t).type_ref;
@@ -1199,7 +1219,7 @@ pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &[String], def: &TyDefId)
         TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(),
         TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(),
     };
-    Binders::new(num_binders, Ty::Unknown)
+    Binders::new(num_binders, TyKind::Unknown.intern(&Interner))
 }
 
 pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> {
@@ -1237,7 +1257,7 @@ pub(crate) fn impl_self_ty_recover(
     impl_id: &ImplId,
 ) -> Binders<Ty> {
     let generics = generics(db.upcast(), (*impl_id).into());
-    Binders::new(generics.len(), Ty::Unknown)
+    Binders::new(generics.len(), TyKind::Unknown.intern(&Interner))
 }
 
 pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
index d57c6de70ea54134b50c12be8edcc6a5b29c955e..f9877e760764969d746a08745fdc79a4a91a9f9d 100644 (file)
@@ -19,8 +19,8 @@
     db::HirDatabase,
     primitive::{self, FloatTy, IntTy, UintTy},
     utils::all_super_traits,
-    AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs,
-    TraitEnvironment, TraitRef, Ty, TypeWalk,
+    AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Interner, Scalar, Substs,
+    TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
 };
 
 /// This is used as a key for indexing impls.
@@ -44,18 +44,20 @@ impl TyFingerprint {
     /// have impls: if we have some `struct S`, we can have an `impl S`, but not
     /// `impl &S`. Hence, this will return `None` for reference types and such.
     pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
-        let fp = match ty {
-            &Ty::Str => TyFingerprint::Str,
-            &Ty::Never => TyFingerprint::Never,
-            &Ty::Slice(..) => TyFingerprint::Slice,
-            &Ty::Array(..) => TyFingerprint::Array,
-            &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar),
-            &Ty::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt),
-            &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
-            &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
-            &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
-            &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig),
-            Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
+        let fp = match *ty.interned(&Interner) {
+            TyKind::Str => TyFingerprint::Str,
+            TyKind::Never => TyFingerprint::Never,
+            TyKind::Slice(..) => TyFingerprint::Slice,
+            TyKind::Array(..) => TyFingerprint::Array,
+            TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar),
+            TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt),
+            TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
+            TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
+            TyKind::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
+            TyKind::Function(FnPointer { num_args, sig, .. }) => {
+                TyFingerprint::FnPtr(num_args, sig)
+            }
+            TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
             _ => return None,
         };
         Some(fp)
@@ -230,31 +232,31 @@ macro_rules! lang_item_crate {
 
         let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
 
-        let lang_item_targets = match self {
-            Ty::Adt(AdtId(def_id), _) => {
+        let lang_item_targets = match self.interned(&Interner) {
+            TyKind::Adt(AdtId(def_id), _) => {
                 return mod_to_crate_ids(def_id.module(db.upcast()));
             }
-            Ty::ForeignType(type_alias_id) => {
+            TyKind::ForeignType(type_alias_id) => {
                 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
             }
-            Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
-            Ty::Scalar(Scalar::Char) => lang_item_crate!("char"),
-            Ty::Scalar(Scalar::Float(f)) => match f {
+            TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
+            TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
+            TyKind::Scalar(Scalar::Float(f)) => match f {
                 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
                 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
                 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
             },
-            &Ty::Scalar(Scalar::Int(t)) => {
+            &TyKind::Scalar(Scalar::Int(t)) => {
                 lang_item_crate!(primitive::int_ty_to_string(t))
             }
-            &Ty::Scalar(Scalar::Uint(t)) => {
+            &TyKind::Scalar(Scalar::Uint(t)) => {
                 lang_item_crate!(primitive::uint_ty_to_string(t))
             }
-            Ty::Str => lang_item_crate!("str_alloc", "str"),
-            Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
-            Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
-            Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
-            Ty::Dyn(_) => {
+            TyKind::Str => lang_item_crate!("str_alloc", "str"),
+            TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
+            TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
+            TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
+            TyKind::Dyn(_) => {
                 return self.dyn_trait().and_then(|trait_| {
                     mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
                 });
@@ -430,7 +432,8 @@ fn iterate_method_candidates_with_autoref(
     }
     let refed = Canonical {
         kinds: deref_chain[0].kinds.clone(),
-        value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())),
+        value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone()))
+            .intern(&Interner),
     };
     if iterate_method_candidates_by_receiver(
         &refed,
@@ -446,7 +449,8 @@ fn iterate_method_candidates_with_autoref(
     }
     let ref_muted = Canonical {
         kinds: deref_chain[0].kinds.clone(),
-        value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())),
+        value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone()))
+            .intern(&Interner),
     };
     if iterate_method_candidates_by_receiver(
         &ref_muted,
@@ -526,7 +530,7 @@ fn iterate_trait_method_candidates(
     // if ty is `dyn Trait`, the trait doesn't need to be in scope
     let inherent_trait =
         self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
-    let env_traits = if let Ty::Placeholder(_) = self_ty.value {
+    let env_traits = if let TyKind::Placeholder(_) = self_ty.value.interned(&Interner) {
         // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
         env.traits_in_scope_from_clauses(&self_ty.value)
             .flat_map(|t| all_super_traits(db.upcast(), t))
@@ -679,13 +683,13 @@ pub(crate) fn inherent_impl_substs(
 }
 
 /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
-/// num_vars_to_keep) by `Ty::Unknown`.
+/// num_vars_to_keep) by `TyKind::Unknown`.
 fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
     s.fold_binders(
         &mut |ty, binders| {
-            if let Ty::BoundVar(bound) = &ty {
+            if let TyKind::BoundVar(bound) = ty.interned(&Interner) {
                 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
-                    Ty::Unknown
+                    TyKind::Unknown.intern(&Interner)
                 } else {
                     ty
                 }
@@ -772,9 +776,11 @@ fn autoderef_method_receiver(
 ) -> Vec<Canonical<Ty>> {
     let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
     // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
-    if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) {
+    if let Some(TyKind::Array(parameters)) =
+        deref_chain.last().map(|ty| ty.value.interned(&Interner))
+    {
         let kinds = deref_chain.last().unwrap().kinds.clone();
-        let unsized_ty = Ty::Slice(parameters.clone());
+        let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
         deref_chain.push(Canonical { value: unsized_ty, kinds })
     }
     deref_chain
index bb9b8bbfcd89c942f7f872f2dfe9eebccd2ff04b..527c5cbbd26bc3d58ac439c1ff6b2ae01747cc6b 100644 (file)
@@ -2,51 +2,55 @@
 use chalk_ir::TyVariableKind;
 use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
 
-use crate::{Scalar, Ty};
+use crate::{Interner, Scalar, Ty, TyKind};
 
 pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
     match op {
-        BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::Scalar(Scalar::Bool),
+        BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
         BinaryOp::Assignment { .. } => Ty::unit(),
-        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty {
-            Ty::Scalar(Scalar::Int(_))
-            | Ty::Scalar(Scalar::Uint(_))
-            | Ty::Scalar(Scalar::Float(_)) => lhs_ty,
-            Ty::InferenceVar(_, TyVariableKind::Integer)
-            | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
-            _ => Ty::Unknown,
-        },
-        BinaryOp::ArithOp(_) => match rhs_ty {
-            Ty::Scalar(Scalar::Int(_))
-            | Ty::Scalar(Scalar::Uint(_))
-            | Ty::Scalar(Scalar::Float(_)) => rhs_ty,
-            Ty::InferenceVar(_, TyVariableKind::Integer)
-            | Ty::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
-            _ => Ty::Unknown,
+        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
+            match lhs_ty.interned(&Interner) {
+                TyKind::Scalar(Scalar::Int(_))
+                | TyKind::Scalar(Scalar::Uint(_))
+                | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
+                TyKind::InferenceVar(_, TyVariableKind::Integer)
+                | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
+                _ => TyKind::Unknown.intern(&Interner),
+            }
+        }
+        BinaryOp::ArithOp(_) => match rhs_ty.interned(&Interner) {
+            TyKind::Scalar(Scalar::Int(_))
+            | TyKind::Scalar(Scalar::Uint(_))
+            | TyKind::Scalar(Scalar::Float(_)) => rhs_ty,
+            TyKind::InferenceVar(_, TyVariableKind::Integer)
+            | TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
+            _ => TyKind::Unknown.intern(&Interner),
         },
     }
 }
 
 pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
     match op {
-        BinaryOp::LogicOp(..) => Ty::Scalar(Scalar::Bool),
+        BinaryOp::LogicOp(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
         BinaryOp::Assignment { op: None } => lhs_ty,
-        BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
-            Ty::Scalar(_) | Ty::Str => lhs_ty,
-            Ty::InferenceVar(_, TyVariableKind::Integer)
-            | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
-            _ => Ty::Unknown,
+        BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.interned(&Interner) {
+            TyKind::Scalar(_) | TyKind::Str => lhs_ty,
+            TyKind::InferenceVar(_, TyVariableKind::Integer)
+            | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
+            _ => TyKind::Unknown.intern(&Interner),
         },
-        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown,
+        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
+            TyKind::Unknown.intern(&Interner)
+        }
         BinaryOp::CmpOp(CmpOp::Ord { .. })
         | BinaryOp::Assignment { op: Some(_) }
-        | BinaryOp::ArithOp(_) => match lhs_ty {
-            Ty::Scalar(Scalar::Int(_))
-            | Ty::Scalar(Scalar::Uint(_))
-            | Ty::Scalar(Scalar::Float(_)) => lhs_ty,
-            Ty::InferenceVar(_, TyVariableKind::Integer)
-            | Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
-            _ => Ty::Unknown,
+        | BinaryOp::ArithOp(_) => match lhs_ty.interned(&Interner) {
+            TyKind::Scalar(Scalar::Int(_))
+            | TyKind::Scalar(Scalar::Uint(_))
+            | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
+            TyKind::InferenceVar(_, TyVariableKind::Integer)
+            | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
+            _ => TyKind::Unknown.intern(&Interner),
         },
     }
 }
index 27f350f70b33aba7f56b9ada291b18401c17c23a..500d1781c93eb755ba2bcbd2759659fe03dc61a6 100644 (file)
@@ -10,7 +10,9 @@
 
 use crate::{db::HirDatabase, DebruijnIndex, Substs};
 
-use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
+use super::{
+    Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
+};
 
 use self::chalk::{from_chalk, Interner, ToChalk};
 
@@ -132,7 +134,7 @@ pub(crate) fn trait_solve_query(
     log::info!("trait_solve_query({})", goal.value.value.display(db));
 
     if let Obligation::Projection(pred) = &goal.value.value {
-        if let Ty::BoundVar(_) = &pred.projection_ty.parameters[0] {
+        if let TyKind::BoundVar(_) = &pred.projection_ty.parameters[0].interned(&Interner) {
             // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
             return Some(Solution::Ambig(Guidance::Unknown));
         }
index 1a2a3a8c7f1fa8a2d8b0be1c0ebf3449d0027f03..55181cc494f305dec9d91934d551c970e8f47031 100644 (file)
     method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
     utils::generics,
     BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate,
-    ProjectionTy, Substs, TraitRef, Ty,
+    ProjectionTy, Substs, TraitRef, Ty, TyKind,
 };
 use mapping::{
     convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType,
     TypeAliasAsValue,
 };
 
+pub use self::interner::Interner;
 pub(crate) use self::interner::*;
 
 pub(super) mod tls;
@@ -90,7 +91,7 @@ fn binder_kind(
             ty: &Ty,
             binders: &CanonicalVarKinds<Interner>,
         ) -> Option<chalk_ir::TyVariableKind> {
-            if let Ty::BoundVar(bv) = ty {
+            if let TyKind::BoundVar(bv) = ty.interned(&Interner) {
                 let binders = binders.as_slice(&Interner);
                 if bv.debruijn == DebruijnIndex::INNERMOST {
                     if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
@@ -220,21 +221,25 @@ fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatu
                     let impl_bound = GenericPredicate::Implemented(TraitRef {
                         trait_: future_trait,
                         // Self type as the first parameter.
-                        substs: Substs::single(Ty::BoundVar(BoundVar {
-                            debruijn: DebruijnIndex::INNERMOST,
-                            index: 0,
-                        })),
+                        substs: Substs::single(
+                            TyKind::BoundVar(BoundVar {
+                                debruijn: DebruijnIndex::INNERMOST,
+                                index: 0,
+                            })
+                            .intern(&Interner),
+                        ),
                     });
                     let proj_bound = GenericPredicate::Projection(ProjectionPredicate {
                         // The parameter of the opaque type.
-                        ty: Ty::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }),
+                        ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
+                            .intern(&Interner),
                         projection_ty: ProjectionTy {
                             associated_ty: future_output,
                             // Self type as the first parameter.
-                            parameters: Substs::single(Ty::BoundVar(BoundVar::new(
-                                DebruijnIndex::INNERMOST,
-                                0,
-                            ))),
+                            parameters: Substs::single(
+                                TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
+                                    .intern(&Interner),
+                            ),
                         },
                     });
                     let bound = OpaqueTyDatumBound {
@@ -263,7 +268,7 @@ fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatu
 
     fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
         // FIXME: actually provide the hidden type; it is relevant for auto traits
-        Ty::Unknown.to_chalk(self.db)
+        TyKind::Unknown.intern(&Interner).to_chalk(self.db)
     }
 
     fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@@ -391,7 +396,8 @@ pub(crate) fn associated_ty_data_query(
     let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
     let ctx = crate::TyLoweringContext::new(db, &resolver)
         .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
-    let self_ty = Ty::BoundVar(crate::BoundVar::new(crate::DebruijnIndex::INNERMOST, 0));
+    let self_ty =
+        TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
     let bounds = type_alias_data
         .bounds
         .iter()
index b0415e8b03f72880995614b66a1573dd85215b51..44cfb93596a6a307c847a966401d2fd4ff464d23 100644 (file)
 impl ToChalk for Ty {
     type Chalk = chalk_ir::Ty<Interner>;
     fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
-        match self {
-            Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
-            Ty::Array(parameters) => array_to_chalk(db, parameters),
-            Ty::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => {
+        match self.0 {
+            TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
+            TyKind::Array(parameters) => array_to_chalk(db, parameters),
+            TyKind::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => {
                 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
                 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
                     num_binders: 0,
@@ -38,57 +38,57 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
                 })
                 .intern(&Interner)
             }
-            Ty::AssociatedType(type_alias, substs) => {
+            TyKind::AssociatedType(type_alias, substs) => {
                 let assoc_type = TypeAliasAsAssocType(type_alias);
                 let assoc_type_id = assoc_type.to_chalk(db);
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
             }
 
-            Ty::OpaqueType(impl_trait_id, substs) => {
+            TyKind::OpaqueType(impl_trait_id, substs) => {
                 let id = impl_trait_id.to_chalk(db);
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
             }
 
-            Ty::ForeignType(type_alias) => {
+            TyKind::ForeignType(type_alias) => {
                 let foreign_type = TypeAliasAsForeignType(type_alias);
                 let foreign_type_id = foreign_type.to_chalk(db);
                 chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
             }
 
-            Ty::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
+            TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
 
-            Ty::Tuple(cardinality, substs) => {
+            TyKind::Tuple(cardinality, substs) => {
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
             }
-            Ty::Raw(mutability, substs) => {
+            TyKind::Raw(mutability, substs) => {
                 let ty = substs[0].clone().to_chalk(db);
                 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
             }
-            Ty::Slice(substs) => {
+            TyKind::Slice(substs) => {
                 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
             }
-            Ty::Str => chalk_ir::TyKind::Str.intern(&Interner),
-            Ty::FnDef(callable_def, substs) => {
+            TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
+            TyKind::FnDef(callable_def, substs) => {
                 let id = callable_def.to_chalk(db);
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
             }
-            Ty::Never => chalk_ir::TyKind::Never.intern(&Interner),
+            TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
 
-            Ty::Closure(def, expr, substs) => {
+            TyKind::Closure(def, expr, substs) => {
                 let closure_id = db.intern_closure((def, expr));
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner)
             }
 
-            Ty::Adt(adt_id, substs) => {
+            TyKind::Adt(adt_id, substs) => {
                 let substitution = substs.to_chalk(db);
                 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
             }
-            Ty::Alias(AliasTy::Projection(proj_ty)) => {
+            TyKind::Alias(AliasTy::Projection(proj_ty)) => {
                 let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db);
                 let substitution = proj_ty.parameters.to_chalk(db);
                 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
@@ -98,7 +98,7 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
                 .cast(&Interner)
                 .intern(&Interner)
             }
-            Ty::Placeholder(id) => {
+            TyKind::Placeholder(id) => {
                 let interned_id = db.intern_type_param_id(id);
                 PlaceholderIndex {
                     ui: UniverseIndex::ROOT,
@@ -106,9 +106,9 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
                 }
                 .to_ty::<Interner>(&Interner)
             }
-            Ty::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
-            Ty::InferenceVar(..) => panic!("uncanonicalized infer ty"),
-            Ty::Dyn(predicates) => {
+            TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
+            TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
+            TyKind::Dyn(predicates) => {
                 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
                     &Interner,
                     predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
@@ -119,7 +119,7 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
                 };
                 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
             }
-            Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
+            TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
                 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
                 let substitution = opaque_ty.parameters.to_chalk(db);
                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
@@ -128,30 +128,30 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
                 }))
                 .intern(&Interner)
             }
-            Ty::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
+            TyKind::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
         }
     }
     fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
         match chalk.data(&Interner).kind.clone() {
-            chalk_ir::TyKind::Error => Ty::Unknown,
-            chalk_ir::TyKind::Array(ty, _size) => Ty::Array(Substs::single(from_chalk(db, ty))),
+            chalk_ir::TyKind::Error => TyKind::Unknown,
+            chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))),
             chalk_ir::TyKind::Placeholder(idx) => {
                 assert_eq!(idx.ui, UniverseIndex::ROOT);
                 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
                     crate::salsa::InternId::from(idx.idx),
                 );
-                Ty::Placeholder(db.lookup_intern_type_param_id(interned_id))
+                TyKind::Placeholder(db.lookup_intern_type_param_id(interned_id))
             }
             chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
                 let associated_ty =
                     from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0;
                 let parameters = from_chalk(db, proj.substitution);
-                Ty::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters }))
+                TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters }))
             }
             chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
                 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id);
                 let parameters = from_chalk(db, opaque_ty.substitution);
-                Ty::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }))
+                TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }))
             }
             chalk_ir::TyKind::Function(chalk_ir::FnPointer {
                 num_binders,
@@ -164,14 +164,14 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
                     db,
                     substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
                 );
-                Ty::Function(FnPointer {
+                TyKind::Function(FnPointer {
                     num_args: (substs.len() - 1),
                     sig: FnSig { variadic },
                     substs,
                 })
             }
-            chalk_ir::TyKind::BoundVar(idx) => Ty::BoundVar(idx),
-            chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown,
+            chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
+            chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown,
             chalk_ir::TyKind::Dyn(where_clauses) => {
                 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
                 let predicates = where_clauses
@@ -180,49 +180,50 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
                     .iter(&Interner)
                     .map(|c| from_chalk(db, c.clone()))
                     .collect();
-                Ty::Dyn(predicates)
+                TyKind::Dyn(predicates)
             }
 
-            chalk_ir::TyKind::Adt(adt_id, subst) => Ty::Adt(adt_id, from_chalk(db, subst)),
-            chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType(
+            chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
+            chalk_ir::TyKind::AssociatedType(type_id, subst) => TyKind::AssociatedType(
                 from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0,
                 from_chalk(db, subst),
             ),
 
             chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
-                Ty::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst))
+                TyKind::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst))
             }
 
-            chalk_ir::TyKind::Scalar(scalar) => Ty::Scalar(scalar),
+            chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
             chalk_ir::TyKind::Tuple(cardinality, subst) => {
-                Ty::Tuple(cardinality, from_chalk(db, subst))
+                TyKind::Tuple(cardinality, from_chalk(db, subst))
             }
             chalk_ir::TyKind::Raw(mutability, ty) => {
-                Ty::Raw(mutability, Substs::single(from_chalk(db, ty)))
+                TyKind::Raw(mutability, Substs::single(from_chalk(db, ty)))
             }
-            chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))),
+            chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
             chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
-                Ty::Ref(mutability, Substs::single(from_chalk(db, ty)))
+                TyKind::Ref(mutability, Substs::single(from_chalk(db, ty)))
             }
-            chalk_ir::TyKind::Str => Ty::Str,
-            chalk_ir::TyKind::Never => Ty::Never,
+            chalk_ir::TyKind::Str => TyKind::Str,
+            chalk_ir::TyKind::Never => TyKind::Never,
 
             chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
-                Ty::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst))
+                TyKind::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst))
             }
 
             chalk_ir::TyKind::Closure(id, subst) => {
                 let id: crate::db::ClosureId = id.into();
                 let (def, expr) = db.lookup_intern_closure(id);
-                Ty::Closure(def, expr, from_chalk(db, subst))
+                TyKind::Closure(def, expr, from_chalk(db, subst))
             }
 
             chalk_ir::TyKind::Foreign(foreign_def_id) => {
-                Ty::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
+                TyKind::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
             }
             chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
             chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
         }
+        .intern(&Interner)
     }
 }
 
index ad0759bdad8c9a4168a04f7caa7658f0e920873c..c81c1d26eff4c1d0bb5de8508de987e0afca4aa9 100644 (file)
@@ -12,7 +12,7 @@
     AssocItem, Crate, HasSource, HirDisplay, ModuleDef,
 };
 use hir_def::FunctionId;
-use hir_ty::{Ty, TypeWalk};
+use hir_ty::TypeWalk;
 use ide_db::base_db::{
     salsa::{self, ParallelDatabase},
     SourceDatabaseExt,
@@ -187,12 +187,12 @@ pub fn run(self, verbosity: Verbosity) -> Result<()> {
             for (expr_id, _) in body.exprs.iter() {
                 let ty = &inference_result[expr_id];
                 num_exprs += 1;
-                if let Ty::Unknown = ty {
+                if ty.is_unknown() {
                     num_exprs_unknown += 1;
                 } else {
                     let mut is_partially_unknown = false;
                     ty.walk(&mut |ty| {
-                        if let Ty::Unknown = ty {
+                        if ty.is_unknown() {
                             is_partially_unknown = true;
                         }
                     });