@@ -124,8 +124,10 @@ impl ImportDirective {
124
124
#[ derive( Clone , Default ) ]
125
125
/// Records information about the resolution of a name in a module.
126
126
pub struct NameResolution < ' a > {
127
- /// The number of unresolved single imports that could define the name.
128
- outstanding_references : usize ,
127
+ /// The number of unresolved single imports of any visibility that could define the name.
128
+ outstanding_references : u32 ,
129
+ /// The number of unresolved `pub` single imports that could define the name.
130
+ pub_outstanding_references : u32 ,
129
131
/// The least shadowable known binding for this name, or None if there are no known bindings.
130
132
pub binding : Option < & ' a NameBinding < ' a > > ,
131
133
duplicate_globs : Vec < & ' a NameBinding < ' a > > ,
@@ -151,9 +153,12 @@ impl<'a> NameResolution<'a> {
151
153
}
152
154
153
155
// Returns the resolution of the name assuming no more globs will define it.
154
- fn result ( & self ) -> ResolveResult < & ' a NameBinding < ' a > > {
156
+ fn result ( & self , allow_private_imports : bool ) -> ResolveResult < & ' a NameBinding < ' a > > {
155
157
match self . binding {
156
158
Some ( binding) if !binding. defined_with ( DefModifiers :: GLOB_IMPORTED ) => Success ( binding) ,
159
+ // If we don't allow private imports and no public imports can define the name, fail.
160
+ _ if !allow_private_imports && self . pub_outstanding_references == 0 &&
161
+ !self . binding . map ( NameBinding :: is_public) . unwrap_or ( false ) => Failed ( None ) ,
157
162
_ if self . outstanding_references > 0 => Indeterminate ,
158
163
Some ( binding) => Success ( binding) ,
159
164
None => Failed ( None ) ,
@@ -162,8 +167,9 @@ impl<'a> NameResolution<'a> {
162
167
163
168
// Returns Some(the resolution of the name), or None if the resolution depends
164
169
// on whether more globs can define the name.
165
- fn try_result ( & self ) -> Option < ResolveResult < & ' a NameBinding < ' a > > > {
166
- match self . result ( ) {
170
+ fn try_result ( & self , allow_private_imports : bool )
171
+ -> Option < ResolveResult < & ' a NameBinding < ' a > > > {
172
+ match self . result ( allow_private_imports) {
167
173
Success ( binding) if binding. defined_with ( DefModifiers :: PRELUDE ) => None ,
168
174
Failed ( _) => None ,
169
175
result @ _ => Some ( result) ,
@@ -200,7 +206,7 @@ impl<'a> ::ModuleS<'a> {
200
206
} ;
201
207
202
208
let resolution = resolutions. get ( & ( name, ns) ) . cloned ( ) . unwrap_or_default ( ) ;
203
- if let Some ( result) = resolution. try_result ( ) {
209
+ if let Some ( result) = resolution. try_result ( allow_private_imports ) {
204
210
// If the resolution doesn't depend on glob definability, check privacy and return.
205
211
return result. and_then ( |binding| {
206
212
let allowed = allow_private_imports || !binding. is_import ( ) || binding. is_public ( ) ;
@@ -234,7 +240,7 @@ impl<'a> ::ModuleS<'a> {
234
240
}
235
241
}
236
242
237
- resolution. result ( )
243
+ resolution. result ( true )
238
244
}
239
245
240
246
// Define the name or return the existing binding if there is a collision.
@@ -246,15 +252,26 @@ impl<'a> ::ModuleS<'a> {
246
252
} )
247
253
}
248
254
249
- pub fn increment_outstanding_references_for ( & self , name : Name , ns : Namespace ) {
255
+ pub fn increment_outstanding_references_for ( & self , name : Name , ns : Namespace , is_public : bool ) {
250
256
let mut resolutions = self . resolutions . borrow_mut ( ) ;
251
- resolutions. entry ( ( name, ns) ) . or_insert_with ( Default :: default) . outstanding_references += 1 ;
257
+ let resolution = resolutions. entry ( ( name, ns) ) . or_insert_with ( Default :: default) ;
258
+ resolution. outstanding_references += 1 ;
259
+ if is_public {
260
+ resolution. pub_outstanding_references += 1 ;
261
+ }
252
262
}
253
263
254
- fn decrement_outstanding_references_for ( & self , name : Name , ns : Namespace ) {
255
- self . update_resolution ( name, ns, |resolution| match resolution. outstanding_references {
256
- 0 => panic ! ( "No more outstanding references!" ) ,
257
- ref mut outstanding_references => * outstanding_references -= 1 ,
264
+ fn decrement_outstanding_references_for ( & self , name : Name , ns : Namespace , is_public : bool ) {
265
+ let decrement_references = |count : & mut _ | {
266
+ assert ! ( * count > 0 ) ;
267
+ * count -= 1 ;
268
+ } ;
269
+
270
+ self . update_resolution ( name, ns, |resolution| {
271
+ decrement_references ( & mut resolution. outstanding_references ) ;
272
+ if is_public {
273
+ decrement_references ( & mut resolution. pub_outstanding_references ) ;
274
+ }
258
275
} )
259
276
}
260
277
@@ -265,11 +282,11 @@ impl<'a> ::ModuleS<'a> {
265
282
{
266
283
let mut resolutions = self . resolutions . borrow_mut ( ) ;
267
284
let resolution = resolutions. entry ( ( name, ns) ) . or_insert_with ( Default :: default) ;
268
- let was_success = resolution. try_result ( ) . and_then ( ResolveResult :: success) . is_some ( ) ;
285
+ let was_success = resolution. try_result ( false ) . and_then ( ResolveResult :: success) . is_some ( ) ;
269
286
270
287
let t = update ( resolution) ;
271
288
if !was_success {
272
- if let Some ( Success ( binding) ) = resolution. try_result ( ) {
289
+ if let Some ( Success ( binding) ) = resolution. try_result ( false ) {
273
290
self . define_in_glob_importers ( name, ns, binding) ;
274
291
}
275
292
}
@@ -460,10 +477,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
460
477
let mut resolve_in_ns = |ns, determined : bool | {
461
478
// Temporarily count the directive as determined so that the resolution fails
462
479
// (as opposed to being indeterminate) when it can only be defined by the directive.
463
- if !determined { module_. decrement_outstanding_references_for ( target, ns) }
480
+ if !determined {
481
+ module_. decrement_outstanding_references_for ( target, ns, directive. is_public )
482
+ }
464
483
let result =
465
484
self . resolver . resolve_name_in_module ( target_module, source, ns, false , true ) ;
466
- if !determined { module_. increment_outstanding_references_for ( target, ns) }
485
+ if !determined {
486
+ module_. increment_outstanding_references_for ( target, ns, directive. is_public )
487
+ }
467
488
result
468
489
} ;
469
490
( resolve_in_ns ( ValueNS , value_determined. get ( ) ) ,
@@ -494,7 +515,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
494
515
self . report_conflict ( target, ns, & directive. import ( binding, None ) , old_binding) ;
495
516
}
496
517
}
497
- module_. decrement_outstanding_references_for ( target, ns) ;
518
+ module_. decrement_outstanding_references_for ( target, ns, directive . is_public ) ;
498
519
}
499
520
500
521
match ( & value_result, & type_result) {
@@ -601,7 +622,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
601
622
}
602
623
603
624
for ( & ( name, ns) , resolution) in target_module. resolutions . borrow ( ) . iter ( ) {
604
- if let Some ( Success ( binding) ) = resolution. try_result ( ) {
625
+ if let Some ( Success ( binding) ) = resolution. try_result ( false ) {
605
626
if binding. defined_with ( DefModifiers :: IMPORTABLE | DefModifiers :: PUBLIC ) {
606
627
let _ = module_. try_define_child ( name, ns, directive. import ( binding, None ) ) ;
607
628
}
0 commit comments