From 2911d7ef9261c9dfbc0509f1756908b5e95f5ce6 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 26 Jan 2019 18:52:41 +0100 Subject: [PATCH] perf: Avoid allocating new ArcKind in Type::kind --- base/src/types/mod.rs | 53 +++++++++++++++++++++--------------------- check/src/kindcheck.rs | 2 +- check/src/typecheck.rs | 9 +++---- completion/src/lib.rs | 11 +++++---- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/base/src/types/mod.rs b/base/src/types/mod.rs index cb311741c2..a2403ecd3b 100644 --- a/base/src/types/mod.rs +++ b/base/src/types/mod.rs @@ -19,21 +19,22 @@ use stable_deref_trait::StableDeref; use itertools::Itertools; -use crate::ast::{Commented, EmptyEnv, IdentEnv}; -use crate::fnv::FnvMap; -use crate::kind::{ArcKind, Kind, KindEnv}; -use crate::merge::merge; -use crate::metadata::Comment; -use crate::pos::{BytePos, HasSpan, Span}; -use crate::source::Source; -use crate::symbol::{Name, Symbol, SymbolRef}; +use crate::{ + ast::{Commented, EmptyEnv, IdentEnv}, + fnv::FnvMap, + kind::{ArcKind, Kind, KindCache, KindEnv}, + merge::merge, + metadata::Comment, + pos::{BytePos, HasSpan, Span}, + source::Source, + symbol::{Name, Symbol, SymbolRef}, +}; #[cfg(feature = "serde")] -use crate::serde::de::DeserializeState; -#[cfg(feature = "serde")] -use crate::serde::ser::SerializeState; -#[cfg(feature = "serde")] -use crate::serialization::{SeSeed, Seed}; +use crate::{ + serde::{de::DeserializeState, ser::SerializeState}, + serialization::{SeSeed, Seed}, +}; use self::pretty_print::Printer; pub use self::{ @@ -667,8 +668,8 @@ where &self.typ } - pub fn kind(&self) -> Cow { - let result_type = self.unresolved_type().kind(); + pub fn kind<'k>(&'k self, cache: &'k KindCache) -> Cow<'k, ArcKind> { + let result_type = self.unresolved_type().kind(cache); self.params().iter().rev().fold(result_type, |acc, param| { Cow::Owned(Kind::function(param.kind.clone(), acc.into_owned())) }) @@ -1145,16 +1146,16 @@ where } } - pub fn kind(&self) -> Cow { - self.kind_(0) + pub fn kind<'k>(&'k self, cache: &'k KindCache) -> Cow<'k, ArcKind> { + self.kind_(cache, 0) } - fn kind_(&self, applied_args: usize) -> Cow { + fn kind_<'k>(&'k self, cache: &'k KindCache, applied_args: usize) -> Cow<'k, ArcKind> { let mut immediate_kind = match *self { - Type::Function(_, _, _) => Cow::Owned(Kind::typ()), - Type::App(ref t, ref args) => t.kind_(args.len()), - Type::Error => Cow::Owned(Kind::error()), - Type::Hole => Cow::Owned(Kind::hole()), + Type::Function(_, _, _) => Cow::Borrowed(&cache.typ), + Type::App(ref t, ref args) => t.kind_(cache, args.len()), + Type::Error => Cow::Borrowed(&cache.error), + Type::Hole => Cow::Borrowed(&cache.hole), Type::Opaque | Type::Builtin(_) | Type::Record(_) | Type::Variant(_) => { Cow::Owned(Kind::typ()) } @@ -1163,17 +1164,17 @@ where let t = Kind::typ(); Cow::Owned(Kind::function(t.clone(), t)) } - Type::Forall(_, ref typ) => typ.kind_(applied_args), + Type::Forall(_, ref typ) => typ.kind_(cache, applied_args), Type::Variable(ref var) => Cow::Borrowed(&var.kind), Type::Skolem(ref skolem) => Cow::Borrowed(&skolem.kind), Type::Generic(ref gen) => Cow::Borrowed(&gen.kind), // FIXME can be another kind - Type::Ident(_) | Type::Projection(_) => Cow::Owned(Kind::typ()), + Type::Ident(_) | Type::Projection(_) => Cow::Owned(cache.typ()), Type::Alias(ref alias) => { return if alias.params().len() < applied_args { - alias.typ.kind_(applied_args - alias.params().len()) + alias.typ.kind_(cache, applied_args - alias.params().len()) } else { - let mut kind = alias.typ.kind_(0).into_owned(); + let mut kind = alias.typ.kind_(cache, 0).into_owned(); for arg in &alias.params()[applied_args..] { kind = Kind::function(arg.kind.clone(), kind) } diff --git a/check/src/kindcheck.rs b/check/src/kindcheck.rs index ef3568a3e5..df8656dc9f 100644 --- a/check/src/kindcheck.rs +++ b/check/src/kindcheck.rs @@ -160,7 +160,7 @@ impl<'a> KindCheck<'a> { // Errors get reported in typecheck as well so ignore them here crate::typecheck::translate_projected_type(self.info, self.idents, &mut NullInterner, ids) .ok() - .map(|typ| typ.kind().into_owned()) + .map(|typ| typ.kind(&self.kind_cache).into_owned()) } // Kindhecks `typ`, infering it to be of kind `Type` diff --git a/check/src/typecheck.rs b/check/src/typecheck.rs index c5a2f7a58e..d4ae69b3f7 100644 --- a/check/src/typecheck.rs +++ b/check/src/typecheck.rs @@ -62,13 +62,14 @@ pub(crate) struct Environment<'a> { stack: ScopedMap, /// Types which exist in some scope (`type Test = ... in ...`) stack_types: ScopedMap)>, + kind_cache: KindCache, } impl<'a> KindEnv for Environment<'a> { fn find_kind(&self, type_name: &SymbolRef) -> Option { self.stack_types .get(type_name) - .map(|&(_, ref alias)| alias.kind().into_owned()) + .map(|&(_, ref alias)| alias.kind(&self.kind_cache).into_owned()) .or_else(|| self.environment.find_kind(type_name)) } } @@ -148,19 +149,19 @@ impl<'a> Typecheck<'a> { metadata: &'a mut FnvMap, ) -> Typecheck<'a> { let symbols = SymbolModule::new(module, symbols); - let kind_cache = KindCache::new(); - let subs = Substitution::new(kind_cache.typ(), interner.clone()); + let subs = Substitution::new(interner.kind_cache.typ(), interner.clone()); Typecheck { environment: Environment { environment, stack: ScopedMap::new(), stack_types: ScopedMap::new(), + kind_cache: interner.kind_cache.clone(), }, symbols: symbols, named_variables: FnvMap::default(), errors: Errors::new(), type_variables: ScopedMap::new(), - kind_cache: kind_cache, + kind_cache: interner.kind_cache.clone(), implicit_resolver: crate::implicits::ImplicitResolver::new(environment, metadata), unbound_variables: ScopedMap::new(), subs, diff --git a/completion/src/lib.rs b/completion/src/lib.rs index 5f45a06307..3897dc9d75 100644 --- a/completion/src/lib.rs +++ b/completion/src/lib.rs @@ -209,7 +209,10 @@ impl> OnFound for Suggest { } self.type_stack.insert( alias.name.clone(), - alias.unresolved_type().kind().into_owned(), + alias + .unresolved_type() + .kind(&Default::default()) + .into_owned(), ); } } @@ -609,7 +612,7 @@ where self.found = MatchState::Found(Match::Type( bind.name.span, &bind.alias.value.name, - bind.alias.value.kind().into_owned(), + bind.alias.value.kind(&Default::default()).into_owned(), )); } else { for param in bind.alias.value.params() { @@ -718,7 +721,7 @@ where self.found = MatchState::Found(Match::Type( typ.span(), builtin.symbol(), - typ.kind().into_owned(), + typ.kind(&Default::default()).into_owned(), )); } @@ -730,7 +733,7 @@ where self.found = MatchState::Found(Match::Type( typ.span(), &alias.name, - typ.kind().into_owned(), + typ.kind(&Default::default()).into_owned(), )); }