diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 58adc8fd38..7b9de11edd 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -54,8 +54,8 @@ use hir_ty::{ 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 @@ impl_from!(Struct, Union, Enum for 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 @@ impl TypeParam { 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 @@ impl Type { } 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 { - 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 @@ impl 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 @@ impl Type { } pub fn as_callable(&self, db: &dyn HirDatabase) -> Option { - 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 @@ impl Type { } 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 @@ impl Type { } 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 @@ impl Type { } pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec { - 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 @@ impl Type { 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); } diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index be1fd1f13d..09009a3d8c 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -14,7 +14,7 @@ use crate::{ 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; diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 2751cd304a..b2bfd68d4e 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -15,7 +15,7 @@ use crate::{ MissingPatFields, RemoveThisSemicolon, }, utils::variant_data, - AdtId, InferenceResult, Ty, + AdtId, InferenceResult, Interner, Ty, TyKind, }; pub(crate) use hir_def::{ @@ -289,11 +289,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> { let (body, source_map): (Arc, Arc) = 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 @@ impl<'a, 'b> ExprValidator<'a, 'b> { _ => 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()) } diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 04d39c5714..5a5cdcbf3a 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -227,7 +227,7 @@ use hir_def::{ 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), _ => (), } diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index e77a20fea1..e095bee282 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs @@ -11,7 +11,7 @@ use hir_def::{ }; 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 }); } } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index ab51cb0a6e..ee15f4f52a 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -12,8 +12,8 @@ use hir_expand::name::Name; 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { } 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { } 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(¶meters.prefix(i)); + if parameter != &actual_default { default_from = i + 1; } - (_, Some(default_parameter)) => { - let actual_default = default_parameter - .clone() - .subst(¶meters.prefix(i)); - if parameter != &actual_default { - default_from = i + 1; - } - } } } - ¶meters.0[0..default_from] } + ¶meters.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 @@ impl HirDisplay for Ty { } } } - 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { } } } - 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 @@ impl HirDisplay for Ty { 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 @@ impl HirDisplay for Ty { } } } - 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 @@ impl HirDisplay for Ty { } }; } - Ty::Unknown => { + TyKind::Unknown => { if f.display_target.is_source_code() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::UnknownType, @@ -582,7 +584,7 @@ impl HirDisplay for Ty { } write!(f, "{{unknown}}")?; } - Ty::InferenceVar(..) => write!(f, "_")?, + TyKind::InferenceVar(..) => write!(f, "_")?, } Ok(()) } diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 4d771a91e8..acde99b04c 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -41,7 +41,8 @@ use super::{ 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 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 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { } } + 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 @@ impl<'a> InferenceContext<'a> { /// 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 @@ impl<'a> InferenceContext<'a> { self.obligations.push(Obligation::Projection(projection)); self.resolve_ty_as_possible(ty) } - None => Ty::Unknown, + None => self.err_ty(), } } @@ -395,8 +400,10 @@ impl<'a> InferenceContext<'a> { /// 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 @@ impl<'a> InferenceContext<'a> { fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { } } // 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 @@ impl<'a> InferenceContext<'a> { } 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 @@ impl<'a> InferenceContext<'a> { result } else { // FIXME diagnostic - (Ty::Unknown, None) + (TyKind::Unknown.intern(&Interner), None) } } @@ -711,12 +718,12 @@ impl Expectation { /// 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 } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 7e8846f274..36670043ae 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -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 @@ impl<'a> InferenceContext<'a> { } 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 @@ impl<'a> InferenceContext<'a> { } 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 @@ impl<'a> InferenceContext<'a> { } // 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 @@ impl<'a> InferenceContext<'a> { } // 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), diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 262177ffbe..4e77f22fdc 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -20,8 +20,8 @@ use crate::{ 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 @@ impl<'a> InferenceContext<'a> { // 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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: Future 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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, ¶m_tys); self.normalize_associated_types_in(ret_ty) @@ -305,8 +313,11 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { expr: tgt_expr, }); } - Ty::Never + TyKind::Never.intern(&Interner) } Expr::Return { expr } => { if let Some(expr) = expr { @@ -369,14 +380,14 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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()) + .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(¶meters) + }) + } + 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(¶meters) + }) + } + _ => None, } - 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(¶meters) - }) - } - 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(¶meters) - }) - } - _ => 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 @@ impl<'a> InferenceContext<'a> { }; 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { ); 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::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)) + Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), + Literal::String(..) => { + TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner))) + .intern(&Interner) } - Literal::Char(..) => Ty::Scalar(Scalar::Char), + Literal::ByteString(..) => { + 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(..) => 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { // 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { }; 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) { diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a0ac8d80fd..a16755cda8 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -12,7 +12,7 @@ use hir_def::{ 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { } ty } else { - Ty::Unknown + self.err_ty() } } Pat::Ref { pat, mutability } => { @@ -159,10 +160,10 @@ impl<'a> InferenceContext<'a> { } 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 @@ impl<'a> InferenceContext<'a> { 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 diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index ae3554bac8..3929521785 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -9,7 +9,7 @@ use hir_def::{ }; 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 @@ impl<'a> InferenceContext<'a> { remaining_segments_for_ty, true, ); - if let Ty::Unknown = ty { + if let TyKind::Unknown = ty.interned(&Interner) { return None; } @@ -209,7 +209,7 @@ impl<'a> InferenceContext<'a> { name: &Name, id: ExprOrPatId, ) -> Option<(ValueNs, Option)> { - if let Ty::Unknown = ty { + if let TyKind::Unknown = ty.interned(&Interner) { return None; } diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 54fcfed108..16d89ed1bf 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 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 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { fn do_canonicalize(&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 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { } 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 Canonicalized { 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 @@ impl Canonicalized { // 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 { // (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 @@ impl TypeVariableTable { 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 @@ impl InferenceTable { 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 @@ impl InferenceTable { } 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 @@ impl InferenceTable { } ( - 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 @@ impl InferenceTable { // 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 @@ impl InferenceTable { 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 @@ impl InferenceTable { /// 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, 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 @@ impl InferenceTable { } /// 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, 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); diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index e77f24e4ed..2309db4922 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -49,7 +49,7 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen 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, 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 @@ impl Substs { /// 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 @@ impl Substs { 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 @@ impl SubstsBuilder { } 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) -> Self { @@ -601,45 +624,52 @@ impl TypeWalk for CallableSig { 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 @@ impl Ty { 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 @@ impl 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 { - 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 @@ impl Ty { } fn builtin_deref(&self) -> Option { - 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 { - 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 { - 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(¶meters)) } - Ty::Closure(.., substs) => { + TyKind::Closure(.., substs) => { let sig_param = &substs[0]; sig_param.callable_sig(db) } @@ -763,18 +797,18 @@ impl Ty { /// `self` is `Option<_>` and the substs contain `u32`, we'll have /// `Option` 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 @@ impl Ty { /// Returns the type parameters of this type if it has some (i.e. is an ADT /// or function); so if `self` is `Option`, 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> { - 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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { } pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option { - 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 @@ pub trait TypeWalk { } /// 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 @@ pub trait TypeWalk { { 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 @@ pub trait TypeWalk { 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 @@ pub trait TypeWalk { 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 @@ pub trait TypeWalk { 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 @@ pub trait TypeWalk { 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 @@ impl TypeWalk for Ty { 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); } _ => { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index d84ec9b7a7..9fe7e3dce2 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -34,7 +34,7 @@ use crate::{ }, 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 @@ impl Ty { pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option) { 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 @@ impl Ty { } 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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { } 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 @@ impl Ty { (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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { 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 @@ impl Ty { // 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 @@ impl GenericPredicate { 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 { 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 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 { @@ -1123,7 +1143,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { 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 { @@ -1237,7 +1257,7 @@ pub(crate) fn impl_self_ty_recover( impl_id: &ImplId, ) -> Binders { 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> { diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index d57c6de70e..f9877e7607 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -19,8 +19,8 @@ use crate::{ 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 { - 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 @@ impl Ty { 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> { 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 diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index bb9b8bbfcd..527c5cbbd2 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs @@ -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), }, } } diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 27f350f70b..500d1781c9 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -10,7 +10,9 @@ use stdx::panic_context; 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)); } diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 1a2a3a8c7f..55181cc494 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -20,13 +20,14 @@ use crate::{ 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 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { ty: &Ty, binders: &CanonicalVarKinds, ) -> Option { - 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 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { 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 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { // 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) -> 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() diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index b0415e8b03..44cfb93596 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -26,10 +26,10 @@ use super::*; impl ToChalk for Ty { type Chalk = chalk_ir::Ty; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { - 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 @@ impl ToChalk for Ty { }) .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 @@ impl ToChalk for Ty { .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 @@ impl ToChalk for Ty { } .to_ty::(&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 @@ impl ToChalk for Ty { }; 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 @@ impl ToChalk for Ty { })) .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) -> 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::(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 @@ impl ToChalk for Ty { 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 @@ impl ToChalk for Ty { .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::(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::(db, foreign_def_id).0) + TyKind::ForeignType(from_chalk::(db, foreign_def_id).0) } chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME } + .intern(&Interner) } } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index ad0759bdad..c81c1d26ef 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -12,7 +12,7 @@ use hir::{ 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 @@ impl AnalysisStatsCmd { 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; } });