summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs66
-rw-r--r--compiler/rustc_passes/src/check_const.rs13
-rw-r--r--compiler/rustc_passes/src/dead.rs34
-rw-r--r--compiler/rustc_passes/src/entry.rs4
-rw-r--r--compiler/rustc_passes/src/errors.rs29
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs23
-rw-r--r--compiler/rustc_passes/src/lang_items.rs375
-rw-r--r--compiler/rustc_passes/src/lib.rs11
-rw-r--r--compiler/rustc_passes/src/lib_features.rs73
-rw-r--r--compiler/rustc_passes/src/liveness.rs108
-rw-r--r--compiler/rustc_passes/src/loops.rs25
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs10
-rw-r--r--compiler/rustc_passes/src/reachable.rs8
-rw-r--r--compiler/rustc_passes/src/stability.rs61
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs30
16 files changed, 490 insertions, 382 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c5767fd90..c5073048b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -130,59 +130,59 @@ impl CheckAttrVisitor<'_> {
&mut specified_inline,
&mut doc_aliases,
),
- sym::no_link => self.check_no_link(hir_id, &attr, span, target),
- sym::export_name => self.check_export_name(hir_id, &attr, span, target),
+ sym::no_link => self.check_no_link(hir_id, attr, span, target),
+ sym::export_name => self.check_export_name(hir_id, attr, span, target),
sym::rustc_layout_scalar_valid_range_start
| sym::rustc_layout_scalar_valid_range_end => {
- self.check_rustc_layout_scalar_valid_range(&attr, span, target)
+ self.check_rustc_layout_scalar_valid_range(attr, span, target)
}
sym::allow_internal_unstable => {
- self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs)
+ self.check_allow_internal_unstable(hir_id, attr, span, target, attrs)
}
- sym::debugger_visualizer => self.check_debugger_visualizer(&attr, target),
+ sym::debugger_visualizer => self.check_debugger_visualizer(attr, target),
sym::rustc_allow_const_fn_unstable => {
- self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target)
+ self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
}
sym::rustc_std_internal_symbol => {
- self.check_rustc_std_internal_symbol(&attr, span, target)
+ self.check_rustc_std_internal_symbol(attr, span, target)
}
sym::naked => self.check_naked(hir_id, attr, span, target),
sym::rustc_never_returns_null_ptr => {
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
sym::rustc_legacy_const_generics => {
- self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item)
+ self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
}
sym::rustc_lint_query_instability => {
- self.check_rustc_lint_query_instability(hir_id, &attr, span, target)
+ self.check_rustc_lint_query_instability(hir_id, attr, span, target)
}
sym::rustc_lint_diagnostics => {
- self.check_rustc_lint_diagnostics(hir_id, &attr, span, target)
+ self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
}
- sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target),
+ sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(attr, span, target),
sym::rustc_lint_opt_deny_field_access => {
- self.check_rustc_lint_opt_deny_field_access(&attr, span, target)
+ self.check_rustc_lint_opt_deny_field_access(attr, span, target)
}
sym::rustc_clean
| sym::rustc_dirty
| sym::rustc_if_this_changed
- | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
+ | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(attr),
sym::rustc_coinductive
| sym::rustc_must_implement_one_of
| sym::rustc_deny_explicit_impl
- | sym::const_trait => self.check_must_be_applied_to_trait(&attr, span, target),
+ | sym::const_trait => self.check_must_be_applied_to_trait(attr, span, target),
sym::cmse_nonsecure_entry => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
}
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
- sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
- sym::must_use => self.check_must_use(hir_id, &attr, target),
- sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
+ sym::must_not_suspend => self.check_must_not_suspend(attr, span, target),
+ sym::must_use => self.check_must_use(hir_id, attr, target),
+ sym::rustc_pass_by_value => self.check_pass_by_value(attr, span, target),
sym::rustc_allow_incoherent_impl => {
- self.check_allow_incoherent_impl(&attr, span, target)
+ self.check_allow_incoherent_impl(attr, span, target)
}
sym::rustc_has_incoherent_inherent_impls => {
- self.check_has_incoherent_inherent_impls(&attr, span, target)
+ self.check_has_incoherent_inherent_impls(attr, span, target)
}
sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
sym::ffi_const => self.check_ffi_const(attr.span, target),
@@ -192,9 +192,9 @@ impl CheckAttrVisitor<'_> {
| sym::unstable
| sym::stable
| sym::rustc_allowed_through_unstable_modules
- | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
- sym::link_ordinal => self.check_link_ordinal(&attr, span, target),
- sym::rustc_confusables => self.check_confusables(&attr, target),
+ | sym::rustc_promotable => self.check_stability_promotable(attr, span, target),
+ sym::link_ordinal => self.check_link_ordinal(attr, span, target),
+ sym::rustc_confusables => self.check_confusables(attr, target),
sym::rustc_safe_intrinsic => {
self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
}
@@ -604,7 +604,7 @@ impl CheckAttrVisitor<'_> {
&& !self.tcx.sess.target.is_like_wasm
&& !self.tcx.sess.opts.actually_rustdoc
{
- let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else {
+ let hir::Node::Item(item) = self.tcx.hir_node(hir_id) else {
unreachable!();
};
let hir::ItemKind::Fn(sig, _, _) = item.kind else {
@@ -820,11 +820,11 @@ impl CheckAttrVisitor<'_> {
self.doc_attr_str_error(meta, "keyword");
return false;
}
- match self.tcx.hir().find(hir_id).and_then(|node| match node {
+ match self.tcx.opt_hir_node(hir_id).and_then(|node| match node {
hir::Node::Item(item) => Some(&item.kind),
_ => None,
}) {
- Some(ItemKind::Mod(ref module)) => {
+ Some(ItemKind::Mod(module)) => {
if !module.item_ids.is_empty() {
self.tcx.sess.emit_err(errors::DocKeywordEmptyMod { span: meta.span() });
return false;
@@ -846,11 +846,11 @@ impl CheckAttrVisitor<'_> {
}
fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
- match self.tcx.hir().find(hir_id).and_then(|node| match node {
+ match self.tcx.opt_hir_node(hir_id).and_then(|node| match node {
hir::Node::Item(item) => Some(&item.kind),
_ => None,
}) {
- Some(ItemKind::Impl(ref i)) => {
+ Some(ItemKind::Impl(i)) => {
let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_]))
|| if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
bare_fn_ty.decl.inputs.len() == 1
@@ -1387,7 +1387,7 @@ impl CheckAttrVisitor<'_> {
/// Checks if `#[link]` is applied to an item other than a foreign module.
fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
if target == Target::ForeignMod
- && let hir::Node::Item(item) = self.tcx.hir().get(hir_id)
+ && let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
&& let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
&& !matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic)
{
@@ -1456,7 +1456,7 @@ impl CheckAttrVisitor<'_> {
}
fn is_impl_item(&self, hir_id: HirId) -> bool {
- matches!(self.tcx.hir().get(hir_id), hir::Node::ImplItem(..))
+ matches!(self.tcx.hir_node(hir_id), hir::Node::ImplItem(..))
}
/// Checks if `#[export_name]` is applied to a function or static. Returns `true` if valid.
@@ -2074,7 +2074,7 @@ impl CheckAttrVisitor<'_> {
&& let hir::Node::Item(Item {
kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic | Abi::PlatformIntrinsic, .. },
..
- }) = hir.get(parent)
+ }) = self.tcx.hir_node(parent)
{
return true;
}
@@ -2222,7 +2222,7 @@ impl CheckAttrVisitor<'_> {
} else {
// special case when `#[macro_export]` is applied to a macro 2.0
let (macro_definition, _) =
- self.tcx.hir().find(hir_id).unwrap().expect_item().expect_macro();
+ self.tcx.opt_hir_node(hir_id).unwrap().expect_item().expect_macro();
let is_decl_macro = !macro_definition.macro_rules;
if is_decl_macro {
@@ -2395,7 +2395,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
// Historically we've run more checks on non-exported than exported macros,
// so this lets us continue to run them while maintaining backwards compatibility.
// In the long run, the checks should be harmonized.
- if let ItemKind::Macro(ref macro_def, _) = item.kind {
+ if let ItemKind::Macro(macro_def, _) = item.kind {
let def_id = item.owner_id.to_def_id();
if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
check_non_exported_macro_for_invalid_attrs(self.tcx, item);
@@ -2443,7 +2443,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
// When checking statements ignore expressions, they will be checked later.
- if let hir::StmtKind::Local(ref l) = stmt.kind {
+ if let hir::StmtKind::Local(l) = stmt.kind {
self.check_attributes(l.hir_id, stmt.span, Target::Statement, None);
}
intravisit::walk_stmt(self, stmt)
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 7188c177f..76c746734 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
-use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks};
+use crate::errors::SkippingConstChecks;
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
@@ -110,8 +110,8 @@ impl<'tcx> CheckConstVisitor<'tcx> {
// However, we cannot allow stable `const fn`s to use unstable features without an explicit
// opt-in via `rustc_allow_const_fn_unstable`.
- let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id));
- attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate)
+ let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
+ attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate)
};
match required_gates {
@@ -138,11 +138,10 @@ impl<'tcx> CheckConstVisitor<'tcx> {
match missing_gates.as_slice() {
[] => {
- tcx.sess.emit_err(ExprNotAllowedInContext {
+ span_bug!(
span,
- expr: expr.name(),
- context: const_kind.keyword_name(),
- });
+ "we should not have reached this point, since `.await` is denied earlier"
+ );
}
[missing_primary, ref missing_secondary @ ..] => {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 2e8c58b02..d27079497 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -32,7 +32,7 @@ use crate::errors::{
// may need to be marked as live.
fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
matches!(
- tcx.hir().find_by_def_id(def_id),
+ tcx.opt_hir_node_by_def_id(def_id),
Some(
Node::Item(..)
| Node::ImplItem(..)
@@ -297,7 +297,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
// tuple struct constructor function
let id = self.struct_constructors.get(&id).copied().unwrap_or(id);
- if let Some(node) = self.tcx.hir().find_by_def_id(id) {
+ if let Some(node) = self.tcx.opt_hir_node_by_def_id(id) {
// When using `#[allow]` or `#[expect]` of `dead_code`, we do a QOL improvement
// by declaring fn calls, statics, ... within said items as live, as well as
// the item itself, although technically this is not the case.
@@ -314,7 +314,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
// for the `#[expect]` case.
//
// Note that an item can and will be duplicated on the worklist with different
- // `ComesFromAllowExpect`, particulary if it was added from the
+ // `ComesFromAllowExpect`, particularly if it was added from the
// `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks,
// this "duplication" is essential as otherwise a function with `#[expect]`
// called from a `pub fn` may be falsely reported as not live, falsely
@@ -373,10 +373,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
self.repr_has_repr_c = def.repr().c();
self.repr_has_repr_simd = def.repr().simd();
- intravisit::walk_item(self, &item)
+ intravisit::walk_item(self, item)
}
hir::ItemKind::ForeignMod { .. } => {}
- _ => intravisit::walk_item(self, &item),
+ _ => intravisit::walk_item(self, item),
},
Node::TraitItem(trait_item) => {
intravisit::walk_trait_item(self, trait_item);
@@ -403,7 +403,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
intravisit::walk_impl_item(self, impl_item);
}
Node::ForeignItem(foreign_item) => {
- intravisit::walk_foreign_item(self, &foreign_item);
+ intravisit::walk_foreign_item(self, foreign_item);
}
_ => {}
}
@@ -459,9 +459,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
self.lookup_and_handle_method(expr.hir_id);
}
hir::ExprKind::Field(ref lhs, ..) => {
- self.handle_field_access(&lhs, expr.hir_id);
+ self.handle_field_access(lhs, expr.hir_id);
}
- hir::ExprKind::Struct(ref qpath, ref fields, _) => {
+ hir::ExprKind::Struct(qpath, fields, _) => {
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
self.handle_res(res);
if let ty::Adt(adt, _) = self.typeck_results().expr_ty(expr).kind() {
@@ -493,7 +493,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
self.in_pat = true;
match pat.kind {
- PatKind::Struct(ref path, ref fields, _) => {
+ PatKind::Struct(ref path, fields, _) => {
let res = self.typeck_results().qpath_res(path, pat.hir_id);
self.handle_field_pattern_match(pat, res, fields);
}
@@ -501,7 +501,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
self.handle_res(res);
}
- PatKind::TupleStruct(ref qpath, ref fields, dotdot) => {
+ PatKind::TupleStruct(ref qpath, fields, dotdot) => {
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
self.handle_tuple_field_pattern_match(pat, res, fields, dotdot);
}
@@ -559,7 +559,7 @@ fn has_allow_dead_code_or_lang_attr(
}
fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
matches!(lint_level, lint::Allow | lint::Expect(_))
}
@@ -805,10 +805,10 @@ impl<'tcx> DeadVisitor<'tcx> {
};
let tcx = self.tcx;
- let first_hir_id = tcx.hir().local_def_id_to_hir_id(first_id);
+ let first_hir_id = tcx.local_def_id_to_hir_id(first_id);
let first_lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, first_hir_id).0;
assert!(dead_codes.iter().skip(1).all(|id| {
- let hir_id = tcx.hir().local_def_id_to_hir_id(*id);
+ let hir_id = tcx.local_def_id_to_hir_id(*id);
let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
level == first_lint_level
}));
@@ -969,7 +969,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
let def_id = item.id.owner_id.def_id;
if !visitor.is_live_code(def_id) {
let name = tcx.item_name(def_id.to_def_id());
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
dead_items.push(DeadItem { def_id, name, level })
@@ -997,7 +997,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
let def_id = variant.def_id.expect_local();
if !live_symbols.contains(&def_id) {
// Record to group diagnostics.
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
dead_variants.push(DeadItem { def_id, name: variant.name, level });
continue;
@@ -1009,9 +1009,9 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
.iter()
.filter_map(|field| {
let def_id = field.did.expect_local();
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
if let ShouldWarnAboutField::Yes(is_pos) =
- visitor.should_warn_about_field(&field)
+ visitor.should_warn_about_field(field)
{
let level = tcx
.lint_level_at_node(
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 51a64b385..7667fc21e 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -38,7 +38,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
}
// If the user wants no main function at all, then stop here.
- if attr::contains_name(&tcx.hir().attrs(CRATE_HIR_ID), sym::no_main) {
+ if attr::contains_name(tcx.hir().attrs(CRATE_HIR_ID), sym::no_main) {
return None;
}
@@ -126,7 +126,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
{
// non-local main imports are handled below
if let Some(def_id) = def_id.as_local()
- && matches!(tcx.hir().find_by_def_id(def_id), Some(Node::ForeignItem(_)))
+ && matches!(tcx.opt_hir_node_by_def_id(def_id), Some(Node::ForeignItem(_)))
{
tcx.sess.emit_err(ExternMain { span: tcx.def_span(def_id) });
return None;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 411c94101..8f8da211d 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -867,9 +867,9 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
#[track_caller]
fn into_diagnostic(
self,
- handler: &'_ rustc_errors::Handler,
+ dcx: &'_ rustc_errors::DiagCtxt,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(fluent::passes_invalid_attr_at_crate_level);
+ let mut diag = dcx.struct_err(fluent::passes_invalid_attr_at_crate_level);
diag.set_span(self.span);
diag.set_arg("name", self.name);
// Only emit an error with a suggestion if we can create a string out
@@ -1005,15 +1005,6 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> {
pub prev_declared: &'b str,
}
-#[derive(Diagnostic)]
-#[diag(passes_expr_not_allowed_in_context, code = "E0744")]
-pub struct ExprNotAllowedInContext<'a> {
- #[primary_span]
- pub span: Span,
- pub expr: String,
- pub context: &'a str,
-}
-
pub struct BreakNonLoop<'a> {
pub span: Span,
pub head: Option<Span>,
@@ -1029,9 +1020,9 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
#[track_caller]
fn into_diagnostic(
self,
- handler: &rustc_errors::Handler,
+ dcx: &rustc_errors::DiagCtxt,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_span_err_with_code(
+ let mut diag = dcx.struct_span_err_with_code(
self.span,
fluent::passes_break_non_loop,
error_code!(E0571),
@@ -1178,9 +1169,9 @@ impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
#[track_caller]
fn into_diagnostic(
self,
- handler: &rustc_errors::Handler,
+ dcx: &rustc_errors::DiagCtxt,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_span_err_with_code(
+ let mut diag = dcx.struct_span_err_with_code(
self.span,
fluent::passes_naked_functions_asm_block,
error_code!(E0787),
@@ -1294,9 +1285,9 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
#[track_caller]
fn into_diagnostic(
self,
- handler: &'a rustc_errors::Handler,
+ dcx: &'a rustc_errors::DiagCtxt,
) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
- let mut diag = handler.struct_span_err_with_code(
+ let mut diag = dcx.struct_span_err_with_code(
DUMMY_SP,
fluent::passes_no_main_function,
error_code!(E0601),
@@ -1357,9 +1348,9 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
#[track_caller]
fn into_diagnostic(
self,
- handler: &rustc_errors::Handler,
+ dcx: &rustc_errors::DiagCtxt,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err_with_code(
+ let mut diag = dcx.struct_err_with_code(
match self.duplicate {
Duplicate::Plain => fluent::passes_duplicate_lang_item,
Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index f825363ae..18a80aa34 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -31,7 +31,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
if !errors.is_empty() {
let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
- tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, message);
+ tcx.sess.span_delayed_bug(rustc_span::DUMMY_SP, message);
}
}
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index f915c1057..c2392620c 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -121,6 +121,8 @@ impl<'k> StatCollector<'k> {
}
fn print(&self, title: &str, prefix: &str) {
+ // We will soon sort, so the initial order does not matter.
+ #[allow(rustc::potential_query_instability)]
let mut nodes: Vec<_> = self.nodes.iter().collect();
nodes.sort_by_key(|(_, node)| node.stats.count * node.stats.size);
@@ -147,6 +149,8 @@ impl<'k> StatCollector<'k> {
to_readable_str(node.stats.size)
);
if !node.subnodes.is_empty() {
+ // We will soon sort, so the initial order does not matter.
+ #[allow(rustc::potential_query_instability)]
let mut subnodes: Vec<_> = node.subnodes.iter().collect();
subnodes.sort_by_key(|(_, subnode)| subnode.count * subnode.size);
@@ -286,7 +290,21 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_pat(&mut self, p: &'v hir::Pat<'v>) {
record_variants!(
(self, p, p.kind, Id::Node(p.hir_id), hir, Pat, PatKind),
- [Wild, Binding, Struct, TupleStruct, Or, Path, Tuple, Box, Ref, Lit, Range, Slice]
+ [
+ Wild,
+ Binding,
+ Struct,
+ TupleStruct,
+ Or,
+ Never,
+ Path,
+ Tuple,
+ Box,
+ Ref,
+ Lit,
+ Range,
+ Slice
+ ]
);
hir_visit::walk_pat(self, p)
}
@@ -411,7 +429,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) {
record_variants!(
(self, b, b, Id::None, hir, GenericBound, GenericBound),
- [Trait, LangItemTrait, Outlives]
+ [Trait, Outlives]
);
hir_visit::walk_param_bound(self, b)
}
@@ -554,6 +572,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Range,
Slice,
Rest,
+ Never,
Paren,
MacCall
]
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 2aec4ea7e..6d14a1409 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -7,21 +7,21 @@
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
//! * Functions called by the compiler itself.
-use crate::check_attr::target_from_impl_item;
use crate::errors::{
DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
};
use crate::weak_lang_items;
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_ast as ast;
+use rustc_ast::visit;
+use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{extract, GenericRequirement};
-use rustc_hir::{LangItem, LanguageItems, Target};
-use rustc_middle::ty::TyCtxt;
+use rustc_hir::{LangItem, LanguageItems, MethodKind, Target};
+use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_session::cstore::ExternCrate;
use rustc_span::symbol::kw::Empty;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
use rustc_middle::query::Providers;
@@ -31,28 +31,55 @@ pub(crate) enum Duplicate {
CrateDepends,
}
-struct LanguageItemCollector<'tcx> {
+struct LanguageItemCollector<'ast, 'tcx> {
items: LanguageItems,
tcx: TyCtxt<'tcx>,
+ resolver: &'ast ResolverAstLowering,
+ // FIXME(#118552): We should probably feed def_span eagerly on def-id creation
+ // so we can avoid constructing this map for local def-ids.
+ item_spans: FxHashMap<DefId, Span>,
+ parent_item: Option<&'ast ast::Item>,
}
-impl<'tcx> LanguageItemCollector<'tcx> {
- fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
- LanguageItemCollector { tcx, items: LanguageItems::new() }
+impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
+ fn new(
+ tcx: TyCtxt<'tcx>,
+ resolver: &'ast ResolverAstLowering,
+ ) -> LanguageItemCollector<'ast, 'tcx> {
+ LanguageItemCollector {
+ tcx,
+ resolver,
+ items: LanguageItems::new(),
+ item_spans: FxHashMap::default(),
+ parent_item: None,
+ }
}
- fn check_for_lang(&mut self, actual_target: Target, def_id: LocalDefId) {
- let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
- if let Some((name, span)) = extract(&attrs) {
+ fn check_for_lang(
+ &mut self,
+ actual_target: Target,
+ def_id: LocalDefId,
+ attrs: &'ast [ast::Attribute],
+ item_span: Span,
+ generics: Option<&'ast ast::Generics>,
+ ) {
+ if let Some((name, attr_span)) = extract(attrs) {
match LangItem::from_name(name) {
// Known lang item with attribute on correct target.
Some(lang_item) if actual_target == lang_item.target() => {
- self.collect_item_extended(lang_item, def_id, span);
+ self.collect_item_extended(
+ lang_item,
+ def_id,
+ item_span,
+ attr_span,
+ generics,
+ actual_target,
+ );
}
// Known lang item with attribute on incorrect target.
Some(lang_item) => {
self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
- span,
+ span: attr_span,
name,
expected_target: lang_item.target(),
actual_target,
@@ -60,122 +87,131 @@ impl<'tcx> LanguageItemCollector<'tcx> {
}
// Unknown lang item.
_ => {
- self.tcx.sess.emit_err(UnknownLangItem { span, name });
+ self.tcx.sess.emit_err(UnknownLangItem { span: attr_span, name });
}
}
}
}
- fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) {
+ fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId, item_span: Option<Span>) {
// Check for duplicates.
- if let Some(original_def_id) = self.items.get(lang_item) {
- if original_def_id != item_def_id {
- let local_span = self.tcx.hir().span_if_local(item_def_id);
- let lang_item_name = lang_item.name();
- let crate_name = self.tcx.crate_name(item_def_id.krate);
- let mut dependency_of = Empty;
- let is_local = item_def_id.is_local();
- let path = if is_local {
- String::new()
- } else {
- self.tcx
- .crate_extern_paths(item_def_id.krate)
- .iter()
- .map(|p| p.display().to_string())
- .collect::<Vec<_>>()
- .join(", ")
- };
- let first_defined_span = self.tcx.hir().span_if_local(original_def_id);
- let mut orig_crate_name = Empty;
- let mut orig_dependency_of = Empty;
- let orig_is_local = original_def_id.is_local();
- let orig_path = if orig_is_local {
- String::new()
- } else {
- self.tcx
- .crate_extern_paths(original_def_id.krate)
- .iter()
- .map(|p| p.display().to_string())
- .collect::<Vec<_>>()
- .join(", ")
- };
- if first_defined_span.is_none() {
- orig_crate_name = self.tcx.crate_name(original_def_id.krate);
- if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) =
- self.tcx.extern_crate(original_def_id)
- {
- orig_dependency_of = self.tcx.crate_name(*inner_dependency_of);
- }
+ if let Some(original_def_id) = self.items.get(lang_item)
+ && original_def_id != item_def_id
+ {
+ let lang_item_name = lang_item.name();
+ let crate_name = self.tcx.crate_name(item_def_id.krate);
+ let mut dependency_of = Empty;
+ let is_local = item_def_id.is_local();
+ let path = if is_local {
+ String::new()
+ } else {
+ self.tcx
+ .crate_extern_paths(item_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ };
+
+ let first_defined_span = self.item_spans.get(&original_def_id).copied();
+ let mut orig_crate_name = Empty;
+ let mut orig_dependency_of = Empty;
+ let orig_is_local = original_def_id.is_local();
+ let orig_path = if orig_is_local {
+ String::new()
+ } else {
+ self.tcx
+ .crate_extern_paths(original_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ };
+
+ if first_defined_span.is_none() {
+ orig_crate_name = self.tcx.crate_name(original_def_id.krate);
+ if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) =
+ self.tcx.extern_crate(original_def_id)
+ {
+ orig_dependency_of = self.tcx.crate_name(*inner_dependency_of);
}
+ }
- let duplicate = if local_span.is_some() {
- Duplicate::Plain
- } else {
- match self.tcx.extern_crate(item_def_id) {
- Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => {
- dependency_of = self.tcx.crate_name(*inner_dependency_of);
- Duplicate::CrateDepends
- }
- _ => Duplicate::Crate,
+ let duplicate = if item_span.is_some() {
+ Duplicate::Plain
+ } else {
+ match self.tcx.extern_crate(item_def_id) {
+ Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => {
+ dependency_of = self.tcx.crate_name(*inner_dependency_of);
+ Duplicate::CrateDepends
}
- };
-
- self.tcx.sess.emit_err(DuplicateLangItem {
- local_span,
- lang_item_name,
- crate_name,
- dependency_of,
- is_local,
- path,
- first_defined_span,
- orig_crate_name,
- orig_dependency_of,
- orig_is_local,
- orig_path,
- duplicate,
- });
+ _ => Duplicate::Crate,
+ }
+ };
+
+ self.tcx.sess.emit_err(DuplicateLangItem {
+ local_span: item_span,
+ lang_item_name,
+ crate_name,
+ dependency_of,
+ is_local,
+ path,
+ first_defined_span,
+ orig_crate_name,
+ orig_dependency_of,
+ orig_is_local,
+ orig_path,
+ duplicate,
+ });
+ } else {
+ // Matched.
+ self.items.set(lang_item, item_def_id);
+ // Collect span for error later
+ if let Some(item_span) = item_span {
+ self.item_spans.insert(item_def_id, item_span);
}
}
-
- // Matched.
- self.items.set(lang_item, item_def_id);
}
// Like collect_item() above, but also checks whether the lang item is declared
// with the right number of generic arguments.
- fn collect_item_extended(&mut self, lang_item: LangItem, item_def_id: LocalDefId, span: Span) {
+ fn collect_item_extended(
+ &mut self,
+ lang_item: LangItem,
+ item_def_id: LocalDefId,
+ item_span: Span,
+ attr_span: Span,
+ generics: Option<&'ast ast::Generics>,
+ target: Target,
+ ) {
let name = lang_item.name();
- // Now check whether the lang_item has the expected number of generic
- // arguments. Generally speaking, binary and indexing operations have
- // one (for the RHS/index), unary operations have none, the closure
- // traits have one for the argument list, coroutines have one for the
- // resume argument, and ordering/equality relations have one for the RHS
- // Some other types like Box and various functions like drop_in_place
- // have minimum requirements.
+ if let Some(generics) = generics {
+ // Now check whether the lang_item has the expected number of generic
+ // arguments. Generally speaking, binary and indexing operations have
+ // one (for the RHS/index), unary operations have none, the closure
+ // traits have one for the argument list, coroutines have one for the
+ // resume argument, and ordering/equality relations have one for the RHS
+ // Some other types like Box and various functions like drop_in_place
+ // have minimum requirements.
- if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) =
- self.tcx.hir().get_by_def_id(item_def_id)
- {
- let (actual_num, generics_span) = match kind.generics() {
- Some(generics) => (
- generics
- .params
- .iter()
- .filter(|p| !self.tcx.has_attr(p.def_id, sym::rustc_host))
- .count(),
- generics.span,
- ),
- None => (0, *item_span),
- };
+ // FIXME: This still doesn't count, e.g., elided lifetimes and APITs.
+ let mut actual_num = generics.params.len();
+ if target.is_associated_item() {
+ actual_num += self
+ .parent_item
+ .unwrap()
+ .opt_generics()
+ .map_or(0, |generics| generics.params.len());
+ }
let mut at_least = false;
let required = match lang_item.required_generics() {
GenericRequirement::Exact(num) if num != actual_num => Some(num),
GenericRequirement::Minimum(num) if actual_num < num => {
at_least = true;
- Some(num)}
- ,
+ Some(num)
+ }
// If the number matches, or there is no requirement, handle it normally
_ => None,
};
@@ -185,10 +221,10 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// item kind of the target is correct, the target is still wrong
// because of the wrong number of generic arguments.
self.tcx.sess.emit_err(IncorrectTarget {
- span,
- generics_span,
+ span: attr_span,
+ generics_span: generics.span,
name: name.as_str(),
- kind: kind.descr(),
+ kind: target.name(),
num,
actual_num,
at_least,
@@ -199,58 +235,117 @@ impl<'tcx> LanguageItemCollector<'tcx> {
}
}
- self.collect_item(lang_item, item_def_id.to_def_id());
+ self.collect_item(lang_item, item_def_id.to_def_id(), Some(item_span));
}
}
/// Traverses and collects all the lang items in all crates.
fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
+ let resolver = tcx.resolver_for_lowering(()).borrow();
+ let (resolver, krate) = &*resolver;
+
// Initialize the collector.
- let mut collector = LanguageItemCollector::new(tcx);
+ let mut collector = LanguageItemCollector::new(tcx, resolver);
// Collect lang items in other crates.
for &cnum in tcx.crates(()).iter() {
for &(def_id, lang_item) in tcx.defined_lang_items(cnum).iter() {
- collector.collect_item(lang_item, def_id);
+ collector.collect_item(lang_item, def_id, None);
}
}
- // Collect lang items in this crate.
- let crate_items = tcx.hir_crate_items(());
+ // Collect lang items local to this crate.
+ visit::Visitor::visit_crate(&mut collector, krate);
- for id in crate_items.items() {
- collector
- .check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.owner_id.def_id);
+ // Find all required but not-yet-defined lang items.
+ weak_lang_items::check_crate(tcx, &mut collector.items, krate);
- if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) {
- let item = tcx.hir().item(id);
- if let hir::ItemKind::Enum(def, ..) = &item.kind {
- for variant in def.variants {
- collector.check_for_lang(Target::Variant, variant.def_id);
- }
- }
- }
- }
+ // Return all the lang items that were found.
+ collector.items
+}
+
+impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
+ fn visit_item(&mut self, i: &'ast ast::Item) {
+ let target = match &i.kind {
+ ast::ItemKind::ExternCrate(_) => Target::ExternCrate,
+ ast::ItemKind::Use(_) => Target::Use,
+ ast::ItemKind::Static(_) => Target::Static,
+ ast::ItemKind::Const(_) => Target::Const,
+ ast::ItemKind::Fn(_) => Target::Fn,
+ ast::ItemKind::Mod(_, _) => Target::Mod,
+ ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
+ ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
+ ast::ItemKind::TyAlias(_) => Target::TyAlias,
+ ast::ItemKind::Enum(_, _) => Target::Enum,
+ ast::ItemKind::Struct(_, _) => Target::Struct,
+ ast::ItemKind::Union(_, _) => Target::Union,
+ ast::ItemKind::Trait(_) => Target::Trait,
+ ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
+ ast::ItemKind::Impl(_) => Target::Impl,
+ ast::ItemKind::MacroDef(_) => Target::MacroDef,
+ ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+ };
- // FIXME: avoid calling trait_item() when possible
- for id in crate_items.trait_items() {
- let item = tcx.hir().trait_item(id);
- collector.check_for_lang(Target::from_trait_item(item), item.owner_id.def_id)
+ self.check_for_lang(
+ target,
+ self.resolver.node_id_to_def_id[&i.id],
+ &i.attrs,
+ i.span,
+ i.opt_generics(),
+ );
+
+ let parent_item = self.parent_item.replace(i);
+ visit::walk_item(self, i);
+ self.parent_item = parent_item;
}
- // FIXME: avoid calling impl_item() when possible
- for id in crate_items.impl_items() {
- let item = tcx.hir().impl_item(id);
- collector.check_for_lang(target_from_impl_item(tcx, item), item.owner_id.def_id)
+ fn visit_enum_def(&mut self, enum_definition: &'ast ast::EnumDef) {
+ for variant in &enum_definition.variants {
+ self.check_for_lang(
+ Target::Variant,
+ self.resolver.node_id_to_def_id[&variant.id],
+ &variant.attrs,
+ variant.span,
+ None,
+ );
+ }
+
+ visit::walk_enum_def(self, enum_definition);
}
- // Extract out the found lang items.
- let LanguageItemCollector { mut items, .. } = collector;
+ fn visit_assoc_item(&mut self, i: &'ast ast::AssocItem, ctxt: visit::AssocCtxt) {
+ let (target, generics) = match &i.kind {
+ ast::AssocItemKind::Fn(fun) => (
+ match &self.parent_item.unwrap().kind {
+ ast::ItemKind::Impl(i) => {
+ if i.of_trait.is_some() {
+ Target::Method(MethodKind::Trait { body: fun.body.is_some() })
+ } else {
+ Target::Method(MethodKind::Inherent)
+ }
+ }
+ ast::ItemKind::Trait(_) => {
+ Target::Method(MethodKind::Trait { body: fun.body.is_some() })
+ }
+ _ => unreachable!(),
+ },
+ &fun.generics,
+ ),
+ ast::AssocItemKind::Const(ct) => (Target::AssocConst, &ct.generics),
+ ast::AssocItemKind::Type(ty) => (Target::AssocTy, &ty.generics),
+ ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+ };
- // Find all required but not-yet-defined lang items.
- weak_lang_items::check_crate(tcx, &mut items);
+ self.check_for_lang(
+ target,
+ self.resolver.node_id_to_def_id[&i.id],
+ &i.attrs,
+ i.span,
+ Some(generics),
+ );
- items
+ visit::walk_assoc_item(self, i, ctxt);
+ }
}
pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 946a9e68d..c969867e8 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -4,11 +4,10 @@
//!
//! This API is completely unstable and subject to change.
-#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(not(bootstrap), doc(rust_logo))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![doc(rust_logo)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(map_try_insert)]
@@ -23,8 +22,6 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
-use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_fluent_macro::fluent_messages;
use rustc_middle::query::Providers;
pub mod abi_test;
@@ -48,7 +45,7 @@ pub mod stability;
mod upvars;
mod weak_lang_items;
-fluent_messages! { "../messages.ftl" }
+rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
pub fn provide(providers: &mut Providers) {
check_attr::provide(providers);
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 0daa273db..6c0412bed 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -8,18 +8,14 @@ use rustc_ast::Attribute;
use rustc_attr::VERSION_PLACEHOLDER;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::lib_features::LibFeatures;
-use rustc_middle::query::Providers;
+use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
+use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::{sym, Span};
use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
-fn new_lib_features() -> LibFeatures {
- LibFeatures { stable: Default::default(), unstable: Default::default() }
-}
-
pub struct LibFeatureCollector<'tcx> {
tcx: TyCtxt<'tcx>,
lib_features: LibFeatures,
@@ -27,10 +23,10 @@ pub struct LibFeatureCollector<'tcx> {
impl<'tcx> LibFeatureCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> {
- LibFeatureCollector { tcx, lib_features: new_lib_features() }
+ LibFeatureCollector { tcx, lib_features: LibFeatures::default() }
}
- fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
+ fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)> {
let stab_attrs = [
sym::stable,
sym::unstable,
@@ -72,8 +68,11 @@ impl<'tcx> LibFeatureCollector<'tcx> {
| sym::rustc_const_unstable
| sym::rustc_default_body_unstable
);
- if since.is_some() || is_unstable {
- return Some((feature, since, attr.span));
+ if is_unstable {
+ return Some((feature, FeatureStability::Unstable, attr.span));
+ }
+ if let Some(since) = since {
+ return Some((feature, FeatureStability::AcceptedSince(since), attr.span));
}
}
// We need to iterate over the other attributes, because
@@ -86,39 +85,39 @@ impl<'tcx> LibFeatureCollector<'tcx> {
None
}
- fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
- let already_in_stable = self.lib_features.stable.contains_key(&feature);
- let already_in_unstable = self.lib_features.unstable.contains_key(&feature);
-
- match (since, already_in_stable, already_in_unstable) {
- (Some(since), _, false) => {
- if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
- if *prev_since != since {
- self.tcx.sess.emit_err(FeatureStableTwice {
- span,
- feature,
- since,
- prev_since: *prev_since,
- });
- return;
- }
- }
+ fn collect_feature(&mut self, feature: Symbol, stability: FeatureStability, span: Span) {
+ let existing_stability = self.lib_features.stability.get(&feature).cloned();
- self.lib_features.stable.insert(feature, (since, span));
+ match (stability, existing_stability) {
+ (_, None) => {
+ self.lib_features.stability.insert(feature, (stability, span));
}
- (None, false, _) => {
- self.lib_features.unstable.insert(feature, span);
+ (
+ FeatureStability::AcceptedSince(since),
+ Some((FeatureStability::AcceptedSince(prev_since), _)),
+ ) => {
+ if prev_since != since {
+ self.tcx.sess.emit_err(FeatureStableTwice { span, feature, since, prev_since });
+ }
+ }
+ (FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => {
+ self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
+ span,
+ feature,
+ declared: "stable",
+ prev_declared: "unstable",
+ });
}
- (Some(_), _, true) | (None, true, _) => {
- let declared = if since.is_some() { "stable" } else { "unstable" };
- let prev_declared = if since.is_none() { "stable" } else { "unstable" };
+ (FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => {
self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
span,
feature,
- declared,
- prev_declared,
+ declared: "unstable",
+ prev_declared: "stable",
});
}
+ // duplicate `unstable` feature is ok.
+ (FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {}
}
}
}
@@ -137,11 +136,11 @@ impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
}
}
-fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
+fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
// If `staged_api` is not enabled then we aren't allowed to define lib
// features; there is no point collecting them.
if !tcx.features().staged_api {
- return new_lib_features();
+ return LibFeatures::default();
}
let mut collector = LibFeatureCollector::new(tcx);
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index b73fb984c..c9e5eb50b 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -170,7 +170,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// compute liveness
let mut lsets = Liveness::new(&mut maps, def_id);
- let entry_ln = lsets.compute(&body, hir_id);
+ let entry_ln = lsets.compute(body, hir_id);
lsets.log_liveness(entry_ln, body_id.hir_id);
// check for various error conditions
@@ -366,7 +366,7 @@ impl<'tcx> IrMaps<'tcx> {
impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
- self.add_from_pat(&local.pat);
+ self.add_from_pat(local.pat);
if local.els.is_some() {
self.add_live_node_for_node(local.hir_id, ExprNode(local.span, local.hir_id));
}
@@ -374,8 +374,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
}
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
- self.add_from_pat(&arm.pat);
- if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
+ self.add_from_pat(arm.pat);
+ if let Some(hir::Guard::IfLet(let_expr)) = arm.guard {
self.add_from_pat(let_expr.pat);
}
intravisit::walk_arm(self, arm);
@@ -400,7 +400,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
match expr.kind {
// live nodes required for uses or definitions of variables:
- hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+ hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
debug!("expr {}: path that leads to {:?}", expr.hir_id, path.res);
if let Res::Local(_var_hir_id) = path.res {
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
@@ -592,7 +592,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match self.successors[ln] {
Some(successor) => self.assigned_on_entry(successor, var),
None => {
- self.ir.tcx.sess.delay_span_bug(DUMMY_SP, "no successor");
+ self.ir.tcx.sess.span_delayed_bug(DUMMY_SP, "no successor");
true
}
}
@@ -736,7 +736,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
}
- let succ = self.propagate_through_expr(&body.value, self.exit_ln);
+ let succ = self.propagate_through_expr(body.value, self.exit_ln);
if self.closure_min_captures.is_none() {
// Either not a closure, or closure without any captured variables.
@@ -776,7 +776,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
if !self.merge_from_succ(self.exit_ln, self.closure_ln) {
break;
}
- assert_eq!(succ, self.propagate_through_expr(&body.value, self.exit_ln));
+ assert_eq!(succ, self.propagate_through_expr(body.value, self.exit_ln));
}
succ
@@ -792,7 +792,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn propagate_through_stmt(&mut self, stmt: &hir::Stmt<'_>, succ: LiveNode) -> LiveNode {
match stmt.kind {
- hir::StmtKind::Local(ref local) => {
+ hir::StmtKind::Local(local) => {
// Note: we mark the variable as defined regardless of whether
// there is an initializer. Initially I had thought to only mark
// the live variable as defined if it was initialized, and then we
@@ -830,7 +830,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.init_from_succ(ln, succ);
self.merge_from_succ(ln, else_ln);
let succ = self.propagate_through_expr(init, ln);
- self.define_bindings_in_pat(&local.pat, succ)
+ self.define_bindings_in_pat(local.pat, succ)
} else {
span_bug!(
stmt.span,
@@ -839,18 +839,18 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
} else {
let succ = self.propagate_through_opt_expr(local.init, succ);
- self.define_bindings_in_pat(&local.pat, succ)
+ self.define_bindings_in_pat(local.pat, succ)
}
}
hir::StmtKind::Item(..) => succ,
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
- self.propagate_through_expr(&expr, succ)
+ self.propagate_through_expr(expr, succ)
}
}
}
fn propagate_through_exprs(&mut self, exprs: &[Expr<'_>], succ: LiveNode) -> LiveNode {
- exprs.iter().rev().fold(succ, |succ, expr| self.propagate_through_expr(&expr, succ))
+ exprs.iter().rev().fold(succ, |succ, expr| self.propagate_through_expr(expr, succ))
}
fn propagate_through_opt_expr(
@@ -866,11 +866,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.kind {
// Interesting cases with control flow or which gen/kill
- hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+ hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
self.access_path(expr.hir_id, path, succ, ACC_READ | ACC_USE)
}
- hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(&e, succ),
+ hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(e, succ),
hir::ExprKind::Closure { .. } => {
debug!("{:?} is an ExprKind::Closure", expr);
@@ -899,9 +899,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// Note that labels have been resolved, so we don't need to look
// at the label ident
- hir::ExprKind::Loop(ref blk, ..) => self.propagate_through_loop(expr, &blk, succ),
+ hir::ExprKind::Loop(ref blk, ..) => self.propagate_through_loop(expr, blk, succ),
- hir::ExprKind::Yield(ref e, ..) => {
+ hir::ExprKind::Yield(e, ..) => {
let yield_ln = self.live_node(expr.hir_id, expr.span);
self.init_from_succ(yield_ln, succ);
self.merge_from_succ(yield_ln, self.exit_ln);
@@ -923,11 +923,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// ( succ )
//
let else_ln = self.propagate_through_opt_expr(else_opt.as_deref(), succ);
- let then_ln = self.propagate_through_expr(&then, succ);
+ let then_ln = self.propagate_through_expr(then, succ);
let ln = self.live_node(expr.hir_id, expr.span);
self.init_from_succ(ln, else_ln);
self.merge_from_succ(ln, then_ln);
- self.propagate_through_expr(&cond, ln)
+ self.propagate_through_expr(cond, ln)
}
hir::ExprKind::Match(ref e, arms, _) => {
@@ -948,7 +948,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let ln = self.live_node(expr.hir_id, expr.span);
self.init_empty(ln, succ);
for arm in arms {
- let body_succ = self.propagate_through_expr(&arm.body, succ);
+ let body_succ = self.propagate_through_expr(arm.body, succ);
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
@@ -957,10 +957,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(let_expr.init, let_bind)
}
});
- let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
+ let arm_succ = self.define_bindings_in_pat(arm.pat, guard_succ);
self.merge_from_succ(ln, arm_succ);
}
- self.propagate_through_expr(&e, ln)
+ self.propagate_through_expr(e, ln)
}
hir::ExprKind::Ret(ref o_e) => {
@@ -968,7 +968,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln)
}
- hir::ExprKind::Become(ref e) => {
+ hir::ExprKind::Become(e) => {
// Ignore succ and subst exit_ln.
self.propagate_through_expr(e, self.exit_ln)
}
@@ -1007,63 +1007,63 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Assign(ref l, ref r, _) => {
// see comment on places in
// propagate_through_place_components()
- let succ = self.write_place(&l, succ, ACC_WRITE);
- let succ = self.propagate_through_place_components(&l, succ);
- self.propagate_through_expr(&r, succ)
+ let succ = self.write_place(l, succ, ACC_WRITE);
+ let succ = self.propagate_through_place_components(l, succ);
+ self.propagate_through_expr(r, succ)
}
hir::ExprKind::AssignOp(_, ref l, ref r) => {
// an overloaded assign op is like a method call
if self.typeck_results.is_method_call(expr) {
- let succ = self.propagate_through_expr(&l, succ);
- self.propagate_through_expr(&r, succ)
+ let succ = self.propagate_through_expr(l, succ);
+ self.propagate_through_expr(r, succ)
} else {
// see comment on places in
// propagate_through_place_components()
- let succ = self.write_place(&l, succ, ACC_WRITE | ACC_READ);
- let succ = self.propagate_through_expr(&r, succ);
- self.propagate_through_place_components(&l, succ)
+ let succ = self.write_place(l, succ, ACC_WRITE | ACC_READ);
+ let succ = self.propagate_through_expr(r, succ);
+ self.propagate_through_place_components(l, succ)
}
}
// Uninteresting cases: just propagate in rev exec order
- hir::ExprKind::Array(ref exprs) => self.propagate_through_exprs(exprs, succ),
+ hir::ExprKind::Array(exprs) => self.propagate_through_exprs(exprs, succ),
- hir::ExprKind::Struct(_, ref fields, ref with_expr) => {
+ hir::ExprKind::Struct(_, fields, ref with_expr) => {
let succ = self.propagate_through_opt_expr(with_expr.as_deref(), succ);
fields
.iter()
.rev()
- .fold(succ, |succ, field| self.propagate_through_expr(&field.expr, succ))
+ .fold(succ, |succ, field| self.propagate_through_expr(field.expr, succ))
}
- hir::ExprKind::Call(ref f, ref args) => {
+ hir::ExprKind::Call(ref f, args) => {
let succ = self.check_is_ty_uninhabited(expr, succ);
let succ = self.propagate_through_exprs(args, succ);
- self.propagate_through_expr(&f, succ)
+ self.propagate_through_expr(f, succ)
}
- hir::ExprKind::MethodCall(.., receiver, ref args, _) => {
+ hir::ExprKind::MethodCall(.., receiver, args, _) => {
let succ = self.check_is_ty_uninhabited(expr, succ);
let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(receiver, succ)
}
- hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ),
+ hir::ExprKind::Tup(exprs) => self.propagate_through_exprs(exprs, succ),
hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => {
- let r_succ = self.propagate_through_expr(&r, succ);
+ let r_succ = self.propagate_through_expr(r, succ);
let ln = self.live_node(expr.hir_id, expr.span);
self.init_from_succ(ln, succ);
self.merge_from_succ(ln, r_succ);
- self.propagate_through_expr(&l, ln)
+ self.propagate_through_expr(l, ln)
}
hir::ExprKind::Index(ref l, ref r, _) | hir::ExprKind::Binary(_, ref l, ref r) => {
- let r_succ = self.propagate_through_expr(&r, succ);
- self.propagate_through_expr(&l, r_succ)
+ let r_succ = self.propagate_through_expr(r, succ);
+ self.propagate_through_expr(l, r_succ)
}
hir::ExprKind::AddrOf(_, _, ref e)
@@ -1071,9 +1071,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
| hir::ExprKind::Type(ref e, _)
| hir::ExprKind::DropTemps(ref e)
| hir::ExprKind::Unary(_, ref e)
- | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(&e, succ),
+ | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
- hir::ExprKind::InlineAsm(ref asm) => {
+ hir::ExprKind::InlineAsm(asm) => {
// Handle non-returning asm
let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) {
self.exit_ln
@@ -1141,7 +1141,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// Note that labels have been resolved, so we don't need to look
// at the label ident
- hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(&blk, succ),
+ hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(blk, succ),
}
}
@@ -1197,7 +1197,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.kind {
hir::ExprKind::Path(_) => succ,
- hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(&e, succ),
+ hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(e, succ),
_ => self.propagate_through_expr(expr, succ),
}
}
@@ -1205,7 +1205,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// see comment on propagate_through_place()
fn write_place(&mut self, expr: &Expr<'_>, succ: LiveNode, acc: u32) -> LiveNode {
match expr.kind {
- hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+ hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
self.access_path(expr.hir_id, path, succ, acc)
}
@@ -1341,7 +1341,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
- self.check_unused_vars_in_pat(&local.pat, None, None, |spans, hir_id, ln, var| {
+ self.check_unused_vars_in_pat(local.pat, None, None, |spans, hir_id, ln, var| {
if local.init.is_some() {
self.warn_about_dead_assign(spans, hir_id, ln, var);
}
@@ -1356,7 +1356,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
}
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
- self.check_unused_vars_in_pat(&arm.pat, None, None, |_, _, _, _| {});
+ self.check_unused_vars_in_pat(arm.pat, None, None, |_, _, _, _| {});
intravisit::walk_arm(self, arm);
}
}
@@ -1364,16 +1364,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Assign(ref l, ..) => {
- this.check_place(&l);
+ this.check_place(l);
}
hir::ExprKind::AssignOp(_, ref l, _) => {
if !this.typeck_results.is_method_call(expr) {
- this.check_place(&l);
+ this.check_place(l);
}
}
- hir::ExprKind::InlineAsm(ref asm) => {
+ hir::ExprKind::InlineAsm(asm) => {
for (op, _op_sp) in asm.operands {
match op {
hir::InlineAsmOperand::Out { expr, .. } => {
@@ -1434,7 +1434,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
impl<'tcx> Liveness<'_, 'tcx> {
fn check_place(&mut self, expr: &'tcx Expr<'tcx>) {
match expr.kind {
- hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+ hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
if let Res::Local(var_hid) = path.res {
// Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually
@@ -1507,7 +1507,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
fn warn_about_unused_args(&self, body: &hir::Body<'_>, entry_ln: LiveNode) {
for p in body.params {
self.check_unused_vars_in_pat(
- &p.pat,
+ p.pat,
Some(entry_ln),
Some(body),
|spans, hir_id, ln, var| {
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 25e131d74..bfaf4a5a9 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -4,7 +4,6 @@ use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Destination, Movability, Node};
-use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
@@ -30,16 +29,16 @@ enum Context {
}
#[derive(Copy, Clone)]
-struct CheckLoopVisitor<'a, 'hir> {
+struct CheckLoopVisitor<'a, 'tcx> {
sess: &'a Session,
- hir_map: Map<'hir>,
+ tcx: TyCtxt<'tcx>,
cx: Context,
}
fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
- &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal },
+ &mut CheckLoopVisitor { sess: tcx.sess, tcx, cx: Normal },
);
}
@@ -51,7 +50,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
- self.hir_map
+ self.tcx.hir()
}
fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
@@ -84,7 +83,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
match e.kind {
hir::ExprKind::Loop(ref b, _, source, _) => {
- self.with_context(Loop(source), |v| v.visit_block(&b));
+ self.with_context(Loop(source), |v| v.visit_block(b));
}
hir::ExprKind::Closure(&hir::Closure {
ref fn_decl,
@@ -98,19 +97,19 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
} else {
Closure(fn_decl_span)
};
- self.visit_fn_decl(&fn_decl);
+ self.visit_fn_decl(fn_decl);
self.with_context(cx, |v| v.visit_nested_body(body));
}
hir::ExprKind::Block(ref b, Some(_label)) => {
- self.with_context(LabeledBlock, |v| v.visit_block(&b));
+ self.with_context(LabeledBlock, |v| v.visit_block(b));
}
hir::ExprKind::Block(ref b, None) if matches!(self.cx, Fn) => {
- self.with_context(Normal, |v| v.visit_block(&b));
+ self.with_context(Normal, |v| v.visit_block(b));
}
hir::ExprKind::Block(ref b, None)
if matches!(self.cx, Normal | Constant | UnlabeledBlock(_)) =>
{
- self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(&b));
+ self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b));
}
hir::ExprKind::Break(break_label, ref opt_expr) => {
if let Some(e) = opt_expr {
@@ -136,13 +135,13 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
Err(hir::LoopIdError::UnresolvedLabel) => None,
};
- if let Some(Node::Block(_)) = loop_id.and_then(|id| self.hir_map.find(id)) {
+ if let Some(Node::Block(_)) = loop_id.and_then(|id| self.tcx.opt_hir_node(id)) {
return;
}
if let Some(break_expr) = opt_expr {
let (head, loop_label, loop_kind) = if let Some(loop_id) = loop_id {
- match self.hir_map.expect_expr(loop_id).kind {
+ match self.tcx.hir().expect_expr(loop_id).kind {
hir::ExprKind::Loop(_, label, source, sp) => {
(Some(sp), label, Some(source))
}
@@ -188,7 +187,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
match destination.target_id {
Ok(loop_id) => {
- if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
+ if let Node::Block(block) = self.tcx.opt_hir_node(loop_id).unwrap() {
self.sess.emit_err(ContinueLabeledBlock {
span: e.span,
block_span: block.span,
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 7f36c59ad..25637f935 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -35,7 +35,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
continue;
}
- let (fn_header, body_id) = match tcx.hir().get_by_def_id(def_id) {
+ let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
@@ -68,7 +68,7 @@ fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Checks that function uses non-Rust ABI.
fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
if abi == Abi::Rust {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
let span = tcx.def_span(def_id);
tcx.emit_spanned_lint(
UNDEFINED_NAKED_FUNCTION_ABI,
@@ -211,7 +211,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
self.items.push((ItemKind::NonAsm, span));
}
- ExprKind::InlineAsm(ref asm) => {
+ ExprKind::InlineAsm(asm) => {
self.items.push((ItemKind::Asm, span));
self.check_inline_asm(asm, span);
}
@@ -282,13 +282,13 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> {
StmtKind::Local(..) => {
self.items.push((ItemKind::NonAsm, stmt.span));
}
- StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
+ StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
self.check_expr(expr, stmt.span);
}
}
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
- self.check_expr(&expr, expr.span);
+ self.check_expr(expr, expr.span);
}
}
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 650bb97c4..f46f831dd 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -115,7 +115,7 @@ impl<'tcx> ReachableContext<'tcx> {
return false;
};
- match self.tcx.hir().find_by_def_id(def_id) {
+ match self.tcx.opt_hir_node_by_def_id(def_id) {
Some(Node::Item(item)) => match item.kind {
hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()),
_ => false,
@@ -146,7 +146,7 @@ impl<'tcx> ReachableContext<'tcx> {
continue;
}
- if let Some(ref item) = self.tcx.hir().find_by_def_id(search_item) {
+ if let Some(ref item) = self.tcx.opt_hir_node_by_def_id(search_item) {
self.propagate_node(item, search_item);
}
}
@@ -260,9 +260,7 @@ impl<'tcx> ReachableContext<'tcx> {
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",
- self.tcx
- .hir()
- .node_to_string(self.tcx.hir().local_def_id_to_hir_id(search_item)),
+ self.tcx.hir().node_to_string(self.tcx.local_def_id_to_hir_id(search_item)),
node,
);
}
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 6a2498f3f..676622cef 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -9,11 +9,12 @@ use rustc_attr::{
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::query::Providers;
@@ -110,7 +111,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
) where
F: FnOnce(&mut Self),
{
- let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
+ let attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
let depr = attr::find_deprecation(self.tcx.sess, self.tcx.features(), attrs);
@@ -119,7 +120,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
is_deprecated = true;
if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
self.tcx.emit_spanned_lint(
USELESS_DEPRECATED,
hir_id,
@@ -157,9 +158,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
return;
}
- let stab = attr::find_stability(&self.tcx.sess, attrs, item_sp);
- let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item_sp);
- let body_stab = attr::find_body_stability(&self.tcx.sess, attrs);
+ let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
+ let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
+ let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
let mut const_span = None;
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
@@ -196,7 +197,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}
- if let Some((depr, span)) = &depr && depr.is_since_rustc_version() && stab.is_none() {
+ if let Some((depr, span)) = &depr
+ && depr.is_since_rustc_version()
+ && stab.is_none()
+ {
self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
}
@@ -717,8 +721,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
let features = self.tcx.features();
if features.staged_api {
let attrs = self.tcx.hir().attrs(item.hir_id());
- let stab = attr::find_stability(&self.tcx.sess, attrs, item.span);
- let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item.span);
+ let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
+ let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
// If this impl block has an #[unstable] attribute, give an
// error if all involved types and traits are stable, because
@@ -975,29 +979,27 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
tcx: TyCtxt<'tcx>,
remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
remaining_implications: &mut FxHashMap<Symbol, Symbol>,
- defined_features: &[(Symbol, Option<Symbol>)],
+ defined_features: &LibFeatures,
all_implications: &FxHashMap<Symbol, Symbol>,
) {
- for (feature, since) in defined_features {
- if let Some(since) = since
+ for (feature, since) in defined_features.to_vec() {
+ if let FeatureStability::AcceptedSince(since) = since
&& let Some(span) = remaining_lib_features.get(&feature)
{
// Warn if the user has enabled an already-stable lib feature.
if let Some(implies) = all_implications.get(&feature) {
- unnecessary_partially_stable_feature_lint(
- tcx, *span, *feature, *implies, *since,
- );
+ unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since);
} else {
- unnecessary_stable_feature_lint(tcx, *span, *feature, *since);
+ unnecessary_stable_feature_lint(tcx, *span, feature, since);
}
}
- remaining_lib_features.remove(feature);
+ remaining_lib_features.remove(&feature);
// `feature` is the feature doing the implying, but `implied_by` is the feature with
// the attribute that establishes this relationship. `implied_by` is guaranteed to be a
// feature defined in the local crate because `remaining_implications` is only the
// implications from this crate.
- remaining_implications.remove(feature);
+ remaining_implications.remove(&feature);
if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
break;
@@ -1006,12 +1008,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
// All local crate implications need to have the feature that implies it confirmed to exist.
- let mut remaining_implications =
- tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone();
+ let mut remaining_implications = tcx.stability_implications(LOCAL_CRATE).clone();
// We always collect the lib features declared in the current crate, even if there are
// no unknown features, because the collection also does feature attribute validation.
- let local_defined_features = tcx.lib_features(()).to_vec();
+ let local_defined_features = tcx.lib_features(LOCAL_CRATE);
if !remaining_lib_features.is_empty() || !remaining_implications.is_empty() {
// Loading the implications of all crates is unavoidable to be able to emit the partial
// stabilization diagnostic, but it can be avoided when there are no
@@ -1025,7 +1026,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
tcx,
&mut remaining_lib_features,
&mut remaining_implications,
- local_defined_features.as_slice(),
+ local_defined_features,
&all_implications,
);
@@ -1037,7 +1038,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
tcx,
&mut remaining_lib_features,
&mut remaining_implications,
- tcx.defined_lib_features(cnum).to_vec().as_slice(),
+ tcx.lib_features(cnum),
&all_implications,
);
}
@@ -1047,14 +1048,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature });
}
+ // We only use the hash map contents to emit errors, and the order of
+ // emitted errors do not affect query stability.
+ #[allow(rustc::potential_query_instability)]
for (implied_by, feature) in remaining_implications {
- let local_defined_features = tcx.lib_features(());
- let span = *local_defined_features
- .stable
+ let local_defined_features = tcx.lib_features(LOCAL_CRATE);
+ let span = local_defined_features
+ .stability
.get(&feature)
- .map(|(_, span)| span)
- .or_else(|| local_defined_features.unstable.get(&feature))
- .expect("feature that implied another does not exist");
+ .expect("feature that implied another does not exist")
+ .1;
tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
}
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 9a6fb88c2..b226c65e9 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -1,5 +1,7 @@
//! Validity checking for weak lang items
+use rustc_ast as ast;
+use rustc_ast::visit;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
@@ -11,7 +13,7 @@ use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}
/// Checks the crate for usage of weak lang items, returning a vector of all the
/// language items required by this crate, but not defined yet.
-pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
+pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems, krate: &ast::Crate) {
// These are never called by user code, they're generated by the compiler.
// They will never implicitly be added to the `missing` array unless we do
// so here.
@@ -22,24 +24,30 @@ pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
items.missing.push(LangItem::EhCatchTypeinfo);
}
- let crate_items = tcx.hir_crate_items(());
- for id in crate_items.foreign_items() {
- let attrs = tcx.hir().attrs(id.hir_id());
- if let Some((lang_item, _)) = lang_items::extract(attrs) {
+ visit::Visitor::visit_crate(&mut WeakLangItemVisitor { tcx, items }, krate);
+
+ verify(tcx, items);
+}
+
+struct WeakLangItemVisitor<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
+ items: &'a mut lang_items::LanguageItems,
+}
+
+impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_, '_> {
+ fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
+ if let Some((lang_item, _)) = lang_items::extract(&i.attrs) {
if let Some(item) = LangItem::from_name(lang_item)
&& item.is_weak()
{
- if items.get(item).is_none() {
- items.missing.push(item);
+ if self.items.get(item).is_none() {
+ self.items.missing.push(item);
}
} else {
- let span = tcx.def_span(id.owner_id);
- tcx.sess.emit_err(UnknownExternLangItem { span, lang_item });
+ self.tcx.sess.emit_err(UnknownExternLangItem { span: i.span, lang_item });
}
}
}
-
- verify(tcx, items);
}
fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {