Skip to content

Commit

Permalink
Unused type warnings, though not indirect
Browse files Browse the repository at this point in the history
  • Loading branch information
Rigidity committed Apr 17, 2024
1 parent bec2891 commit 3db6bc8
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 31 deletions.
15 changes: 13 additions & 2 deletions crates/rue-compiler/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct Database {
hir: Arena<Hir>,
lir: Arena<Lir>,
symbol_tokens: HashMap<SymbolId, SyntaxToken>,
type_tokens: HashMap<TypeId, SyntaxToken>,
}

impl Database {
Expand All @@ -45,8 +46,14 @@ impl Database {
id
}

pub(crate) fn alloc_type(&mut self, ty: Type) -> TypeId {
TypeId(self.types.alloc(ty))
pub(crate) fn alloc_type(&mut self, ty: Type, token: Option<SyntaxToken>) -> TypeId {
let id = TypeId(self.types.alloc(ty));

if let Some(token) = token {
self.type_tokens.insert(id, token);
}

id
}

pub(crate) fn alloc_hir(&mut self, hir: Hir) -> HirId {
Expand Down Expand Up @@ -80,6 +87,10 @@ impl Database {
self.ty_raw(id)
}

pub fn type_token(&self, id: TypeId) -> Option<SyntaxToken> {
self.type_tokens.get(&id).cloned()
}

pub(crate) fn ty_mut(&mut self, id: TypeId) -> &mut Type {
&mut self.types[id.0]
}
Expand Down
3 changes: 3 additions & 0 deletions crates/rue-compiler/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub enum WarningKind {

#[error("unused symbol `{0}`")]
UnusedSymbol(String),

#[error("unused type `{0}`")]
UnusedType(String),
}

#[derive(Debug, Error, Clone, PartialEq, Eq, Hash)]
Expand Down
65 changes: 38 additions & 27 deletions crates/rue-compiler/src/lowerer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ pub struct Lowerer<'a> {

impl<'a> Lowerer<'a> {
pub fn new(db: &'a mut Database) -> Self {
let int_type = db.alloc_type(Type::Int);
let bool_type = db.alloc_type(Type::Bool);
let bytes_type = db.alloc_type(Type::Bytes);
let bytes32_type = db.alloc_type(Type::Bytes32);
let pk_type = db.alloc_type(Type::PublicKey);
let any_type = db.alloc_type(Type::Any);
let nil_type = db.alloc_type(Type::Nil);
let int_type = db.alloc_type(Type::Int, None);
let bool_type = db.alloc_type(Type::Bool, None);
let bytes_type = db.alloc_type(Type::Bytes, None);
let bytes32_type = db.alloc_type(Type::Bytes32, None);
let pk_type = db.alloc_type(Type::PublicKey, None);
let any_type = db.alloc_type(Type::Any, None);
let nil_type = db.alloc_type(Type::Nil, None);
let nil_hir = db.alloc_hir(Hir::Atom(Vec::new()));
let unknown_type = db.alloc_type(Type::Unknown);
let unknown_type = db.alloc_type(Type::Unknown, None);
let unknown_hir = db.alloc_hir(Hir::Unknown);

// This is the root scope, with builtins for various types and functions.
Expand Down Expand Up @@ -288,7 +288,7 @@ impl<'a> Lowerer<'a> {

/// Define a type for an alias in the current scope, but leave it as unknown for now.
fn declare_type_alias(&mut self, type_alias: TypeAliasItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
let type_id = self.db.alloc_type(Type::Unknown, type_alias.name());
if let Some(name) = type_alias.name() {
self.scope_mut().define_type(name.to_string(), type_id);
}
Expand All @@ -297,7 +297,7 @@ impl<'a> Lowerer<'a> {

/// Define a type for a struct in the current scope, but leave it as unknown for now.
fn declare_struct(&mut self, struct_item: StructItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
let type_id = self.db.alloc_type(Type::Unknown, struct_item.name());
if let Some(name) = struct_item.name() {
self.scope_mut().define_type(name.to_string(), type_id);
}
Expand All @@ -319,10 +319,15 @@ impl<'a> Lowerer<'a> {
continue;
}

variants.insert(name.to_string(), self.db.alloc_type(Type::Unknown));
variants.insert(
name.to_string(),
self.db.alloc_type(Type::Unknown, variant.name()),
);
}

let type_id = self.db.alloc_type(Type::Enum(EnumType::new(variants)));
let type_id = self
.db
.alloc_type(Type::Enum(EnumType::new(variants)), enum_item.name());

if let Some(name) = enum_item.name() {
self.scope_mut().define_type(name.to_string(), type_id);
Expand Down Expand Up @@ -1218,7 +1223,9 @@ impl<'a> Lowerer<'a> {
Some((Guard::new(to, self.bytes_type), hir_id))
}
(Type::Any, Type::Bytes) => {
let pair_type = self.db.alloc_type(Type::Pair(self.any_type, self.any_type));
let pair_type = self
.db
.alloc_type(Type::Pair(self.any_type, self.any_type), None);
let is_cons = self.db.alloc_hir(Hir::IsCons(hir_id));
let hir_id = self.db.alloc_hir(Hir::Not(is_cons));
Some((Guard::new(to, pair_type), hir_id))
Expand All @@ -1236,7 +1243,7 @@ impl<'a> Lowerer<'a> {
Some((Guard::new(to, self.nil_type), hir_id))
}
(Type::List(inner), Type::Nil) => {
let pair_type = self.db.alloc_type(Type::Pair(inner, from));
let pair_type = self.db.alloc_type(Type::Pair(inner, from), None);
let is_cons = self.db.alloc_hir(Hir::IsCons(hir_id));
let hir_id = self.db.alloc_hir(Hir::Not(is_cons));
Some((Guard::new(to, pair_type), hir_id))
Expand Down Expand Up @@ -1333,7 +1340,7 @@ impl<'a> Lowerer<'a> {
_ => None,
};
} else {
list_type = Some(self.db.alloc_type(Type::List(output.ty())));
list_type = Some(self.db.alloc_type(Type::List(output.ty()), None));
item_type = Some(output.ty());
}
}
Expand Down Expand Up @@ -1361,7 +1368,7 @@ impl<'a> Lowerer<'a> {

Value::typed(
hir_id,
list_type.unwrap_or_else(|| self.db.alloc_type(Type::List(self.unknown_type))),
list_type.unwrap_or_else(|| self.db.alloc_type(Type::List(self.unknown_type), None)),
)
}

Expand Down Expand Up @@ -1401,7 +1408,7 @@ impl<'a> Lowerer<'a> {
};

let hir_id = self.db.alloc_hir(Hir::Pair(first.hir(), rest.hir()));
let type_id = self.db.alloc_type(Type::Pair(first.ty(), rest.ty()));
let type_id = self.db.alloc_type(Type::Pair(first.ty(), rest.ty()), None);

Value::typed(hir_id, type_id)
}
Expand Down Expand Up @@ -1485,7 +1492,7 @@ impl<'a> Lowerer<'a> {

Value::typed(
self.db.alloc_hir(Hir::Reference(symbol_id)),
self.db.alloc_type(Type::Function(ty)),
self.db.alloc_type(Type::Function(ty), None),
)
}

Expand Down Expand Up @@ -1623,7 +1630,9 @@ impl<'a> Lowerer<'a> {
self.db.alloc_hir(Hir::Reference(symbol_id)),
self.symbol_type(symbol_id)
.unwrap_or_else(|| match self.db.symbol(symbol_id) {
Symbol::Function { ty, .. } => self.db.alloc_type(Type::Function(ty.clone())),
Symbol::Function { ty, .. } => {
self.db.alloc_type(Type::Function(ty.clone()), None)
}
Symbol::Parameter { type_id } => *type_id,
Symbol::LetBinding { type_id, .. } => *type_id,
Symbol::ConstBinding { type_id, .. } => *type_id,
Expand Down Expand Up @@ -1823,8 +1832,11 @@ impl<'a> Lowerer<'a> {
return self.unknown_type;
};

self.scope_mut().use_type(ty);

for name in idents {
ty = self.path_into_type(ty, name.text(), name.text_range());
self.scope_mut().use_type(ty);
}

ty
Expand Down Expand Up @@ -1852,7 +1864,7 @@ impl<'a> Lowerer<'a> {
};

let item_type = self.compile_type(inner);
self.db.alloc_type(Type::List(item_type))
self.db.alloc_type(Type::List(item_type), None)
}

fn compile_pair_type(&mut self, pair_type: PairType) -> TypeId {
Expand All @@ -1866,7 +1878,7 @@ impl<'a> Lowerer<'a> {
.map(|ty| self.compile_type(ty))
.unwrap_or(self.unknown_type);

self.db.alloc_type(Type::Pair(first, rest))
self.db.alloc_type(Type::Pair(first, rest), None)
}

fn compile_function_type(&mut self, function: AstFunctionType) -> TypeId {
Expand Down Expand Up @@ -1897,11 +1909,10 @@ impl<'a> Lowerer<'a> {
.map(|ty| self.compile_type(ty))
.unwrap_or(self.unknown_type);

self.db.alloc_type(Type::Function(FunctionType::new(
parameter_types,
return_type,
vararg,
)))
self.db.alloc_type(
Type::Function(FunctionType::new(parameter_types, return_type, vararg)),
None,
)
}

fn compile_optional_type(&mut self, optional: OptionalType) -> TypeId {
Expand All @@ -1918,7 +1929,7 @@ impl<'a> Lowerer<'a> {
return inner;
}

self.db.alloc_type(Type::Optional(ty))
self.db.alloc_type(Type::Optional(ty), None)
}

fn try_unwrap_optional(&mut self, ty: TypeId) -> TypeId {
Expand Down
48 changes: 47 additions & 1 deletion crates/rue-compiler/src/optimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
hir::{BinOp, Hir},
lir::Lir,
symbol::Symbol,
Diagnostic, DiagnosticKind, WarningKind,
Diagnostic, DiagnosticKind, TypeId, WarningKind,
};

#[derive(Default)]
Expand All @@ -17,6 +17,7 @@ struct Environment {
captures: IndexSet<SymbolId>,
parameters: IndexSet<SymbolId>,
used_symbols: HashSet<SymbolId>,
used_types: HashSet<TypeId>,
varargs: bool,
inherits_from: Option<ScopeId>,
}
Expand Down Expand Up @@ -84,6 +85,10 @@ impl<'a> Optimizer<'a> {
for symbol_id in self.env(scope_id).used_symbols.clone() {
self.env_mut(parent_scope_id).used_symbols.insert(symbol_id);
}

for type_id in self.env(scope_id).used_types.clone() {
self.env_mut(parent_scope_id).used_types.insert(type_id);
}
}

fn compute_captures_entrypoint(
Expand All @@ -97,6 +102,8 @@ impl<'a> Optimizer<'a> {
}

self.environments.insert(scope_id, Environment::default());
let used_types = self.db.scope(scope_id).used_types().clone();
self.env_mut(scope_id).used_types.extend(used_types);
self.env_mut(scope_id).inherits_from = inherits_from;
self.compute_captures_hir(scope_id, hir_id);

Expand All @@ -117,6 +124,24 @@ impl<'a> Optimizer<'a> {
);
}
}

let unused_types: Vec<TypeId> = self
.db
.scope(scope_id)
.local_types()
.iter()
.filter(|&type_id| !self.env(scope_id).used_types.contains(type_id))
.copied()
.collect();

for type_id in unused_types {
if let Some(token) = self.db.type_token(type_id) {
self.warning(
WarningKind::UnusedType(token.to_string()),
token.text_range(),
);
}
}
}

fn compute_captures_hir(&mut self, scope_id: ScopeId, hir_id: HirId) {
Expand Down Expand Up @@ -235,6 +260,27 @@ impl<'a> Optimizer<'a> {
}
}

let unused_types: Vec<TypeId> = self
.db
.scope(root_scope_id)
.local_types()
.iter()
.filter(|&type_id| {
!self.env(scope_id).used_types.contains(type_id)
&& !self.db.scope(root_scope_id).used_types().contains(type_id)
})
.copied()
.collect();

for type_id in unused_types {
if let Some(token) = self.db.type_token(type_id) {
self.warning(
WarningKind::UnusedType(token.to_string()),
token.text_range(),
);
}
}

for symbol_id in self.db.scope(scope_id).local_symbols() {
if self.db.symbol(symbol_id).is_parameter() {
self.env_mut(scope_id).parameters.insert(symbol_id);
Expand Down
15 changes: 14 additions & 1 deletion crates/rue-compiler/src/scope.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

use indexmap::IndexSet;

Expand All @@ -10,6 +10,7 @@ pub struct Scope {
type_aliases: HashMap<String, TypeId>,
type_names: HashMap<TypeId, String>,
local_symbols: IndexSet<SymbolId>,
used_types: HashSet<TypeId>,
}

impl Scope {
Expand Down Expand Up @@ -42,4 +43,16 @@ impl Scope {
pub fn local_symbols(&self) -> Vec<SymbolId> {
self.local_symbols.iter().copied().collect()
}

pub fn local_types(&self) -> Vec<TypeId> {
self.type_names.keys().copied().collect()
}

pub fn use_type(&mut self, type_id: TypeId) {
self.used_types.insert(type_id);
}

pub fn used_types(&self) -> &HashSet<TypeId> {
&self.used_types
}
}

0 comments on commit 3db6bc8

Please sign in to comment.