From 793b658082f71f016655f7f4f3e44432814116fa Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Wed, 14 Aug 2019 23:10:58 +0200 Subject: [PATCH] perf(check): Only initialize the variable generator when it is necessary (-3%) --- check/src/typecheck.rs | 12 +++++++----- check/src/typecheck/generalize.rs | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/check/src/typecheck.rs b/check/src/typecheck.rs index fed212e28c..5f5524e308 100644 --- a/check/src/typecheck.rs +++ b/check/src/typecheck.rs @@ -25,7 +25,7 @@ use crate::base::{ symbol::{Symbol, SymbolModule, SymbolRef, Symbols}, types::{ self, Alias, AliasRef, AppVec, ArcType, ArgType, Field, Flags, Generic, PrimitiveEnv, Type, - TypeCache, TypeContext, TypeEnv, TypeExt, + TypeCache, TypeContext, TypeEnv, TypeExt, Walker, }, }; @@ -1445,7 +1445,7 @@ impl<'a> Typecheck<'a> { } let mut modifier = TypeModifier::Rigid; - types::walk_type(&self.subs.zonk(&original_func_type), &mut |typ: &RcType| { + types::FlagsVisitor(Flags::HAS_VARIABLES, |typ: &RcType| { if modifier == TypeModifier::Rigid { if let Type::Variable(var) = &**typ { if !return_variables.contains(&var.id) { @@ -1453,7 +1453,8 @@ impl<'a> Typecheck<'a> { } } } - }); + }) + .walk(&self.subs.zonk(&original_func_type)); Ok(TailCall::Type(ModType::new(modifier, func_type))) } @@ -2913,7 +2914,7 @@ impl<'a> Typecheck<'a> { let new_type = f(self, ModType::new(original_type.modifier, skolemized)); let original_type = self.subs.zonk(&original_type); - types::walk_type(&original_type, &mut |typ: &RcType| { + types::FlagsVisitor(Flags::HAS_SKOLEMS, |typ: &RcType| { if let Type::Skolem(skolem) = &**typ { if !self.environment.skolem_variables.contains_key(&skolem.name) { self.error( @@ -2925,7 +2926,8 @@ impl<'a> Typecheck<'a> { ); } } - }); + }) + .walk(&original_type); self.with_forall(&original_type, new_type) } diff --git a/check/src/typecheck/generalize.rs b/check/src/typecheck/generalize.rs index 18284dff24..fe39cb6788 100644 --- a/check/src/typecheck/generalize.rs +++ b/check/src/typecheck/generalize.rs @@ -14,7 +14,8 @@ pub(crate) struct TypeGeneralizer<'a, 'b: 'a> { /// We delay updating the substitution until after all recursive bindings have been typechecked /// to ensure that they get can figure out which variable got generalized for each binding delayed_generalizations: Vec<(u32, RcType)>, - variable_generator: TypeVariableGenerator, + variable_generator: Option, + top_type: RcType, pub tc: &'a mut Typecheck<'b>, span: Span, } @@ -55,7 +56,8 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> { level, unbound_variables: Default::default(), delayed_generalizations: Vec::new(), - variable_generator: TypeVariableGenerator::new(&tc.subs, typ), + variable_generator: None, + top_type: typ.clone(), tc, span, } @@ -152,9 +154,18 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> { let Self { tc, variable_generator, + top_type, .. } = self; let gen = self.unbound_variables.entry(var.id).or_insert_with(|| { + let variable_generator = match variable_generator { + Some(v) => v, + None => { + *variable_generator = + Some(TypeVariableGenerator::new(&tc.subs, top_type)); + variable_generator.as_mut().unwrap() + } + }; // Create a prefix if none exists let id = variable_generator.next_variable(tc); @@ -249,7 +260,7 @@ impl TypeVariableGenerator { gather_foralls(&mut map, subs, typ); TypeVariableGenerator { map, - name: "".to_string(), + name: String::new(), i: 0, } }