stop abusing map to find free variables of WC

This commit is contained in:
Niko Matsakis 2018-07-13 20:17:57 +03:00 committed by Markus Westerlind
parent 4117907695
commit e82990331d
3 changed files with 79 additions and 23 deletions

View File

@ -1,5 +1,6 @@
use grammar::parse_tree::{self, TypeParameter};
use grammar::repr;
use std::iter;
/// Finds the set of "free variables" in something -- that is, the
/// type/lifetime parameters that appear and are not bound. For
@ -19,9 +20,7 @@ impl<T: FreeVariables> FreeVariables for Option<T> {
impl<T: FreeVariables> FreeVariables for Vec<T> {
fn free_variables(&self) -> Vec<TypeParameter> {
self.into_iter()
.flat_map(|e| e.free_variables())
.collect()
self.into_iter().flat_map(|e| e.free_variables()).collect()
}
}
@ -31,7 +30,8 @@ impl FreeVariables for repr::TypeRepr {
repr::TypeRepr::Tuple(tys) => tys.free_variables(),
repr::TypeRepr::Nominal(data) => data.free_variables(),
repr::TypeRepr::Associated {
type_parameter, id: _
type_parameter,
id: _,
} => vec![TypeParameter::Id(type_parameter.clone())],
repr::TypeRepr::Lifetime(l) => vec![TypeParameter::Lifetime(l.clone())],
repr::TypeRepr::Ref {
@ -69,3 +69,61 @@ impl FreeVariables for repr::NominalTypeRepr {
.collect()
}
}
impl<T: FreeVariables> FreeVariables for parse_tree::WhereClause<T> {
fn free_variables(&self) -> Vec<TypeParameter> {
match self {
parse_tree::WhereClause::Lifetime { lifetime, bounds } =>
iter::once(TypeParameter::Lifetime(lifetime.clone()))
.chain(bounds.iter().map(|l| TypeParameter::Lifetime(l.clone())))
.collect(),
parse_tree::WhereClause::Type { forall, ty, bounds } => ty
.free_variables()
.into_iter()
.chain(bounds.free_variables())
.filter(|tp| !forall.contains(tp))
.collect(),
}
}
}
impl<T: FreeVariables> FreeVariables for parse_tree::TypeBoundParameter<T> {
fn free_variables(&self) -> Vec<TypeParameter> {
match self {
parse_tree::TypeBoundParameter::Lifetime(l) => vec![TypeParameter::Lifetime(l.clone())],
parse_tree::TypeBoundParameter::TypeParameter(t) => t.free_variables(),
parse_tree::TypeBoundParameter::Associated(..) => vec![],
}
}
}
impl<T: FreeVariables> FreeVariables for parse_tree::TypeBound<T> {
fn free_variables(&self) -> Vec<TypeParameter> {
match self {
parse_tree::TypeBound::Lifetime(l) => vec![TypeParameter::Lifetime(l.clone())],
parse_tree::TypeBound::Fn {
forall,
path,
parameters,
ret,
} => path
.free_variables()
.into_iter()
.chain(parameters.free_variables())
.chain(ret.free_variables())
.filter(|tp| !forall.contains(tp))
.collect(),
parse_tree::TypeBound::Trait {
forall,
path,
parameters,
} => path
.free_variables()
.into_iter()
.chain(parameters.free_variables())
.filter(|tp| !forall.contains(tp))
.collect(),
}
}
}

View File

@ -145,17 +145,16 @@ impl<'ascent, 'grammar, W: Write>
.cloned()
.collect();
let mut referenced_where_clauses = Set::new();
for wc in &grammar.where_clauses {
wc.map(|ty| {
if ty.free_variables()
let referenced_where_clauses: Set<_> = grammar
.where_clauses
.iter()
.filter(|wc| {
wc.free_variables()
.iter()
.any(|p| nonterminal_type_params.contains(p))
{
referenced_where_clauses.insert(wc.clone());
}
});
}
})
.cloned()
.collect();
let nonterminal_where_clauses: Vec<_> = grammar
.where_clauses
@ -547,7 +546,7 @@ impl<'ascent, 'grammar, W: Write>
vec![format!(
"{}TOKENS: Iterator<Item=Result<{},{}>>",
self.prefix, triple_type, iter_error_type
),],
)],
None,
true, // include grammar parameters
fn_args,

View File

@ -319,17 +319,16 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
.cloned()
.collect();
let mut referenced_where_clauses = Set::new();
for wc in &grammar.where_clauses {
wc.map(|ty| {
if ty.free_variables()
let referenced_where_clauses: Set<_> = grammar
.where_clauses
.iter()
.filter(|wc| {
wc.free_variables()
.iter()
.any(|p| symbol_type_params.contains(p))
{
referenced_where_clauses.insert(wc.clone());
}
});
}
})
.cloned()
.collect();
let symbol_where_clauses: Vec<_> = grammar
.where_clauses