@@ -72,36 +72,48 @@ pub struct SourceMap {
7272 /// This serves as the exact inverse of the `lookup` map.
7373 ///
7474 /// This is highly useful for error reporting and diagnostics.
75- paths : Vec < CanonPath > ,
75+ entries : Vec < CanonSourceFile > ,
7676}
7777
7878impl SourceMap {
7979 fn new ( root_source : CanonSourceFile ) -> Self {
8080 let mut ids = HashMap :: new ( ) ;
81+
8182 ids. insert ( root_source. name ( ) . clone ( ) , MAIN_MODULE ) ;
83+
8284 Self {
8385 ids,
84- paths : vec ! [ root_source. name ( ) . clone ( ) ] ,
86+ entries : vec ! [ root_source] ,
8587 }
8688 }
8789
88- fn insert ( & mut self , path : CanonPath ) {
89- let id = self . paths . len ( ) ;
90- self . ids . insert ( path. clone ( ) , id) ;
91- self . paths . push ( path) ;
92- debug_assert_eq ! ( self . ids. len( ) , self . paths. len( ) ) ;
90+ fn insert ( & mut self , entry : CanonSourceFile ) {
91+ let id = self . entries . len ( ) ;
92+
93+ self . ids . insert ( entry. name ( ) . clone ( ) , id) ;
94+ self . entries . push ( entry) ;
95+
96+ debug_assert_eq ! ( self . ids. len( ) , self . entries. len( ) ) ;
9397 }
9498
9599 fn len ( & self ) -> usize {
96- self . paths . len ( )
100+ self . entries . len ( )
97101 }
98102
99- pub fn get_id ( & self , path : & CanonPath ) -> Option < usize > {
103+ pub fn id ( & self , path : & CanonPath ) -> Option < usize > {
100104 self . ids . get ( path) . copied ( )
101105 }
102106
103- pub fn get_path ( & self , id : usize ) -> Option < & CanonPath > {
104- self . paths . get ( id)
107+ pub fn entry ( & self , id : usize ) -> Option < & CanonSourceFile > {
108+ self . entries . get ( id)
109+ }
110+
111+ pub fn content ( & self , id : usize ) -> Option < Arc < str > > {
112+ self . entries . get ( id) . map ( |e| e. content ( ) . clone ( ) )
113+ }
114+
115+ pub fn path ( & self , id : usize ) -> Option < & CanonPath > {
116+ self . entries . get ( id) . map ( |e| e. name ( ) )
105117 }
106118
107119 pub fn iter ( & self ) -> impl Iterator < Item = ( & CanonPath , & usize ) > {
@@ -289,7 +301,7 @@ impl DependencyGraph {
289301 continue ;
290302 }
291303
292- if let Some ( existing_id) = self . source_map . get_id ( & path) {
304+ if let Some ( existing_id) = self . source_map . id ( & path) {
293305 let deps = self . dependencies . entry ( current. id ) . or_default ( ) ;
294306 if !deps. contains ( & existing_id) {
295307 deps. push ( existing_id) ;
@@ -299,11 +311,27 @@ impl DependencyGraph {
299311
300312 let new_id = self . source_map . len ( ) ;
301313
314+ let Ok ( content) = std:: fs:: read_to_string ( path. as_path ( ) ) else {
315+ let err = RichError :: new (
316+ Error :: FileNotFound {
317+ filename : PathBuf :: from ( path. as_path ( ) ) ,
318+ } ,
319+ import_span,
320+ )
321+ . with_source ( current. source . clone ( ) ) ;
322+
323+ ctx. handler . push ( err) ;
324+
325+ // Safe to ignore output: previous `.contains` check prevents collisions.
326+ let _ = ctx. invalid_imports . insert ( path) ;
327+ continue ;
328+ } ;
329+
330+ let source = CanonSourceFile :: new ( path. clone ( ) , Arc :: from ( content) ) ;
331+
302332 let Some ( module) = Self :: parse_and_get_source_module (
303333 new_id,
304- & path,
305- & current. source ,
306- import_span,
334+ source. clone ( ) ,
307335 ctx. handler ,
308336 ctx. unstable_features ,
309337 ) else {
@@ -312,7 +340,7 @@ impl DependencyGraph {
312340 continue ;
313341 } ;
314342
315- self . source_map . insert ( path . clone ( ) ) ;
343+ self . source_map . insert ( source ) ;
316344 self . modules . push ( module) ;
317345
318346 self . dependencies
@@ -323,33 +351,17 @@ impl DependencyGraph {
323351 }
324352 }
325353
326- /// This helper cleanly encapsulates the process of loading source text, parsing it
327- /// into an `parse::Program`, and combining them so the compiler can easily work with the file.
328- /// If the file is missing or contains syntax errors, it logs the diagnostic to the
354+ /// This helper cleanly encapsulates the process of parsing source text into an
355+ /// `parse::Program`, and combining them so the compiler can easily work with the file.
356+ /// If the file is contains syntax errors, it logs the diagnostic to the
329357 /// `ErrorCollector` and safely returns `None`.
330358 fn parse_and_get_source_module (
331359 new_id : usize ,
332- path : & CanonPath ,
333- importer_source : & CanonSourceFile ,
334- span : Span ,
360+ source : CanonSourceFile ,
335361 handler : & mut ErrorCollector ,
336362 unstable_features : & UnstableFeatures ,
337363 ) -> Option < SourceModule > {
338- let Ok ( content) = std:: fs:: read_to_string ( path. as_path ( ) ) else {
339- let err = RichError :: new (
340- Error :: FileNotFound {
341- filename : PathBuf :: from ( path. as_path ( ) ) ,
342- } ,
343- span,
344- )
345- . with_source ( importer_source. clone ( ) ) ;
346-
347- handler. push ( err) ;
348- return None ;
349- } ;
350-
351364 let mut error_handler = ErrorCollector :: new ( ) ;
352- let source = CanonSourceFile :: new ( path. clone ( ) , Arc :: from ( content) ) ;
353365 let ast = parse:: Program :: parse_from_str_with_errors (
354366 new_id,
355367 source. clone ( ) ,
@@ -715,7 +727,7 @@ pub(crate) mod tests {
715727
716728 // Assert: Size checks
717729 assert_eq ! ( graph. modules. len( ) , 3 ) ;
718- assert_eq ! ( graph. source_map. paths . len( ) , 3 ) ;
730+ assert_eq ! ( graph. source_map. entries . len( ) , 3 ) ;
719731
720732 // Assert: Ensure BFS assigned the IDs in the exact correct order
721733 let main_id = ids[ "main" ] ;
0 commit comments