From 064c6e4815b212d72f008082939376f570897c19 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 3 Dec 2020 15:34:15 +0000 Subject: Type Resolve ReturnExpr's to ensure they match the function type. This an implementation to check return types for functions it needs work to handle structs and other data structures later on. --- gcc/rust/analysis/rust-type-resolution.cc | 52 +++++++++++++++++++++++++++++-- gcc/rust/analysis/rust-type-resolution.h | 8 +++++ 2 files changed, 57 insertions(+), 3 deletions(-) (limited to 'gcc/rust/analysis') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 8558847..51c7380 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -774,9 +774,42 @@ TypeResolution::visit (AST::RangeFromToInclExpr &expr) void TypeResolution::visit (AST::RangeToInclExpr &expr) {} + void TypeResolution::visit (AST::ReturnExpr &expr) -{} +{ + // Ensure the type of this matches the function + auto before = typeBuffer.size (); + expr.get_expr ()->accept_vis (*this); + + if (typeBuffer.size () <= before) + { + rust_error_at (expr.get_expr ()->get_locus_slow (), + "unable to determine type for return expr"); + return; + } + + auto inferedType = typeBuffer.back (); + typeBuffer.pop_back (); + + // check this is compatible with the return type + // this will again have issues with structs before we move to HIR + + auto function = scope.CurrentFunction (); + if (!function->has_function_return_type ()) + { + rust_error_at (expr.get_locus (), "return for void function %s", + function->as_string ().c_str ()); + return; + } + + if (!typesAreCompatible (function->return_type.get (), inferedType, + expr.get_locus_slow ())) + { + return; + } +} + void TypeResolution::visit (AST::UnsafeBlockExpr &expr) {} @@ -889,18 +922,26 @@ TypeResolution::visit (AST::Function &function) // its a marker for a void function scope.InsertType (function.function_name, function.return_type.get ()); scope.InsertFunction (function.function_name, &function); + scope.PushFunction (&function); scope.Push (); for (auto ¶m : function.function_params) { if (!isTypeInScope (param.type.get (), param.locus)) - return; + { + scope.Pop (); + scope.PopFunction (); + return; + } auto before = letPatternBuffer.size (); param.param_name->accept_vis (*this); if (letPatternBuffer.size () <= before) { rust_error_at (param.locus, "failed to analyse parameter name"); + + scope.Pop (); + scope.PopFunction (); return; } @@ -913,7 +954,11 @@ TypeResolution::visit (AST::Function &function) if (function.has_function_return_type ()) { if (!isTypeInScope (function.return_type.get (), function.locus)) - return; + { + scope.Pop (); + scope.PopFunction (); + return; + } } // walk the expression body @@ -927,6 +972,7 @@ TypeResolution::visit (AST::Function &function) function.locals.push_back (value); scope.Pop (); + scope.PopFunction (); } void diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h index d461b66..0fef2ae 100644 --- a/gcc/rust/analysis/rust-type-resolution.h +++ b/gcc/rust/analysis/rust-type-resolution.h @@ -55,6 +55,12 @@ public: return functionScope.Lookup (ident, fn); } + void PushFunction (AST::Function *fn) { functionStack.push_back (fn); } + + void PopFunction () { functionStack.pop_back (); } + + AST::Function *CurrentFunction () { return functionStack.back (); } + void InsertLocal (std::string ident, AST::LetStmt *let) { localsPerBlock.Insert (ident, let); @@ -91,6 +97,8 @@ public: } private: + std::vector functionStack; + Scope functionScope; Scope localsPerBlock; Scope structsPerBlock; -- cgit v1.1