@@ -52,7 +52,11 @@ pub struct Program {
5252}
5353
5454impl Program {
55- pub fn from_parse ( parsed : & parse:: Program , source : SourceFile , handler : & mut ErrorCollector ) -> Option < Self > {
55+ pub fn from_parse (
56+ parsed : & parse:: Program ,
57+ source : SourceFile ,
58+ handler : & mut ErrorCollector ,
59+ ) -> Option < Self > {
5660 let root_path = source. name ( ) . without_extension ( ) ;
5761
5862 let mut items: Vec < Item > = Vec :: new ( ) ;
@@ -145,7 +149,7 @@ impl Item {
145149 pub fn from_parse ( parsed : & parse:: Item , file_id : usize ) -> Result < Self , RichError > {
146150 match parsed {
147151 parse:: Item :: TypeAlias ( alias) => {
148- let driver_alias = TypeAlias :: from_parse ( alias, file_id ) ;
152+ let driver_alias = TypeAlias :: from_parse ( alias) ;
149153 Ok ( Item :: TypeAlias ( driver_alias) )
150154 }
151155 parse:: Item :: Function ( func) => {
@@ -229,7 +233,6 @@ impl_eq_hash!(Function; file_id, name, params, ret, body);
229233#[ derive( Clone , Debug ) ]
230234#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
231235pub struct TypeAlias {
232- file_id : usize , // NOTE: Maybe don't need
233236 name : AliasName ,
234237 ty : AliasedType ,
235238 span : Span ,
@@ -240,20 +243,14 @@ impl TypeAlias {
240243 ///
241244 /// We explicitly pass `file_id` here because the `parse::Function`
242245 /// doesn't know which file it came from.
243- pub fn from_parse ( parsed : & parse:: TypeAlias , file_id : usize ) -> Self {
246+ pub fn from_parse ( parsed : & parse:: TypeAlias ) -> Self {
244247 Self {
245- file_id,
246248 name : parsed. name ( ) . clone ( ) ,
247249 ty : parsed. ty ( ) . clone ( ) ,
248250 span : * parsed. as_ref ( ) ,
249251 }
250252 }
251253
252- /// Access the visibility of the alias.
253- pub fn file_id ( & self ) -> usize {
254- self . file_id
255- }
256-
257254 /// Access the name of the alias.
258255 pub fn name ( & self ) -> & AliasName {
259256 & self . name
@@ -273,12 +270,25 @@ impl TypeAlias {
273270 }
274271}
275272
276- impl_eq_hash ! ( TypeAlias ; file_id , name, ty) ;
273+ impl_eq_hash ! ( TypeAlias ; name, ty) ;
277274
278275#[ derive( Debug ) ]
279276pub enum C3Error {
280- CycleDetected ( Vec < usize > ) ,
281- InconsistentLinearization { module : usize } ,
277+ CycleDetected ( Vec < String > ) ,
278+ InconsistentLinearization { module : String } ,
279+ }
280+
281+ impl fmt:: Display for C3Error {
282+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
283+ match self {
284+ C3Error :: CycleDetected ( cycle) => {
285+ write ! ( f, "Circular dependency detected: {:?}" , cycle. join( " -> " ) )
286+ }
287+ C3Error :: InconsistentLinearization { module } => {
288+ write ! ( f, "Inconsistent resolution order for module '{:?}'" , module)
289+ }
290+ }
291+ }
282292}
283293
284294impl ProjectGraph {
@@ -289,29 +299,22 @@ impl ProjectGraph {
289299 handler : & mut ErrorCollector ,
290300 ) -> Option < Module > {
291301 let dep_key = SourceName :: Real ( Arc :: from ( full_path. with_extension ( "" ) ) ) ;
292- let content = match std:: fs:: read_to_string ( & full_path) {
293- Ok ( c) => c,
294- Err ( _) => {
295- let err = RichError :: new ( Error :: FileNotFound ( PathBuf :: from ( full_path) ) , span)
296- . with_source ( importer_source. clone ( ) ) ;
297-
298- handler. push ( err) ;
299- return None ;
300- }
302+ let Ok ( content) = std:: fs:: read_to_string ( full_path) else {
303+ let err = RichError :: new ( Error :: FileNotFound ( PathBuf :: from ( full_path) ) , span)
304+ . with_source ( importer_source. clone ( ) ) ;
305+
306+ handler. push ( err) ;
307+ return None ;
301308 } ;
302309
303310 let dep_source_file = SourceFile :: new ( dep_key. clone ( ) , Arc :: from ( content. clone ( ) ) ) ;
304311
305- if let Some ( parsed_program) =
306- parse:: Program :: parse_from_str_with_errors ( & content, dep_source_file. clone ( ) , handler)
307- {
308- Some ( Module {
312+ parse:: Program :: parse_from_str_with_errors ( & content, dep_source_file. clone ( ) , handler) . map (
313+ |parsed_program| Module {
309314 source : dep_source_file,
310315 parsed_program,
311- } )
312- } else {
313- None
314- }
316+ } ,
317+ )
315318 }
316319
317320 pub fn new (
@@ -374,14 +377,12 @@ impl ProjectGraph {
374377 continue ;
375378 }
376379
377- let module = if let Some ( module) = ProjectGraph :: parse_and_get_program (
380+ let Some ( module) = ProjectGraph :: parse_and_get_program (
378381 & full_path,
379382 importer_source. clone ( ) ,
380- import_span. clone ( ) ,
383+ import_span,
381384 handler,
382- ) {
383- module
384- } else {
385+ ) else {
385386 continue ;
386387 } ;
387388
@@ -432,7 +433,11 @@ impl ProjectGraph {
432433
433434 if visiting. contains ( & module) {
434435 let cycle_start = visiting. iter ( ) . position ( |m| * m == module) . unwrap ( ) ;
435- return Err ( C3Error :: CycleDetected ( visiting[ cycle_start..] . to_vec ( ) ) ) ;
436+ let cycle_names: Vec < String > = visiting[ cycle_start..]
437+ . iter ( )
438+ . map ( |& id| self . modules [ id] . source . name ( ) . to_string ( ) )
439+ . collect ( ) ;
440+ return Err ( C3Error :: CycleDetected ( cycle_names) ) ;
436441 }
437442
438443 visiting. push ( module) ;
@@ -442,14 +447,16 @@ impl ProjectGraph {
442447 let mut seqs: Vec < Vec < usize > > = Vec :: new ( ) ;
443448
444449 for parent in & parents {
445- let lin = self . linearize_rec ( * parent, memo, visiting) ?;
446- seqs. push ( lin ) ;
450+ let line = self . linearize_rec ( * parent, memo, visiting) ?;
451+ seqs. push ( line ) ;
447452 }
448453
449454 seqs. push ( parents. clone ( ) ) ;
450455
451456 let mut result = vec ! [ module] ;
452- let merged = merge ( seqs) . ok_or ( C3Error :: InconsistentLinearization { module } ) ?;
457+ let merged = merge ( seqs) . ok_or ( C3Error :: InconsistentLinearization {
458+ module : self . modules [ module] . source . name ( ) . to_string ( ) ,
459+ } ) ?;
453460
454461 result. extend ( merged) ;
455462
@@ -466,19 +473,17 @@ impl ProjectGraph {
466473 elem : & Identifier ,
467474 use_decl : & parse:: UseDecl ,
468475 ) -> Option < RichError > {
469- let resolution = if let Some ( res) = resolutions[ ind] . get ( elem) {
470- res
471- } else {
476+ let Some ( resolution) = resolutions[ ind] . get ( elem) else {
472477 return Some ( RichError :: new (
473478 Error :: UnresolvedItem ( elem. as_inner ( ) . to_string ( ) ) ,
474- * use_decl. span ( )
479+ * use_decl. span ( ) ,
475480 ) ) ;
476481 } ;
477-
482+
478483 if matches ! ( resolution. visibility, parse:: Visibility :: Private ) {
479484 return Some ( RichError :: new (
480485 Error :: PrivateItem ( elem. as_inner ( ) . to_string ( ) ) ,
481- * use_decl. span ( )
486+ * use_decl. span ( ) ,
482487 ) ) ;
483488 }
484489
@@ -512,7 +517,7 @@ impl ProjectGraph {
512517 visibility : vis. clone ( ) ,
513518 } ,
514519 ) ;
515-
520+
516521 None
517522 }
518523
@@ -597,11 +602,17 @@ impl ProjectGraph {
597602 }
598603 }
599604
600- pub fn resolve_complication_order ( & self , handler : & mut ErrorCollector ) -> Option < Program > {
601- // TODO: @LesterEvSe, Resolve errors more appropriately
602- let mut order = self . c3_linearize ( ) . unwrap ( ) ;
605+ pub fn resolve_complication_order (
606+ & self ,
607+ handler : & mut ErrorCollector ,
608+ ) -> Result < Option < Program > , String > {
609+ let mut order = match self . c3_linearize ( ) {
610+ Ok ( order) => order,
611+ Err ( err) => return Err ( err. to_string ( ) ) ,
612+ } ;
603613 order. reverse ( ) ;
604- self . build_program ( & order, handler)
614+
615+ Ok ( self . build_program ( & order, handler) )
605616 }
606617}
607618
@@ -687,13 +698,7 @@ impl fmt::Display for Item {
687698
688699impl fmt:: Display for TypeAlias {
689700 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
690- write ! (
691- f,
692- "type {} [file_id: {}] = {};" ,
693- self . name( ) ,
694- self . file_id( ) ,
695- self . ty( )
696- )
701+ write ! ( f, "type {} = {};" , self . name( ) , self . ty( ) )
697702 }
698703}
699704
@@ -809,9 +814,11 @@ pub(crate) mod tests {
809814 parse:: Program :: parse_from_str_with_errors ( & content, source. clone ( ) , & mut handler) ;
810815
811816 // 5. Check results
812- if handler. has_errors ( ) {
813- panic ! ( "Test Setup Failed: Root file syntax error: {}" , ErrorCollector :: to_string( & handler) ) ;
814- }
817+ assert ! (
818+ !handler. has_errors( ) ,
819+ "Test Setup Failed: Root file syntax error: {}" ,
820+ ErrorCollector :: to_string( & handler)
821+ ) ;
815822
816823 ( program. expect ( "Root parsing failed internally" ) , source)
817824 }
@@ -872,7 +879,7 @@ pub(crate) mod tests {
872879 let root_id = * ids. get ( "main" ) . unwrap ( ) ;
873880 let order = vec ! [ root_id] ; // Only one file
874881
875- let mut error_handler= ErrorCollector :: new ( ) ;
882+ let mut error_handler = ErrorCollector :: new ( ) ;
876883 let program = graph
877884 . build_program ( & order, & mut error_handler)
878885 . expect ( "Failed to build program" ) ;
@@ -964,8 +971,8 @@ pub(crate) mod tests {
964971
965972 // Order: A -> B -> Root
966973 let order = vec ! [ id_a, id_b, id_root] ;
967-
968- let mut error_handler= ErrorCollector :: new ( ) ;
974+
975+ let mut error_handler = ErrorCollector :: new ( ) ;
969976 let result = graph. build_program ( & order, & mut error_handler) ;
970977
971978 assert ! (
0 commit comments