use diagnostics::LocalSink;
use syntax::ast::{Expression, Generic};
pub(crate) fn run(typed_ast: &[Expression], sink: &LocalSink) {
for item in typed_ast {
visit(item, sink);
}
}
fn visit(expression: &Expression, sink: &LocalSink) {
check_type_name(expression, sink);
for generic in generics_of(expression) {
if is_reserved(&generic.name) {
sink.push(diagnostics::infer::predeclared_type_shadowed(
&generic.name,
generic.span,
));
}
}
for child in expression.children() {
visit(child, sink);
}
}
fn check_type_name(expression: &Expression, sink: &LocalSink) {
let (name, name_span) = match expression {
Expression::Enum {
name, name_span, ..
}
| Expression::ValueEnum {
name, name_span, ..
}
| Expression::Struct {
name, name_span, ..
}
| Expression::TypeAlias {
name, name_span, ..
}
| Expression::Interface {
name, name_span, ..
} => (name, name_span),
_ => return,
};
if is_reserved(name) {
sink.push(diagnostics::infer::predeclared_type_shadowed(
name, *name_span,
));
}
}
fn generics_of(expression: &Expression) -> &[Generic] {
match expression {
Expression::Function { generics, .. }
| Expression::ImplBlock { generics, .. }
| Expression::Enum { generics, .. }
| Expression::Struct { generics, .. }
| Expression::TypeAlias { generics, .. }
| Expression::Interface { generics, .. } => generics,
_ => &[],
}
}
fn is_reserved(name: &str) -> bool {
matches!(name, "any" | "comparable")
}