mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #154361 - nnethercote:rustc_hir_analysis-rustc_lint, r=davidtwco
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 is what 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. r? @davidtwco
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