未验证 提交 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 {
[eval_always] CoherenceInherentImplOverlapCheck,
[] CoherenceCheckTrait(DefId),
[eval_always] PrivacyAccessLevels(CrateNum),
[eval_always] CheckPrivateInPublic(CrateNum),
[eval_always] Analysis(CrateNum),
// 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) {
}
}
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 {
if let hir::ItemKind::Enum(ref def, _) = item.node {
for variant in &def.variants {
......
......@@ -30,7 +30,7 @@
use crate::ty::AdtKind;
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_macros::HashStable;
......@@ -779,15 +779,15 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
{
parallel!({
par_iter(&self.items).for_each(|(_, item)| {
par_for_each_in(&self.items, |(_, 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);
});
}, {
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
});
......
......@@ -10,12 +10,6 @@
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
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) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
......
......@@ -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());
}
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<'_>) {
*providers = Providers {
check_mod_liveness,
......
......@@ -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
/// features and possibly prints errors.
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> {
}
}
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> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"type-checking all item bodies".into()
......
......@@ -350,8 +350,9 @@
[] fn check_match: CheckMatch(DefId)
-> 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 check_private_in_public: CheckPrivateInPublic(CrateNum) -> (),
},
Other {
......
......@@ -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)
},
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::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
DepKind::MirConst => { force!(mir_const, def_id!()); }
......
......@@ -65,6 +65,7 @@ impl<T: ?Sized> Sync for T {}
}
use std::ops::Add;
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
#[derive(Debug)]
pub struct Atomic<T: Copy>(Cell<T>);
......@@ -130,7 +131,21 @@ pub fn fetch_add(&self, val: T, _: Ordering) -> T {
#[macro_export]
macro_rules! parallel {
($($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 {
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 use std::rc::Rc as Lrc;
......@@ -278,23 +313,26 @@ pub fn lock_mut(&self) -> LockGuard<'_, T> {
use std::thread;
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_rules! parallel {
(impl [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
parallel!(impl [$block, $($c,)*] [$($rest),*])
(impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
};
(impl [$($blocks:tt,)*] []) => {
(impl $fblock:tt [$($blocks:tt,)*] []) => {
::rustc_data_structures::sync::scope(|s| {
$(
s.spawn(|_| $blocks);
)*
$fblock;
})
};
($($blocks:tt),*) => {
// Reverse the order of the blocks since Rayon executes them in reverse order
($fblock:tt, $($blocks:tt),*) => {
// 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
// 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 {
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]>;
/// This makes locks panic if they are already held.
......
......@@ -21,7 +21,7 @@
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::fingerprint::Fingerprint;
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_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
......@@ -191,51 +191,50 @@ fn analysis<'tcx>(
let sess = tcx.sess;
parallel!({
time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});
time(sess, "misc checking 1", || {
parallel!({
time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});
time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
time(sess, "looking for derive registrar", || {
proc_macro_decls::find(tcx)
});
}, {
time(sess, "loop checking", || loops::check_crate(tcx));
}, {
time(sess, "attribute checking", || {
hir::check_attr::check_crate(tcx)
});
}, {
time(sess, "stability checking", || {
stability::check_unstable_api_usage(tcx)
time(sess, "looking for derive registrar", || {
proc_macro_decls::find(tcx)
});
}, {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
});
});
});
// passes are timed inside typeck
typeck::check_crate(tcx)?;
time(sess, "misc checking", || {
time(sess, "misc checking 2", || {
parallel!({
time(sess, "rvalue promotion", || {
rvalue_promotion::check_crate(tcx)
});
}, {
time(sess, "intrinsic checking", || {
middle::intrinsicck::check_crate(tcx)
time(sess, "rvalue promotion + match checking", || {
tcx.par_body_owners(|def_id| {
tcx.ensure().const_is_rvalue_promotable_to_static(def_id);
tcx.ensure().check_match(def_id);
});
});
}, {
time(sess, "match checking", || mir::matchck_crate(tcx));
}, {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
time(sess, "liveness checking", || {
middle::liveness::check_crate(tcx)
time(sess, "liveness checking + intrinsic checking", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
});
});
});
});
......@@ -276,19 +275,30 @@ fn analysis<'tcx>(
return Err(ErrorReported);
}
time(sess, "misc checking", || {
time(sess, "misc checking 3", || {
parallel!({
time(sess, "privacy checking", || {
rustc_privacy::check_crate(tcx)
time(sess, "privacy access levels", || {
tcx.ensure().privacy_access_levels(LOCAL_CRATE);
});
}, {
time(sess, "death checking", || middle::dead::check_crate(tcx));
}, {
time(sess, "unused lib feature checking", || {
stability::check_unused_or_stable_features(tcx)
parallel!({
time(sess, "private in public", || {
tcx.ensure().check_private_in_public(LOCAL_CRATE);
});
}, {
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 @@
use syntax::ptr::P;
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>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
......
......@@ -3,7 +3,6 @@
mod _match;
mod check_match;
pub use self::check_match::check_crate;
pub(crate) use self::check_match::check_match;
use crate::const_eval::{const_field, const_variant_index};
......
......@@ -54,7 +54,6 @@
pub mod monomorphize;
pub mod const_eval;
pub use hair::pattern::check_crate as matchck_crate;
use rustc::ty::query::Providers;
pub fn provide(providers: &mut Providers<'_>) {
......
......@@ -45,12 +45,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
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) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
sess: &tcx.sess,
......
......@@ -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>,
def_id: DefId)
-> bool
......
......@@ -1766,19 +1766,15 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
privacy_access_levels,
check_private_in_public,
check_mod_privacy,
..*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) {
let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages.
let mut visitor = NamePrivacyVisitor {
tcx,
......@@ -1809,18 +1805,6 @@ fn privacy_access_levels<'tcx>(
) -> Lrc<AccessLevels> {
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
// items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor {
......@@ -1830,7 +1814,7 @@ fn privacy_access_levels<'tcx>(
changed: false,
};
loop {
intravisit::walk_crate(&mut visitor, krate);
intravisit::walk_crate(&mut visitor, tcx.hir().krate());
if visitor.changed {
visitor.changed = false;
} else {
......@@ -1839,36 +1823,46 @@ fn privacy_access_levels<'tcx>(
}
visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
{
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
access_levels: &visitor.access_levels,
in_variant: false,
old_error_set: Default::default(),
};
intravisit::walk_crate(&mut visitor, krate);
Lrc::new(visitor.access_levels)
}
fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
assert_eq!(krate, LOCAL_CRATE);
let has_pub_restricted = {
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
};
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
// Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
let krate = tcx.hir().krate();
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,
has_pub_restricted,
old_error_set: &visitor.old_error_set,
private_crates
has_pub_restricted: false
};
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 }
......@@ -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> {
tcx.sess.track_errors(|| {
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
tcx.hir().krate().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));
}
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
})
}
......@@ -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 });
}
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)
-> Result<(), ErrorReported>
{
......
......@@ -15,7 +15,7 @@
use syntax_pos::Span;
use errors::{DiagnosticBuilder, DiagnosticId};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::itemlikevisit::ParItemLikeVisitor;
use rustc::hir;
/// Helper type of a temporary returned by `.for_item(...)`.
......@@ -1061,20 +1061,20 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
}
}
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'tcx hir::Item) {
impl<'a, 'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&self, i: &'tcx hir::Item) {
debug!("visit_item: {:?}", i);
let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_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);
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);
}
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);
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);
......
......@@ -141,9 +141,7 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
for &impl_id in impls {
check_impl_overlap(tcx, impl_id);
}
use rustc::util::common::time;
time(tcx.sess, "builtin::check_trait checking", ||
builtin::check_trait(tcx, def_id));
builtin::check_trait(tcx, def_id);
}
pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
......
......@@ -56,12 +56,6 @@
///////////////////////////////////////////////////////////////////////////
// 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) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
......
......@@ -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
// have valid types and not error
tcx.sess.track_errors(|| {
time(tcx.sess, "type collecting", ||
collect::collect_item_types(tcx));
time(tcx.sess, "type collecting", || {
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 {
......@@ -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, "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_for_entry_fn(tcx);
......
......@@ -8,6 +8,7 @@ trait Foo {
impl<T> Foo for T where NoData<T>: Foo {
//~^ ERROR: overflow evaluating the requirement
fn answer(self) {
//~^ ERROR: overflow evaluating the requirement
let val: NoData<T> = NoData;
}
}
......
......@@ -7,6 +7,7 @@ trait Foo {
impl Foo for FooStruct {
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
type A = <FooStruct as Foo>::A;
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
}
fn main() {}
......@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
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`.
......@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
fn main() {}
......@@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
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`.
......@@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T::Next> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
fn main() {}
......@@ -7,6 +7,15 @@ LL | impl<T: Next> Next for GetNext<T> {
= 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>`
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`.
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
--> $DIR/private-inferred-type.rs:97:9
|
......@@ -202,24 +220,6 @@ 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
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.
先完成此消息的编辑!
想要评论请 注册