@@ -14,7 +14,7 @@ mod stmt;
1414pub use errors:: TypeCheckError ;
1515
1616use crate :: {
17- hir_def:: { expr:: HirExpression , stmt:: HirStatement } ,
17+ hir_def:: { expr:: HirExpression , stmt:: HirStatement , traits :: TraitConstraint } ,
1818 node_interner:: { ExprId , FuncId , NodeInterner , StmtId } ,
1919 Type ,
2020} ;
@@ -28,6 +28,12 @@ pub struct TypeChecker<'interner> {
2828 interner : & ' interner mut NodeInterner ,
2929 errors : Vec < TypeCheckError > ,
3030 current_function : Option < FuncId > ,
31+
32+ /// Trait constraints are collected during type checking until they are
33+ /// verified at the end of a function. This is because constraints arise
34+ /// on each variable, but it is only until function calls when the types
35+ /// needed for the trait constraint may become known.
36+ trait_constraints : Vec < ( TraitConstraint , ExprId ) > ,
3137}
3238
3339/// Type checks a function and assigns the
@@ -66,18 +72,24 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec<Type
6672 type_checker. bind_pattern ( & param. 0 , param. 1 ) ;
6773 }
6874
69- let ( function_last_type, delayed_type_check_functions, mut body_errors ) =
75+ let ( function_last_type, delayed_type_check_functions) =
7076 type_checker. check_function_body ( function_body_id) ;
7177
72- errors. append ( & mut body_errors) ;
73-
7478 // Go through any delayed type checking errors to see if they are resolved, or error otherwise.
7579 for type_check_fn in delayed_type_check_functions {
7680 if let Err ( error) = type_check_fn ( ) {
7781 errors. push ( error) ;
7882 }
7983 }
8084
85+ // Verify any remaining trait constraints arising from the function body
86+ for ( constraint, expr_id) in std:: mem:: take ( & mut type_checker. trait_constraints ) {
87+ let span = type_checker. interner . expr_span ( & expr_id) ;
88+ type_checker. verify_trait_constraint ( & constraint. typ , constraint. trait_id , expr_id, span) ;
89+ }
90+
91+ errors. append ( & mut type_checker. errors ) ;
92+
8193 // Now remove all the `where` clause constraints we added
8294 for constraint in & meta. trait_constraints {
8395 interner. remove_assumed_trait_implementations_for_trait ( constraint. trait_id ) ;
@@ -146,26 +158,30 @@ fn function_info(interner: &NodeInterner, function_body_id: &ExprId) -> (noirc_e
146158
147159impl < ' interner > TypeChecker < ' interner > {
148160 fn new ( interner : & ' interner mut NodeInterner ) -> Self {
149- Self { delayed_type_checks : Vec :: new ( ) , interner, errors : vec ! [ ] , current_function : None }
161+ Self {
162+ delayed_type_checks : Vec :: new ( ) ,
163+ interner,
164+ errors : Vec :: new ( ) ,
165+ trait_constraints : Vec :: new ( ) ,
166+ current_function : None ,
167+ }
150168 }
151169
152170 pub fn push_delayed_type_check ( & mut self , f : TypeCheckFn ) {
153171 self . delayed_type_checks . push ( f) ;
154172 }
155173
156- fn check_function_body (
157- mut self ,
158- body : & ExprId ,
159- ) -> ( Type , Vec < TypeCheckFn > , Vec < TypeCheckError > ) {
174+ fn check_function_body ( & mut self , body : & ExprId ) -> ( Type , Vec < TypeCheckFn > ) {
160175 let body_type = self . check_expression ( body) ;
161- ( body_type, self . delayed_type_checks , self . errors )
176+ ( body_type, std :: mem :: take ( & mut self . delayed_type_checks ) )
162177 }
163178
164179 pub fn check_global ( id : & StmtId , interner : & ' interner mut NodeInterner ) -> Vec < TypeCheckError > {
165180 let mut this = Self {
166181 delayed_type_checks : Vec :: new ( ) ,
167182 interner,
168- errors : vec ! [ ] ,
183+ errors : Vec :: new ( ) ,
184+ trait_constraints : Vec :: new ( ) ,
169185 current_function : None ,
170186 } ;
171187 this. check_statement ( id) ;
0 commit comments