From c0acb066b4503a407ee13f7b99a3a7111bcdfc82 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 26 Jan 2019 21:50:35 +0100 Subject: [PATCH] perf: Avoid recursing more in occurs check --- base/src/types/mod.rs | 25 +++++++++++++++++++++---- check/src/substitution.rs | 20 ++++++++------------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/base/src/types/mod.rs b/base/src/types/mod.rs index a2403ecd3b..329d5c499e 100644 --- a/base/src/types/mod.rs +++ b/base/src/types/mod.rs @@ -2527,7 +2527,6 @@ where I: 'a, { match **typ { - Type::Forall(_, ref typ) => f.walk(typ), Type::Function(_, ref arg, ref ret) => { f.walk(arg); f.walk(ret); @@ -2538,7 +2537,10 @@ where f.walk(a); } } - Type::Record(ref row) | Type::Variant(ref row) | Type::Effect(ref row) => f.walk(row), + Type::Forall(_, ref typ) + | Type::Record(ref typ) + | Type::Variant(ref typ) + | Type::Effect(ref typ) => f.walk(typ), Type::ExtendRow { ref types, ref fields, @@ -3442,9 +3444,24 @@ where } } -impl<'a, I, T, F: ?Sized> Walker<'a, T> for F +pub struct FlagsVisitor(pub Flags, pub F); + +impl<'a, T, F> Walker<'a, T> for FlagsVisitor +where + F: ?Sized + FnMut(&'a T), + T: TypeExt + 'a, +{ + fn walk(&mut self, typ: &'a T) { + if self.0.intersects(typ.flags()) { + (self.1)(typ); + walk_type_(typ, self); + } + } +} + +impl<'a, I, T, F> Walker<'a, T> for F where - F: FnMut(&'a T), + F: ?Sized + FnMut(&'a T), T: Deref> + 'a, I: 'a, { diff --git a/check/src/substitution.rs b/check/src/substitution.rs index aa23dbc9de..5563e29979 100644 --- a/check/src/substitution.rs +++ b/check/src/substitution.rs @@ -158,7 +158,7 @@ where T: Substitutable, { fn walk(&mut self, typ: &'t T) { - if self.occurs { + if !typ.contains_variables() || self.occurs { return; } let typ = self.subs.real(typ); @@ -174,17 +174,13 @@ where } } - if typ.contains_variables() { - let mut occurs = Occurs { - occurs: false, - var: var, - subs: subs, - }; - occurs.walk(typ); - occurs.occurs - } else { - false - } + let mut occurs = Occurs { + occurs: false, + var: var, + subs: subs, + }; + occurs.walk(typ); + occurs.occurs } /// Specialized union implementation which makes sure that variables with a higher level always