Auto merge of #144841 - cjgillot:typeck-no-attrs, r=davidtwco
Access less HIR attributes from typeck Typeck relies on attributes to modify its own behaviour. This is a problem, as this means that `typeck(some function)` may depend on the span and doc-comments of many other functions. This PR attempts to reduce such accesses to attributes. This yields to a sizeable perf improvement: https://github.com/rust-lang/rust/pull/144841#issuecomment-3153339771 Fixes https://github.com/rust-lang/rust/issues/124352
This commit is contained in:
commit
269d5b56bc
10 changed files with 62 additions and 39 deletions
|
|
@ -511,7 +511,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Untranslatable diagnostics are okay for rustc internals
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
|
||||
if self.has_rustc_attrs
|
||||
&& self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses)
|
||||
{
|
||||
let predicates = self.tcx.predicates_of(def_id);
|
||||
let predicates = predicates.instantiate(self.tcx, args);
|
||||
for (predicate, predicate_span) in predicates {
|
||||
|
|
@ -894,7 +896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// If we have `rustc_do_not_const_check`, do not check `[const]` bounds.
|
||||
if self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
|
||||
if self.has_rustc_attrs && self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
|
|||
/// These are stored here so we may collect them when canonicalizing user
|
||||
/// type ascriptions later.
|
||||
pub(super) trait_ascriptions: RefCell<ItemLocalMap<Vec<ty::Clause<'tcx>>>>,
|
||||
|
||||
/// Whether the current crate enables the `rustc_attrs` feature.
|
||||
/// This allows to skip processing attributes in many places.
|
||||
pub(super) has_rustc_attrs: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
|
@ -154,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
diverging_fallback_behavior,
|
||||
diverging_block_behavior,
|
||||
trait_ascriptions: Default::default(),
|
||||
has_rustc_attrs: root_ctxt.tcx.features().rustc_attrs(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -525,10 +530,13 @@ fn parse_never_type_options_attr(
|
|||
let mut fallback = None;
|
||||
let mut block = None;
|
||||
|
||||
let items = tcx
|
||||
.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
|
||||
.map(|attr| attr.meta_item_list().unwrap())
|
||||
.unwrap_or_default();
|
||||
let items = if tcx.features().rustc_attrs() {
|
||||
tcx.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
|
||||
.map(|attr| attr.meta_item_list().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let items = items.unwrap_or_default();
|
||||
|
||||
for item in items {
|
||||
if item.has_name(sym::fallback) && fallback.is_none() {
|
||||
|
|
|
|||
|
|
@ -46,12 +46,12 @@ use rustc_data_structures::unord::UnordSet;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{HirId, HirIdMap, Node, find_attr};
|
||||
use rustc_hir::{HirId, HirIdMap, Node};
|
||||
use rustc_hir_analysis::check::{check_abi, check_custom_abi};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -174,7 +174,7 @@ fn typeck_with_inspect<'tcx>(
|
|||
.map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)),
|
||||
);
|
||||
|
||||
if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..)) {
|
||||
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
naked_functions::typeck_naked_fn(tcx, def_id, body);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -777,31 +777,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
|
||||
self.assemble_inherent_candidates_from_object(generalized_self_ty);
|
||||
self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps);
|
||||
if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) {
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(
|
||||
raw_self_ty,
|
||||
receiver_steps,
|
||||
);
|
||||
}
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
|
||||
}
|
||||
ty::Adt(def, _) => {
|
||||
let def_id = def.did();
|
||||
self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps);
|
||||
if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(
|
||||
raw_self_ty,
|
||||
receiver_steps,
|
||||
);
|
||||
}
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
|
||||
}
|
||||
ty::Foreign(did) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(did, receiver_steps);
|
||||
if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(
|
||||
raw_self_ty,
|
||||
receiver_steps,
|
||||
);
|
||||
}
|
||||
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
|
||||
}
|
||||
ty::Param(_) => {
|
||||
self.assemble_inherent_candidates_from_param(raw_self_ty);
|
||||
|
|
@ -2400,17 +2385,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
if !self.is_relevant_kind_for_mode(x.kind) {
|
||||
return false;
|
||||
}
|
||||
if self.matches_by_doc_alias(x.def_id) {
|
||||
return true;
|
||||
}
|
||||
match edit_distance_with_substrings(
|
||||
if let Some(d) = edit_distance_with_substrings(
|
||||
name.as_str(),
|
||||
x.name().as_str(),
|
||||
max_dist,
|
||||
) {
|
||||
Some(d) => d > 0,
|
||||
None => false,
|
||||
return d > 0;
|
||||
}
|
||||
self.matches_by_doc_alias(x.def_id)
|
||||
})
|
||||
.copied()
|
||||
.collect()
|
||||
|
|
|
|||
|
|
@ -1747,7 +1747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool {
|
||||
self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
|
||||
self.has_rustc_attrs && self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
|
||||
}
|
||||
|
||||
fn log_capture_analysis_first_pass(
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// This attribute causes us to dump some writeback information
|
||||
// in the form of errors, which is used for unit tests.
|
||||
let rustc_dump_user_args = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
|
||||
let rustc_dump_user_args =
|
||||
self.has_rustc_attrs && self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
|
||||
|
||||
let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args);
|
||||
for param in body.params {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||
use rustc_span::symbol::sym;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::query::LocalCrate;
|
||||
|
|
@ -239,6 +240,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
|
|||
|
||||
/// Query provider for `incoherent_impls`.
|
||||
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
|
||||
if let Some(def_id) = simp.def()
|
||||
&& !tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls)
|
||||
{
|
||||
return &[];
|
||||
}
|
||||
|
||||
let mut impls = Vec::new();
|
||||
for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
|
||||
for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
//@ known-bug: #124352
|
||||
#![rustc_never_type_options(: Unsize<U> = "hi")]
|
||||
|
||||
fn main() {}
|
||||
8
tests/ui/attributes/malformed-never-type-options.rs
Normal file
8
tests/ui/attributes/malformed-never-type-options.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//! Regression test for #124352
|
||||
//! The `rustc_*` attribute is malformed, but ICEing without a `feature(rustc_attrs)` is still bad.
|
||||
|
||||
#![rustc_never_type_options(: Unsize<U> = "hi")]
|
||||
//~^ ERROR expected unsuffixed literal, found `:`
|
||||
//~| ERROR use of an internal attribute
|
||||
|
||||
fn main() {}
|
||||
19
tests/ui/attributes/malformed-never-type-options.stderr
Normal file
19
tests/ui/attributes/malformed-never-type-options.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error: expected unsuffixed literal, found `:`
|
||||
--> $DIR/malformed-never-type-options.rs:4:29
|
||||
|
|
||||
LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
|
||||
| ^
|
||||
|
||||
error[E0658]: use of an internal attribute
|
||||
--> $DIR/malformed-never-type-options.rs:4:1
|
||||
|
|
||||
LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
= note: the `#[rustc_never_type_options]` attribute is an internal implementation detail that will never be stable
|
||||
= note: `rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue