From af466f8542173002361eb134e66102908c7cd024 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 14 Mar 2021 17:25:29 +0100 Subject: Make Ty wrap TyKind in an Arc ... like it will be in Chalk. We still keep `interned_mut` and `into_inner` methods that will probably not exist with Chalk. This worsens performance slightly (5ginstr inference on RA), but doesn't include other simplifications we can do yet. --- crates/hir_ty/src/infer.rs | 30 ++++++++++++++++++++++++------ crates/hir_ty/src/infer/coerce.rs | 2 +- crates/hir_ty/src/infer/expr.rs | 2 +- crates/hir_ty/src/infer/pat.rs | 12 ++++++------ crates/hir_ty/src/infer/unify.rs | 4 ++-- crates/hir_ty/src/lib.rs | 26 +++++++++++++++++--------- crates/hir_ty/src/lower.rs | 2 +- crates/hir_ty/src/traits/chalk/mapping.rs | 2 +- 8 files changed, 53 insertions(+), 27 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index fbfedb4e6..6dfe53902 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -108,6 +108,17 @@ pub struct TypeMismatch { pub actual: Ty, } +#[derive(Clone, PartialEq, Eq, Debug)] +struct InternedStandardTypes { + unknown: Ty, +} + +impl Default for InternedStandardTypes { + fn default() -> Self { + InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) } + } +} + /// The result of type inference: A mapping from expressions and patterns to types. #[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct InferenceResult { @@ -126,6 +137,8 @@ pub struct InferenceResult { pub type_of_expr: ArenaMap, pub type_of_pat: ArenaMap, pub(super) type_mismatches: ArenaMap, + /// Interned Unknown to return references to. + standard_types: InternedStandardTypes, } impl InferenceResult { @@ -170,7 +183,7 @@ impl Index for InferenceResult { type Output = Ty; fn index(&self, expr: ExprId) -> &Ty { - self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown)) + self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown) } } @@ -178,7 +191,7 @@ impl Index for InferenceResult { type Output = Ty; fn index(&self, pat: PatId) -> &Ty { - self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown)) + self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown) } } @@ -723,14 +736,19 @@ impl Expectation { /// This expresses no expectation on the type. fn none() -> Self { - Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false } + Expectation { + // FIXME + ty: TyKind::Unknown.intern(&Interner), + rvalue_hint: false, + } } - fn coercion_target(&self) -> &Ty { + fn coercion_target(&self) -> Ty { if self.rvalue_hint { - &Ty(TyKind::Unknown) + // FIXME + TyKind::Unknown.intern(&Interner) } else { - &self.ty + self.ty.clone() } } } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 36670043a..435f7d0db 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> { } // Pointer weakening and function to pointer - match (&mut from_ty.0, to_ty.interned(&Interner)) { + match (from_ty.interned_mut(), to_ty.interned(&Interner)) { // `*mut T` -> `*const T` // `&mut T` -> `&T` (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 55163c963..e9ca2b86f 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -800,7 +800,7 @@ impl<'a> InferenceContext<'a> { // we don't even make an attempt at coercion self.table.new_maybe_never_var() } else { - self.coerce(&Ty::unit(), expected.coercion_target()); + self.coerce(&Ty::unit(), &expected.coercion_target()); Ty::unit() } }; diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a16755cda..2e812ab94 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -158,11 +158,11 @@ impl<'a> InferenceContext<'a> { if mutability != exp_mut { // FIXME: emit type error? } - inner_ty + inner_ty.clone() } - _ => &Ty(TyKind::Unknown), + _ => self.result.standard_types.unknown.clone(), }; - let subty = self.infer_pat(*pat, expectation, default_bm); + let subty = self.infer_pat(*pat, &expectation, default_bm); TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner) } Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( @@ -232,11 +232,11 @@ impl<'a> InferenceContext<'a> { Pat::Box { inner } => match self.resolve_boxed_box() { Some(box_adt) => { let inner_expected = match expected.as_adt() { - Some((adt, substs)) if adt == box_adt => substs.as_single(), - _ => &Ty(TyKind::Unknown), + Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), + _ => self.result.standard_types.unknown.clone(), }; - let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); + let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); Ty::adt_ty(box_adt, Substs::single(inner_ty)) } None => self.err_ty(), diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index ebc612ca9..2501a4e0a 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -108,7 +108,7 @@ impl Canonicalized { pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { ty.walk_mut_binders( &mut |ty, binders| { - if let &mut TyKind::BoundVar(bound) = &mut ty.0 { + if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { if bound.debruijn >= binders { let (v, k) = self.free_vars[bound.index]; *ty = TyKind::InferenceVar(v, k).intern(&Interner); @@ -404,7 +404,7 @@ impl InferenceTable { if i > 0 { cov_mark::hit!(type_var_resolves_to_int_var); } - match &ty.0 { + match ty.interned(&Interner) { TyKind::InferenceVar(tv, _) => { let inner = tv.to_inner(); match self.var_unification_table.inlined_probe_value(inner).known() { diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 484652073..0b2da8971 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -248,11 +248,11 @@ pub enum TyKind { } #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Ty(TyKind); +pub struct Ty(Arc); impl TyKind { pub fn intern(self, _interner: &Interner) -> Ty { - Ty(self) + Ty(Arc::new(self)) } } @@ -260,6 +260,14 @@ impl Ty { pub fn interned(&self, _interner: &Interner) -> &TyKind { &self.0 } + + pub fn interned_mut(&mut self) -> &mut TyKind { + Arc::make_mut(&mut self.0) + } + + pub fn into_inner(self) -> TyKind { + Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) + } } /// A list of substitutions for generic parameters. @@ -814,7 +822,7 @@ 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.0 { + match self.interned_mut() { TyKind::Adt(_, substs) | TyKind::Slice(substs) | TyKind::Array(substs) @@ -854,7 +862,7 @@ impl Ty { } pub fn substs_mut(&mut self) -> Option<&mut Substs> { - match &mut self.0 { + match self.interned_mut() { TyKind::Adt(_, substs) | TyKind::Slice(substs) | TyKind::Array(substs) @@ -988,7 +996,7 @@ pub trait TypeWalk { { self.walk_mut_binders( &mut |ty_mut, binders| { - let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); + let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); *ty_mut = f(ty, binders); }, binders, @@ -1001,7 +1009,7 @@ pub trait TypeWalk { Self: Sized, { self.walk_mut(&mut |ty_mut| { - let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); + let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); *ty_mut = f(ty); }); self @@ -1022,7 +1030,7 @@ pub trait TypeWalk { { self.walk_mut_binders( &mut |ty, binders| { - if let &mut TyKind::BoundVar(bound) = &mut ty.0 { + if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { if bound.debruijn >= binders { *ty = substs.0[bound.index].clone().shift_bound_vars(binders); } @@ -1039,7 +1047,7 @@ pub trait TypeWalk { Self: Sized, { self.fold_binders( - &mut |ty, binders| match &ty.0 { + &mut |ty, binders| match ty.interned(&Interner) { TyKind::BoundVar(bound) if bound.debruijn >= binders => { TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) } @@ -1084,7 +1092,7 @@ impl TypeWalk for Ty { f: &mut impl FnMut(&mut Ty, DebruijnIndex), binders: DebruijnIndex, ) { - match &mut self.0 { + match self.interned_mut() { TyKind::Alias(AliasTy::Projection(p_ty)) => { p_ty.substitution.walk_mut_binders(f, binders); } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index d026310f4..2a4ad9172 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -993,7 +993,7 @@ pub(crate) fn generic_defaults_query( // Each default can only refer to previous parameters. ty.walk_mut_binders( - &mut |ty, binders| match &mut ty.0 { + &mut |ty, binders| match ty.interned_mut() { TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { if *index >= idx { // type variable default referring to parameter coming diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 05a4bf0df..2ab976190 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -24,7 +24,7 @@ use super::*; impl ToChalk for Ty { type Chalk = chalk_ir::Ty; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { - match self.0 { + match self.into_inner() { TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters), TyKind::Array(parameters) => array_to_chalk(db, parameters), TyKind::Function(FnPointer { sig, substs, .. }) => { -- cgit v1.2.3