diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_passes | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r-- | compiler/rustc_passes/Cargo.toml | 3 | ||||
-rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 66 | ||||
-rw-r--r-- | compiler/rustc_passes/src/check_const.rs | 13 | ||||
-rw-r--r-- | compiler/rustc_passes/src/dead.rs | 34 | ||||
-rw-r--r-- | compiler/rustc_passes/src/entry.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_passes/src/errors.rs | 29 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_id_validator.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_stats.rs | 23 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lang_items.rs | 375 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lib.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lib_features.rs | 73 | ||||
-rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 108 | ||||
-rw-r--r-- | compiler/rustc_passes/src/loops.rs | 25 | ||||
-rw-r--r-- | compiler/rustc_passes/src/naked_functions.rs | 10 | ||||
-rw-r--r-- | compiler/rustc_passes/src/reachable.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_passes/src/stability.rs | 61 | ||||
-rw-r--r-- | compiler/rustc_passes/src/weak_lang_items.rs | 30 |
17 files changed, 491 insertions, 384 deletions
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 40c3811e0..80e6c104b 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.10.1" +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } @@ -19,7 +19,6 @@ rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } 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) { |