@@ -64,7 +64,7 @@ pub mod fatal_error;
6464pub mod profiling;
6565
6666use rustc_data_structures:: stable_hasher:: { Hash128 , Hash64 , HashStable , StableHasher } ;
67- use rustc_data_structures:: sync:: { Lock , Lrc } ;
67+ use rustc_data_structures:: sync:: { FreezeLock , FreezeWriteGuard , Lock , Lrc } ;
6868
6969use std:: borrow:: Cow ;
7070use std:: cmp:: { self , Ordering } ;
@@ -1206,7 +1206,6 @@ pub enum ExternalSourceKind {
12061206 AbsentOk ,
12071207 /// A failed attempt has been made to load the external source.
12081208 AbsentErr ,
1209- Unneeded ,
12101209}
12111210
12121211impl ExternalSource {
@@ -1343,7 +1342,7 @@ pub struct SourceFile {
13431342 pub src_hash : SourceFileHash ,
13441343 /// The external source code (used for external crates, which will have a `None`
13451344 /// value as `self.src`.
1346- pub external_src : Lock < ExternalSource > ,
1345+ pub external_src : FreezeLock < ExternalSource > ,
13471346 /// The start position of this source in the `SourceMap`.
13481347 pub start_pos : BytePos ,
13491348 /// The byte length of this source.
@@ -1368,7 +1367,10 @@ impl Clone for SourceFile {
13681367 name : self . name . clone ( ) ,
13691368 src : self . src . clone ( ) ,
13701369 src_hash : self . src_hash ,
1371- external_src : Lock :: new ( self . external_src . borrow ( ) . clone ( ) ) ,
1370+ external_src : {
1371+ let lock = self . external_src . read ( ) ;
1372+ FreezeLock :: with ( lock. clone ( ) , self . external_src . is_frozen ( ) )
1373+ } ,
13721374 start_pos : self . start_pos ,
13731375 source_len : self . source_len ,
13741376 lines : Lock :: new ( self . lines . borrow ( ) . clone ( ) ) ,
@@ -1488,7 +1490,7 @@ impl<D: Decoder> Decodable<D> for SourceFile {
14881490 src_hash,
14891491 // Unused - the metadata decoder will construct
14901492 // a new SourceFile, filling in `external_src` properly
1491- external_src : Lock :: new ( ExternalSource :: Unneeded ) ,
1493+ external_src : FreezeLock :: frozen ( ExternalSource :: Unneeded ) ,
14921494 lines : Lock :: new ( lines) ,
14931495 multibyte_chars,
14941496 non_narrow_chars,
@@ -1530,7 +1532,7 @@ impl SourceFile {
15301532 name,
15311533 src : Some ( Lrc :: new ( src) ) ,
15321534 src_hash,
1533- external_src : Lock :: new ( ExternalSource :: Unneeded ) ,
1535+ external_src : FreezeLock :: frozen ( ExternalSource :: Unneeded ) ,
15341536 start_pos : BytePos :: from_u32 ( 0 ) ,
15351537 source_len : RelativeBytePos :: from_u32 ( source_len) ,
15361538 lines : Lock :: new ( SourceFileLines :: Lines ( lines) ) ,
@@ -1612,35 +1614,37 @@ impl SourceFile {
16121614 where
16131615 F : FnOnce ( ) -> Option < String > ,
16141616 {
1615- if matches ! (
1616- * self . external_src. borrow( ) ,
1617- ExternalSource :: Foreign { kind: ExternalSourceKind :: AbsentOk , .. }
1618- ) {
1617+ if !self . external_src . is_frozen ( ) {
16191618 let src = get_src ( ) ;
1620- let mut external_src = self . external_src . borrow_mut ( ) ;
1621- // Check that no-one else have provided the source while we were getting it
1622- if let ExternalSource :: Foreign {
1623- kind : src_kind @ ExternalSourceKind :: AbsentOk , ..
1624- } = & mut * external_src
1625- {
1626- if let Some ( mut src) = src {
1627- // The src_hash needs to be computed on the pre-normalized src.
1628- if self . src_hash . matches ( & src) {
1629- normalize_src ( & mut src) ;
1630- * src_kind = ExternalSourceKind :: Present ( Lrc :: new ( src) ) ;
1631- return true ;
1632- }
1619+ let src = src. and_then ( |mut src| {
1620+ // The src_hash needs to be computed on the pre-normalized src.
1621+ self . src_hash . matches ( & src) . then ( || {
1622+ normalize_src ( & mut src) ;
1623+ src
1624+ } )
1625+ } ) ;
1626+
1627+ self . external_src . try_write ( ) . map ( |mut external_src| {
1628+ if let ExternalSource :: Foreign {
1629+ kind : src_kind @ ExternalSourceKind :: AbsentOk ,
1630+ ..
1631+ } = & mut * external_src
1632+ {
1633+ * src_kind = if let Some ( src) = src {
1634+ ExternalSourceKind :: Present ( Lrc :: new ( src) )
1635+ } else {
1636+ ExternalSourceKind :: AbsentErr
1637+ } ;
16331638 } else {
1634- * src_kind = ExternalSourceKind :: AbsentErr ;
1639+ panic ! ( "unexpected state {:?}" , * external_src )
16351640 }
16361641
1637- false
1638- } else {
1639- self . src . is_some ( ) || external_src. get_source ( ) . is_some ( )
1640- }
1641- } else {
1642- self . src . is_some ( ) || self . external_src . borrow ( ) . get_source ( ) . is_some ( )
1642+ // Freeze this so we don't try to load the source again.
1643+ FreezeWriteGuard :: freeze ( external_src)
1644+ } ) ;
16431645 }
1646+
1647+ self . src . is_some ( ) || self . external_src . read ( ) . get_source ( ) . is_some ( )
16441648 }
16451649
16461650 /// Gets a line from the list of pre-computed line-beginnings.
0 commit comments