1- use crate :: ast:: { Program , parse_program} ;
21use crate :: checks;
32use crate :: diagnostic:: Diagnostic ;
43use crate :: hir:: { FunctionSig , Hir , HirTypeKind } ;
54use crate :: lexer:: { Token , lex} ;
6- use crate :: syntax:: ast:: { Callee , Item } ;
5+ use crate :: syntax:: ast:: { Callee , EffectDecl , Item } ;
76use crate :: syntax:: parse_source;
87
98pub fn analyze_source ( file : & str , source : & str ) -> Vec < Diagnostic > {
109 let tokens = lex ( file, source) ;
11- let program = parse_program ( & tokens) ;
1210 let syntax_program = parse_source ( file, source) ;
1311 let hir = Hir :: from_syntax ( & syntax_program) ;
1412 let mut analyzer = Analyzer {
1513 tokens : & tokens,
16- program,
1714 syntax_program,
1815 hir,
1916 diagnostics : Vec :: new ( ) ,
@@ -24,7 +21,6 @@ pub fn analyze_source(file: &str, source: &str) -> Vec<Diagnostic> {
2421
2522pub ( crate ) struct Analyzer < ' a > {
2623 pub ( crate ) tokens : & ' a [ Token ] ,
27- pub ( crate ) program : Program ,
2824 pub ( crate ) syntax_program : crate :: syntax:: ast:: Program ,
2925 pub ( crate ) hir : Hir ,
3026 pub ( crate ) diagnostics : Vec < Diagnostic > ,
@@ -42,7 +38,7 @@ impl Analyzer<'_> {
4238 }
4339
4440 fn check_file_mode_present ( & mut self ) {
45- if self . program . mode . is_none ( ) {
41+ if self . syntax_program . mode . is_none ( ) {
4642 let span = self . tokens . first ( ) . map ( |token| token. span . clone ( ) ) . unwrap ( ) ;
4743 self . diagnostics . push (
4844 Diagnostic :: error (
@@ -61,23 +57,16 @@ impl Analyzer<'_> {
6157 }
6258
6359 fn check_signature_explicitness ( & mut self ) {
64- for function in self . program . functions . values ( ) {
65- if function
66- . return_type
67- . as_deref ( )
68- . unwrap_or_default ( )
69- . is_empty ( )
70- {
71- let span = self
72- . tokens
73- . get ( function. body_start . saturating_sub ( 1 ) )
74- . map ( |token| token. span . clone ( ) )
75- . unwrap_or_else ( || self . tokens [ 0 ] . span . clone ( ) ) ;
60+ for item in & self . syntax_program . items {
61+ let Item :: Function ( function) = item else {
62+ continue ;
63+ } ;
64+ if function. return_ty . is_none ( ) {
7665 self . diagnostics . push (
7766 Diagnostic :: error (
7867 "RS0002" ,
7968 format ! ( "function `{}` must declare an explicit return type." , function. name) ,
80- span,
69+ function . span . clone ( ) ,
8170 "missing return type" ,
8271 )
8372 . with_cause ( "Public APIs must not rely on inference; this checker applies the canonical rule to all functions." )
@@ -86,20 +75,15 @@ impl Analyzer<'_> {
8675 }
8776
8877 for param in & function. params {
89- if param. type_name . is_empty ( ) {
90- let span = self
91- . tokens
92- . get ( function. body_start . saturating_sub ( 1 ) )
93- . map ( |token| token. span . clone ( ) )
94- . unwrap_or_else ( || self . tokens [ 0 ] . span . clone ( ) ) ;
78+ if param. ty . name . is_empty ( ) {
9579 self . diagnostics . push (
9680 Diagnostic :: error (
9781 "RS0003" ,
9882 format ! (
9983 "parameter `{}` in `{}` must declare an explicit type." ,
10084 param. name, function. name
10185 ) ,
102- span,
86+ param . span . clone ( ) ,
10387 "missing parameter type" ,
10488 )
10589 . with_fix (
@@ -112,23 +96,19 @@ impl Analyzer<'_> {
11296 }
11397
11498 for effect in & function. effects {
115- let valid = effect == "no_panic"
116- || effect == "noalloc"
117- || effect == "no_block"
118- || effect == "pure"
119- || effect == "unsafe"
120- || effect == "native"
121- || effect. starts_with ( "retains(" ) ;
99+ let effect_name = effect_name ( effect) ;
100+ let valid = effect_name == "no_panic"
101+ || effect_name == "noalloc"
102+ || effect_name == "no_block"
103+ || effect_name == "pure"
104+ || effect_name == "unsafe"
105+ || effect_name == "native"
106+ || matches ! ( effect, EffectDecl :: Retains ( _) ) ;
122107 if !valid {
123- let span = self
124- . tokens
125- . get ( function. body_start . saturating_sub ( 1 ) )
126- . map ( |token| token. span . clone ( ) )
127- . unwrap_or_else ( || self . tokens [ 0 ] . span . clone ( ) ) ;
128108 self . diagnostics . push ( Diagnostic :: warning (
129109 "RS0004" ,
130- format ! ( "unknown effect `{effect }` in `{}`." , function. name) ,
131- span,
110+ format ! ( "unknown effect `{effect_name }` in `{}`." , function. name) ,
111+ function . span . clone ( ) ,
132112 "unknown effect" ,
133113 ) ) ;
134114 }
@@ -170,3 +150,9 @@ impl Analyzer<'_> {
170150 }
171151 }
172152}
153+
154+ fn effect_name ( effect : & EffectDecl ) -> & str {
155+ match effect {
156+ EffectDecl :: Name ( name) | EffectDecl :: Retains ( name) => name,
157+ }
158+ }
0 commit comments