about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs2
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs10
-rw-r--r--compiler/rustc_borrowck/src/nll.rs1
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs55
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs3
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs60
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs10
-rw-r--r--compiler/rustc_lint/src/lints.rs21
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs43
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl9
-rw-r--r--compiler/rustc_parse/src/errors.rs31
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs64
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs21
-rw-r--r--compiler/rustc_passes/src/errors.rs11
-rw-r--r--compiler/rustc_target/src/asm/arm.rs80
30 files changed, 333 insertions, 147 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 79717c969d7..941bb78c0dd 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -899,7 +899,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        validate_attr::check_attr(&self.session.psess, attr);
+        validate_attr::check_attr(&self.features, &self.session.psess, attr);
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 3e6d0311b27..0bae1bd07a2 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -126,7 +126,7 @@ impl<'tcx> BorrowSet<'tcx> {
     ) -> Self {
         let mut visitor = GatherBorrows {
             tcx,
-            body: body,
+            body,
             location_map: Default::default(),
             activation_map: Default::default(),
             local_map: Default::default(),
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index c1f75328272..8a2936c2657 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -213,7 +213,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
             via(msg_old),
         );
 
-        if msg_new == "" {
+        if msg_new.is_empty() {
             // If `msg_new` is empty, then this isn't a borrow of a union field.
             err.span_label(span, format!("{kind_new} borrow occurs here"));
             err.span_label(old_span, format!("{kind_old} borrow occurs here"));
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index ec7d4582a60..f2b5ddcd782 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -43,9 +43,9 @@ impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
     }
 
     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
-        state.borrows.clone_from(&self.borrows.entry_set_for_block(block));
-        state.uninits.clone_from(&self.uninits.entry_set_for_block(block));
-        state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block));
+        state.borrows.clone_from(self.borrows.entry_set_for_block(block));
+        state.uninits.clone_from(self.uninits.entry_set_for_block(block));
+        state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block));
     }
 
     fn reconstruct_before_statement_effect(
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 67c11ff4a5b..c214c52880a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -895,7 +895,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             for alias_ty in alias_tys {
                 if alias_ty.span.desugaring_kind().is_some() {
                     // Skip `async` desugaring `impl Future`.
-                    ()
                 }
                 if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
                     if lt.ident.name == kw::Empty {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 77fb9fb4315..25a0d40218b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -519,7 +519,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     }
 
                     // Otherwise, let's descend into the referent types.
-                    search_stack.push((*referent_ty, &referent_hir_ty.ty));
+                    search_stack.push((*referent_ty, referent_hir_ty.ty));
                 }
 
                 // Match up something like `Foo<'1>`
@@ -558,7 +558,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 }
 
                 (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
-                    search_stack.push((*mut_ty, &mut_hir_ty.ty));
+                    search_stack.push((*mut_ty, mut_hir_ty.ty));
                 }
 
                 _ => {
@@ -652,7 +652,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
         let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
             self.infcx.tcx,
-            &self.upvars,
+            self.upvars,
             upvar_index,
         );
         let region_name = self.synthesize_region_name();
@@ -717,7 +717,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                             .output;
                         span = output.span();
                         if let hir::FnRetTy::Return(ret) = output {
-                            hir_ty = Some(self.get_future_inner_return_ty(*ret));
+                            hir_ty = Some(self.get_future_inner_return_ty(ret));
                         }
                         " of async function"
                     }
@@ -958,7 +958,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         {
             let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
                 self.infcx.tcx,
-                &self.upvars,
+                self.upvars,
                 upvar_index,
             );
             let region_name = self.synthesize_region_name();
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 5d7ce548469..923cf7e9405 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -114,7 +114,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
             move_data,
             elements,
             upvars,
