From 6cad569a95c52ff9c9f4494d62512b4f57b3f722 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 8 Jun 2022 20:23:07 +0800 Subject: [PATCH 01/10] thir: wrap hir id of vars into local var id --- compiler/rustc_middle/src/thir.rs | 20 +++++++++++-- .../src/build/expr/as_place.rs | 28 +++++++++---------- .../rustc_mir_build/src/build/matches/mod.rs | 15 +++++----- compiler/rustc_mir_build/src/build/mod.rs | 15 +++++----- compiler/rustc_mir_build/src/thir/cx/expr.rs | 7 +++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 6 ++-- 6 files changed, 53 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index c3b79917dda91..120d09ee35382 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -191,6 +191,20 @@ pub enum StmtKind<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Expr<'_>, 104); +#[derive( + Clone, + Debug, + Copy, + PartialEq, + Eq, + Hash, + HashStable, + TyEncodable, + TyDecodable, + TypeFoldable +)] +pub struct LocalVarId(pub hir::HirId); + /// A THIR expression. #[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { @@ -332,7 +346,7 @@ pub enum ExprKind<'tcx> { }, /// A local variable. VarRef { - id: hir::HirId, + id: LocalVarId, }, /// Used to represent upvars mentioned in a closure/generator UpvarRef { @@ -340,7 +354,7 @@ pub enum ExprKind<'tcx> { closure_def_id: DefId, /// HirId of the root variable - var_hir_id: hir::HirId, + var_hir_id: LocalVarId, }, /// A borrow, e.g. `&arg`. Borrow { @@ -596,7 +610,7 @@ pub enum PatKind<'tcx> { mutability: Mutability, name: Symbol, mode: BindingMode, - var: hir::HirId, + var: LocalVarId, ty: Ty<'tcx>, subpattern: Option>, /// Is this the leftmost occurrence of the binding, i.e., is `var` the diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 981441fab040f..e77f5931dd65d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -3,8 +3,7 @@ use crate::build::expr::category::Category; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; -use rustc_hir::def_id::DefId; -use rustc_hir::HirId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::place::Projection as HirProjection; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; @@ -57,7 +56,7 @@ pub(crate) enum PlaceBase { /// figure out that it is captured until all the `Field` projections are applied. Upvar { /// HirId of the upvar - var_hir_id: HirId, + var_hir_id: LocalVarId, /// DefId of the closure closure_def_id: DefId, /// The trait closure implements, `Fn`, `FnMut`, `FnOnce` @@ -151,12 +150,12 @@ fn is_ancestor_or_same_capture( /// `ty::MinCaptureList` of the root variable `var_hir_id`. fn compute_capture_idx<'tcx>( closure_min_captures: &ty::RootVariableMinCaptureList<'tcx>, - var_hir_id: HirId, + var_hir_id: LocalVarId, root_var_idx: usize, ) -> usize { let mut res = 0; for (var_id, capture_list) in closure_min_captures { - if *var_id == var_hir_id { + if *var_id == var_hir_id.0 { res += root_var_idx; break; } else { @@ -176,12 +175,12 @@ fn compute_capture_idx<'tcx>( /// Returns None, when the ancestor is not found. fn find_capture_matching_projections<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, - var_hir_id: HirId, + var_hir_id: LocalVarId, closure_def_id: DefId, projections: &[PlaceElem<'tcx>], ) -> Option<(usize, &'a ty::CapturedPlace<'tcx>)> { let closure_min_captures = typeck_results.closure_min_captures.get(&closure_def_id)?; - let root_variable_min_captures = closure_min_captures.get(&var_hir_id)?; + let root_variable_min_captures = closure_min_captures.get(&var_hir_id.0)?; let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections); @@ -500,8 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, ), ExprKind::UpvarRef { closure_def_id, var_hir_id } => { - let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); - this.lower_captured_upvar(block, upvar_id) + this.lower_captured_upvar(block, closure_def_id.expect_local(), var_hir_id) } ExprKind::VarRef { id } => { @@ -627,11 +625,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_captured_upvar( &mut self, block: BasicBlock, - upvar_id: ty::UpvarId, + closure_expr_id: LocalDefId, + var_hir_id: LocalVarId, ) -> BlockAnd> { - let closure_ty = self - .typeck_results - .node_type(self.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id)); + let closure_ty = + self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_expr_id)); let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() { self.infcx.closure_kind(closure_substs).unwrap() @@ -641,8 +639,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; block.and(PlaceBuilder::from(PlaceBase::Upvar { - var_hir_id: upvar_id.var_path.hir_id, - closure_def_id: upvar_id.closure_expr_id.to_def_id(), + var_hir_id, + closure_def_id: closure_expr_id.to_def_id(), closure_kind, })) } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 43a84f69699aa..dc1860cb11297 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -14,7 +14,6 @@ use rustc_data_structures::{ fx::{FxHashSet, FxIndexMap, FxIndexSet}, stack::ensure_sufficient_stack, }; -use rustc_hir::HirId; use rustc_index::bit_set::BitSet; use rustc_middle::middle::region; use rustc_middle::mir::*; @@ -690,7 +689,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn storage_live_binding( &mut self, block: BasicBlock, - var: HirId, + var: LocalVarId, span: Span, for_guard: ForGuard, schedule_drop: bool, @@ -700,7 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); // Altough there is almost always scope for given variable in corner cases // like #92893 we might get variable with no scope. - if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) && schedule_drop{ + if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) && schedule_drop{ self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } Place::from(local_id) @@ -708,12 +707,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn schedule_drop_for_binding( &mut self, - var: HirId, + var: LocalVarId, span: Span, for_guard: ForGuard, ) { let local_id = self.var_local_id(var, for_guard); - if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) { + if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) { self.schedule_drop(span, region_scope, local_id, DropKind::Value); } } @@ -730,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability, Symbol, BindingMode, - HirId, + LocalVarId, Span, Ty<'tcx>, UserTypeProjections, @@ -917,7 +916,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>( struct Binding<'tcx> { span: Span, source: Place<'tcx>, - var_id: HirId, + var_id: LocalVarId, binding_mode: BindingMode, } @@ -2184,7 +2183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mutability: Mutability, name: Symbol, mode: BindingMode, - var_id: HirId, + var_id: LocalVarId, var_ty: Ty<'tcx>, user_ty: UserTypeProjections, has_guard: ArmHasGuard, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 4ae74433df63d..793066e43c3c7 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -4,11 +4,12 @@ use crate::build::scope::DropKind; use crate::thir::constant::parse_float; use crate::thir::pattern::pat_from_hir; use rustc_ast as ast; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{GeneratorKind, HirIdMap, Node}; +use rustc_hir::{GeneratorKind, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; @@ -16,7 +17,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::interpret::Allocation; use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar}; use rustc_middle::mir::*; -use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, PatKind, Thir}; +use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults}; use rustc_span::symbol::sym; @@ -445,7 +446,7 @@ struct Builder<'a, 'tcx> { /// Maps `HirId`s of variable bindings to the `Local`s created for them. /// (A match binding can have two locals; the 2nd is for the arm's guard.) - var_indices: HirIdMap, + var_indices: FxHashMap, local_decls: IndexVec>, canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, upvar_mutbls: Vec, @@ -455,11 +456,11 @@ struct Builder<'a, 'tcx> { } impl<'a, 'tcx> Builder<'a, 'tcx> { - fn is_bound_var_in_guard(&self, id: hir::HirId) -> bool { + fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool { self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id)) } - fn var_local_id(&self, id: hir::HirId, for_guard: ForGuard) -> Local { + fn var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local { self.var_indices[&id].local_id(for_guard) } } @@ -543,11 +544,11 @@ enum LocalsForNode { #[derive(Debug)] struct GuardFrameLocal { - id: hir::HirId, + id: LocalVarId, } impl GuardFrameLocal { - fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self { + fn new(id: LocalVarId, _binding_mode: BindingMode) -> Self { GuardFrameLocal { id } } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index bd9f599fff0a1..fb2f5861c6f03 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -903,9 +903,12 @@ impl<'tcx> Cx<'tcx> { ); if is_upvar { - ExprKind::UpvarRef { closure_def_id: self.body_owner, var_hir_id } + ExprKind::UpvarRef { + closure_def_id: self.body_owner, + var_hir_id: LocalVarId(var_hir_id), + } } else { - ExprKind::VarRef { id: var_hir_id } + ExprKind::VarRef { id: LocalVarId(var_hir_id) } } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e0dec1daf63c8..417cf0f89c412 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -19,7 +19,7 @@ use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput}; use rustc_middle::mir::{self, UserTypeProjection}; use rustc_middle::mir::{BorrowKind, Field, Mutability}; -use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange}; +use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::CanonicalUserTypeAnnotation; use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType}; @@ -288,7 +288,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { mutability, mode, name: ident.name, - var: id, + var: LocalVarId(id), ty: var_ty, subpattern: self.lower_opt_pattern(sub), is_primary: id == pat.hir_id, @@ -664,7 +664,7 @@ macro_rules! ClonePatternFoldableImpls { } ClonePatternFoldableImpls! { <'tcx> - Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>, + Span, Field, Mutability, Symbol, LocalVarId, usize, ty::Const<'tcx>, Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>, SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, UserTypeProjection, CanonicalUserTypeAnnotation<'tcx> From db14d81098a9eb4d46880fa905f71a204b994942 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 9 Jun 2022 12:52:03 -0700 Subject: [PATCH 02/10] Remove -sASSERTIONS=1 from wasm32_unknown_emscripten default link args This is a debug setting. We should only make debug builds if user requests a debug build. Currently this is inserted in release builds. Furthermore, it would be better to insert these settings in --pre-link-args because then it would be possible to override them if appropriate. Because these are inserted at the end, it is necessary to patch emscripten to remove them. --- compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index b34cac41d78ca..f02db4b0f3578 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -20,8 +20,6 @@ pub fn target() -> Target { "-s".into(), "ERROR_ON_UNDEFINED_SYMBOLS=1".into(), "-s".into(), - "ASSERTIONS=1".into(), - "-s".into(), "ABORTING_MALLOC=0".into(), "-Wl,--fatal-warnings".into(), ], From 9f305d3fa5a99661172de54dbf3300634e0e5dfc Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 9 Jun 2022 13:37:38 -0700 Subject: [PATCH 03/10] Remove ERROR_ON_UNDEFINED_SYMBOLS according to sbc100's comments --- compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index f02db4b0f3578..57a8dc1460751 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -17,8 +17,6 @@ pub fn target() -> Target { post_link_args.insert( LinkerFlavor::Em, vec![ - "-s".into(), - "ERROR_ON_UNDEFINED_SYMBOLS=1".into(), "-s".into(), "ABORTING_MALLOC=0".into(), "-Wl,--fatal-warnings".into(), From b32238ae6f788bf14b24c46e1e9224c21dd59846 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 9 Jun 2022 14:07:08 -0700 Subject: [PATCH 04/10] Clean up --- compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 57a8dc1460751..975051100b039 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -16,11 +16,7 @@ pub fn target() -> Target { let mut post_link_args = LinkArgs::new(); post_link_args.insert( LinkerFlavor::Em, - vec![ - "-s".into(), - "ABORTING_MALLOC=0".into(), - "-Wl,--fatal-warnings".into(), - ], + vec!["-sABORTING_MALLOC=0".into(), "-Wl,--fatal-warnings".into()], ); let opts = TargetOptions { From eb3c611e1d3829e05aec8f9887efa164ea2c6da5 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 9 Jun 2022 04:46:51 +0200 Subject: [PATCH 05/10] Never regard macro rules with compile_error! invocations as unused The very point of compile_error! is to never be reached, and one of the use cases of the macro, currently also listed as examples in the documentation of compile_error, is to create nicer errors for wrong macro invocations. Thus, we shuuld never warn about unused macro arms that contain invocations of compile_error. --- compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_expand/src/mbe/macro_rules.rs | 36 +++++++++++++++++-- .../rustc_resolve/src/build_reduced_graph.rs | 6 ++-- compiler/rustc_resolve/src/macros.rs | 2 +- .../unused-macro-rules-compile-error.rs | 27 ++++++++++++++ .../unused-macro-rules-compile-error.stderr | 26 ++++++++++++++ 6 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/lint/unused/unused-macro-rules-compile-error.rs create mode 100644 src/test/ui/lint/unused/unused-macro-rules-compile-error.stderr diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 7043ad5464530..86ff110eec183 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,4 +1,5 @@ #![allow(rustc::potential_query_instability)] +#![feature(array_windows)] #![feature(associated_type_bounds)] #![feature(associated_type_defaults)] #![feature(if_let_guard)] diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index b86304ba6b1b1..2a767646eafe6 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -380,7 +380,7 @@ pub fn compile_declarative_macro( features: &Features, def: &ast::Item, edition: Edition, -) -> (SyntaxExtension, Vec) { +) -> (SyntaxExtension, Vec<(usize, Span)>) { debug!("compile_declarative_macro: {:?}", def); let mk_syn_ext = |expander| { SyntaxExtension::new( @@ -542,8 +542,17 @@ pub fn compile_declarative_macro( // Compute the spans of the macro rules // We only take the span of the lhs here, // so that the spans of created warnings are smaller. + // Also, we are only interested in non-foreign macros. let rule_spans = if def.id != DUMMY_NODE_ID { - lhses.iter().map(|lhs| lhs.span()).collect::>() + lhses + .iter() + .zip(rhses.iter()) + .enumerate() + // If the rhs contains an invocation like compile_error!, + // don't consider the rule for the unused rule lint. + .filter(|(_idx, (_lhs, rhs))| !has_compile_error_macro(rhs)) + .map(|(idx, (lhs, _rhs))| (idx, lhs.span())) + .collect::>() } else { Vec::new() }; @@ -651,6 +660,29 @@ fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) err == sess.span_diagnostic.err_count() } +fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { + match rhs { + mbe::TokenTree::Delimited(_sp, d) => { + let has_compile_error = d.tts.array_windows::<3>().any(|[ident, bang, args]| { + if let mbe::TokenTree::Token(ident) = ident && + let TokenKind::Ident(ident, _) = ident.kind && + ident == sym::compile_error && + let mbe::TokenTree::Token(bang) = bang && + let TokenKind::Not = bang.kind && + let mbe::TokenTree::Delimited(_, del) = args && + del.delim != Delimiter::Invisible + { + true + } else { + false + } + }); + if has_compile_error { true } else { d.tts.iter().any(has_compile_error_macro) } + } + _ => false, + } +} + // `The FirstSets` for a matcher is a mapping from subsequences in the // matcher to the FIRST set for that subsequence. // diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 20d9123e411ab..f8fa7a0941d00 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1220,12 +1220,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ident: Ident, def_id: LocalDefId, node_id: NodeId, - rule_spans: &[Span], + rule_spans: &[(usize, Span)], ) { if !ident.as_str().starts_with('_') { self.r.unused_macros.insert(def_id, (node_id, ident)); - for (rule_i, rule_span) in rule_spans.iter().enumerate() { - self.r.unused_macro_rules.insert((def_id, rule_i), (ident, *rule_span)); + for (rule_i, rule_span) in rule_spans.iter() { + self.r.unused_macro_rules.insert((def_id, *rule_i), (ident, *rule_span)); } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2e2d3674560e8..3fb34cdcd9bd9 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -870,7 +870,7 @@ impl<'a> Resolver<'a> { &mut self, item: &ast::Item, edition: Edition, - ) -> (SyntaxExtension, Vec) { + ) -> (SyntaxExtension, Vec<(usize, Span)>) { let (mut result, mut rule_spans) = compile_declarative_macro( &self.session, self.session.features_untracked(), diff --git a/src/test/ui/lint/unused/unused-macro-rules-compile-error.rs b/src/test/ui/lint/unused/unused-macro-rules-compile-error.rs new file mode 100644 index 0000000000000..4d51db89bc0b3 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-compile-error.rs @@ -0,0 +1,27 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +macro_rules! num { + (one) => { 1 }; + // Most simple (and common) case + (two) => { compile_error!("foo"); }; + // Some nested use + (two_) => { foo(compile_error!("foo")); }; + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// compile_error not used as a macro invocation +macro_rules! num2 { + (one) => { 1 }; + // Only identifier present + (two) => { fn compile_error() {} }; //~ ERROR: rule of macro + // Only identifier and bang present + (two_) => { compile_error! }; //~ ERROR: rule of macro + (three) => { 3 }; +} +const _NUM2: u8 = num2!(one) + num2!(three); + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-macro-rules-compile-error.stderr b/src/test/ui/lint/unused/unused-macro-rules-compile-error.stderr new file mode 100644 index 0000000000000..76af8c967db1e --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-compile-error.stderr @@ -0,0 +1,26 @@ +error: 5th rule of macro `num` is never used + --> $DIR/unused-macro-rules-compile-error.rs:12:5 + | +LL | (four) => { 4 }; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-compile-error.rs:1:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 3rd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:22:5 + | +LL | (two_) => { compile_error! }; + | ^^^^^^ + +error: 2nd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:20:5 + | +LL | (two) => { fn compile_error() {} }; + | ^^^^^ + +error: aborting due to 3 previous errors + From 777e136f4cd811bec0c5dabd47e1ae4285f25ca2 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 9 Jun 2022 23:34:06 +0200 Subject: [PATCH 06/10] Suppress the unused_macro_rules lint if malformed rules are encountered Prior to this commit, if a macro had any malformed rules, all rules would be reported as unused, regardless of whether they were used or not. So we just turn off unused rule checking completely for macros with malformed rules. --- compiler/rustc_expand/src/mbe/macro_rules.rs | 10 ++++++---- .../lint/unused/unused-macro-rules-malformed-rule.rs | 11 +++++++++++ .../unused/unused-macro-rules-malformed-rule.stderr | 8 ++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/unused/unused-macro-rules-malformed-rule.rs create mode 100644 src/test/ui/lint/unused/unused-macro-rules-malformed-rule.stderr diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 2a767646eafe6..04af1eaf67b6d 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -539,11 +539,11 @@ pub fn compile_declarative_macro( None => {} } - // Compute the spans of the macro rules - // We only take the span of the lhs here, - // so that the spans of created warnings are smaller. + // Compute the spans of the macro rules for unused rule linting. + // To avoid warning noise, only consider the rules of this + // macro for the lint, if all rules are valid. // Also, we are only interested in non-foreign macros. - let rule_spans = if def.id != DUMMY_NODE_ID { + let rule_spans = if valid && def.id != DUMMY_NODE_ID { lhses .iter() .zip(rhses.iter()) @@ -551,6 +551,8 @@ pub fn compile_declarative_macro( // If the rhs contains an invocation like compile_error!, // don't consider the rule for the unused rule lint. .filter(|(_idx, (_lhs, rhs))| !has_compile_error_macro(rhs)) + // We only take the span of the lhs here, + // so that the spans of created warnings are smaller. .map(|(idx, (lhs, _rhs))| (idx, lhs.span())) .collect::>() } else { diff --git a/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.rs b/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.rs new file mode 100644 index 0000000000000..a826026ec405c --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.rs @@ -0,0 +1,11 @@ +#![deny(unused_macro_rules)] + +macro_rules! foo { + (v) => {}; + (w) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + foo!(v); +} diff --git a/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.stderr b/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.stderr new file mode 100644 index 0000000000000..797c867103f03 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-malformed-rule.stderr @@ -0,0 +1,8 @@ +error: macro rhs must be delimited + --> $DIR/unused-macro-rules-malformed-rule.rs:6:11 + | +LL | () => 0; + | ^ + +error: aborting due to previous error + From 787e24cdfd5bef5136540287dd918e48b8a645db Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 9 Jun 2022 23:46:40 +0200 Subject: [PATCH 07/10] Test that the unused_macros lint works correctly if rules are malformed The unused_macro_rules lint had a bug where it would regard all rules of a macro as unused if one rule were malformed. This bug doesn't exist with the unused_macros lint. To ensure it doesn't appear in the future, we add a test for it. --- .../unused/unused-macros-malformed-rule.rs | 15 +++++++++++ .../unused-macros-malformed-rule.stderr | 26 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/test/ui/lint/unused/unused-macros-malformed-rule.rs create mode 100644 src/test/ui/lint/unused/unused-macros-malformed-rule.stderr diff --git a/src/test/ui/lint/unused/unused-macros-malformed-rule.rs b/src/test/ui/lint/unused/unused-macros-malformed-rule.rs new file mode 100644 index 0000000000000..d4c35fad9b0f0 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macros-malformed-rule.rs @@ -0,0 +1,15 @@ +#![deny(unused_macros)] + +macro_rules! foo { //~ ERROR: unused macro definition + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +macro_rules! bar { + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + bar!(v); +} diff --git a/src/test/ui/lint/unused/unused-macros-malformed-rule.stderr b/src/test/ui/lint/unused/unused-macros-malformed-rule.stderr new file mode 100644 index 0000000000000..9a880dccfbf6d --- /dev/null +++ b/src/test/ui/lint/unused/unused-macros-malformed-rule.stderr @@ -0,0 +1,26 @@ +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:5:11 + | +LL | () => 0; + | ^ + +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:10:11 + | +LL | () => 0; + | ^ + +error: unused macro definition: `foo` + --> $DIR/unused-macros-malformed-rule.rs:3:14 + | +LL | macro_rules! foo { + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-malformed-rule.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + From 28ca3bdeb278cdf0d8b1a87777183689da6f9509 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Jun 2022 11:57:53 +0200 Subject: [PATCH 08/10] Use relative links instead of linking to doc.rust-lang.org when possible --- library/core/src/hash/sip.rs | 2 +- library/core/src/mem/maybe_uninit.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 97e32ca77db82..81bf1dfdf4510 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -38,7 +38,7 @@ struct SipHasher24 { /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ /// hashing. This lets you key your hash tables from a strong RNG, such as -/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html). +/// [`rand::os::OsRng`](https://docs.rs/rand/latest/rand/rngs/struct.OsRng.html). /// /// Although the SipHash algorithm is considered to be generally strong, /// it is not intended for cryptographic purposes. As such, all diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index cac7f435573a5..b4ea536083392 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -865,7 +865,7 @@ impl MaybeUninit { /// /// For instance, you cannot [`Read`] into an uninitialized buffer: /// - /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html + /// [`Read`]: ../../std/io/trait.Read.html /// /// ```rust,no_run /// use std::{io, mem::MaybeUninit}; From 20e166eab45a76ee127e24f196ecdac6378b0e0a Mon Sep 17 00:00:00 2001 From: CorinJG Date: Fri, 10 Jun 2022 11:25:47 +0100 Subject: [PATCH 09/10] Fixed several error_codes/Exxxx.md messages which used UpperCamelCase instead of snake_case for module names --- .../rustc_error_codes/src/error_codes/E0451.md | 12 ++++++------ .../rustc_error_codes/src/error_codes/E0574.md | 10 +++++----- .../rustc_error_codes/src/error_codes/E0577.md | 12 ++++++------ .../rustc_error_codes/src/error_codes/E0603.md | 10 +++++----- .../rustc_error_codes/src/error_codes/E0742.md | 16 ++++++++-------- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0451.md b/compiler/rustc_error_codes/src/error_codes/E0451.md index 821073fe16eae..a12378a206de2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0451.md +++ b/compiler/rustc_error_codes/src/error_codes/E0451.md @@ -3,14 +3,14 @@ A struct constructor with private fields was invoked. Erroneous code example: ```compile_fail,E0451 -mod Bar { +mod bar { pub struct Foo { pub a: isize, b: isize, } } -let f = Bar::Foo{ a: 0, b: 0 }; // error: field `b` of struct `Bar::Foo` +let f = bar::Foo{ a: 0, b: 0 }; // error: field `b` of struct `bar::Foo` // is private ``` @@ -18,20 +18,20 @@ To fix this error, please ensure that all the fields of the struct are public, or implement a function for easy instantiation. Examples: ``` -mod Bar { +mod bar { pub struct Foo { pub a: isize, pub b: isize, // we set `b` field public } } -let f = Bar::Foo{ a: 0, b: 0 }; // ok! +let f = bar::Foo{ a: 0, b: 0 }; // ok! ``` Or: ``` -mod Bar { +mod bar { pub struct Foo { pub a: isize, b: isize, // still private @@ -44,5 +44,5 @@ mod Bar { } } -let f = Bar::Foo::new(); // ok! +let f = bar::Foo::new(); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0574.md b/compiler/rustc_error_codes/src/error_codes/E0574.md index 8154d5b782e36..4881f61d0bc48 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0574.md +++ b/compiler/rustc_error_codes/src/error_codes/E0574.md @@ -4,9 +4,9 @@ expected. Erroneous code example: ```compile_fail,E0574 -mod Mordor {} +mod mordor {} -let sauron = Mordor { x: () }; // error! +let sauron = mordor { x: () }; // error! enum Jak { Daxter { i: isize }, @@ -19,17 +19,17 @@ match eco { ``` In all these errors, a type was expected. For example, in the first error, -we tried to instantiate the `Mordor` module, which is impossible. If you want +we tried to instantiate the `mordor` module, which is impossible. If you want to instantiate a type inside a module, you can do it as follow: ``` -mod Mordor { +mod mordor { pub struct TheRing { pub x: usize, } } -let sauron = Mordor::TheRing { x: 1 }; // ok! +let sauron = mordor::TheRing { x: 1 }; // ok! ``` In the second error, we tried to bind the `Jak` enum directly, which is not diff --git a/compiler/rustc_error_codes/src/error_codes/E0577.md b/compiler/rustc_error_codes/src/error_codes/E0577.md index 1feb9c0acf364..579a8b596e3a6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0577.md +++ b/compiler/rustc_error_codes/src/error_codes/E0577.md @@ -3,21 +3,21 @@ Something other than a module was found in visibility scope. Erroneous code example: ```compile_fail,E0577,edition2018 -pub struct Sea; +pub struct sea; -pub (in crate::Sea) struct Shark; // error! +pub (in crate::sea) struct Shark; // error! fn main() {} ``` -`Sea` is not a module, therefore it is invalid to use it in a visibility path. -To fix this error we need to ensure `Sea` is a module. +`sea` is not a module, therefore it is invalid to use it in a visibility path. +To fix this error we need to ensure `sea` is a module. Please note that the visibility scope can only be applied on ancestors! ```edition2018 -pub mod Sea { - pub (in crate::Sea) struct Shark; // ok! +pub mod sea { + pub (in crate::sea) struct Shark; // ok! } fn main() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0603.md b/compiler/rustc_error_codes/src/error_codes/E0603.md index 69fefce3908fd..eb293118acc86 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0603.md +++ b/compiler/rustc_error_codes/src/error_codes/E0603.md @@ -3,13 +3,13 @@ A private item was used outside its scope. Erroneous code example: ```compile_fail,E0603 -mod SomeModule { +mod foo { const PRIVATE: u32 = 0x_a_bad_1dea_u32; // This const is private, so we // can't use it outside of the - // `SomeModule` module. + // `foo` module. } -println!("const value: {}", SomeModule::PRIVATE); // error: constant `PRIVATE` +println!("const value: {}", foo::PRIVATE); // error: constant `PRIVATE` // is private ``` @@ -17,10 +17,10 @@ In order to fix this error, you need to make the item public by using the `pub` keyword. Example: ``` -mod SomeModule { +mod foo { pub const PRIVATE: u32 = 0x_a_bad_1dea_u32; // We set it public by using the // `pub` keyword. } -println!("const value: {}", SomeModule::PRIVATE); // ok! +println!("const value: {}", foo::PRIVATE); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0742.md b/compiler/rustc_error_codes/src/error_codes/E0742.md index fed9f1f4cee9c..e10c1639dd38a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0742.md +++ b/compiler/rustc_error_codes/src/error_codes/E0742.md @@ -4,18 +4,18 @@ item. Erroneous code example: ```compile_fail,E0742,edition2018 -pub mod Sea {} +pub mod sea {} -pub (in crate::Sea) struct Shark; // error! +pub (in crate::sea) struct Shark; // error! fn main() {} ``` -To fix this error, we need to move the `Shark` struct inside the `Sea` module: +To fix this error, we need to move the `Shark` struct inside the `sea` module: ```edition2018 -pub mod Sea { - pub (in crate::Sea) struct Shark; // ok! +pub mod sea { + pub (in crate::sea) struct Shark; // ok! } fn main() {} @@ -25,9 +25,9 @@ Of course, you can do it as long as the module you're referring to is an ancestor: ```edition2018 -pub mod Earth { - pub mod Sea { - pub (in crate::Earth) struct Shark; // ok! +pub mod earth { + pub mod sea { + pub (in crate::earth) struct Shark; // ok! } } From 6227d89d6aad396a1ff5a7a9bf390baa4fad93f1 Mon Sep 17 00:00:00 2001 From: CorinJG Date: Fri, 10 Jun 2022 14:21:40 +0100 Subject: [PATCH 10/10] E0577 fixed Sea struct CamelCase/sea module snake_case --- compiler/rustc_error_codes/src/error_codes/E0577.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0577.md b/compiler/rustc_error_codes/src/error_codes/E0577.md index 579a8b596e3a6..eba2d3b14175b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0577.md +++ b/compiler/rustc_error_codes/src/error_codes/E0577.md @@ -3,14 +3,14 @@ Something other than a module was found in visibility scope. Erroneous code example: ```compile_fail,E0577,edition2018 -pub struct sea; +pub struct Sea; -pub (in crate::sea) struct Shark; // error! +pub (in crate::Sea) struct Shark; // error! fn main() {} ``` -`sea` is not a module, therefore it is invalid to use it in a visibility path. +`Sea` is not a module, therefore it is invalid to use it in a visibility path. To fix this error we need to ensure `sea` is a module. Please note that the visibility scope can only be applied on ancestors!