diff --git a/Cargo.lock b/Cargo.lock index 980b362c0509a..961a3ba9f19cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3688,6 +3688,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_lexer", + "rustc_lint_defs", "rustc_parse", "rustc_parse_format", "rustc_session", diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 952e18c1e570d..4a9904891ecad 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -84,7 +84,7 @@ pub enum LocalsStateAtExit { } impl LocalsStateAtExit { - fn build( + fn build<'tcx>( locals_are_invalidated_at_exit: bool, body: &Body<'tcx>, move_data: &MoveData<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 881ebed602946..96326ef2d5a07 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -31,7 +31,7 @@ enum UniverseInfoInner<'tcx> { Other, } -impl UniverseInfo<'tcx> { +impl<'tcx> UniverseInfo<'tcx> { crate fn other() -> UniverseInfo<'tcx> { UniverseInfo(UniverseInfoInner::Other) } @@ -191,7 +191,7 @@ struct PredicateQuery<'tcx> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); @@ -231,7 +231,7 @@ struct NormalizeQuery<'tcx, T> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> +impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> where T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, { @@ -291,7 +291,7 @@ struct AscribeUserTypeQuery<'tcx> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 98c619cdd291c..ab9ecec9715d9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1598,8 +1598,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, mpi: MovePathIndex, ) -> (Vec, Vec) { - fn predecessor_locations( - body: &'a mir::Body<'tcx>, + fn predecessor_locations<'a>( + body: &'a mir::Body<'_>, location: Location, ) -> impl Iterator + 'a { if location.statement_index == 0 { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index dec1940ace881..46c85dd6d35e1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -409,7 +409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Add a note that a type does not implement `Copy` pub(super) fn note_type_does_not_implement_copy( &self, - err: &mut DiagnosticBuilder<'a>, + err: &mut DiagnosticBuilder<'_>, place_desc: &str, ty: Ty<'tcx>, span: Option, @@ -733,7 +733,7 @@ pub(super) enum BorrowedContentSource<'tcx> { OverloadedIndex(Ty<'tcx>), } -impl BorrowedContentSource<'tcx> { +impl<'tcx> BorrowedContentSource<'tcx> { pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String { match *self { BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index b4821ee36e0a3..0434c1ba59a10 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -747,7 +747,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option { + fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option { match hir_map.find(id) { Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { @@ -1066,7 +1066,7 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool { /// LL | s: &'a String /// | ---------- use `&'a mut String` here to make mutable /// ``` -fn annotate_struct_field( +fn annotate_struct_field<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, field: &mir::Field, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4136adcf65e08..63ffcb3ec4587 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -3,7 +3,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index f22d355e61344..0fe44328fd9f1 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -53,7 +53,7 @@ rustc_index::newtype_index! { } } -impl Default for MemberConstraintSet<'tcx, ty::RegionVid> { +impl Default for MemberConstraintSet<'_, ty::RegionVid> { fn default() -> Self { Self { first_constraints: Default::default(), @@ -97,7 +97,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> { } } -impl MemberConstraintSet<'tcx, R1> +impl<'tcx, R1> MemberConstraintSet<'tcx, R1> where R1: Copy + Hash + Eq, { @@ -140,7 +140,7 @@ where } } -impl MemberConstraintSet<'tcx, R> +impl MemberConstraintSet<'_, R> where R: Copy + Hash + Eq, { diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index d5d00b467eeed..b2c8dfc82c206 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -141,7 +141,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. -pub(crate) fn is_upvar_field_projection( +pub(crate) fn is_upvar_field_projection<'tcx>( tcx: TyCtxt<'tcx>, upvars: &[Upvar<'tcx>], place_ref: PlaceRef<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 8d97c3cbb0b0e..fec6bdf314b1d 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -58,7 +58,7 @@ crate struct CreateResult<'tcx> { crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } -crate fn create( +crate fn create<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, implicit_region_bound: Option>, @@ -81,7 +81,7 @@ crate fn create( .create() } -impl UniversalRegionRelations<'tcx> { +impl UniversalRegionRelations<'_> { /// Records in the `outlives_relation` (and /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the /// builder below. @@ -110,7 +110,7 @@ impl UniversalRegionRelations<'tcx> { /// outlives `fr` and (b) is not local. /// /// (*) If there are multiple competing choices, we return all of them. - crate fn non_local_upper_bounds(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { + crate fn non_local_upper_bounds<'a>(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { debug!("non_local_upper_bound(fr={:?})", fr); let res = self.non_local_bounds(&self.inverse_outlives, fr); assert!(!res.is_empty(), "can't find an upper bound!?"); @@ -232,7 +232,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> { region_bound_pairs: RegionBoundPairs<'tcx>, } -impl UniversalRegionRelationsBuilder<'cx, 'tcx> { +impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { crate fn create(mut self) -> CreateResult<'tcx> { let unnormalized_input_output_tys = self .universal_regions diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 8b74abd94c077..dd23683fae8de 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -152,7 +152,7 @@ impl LocalUseMapBuild<'_> { } } -impl Visitor<'tcx> for LocalUseMapBuild<'_> { +impl Visitor<'_> for LocalUseMapBuild<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { if self.locals_with_use_data[local] { match def_use::categorize(context) { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 1e712354d6a83..f18fe1f43d4da 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -74,7 +74,7 @@ pub(super) fn generate<'mir, 'tcx>( // to compute whether a variable `X` is live if that variable contains // some region `R` in its type where `R` is not known to outlive a free // region (i.e., where `R` may be valid for just a subset of the fn body). -fn compute_live_locals( +fn compute_live_locals<'tcx>( tcx: TyCtxt<'tcx>, free_regions: &FxHashSet, body: &Body<'tcx>, @@ -104,7 +104,7 @@ fn compute_live_locals( /// regions. For these regions, we do not need to compute /// liveness, since the outlives constraints will ensure that they /// are live over the whole fn body anyhow. -fn regions_that_outlive_free_regions( +fn regions_that_outlive_free_regions<'tcx>( num_region_vars: usize, universal_regions: &UniversalRegions<'tcx>, constraint_set: &OutlivesConstraintSet<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 79ab8b713f95d..ee067c4872f67 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -53,7 +53,7 @@ impl UseFactsExtractor<'_> { } } -impl Visitor<'tcx> for UseFactsExtractor<'_> { +impl Visitor<'_> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match def_use::categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -63,7 +63,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> { } } - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) { self.super_place(place, context, location); match context { PlaceContext::NonMutatingUse(_) => { @@ -82,7 +82,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> { } } -pub(super) fn populate_access_facts( +pub(super) fn populate_access_facts<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, location_table: &LocationTable, @@ -123,7 +123,7 @@ pub(super) fn populate_access_facts( // For every potentially drop()-touched region `region` in `local`'s type // (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. -pub(super) fn add_drop_of_var_derefs_origin( +pub(super) fn add_drop_of_var_derefs_origin<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 73c284071d5cc..0969b9a508f1d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -34,7 +34,7 @@ use crate::{ /// DROP-LIVE set are to the liveness sets for regions found in the /// `dropck_outlives` result of the variable's type (in particular, /// this respects `#[may_dangle]` annotations). -pub(super) fn trace( +pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, @@ -119,7 +119,7 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> { stack: Vec, } -impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { +impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { @@ -418,7 +418,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } -impl LivenessContext<'_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 195ed13a02705..872a432144704 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -945,7 +945,7 @@ crate struct MirTypeckRegionConstraints<'tcx> { crate type_tests: Vec>, } -impl MirTypeckRegionConstraints<'tcx> { +impl<'tcx> MirTypeckRegionConstraints<'tcx> { fn placeholder_region( &mut self, infcx: &InferCtxt<'_, 'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 415d1abaa8b08..cc3fe0a123c55 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -51,7 +51,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { universe_info: UniverseInfo<'tcx>, } -impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { +impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, @@ -62,7 +62,7 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } } -impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { +impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index fd34f947f72c0..9031c3b2ecfbb 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -15,6 +15,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } +rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 5933a49ea5803..31086a2acf8cc 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -1,4 +1,4 @@ -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; @@ -25,6 +25,7 @@ crate fn expand( annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval); vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)] } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index d2629926b51da..c08b141b557ca 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -1,6 +1,6 @@ /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::attr; @@ -27,6 +27,7 @@ pub fn expand_test_case( anno_item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::test_case); + warn_on_duplicate_attribute(&ecx, &anno_item, sym::test_case); if !ecx.ecfg.should_test { return vec![]; @@ -55,6 +56,7 @@ pub fn expand_test( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::test); + warn_on_duplicate_attribute(&cx, &item, sym::test); expand_test_or_bench(cx, attr_sp, item, false) } @@ -65,6 +67,7 @@ pub fn expand_bench( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::bench); + warn_on_duplicate_attribute(&cx, &item, sym::bench); expand_test_or_bench(cx, attr_sp, item, true) } diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 01ea80c4c8a06..527fe50eff0ce 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,6 +1,7 @@ -use rustc_ast::MetaItem; -use rustc_expand::base::ExtCtxt; +use rustc_ast::{Attribute, MetaItem}; +use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_feature::AttributeTemplate; +use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; use rustc_parse::validate_attr; use rustc_span::Symbol; @@ -10,3 +11,33 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na let attr = ecx.attribute(meta_item.clone()); validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template); } + +/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when +/// an attribute may have been mistakenly duplicated. +pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { + let attrs: Option<&[Attribute]> = match item { + Annotatable::Item(item) => Some(&item.attrs), + Annotatable::TraitItem(item) => Some(&item.attrs), + Annotatable::ImplItem(item) => Some(&item.attrs), + Annotatable::ForeignItem(item) => Some(&item.attrs), + Annotatable::Expr(expr) => Some(&expr.attrs), + Annotatable::Arm(arm) => Some(&arm.attrs), + Annotatable::ExprField(field) => Some(&field.attrs), + Annotatable::PatField(field) => Some(&field.attrs), + Annotatable::GenericParam(param) => Some(¶m.attrs), + Annotatable::Param(param) => Some(¶m.attrs), + Annotatable::FieldDef(def) => Some(&def.attrs), + Annotatable::Variant(variant) => Some(&variant.attrs), + _ => None, + }; + if let Some(attrs) = attrs { + if let Some(attr) = ecx.sess.find_by_name(attrs, name) { + ecx.parse_sess().buffer_lint( + DUPLICATE_MACRO_ATTRIBUTES, + attr.span, + ecx.current_expansion.lint_node_id, + "duplicated attribute", + ); + } + } +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8a8e391744856..27a06943cbc25 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3066,6 +3066,7 @@ declare_lint_pass! { TEXT_DIRECTION_CODEPOINT_IN_COMMENT, DEREF_INTO_DYN_SUPERTRAIT, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + DUPLICATE_MACRO_ATTRIBUTES, ] } @@ -3603,3 +3604,32 @@ declare_lint! { reference: "issue #89460 ", }; } + +declare_lint! { + /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro + /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test` + /// and `test_case`. + /// + /// ### Example + /// + /// ```rust,ignore (needs --test) + /// #[test] + /// #[test] + /// fn foo() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A duplicated attribute may erroneously originate from a copy-paste and the effect of it + /// being duplicated may not be obvious or desireable. + /// + /// For instance, doubling the `#[test]` attributes registers the test to be run twice with no + /// change to its environment. + /// + /// [issue #90979]: https://github.com/rust-lang/rust/issues/90979 + pub DUPLICATE_MACRO_ATTRIBUTES, + Warn, + "duplicated attribute" +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3154859bc651b..7500df896e971 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -870,8 +870,9 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) && tcx.sess.opts.output_types.should_codegen(); - // Only check the presence of the `const` modifier. - let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()); + // The function has a `const` modifier or is annotated with `default_method_body_is_const`. + let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) + || tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const); let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; (is_const_fn, needs_inline || always_encode_mir) } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 20b6453990d75..f577f102e8db2 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -64,7 +64,7 @@ impl ManuallyDrop { /// ``` #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value } @@ -82,7 +82,7 @@ impl ManuallyDrop { /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { slot.value diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index da88c8c9261b4..210a9ec718315 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -417,6 +417,33 @@ impl Error { Self::_new(kind, error.into()) } + /// Creates a new I/O error from an arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. It is a shortcut for [`Error::new`] + /// with [`ErrorKind::Other`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_error_other)] + /// + /// use std::io::Error; + /// + /// // errors can be created from strings + /// let custom_error = Error::other("oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::other(custom_error); + /// ``` + #[unstable(feature = "io_error_other", issue = "91946")] + pub fn other(error: E) -> Error + where + E: Into>, + { + Self::_new(ErrorKind::Other, error.into()) + } + fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } } diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index de6b52a5e001c..2f7c57bcdc461 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -53,7 +53,7 @@ files_to_extract=( for lib in c cxxrt gcc_s m thr util; do files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*") done -for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs index 4e146a07d154a..3410f46e2a8d2 100644 --- a/src/librustdoc/passes/bare_urls.rs +++ b/src/librustdoc/passes/bare_urls.rs @@ -1,3 +1,5 @@ +//! Detects links that are not linkified, e.g., in Markdown such as `Go to https://example.com/.` +//! Suggests wrapping the link with angle brackets: `Go to .` to linkify it. use super::Pass; use crate::clean::*; use crate::core::DocContext; diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 85542ebd9ac55..6111c982de922 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -1,3 +1,4 @@ +//! Calculates information used for the --show-coverage flag. use crate::clean; use crate::core::DocContext; use crate::html::markdown::{find_testable_code, ErrorCodes}; diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index fd2ab0dc97cb2..a50bf558bf3d1 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,3 +1,4 @@ +//! Validates syntax inside Rust code blocks (\`\`\`rust). use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler}; use rustc_middle::lint::LintDiagnosticBuilder; diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 7d3010cf3325b..b86ec8abefaae 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -1,3 +1,5 @@ +//! Looks for items missing (or incorrectly having) doctests. +//! //! This pass is overloaded and runs two different lints. //! //! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests. diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 8524f872ca364..baa0c7595eb86 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -1,3 +1,6 @@ +//! Collects trait impls for each item in the crate. For example, if a crate +//! defines a struct that implements a trait, this pass will note that the +//! struct implements that trait. use super::Pass; use crate::clean::*; use crate::core::DocContext; diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 56b222d893262..f7a9a0899e390 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -1,3 +1,4 @@ +//! Detects invalid HTML (like an unclosed ``) in doc comments. use super::Pass; use crate::clean::*; use crate::core::DocContext; diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index f5a362bfbe8c6..d3df2d2794b42 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -1,3 +1,4 @@ +//! Propagates [`#[doc(cfg(...))]`](https://github.com/rust-lang/rust/issues/43781) to child items. use std::sync::Arc; use crate::clean::cfg::Cfg; diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 0aedbda35e9a8..e63534659add7 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -1,3 +1,4 @@ +//! Strip all doc(hidden) items from the output. use rustc_span::symbol::sym; use std::mem; diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index 63869324cb8d2..21ce9ae7a28e1 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -1,3 +1,5 @@ +//! Strips all private import statements (use, extern crate) from a +//! crate. use crate::clean; use crate::core::DocContext; use crate::fold::DocFolder; diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index dfdba2a4b3666..c6b5bec4692dc 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -1,3 +1,5 @@ +//! Strip all private items from the output. Additionally implies strip_priv_imports. +//! Basically, the goal is to remove items that are not relevant for public documentation. use crate::clean::{self, ItemIdSet}; use crate::core::DocContext; use crate::fold::DocFolder; diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 74a9a2da06d36..675443b48a206 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -1,3 +1,4 @@ +//! A collection of utility functions for the `strip_*` passes. use rustc_hir::def_id::DefId; use rustc_middle::middle::privacy::AccessLevels; use std::mem; diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 97f4f941e0686..6cac31d2f90dc 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -1,3 +1,16 @@ +//! Removes excess indentation on comments in order for the Markdown +//! to be parsed correctly. This is necessary because the convention for +//! writing documentation is to provide a space between the /// or //! marker +//! and the doc text, but Markdown is whitespace-sensitive. For example, +//! a block of text with four-space indentation is parsed as a code block, +//! so if we didn't unindent comments, these list items +//! +//! /// A list: +//! /// +//! /// - Foo +//! /// - Bar +//! +//! would be parsed as if they were in a code block, which is likely not what the user intended. use std::cmp; use rustc_span::symbol::kw; diff --git a/src/test/ui/attributes/duplicated-attributes.rs b/src/test/ui/attributes/duplicated-attributes.rs new file mode 100644 index 0000000000000..84a5abcf8b4bc --- /dev/null +++ b/src/test/ui/attributes/duplicated-attributes.rs @@ -0,0 +1,41 @@ +// Test that, if an item is annotated with a builtin attribute more than once, a warning is +// emitted. +// Tests https://github.com/rust-lang/rust/issues/90979 + +// check-pass +// compile-flags: --test + +#![feature(test)] +#![feature(cfg_eval)] + +#[test] +#[test] +//~^ WARNING duplicated attribute +fn f() {} + +// The following shouldn't trigger an error. The attribute is not duplicated. +#[test] +fn f2() {} + +// The following shouldn't trigger an error either. The second attribute is not #[test]. +#[test] +#[inline] +fn f3() {} + +extern crate test; +use test::Bencher; + +#[bench] +#[bench] +//~^ WARNING duplicated attribute +fn f4(_: &mut Bencher) {} + +#[cfg_eval] +#[cfg_eval] +//~^ WARNING duplicated attribute +struct S; + +#[cfg_eval] +struct S2; + +fn main() {} diff --git a/src/test/ui/attributes/duplicated-attributes.stderr b/src/test/ui/attributes/duplicated-attributes.stderr new file mode 100644 index 0000000000000..735d950b27c22 --- /dev/null +++ b/src/test/ui/attributes/duplicated-attributes.stderr @@ -0,0 +1,22 @@ +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:12:1 + | +LL | #[test] + | ^^^^^^^ + | + = note: `#[warn(duplicate_macro_attributes)]` on by default + +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:29:1 + | +LL | #[bench] + | ^^^^^^^^ + +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:34:1 + | +LL | #[cfg_eval] + | ^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs index d8fd7ef3c1f44..2d049277d7fcf 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -1,6 +1,9 @@ +#![feature(const_fn_trait_bound)] #![feature(const_trait_impl)] pub trait MyTrait { + #[default_method_body_is_const] + fn defaulted_func(&self) {} fn func(self); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs new file mode 100644 index 0000000000000..c0f90c116e459 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -0,0 +1,18 @@ +// This tests that `default_method_body_is_const` methods can +// be called from a const context when used across crates. +// +// check-pass + +#![feature(const_trait_impl)] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +const _: () = { + Const.func(); + Const.defaulted_func(); +}; + +fn main() {}