@@ -65,6 +65,7 @@ fn builtin_decls() -> Vec<Decl> {
6565 body: None ,
6666 ret: mk_type( Type :: Void ) ,
6767 constraints: vec![ ] ,
68+ requires: vec![ ] ,
6869 loc: test_loc( ) ,
6970 arena: ExprArena :: new( ) ,
7071 types: vec![ ] ,
@@ -83,6 +84,7 @@ fn builtin_decls() -> Vec<Decl> {
8384 body: None ,
8485 ret: mk_type( Type :: Void ) ,
8586 constraints: vec![ ] ,
87+ requires: vec![ ] ,
8688 loc: test_loc( ) ,
8789 arena: ExprArena :: new( ) ,
8890 types: vec![ ] ,
@@ -101,6 +103,7 @@ fn builtin_decls() -> Vec<Decl> {
101103 body: None ,
102104 ret: mk_type( Type :: Void ) ,
103105 constraints: vec![ ] ,
106+ requires: vec![ ] ,
104107 loc: test_loc( ) ,
105108 arena: ExprArena :: new( ) ,
106109 types: vec![ ] ,
@@ -130,6 +133,7 @@ fn builtin_decls() -> Vec<Decl> {
130133 body : None ,
131134 ret : ret_ty,
132135 constraints : vec ! [ ] ,
136+ requires : vec ! [ ] ,
133137 loc : test_loc ( ) ,
134138 arena : ExprArena :: new ( ) ,
135139 types : vec ! [ ] ,
@@ -155,6 +159,7 @@ fn builtin_decls() -> Vec<Decl> {
155159 body : None ,
156160 ret : bool_ty,
157161 constraints : vec ! [ ] ,
162+ requires : vec ! [ ] ,
158163 loc : test_loc ( ) ,
159164 arena : ExprArena :: new ( ) ,
160165 types : vec ! [ ] ,
@@ -188,6 +193,7 @@ fn builtin_decls() -> Vec<Decl> {
188193 body : None ,
189194 ret : ret_ty,
190195 constraints : vec ! [ ] ,
196+ requires : vec ! [ ] ,
191197 loc : test_loc ( ) ,
192198 arena : ExprArena :: new ( ) ,
193199 types : vec ! [ ] ,
@@ -225,6 +231,7 @@ fn builtin_decls() -> Vec<Decl> {
225231 body : None ,
226232 ret : f32x4_ty,
227233 constraints : vec ! [ ] ,
234+ requires : vec ! [ ] ,
228235 loc : test_loc ( ) ,
229236 arena : ExprArena :: new ( ) ,
230237 types : vec ! [ ] ,
@@ -244,6 +251,7 @@ fn builtin_decls() -> Vec<Decl> {
244251 body : None ,
245252 ret : f32x4_ty,
246253 constraints : vec ! [ ] ,
254+ requires : vec ! [ ] ,
247255 loc : test_loc ( ) ,
248256 arena : ExprArena :: new ( ) ,
249257 types : vec ! [ ] ,
@@ -627,7 +635,11 @@ impl Compiler {
627635 let mut pass = MonomorphPass :: new ( ) ;
628636 let entry_points = self . effective_entry_points ( ) ;
629637 let all_decls = pass. monomorphize_multi ( & self . decls , & entry_points) ?;
630- // monomorphize now returns all decls (original + specialized)
638+ // Capture the names of newly-generated specialized decls so we can
639+ // run a focused safety-check pass on them (their bodies were skipped
640+ // pre-monomorph because they contained size variables).
641+ let specialized_names: std:: collections:: HashSet < Name > =
642+ pass. instantiated_names ( ) . collect ( ) ;
631643 self . decls = DeclTable :: new ( all_decls) ;
632644
633645 // Rename non-generic overloaded functions to unique symbols.
@@ -636,6 +648,32 @@ impl Compiler {
636648 rename_overloaded_functions ( & mut self . decls ) ;
637649 self . decls = DeclTable :: new ( self . decls . decls . clone ( ) ) ;
638650
651+ // Re-run the safety checker on specialized declarations only.
652+ // Their bodies were skipped pre-monomorph because they had non-empty
653+ // size_vars; now sizes are concrete (`[T; Known(K)]`) so bounds and
654+ // require clauses can be verified properly.
655+ if !specialized_names. is_empty ( ) {
656+ let mut sc = SafetyChecker :: new ( ) ;
657+ for decl in & self . decls . decls {
658+ if let Decl :: Func ( f) = decl {
659+ if specialized_names. contains ( & f. name ) {
660+ sc. check_decl ( decl, & self . decls ) ;
661+ }
662+ }
663+ }
664+ if !self . quiet {
665+ sc. print_errors ( ) ;
666+ }
667+ for err in & sc. errors {
668+ self . last_errors
669+ . push ( format_error ( err. location , & err. message ) ) ;
670+ }
671+ self . last_safety_errors . extend ( sc. errors . iter ( ) . cloned ( ) ) ;
672+ if !sc. errors . is_empty ( ) {
673+ return Err ( format ! ( "safety check failed for {} call(s)" , sc. errors. len( ) ) ) ;
674+ }
675+ }
676+
639677 // Hoist loop-invariant struct field reads (after monomorphization
640678 // so we operate on concrete types, and after safety checking).
641679 {
0 commit comments