@@ -32,7 +32,7 @@ use std::sync::Arc;
32
32
use diagnostics:: { ImportSuggestion , LabelSuggestion , Suggestion } ;
33
33
use effective_visibilities:: EffectiveVisibilitiesVisitor ;
34
34
use errors:: { ParamKindInEnumDiscriminant , ParamKindInNonTrivialAnonConst } ;
35
- use imports:: { Import , ImportData , ImportKind , NameResolution } ;
35
+ use imports:: { Import , ImportData , ImportKind , NameResolution , PendingBinding } ;
36
36
use late:: {
37
37
ForwardGenericParamBanReason , HasGenericParams , PathSource , PatternSource ,
38
38
UnnecessaryQualification ,
@@ -1025,18 +1025,26 @@ impl<'ra> NameBindingData<'ra> {
1025
1025
}
1026
1026
}
1027
1027
1028
- #[ derive( Default , Clone ) ]
1029
1028
struct ExternPreludeEntry < ' ra > {
1030
1029
/// Binding from an `extern crate` item.
1031
- item_binding : Option < NameBinding < ' ra > > ,
1030
+ /// The boolean flag is true is `item_binding` is non-redundant, happens either when
1031
+ /// `flag_binding` is `None`, or when `extern crate` introducing `item_binding` used renaming.
1032
+ item_binding : Option < ( NameBinding < ' ra > , /* introduced by item */ bool ) > ,
1032
1033
/// Binding from an `--extern` flag, lazily populated on first use.
1033
- flag_binding : Cell < Option < NameBinding < ' ra > > > ,
1034
- /// There was no `--extern` flag introducing this name,
1035
- /// `flag_binding` doesn't need to be populated.
1036
- only_item : bool ,
1037
- /// `item_binding` is non-redundant, happens either when `only_item` is true,
1038
- /// or when `extern crate` introducing `item_binding` used renaming.
1039
- introduced_by_item : bool ,
1034
+ flag_binding : Option < Cell < PendingBinding < ' ra > > > ,
1035
+ }
1036
+
1037
+ impl ExternPreludeEntry < ' _ > {
1038
+ fn introduced_by_item ( & self ) -> bool {
1039
+ matches ! ( self . item_binding, Some ( ( _, true ) ) )
1040
+ }
1041
+
1042
+ fn flag ( ) -> Self {
1043
+ ExternPreludeEntry {
1044
+ item_binding : None ,
1045
+ flag_binding : Some ( Cell :: new ( PendingBinding :: Pending ) ) ,
1046
+ }
1047
+ }
1040
1048
}
1041
1049
1042
1050
struct DeriveData {
@@ -1528,19 +1536,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1528
1536
&& let name = Symbol :: intern ( name)
1529
1537
&& name. can_be_raw ( )
1530
1538
{
1531
- Some ( ( Macros20NormalizedIdent :: with_dummy_span ( name) , Default :: default ( ) ) )
1539
+ let ident = Macros20NormalizedIdent :: with_dummy_span ( name) ;
1540
+ Some ( ( ident, ExternPreludeEntry :: flag ( ) ) )
1532
1541
} else {
1533
1542
None
1534
1543
}
1535
1544
} )
1536
1545
. collect ( ) ;
1537
1546
1538
1547
if !attr:: contains_name ( attrs, sym:: no_core) {
1539
- extern_prelude
1540
- . insert ( Macros20NormalizedIdent :: with_dummy_span ( sym :: core ) , Default :: default ( ) ) ;
1548
+ let ident = Macros20NormalizedIdent :: with_dummy_span ( sym :: core ) ;
1549
+ extern_prelude . insert ( ident , ExternPreludeEntry :: flag ( ) ) ;
1541
1550
if !attr:: contains_name ( attrs, sym:: no_std) {
1542
- extern_prelude
1543
- . insert ( Macros20NormalizedIdent :: with_dummy_span ( sym :: std ) , Default :: default ( ) ) ;
1551
+ let ident = Macros20NormalizedIdent :: with_dummy_span ( sym :: std ) ;
1552
+ extern_prelude . insert ( ident , ExternPreludeEntry :: flag ( ) ) ;
1544
1553
}
1545
1554
}
1546
1555
@@ -2062,12 +2071,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2062
2071
}
2063
2072
// Avoid marking `extern crate` items that refer to a name from extern prelude,
2064
2073
// but not introduce it, as used if they are accessed from lexical scope.
2065
- if used == Used :: Scope {
2066
- if let Some ( entry) = self . extern_prelude . get ( & Macros20NormalizedIdent :: new ( ident) ) {
2067
- if !entry. introduced_by_item && entry. item_binding == Some ( used_binding) {
2068
- return ;
2069
- }
2070
- }
2074
+ if used == Used :: Scope
2075
+ && let Some ( entry) = self . extern_prelude . get ( & Macros20NormalizedIdent :: new ( ident) )
2076
+ && entry. item_binding == Some ( ( used_binding, false ) )
2077
+ {
2078
+ return ;
2071
2079
}
2072
2080
let old_used = self . import_use_map . entry ( import) . or_insert ( used) ;
2073
2081
if * old_used < used {
@@ -2226,7 +2234,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2226
2234
finalize : bool ,
2227
2235
) -> Option < NameBinding < ' ra > > {
2228
2236
let entry = self . extern_prelude . get ( & Macros20NormalizedIdent :: new ( ident) ) ;
2229
- entry. and_then ( |entry| entry. item_binding ) . map ( |binding| {
2237
+ entry. and_then ( |entry| entry. item_binding ) . map ( |( binding, _ ) | {
2230
2238
if finalize {
2231
2239
self . get_mut ( ) . record_use ( ident, binding, Used :: Scope ) ;
2232
2240
}
@@ -2236,31 +2244,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2236
2244
2237
2245
fn extern_prelude_get_flag ( & self , ident : Ident , finalize : bool ) -> Option < NameBinding < ' ra > > {
2238
2246
let entry = self . extern_prelude . get ( & Macros20NormalizedIdent :: new ( ident) ) ;
2239
- entry. and_then ( |entry| match entry. flag_binding . get ( ) {
2240
- Some ( binding) => {
2241
- if finalize {
2242
- self . cstore_mut ( ) . process_path_extern ( self . tcx , ident. name , ident. span ) ;
2247
+ entry. and_then ( |entry| entry. flag_binding . as_ref ( ) ) . and_then ( |flag_binding| {
2248
+ let binding = match flag_binding. get ( ) {
2249
+ PendingBinding :: Ready ( binding) => {
2250
+ if finalize {
2251
+ self . cstore_mut ( ) . process_path_extern ( self . tcx , ident. name , ident. span ) ;
2252
+ }
2253
+ binding
2243
2254
}
2244
- Some ( binding)
2245
- }
2246
- None if entry. only_item => None ,
2247
- None => {
2248
- let crate_id = if finalize {
2249
- self . cstore_mut ( ) . process_path_extern ( self . tcx , ident. name , ident. span )
2250
- } else {
2251
- self . cstore_mut ( ) . maybe_process_path_extern ( self . tcx , ident. name )
2252
- } ;
2253
- match crate_id {
2254
- Some ( crate_id) => {
2255
+ PendingBinding :: Pending => {
2256
+ let crate_id = if finalize {
2257
+ self . cstore_mut ( ) . process_path_extern ( self . tcx , ident. name , ident. span )
2258
+ } else {
2259
+ self . cstore_mut ( ) . maybe_process_path_extern ( self . tcx , ident. name )
2260
+ } ;
2261
+ crate_id. map ( |crate_id| {
2255
2262
let res = Res :: Def ( DefKind :: Mod , crate_id. as_def_id ( ) ) ;
2256
- let binding =
2257
- self . arenas . new_pub_res_binding ( res, DUMMY_SP , LocalExpnId :: ROOT ) ;
2258
- entry. flag_binding . set ( Some ( binding) ) ;
2259
- Some ( binding)
2260
- }
2261
- None => finalize. then_some ( self . dummy_binding ) ,
2263
+ self . arenas . new_pub_res_binding ( res, DUMMY_SP , LocalExpnId :: ROOT )
2264
+ } )
2262
2265
}
2263
- }
2266
+ } ;
2267
+ flag_binding. set ( PendingBinding :: Ready ( binding) ) ;
2268
+ binding. or_else ( || finalize. then_some ( self . dummy_binding ) )
2264
2269
} )
2265
2270
}
2266
2271
0 commit comments