diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index 968c32bb..706c7e9b 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -115,9 +115,11 @@ pub struct Function { pub function_node: ast::FunctionDef, pub is_method: bool, pub is_generator: bool, + /// return statements that are reachable in the top level function body pub return_statements: Vec, + /// yield statements that are reachable in the top level function body pub yeild_statements: Vec, - // helpful to later type check exceptions + /// raise statements that are reachable in the top level function body pub raise_statements: Vec, } diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index 852dd012..db99f510 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -49,7 +49,7 @@ impl TypeEvaluator { None => symbol.last_declaration(), }; - log::debug!("get_symbol_node_type: {:?}", decl); + log::debug!("fetch symbol declaration: {:?}", decl); match decl { Some(decl) => self.get_type_from_declaration(decl), None => Ok(PythonType::Any), @@ -222,27 +222,11 @@ impl TypeEvaluator { let annotated_return_type = if let Some(type_annotation) = f.function_node.returns.clone() { type_inference::get_type_from_annotation(&type_annotation) } else { - // TODO infer from function body - PythonType::Unknown + let inferred_return_type = self.infer_function_return_type(f); + log::debug!("infered_return_type: {:?}", inferred_return_type); + inferred_return_type }; - let is_never = if f.is_abstract() { - false - } else { - // TODO: if all code paths are raising then it's never type - f.function_node.body.iter().any(|stmt| match stmt { - ast::Statement::Raise(_) => true, - _ => false, - }) - }; - - - log::debug!("is_never: {}", is_never); - if is_never { - // TODO: if type annotation is not correct error - return Ok(PythonType::Never); - } - let arguments = f.function_node.args.clone(); let name = f.function_node.name.clone(); @@ -277,10 +261,12 @@ impl TypeEvaluator { name: name.to_string(), position, }; - match self.symbol_table.lookup_in_scope(lookup_request) { + let result = match self.symbol_table.lookup_in_scope(lookup_request) { Some(symbol) => self.get_symbol_node_type(symbol, position), None => Ok(PythonType::Unknown), - } + }; + log::debug!("infer_type_from_symbol_table: {:?} => {:?}", name, result); + result } fn get_sequence_type_from_elements(&self, elements: &Vec) -> PythonType { @@ -296,6 +282,13 @@ impl TypeEvaluator { } prev_elm_type } + + fn infer_function_return_type(&self, f: &crate::symbol_table::Function) -> PythonType { + if !f.is_abstract() && !f.raise_statements.is_empty() { + return PythonType::Never; + } + PythonType::Unknown + } } impl TraversalVisitorImmutGeneric for TypeEvaluator {