Privacy: tweak macros + more tests
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 44f14fa..c2b7c6c 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -278,9 +278,8 @@ fn update_reachability_from_macro(
         // all the parents in the loop below are also guaranteed to be modules.
         let mut module_def_id = macro_module_def_id;
         loop {
-            let changed_reachability =
-                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
-            if changed_reachability || module_def_id == CRATE_DEF_ID {
+            self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
+            if module_def_id == CRATE_DEF_ID {
                 break;
             }
             module_def_id = self.r.tcx.local_parent(module_def_id);
@@ -294,7 +293,7 @@ fn update_macro_reachable(
         module_def_id: LocalDefId,
         defining_mod: LocalDefId,
         macro_ev: EffectiveVisibility,
-    ) -> bool {
+    ) {
         if self.macro_reachable.insert((module_def_id, defining_mod)) {
             let module = self.r.expect_module(module_def_id.to_def_id());
             for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
@@ -311,9 +310,6 @@ fn update_macro_reachable(
                     self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
                 }
             }
-            true
-        } else {
-            false
         }
     }
 
diff --git a/tests/ui/definition-reachable/auxiliary/field-access-macro.rs b/tests/ui/definition-reachable/auxiliary/field-access-macro.rs
new file mode 100644
index 0000000..92a1717
--- /dev/null
+++ b/tests/ui/definition-reachable/auxiliary/field-access-macro.rs
@@ -0,0 +1,16 @@
+#![feature(decl_macro)]
+
+mod n {
+    pub struct Struct(i32);
+    pub fn get_struct() -> Struct { Struct(0) }
+
+    pub macro allow_field_access($x:expr) {
+        &mut $x.0
+    }
+}
+
+pub use n::{allow_field_access, get_struct};
+
+pub macro deny_field_access($x:expr) {
+    &mut $x.0
+}
diff --git a/tests/ui/definition-reachable/auxiliary/transitive-macro.rs b/tests/ui/definition-reachable/auxiliary/transitive-macro.rs
new file mode 100644
index 0000000..993250b
--- /dev/null
+++ b/tests/ui/definition-reachable/auxiliary/transitive-macro.rs
@@ -0,0 +1,15 @@
+#![feature(decl_macro)]
+
+mod mod1 {
+    mod mod2 {
+        pub fn foo() {}
+    }
+
+    pub(crate) macro m1() {
+        mod2::foo()
+    }
+}
+
+pub macro m() {
+    mod1::m1!()
+}
diff --git a/tests/ui/definition-reachable/field-access.rs b/tests/ui/definition-reachable/field-access.rs
new file mode 100644
index 0000000..b2776eb
--- /dev/null
+++ b/tests/ui/definition-reachable/field-access.rs
@@ -0,0 +1,11 @@
+//@ aux-build:field-access-macro.rs
+
+extern crate field_access_macro;
+
+fn main() {
+    let mut s = field_access_macro::get_struct();
+
+    let try_field_access = field_access_macro::allow_field_access!(s); // Ok
+    let try_field_access = field_access_macro::deny_field_access!(s);
+    //~^ ERROR field `0` of struct `field_access_macro::n::Struct` is private
+}
diff --git a/tests/ui/definition-reachable/field-access.stderr b/tests/ui/definition-reachable/field-access.stderr
new file mode 100644
index 0000000..b422976
--- /dev/null
+++ b/tests/ui/definition-reachable/field-access.stderr
@@ -0,0 +1,11 @@
+error[E0616]: field `0` of struct `field_access_macro::n::Struct` is private
+  --> $DIR/field-access.rs:9:28
+   |
+LL |     let try_field_access = field_access_macro::deny_field_access!(s);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field
+   |
+   = note: this error originates in the macro `field_access_macro::deny_field_access` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/tests/ui/definition-reachable/field-method.rs b/tests/ui/definition-reachable/field-method.rs
index d15b982..94f3520 100644
--- a/tests/ui/definition-reachable/field-method.rs
+++ b/tests/ui/definition-reachable/field-method.rs
@@ -1,11 +1,11 @@
-// Check that functions accessible through a field visible to a macro are
+// Check that functions visible to macros through paths with >2 segments are
 // considered reachable
 
-//@ aux-build:nested-fn-macro.rs
+//@ aux-build:field-method-macro.rs
 //@ run-pass
 
-extern crate nested_fn_macro;
+extern crate field_method_macro;
 
 fn main() {
-    assert_eq!(nested_fn_macro::m!(), 12);
+    assert_eq!(field_method_macro::m!(), 33);
 }
diff --git a/tests/ui/definition-reachable/nested-fn.rs b/tests/ui/definition-reachable/nested-fn.rs
index 94f3520..d15b982 100644
--- a/tests/ui/definition-reachable/nested-fn.rs
+++ b/tests/ui/definition-reachable/nested-fn.rs
@@ -1,11 +1,11 @@
-// Check that functions visible to macros through paths with >2 segments are
+// Check that functions accessible through a field visible to a macro are
 // considered reachable
 
-//@ aux-build:field-method-macro.rs
+//@ aux-build:nested-fn-macro.rs
 //@ run-pass
 
-extern crate field_method_macro;
+extern crate nested_fn_macro;
 
 fn main() {
-    assert_eq!(field_method_macro::m!(), 33);
+    assert_eq!(nested_fn_macro::m!(), 12);
 }
diff --git a/tests/ui/definition-reachable/transitive.rs b/tests/ui/definition-reachable/transitive.rs
new file mode 100644
index 0000000..e5963de
--- /dev/null
+++ b/tests/ui/definition-reachable/transitive.rs
@@ -0,0 +1,10 @@
+//@ aux-build:transitive-macro.rs
+//@ build-fail
+
+extern crate transitive_macro;
+
+fn main() {
+    transitive_macro::m!();
+}
+
+//~? ERROR missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro`
diff --git a/tests/ui/definition-reachable/transitive.stderr b/tests/ui/definition-reachable/transitive.stderr
new file mode 100644
index 0000000..8449983
--- /dev/null
+++ b/tests/ui/definition-reachable/transitive.stderr
@@ -0,0 +1,10 @@
+error: missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro`
+   |
+note: missing optimized MIR for this item (was the crate `transitive_macro` compiled with `--emit=metadata`?)
+  --> $DIR/auxiliary/transitive-macro.rs:5:9
+   |
+LL |         pub fn foo() {}
+   |         ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/privacy/effective-visibilities-macro-2.rs b/tests/ui/privacy/effective-visibilities-macro-2.rs
new file mode 100644
index 0000000..0af3c92
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro-2.rs
@@ -0,0 +1,26 @@
+// Make sure that `Placeholder` will be marked as reachable without `use crate::ty` like in
+// `effective-visibility-macro.rs` test.
+
+#![feature(rustc_attrs, decl_macro)]
+
+pub mod ty {
+    pub mod print {
+        mod pretty {
+            #[rustc_effective_visibility]
+            pub macro with_no_queries() {}
+            //~^ ERROR  Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+        }
+
+        pub use self::pretty::with_no_queries;
+    }
+
+    #[rustc_effective_visibility]
+    mod sty {
+    //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+        #[rustc_effective_visibility]
+        pub type Placeholder = ();
+        //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/effective-visibilities-macro-2.stderr b/tests/ui/privacy/effective-visibilities-macro-2.stderr
new file mode 100644
index 0000000..bd643e2
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro-2.stderr
@@ -0,0 +1,20 @@
+error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro-2.rs:10:13
+   |
+LL |             pub macro with_no_queries() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+  --> $DIR/effective-visibilities-macro-2.rs:18:5
+   |
+LL |     mod sty {
+   |     ^^^^^^^
+
+error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro-2.rs:21:9
+   |
+LL |         pub type Placeholder = ();
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/privacy/effective-visibilities-macro.rs b/tests/ui/privacy/effective-visibilities-macro.rs
new file mode 100644
index 0000000..f5857fd
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro.rs
@@ -0,0 +1,25 @@
+#![feature(rustc_attrs, decl_macro)]
+
+pub mod ty {
+    pub mod print {
+        mod pretty {
+            #[rustc_effective_visibility]
+            pub macro with_no_queries() {}
+            //~^ ERROR  Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+        }
+
+        pub use self::pretty::with_no_queries;
+        // Start visiting outer modules during macro-reachable phase.
+        use crate::ty;
+    }
+
+    #[rustc_effective_visibility]
+    mod sty {
+    //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+        #[rustc_effective_visibility]
+        pub type Placeholder = ();
+        //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/effective-visibilities-macro.stderr b/tests/ui/privacy/effective-visibilities-macro.stderr
new file mode 100644
index 0000000..d08107e
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro.stderr
@@ -0,0 +1,20 @@
+error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro.rs:7:13
+   |
+LL |             pub macro with_no_queries() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+  --> $DIR/effective-visibilities-macro.rs:17:5
+   |
+LL |     mod sty {
+   |     ^^^^^^^
+
+error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro.rs:20:9
+   |
+LL |         pub type Placeholder = ();
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+