1
Fork 0

Rollup merge of #85068 - luqmana:78708-xcrate-diag, r=estebank

Fix diagnostic for cross crate private tuple struct constructors

Fixes #78708.

There was already some limited support for certain cross-crate scenarios but that didn't handle a tuple struct rexported from an inner module for example (e.g. the NonZero* types as seen in #85049).

```Rust
➜  cat bug.rs
fn main() {
    let _x = std::num::NonZeroU32(12);
    let n = std::num::NonZeroU32::new(1).unwrap();
    match n {
        std::num::NonZeroU32(i) => {},
    }
}
```

**Before:**
<details>

```Rust
➜  rustc +nightly bug.rs
error[E0423]: expected function, tuple struct or tuple variant, found struct `std::num::NonZeroU32`
   --> bug.rs:2:14
    |
2   |       let _x = std::num::NonZeroU32(12);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `std::num::NonZeroU32 { 0: val }`
    |
   ::: /home/luqman/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/nonzero.rs:148:1
[snip]
error[E0532]: expected tuple struct or tuple variant, found struct `std::num::NonZeroU32`
   --> bug.rs:5:9
    |
5   |           std::num::NonZeroU32(i) => {},
    |           ^^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `std::num::NonZeroU32 { 0 }`
    |
   ::: /home/luqman/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/nonzero.rs:148:1
[snip]

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0423, E0532.
For more information about an error, try `rustc --explain E0423`.
```
</details>

**After:**
<details>

```Rust
➜  /rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustc bug.rs
error[E0423]: cannot initialize a tuple struct which contains private fields
   --> bug.rs:2:14
    |
2   |     let _x = std::num::NonZeroU32(12);
    |              ^^^^^^^^^^^^^^^^^^^^
    |
note: constructor is not visible here due to private fields
   --> /rust/library/core/src/num/nonzero.rs:148:1
[snip]
error[E0532]: cannot match against a tuple struct which contains private fields
 --> bug.rs:5:9
  |
5 |         std::num::NonZeroU32(i) => {},
  |         ^^^^^^^^^^^^^^^^^^^^
  |
note: constructor is not visible here due to private fields
 --> bug.rs:5:30
  |
5 |         std::num::NonZeroU32(i) => {},
  |                              ^ private field

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0423, E0532.
For more information about an error, try `rustc --explain E0423`.
```
</details>

One question is if we should only collect the needed info for the cross-crate case after encountering an error instead of always doing it. Perf run perhaps to gauge the impact.
This commit is contained in:
Guillaume Gomez 2021-05-13 15:54:10 +02:00 committed by GitHub
commit 3db335b934
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 14 deletions

View file

@ -27,7 +27,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, Body, Promoted};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
use rustc_serialize::{opaque, Decodable, Decoder};
use rustc_session::Session;
use rustc_span::hygiene::ExpnDataDecodeMode;
@ -1312,6 +1312,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.collect()
}
fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec<Visibility> {
self.root
.tables
.children
.get(self, id)
.unwrap_or_else(Lazy::empty)
.decode(self)
.map(|field_index| self.get_visibility(field_index))
.collect()
}
fn get_inherent_implementations_for_type(
&self,
tcx: TyCtxt<'tcx>,

View file

@ -8,7 +8,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::stable_map::FxHashMap;
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_middle::hir::exports::Export;
@ -17,7 +17,7 @@ use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_session::utils::NativeLibKind;
use rustc_session::{CrateDisambiguator, Session};
use rustc_span::source_map::{Span, Spanned};
@ -392,6 +392,20 @@ impl CStore {
self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
}
pub fn struct_field_visibilities_untracked(&self, def: DefId) -> Vec<Visibility> {
self.get_crate_data(def.krate).get_struct_field_visibilities(def.index)
}
pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> {
self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| {
(ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index))
})
}
pub fn visibility_untracked(&self, def: DefId) -> Visibility {
self.get_crate_data(def.krate).get_visibility(def.index)
}
pub fn item_children_untracked(
&self,
def_id: DefId,