@@ -12,7 +12,7 @@ use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleIm
12
12
use crate :: { Module , ModuleData , ModuleKind , NameBinding , NameBindingKind , Segment , ToNameBinding } ;
13
13
use crate :: { ModuleOrUniformRoot , ParentScope , PerNS , Resolver , ResolverArenas , ExternPreludeEntry } ;
14
14
use crate :: Namespace :: { self , TypeNS , ValueNS , MacroNS } ;
15
- use crate :: { ResolutionError , Determinacy , PathResult , CrateLint } ;
15
+ use crate :: { ResolutionError , VisResolutionError , Determinacy , PathResult , CrateLint } ;
16
16
17
17
use rustc:: bug;
18
18
use rustc:: hir:: def:: { self , * } ;
@@ -32,8 +32,7 @@ use syntax::attr;
32
32
use syntax:: ast:: { self , Block , ForeignItem , ForeignItemKind , Item , ItemKind , NodeId } ;
33
33
use syntax:: ast:: { MetaItemKind , StmtKind , TraitItem , TraitItemKind } ;
34
34
use syntax:: token:: { self , Token } ;
35
- use syntax:: print:: pprust;
36
- use syntax:: { span_err, struct_span_err} ;
35
+ use syntax:: span_err;
37
36
use syntax:: source_map:: { respan, Spanned } ;
38
37
use syntax:: symbol:: { kw, sym} ;
39
38
use syntax:: visit:: { self , Visitor } ;
@@ -192,14 +191,25 @@ impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
192
191
193
192
impl < ' a , ' b > BuildReducedGraphVisitor < ' a , ' b > {
194
193
fn resolve_visibility ( & mut self , vis : & ast:: Visibility ) -> ty:: Visibility {
194
+ self . resolve_visibility_speculative ( vis, false ) . unwrap_or_else ( |err| {
195
+ self . r . report_vis_error ( err) ;
196
+ ty:: Visibility :: Public
197
+ } )
198
+ }
199
+
200
+ fn resolve_visibility_speculative < ' ast > (
201
+ & mut self ,
202
+ vis : & ' ast ast:: Visibility ,
203
+ speculative : bool ,
204
+ ) -> Result < ty:: Visibility , VisResolutionError < ' ast > > {
195
205
let parent_scope = & self . parent_scope ;
196
206
match vis. node {
197
- ast:: VisibilityKind :: Public => ty:: Visibility :: Public ,
207
+ ast:: VisibilityKind :: Public => Ok ( ty:: Visibility :: Public ) ,
198
208
ast:: VisibilityKind :: Crate ( ..) => {
199
- ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) )
209
+ Ok ( ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) ) )
200
210
}
201
211
ast:: VisibilityKind :: Inherited => {
202
- ty:: Visibility :: Restricted ( parent_scope. module . normal_ancestor_id )
212
+ Ok ( ty:: Visibility :: Restricted ( parent_scope. module . normal_ancestor_id ) )
203
213
}
204
214
ast:: VisibilityKind :: Restricted { ref path, id, .. } => {
205
215
// For visibilities we are not ready to provide correct implementation of "uniform
@@ -209,86 +219,67 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
209
219
let ident = path. segments . get ( 0 ) . expect ( "empty path in visibility" ) . ident ;
210
220
let crate_root = if ident. is_path_segment_keyword ( ) {
211
221
None
212
- } else if ident. span . rust_2018 ( ) {
213
- let msg = "relative paths are not supported in visibilities on 2018 edition" ;
214
- self . r . session . struct_span_err ( ident. span , msg)
215
- . span_suggestion (
216
- path. span ,
217
- "try" ,
218
- format ! ( "crate::{}" , pprust:: path_to_string( & path) ) ,
219
- Applicability :: MaybeIncorrect ,
220
- )
221
- . emit ( ) ;
222
- return ty:: Visibility :: Public ;
223
- } else {
224
- let ctxt = ident. span . ctxt ( ) ;
222
+ } else if ident. span . rust_2015 ( ) {
225
223
Some ( Segment :: from_ident ( Ident :: new (
226
- kw:: PathRoot , path. span . shrink_to_lo ( ) . with_ctxt ( ctxt)
224
+ kw:: PathRoot , path. span . shrink_to_lo ( ) . with_ctxt ( ident . span . ctxt ( ) )
227
225
) ) )
226
+ } else {
227
+ return Err ( VisResolutionError :: Relative2018 ( ident. span , path) ) ;
228
228
} ;
229
229
230
230
let segments = crate_root. into_iter ( )
231
231
. chain ( path. segments . iter ( ) . map ( |seg| seg. into ( ) ) ) . collect :: < Vec < _ > > ( ) ;
232
- let expected_found_error = |this : & Self , res : Res | {
233
- let path_str = Segment :: names_to_string ( & segments) ;
234
- struct_span_err ! ( this. r. session, path. span, E0577 ,
235
- "expected module, found {} `{}`" , res. descr( ) , path_str)
236
- . span_label ( path. span , "not a module" ) . emit ( ) ;
237
- } ;
232
+ let expected_found_error = |res| Err ( VisResolutionError :: ExpectedFound (
233
+ path. span , Segment :: names_to_string ( & segments) , res
234
+ ) ) ;
238
235
match self . r . resolve_path (
239
236
& segments,
240
237
Some ( TypeNS ) ,
241
238
parent_scope,
242
- true ,
239
+ !speculative ,
243
240
path. span ,
244
241
CrateLint :: SimplePath ( id) ,
245
242
) {
246
243
PathResult :: Module ( ModuleOrUniformRoot :: Module ( module) ) => {
247
244
let res = module. res ( ) . expect ( "visibility resolved to unnamed block" ) ;
248
- self . r . record_partial_res ( id, PartialRes :: new ( res) ) ;
245
+ if !speculative {
246
+ self . r . record_partial_res ( id, PartialRes :: new ( res) ) ;
247
+ }
249
248
if module. is_normal ( ) {
250
249
if res == Res :: Err {
251
- ty:: Visibility :: Public
250
+ Ok ( ty:: Visibility :: Public )
252
251
} else {
253
252
let vis = ty:: Visibility :: Restricted ( res. def_id ( ) ) ;
254
253
if self . r . is_accessible_from ( vis, parent_scope. module ) {
255
- vis
254
+ Ok ( vis)
256
255
} else {
257
- struct_span_err ! ( self . r. session, path. span, E0742 ,
258
- "visibilities can only be restricted to ancestor modules" )
259
- . emit ( ) ;
260
- ty:: Visibility :: Public
256
+ Err ( VisResolutionError :: AncestorOnly ( path. span ) )
261
257
}
262
258
}
263
259
} else {
264
- expected_found_error ( self , res) ;
265
- ty:: Visibility :: Public
260
+ expected_found_error ( res)
266
261
}
267
262
}
268
- PathResult :: Module ( ..) => {
269
- self . r . session . span_err ( path. span , "visibility must resolve to a module" ) ;
270
- ty:: Visibility :: Public
271
- }
272
- PathResult :: NonModule ( partial_res) => {
273
- expected_found_error ( self , partial_res. base_res ( ) ) ;
274
- ty:: Visibility :: Public
275
- }
276
- PathResult :: Failed { span, label, suggestion, .. } => {
277
- self . r . report_error (
278
- span, ResolutionError :: FailedToResolve { label, suggestion }
279
- ) ;
280
- ty:: Visibility :: Public
281
- }
282
- PathResult :: Indeterminate => {
283
- span_err ! ( self . r. session, path. span, E0578 ,
284
- "cannot determine resolution for the visibility" ) ;
285
- ty:: Visibility :: Public
286
- }
263
+ PathResult :: Module ( ..) =>
264
+ Err ( VisResolutionError :: ModuleOnly ( path. span ) ) ,
265
+ PathResult :: NonModule ( partial_res) =>
266
+ expected_found_error ( partial_res. base_res ( ) ) ,
267
+ PathResult :: Failed { span, label, suggestion, .. } =>
268
+ Err ( VisResolutionError :: FailedToResolve ( span, label, suggestion) ) ,
269
+ PathResult :: Indeterminate =>
270
+ Err ( VisResolutionError :: Indeterminate ( path. span ) ) ,
287
271
}
288
272
}
289
273
}
290
274
}
291
275
276
+ fn insert_field_names_local ( & mut self , def_id : DefId , vdata : & ast:: VariantData ) {
277
+ let field_names = vdata. fields ( ) . iter ( ) . map ( |field| {
278
+ respan ( field. span , field. ident . map_or ( kw:: Invalid , |ident| ident. name ) )
279
+ } ) . collect ( ) ;
280
+ self . insert_field_names ( def_id, field_names) ;
281
+ }
282
+
292
283
fn insert_field_names ( & mut self , def_id : DefId , field_names : Vec < Spanned < Name > > ) {
293
284
if !field_names. is_empty ( ) {
294
285
self . r . field_names . insert ( def_id, field_names) ;
@@ -726,59 +717,52 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
726
717
}
727
718
728
719
// These items live in both the type and value namespaces.
729
- ItemKind :: Struct ( ref struct_def , _) => {
720
+ ItemKind :: Struct ( ref vdata , _) => {
730
721
// Define a name in the type namespace.
731
722
let def_id = self . r . definitions . local_def_id ( item. id ) ;
732
723
let res = Res :: Def ( DefKind :: Struct , def_id) ;
733
724
self . r . define ( parent, ident, TypeNS , ( res, vis, sp, expansion) ) ;
734
725
735
- let mut ctor_vis = vis;
736
-
737
- let has_non_exhaustive = attr:: contains_name ( & item. attrs , sym:: non_exhaustive) ;
738
-
739
- // If the structure is marked as non_exhaustive then lower the visibility
740
- // to within the crate.
741
- if has_non_exhaustive && vis == ty:: Visibility :: Public {
742
- ctor_vis = ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) ) ;
743
- }
744
-
745
726
// Record field names for error reporting.
746
- let field_names = struct_def. fields ( ) . iter ( ) . map ( |field| {
747
- // NOTE: The field may be an expansion placeholder, but expansion sets correct
748
- // visibilities for unnamed field placeholders specifically, so the constructor
749
- // visibility should still be determined correctly.
750
- let field_vis = self . resolve_visibility ( & field. vis ) ;
751
- if ctor_vis. is_at_least ( field_vis, & * self . r ) {
752
- ctor_vis = field_vis;
753
- }
754
- respan ( field. span , field. ident . map_or ( kw:: Invalid , |ident| ident. name ) )
755
- } ) . collect ( ) ;
756
- let item_def_id = self . r . definitions . local_def_id ( item. id ) ;
757
- self . insert_field_names ( item_def_id, field_names) ;
727
+ self . insert_field_names_local ( def_id, vdata) ;
758
728
759
729
// If this is a tuple or unit struct, define a name
760
730
// in the value namespace as well.
761
- if let Some ( ctor_node_id) = struct_def. ctor_id ( ) {
731
+ if let Some ( ctor_node_id) = vdata. ctor_id ( ) {
732
+ let mut ctor_vis = vis;
733
+ // If the structure is marked as non_exhaustive then lower the visibility
734
+ // to within the crate.
735
+ if vis == ty:: Visibility :: Public &&
736
+ attr:: contains_name ( & item. attrs , sym:: non_exhaustive) {
737
+ ctor_vis = ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) ) ;
738
+ }
739
+ for field in vdata. fields ( ) {
740
+ // NOTE: The field may be an expansion placeholder, but expansion sets
741
+ // correct visibilities for unnamed field placeholders specifically, so the
742
+ // constructor visibility should still be determined correctly.
743
+ if let Ok ( field_vis) =
744
+ self . resolve_visibility_speculative ( & field. vis , true ) {
745
+ if ctor_vis. is_at_least ( field_vis, & * self . r ) {
746
+ ctor_vis = field_vis;
747
+ }
748
+ }
749
+ }
762
750
let ctor_res = Res :: Def (
763
- DefKind :: Ctor ( CtorOf :: Struct , CtorKind :: from_ast ( struct_def ) ) ,
751
+ DefKind :: Ctor ( CtorOf :: Struct , CtorKind :: from_ast ( vdata ) ) ,
764
752
self . r . definitions . local_def_id ( ctor_node_id) ,
765
753
) ;
766
754
self . r . define ( parent, ident, ValueNS , ( ctor_res, ctor_vis, sp, expansion) ) ;
767
- self . r . struct_constructors . insert ( res . def_id ( ) , ( ctor_res, ctor_vis) ) ;
755
+ self . r . struct_constructors . insert ( def_id, ( ctor_res, ctor_vis) ) ;
768
756
}
769
757
}
770
758
771
759
ItemKind :: Union ( ref vdata, _) => {
772
- let res = Res :: Def ( DefKind :: Union , self . r . definitions . local_def_id ( item. id ) ) ;
760
+ let def_id = self . r . definitions . local_def_id ( item. id ) ;
761
+ let res = Res :: Def ( DefKind :: Union , def_id) ;
773
762
self . r . define ( parent, ident, TypeNS , ( res, vis, sp, expansion) ) ;
774
763
775
764
// Record field names for error reporting.
776
- let field_names = vdata. fields ( ) . iter ( ) . map ( |field| {
777
- self . resolve_visibility ( & field. vis ) ;
778
- respan ( field. span , field. ident . map_or ( kw:: Invalid , |ident| ident. name ) )
779
- } ) . collect ( ) ;
780
- let item_def_id = self . r . definitions . local_def_id ( item. id ) ;
781
- self . insert_field_names ( item_def_id, field_names) ;
765
+ self . insert_field_names_local ( def_id, vdata) ;
782
766
}
783
767
784
768
ItemKind :: Impl ( .., ref impl_items) => {
@@ -1281,6 +1265,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
1281
1265
if sf. is_placeholder {
1282
1266
self . visit_invoc ( sf. id ) ;
1283
1267
} else {
1268
+ self . resolve_visibility ( & sf. vis ) ;
1284
1269
visit:: walk_struct_field ( self , sf) ;
1285
1270
}
1286
1271
}
0 commit comments