-            polonius_input,
         );
 
     // Create the region inference context, taking ownership of the
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 9984f76e6d4..c590104978c 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -43,8 +43,8 @@ pub(crate) fn emit_facts<'tcx>(
     emit_universal_region_facts(
         all_facts,
         borrow_set,
-        &universal_regions,
-        &universal_region_relations,
+        universal_regions,
+        universal_region_relations,
     );
     emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
     emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index bf1c1b1433e..c56eaaff076 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -344,7 +344,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
 
     for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
         let reg_var = ty::RegionVid::from_usize(reg_var_idx);
-        let origin = var_to_origin.get(&reg_var).unwrap_or_else(|| &RegionCtxt::Unknown);
+        let origin = var_to_origin.get(&reg_var).unwrap_or(&RegionCtxt::Unknown);
         components[scc_idx.as_usize()].insert((reg_var, *origin));
     }
 
@@ -2216,7 +2216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // #114907 where this happens via liveness and dropck outlives results.
         // Therefore, we return a default value in case that happens, which should at worst emit a
         // suboptimal error, instead of the ICE.
-        self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other())
+        self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other)
     }
 
     /// Tries to find the terminator of the loop in which the region 'r' resides.
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 51c3648d730..67e5c8352df 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -418,9 +418,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
             let opaque_param = opaque_generics.param_at(i, tcx);
             let kind = opaque_param.kind.descr();
 
-            if let Err(guar) = opaque_env.param_is_error(i) {
-                return Err(guar);
-            }
+            opaque_env.param_is_error(i)?;
 
             return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
                 ty: arg,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 8b863efad6c..b777e01f7a6 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -12,9 +12,7 @@ use rustc_mir_dataflow::ResultsCursor;
 use std::rc::Rc;
 
 use crate::{
-    constraints::OutlivesConstraintSet,
-    facts::{AllFacts, AllFactsExt},
-    region_infer::values::LivenessValues,
+    constraints::OutlivesConstraintSet, region_infer::values::LivenessValues,
     universal_regions::UniversalRegions,
 };
 
