Skip to content

Commit

Permalink
perf: Avoid recomputing generalization for the same type
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Jan 27, 2019
1 parent 75174cd commit 0732ce1
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions check/src/typecheck/generalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub(crate) struct TypeGeneralizer<'a, 'b: 'a> {
variable_generator: TypeVariableGenerator,
tc: &'a mut Typecheck<'b>,
span: Span<BytePos>,
visited: FnvMap<RcType, RcType>,
}

impl<'a, 'b> ::std::ops::Deref for TypeGeneralizer<'a, 'b> {
Expand Down Expand Up @@ -75,6 +76,7 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> {
variable_generator: TypeVariableGenerator::new(&tc.subs, typ),
tc,
span,
visited: Default::default(),
}
}

Expand Down Expand Up @@ -186,7 +188,13 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> {
return replacement;
}

match **typ {
if RcType::strong_count(&typ) > 2 {
if let Some(new_type) = self.visited.get(typ) {
return Some(new_type.clone());
}
}

let new_type = match **typ {
Type::Variable(ref var) if self.subs.get_level(var.id) >= self.level => {
// Create a prefix if none exists
let id = self.variable_generator.next_variable(self.tc);
Expand Down Expand Up @@ -257,7 +265,7 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> {

Some(self.generic(generic))
} else {
replacement
replacement.clone()
}
}

Expand Down Expand Up @@ -290,7 +298,15 @@ impl<'a, 'b> TypeGeneralizer<'a, 'b> {
.map(|t| unroll_typ(self.tc, &t).unwrap_or(t))
.or_else(|| replacement.clone())
}
};

if let Some(new_type) = &new_type {
if RcType::strong_count(&typ) > 2 {
self.visited.insert(typ.clone(), new_type.clone());
}
}

new_type
}
}

Expand Down

0 comments on commit 0732ce1

Please sign in to comment.