From 89002f34e4ae2d7cfe9eb53fbb0ba2c774f60501 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 12:13:34 +0300 Subject: [PATCH] Add function double-definition checking --- reid/src/lib.rs | 4 +++- reid/src/mir/typecheck.rs | 19 ++++++++++++++----- reid/src/mir/typeinference.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/reid/src/lib.rs b/reid/src/lib.rs index fbca027..1fa5844 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -129,7 +129,9 @@ pub fn perform_all_passes<'map>( dbg!(&context); for module in &mut context.modules { - module.1.functions.extend(form_intrinsics()); + for intrinsic in form_intrinsics() { + module.1.functions.insert(0, intrinsic); + } } #[cfg(debug_assertions)] diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index ec66b2d..23e586b 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -26,8 +26,8 @@ pub enum ErrorKind { FunctionNotDefined(String), #[error("Expected a return type of {0}, got {1} instead")] ReturnTypeMismatch(TypeKind, TypeKind), - #[error("Function already defined: {0}")] - FunctionAlreadyDefined(String), + #[error("Function {0} already defined {1}")] + FunctionAlreadyDefined(String, ErrorTypedefKind), #[error("Variable already defined: {0}")] VariableAlreadyDefined(String), #[error("Variable {0} is not declared as mutable")] @@ -80,6 +80,16 @@ pub struct TypeCheck<'t> { type TypecheckPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>; +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum ErrorTypedefKind { + #[error("locally")] + Local, + #[error("as an extern")] + Extern, + #[error("as an intrinsic")] + Intrinsic, +} + impl<'t> Pass for TypeCheck<'t> { type Data = (); type TError = ErrorKind; @@ -116,10 +126,9 @@ impl<'t> Pass for TypeCheck<'t> { } } - let seen = HashSet::new(); for typedef in defmap.values() { - let mut curr = seen.clone(); - curr.insert(typedef.name.clone()); + let mut seen_types = HashSet::new(); + seen_types.insert(typedef.name.clone()); check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state); } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 0fa8f41..5a805ba 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -4,13 +4,13 @@ //! must then be passed through TypeCheck with the same [`TypeRefs`] in order to //! place the correct types from the IDs and check that there are no issues. -use std::{convert::Infallible, iter}; +use std::{collections::HashMap, convert::Infallible, iter}; use crate::{mir::TypeKind, util::try_all}; use super::{ pass::{Pass, PassResult, PassState}, - typecheck::ErrorKind, + typecheck::{ErrorKind, ErrorTypedefKind}, typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, @@ -33,6 +33,28 @@ impl<'t> Pass for TypeInference<'t> { type TError = ErrorKind; fn module(&mut self, module: &mut Module, mut state: TypeInferencePassState) -> PassResult { + let mut seen_functions = HashMap::new(); + for function in &mut module.functions { + if let Some(kind) = seen_functions.get(&function.name) { + state.note_errors( + &vec![ErrorKind::FunctionAlreadyDefined( + function.name.clone(), + *kind, + )], + function.signature(), + ); + } else { + seen_functions.insert( + function.name.clone(), + match function.kind { + FunctionDefinitionKind::Local(..) => ErrorTypedefKind::Local, + FunctionDefinitionKind::Extern(..) => ErrorTypedefKind::Extern, + FunctionDefinitionKind::Intrinsic(..) => ErrorTypedefKind::Intrinsic, + }, + ); + } + } + for function in &mut module.functions { let res = function.infer_types(&self.refs, &mut state.inner()); state.ok(res, function.block_meta());