@@ -38,7 +36,6 @@ pub(super) fn generate<'mir, 'tcx>(
     elements: &Rc<DenseLocationMap>,
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
-    use_polonius: bool,
 ) {
     debug!("liveness::generate");
 
@@ -49,11 +46,8 @@ pub(super) fn generate<'mir, 'tcx>(
     );
     let (relevant_live_locals, boring_locals) =
         compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
-    let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
 
-    if facts_enabled {
-        polonius::populate_access_facts(typeck, body, move_data);
-    };
+    polonius::populate_access_facts(typeck, body, move_data);
 
     trace::trace(
         typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index d8f03a07a63..a009e28a0dd 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -87,10 +87,10 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
 ) {
-    debug!("populate_access_facts()");
-    let location_table = typeck.borrowck_context.location_table;
-
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+        debug!("populate_access_facts()");
+        let location_table = typeck.borrowck_context.location_table;
+
         let mut extractor = UseFactsExtractor {
             var_defined_at: &mut facts.var_defined_at,
             var_used_at: &mut facts.var_used_at,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 50843c602cc..359c4ea0eb1 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -217,35 +217,52 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
     /// Add facts for all locals with free regions, since regions may outlive
     /// the function body only at certain nodes in the CFG.
     fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> {
-        let drop_used = self
-            .cx
-            .typeck
-            .borrowck_context
-            .all_facts
-            .as_ref()
-            .map(|facts| facts.var_dropped_at.clone())?;
+        // This collect is more necessary than immediately apparent
+        // because these facts go into `add_drop_live_facts_for()`,
+        // which also writes to `all_facts`, and so this is genuinely
+        // a simulatneous overlapping mutable borrow.
+        // FIXME for future hackers: investigate whether this is
+        // actually necessary; these facts come from Polonius
+        // and probably maybe plausibly does not need to go back in.
+        // It may be necessary to just pick out the parts of
+        // `add_drop_live_facts_for()` that make sense.
+        let facts_to_add: Vec<_> = {
+            let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at;
+
+            let relevant_live_locals: FxIndexSet<_> =
+                relevant_live_locals.iter().copied().collect();
+
+            drop_used
+                .iter()
+                .filter_map(|(local, location_index)| {
+                    let local_ty = self.cx.body.local_decls[*local].ty;
+                    if relevant_live_locals.contains(local) || !local_ty.has_free_regions() {
+                        return None;
+                    }
 
-        let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect();
-
-        let locations = IntervalSet::new(self.cx.elements.num_points());
-
-        for (local, location_index) in drop_used {
-            if !relevant_live_locals.contains(&local) {
-                let local_ty = self.cx.body.local_decls[local].ty;
-                if local_ty.has_free_regions() {
                     let location = match self
                         .cx
                         .typeck
                         .borrowck_context
                         .location_table
-                        .to_location(location_index)
+                        .to_location(*location_index)
                     {
                         RichLocation::Start(l) => l,
                         RichLocation::Mid(l) => l,
                     };
-                    self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
-                }
-            }
+
+                    Some((*local, local_ty, location))
+                })
+                .collect()
+        };
+
+        // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive!
+        // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd
+        // name with a description of what it means for future mortals passing by.
+        let locations = IntervalSet::new(self.cx.elements.num_points());
+
+        for (local, local_ty, location) in facts_to_add {
+            self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
         }
         Some(())
     }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c7c1b2af6a7..81bde14a82f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -133,7 +133,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
     move_data: &MoveData<'tcx>,
     elements: &Rc<DenseLocationMap>,
     upvars: &[&ty::CapturedPlace<'tcx>],
-    use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -189,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
     checker.check_signature_annotation(body);
 
-    liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius);
+    liveness::generate(&mut checker, body, elements, flow_inits, move_data);
 
     translate_outlives_facts(&mut checker);
     let opaque_type_values = infcx.take_opaque_types();
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index a331d83aab0..26fc77c7f33 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1883,7 +1883,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         let mut span: Option<Span> = None;
         while let Some(attr) = attrs.next() {
             rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
-            validate_attr::check_attr(&self.cx.sess.psess, attr);
+            validate_attr::check_attr(features, &self.cx.sess.psess, attr);
 
             let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
             span = Some(current_span);
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9e2756f07ed..5e83e0d27e1 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1145,10 +1145,6 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
     })
 }
 
-pub fn is_unsafe_attr(name: Symbol) -> bool {
-    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
-}
-
 pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
     LazyLock::new(|| {
         let mut map = FxHashMap::default();
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index fb3b7c0a127..bf429364318 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -125,7 +125,7 @@ pub use accepted::ACCEPTED_FEATURES;
 pub use builtin_attrs::AttributeDuplicates;
 pub use builtin_attrs::{
     deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
-    is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
+    is_valid_for_get_attr, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
     BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
 };
 pub use removed::REMOVED_FEATURES;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 9dd82868adc..b3ebc0621cb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -26,10 +26,8 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt,
-    Upcast,
-};
+use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};
+use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
@@ -1111,12 +1109,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
             )
         {
-            err.multipart_suggestion(
+            // When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.
+            // For example:
+            // fn mismatch_types() -> i32 {
+            //     match 1 {
+            //         x => dbg!(x),
+            //     }
+            //     todo!()
+            // }
+            // -------------^^^^^^^-
+            // Don't add semicolon `;` at the end of `dbg!(x)` expr
+            fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
+                for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
+                    match node {
+                        hir::Node::Block(block) => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        hir::Node::Arm(arm) => {
+                            if let hir::ExprKind::Block(block, _) = arm.body.kind
+                                && let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                return true;
+                            }
+                        }
+                        hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        _ => {
+                            return false;
+                        }
+                    }
+                }
+
+                false
+            }
+            let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())];
+            if !is_in_arm(expr, self.tcx) {
+                suggs.push((span.shrink_to_hi(), ";".to_string()));
+            }
+            err.multipart_suggestion_verbose(
                 "you might have meant to return this value",
-                vec![
-                    (span.shrink_to_lo(), "return ".to_string()),
-                    (span.shrink_to_hi(), ";".to_string()),
-                ],
+                suggs,
                 Applicability::MaybeIncorrect,
             );
         }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index fdedf2c2e6d..eac5083ffbf 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -825,6 +825,10 @@ lint_unnameable_test_items = cannot test inner items
 lint_unnecessary_qualification = unnecessary qualification
     .suggestion = remove the unnecessary path segments
 
+lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
+    .label = usage of unsafe attribute
+lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
+
 lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
 lint_untranslatable_diag = diagnostics should be created using translatable messages
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 290bb5173db..adb2a3275c0 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -319,6 +319,16 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
         BuiltinLintDiag::UnusedQualifications { removal_span } => {
             lints::UnusedQualifications { removal_span }.decorate_lint(diag);
         }
+        BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+            attribute_name_span,
+            sugg_spans: (left, right),
+        } => {
+            lints::UnsafeAttrOutsideUnsafe {
+                span: attribute_name_span,
+                suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
+            }
+            .decorate_lint(diag);
+        }
         BuiltinLintDiag::AssociatedConstElidedLifetime {
             elided,
             span: lt_span,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index b26d04d0618..6df3a11deb0 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2890,3 +2890,24 @@ pub struct RedundantImportVisibility {
     pub import_vis: String,
     pub max_vis: String,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unsafe_attr_outside_unsafe)]
+pub struct UnsafeAttrOutsideUnsafe {
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_unsafe_attr_outside_unsafe_suggestion,
+    applicability = "machine-applicable"
+)]
+pub struct UnsafeAttrOutsideUnsafeSuggestion {
+    #[suggestion_part(code = "unsafe(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1913b9d6a1c..265779c9374 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -115,6 +115,7 @@ declare_lint_pass! {
         UNNAMEABLE_TYPES,
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
+        UNSAFE_ATTR_OUTSIDE_UNSAFE,
         UNSAFE_OP_IN_UNSAFE_FN,
         UNSTABLE_NAME_COLLISIONS,
         UNSTABLE_SYNTAX_PRE_EXPANSION,
@@ -4902,3 +4903,45 @@ declare_lint! {
         reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
     };
 }
+
+declare_lint! {
+    /// The `unsafe_attr_outside_unsafe` lint detects a missing unsafe keyword
+    /// on attributes considered unsafe.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(unsafe_attributes)]
+    /// #![warn(unsafe_attr_outside_unsafe)]
+    ///
+    /// #[no_mangle]
+    /// extern "C" fn foo() {}
+    ///
+    /// fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Some attributes (e.g. `no_mangle`, `export_name`, `link_section` -- see
+    /// [issue #82499] for a more complete list) are considered "unsafe" attributes.
+    /// An unsafe attribute must only be used inside unsafe(...).
+    ///
+    /// This lint can automatically wrap the attributes in `unsafe(...)` , but this
+    /// obviously cannot verify that the preconditions of the `unsafe`
+    /// attributes are fulfilled, so that is still up to the user.
+    ///
+    /// The lint is currently "allow" by default, but that might change in the
+    /// future.
+    ///
+    /// [editions]: https://doc.rust-lang.org/edition-guide/
+    /// [issue #82499]: https://github.com/rust-lang/rust/issues/82499
+    pub UNSAFE_ATTR_OUTSIDE_UNSAFE,
+    Allow,
+    "detects unsafe attributes outside of unsafe",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index b3838f915f6..f33aadfbbc8 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -691,6 +691,10 @@ pub enum BuiltinLintDiag {
         /// The span of the unnecessarily-qualified path to remove.
         removal_span: Span,
     },
+    UnsafeAttrOutsideUnsafe {
+        attribute_name_span: Span,
+        sugg_spans: (Span, Span),
+    },
     AssociatedConstElidedLifetime {
         elided: bool,
         span: Span,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index efb9526eabc..f08efe60d96 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -366,6 +366,10 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
     .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
     .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
 
+parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
+    .suggestion = remove the `unsafe(...)`
+    .note = extraneous unsafe is not allowed in attributes
+
 parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
     .label = the `block` fragment is within this context
     .suggestion = wrap this in another block
@@ -866,6 +870,11 @@ parse_unmatched_angle_brackets = {$num_extra_brackets ->
            *[other] remove extra angle brackets
         }
 
+parse_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
+    .label = usage of unsafe attribute
+parse_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
+
+
 parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
     .label = {parse_unskipped_whitespace}
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 46e15734853..8d49887f164 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2997,3 +2997,34 @@ pub(crate) struct DotDotRangeAttribute {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_invalid_attr_unsafe)]
+#[note]
+pub struct InvalidAttrUnsafe {
+    #[primary_span]
+    pub span: Span,
+    pub name: Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unsafe_attr_outside_unsafe)]
+pub struct UnsafeAttrOutsideUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    parse_unsafe_attr_outside_unsafe_suggestion,
+    applicability = "machine-applicable"
+)]
+pub struct UnsafeAttrOutsideUnsafeSuggestion {
+    #[suggestion_part(code = "unsafe(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 4ca52146039..bcb1131cc19 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -5,21 +5,73 @@ use crate::{errors, parse_in};
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::DelimSpan;
 use rustc_ast::MetaItemKind;
-use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
+use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
 use rustc_errors::{Applicability, FatalError, PResult};
-use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{
+    AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
+};
 use rustc_session::errors::report_lit_error;
-use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, BytePos, Span, Symbol};
 
-pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
+pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
     if attr.is_doc_comment() {
         return;
     }
 
     let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
+    let attr_item = attr.get_normal_item();
+
+    let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe);
+
+    if features.unsafe_attributes {
+        if is_unsafe_attr {
+            if let ast::Safety::Default = attr_item.unsafety {
+                let path_span = attr_item.path.span;
+
+                // If the `attr_item`'s span is not from a macro, then just suggest
+                // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
+                // `unsafe(`, `)` right after and right before the opening and closing
+                // square bracket respectively.
+                let diag_span = if attr_item.span().can_be_used_for_suggestions() {
+                    attr_item.span()
+                } else {
+                    attr.span
+                        .with_lo(attr.span.lo() + BytePos(2))
+                        .with_hi(attr.span.hi() - BytePos(1))
+                };
+
+                if attr.span.at_least_rust_2024() {
+                    psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
+                        span: path_span,
+                        suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
+                            left: diag_span.shrink_to_lo(),
+                            right: diag_span.shrink_to_hi(),
+                        },
+                    });
+                } else {
+                    psess.buffer_lint(
+                        UNSAFE_ATTR_OUTSIDE_UNSAFE,
+                        path_span,
+                        ast::CRATE_NODE_ID,
+                        BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+                            attribute_name_span: path_span,
+                            sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
+                        },
+                    );
+                }
+            }
+        } else {
+            if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+                psess.dcx().emit_err(errors::InvalidAttrUnsafe {
+                    span: unsafe_span,
+                    name: attr_item.path.clone(),
+                });
+            }
+        }
+    }
 
     // Check input tokens for built-in and key-value attributes.
     match attr_info {
@@ -32,7 +84,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
                 }
             }
         }
