mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Make rustc_hir_analysis not depend on rustc_lint.
`rustc_hir_analysis` depends on `rustc_lint` in just a single function: `emit_delayed_lint`, which is used by the "emit_ast_lowering_delayed_lints" checking section within `rustc_hir_analysis::check_crate`. This commit moves that function and section to out of `rustc_hir_analysis::check_crate`, into `rustc_interface`, eliminating the dependency. This seems reasonable because the delayed lint errors aren't really related to HIR analysis. They were in there just because HIR analysis follows AST lowering. This means `rustc_hir_analysis` and `rustc_lint` can both start compiling as soon as `rustc_trait_selection` finishes. This also changes the error order in one test, which doesn't matter. The commit also changes `emit_delayed_lint` to `emit_delayed_lints`, factoring out some code duplicated in rustdoc.
This commit is contained in:
@@ -4021,7 +4021,6 @@ dependencies = [
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_lint",
|
||||
"rustc_lint_defs",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
|
||||
@@ -19,7 +19,6 @@ rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_lint = { path = "../rustc_lint" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
|
||||
@@ -85,8 +85,6 @@
|
||||
use rustc_abi::{CVariadicStatus, ExternAbi};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_lint::DecorateAttrLint;
|
||||
use rustc_middle::mir::interpret::GlobalId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{Const, Ty, TyCtxt};
|
||||
@@ -147,23 +145,6 @@ pub fn provide(providers: &mut Providers) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) {
|
||||
match lint {
|
||||
DelayedLint::AttributeParsing(attribute_lint) => {
|
||||
tcx.emit_node_span_lint(
|
||||
attribute_lint.lint_id.lint,
|
||||
attribute_lint.id,
|
||||
attribute_lint.span,
|
||||
DecorateAttrLint {
|
||||
sess: tcx.sess,
|
||||
tcx: Some(tcx),
|
||||
diagnostic: &attribute_lint.kind,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
let _prof_timer = tcx.sess.timer("type_check_crate");
|
||||
|
||||
@@ -182,42 +163,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
let _: R = tcx.ensure_result().crate_inherent_impls_overlap_check(());
|
||||
});
|
||||
|
||||
tcx.sess.time("emit_ast_lowering_delayed_lints", || {
|
||||
// sanity check in debug mode that all lints are really noticed
|
||||
// and we really will emit them all in the loop right below.
|
||||
//
|
||||
// during ast lowering, when creating items, foreign items, trait items and impl items
|
||||
// we store in them whether they have any lints in their owner node that should be
|
||||
// picked up by `hir_crate_items`. However, theoretically code can run between that
|
||||
// boolean being inserted into the item and the owner node being created.
|
||||
// We don't want any new lints to be emitted there
|
||||
// (though honestly, you have to really try to manage to do that but still),
|
||||
// but this check is there to catch that.
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
// iterate over all owners
|
||||
for owner_id in tcx.hir_crate_items(()).owners() {
|
||||
// if it has delayed lints
|
||||
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
|
||||
if !delayed_lints.lints.is_empty() {
|
||||
// assert that delayed_lint_items also picked up this item to have lints
|
||||
assert!(
|
||||
tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
|
||||
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
|
||||
for lint in &delayed_lints.lints {
|
||||
emit_delayed_lint(lint, tcx);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tcx.par_hir_body_owners(|item_def_id| {
|
||||
let def_kind = tcx.def_kind(item_def_id);
|
||||
// Make sure we evaluate all static and (non-associated) const items, even if unused.
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_hir::{Attribute, MaybeOwner, find_attr};
|
||||
use rustc_incremental::setup_dep_graph;
|
||||
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
|
||||
use rustc_lint::{
|
||||
BufferedEarlyLint, DecorateAttrLint, EarlyCheckNode, LintStore, unerased_lint_store,
|
||||
};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
@@ -1025,6 +1028,29 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn emit_delayed_lints(tcx: TyCtxt<'_>) {
|
||||
for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
|
||||
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
|
||||
for lint in &delayed_lints.lints {
|
||||
match lint {
|
||||
DelayedLint::AttributeParsing(attribute_lint) => {
|
||||
tcx.emit_node_span_lint(
|
||||
attribute_lint.lint_id.lint,
|
||||
attribute_lint.id,
|
||||
attribute_lint.span,
|
||||
DecorateAttrLint {
|
||||
sess: tcx.sess,
|
||||
tcx: Some(tcx),
|
||||
diagnostic: &attribute_lint.kind,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
|
||||
/// This function never fails.
|
||||
fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
@@ -1074,6 +1100,32 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
]);
|
||||
});
|
||||
|
||||
sess.time("emit_ast_lowering_delayed_lints", || {
|
||||
// Sanity check in debug mode that all lints are really noticed and we really will emit
|
||||
// them all in the loop right below.
|
||||
//
|
||||
// During ast lowering, when creating items, foreign items, trait items and impl items,
|
||||
// we store in them whether they have any lints in their owner node that should be
|
||||
// picked up by `hir_crate_items`. However, theoretically code can run between that
|
||||
// boolean being inserted into the item and the owner node being created. We don't want
|
||||
// any new lints to be emitted there (you have to really try to manage that but still),
|
||||
// but this check is there to catch that.
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let hir_items = tcx.hir_crate_items(());
|
||||
for owner_id in hir_items.owners() {
|
||||
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
|
||||
if !delayed_lints.lints.is_empty() {
|
||||
// Assert that delayed_lint_items also picked up this item to have lints.
|
||||
assert!(hir_items.delayed_lint_items().any(|i| i == owner_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit_delayed_lints(tcx);
|
||||
});
|
||||
|
||||
rustc_hir_analysis::check_crate(tcx);
|
||||
// Freeze definitions as we don't add new ones at this point.
|
||||
// We need to wait until now since we synthesize a by-move body
|
||||
|
||||
@@ -904,13 +904,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
|
||||
return;
|
||||
}
|
||||
|
||||
for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
|
||||
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
|
||||
for lint in &delayed_lints.lints {
|
||||
rustc_hir_analysis::emit_delayed_lint(lint, tcx);
|
||||
}
|
||||
}
|
||||
}
|
||||
rustc_interface::passes::emit_delayed_lints(tcx);
|
||||
|
||||
if render_opts.dep_info().is_some() {
|
||||
rustc_interface::passes::write_dep_info(tcx);
|
||||
|
||||
@@ -38,14 +38,6 @@ LL | #[inline]
|
||||
|
|
||||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/inline-trait-and-foreign-items.rs:26:14
|
||||
|
|
||||
LL | type U = impl Trait;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `U` must be used in combination with a concrete type within the same impl
|
||||
|
||||
warning: `#[inline]` attribute cannot be used on associated consts
|
||||
--> $DIR/inline-trait-and-foreign-items.rs:7:5
|
||||
|
|
||||
@@ -69,5 +61,13 @@ LL | #[inline]
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/inline-trait-and-foreign-items.rs:26:14
|
||||
|
|
||||
LL | type U = impl Trait;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `U` must be used in combination with a concrete type within the same impl
|
||||
|
||||
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||
|
||||
|
||||
Reference in New Issue
Block a user