use diagnostics::LocalSink;
use syntax::ast::{BinaryOperator, Expression, Literal};
use syntax::types::SimpleKind;
pub(crate) fn run(typed_ast: &[Expression], sink: &LocalSink) {
for item in typed_ast {
visit_expression(item, sink);
}
}
fn visit_expression(expression: &Expression, sink: &LocalSink) {
if let Expression::Binary {
operator,
left,
right,
span,
..
} = expression
&& matches!(
operator,
BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight
)
&& let Some(kind) = left.get_type().as_simple()
&& let Some(bit_width) = fixed_bit_width(kind)
&& let Expression::Literal {
literal: Literal::Integer { value, .. },
..
} = right.unwrap_parens()
&& *value >= u64::from(bit_width)
{
sink.push(diagnostics::infer::oversized_shift(
span,
kind.leaf_name(),
bit_width,
*value,
));
}
for child in expression.children() {
visit_expression(child, sink);
}
}
fn fixed_bit_width(kind: SimpleKind) -> Option<u32> {
match kind {
SimpleKind::Int8 | SimpleKind::Uint8 | SimpleKind::Byte => Some(8),
SimpleKind::Int16 | SimpleKind::Uint16 => Some(16),
SimpleKind::Int32 | SimpleKind::Uint32 | SimpleKind::Rune => Some(32),
SimpleKind::Int64 | SimpleKind::Uint64 => Some(64),
_ => None,
}
}