未验证 提交 f32d62e5 编写于 作者: M Mazdak Farrokhzad 提交者: GitHub

Rollup merge of #58679 - Zoxc:passes-refactor, r=michaelwoerister

Refactor passes and pass execution to be more parallel

For `syntex_syntax` (with 16 threads and 8 cores):
- Cuts `misc checking 1` from `0.096s` to `0.08325s`.
- Cuts `misc checking 2` from `0.3575s` to `0.2545s`.
- Cuts `misc checking 3` from `0.34625s` to `0.21375s`.
- Cuts `wf checking` from `0.3085s` to `0.05025s`.

Reduces overall execution time for `syntex_syntax` (with 8 threads and cores) from `4.92s` to `4.34s`.

Subsumes https://github.com/rust-lang/rust/pull/58494
Blocked on https://github.com/rust-lang/rust/pull/58250

r? @michaelwoerister
...@@ -456,6 +456,7 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode { ...@@ -456,6 +456,7 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
[eval_always] CoherenceInherentImplOverlapCheck, [eval_always] CoherenceInherentImplOverlapCheck,
[] CoherenceCheckTrait(DefId), [] CoherenceCheckTrait(DefId),
[eval_always] PrivacyAccessLevels(CrateNum), [eval_always] PrivacyAccessLevels(CrateNum),
[eval_always] CheckPrivateInPublic(CrateNum),
[eval_always] Analysis(CrateNum), [eval_always] Analysis(CrateNum),
// Represents the MIR for a fn; also used as the task node for // Represents the MIR for a fn; also used as the task node for
......
...@@ -344,12 +344,6 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) { ...@@ -344,12 +344,6 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
} }
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
}
}
fn is_c_like_enum(item: &hir::Item) -> bool { fn is_c_like_enum(item: &hir::Item) -> bool {
if let hir::ItemKind::Enum(ref def, _) = item.node { if let hir::ItemKind::Enum(ref def, _) = item.node {
for variant in &def.variants { for variant in &def.variants {
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
use crate::ty::AdtKind; use crate::ty::AdtKind;
use crate::ty::query::Providers; use crate::ty::query::Providers;
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync}; use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_macros::HashStable; use rustc_macros::HashStable;
...@@ -779,15 +779,15 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V) ...@@ -779,15 +779,15 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
{ {
parallel!({ parallel!({
par_iter(&self.items).for_each(|(_, item)| { par_for_each_in(&self.items, |(_, item)| {
visitor.visit_item(item); visitor.visit_item(item);
}); });
}, { }, {
par_iter(&self.trait_items).for_each(|(_, trait_item)| { par_for_each_in(&self.trait_items, |(_, trait_item)| {
visitor.visit_trait_item(trait_item); visitor.visit_trait_item(trait_item);
}); });
}, { }, {
par_iter(&self.impl_items).for_each(|(_, impl_item)| { par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item); visitor.visit_impl_item(impl_item);
}); });
}); });
......
...@@ -10,12 +10,6 @@ ...@@ -10,12 +10,6 @@
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir; use crate::hir;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
}
}
fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module( tcx.hir().visit_item_likes_in_module(
module_def_id, module_def_id,
......
...@@ -185,12 +185,6 @@ fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { ...@@ -185,12 +185,6 @@ fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor()); tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
}
}
pub fn provide(providers: &mut Providers<'_>) { pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers { *providers = Providers {
check_mod_liveness, check_mod_liveness,
......
...@@ -456,12 +456,6 @@ pub fn local_deprecation_entry(&self, id: HirId) -> Option<DeprecationEntry> { ...@@ -456,12 +456,6 @@ pub fn local_deprecation_entry(&self, id: HirId) -> Option<DeprecationEntry> {
} }
} }
pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
}
}
/// Cross-references the feature names of unstable APIs with enabled /// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors. /// features and possibly prints errors.
fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
......
...@@ -369,6 +369,12 @@ fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { ...@@ -369,6 +369,12 @@ fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
} }
} }
impl<'tcx> QueryDescription<'tcx> for queries::check_private_in_public<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"checking for private elements in public interfaces".into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"type-checking all item bodies".into() "type-checking all item bodies".into()
......
...@@ -350,8 +350,9 @@ ...@@ -350,8 +350,9 @@
[] fn check_match: CheckMatch(DefId) [] fn check_match: CheckMatch(DefId)
-> Result<(), ErrorReported>, -> Result<(), ErrorReported>,
/// Performs the privacy check and computes "access levels". /// Performs part of the privacy check and computes "access levels".
[] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>, [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>,
[] fn check_private_in_public: CheckPrivateInPublic(CrateNum) -> (),
}, },
Other { Other {
......
...@@ -1251,6 +1251,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, ...@@ -1251,6 +1251,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
force!(crate_inherent_impls_overlap_check, LOCAL_CRATE) force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
}, },
DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); } DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
DepKind::CheckPrivateInPublic => { force!(check_private_in_public, LOCAL_CRATE); }
DepKind::MirBuilt => { force!(mir_built, def_id!()); } DepKind::MirBuilt => { force!(mir_built, def_id!()); }
DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); } DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
DepKind::MirConst => { force!(mir_const, def_id!()); } DepKind::MirConst => { force!(mir_const, def_id!()); }
......
...@@ -65,6 +65,7 @@ impl<T: ?Sized> Sync for T {} ...@@ -65,6 +65,7 @@ impl<T: ?Sized> Sync for T {}
} }
use std::ops::Add; use std::ops::Add;
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
#[derive(Debug)] #[derive(Debug)]
pub struct Atomic<T: Copy>(Cell<T>); pub struct Atomic<T: Copy>(Cell<T>);
...@@ -130,7 +131,21 @@ pub fn fetch_add(&self, val: T, _: Ordering) -> T { ...@@ -130,7 +131,21 @@ pub fn fetch_add(&self, val: T, _: Ordering) -> T {
#[macro_export] #[macro_export]
macro_rules! parallel { macro_rules! parallel {
($($blocks:tt),*) => { ($($blocks:tt),*) => {
$($blocks)*; // We catch panics here ensuring that all the blocks execute.
// This makes behavior consistent with the parallel compiler.
let mut panic = None;
$(
if let Err(p) = ::std::panic::catch_unwind(
::std::panic::AssertUnwindSafe(|| $blocks)
) {
if panic.is_none() {
panic = Some(p);
}
}
)*
if let Some(panic) = panic {
::std::panic::resume_unwind(panic);
}
} }
} }
...@@ -140,6 +155,26 @@ pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter { ...@@ -140,6 +155,26 @@ pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
t.into_iter() t.into_iter()
} }
pub fn par_for_each_in<T: IntoIterator>(
t: T,
for_each:
impl Fn(<<T as IntoIterator>::IntoIter as Iterator>::Item) + Sync + Send
) {
// We catch panics here ensuring that all the loop iterations execute.
// This makes behavior consistent with the parallel compiler.
let mut panic = None;
t.into_iter().for_each(|i| {
if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
if panic.is_none() {
panic = Some(p);
}
}
});
if let Some(panic) = panic {
resume_unwind(panic);
}
}
pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>; pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;
pub use std::rc::Rc as Lrc; pub use std::rc::Rc as Lrc;
...@@ -278,23 +313,26 @@ pub fn lock_mut(&self) -> LockGuard<'_, T> { ...@@ -278,23 +313,26 @@ pub fn lock_mut(&self) -> LockGuard<'_, T> {
use std::thread; use std::thread;
pub use rayon::{join, scope}; pub use rayon::{join, scope};
/// Runs a list of blocks in parallel. The first block is executed immediately on
/// the current thread. Use that for the longest running block.
#[macro_export] #[macro_export]
macro_rules! parallel { macro_rules! parallel {
(impl [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => { (impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
parallel!(impl [$block, $($c,)*] [$($rest),*]) parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
}; };
(impl [$($blocks:tt,)*] []) => { (impl $fblock:tt [$($blocks:tt,)*] []) => {
::rustc_data_structures::sync::scope(|s| { ::rustc_data_structures::sync::scope(|s| {
$( $(
s.spawn(|_| $blocks); s.spawn(|_| $blocks);
)* )*
$fblock;
}) })
}; };
($($blocks:tt),*) => { ($fblock:tt, $($blocks:tt),*) => {
// Reverse the order of the blocks since Rayon executes them in reverse order // Reverse the order of the later blocks since Rayon executes them in reverse order
// when using a single thread. This ensures the execution order matches that // when using a single thread. This ensures the execution order matches that
// of a single threaded rustc // of a single threaded rustc
parallel!(impl [] [$($blocks),*]); parallel!(impl $fblock [] [$($blocks),*]);
}; };
} }
...@@ -307,6 +345,15 @@ pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter { ...@@ -307,6 +345,15 @@ pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
t.into_par_iter() t.into_par_iter()
} }
pub fn par_for_each_in<T: IntoParallelIterator>(
t: T,
for_each: impl Fn(
<<T as IntoParallelIterator>::Iter as ParallelIterator>::Item
) + Sync + Send
) {
t.into_par_iter().for_each(for_each)
}
pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>; pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
/// This makes locks panic if they are already held. /// This makes locks panic if they are already held.
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
use rustc_incremental; use rustc_incremental;
use rustc_metadata::creader::CrateLoader; use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore}; use rustc_metadata::cstore::{self, CStore};
...@@ -191,51 +191,50 @@ fn analysis<'tcx>( ...@@ -191,51 +191,50 @@ fn analysis<'tcx>(
let sess = tcx.sess; let sess = tcx.sess;
parallel!({ time(sess, "misc checking 1", || {
time(sess, "looking for entry point", || { parallel!({
middle::entry::find_entry_point(tcx) time(sess, "looking for entry point", || {
}); middle::entry::find_entry_point(tcx)
});
time(sess, "looking for plugin registrar", || { time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx) plugin::build::find_plugin_registrar(tcx)
}); });
time(sess, "looking for derive registrar", || { time(sess, "looking for derive registrar", || {
proc_macro_decls::find(tcx) proc_macro_decls::find(tcx)
}); });
}, { }, {
time(sess, "loop checking", || loops::check_crate(tcx)); par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
}, { tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
time(sess, "attribute checking", || { tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
hir::check_attr::check_crate(tcx) tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
}); });
}, {
time(sess, "stability checking", || {
stability::check_unstable_api_usage(tcx)
}); });
}); });
// passes are timed inside typeck // passes are timed inside typeck
typeck::check_crate(tcx)?; typeck::check_crate(tcx)?;
time(sess, "misc checking", || { time(sess, "misc checking 2", || {
parallel!({ parallel!({
time(sess, "rvalue promotion", || { time(sess, "rvalue promotion + match checking", || {
rvalue_promotion::check_crate(tcx) tcx.par_body_owners(|def_id| {
}); tcx.ensure().const_is_rvalue_promotable_to_static(def_id);
}, { tcx.ensure().check_match(def_id);
time(sess, "intrinsic checking", || { });
middle::intrinsicck::check_crate(tcx)
}); });
}, { }, {
time(sess, "match checking", || mir::matchck_crate(tcx)); time(sess, "liveness checking + intrinsic checking", || {
}, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
// this must run before MIR dump, because // this must run before MIR dump, because
// "not all control paths return a value" is reported here. // "not all control paths return a value" is reported here.
// //
// maybe move the check to a MIR pass? // maybe move the check to a MIR pass?
time(sess, "liveness checking", || { tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
middle::liveness::check_crate(tcx)
tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
});
}); });
}); });
}); });
...@@ -276,19 +275,30 @@ fn analysis<'tcx>( ...@@ -276,19 +275,30 @@ fn analysis<'tcx>(
return Err(ErrorReported); return Err(ErrorReported);
} }
time(sess, "misc checking", || { time(sess, "misc checking 3", || {
parallel!({ parallel!({
time(sess, "privacy checking", || { time(sess, "privacy access levels", || {
rustc_privacy::check_crate(tcx) tcx.ensure().privacy_access_levels(LOCAL_CRATE);
}); });
}, { parallel!({
time(sess, "death checking", || middle::dead::check_crate(tcx)); time(sess, "private in public", || {
}, { tcx.ensure().check_private_in_public(LOCAL_CRATE);
time(sess, "unused lib feature checking", || { });
stability::check_unused_or_stable_features(tcx) }, {
time(sess, "death checking", || middle::dead::check_crate(tcx));
}, {
time(sess, "unused lib feature checking", || {
stability::check_unused_or_stable_features(tcx)
});
}, {
time(sess, "lint checking", || lint::check_crate(tcx));
}); });
}, { }, {
time(sess, "lint checking", || lint::check_crate(tcx)); time(sess, "privacy checking modules", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
});
});
}); });
}); });
......
...@@ -27,13 +27,6 @@ ...@@ -27,13 +27,6 @@
use syntax::ptr::P; use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use syntax_pos::{Span, DUMMY_SP, MultiSpan};
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for def_id in tcx.body_owners() {
tcx.ensure().check_match(def_id);
}
tcx.sess.abort_if_errors();
}
pub(crate) fn check_match<'a, 'tcx>( pub(crate) fn check_match<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId, def_id: DefId,
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
mod _match; mod _match;
mod check_match; mod check_match;
pub use self::check_match::check_crate;
pub(crate) use self::check_match::check_match; pub(crate) use self::check_match::check_match;
use crate::const_eval::{const_field, const_variant_index}; use crate::const_eval::{const_field, const_variant_index};
......
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
pub mod monomorphize; pub mod monomorphize;
pub mod const_eval; pub mod const_eval;
pub use hair::pattern::check_crate as matchck_crate;
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
pub fn provide(providers: &mut Providers<'_>) { pub fn provide(providers: &mut Providers<'_>) {
......
...@@ -45,12 +45,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> { ...@@ -45,12 +45,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
cx: Context, cx: Context,
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
}
}
fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor { tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
sess: &tcx.sess, sess: &tcx.sess,
......
...@@ -39,13 +39,6 @@ pub fn provide(providers: &mut Providers<'_>) { ...@@ -39,13 +39,6 @@ pub fn provide(providers: &mut Providers<'_>) {
}; };
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &body_id in &tcx.hir().krate().body_ids {
let def_id = tcx.hir().body_owner_def_id(body_id);
tcx.const_is_rvalue_promotable_to_static(def_id);
}
}
fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId) def_id: DefId)
-> bool -> bool
......
...@@ -1766,19 +1766,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) { ...@@ -1766,19 +1766,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
pub fn provide(providers: &mut Providers<'_>) { pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers { *providers = Providers {
privacy_access_levels, privacy_access_levels,
check_private_in_public,
check_mod_privacy, check_mod_privacy,
..*providers ..*providers
}; };
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc<AccessLevels> {
tcx.privacy_access_levels(LOCAL_CRATE)
}
fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
let empty_tables = ty::TypeckTables::empty(None); let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages. // Check privacy of names not checked in previous compilation stages.
let mut visitor = NamePrivacyVisitor { let mut visitor = NamePrivacyVisitor {
tcx, tcx,
...@@ -1809,18 +1805,6 @@ fn privacy_access_levels<'tcx>( ...@@ -1809,18 +1805,6 @@ fn privacy_access_levels<'tcx>(
) -> Lrc<AccessLevels> { ) -> Lrc<AccessLevels> {
assert_eq!(krate, LOCAL_CRATE); assert_eq!(krate, LOCAL_CRATE);
let krate = tcx.hir().krate();
for &module in krate.modules.keys() {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
}
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Build up a set of all exported items in the AST. This is a set of all // Build up a set of all exported items in the AST. This is a set of all
// items which are reachable from external crates based on visibility. // items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor { let mut visitor = EmbargoVisitor {
...@@ -1830,7 +1814,7 @@ fn privacy_access_levels<'tcx>( ...@@ -1830,7 +1814,7 @@ fn privacy_access_levels<'tcx>(
changed: false, changed: false,
}; };
loop { loop {
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, tcx.hir().krate());
if visitor.changed { if visitor.changed {
visitor.changed = false; visitor.changed = false;
} else { } else {
...@@ -1839,36 +1823,46 @@ fn privacy_access_levels<'tcx>( ...@@ -1839,36 +1823,46 @@ fn privacy_access_levels<'tcx>(
} }
visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public)); visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
{ Lrc::new(visitor.access_levels)
let mut visitor = ObsoleteVisiblePrivateTypesVisitor { }
tcx,
access_levels: &visitor.access_levels,
in_variant: false,
old_error_set: Default::default(),
};
intravisit::walk_crate(&mut visitor, krate);
fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
assert_eq!(krate, LOCAL_CRATE);
let has_pub_restricted = { let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
let mut pub_restricted_visitor = PubRestrictedVisitor {
tcx,
has_pub_restricted: false
};
intravisit::walk_crate(&mut pub_restricted_visitor, krate);
pub_restricted_visitor.has_pub_restricted
};
// Check for private types and traits in public interfaces. let krate = tcx.hir().krate();
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
access_levels: &access_levels,
in_variant: false,
old_error_set: Default::default(),
};
intravisit::walk_crate(&mut visitor, krate);
let has_pub_restricted = {
let mut pub_restricted_visitor = PubRestrictedVisitor {
tcx, tcx,
has_pub_restricted, has_pub_restricted: false
old_error_set: &visitor.old_error_set,
private_crates
}; };
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); intravisit::walk_crate(&mut pub_restricted_visitor, krate);
} pub_restricted_visitor.has_pub_restricted
};
Lrc::new(visitor.access_levels) let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx,
has_pub_restricted,
old_error_set: &visitor.old_error_set,
private_crates
};
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
} }
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
...@@ -694,15 +694,7 @@ fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } ...@@ -694,15 +694,7 @@ fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
tcx.hir().krate().visit_all_item_likes(&mut visit); tcx.hir().krate().par_visit_all_item_likes(&mut visit);
})
}
pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
}
}) })
} }
...@@ -710,10 +702,6 @@ fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) ...@@ -710,10 +702,6 @@ fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId)
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
} }
pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.typeck_item_bodies(LOCAL_CRATE)
}
fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
-> Result<(), ErrorReported> -> Result<(), ErrorReported>
{ {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
use syntax_pos::Span; use syntax_pos::Span;
use errors::{DiagnosticBuilder, DiagnosticId}; use errors::{DiagnosticBuilder, DiagnosticId};
use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::itemlikevisit::ParItemLikeVisitor;
use rustc::hir; use rustc::hir;
/// Helper type of a temporary returned by `.for_item(...)`. /// Helper type of a temporary returned by `.for_item(...)`.
...@@ -1061,20 +1061,20 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) ...@@ -1061,20 +1061,20 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
} }
} }
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> { impl<'a, 'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'tcx hir::Item) { fn visit_item(&self, i: &'tcx hir::Item) {
debug!("visit_item: {:?}", i); debug!("visit_item: {:?}", i);
let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_id); let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id); self.tcx.ensure().check_item_well_formed(def_id);
} }
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem) {
debug!("visit_trait_item: {:?}", trait_item); debug!("visit_trait_item: {:?}", trait_item);
let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id); let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id); self.tcx.ensure().check_trait_item_well_formed(def_id);
} }
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem) {
debug!("visit_impl_item: {:?}", impl_item); debug!("visit_impl_item: {:?}", impl_item);
let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id); let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
self.tcx.ensure().check_impl_item_well_formed(def_id); self.tcx.ensure().check_impl_item_well_formed(def_id);
......
...@@ -141,9 +141,7 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { ...@@ -141,9 +141,7 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
for &impl_id in impls { for &impl_id in impls {
check_impl_overlap(tcx, impl_id); check_impl_overlap(tcx, impl_id);
} }
use rustc::util::common::time; builtin::check_trait(tcx, def_id);
time(tcx.sess, "builtin::check_trait checking", ||
builtin::check_trait(tcx, def_id));
} }
pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
......
...@@ -56,12 +56,6 @@ ...@@ -56,12 +56,6 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Main entry point // Main entry point
pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
}
}
fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module( tcx.hir().visit_item_likes_in_module(
module_def_id, module_def_id,
......
...@@ -322,8 +322,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) ...@@ -322,8 +322,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
// this ensures that later parts of type checking can assume that items // this ensures that later parts of type checking can assume that items
// have valid types and not error // have valid types and not error
tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
time(tcx.sess, "type collecting", || time(tcx.sess, "type collecting", || {
collect::collect_item_types(tcx)); for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
}
});
})?; })?;
if tcx.features().rustc_attrs { if tcx.features().rustc_attrs {
...@@ -352,9 +355,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) ...@@ -352,9 +355,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?; time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?; time(tcx.sess, "item-types checking", || {
tcx.sess.track_errors(|| {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
}
})
})?;
time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?; time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE))?;
check_unused::check_crate(tcx); check_unused::check_crate(tcx);
check_for_entry_fn(tcx); check_for_entry_fn(tcx);
......
...@@ -8,6 +8,7 @@ trait Foo { ...@@ -8,6 +8,7 @@ trait Foo {
impl<T> Foo for T where NoData<T>: Foo { impl<T> Foo for T where NoData<T>: Foo {
//~^ ERROR: overflow evaluating the requirement //~^ ERROR: overflow evaluating the requirement
fn answer(self) { fn answer(self) {
//~^ ERROR: overflow evaluating the requirement
let val: NoData<T> = NoData; let val: NoData<T> = NoData;
} }
} }
......
...@@ -7,6 +7,7 @@ trait Foo { ...@@ -7,6 +7,7 @@ trait Foo {
impl Foo for FooStruct { impl Foo for FooStruct {
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A` //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
type A = <FooStruct as Foo>::A; type A = <FooStruct as Foo>::A;
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
} }
fn main() {} fn main() {}
...@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A` ...@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
LL | impl Foo for FooStruct { LL | impl Foo for FooStruct {
| ^^^ | ^^^
error: aborting due to previous error error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
--> $DIR/issue-21946.rs:9:5
|
LL | type A = <FooStruct as Foo>::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`. For more information about this error, try `rustc --explain E0275`.
...@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T } ...@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> { impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement //~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T> as Next>::Next; type Next = <GetNext<T> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
} }
fn main() {} fn main() {}
...@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next` ...@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
LL | impl<T: Next> Next for GetNext<T> { LL | impl<T: Next> Next for GetNext<T> {
| ^^^^ | ^^^^
error: aborting due to previous error error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
--> $DIR/issue-23122-1.rs:9:5
|
LL | type Next = <GetNext<T> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`. For more information about this error, try `rustc --explain E0275`.
...@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T } ...@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> { impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement //~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T::Next> as Next>::Next; type Next = <GetNext<T::Next> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
} }
fn main() {} fn main() {}
...@@ -7,6 +7,15 @@ LL | impl<T: Next> Next for GetNext<T> { ...@@ -7,6 +7,15 @@ LL | impl<T: Next> Next for GetNext<T> {
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
error: aborting due to previous error error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
--> $DIR/issue-23122-2.rs:9:5
|
LL | type Next = <GetNext<T::Next> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`. For more information about this error, try `rustc --explain E0275`.
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: type `m::Priv` is private error: type `m::Priv` is private
--> $DIR/private-inferred-type.rs:97:9 --> $DIR/private-inferred-type.rs:97:9
| |
...@@ -202,24 +220,6 @@ error: type `m::Priv` is private ...@@ -202,24 +220,6 @@ error: type `m::Priv` is private
LL | match a { //~ ERROR type `m::Priv` is private LL | match a { //~ ERROR type `m::Priv` is private
| ^ | ^
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: aborting due to 33 previous errors error: aborting due to 33 previous errors
For more information about this error, try `rustc --explain E0446`. For more information about this error, try `rustc --explain E0446`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册