diff --git a/Cargo.lock b/Cargo.lock
index fd2f2350c189a..1b7e0694afd87 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<T> 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<MoveSite>, Vec<Location>) {
-        fn predecessor_locations(
-            body: &'a mir::Body<'tcx>,
+        fn predecessor_locations<'a>(
+            body: &'a mir::Body<'_>,
             location: Location,
         ) -> impl Iterator<Item = Location> + '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<Span>,
@@ -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<BodyId> {
+        fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option<BodyId> {
             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<R1> MemberConstraintSet<'tcx, R1>
+impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
 where
     R1: Copy + Hash + Eq,
 {
@@ -140,7 +140,7 @@ where
     }
 }
 
-impl<R> MemberConstraintSet<'tcx, R>
+impl<R> 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<ty::Region<'tcx>>,
@@ -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<RegionVid>,
     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<RegionValueElements>,
@@ -119,7 +119,7 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
     stack: Vec<PointIndex>,
 }
 
-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<TypeTest<'tcx>>,
 }
 
-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<Annotatable> {
     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<Annotatable> {
     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<Annotatable> {
     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<Annotatable> {
     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(&param.attrs),
+        Annotatable::Param(param) => Some(&param.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_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs
index 61c3ef62fb193..68e3082cac763 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs
@@ -34,6 +34,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
 fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
     let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity
 
+    ret.push(String::from("-Wl,-z,origin"));
     for rpath in rpaths {
         if rpath.contains(',') {
             ret.push("-Wl,-rpath".into());
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 <https://github.com/rust-lang/rust/issues/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/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<T> ManuallyDrop<T> {
     /// ```
     #[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<T> {
         ManuallyDrop { value }
@@ -82,7 +82,7 @@ impl<T> ManuallyDrop<T> {
     /// 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>) -> 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<E>(error: E) -> Error
+    where
+        E: Into<Box<dyn error::Error + Send + Sync>>,
+    {
+        Self::_new(ErrorKind::Other, error.into())
+    }
+
     fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
         Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
     }
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 952a65a428688..bbd2c087ccabb 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1176,6 +1176,7 @@ impl<'a> Builder<'a> {
                 rustflags.arg("-Zosx-rpath-install-name");
                 Some("-Wl,-rpath,@loader_path/../lib")
             } else if !target.contains("windows") {
+                rustflags.arg("-Clink-args=-Wl,-z,origin");
                 Some("-Wl,-rpath,$ORIGIN/../lib")
             } else {
                 None
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/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
+