@@ -57,8 +57,8 @@ struct CachedSourceOwner {
5757
5858#[ derive( Debug ) ]
5959struct CachedSourceDependent < ' a > {
60- cached_colomns_map : OnceLock < Option < SourceMap < ' static > > > ,
61- cached_line_only_map : OnceLock < Option < SourceMap < ' static > > > ,
60+ cached_colomns_map : OnceLock < Option < Cow < ' static , SourceMap < ' static > > > > ,
61+ cached_line_only_map : OnceLock < Option < Cow < ' static , SourceMap < ' static > > > > ,
6262 phantom : std:: marker:: PhantomData < & ' a ( ) > ,
6363}
6464
@@ -116,31 +116,39 @@ impl Source for CachedSource {
116116 }
117117
118118 fn map < ' a > ( & ' a self , options : & MapOptions ) -> Option < Cow < ' a , SourceMap < ' a > > > {
119+ fn get_or_init_cache < ' b > (
120+ owner : & ' b CachedSourceOwner ,
121+ cache : & ' b OnceLock < Option < Cow < ' static , SourceMap < ' static > > > > ,
122+ options : & MapOptions ,
123+ ) -> Option < Cow < ' b , SourceMap < ' b > > > {
124+ cache
125+ . get_or_init ( || {
126+ let map = owner. inner . map ( options) ;
127+ // SAFETY: This transmute is safe because:
128+ // 1. BoxSource is an immutable wrapper around Arc<dyn Source>, ensuring the underlying
129+ // data remains stable throughout the CachedSource's lifetime
130+ // 2. The SourceMap references string data that lives in the BoxSource, which is owned
131+ // by the CachedSourceOwner and guaranteed to outlive any cached references
132+ // 3. The self_cell structure ensures that the dependent (cache) cannot outlive the
133+ // owner (BoxSource), maintaining memory safety invariants
134+ // 4. We're extending the lifetime to 'static for caching purposes, but the actual
135+ // data lifetime is managed by the self-referential structure
136+ #[ allow( unsafe_code) ]
137+ unsafe { std:: mem:: transmute :: < _ , Option < Cow < ' static , SourceMap < ' static > > > > ( map) }
138+ } )
139+ . as_ref ( )
140+ . map ( |map| {
141+ Cow :: Borrowed ( map. as_ref ( ) )
142+ } )
143+ }
144+
119145 if options. columns {
120146 self . 0 . with_dependent ( |owner, dependent| {
121- dependent
122- . cached_colomns_map
123- . get_or_init ( || {
124- owner
125- . inner
126- . map ( options)
127- . map ( |m| m. as_ref ( ) . clone ( ) . into_owned ( ) )
128- } )
129- . as_ref ( )
130- . map ( Cow :: Borrowed )
147+ get_or_init_cache ( owner, & dependent. cached_colomns_map , options)
131148 } )
132149 } else {
133150 self . 0 . with_dependent ( |owner, dependent| {
134- dependent
135- . cached_line_only_map
136- . get_or_init ( || {
137- owner
138- . inner
139- . map ( options)
140- . map ( |m| m. as_ref ( ) . clone ( ) . into_owned ( ) )
141- } )
142- . as_ref ( )
143- . map ( Cow :: Borrowed )
151+ get_or_init_cache ( owner, & dependent. cached_line_only_map , options)
144152 } )
145153 }
146154 }
@@ -187,7 +195,7 @@ impl StreamChunks for CachedSource {
187195 on_name,
188196 ) ;
189197 dependent. cached_colomns_map . get_or_init ( || {
190- unsafe { std:: mem:: transmute :: < Option < SourceMap > , Option < SourceMap < ' static > > > ( map) }
198+ unsafe { std:: mem:: transmute :: < Option < SourceMap > , Option < SourceMap < ' static > > > ( map) } . map ( Cow :: Owned )
191199 } ) ;
192200 generated_info
193201 } )
@@ -201,7 +209,7 @@ impl StreamChunks for CachedSource {
201209 on_name,
202210 ) ;
203211 dependent. cached_line_only_map . get_or_init ( || {
204- unsafe { std:: mem:: transmute :: < Option < SourceMap > , Option < SourceMap < ' static > > > ( map) }
212+ unsafe { std:: mem:: transmute :: < Option < SourceMap > , Option < SourceMap < ' static > > > ( map) } . map ( Cow :: Owned )
205213 } ) ;
206214 generated_info
207215 } )
0 commit comments