-        _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
+        _ if let AttrArgs::Eq(..) = attr_item.args => {
             // All key-value attributes are restricted to meta-item syntax.
             match parse_meta(psess, attr) {
                 Ok(_) => {}
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 84c71c4bed2..9a830b0f49b 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -384,10 +384,6 @@ passes_invalid_attr_at_crate_level =
 passes_invalid_attr_at_crate_level_item =
     the inner attribute doesn't annotate this {$kind}
 
-passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
-    .suggestion = remove the `unsafe(...)`
-    .note = extraneous unsafe is not allowed in attributes
-
 passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
 
 passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index a0b3470df6d..2ed5bba85c6 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,9 +10,7 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, IntoDiagArg, MultiSpan};
 use rustc_errors::{DiagCtxtHandle, StashKey};
-use rustc_feature::{
-    is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
-};
+use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir};
@@ -116,8 +114,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut seen = FxHashMap::default();
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            self.check_unsafe_attr(attr);
-
             match attr.path().as_slice() {
                 [sym::diagnostic, sym::do_not_recommend] => {
                     self.check_do_not_recommend(attr.span, hir_id, target)
@@ -312,21 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         true
     }
 
-    /// Checks if `unsafe()` is applied to an invalid attribute.
-    fn check_unsafe_attr(&self, attr: &Attribute) {
-        if !attr.is_doc_comment() {
-            let attr_item = attr.get_normal_item();
-            if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety {
-                if !is_unsafe_attr(attr.name_or_empty()) {
-                    self.dcx().emit_err(errors::InvalidAttrUnsafe {
-                        span: unsafe_span,
-                        name: attr_item.path.clone(),
-                    });
-                }
-            }
-        }
-    }
-
     /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
     fn check_diagnostic_on_unimplemented(
         &self,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index d27b94ebd22..f0596568092 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use crate::fluent_generated as fluent;
-use rustc_ast::{ast, Label};
+use rustc_ast::Label;
 use rustc_errors::{
     codes::*, Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee,
     Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -863,15 +863,6 @@ pub struct InvalidAttrAtCrateLevel {
     pub item: Option<ItemFollowingInnerAttr>,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_invalid_attr_unsafe)]
-#[note]
-pub struct InvalidAttrUnsafe {
-    #[primary_span]
-    pub span: Span,
-    pub name: ast::Path,
-}
-
 #[derive(Clone, Copy)]
 pub struct ItemFollowingInnerAttr {
     pub span: Span,
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index 9d79faadd61..70fcaab1847 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -148,22 +148,22 @@ def_regs! {
         r11: reg = ["r11", "fp"] % frame_pointer_r11,
         r12: reg = ["r12", "ip"] % not_thumb1,
         r14: reg = ["r14", "lr"] % not_thumb1,
-        s0: sreg, sreg_low16 = ["s0"],
-        s1: sreg, sreg_low16 = ["s1"],
-        s2: sreg, sreg_low16 = ["s2"],
-        s3: sreg, sreg_low16 = ["s3"],
-        s4: sreg, sreg_low16 = ["s4"],
-        s5: sreg, sreg_low16 = ["s5"],
-        s6: sreg, sreg_low16 = ["s6"],
-        s7: sreg, sreg_low16 = ["s7"],
-        s8: sreg, sreg_low16 = ["s8"],
-        s9: sreg, sreg_low16 = ["s9"],
-        s10: sreg, sreg_low16 = ["s10"],
-        s11: sreg, sreg_low16 = ["s11"],
-        s12: sreg, sreg_low16 = ["s12"],
-        s13: sreg, sreg_low16 = ["s13"],
-        s14: sreg, sreg_low16 = ["s14"],
-        s15: sreg, sreg_low16 = ["s15"],
+        s0: sreg_low16, sreg = ["s0"],
+        s1: sreg_low16, sreg = ["s1"],
+        s2: sreg_low16, sreg = ["s2"],
+        s3: sreg_low16, sreg = ["s3"],
+        s4: sreg_low16, sreg = ["s4"],
+        s5: sreg_low16, sreg = ["s5"],
+        s6: sreg_low16, sreg = ["s6"],
+        s7: sreg_low16, sreg = ["s7"],
+        s8: sreg_low16, sreg = ["s8"],
+        s9: sreg_low16, sreg = ["s9"],
+        s10: sreg_low16, sreg = ["s10"],
+        s11: sreg_low16, sreg = ["s11"],
+        s12: sreg_low16, sreg = ["s12"],
+        s13: sreg_low16, sreg = ["s13"],
+        s14: sreg_low16, sreg = ["s14"],
+        s15: sreg_low16, sreg = ["s15"],
         s16: sreg = ["s16"],
         s17: sreg = ["s17"],
         s18: sreg = ["s18"],
@@ -180,22 +180,22 @@ def_regs! {
         s29: sreg = ["s29"],
         s30: sreg = ["s30"],
         s31: sreg = ["s31"],
-        d0: dreg, dreg_low16, dreg_low8 = ["d0"],
-        d1: dreg, dreg_low16, dreg_low8 = ["d1"],
-        d2: dreg, dreg_low16, dreg_low8 = ["d2"],
-        d3: dreg, dreg_low16, dreg_low8 = ["d3"],
-        d4: dreg, dreg_low16, dreg_low8 = ["d4"],
-        d5: dreg, dreg_low16, dreg_low8 = ["d5"],
-        d6: dreg, dreg_low16, dreg_low8 = ["d6"],
-        d7: dreg, dreg_low16, dreg_low8 = ["d7"],
-        d8: dreg, dreg_low16 = ["d8"],
-        d9: dreg, dreg_low16 = ["d9"],
-        d10: dreg, dreg_low16 = ["d10"],
-        d11: dreg, dreg_low16 = ["d11"],
-        d12: dreg, dreg_low16 = ["d12"],
-        d13: dreg, dreg_low16 = ["d13"],
-        d14: dreg, dreg_low16 = ["d14"],
-        d15: dreg, dreg_low16 = ["d15"],
+        d0: dreg_low8, dreg_low16, dreg = ["d0"],
+        d1: dreg_low8, dreg_low16, dreg = ["d1"],
+        d2: dreg_low8, dreg_low16, dreg = ["d2"],
+        d3: dreg_low8, dreg_low16, dreg = ["d3"],
+        d4: dreg_low8, dreg_low16, dreg = ["d4"],
+        d5: dreg_low8, dreg_low16, dreg = ["d5"],
+        d6: dreg_low8, dreg_low16, dreg = ["d6"],
+        d7: dreg_low8, dreg_low16, dreg = ["d7"],
+        d8: dreg_low16, dreg = ["d8"],
+        d9: dreg_low16, dreg = ["d9"],
+        d10: dreg_low16, dreg = ["d10"],
+        d11: dreg_low16, dreg = ["d11"],
+        d12: dreg_low16, dreg = ["d12"],
+        d13: dreg_low16, dreg = ["d13"],
+        d14: dreg_low16, dreg = ["d14"],
+        d15: dreg_low16, dreg = ["d15"],
         d16: dreg = ["d16"],
         d17: dreg = ["d17"],
         d18: dreg = ["d18"],
@@ -212,14 +212,14 @@ def_regs! {
         d29: dreg = ["d29"],
         d30: dreg = ["d30"],
         d31: dreg = ["d31"],
-        q0: qreg, qreg_low8, qreg_low4 = ["q0"],
-        q1: qreg, qreg_low8, qreg_low4 = ["q1"],
-        q2: qreg, qreg_low8, qreg_low4 = ["q2"],
-        q3: qreg, qreg_low8, qreg_low4 = ["q3"],
-        q4: qreg, qreg_low8 = ["q4"],
-        q5: qreg, qreg_low8 = ["q5"],
-        q6: qreg, qreg_low8 = ["q6"],
-        q7: qreg, qreg_low8 = ["q7"],
+        q0: qreg_low4, qreg_low8, qreg = ["q0"],
+        q1: qreg_low4, qreg_low8, qreg = ["q1"],
+        q2: qreg_low4, qreg_low8, qreg = ["q2"],
+        q3: qreg_low4, qreg_low8, qreg = ["q3"],
+        q4: qreg_low8, qreg = ["q4"],
+        q5: qreg_low8, qreg = ["q5"],
+        q6: qreg_low8, qreg = ["q6"],
+        q7: qreg_low8, qreg = ["q7"],
         q8: qreg = ["q8"],
         q9: qreg = ["q9"],
         q10: qreg = ["q10"],