about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-12-07 00:03:58 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-12-09 22:33:23 +0300
commit9e6725dcfe59665384e51ceb04280fee725d09a3 (patch)
tree258c63c982959b69433e018bfe16a8a1fe8c987b
parent7de9402b77ded0d8ec9e1c554521b2121449ef2b (diff)
resolve: Resolve visibilities on fields with non-builtin attributes
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs18
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.rs26
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.stderr22
3 files changed, 62 insertions, 4 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 04e233c5973..cfe88f67b94 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -192,6 +192,14 @@ impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
+        self.resolve_visibility_speculative(vis, false)
+    }
+
+    fn resolve_visibility_speculative(
+        &mut self,
+        vis: &ast::Visibility,
+        speculative: bool,
+    ) -> ty::Visibility {
         let parent_scope = &self.parent_scope;
         match vis.node {
             ast::VisibilityKind::Public => ty::Visibility::Public,
@@ -239,13 +247,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     &segments,
                     Some(TypeNS),
                     parent_scope,
-                    true,
+                    !speculative,
                     path.span,
                     CrateLint::SimplePath(id),
                 ) {
                     PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
                         let res = module.res().expect("visibility resolved to unnamed block");
-                        self.r.record_partial_res(id, PartialRes::new(res));
+                        if !speculative {
+                            self.r.record_partial_res(id, PartialRes::new(res));
+                        }
                         if module.is_normal() {
                             if res == Res::Err {
                                 ty::Visibility::Public
@@ -747,7 +757,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     // NOTE: The field may be an expansion placeholder, but expansion sets correct
                     // visibilities for unnamed field placeholders specifically, so the constructor
                     // visibility should still be determined correctly.
-                    let field_vis = self.resolve_visibility(&field.vis);
+                    let field_vis = self.resolve_visibility_speculative(&field.vis, true);
                     if ctor_vis.is_at_least(field_vis, &*self.r) {
                         ctor_vis = field_vis;
                     }
@@ -774,7 +784,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
 
                 // Record field names for error reporting.
                 let field_names = vdata.fields().iter().map(|field| {
-                    self.resolve_visibility(&field.vis);
                     respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
                 }).collect();
                 let item_def_id = self.r.definitions.local_def_id(item.id);
@@ -1281,6 +1290,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         if sf.is_placeholder {
             self.visit_invoc(sf.id);
         } else {
+            self.resolve_visibility(&sf.vis);
             visit::walk_struct_field(self, sf);
         }
     }
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.rs b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
new file mode 100644
index 00000000000..36f3feb973d
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
@@ -0,0 +1,26 @@
+// Non-builtin attributes do not mess with field visibility resolution (issue #67006).
+
+mod internal {
+    struct S {
+        #[rustfmt::skip]
+        pub(in crate::internal) field: u8 // OK
+    }
+
+    struct Z(
+        #[rustfmt::skip]
+        pub(in crate::internal) u8 // OK
+    );
+}
+
+struct S {
+    #[rustfmt::skip]
+    pub(in nonexistent) field: u8 //~ ERROR failed to resolve
+}
+
+struct Z(
+    #[rustfmt::skip]
+    pub(in nonexistent) u8 //~ ERROR failed to resolve
+                           //~| ERROR cannot determine resolution for the visibility
+);
+
+fn main() {}
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.stderr b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
new file mode 100644
index 00000000000..8c283e9bcb9
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
@@ -0,0 +1,22 @@
+error[E0578]: cannot determine resolution for the visibility
+  --> $DIR/field-attributes-vis-unresolved.rs:22:12
+   |
+LL |     pub(in nonexistent) u8
+   |            ^^^^^^^^^^^
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+  --> $DIR/field-attributes-vis-unresolved.rs:17:12
+   |
+LL |     pub(in nonexistent) field: u8
+   |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+  --> $DIR/field-attributes-vis-unresolved.rs:22:12
+   |
+LL |     pub(in nonexistent) u8
+   |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0433, E0578.
+For more information about an error, try `rustc --explain E0433`.