about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-04-14 17:49:26 +0200
committerGitHub <noreply@github.com>2019-04-14 17:49:26 +0200
commit9506f62a7ab10629f10926f2bad8bd7e78e755a8 (patch)
tree611ef7727c62cd6efd63a47d08d6a7d8b761e802
parent271eb8fc5a420280937bb1745f1e7aee7901ad26 (diff)
parentdbc7042bfe690d55cbcd40e75851efd8af9bb34e (diff)
downloadrust-9506f62a7ab10629f10926f2bad8bd7e78e755a8.tar.gz
rust-9506f62a7ab10629f10926f2bad8bd7e78e755a8.zip
Rollup merge of #59936 - petrochenkov:confict, r=davidtwco
Fix cross-crate visibility of fictive variant constructors

After merging https://github.com/rust-lang/rust/pull/59376 I realized that the code in the decoder wasn't entirely correct - we "decoded" fictive variant constructors with their variant's visibility, which could be public, rather than demoted to `pub(crate)`.

Fictive constructors are not directly usable in expression/patterns, but the effect still can be observed with imports.

r? @davidtwco
-rw-r--r--src/librustc_metadata/decoder.rs13
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs12
2 files changed, 24 insertions, 1 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index f7ea67ef349..5dade8d9438 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -831,7 +831,18 @@ impl<'a, 'tcx> CrateMetadata {
                             let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
                             let ctor_kind = self.get_ctor_kind(child_index);
                             let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
-                            let vis = self.get_visibility(ctor_def_id.index);
+                            let mut vis = self.get_visibility(ctor_def_id.index);
+                            if ctor_def_id == def_id && vis == ty::Visibility::Public {
+                                // For non-exhaustive variants lower the constructor visibility to
+                                // within the crate. We only need this for fictive constructors,
+                                // for other constructors correct visibilities
+                                // were already encoded in metadata.
+                                let attrs = self.get_item_attrs(def_id.index, sess);
+                                if attr::contains_name(&attrs, "non_exhaustive") {
+                                    let crate_def_id = DefId { index: CRATE_DEF_INDEX, ..def_id };
+                                    vis = ty::Visibility::Restricted(crate_def_id);
+                                }
+                            }
                             callback(def::Export { def: ctor_def, ident, vis, span });
                         }
                         _ => {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
new file mode 100644
index 00000000000..62f6e4463f9
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// aux-build:variants.rs
+
+extern crate variants;
+
+const S: u8 = 0;
+
+// OK, `Struct` in value namespace is crate-private, so it's filtered away
+// and there's no conflict with the previously defined `const S`.
+use variants::NonExhaustiveVariants::Struct as S;
+
+fn main() {}