diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index dc49a45fe7309..955480a1a7411 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -906,16 +906,12 @@ where
         }
         // We still require the sizes to match.
         if src.layout.size != dest.layout.size {
-            // FIXME: This should be an assert instead of an error, but if we transmute within an
-            // array length computation, `typeck` may not have yet been run and errored out. In fact
-            // most likely we *are* running `typeck` right now. Investigate whether we can bail out
-            // on `typeck_results().has_errors` at all const eval entry points.
-            debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
-            self.tcx.sess.delay_span_bug(
+            span_bug!(
                 self.cur_span(),
-                "size-changing transmute, should have been caught by transmute checking",
+                "size-changing transmute, should have been caught by transmute checking: {:#?}\ndest: {:#?}",
+                src,
+                dest
             );
-            throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
         }
         // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
         // to avoid that here.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index afbf48fceb510..e6c9c6693c5ab 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -937,7 +937,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                         //
                         // maybe move the check to a MIR pass?
                         tcx.ensure().check_mod_liveness(module);
-                        tcx.ensure().check_mod_intrinsics(module);
                     });
                 });
             }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index bb6b10149ab49..cb6fd006c3efe 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -149,8 +149,6 @@ pub enum InvalidProgramInfo<'tcx> {
     /// (which unfortunately typeck does not reject).
     /// Not using `FnAbiError` as that contains a nested `LayoutError`.
     FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
-    /// An invalid transmute happened.
-    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
     /// SizeOf of unsized type was requested.
     SizeOfUnsizedType(Ty<'tcx>),
 }
@@ -166,11 +164,6 @@ impl fmt::Display for InvalidProgramInfo<'_> {
             }
             Layout(ref err) => write!(f, "{}", err),
             FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err),
-            TransmuteSizeDiff(from_ty, to_ty) => write!(
-                f,
-                "transmuting `{}` to `{}` is not possible, because these types do not have the same size",
-                from_ty, to_ty
-            ),
             SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty),
         }
     }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0c936b7ae101b..68b81efaa0002 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -804,10 +804,6 @@ rustc_queries! {
         desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
     }
 
-    query check_mod_intrinsics(key: LocalDefId) -> () {
-        desc { |tcx| "checking intrinsics in {}", describe_as_module(key, tcx) }
-    }
-
     query check_mod_liveness(key: LocalDefId) -> () {
         desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) }
     }
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 510280ee38637..a2d8e5168c4d0 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -30,7 +30,6 @@ mod diagnostic_items;
 pub mod entry;
 pub mod hir_id_validator;
 pub mod hir_stats;
-mod intrinsicck;
 mod lang_items;
 pub mod layout_test;
 mod lib_features;
@@ -54,7 +53,6 @@ pub fn provide(providers: &mut Providers) {
     loops::provide(providers);
     naked_functions::provide(providers);
     liveness::provide(providers);
-    intrinsicck::provide(providers);
     reachable::provide(providers);
     stability::provide(providers);
     upvars::provide(providers);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 266fcc777ef56..0cefa802c857d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -273,6 +273,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
     ) {
+        self.set_tainted_by_errors();
         let tcx = self.tcx;
         let mut span = obligation.cause.span;
 
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 3e76738cc5d9e..a6d7fecb2e83b 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -1,3 +1,5 @@
+use crate::check::wfcheck::for_item;
+
 use super::coercion::CoerceMany;
 use super::compare_method::check_type_bounds;
 use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
@@ -871,6 +873,14 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                 }
             }
         }
+        DefKind::GlobalAsm => {
+            let it = tcx.hir().item(id);
+            let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
+            for_item(tcx, it).with_fcx(|fcx| {
+                fcx.check_asm(asm, it.hir_id());
+                Default::default()
+            })
+        }
         _ => {}
     }
 }
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 09b0dc0a0ea2e..ea81f1ef90c9a 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -51,6 +51,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
+use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
@@ -294,7 +295,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_lang_item_path(lang_item, expr, hir_id)
             }
             ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
-            ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
+            ExprKind::InlineAsm(asm) => {
+                // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
+                self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
+                self.check_expr_asm(asm)
+            }
             ExprKind::Break(destination, ref expr_opt) => {
                 self.check_expr_break(destination, expr_opt.as_deref(), expr)
             }
@@ -530,8 +535,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
         };
 
-        if let ty::FnDef(..) = ty.kind() {
+        if let ty::FnDef(did, ..) = *ty.kind() {
             let fn_sig = ty.fn_sig(tcx);
+            if tcx.fn_sig(did).abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute {
+                let from = fn_sig.inputs().skip_binder()[0];
+                let to = fn_sig.output().skip_binder();
+                // We defer the transmute to the end of typeck, once all inference vars have
+                // been resolved or we errored. This is important as we can only check transmute
+                // on concrete types, but the output type may not be known yet (it would only
+                // be known if explicitly specified via turbofish).
+                self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span));
+            }
             if !tcx.features().unsized_fn_params {
                 // We want to remove some Sized bounds from std functions,
                 // but don't want to expose the removal to stable Rust.
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index a02d8c89772a2..31c590795a65c 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -47,6 +47,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub(in super::super) fn check_transmutes(&self) {
+        let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
+        debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
+        for (from, to, span) in deferred_transmute_checks.drain(..) {
+            self.check_transmute(span, from, to);
+        }
+    }
+
+    pub(in super::super) fn check_asms(&self) {
+        let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
+        debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
+        for (asm, hir_id) in deferred_asm_checks.drain(..) {
+            let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
+            self.check_asm(asm, enclosing_id);
+        }
+    }
+
     pub(in super::super) fn check_method_argument_types(
         &self,
         sp: Span,
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index 5cd63cae8ad9b..08a64d8e67364 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -50,6 +50,10 @@ pub struct Inherited<'a, 'tcx> {
 
     pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
 
+    pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, Span)>>,
+
+    pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
+
     pub(super) deferred_generator_interiors:
         RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
 
@@ -113,6 +117,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
             deferred_sized_obligations: RefCell::new(Vec::new()),
             deferred_call_resolutions: RefCell::new(Default::default()),
             deferred_cast_checks: RefCell::new(Vec::new()),
+            deferred_transmute_checks: RefCell::new(Vec::new()),
+            deferred_asm_checks: RefCell::new(Vec::new()),
             deferred_generator_interiors: RefCell::new(Vec::new()),
             diverging_type_vars: RefCell::new(Default::default()),
             body_id,
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_typeck/src/check/intrinsicck.rs
similarity index 84%
rename from compiler/rustc_passes/src/intrinsicck.rs
rename to compiler/rustc_typeck/src/check/intrinsicck.rs
index 9c840777bafc1..027868be8bb0d 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_typeck/src/check/intrinsicck.rs
@@ -1,37 +1,16 @@
-use hir::intravisit::walk_inline_asm;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
 use rustc_index::vec::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy};
+use rustc_middle::ty::{self, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
 use rustc_session::lint;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{Pointer, VariantIdx};
-use rustc_target::asm::{InlineAsmRegOrRegClass, InlineAsmType};
+use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
 
-fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx });
-}
-
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_intrinsics, ..*providers };
-}
-
-struct ItemVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-struct ExprVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    typeck_results: &'tcx ty::TypeckResults<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-}
+use super::FnCtxt;
 
 /// If the type is `Option<T>`, it will return `T`, otherwise
 /// the type itself. Works on most `Option`-like types.
@@ -60,14 +39,15 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     ty
 }
 
-impl<'tcx> ExprVisitor<'tcx> {
-    fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        self.tcx.is_intrinsic(def_id) && self.tcx.item_name(def_id) == sym::transmute
-    }
-
-    fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
-        let sk_from = SizeSkeleton::compute(from, self.tcx, self.param_env);
-        let sk_to = SizeSkeleton::compute(to, self.tcx, self.param_env);
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    pub fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
+        let convert = |ty: Ty<'tcx>| {
+            let ty = self.resolve_vars_if_possible(ty);
+            let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+            (SizeSkeleton::compute(ty, self.tcx, self.param_env), ty)
+        };
+        let (sk_from, from) = convert(from);
+        let (sk_to, to) = convert(to);
 
         // Check for same size using the skeletons.
         if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
@@ -139,7 +119,8 @@ impl<'tcx> ExprVisitor<'tcx> {
         target_features: &FxHashSet<Symbol>,
     ) -> Option<InlineAsmType> {
         // Check the type against the allowed types for inline asm.
-        let ty = self.typeck_results.expr_ty_adjusted(expr);
+        let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
+        let ty = self.resolve_vars_if_possible(ty);
         let asm_ty_isize = match self.tcx.sess.target.pointer_width {
             16 => InlineAsmType::I16,
             32 => InlineAsmType::I32,
@@ -152,10 +133,24 @@ impl<'tcx> ExprVisitor<'tcx> {
             ty::Error(_) => return None,
             ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
             ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
+            // Somewhat of a hack: fallback in the presence of errors does not actually
+            // fall back to i32, but to ty::Error. For integer inference variables this
+            // means that they don't get any fallback and stay as `{integer}`.
+            // Since compilation can't succeed anyway, it's fine to use this to avoid printing
+            // "cannot use value of type `{integer}`", even though that would absolutely
+            // work due due i32 fallback if the current function had no other errors.
+            ty::Infer(InferTy::IntVar(_)) => {
+                assert!(self.is_tainted_by_errors());
+                Some(InlineAsmType::I32)
+            }
             ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
             ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
             ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
             ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
+            ty::Infer(InferTy::FloatVar(_)) => {
+                assert!(self.is_tainted_by_errors());
+                Some(InlineAsmType::F32)
+            }
             ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
             ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
             ty::FnPtr(_) => Some(asm_ty_isize),
@@ -208,6 +203,11 @@ impl<'tcx> ExprVisitor<'tcx> {
             return None;
         };
 
+        if ty.has_infer_types_or_consts() {
+            assert!(self.is_tainted_by_errors());
+            return None;
+        }
+
         // Check that the type implements Copy. The only case where this can
         // possibly fail is for SIMD types which don't #[derive(Copy)].
         if !ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), self.param_env) {
@@ -230,10 +230,10 @@ impl<'tcx> ExprVisitor<'tcx> {
             if in_asm_ty != asm_ty {
                 let msg = "incompatible types for asm inout argument";
                 let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
-                err.span_label(
-                    in_expr.span,
-                    &format!("type `{}`", self.typeck_results.expr_ty_adjusted(in_expr)),
-                );
+
+                let in_expr_ty = self.typeck_results.borrow().expr_ty_adjusted(in_expr);
+                let in_expr_ty = self.resolve_vars_if_possible(in_expr_ty);
+                err.span_label(in_expr.span, &format!("type `{in_expr_ty}`"));
                 err.span_label(expr.span, &format!("type `{ty}`"));
                 err.note(
                     "asm inout arguments must have the same type, \
@@ -337,12 +337,14 @@ impl<'tcx> ExprVisitor<'tcx> {
         Some(asm_ty)
     }
 
-    fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) {
+    pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: hir::HirId) {
         let hir = self.tcx.hir();
-        let enclosing_id = hir.enclosing_body_owner(hir_id);
         let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
         let target_features = self.tcx.asm_target_features(enclosing_def_id);
-        let asm_arch = self.tcx.sess.asm_arch.unwrap();
+        let Some(asm_arch) = self.tcx.sess.asm_arch else {
+            self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm");
+            return;
+        };
         for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
             // Validate register classes against currently enabled target
             // features. We check that at least one type is available for
@@ -358,6 +360,11 @@ impl<'tcx> ExprVisitor<'tcx> {
                 // Some explicit registers cannot be used depending on the
                 // target. Reject those here.
                 if let InlineAsmRegOrRegClass::Reg(reg) = reg {
+                    if let InlineAsmReg::Err = reg {
+                        // `validate` will panic on `Err`, as an error must
+                        // already have been reported.
+                        continue;
+                    }
                     if let Err(msg) = reg.validate(
                         asm_arch,
                         self.tcx.sess.relocation_model(),
@@ -374,6 +381,9 @@ impl<'tcx> ExprVisitor<'tcx> {
                 if !op.is_clobber() {
                     let mut missing_required_features = vec![];
                     let reg_class = reg.reg_class();
+                    if let InlineAsmRegClass::Err = reg_class {
+                        continue;
+                    }
                     for &(_, feature) in reg_class.supported_types(asm_arch) {
                         match feature {
                             Some(feature) => {
@@ -482,33 +492,6 @@ impl<'tcx> ExprVisitor<'tcx> {
                         );
                     }
                 }
-                // These are checked in ItemVisitor.
-                hir::InlineAsmOperand::Const { .. }
-                | hir::InlineAsmOperand::SymFn { .. }
-                | hir::InlineAsmOperand::SymStatic { .. } => {}
-            }
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> {
-    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        let owner_def_id = self.tcx.hir().body_owner_def_id(body_id);
-        let body = self.tcx.hir().body(body_id);
-        let param_env = self.tcx.param_env(owner_def_id.to_def_id());
-        let typeck_results = self.tcx.typeck(owner_def_id);
-        ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body);
-        self.visit_body(body);
-    }
-
-    fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
-        for (op, op_sp) in asm.operands.iter() {
-            match *op {
-                // These are checked in ExprVisitor.
-                hir::InlineAsmOperand::In { .. }
-                | hir::InlineAsmOperand::Out { .. }
-                | hir::InlineAsmOperand::InOut { .. }
-                | hir::InlineAsmOperand::SplitInOut { .. } => {}
                 // No special checking is needed for these:
                 // - Typeck has checked that Const operands are integers.
                 // - AST lowering guarantees that SymStatic points to a static.
@@ -534,31 +517,5 @@ impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> {
                 }
             }
         }
-        walk_inline_asm(self, asm, id);
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        match expr.kind {
-            hir::ExprKind::Path(ref qpath) => {
-                let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
-                if let Res::Def(DefKind::Fn, did) = res
-                    && self.def_id_is_transmute(did)
-                {
-                    let typ = self.typeck_results.node_type(expr.hir_id);
-                    let sig = typ.fn_sig(self.tcx);
-                    let from = sig.inputs().skip_binder()[0];
-                    let to = sig.output().skip_binder();
-                    self.check_transmute(expr.span, from, to);
-                }
-            }
-
-            hir::ExprKind::InlineAsm(asm) => self.check_asm(asm, expr.hir_id),
-
-            _ => {}
-        }
-
-        intravisit::walk_expr(self, expr);
     }
 }
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 280fae5fe6ddd..7e686d0f5e99a 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -81,6 +81,7 @@ mod gather_locals;
 mod generator_interior;
 mod inherited;
 pub mod intrinsic;
+mod intrinsicck;
 pub mod method;
 mod op;
 mod pat;
@@ -487,6 +488,12 @@ fn typeck_with_fallback<'tcx>(
 
         fcx.select_all_obligations_or_error();
 
+        if !fcx.infcx.is_tainted_by_errors() {
+            fcx.check_transmutes();
+        }
+
+        fcx.check_asms();
+
         if fn_sig.is_some() {
             fcx.regionck_fn(id, body, span, wf_tys);
         } else {
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 50966868ec7d9..956e4ce49b025 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -41,7 +41,7 @@ use std::ops::ControlFlow;
 /// ```ignore (illustrative)
 /// F: for<'b, 'tcx> where 'tcx FnOnce(FnCtxt<'b, 'tcx>)
 /// ```
-struct CheckWfFcxBuilder<'tcx> {
+pub(super) struct CheckWfFcxBuilder<'tcx> {
     inherited: super::InheritedBuilder<'tcx>,
     id: hir::HirId,
     span: Span,
@@ -49,7 +49,7 @@ struct CheckWfFcxBuilder<'tcx> {
 }
 
 impl<'tcx> CheckWfFcxBuilder<'tcx> {
-    fn with_fcx<F>(&mut self, f: F)
+    pub(super) fn with_fcx<F>(&mut self, f: F)
     where
         F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet<Ty<'tcx>>,
     {
@@ -966,7 +966,7 @@ fn check_associated_item(
     })
 }
 
-fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
+pub(super) fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
     for_id(tcx, item.def_id, item.span)
 }
 
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 4ffd199b133ad..454c71d4971eb 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
 #![feature(hash_drain_filter)]
 #![feature(if_let_guard)]
 #![feature(is_sorted)]
+#![feature(iter_intersperse)]
 #![feature(label_break_value)]
 #![feature(let_chains)]
 #![feature(let_else)]
diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs
index 1a3141019161d..2b6a9b71cd506 100644
--- a/src/test/ui/asm/aarch64/bad-reg.rs
+++ b/src/test/ui/asm/aarch64/bad-reg.rs
@@ -36,9 +36,11 @@ fn main() {
 
         asm!("", in("p0") foo);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+        //~| ERROR type `i32` cannot be used with this register class
         asm!("", out("p0") _);
         asm!("{}", in(preg) foo);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+        //~| ERROR type `i32` cannot be used with this register class
         asm!("{}", out(preg) _);
         //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
 
diff --git a/src/test/ui/asm/aarch64/bad-reg.stderr b/src/test/ui/asm/aarch64/bad-reg.stderr
index e3316b85193e4..0ba627dac309f 100644
--- a/src/test/ui/asm/aarch64/bad-reg.stderr
+++ b/src/test/ui/asm/aarch64/bad-reg.stderr
@@ -87,19 +87,19 @@ LL |         asm!("", in("p0") foo);
    |                  ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:40:20
+  --> $DIR/bad-reg.rs:41:20
    |
 LL |         asm!("{}", in(preg) foo);
    |                    ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:42:20
+  --> $DIR/bad-reg.rs:44:20
    |
 LL |         asm!("{}", out(preg) _);
    |                    ^^^^^^^^^^^
 
 error: register `x0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:48:32
+  --> $DIR/bad-reg.rs:50:32
    |
 LL |         asm!("", in("x0") foo, in("w0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `x0`
@@ -107,7 +107,7 @@ LL |         asm!("", in("x0") foo, in("w0") bar);
    |                  register `x0`
 
 error: register `x0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:50:32
+  --> $DIR/bad-reg.rs:52:32
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `x0`
@@ -115,13 +115,13 @@ LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  register `x0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:50:18
+  --> $DIR/bad-reg.rs:52:18
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ^^^^^^^^^^^^
 
 error: register `v0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:53:32
+  --> $DIR/bad-reg.rs:55:32
    |
 LL |         asm!("", in("v0") foo, in("q0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `v0`
@@ -129,7 +129,7 @@ LL |         asm!("", in("v0") foo, in("q0") bar);
    |                  register `v0`
 
 error: register `v0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:55:32
+  --> $DIR/bad-reg.rs:57:32
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `v0`
@@ -137,10 +137,26 @@ LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  register `v0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:55:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ^^^^^^^^^^^^
 
-error: aborting due to 18 previous errors
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:37:27
+   |
+LL |         asm!("", in("p0") foo);
+   |                           ^^^
+   |
+   = note: register class `preg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:41:29
+   |
+LL |         asm!("{}", in(preg) foo);
+   |                             ^^^
+   |
+   = note: register class `preg` supports these types: 
+
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs
new file mode 100644
index 0000000000000..e4d29754556c8
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.rs
@@ -0,0 +1,37 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+struct SimdType(f32, f32, f32, f32);
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+    unsafe {
+        // Inputs must be initialized
+
+        let x: u64;
+        asm!("{}", in(reg) x);
+        //~^ ERROR use of possibly-uninitialized variable: `x`
+        let mut y: u64;
+        asm!("{}", inout(reg) y);
+        //~^ ERROR use of possibly-uninitialized variable: `y`
+        let _ = y;
+
+        // Outputs require mutable places
+
+        let v: Vec<u64> = vec![0, 1, 2];
+        asm!("{}", in(reg) v[0]);
+        asm!("{}", out(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+        asm!("{}", inout(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+        // Sym operands must point to a function or static
+    }
+}
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr
new file mode 100644
index 0000000000000..37bbe394994e0
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/type-check-2-2.rs:19:28
+   |
+LL |         asm!("{}", in(reg) x);
+   |                            ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/type-check-2-2.rs:22:9
+   |
+LL |         asm!("{}", inout(reg) y);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2-2.rs:30:29
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         asm!("{}", in(reg) v[0]);
+LL |         asm!("{}", out(reg) v[0]);
+   |                             ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2-2.rs:32:31
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         asm!("{}", inout(reg) v[0]);
+   |                               ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs
index 9e53a2e0c5230..fdafe63c7b07b 100644
--- a/src/test/ui/asm/aarch64/type-check-2.rs
+++ b/src/test/ui/asm/aarch64/type-check-2.rs
@@ -15,23 +15,6 @@ fn main() {
     unsafe {
         // Inputs must be initialized
 
-        let x: u64;
-        asm!("{}", in(reg) x);
-        //~^ ERROR use of possibly-uninitialized variable: `x`
-        let mut y: u64;
-        asm!("{}", inout(reg) y);
-        //~^ ERROR use of possibly-uninitialized variable: `y`
-        let _ = y;
-
-        // Outputs require mutable places
-
-        let v: Vec<u64> = vec![0, 1, 2];
-        asm!("{}", in(reg) v[0]);
-        asm!("{}", out(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
-        asm!("{}", inout(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
-
         // Sym operands must point to a function or static
 
         const C: i32 = 0;
diff --git a/src/test/ui/asm/aarch64/type-check-2.stderr b/src/test/ui/asm/aarch64/type-check-2.stderr
index 6047bed6e7802..4b99652cd20bd 100644
--- a/src/test/ui/asm/aarch64/type-check-2.stderr
+++ b/src/test/ui/asm/aarch64/type-check-2.stderr
@@ -1,13 +1,29 @@
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:75:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:24:20
+   |
+LL |         asm!("{}", sym C);
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:46:31
+  --> $DIR/type-check-2.rs:29:31
    |
 LL |         asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
-  --> $DIR/type-check-2.rs:58:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:38]` for inline assembly
+  --> $DIR/type-check-2.rs:41:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +31,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+  --> $DIR/type-check-2.rs:43:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +40,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:62:28
+  --> $DIR/type-check-2.rs:45:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +48,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:64:28
+  --> $DIR/type-check-2.rs:47:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +56,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:72:31
+  --> $DIR/type-check-2.rs:55:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,60 +64,12 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:75:31
+  --> $DIR/type-check-2.rs:58:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:41:20
-   |
-LL |         asm!("{}", sym C);
-   |                    ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:92:19
-   |
-LL | global_asm!("{}", sym C);
-   |                   ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/type-check-2.rs:19:28
-   |
-LL |         asm!("{}", in(reg) x);
-   |                            ^ use of possibly-uninitialized `x`
-
-error[E0381]: use of possibly-uninitialized variable: `y`
-  --> $DIR/type-check-2.rs:22:9
-   |
-LL |         asm!("{}", inout(reg) y);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:30:29
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-LL |         asm!("{}", in(reg) v[0]);
-LL |         asm!("{}", out(reg) v[0]);
-   |                             ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:32:31
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-...
-LL |         asm!("{}", inout(reg) v[0]);
-   |                               ^ cannot borrow as mutable
-
-error: aborting due to 13 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0381, E0596.
-For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/aarch64/type-check-3.rs b/src/test/ui/asm/aarch64/type-check-3.rs
index 8cac18b805269..623f6593d79ba 100644
--- a/src/test/ui/asm/aarch64/type-check-3.rs
+++ b/src/test/ui/asm/aarch64/type-check-3.rs
@@ -95,21 +95,3 @@ fn main() {
         asm!("{:x}", inout(reg) main => val_u64);
     }
 }
-
-// Constants must be... constant
-
-static S: i32 = 1;
-const fn const_foo(x: i32) -> i32 {
-    x
-}
-const fn const_bar<T>(x: T) -> T {
-    x
-}
-global_asm!("{}", const S);
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_foo(0));
-global_asm!("{}", const const_foo(S));
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_bar(0));
-global_asm!("{}", const const_bar(S));
-//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr
index c31a62ae7912a..b320abdc01b72 100644
--- a/src/test/ui/asm/aarch64/type-check-3.stderr
+++ b/src/test/ui/asm/aarch64/type-check-3.stderr
@@ -143,30 +143,5 @@ LL |         asm!("{:x}", inout(reg) main => val_u32);
    |
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:108:25
-   |
-LL | global_asm!("{}", const S);
-   |                         ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:111:35
-   |
-LL | global_asm!("{}", const const_foo(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:114:35
-   |
-LL | global_asm!("{}", const const_bar(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error: aborting due to 9 previous errors; 10 warnings emitted
+error: aborting due to 6 previous errors; 10 warnings emitted
 
-For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/aarch64/type-check-4.rs b/src/test/ui/asm/aarch64/type-check-4.rs
new file mode 100644
index 0000000000000..bd23755c02316
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-4.rs
@@ -0,0 +1,32 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(repr_simd, stdsimd, asm_const)]
+
+use std::arch::aarch64::float64x2_t;
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct Simd256bit(f64, f64, f64, f64);
+
+fn main() {
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+    x
+}
+const fn const_bar<T>(x: T) -> T {
+    x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/aarch64/type-check-4.stderr b/src/test/ui/asm/aarch64/type-check-4.stderr
new file mode 100644
index 0000000000000..4837e647beae1
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:25:25
+   |
+LL | global_asm!("{}", const S);
+   |                         ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:28:35
+   |
+LL | global_asm!("{}", const const_foo(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:31:35
+   |
+LL | global_asm!("{}", const const_bar(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
index 11c4e01f4186d..7ef93e15f5ba1 100644
--- a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `w` modifier to have the register formatted as `w0`
+   = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
index 11c4e01f4186d..7ef93e15f5ba1 100644
--- a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `w` modifier to have the register formatted as `w0`
+   = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
index b062c45e6ea34..556371747920e 100644
--- a/src/test/ui/asm/bad-template.rs
+++ b/src/test/ui/asm/bad-template.rs
@@ -49,6 +49,7 @@ fn main() {
         //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
         asm!("{:foo}", in(reg) foo);
         //~^ ERROR asm template modifier must be a single character
+        //~| WARN formatting may not be suitable for sub-register argument [asm_sub_register]
         asm!("", in(reg) 0, in(reg) 1);
         //~^ ERROR multiple unused asm arguments
     }
diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
index c198e0a69dde1..250bc3be42ebb 100644
--- a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `e` modifier to have the register formatted as `eax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
index c198e0a69dde1..250bc3be42ebb 100644
--- a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
@@ -89,7 +89,7 @@ LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:52:18
+  --> $DIR/bad-template.rs:53:18
    |
 LL |         asm!("", in(reg) 0, in(reg) 1);
    |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -99,7 +99,7 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:58:14
+  --> $DIR/bad-template.rs:59:14
    |
 LL | global_asm!("{}");
    |              ^^ from here
@@ -107,7 +107,7 @@ LL | global_asm!("{}");
    = note: no arguments were given
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:60:14
+  --> $DIR/bad-template.rs:61:14
    |
 LL | global_asm!("{1}", const FOO);
    |              ^^^ from here
@@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO);
    = note: there is 1 argument
 
 error: argument never used
-  --> $DIR/bad-template.rs:60:20
+  --> $DIR/bad-template.rs:61:20
    |
 LL | global_asm!("{1}", const FOO);
    |                    ^^^^^^^^^ argument never used
@@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
-  --> $DIR/bad-template.rs:63:15
+  --> $DIR/bad-template.rs:64:15
    |
 LL | global_asm!("{a}");
    |               ^
 
 error: invalid reference to argument at index 0
-  --> $DIR/bad-template.rs:65:14
+  --> $DIR/bad-template.rs:66:14
    |
 LL | global_asm!("{}", a = const FOO);
    |              ^^   ------------- named argument
@@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO);
    |
    = note: no positional arguments were given
 note: named arguments cannot be referenced by position
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^
 
 error: named argument never used
-  --> $DIR/bad-template.rs:65:19
+  --> $DIR/bad-template.rs:66:19
    |
 LL | global_asm!("{}", a = const FOO);
    |                   ^^^^^^^^^^^^^ named argument never used
@@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
-  --> $DIR/bad-template.rs:68:14
+  --> $DIR/bad-template.rs:69:14
    |
 LL | global_asm!("{1}", a = const FOO);
    |              ^^^ from here
@@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO);
    = note: no positional arguments were given
 
 error: named argument never used
-  --> $DIR/bad-template.rs:68:20
+  --> $DIR/bad-template.rs:69:20
    |
 LL | global_asm!("{1}", a = const FOO);
    |                    ^^^^^^^^^^^^^ named argument never used
@@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: asm template modifier must be a single character
-  --> $DIR/bad-template.rs:71:16
+  --> $DIR/bad-template.rs:72:16
    |
 LL | global_asm!("{:foo}", const FOO);
    |                ^^^
 
 error: multiple unused asm arguments
-  --> $DIR/bad-template.rs:73:17
+  --> $DIR/bad-template.rs:74:17
    |
 LL | global_asm!("", const FOO, const FOO);
    |                 ^^^^^^^^^  ^^^^^^^^^ argument never used
@@ -183,5 +183,15 @@ LL | global_asm!("", const FOO, const FOO);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 21 previous errors
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/bad-template.rs:50:15
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |               ^^^^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `e` modifier to have the register formatted as `eax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
index 2a57afa1a6a6e..9e626f5711db4 100644
--- a/src/test/ui/asm/naked-functions.rs
+++ b/src/test/ui/asm/naked-functions.rs
@@ -37,6 +37,7 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 {
 }
 
 #[naked]
+#[allow(asm_sub_register)]
 pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
     asm!("/* {0} */", in(reg) a, options(noreturn));
     //~^ ERROR referencing function parameters is not allowed in naked functions
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
index 8a610b25f0039..1828066b692a4 100644
--- a/src/test/ui/asm/naked-functions.stderr
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -1,23 +1,23 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:110:14
+  --> $DIR/naked-functions.rs:111:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:202:5
+  --> $DIR/naked-functions.rs:203:5
    |
 LL |     compile_error!("this is a user specified error")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:208:5
+  --> $DIR/naked-functions.rs:209:5
    |
 LL |     compile_error!("this is a user specified error");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/naked-functions.rs:215:10
+  --> $DIR/naked-functions.rs:216:10
    |
 LL |     asm!(invalid_syntax)
    |          ^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:41:31
+  --> $DIR/naked-functions.rs:42:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -74,13 +74,13 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:41:23
+  --> $DIR/naked-functions.rs:42:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:47:1
+  --> $DIR/naked-functions.rs:48:1
    |
 LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
 LL | |
@@ -90,7 +90,7 @@ LL | | }
    | |_^
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:64:10
+  --> $DIR/naked-functions.rs:65:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -105,7 +105,7 @@ LL |          out(reg) e,
    |          ^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:62:5
+  --> $DIR/naked-functions.rs:63:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -122,7 +122,7 @@ LL |          sym G, options(noreturn),
    |               +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:53:1
+  --> $DIR/naked-functions.rs:54:1
    |
 LL | / pub unsafe extern "C" fn unsupported_operands() {
 LL | |
@@ -142,7 +142,7 @@ LL | | }
    | |_^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:76:1
+  --> $DIR/naked-functions.rs:77:1
    |
 LL | / pub extern "C" fn missing_assembly() {
 LL | |
@@ -150,7 +150,7 @@ LL | | }
    | |_^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:83:5
+  --> $DIR/naked-functions.rs:84:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -161,7 +161,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:85:5
+  --> $DIR/naked-functions.rs:86:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -172,7 +172,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:87:5
+  --> $DIR/naked-functions.rs:88:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -183,7 +183,7 @@ LL |     asm!("", options(noreturn));
    |            +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:81:1
+  --> $DIR/naked-functions.rs:82:1
    |
 LL | / pub extern "C" fn too_many_asm_blocks() {
 LL | |
@@ -201,7 +201,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:96:11
+  --> $DIR/naked-functions.rs:97:11
    |
 LL |         *&y
    |           ^
@@ -209,7 +209,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:94:5
+  --> $DIR/naked-functions.rs:95:5
    |
 LL | /     pub extern "C" fn inner(y: usize) -> usize {
 LL | |
@@ -220,19 +220,19 @@ LL | |     }
    | |_____^
 
 error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:104:5
+  --> $DIR/naked-functions.rs:105:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:110:5
+  --> $DIR/naked-functions.rs:111:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:110:5
+  --> $DIR/naked-functions.rs:111:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -243,13 +243,13 @@ LL |     asm!("", options(noreturn), options(readonly, nostack), options(pure));
    |            +++++++++++++++++++
 
 error[E0787]: asm options unsupported in naked functions: `may_unwind`
-  --> $DIR/naked-functions.rs:118:5
+  --> $DIR/naked-functions.rs:119:5
    |
 LL |     asm!("", options(noreturn, may_unwind));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:123:15
+  --> $DIR/naked-functions.rs:124:15
    |
 LL | pub unsafe fn default_abi() {
    |               ^^^^^^^^^^^
@@ -257,43 +257,43 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:129:15
+  --> $DIR/naked-functions.rs:130:15
    |
 LL | pub unsafe fn rust_abi() {
    |               ^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:169:1
+  --> $DIR/naked-functions.rs:170:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:176:1
+  --> $DIR/naked-functions.rs:177:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:183:1
+  --> $DIR/naked-functions.rs:184:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:190:1
+  --> $DIR/naked-functions.rs:191:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:192:1
+  --> $DIR/naked-functions.rs:193:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:194:1
+  --> $DIR/naked-functions.rs:195:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
index 367a035387bc8..50b369ae04527 100644
--- a/src/test/ui/asm/type-check-1.rs
+++ b/src/test/ui/asm/type-check-1.rs
@@ -22,10 +22,13 @@ fn main() {
         let v: [u64; 3] = [0, 1, 2];
         asm!("{}", in(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
         asm!("{}", out(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
         asm!("{}", inout(reg) v[..]);
         //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        //~| ERROR cannot use value of type `[u64]` for inline assembly
 
         // Constants must be... constant
 
diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr
index bf5ea1befb69e..52d814ce6829c 100644
--- a/src/test/ui/asm/type-check-1.stderr
+++ b/src/test/ui/asm/type-check-1.stderr
@@ -1,5 +1,5 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:39:26
+  --> $DIR/type-check-1.rs:42:26
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -8,7 +8,7 @@ LL |         asm!("{}", const x);
    |                          ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:42:36
+  --> $DIR/type-check-1.rs:45:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -17,7 +17,7 @@ LL |         asm!("{}", const const_foo(x));
    |                                    ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:45:36
+  --> $DIR/type-check-1.rs:48:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -26,7 +26,7 @@ LL |         asm!("{}", const const_bar(x));
    |                                    ^ non-constant value
 
 error: invalid `sym` operand
-  --> $DIR/type-check-1.rs:47:24
+  --> $DIR/type-check-1.rs:50:24
    |
 LL |         asm!("{}", sym x);
    |                        ^ is a local variable
@@ -34,13 +34,13 @@ LL |         asm!("{}", sym x);
    = help: `sym` operands must refer to either a function or a static
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:55:26
+  --> $DIR/type-check-1.rs:58:26
    |
 LL |         asm!("{}", const 0f32);
    |                          ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:57:26
+  --> $DIR/type-check-1.rs:60:26
    |
 LL |         asm!("{}", const 0 as *mut u8);
    |                          ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -49,7 +49,7 @@ LL |         asm!("{}", const 0 as *mut u8);
            found raw pointer `*mut u8`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:59:26
+  --> $DIR/type-check-1.rs:62:26
    |
 LL |         asm!("{}", const &0);
    |                          ^^ expected integer, found `&{integer}`
@@ -82,7 +82,7 @@ LL |         asm!("{}", in(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:25:29
+  --> $DIR/type-check-1.rs:26:29
    |
 LL |         asm!("{}", out(reg) v[..]);
    |                             ^^^^^ doesn't have a size known at compile-time
@@ -91,7 +91,7 @@ LL |         asm!("{}", out(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:27:31
+  --> $DIR/type-check-1.rs:29:31
    |
 LL |         asm!("{}", inout(reg) v[..]);
    |                               ^^^^^ doesn't have a size known at compile-time
@@ -99,14 +99,38 @@ LL |         asm!("{}", inout(reg) v[..]);
    = help: the trait `Sized` is not implemented for `[u64]`
    = note: all inline asm arguments must have a statically known size
 
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:23:28
+   |
+LL |         asm!("{}", in(reg) v[..]);
+   |                            ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:26:29
+   |
+LL |         asm!("{}", out(reg) v[..]);
+   |                             ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+  --> $DIR/type-check-1.rs:29:31
+   |
+LL |         asm!("{}", inout(reg) v[..]);
+   |                               ^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:73:25
+  --> $DIR/type-check-1.rs:76:25
    |
 LL | global_asm!("{}", const 0f32);
    |                         ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:75:25
+  --> $DIR/type-check-1.rs:78:25
    |
 LL | global_asm!("{}", const 0 as *mut u8);
    |                         ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -114,7 +138,7 @@ LL | global_asm!("{}", const 0 as *mut u8);
    = note:     expected type `{integer}`
            found raw pointer `*mut u8`
 
-error: aborting due to 14 previous errors
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0435.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs
index 272372ebedc1d..a4f50a534a158 100644
--- a/src/test/ui/asm/x86_64/bad-reg.rs
+++ b/src/test/ui/asm/x86_64/bad-reg.rs
@@ -32,16 +32,21 @@ fn main() {
 
         asm!("", in("st(2)") foo);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("mm0") foo);
         //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("k0") foo);
         //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", out("st(2)") _);
         asm!("", out("mm0") _);
         asm!("{}", in(x87_reg) foo);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("{}", in(mmx_reg) foo);
         //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+        //~| ERROR `i32` cannot be used with this register class
         asm!("{}", out(x87_reg) _);
         //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
         asm!("{}", out(mmx_reg) _);
@@ -52,9 +57,12 @@ fn main() {
 
         asm!("", in("eax") foo, in("al") bar);
         //~^ ERROR register `al` conflicts with register `ax`
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("rax") foo, out("rax") bar);
         //~^ ERROR register `ax` conflicts with register `ax`
         asm!("", in("al") foo, lateout("al") bar);
+        //~^ ERROR `i32` cannot be used with this register class
+        //~| ERROR `i32` cannot be used with this register class
         asm!("", in("xmm0") foo, in("ymm0") bar);
         //~^ ERROR register `ymm0` conflicts with register `xmm0`
         asm!("", in("xmm0") foo, out("ymm0") bar);
diff --git a/src/test/ui/asm/x86_64/bad-reg.stderr b/src/test/ui/asm/x86_64/bad-reg.stderr
index 84b8b5ec2850b..82b7ebd0fb07a 100644
--- a/src/test/ui/asm/x86_64/bad-reg.stderr
+++ b/src/test/ui/asm/x86_64/bad-reg.stderr
@@ -71,43 +71,43 @@ LL |         asm!("", in("st(2)") foo);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", in("mm0") foo);
    |                  ^^^^^^^^^^^^^
 
 error: register class `kreg0` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:39:18
    |
 LL |         asm!("", in("k0") foo);
    |                  ^^^^^^^^^^^^
 
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:41:20
+  --> $DIR/bad-reg.rs:44:20
    |
 LL |         asm!("{}", in(x87_reg) foo);
    |                    ^^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:43:20
+  --> $DIR/bad-reg.rs:47:20
    |
 LL |         asm!("{}", in(mmx_reg) foo);
    |                    ^^^^^^^^^^^^^^^
 
 error: register class `x87_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:45:20
+  --> $DIR/bad-reg.rs:50:20
    |
 LL |         asm!("{}", out(x87_reg) _);
    |                    ^^^^^^^^^^^^^^
 
 error: register class `mmx_reg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:47:20
+  --> $DIR/bad-reg.rs:52:20
    |
 LL |         asm!("{}", out(mmx_reg) _);
    |                    ^^^^^^^^^^^^^^
 
 error: register `al` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:53:33
+  --> $DIR/bad-reg.rs:58:33
    |
 LL |         asm!("", in("eax") foo, in("al") bar);
    |                  -------------  ^^^^^^^^^^^^ register `al`
@@ -115,7 +115,7 @@ LL |         asm!("", in("eax") foo, in("al") bar);
    |                  register `ax`
 
 error: register `ax` conflicts with register `ax`
-  --> $DIR/bad-reg.rs:55:33
+  --> $DIR/bad-reg.rs:61:33
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  -------------  ^^^^^^^^^^^^^^ register `ax`
@@ -123,13 +123,13 @@ LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  register `ax`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:55:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", in("rax") foo, out("rax") bar);
    |                  ^^^^^^^^^^^^^
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:58:34
+  --> $DIR/bad-reg.rs:66:34
    |
 LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^ register `ymm0`
@@ -137,7 +137,7 @@ LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
    |                  register `xmm0`
 
 error: register `ymm0` conflicts with register `xmm0`
-  --> $DIR/bad-reg.rs:60:34
+  --> $DIR/bad-reg.rs:68:34
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  --------------  ^^^^^^^^^^^^^^^ register `ymm0`
@@ -145,10 +145,74 @@ LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  register `xmm0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:60:18
+  --> $DIR/bad-reg.rs:68:18
    |
 LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
    |                  ^^^^^^^^^^^^^^
 
-error: aborting due to 20 previous errors
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:33:30
+   |
+LL |         asm!("", in("st(2)") foo);
+   |                              ^^^
+   |
+   = note: register class `x87_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:36:28
+   |
+LL |         asm!("", in("mm0") foo);
+   |                            ^^^
+   |
+   = note: register class `mmx_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:39:27
+   |
+LL |         asm!("", in("k0") foo);
+   |                           ^^^
+   |
+   = note: register class `kreg0` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:44:32
+   |
+LL |         asm!("{}", in(x87_reg) foo);
+   |                                ^^^
+   |
+   = note: register class `x87_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:47:32
+   |
+LL |         asm!("{}", in(mmx_reg) foo);
+   |                                ^^^
+   |
+   = note: register class `mmx_reg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:58:42
+   |
+LL |         asm!("", in("eax") foo, in("al") bar);
+   |                                          ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:63:27
+   |
+LL |         asm!("", in("al") foo, lateout("al") bar);
+   |                           ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:63:46
+   |
+LL |         asm!("", in("al") foo, lateout("al") bar);
+   |                                              ^^^
+   |
+   = note: register class `reg_byte` supports these types: i8
+
+error: aborting due to 28 previous errors
 
diff --git a/src/test/ui/asm/x86_64/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs
index eb87ea91085f0..59d8cde3fb6c7 100644
--- a/src/test/ui/asm/x86_64/type-check-2.rs
+++ b/src/test/ui/asm/x86_64/type-check-2.rs
@@ -13,10 +13,8 @@ fn main() {
 
         let x: u64;
         asm!("{}", in(reg) x);
-        //~^ ERROR use of possibly-uninitialized variable: `x`
         let mut y: u64;
         asm!("{}", inout(reg) y);
-        //~^ ERROR use of possibly-uninitialized variable: `y`
         let _ = y;
 
         // Outputs require mutable places
@@ -24,9 +22,7 @@ fn main() {
         let v: Vec<u64> = vec![0, 1, 2];
         asm!("{}", in(reg) v[0]);
         asm!("{}", out(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
         asm!("{}", inout(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
 
         // Sym operands must point to a function or static
 
@@ -36,6 +32,8 @@ fn main() {
         asm!("{}", sym main);
         asm!("{}", sym C);
         //~^ ERROR invalid `sym` operand
+        asm!("{}", sym x);
+        //~^ ERROR invalid `sym` operand
 
         // Register operands must be Copy
 
diff --git a/src/test/ui/asm/x86_64/type-check-2.stderr b/src/test/ui/asm/x86_64/type-check-2.stderr
index cb3960acdf9d3..46baeb511ca77 100644
--- a/src/test/ui/asm/x86_64/type-check-2.stderr
+++ b/src/test/ui/asm/x86_64/type-check-2.stderr
@@ -1,13 +1,37 @@
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:35:24
+   |
+LL |         asm!("{}", sym x);
+   |                        ^ is a local variable
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:86:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:33:20
+   |
+LL |         asm!("{}", sym C);
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error: arguments for inline assembly must be copyable
-  --> $DIR/type-check-2.rs:42:32
+  --> $DIR/type-check-2.rs:40:32
    |
 LL |         asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `SimdNonCopy` does not implement the Copy trait
 
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
-  --> $DIR/type-check-2.rs:54:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:38]` for inline assembly
+  --> $DIR/type-check-2.rs:52:28
    |
 LL |         asm!("{}", in(reg) |x: i32| x);
    |                            ^^^^^^^^^^
@@ -15,7 +39,7 @@ LL |         asm!("{}", in(reg) |x: i32| x);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `Vec<i32>` for inline assembly
-  --> $DIR/type-check-2.rs:56:28
+  --> $DIR/type-check-2.rs:54:28
    |
 LL |         asm!("{}", in(reg) vec![0]);
    |                            ^^^^^^^
@@ -24,7 +48,7 @@ LL |         asm!("{}", in(reg) vec![0]);
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot use value of type `(i32, i32, i32)` for inline assembly
-  --> $DIR/type-check-2.rs:58:28
+  --> $DIR/type-check-2.rs:56:28
    |
 LL |         asm!("{}", in(reg) (1, 2, 3));
    |                            ^^^^^^^^^
@@ -32,7 +56,7 @@ LL |         asm!("{}", in(reg) (1, 2, 3));
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[i32; 3]` for inline assembly
-  --> $DIR/type-check-2.rs:60:28
+  --> $DIR/type-check-2.rs:58:28
    |
 LL |         asm!("{}", in(reg) [1, 2, 3]);
    |                            ^^^^^^^^^
@@ -40,7 +64,7 @@ LL |         asm!("{}", in(reg) [1, 2, 3]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `fn() {main}` for inline assembly
-  --> $DIR/type-check-2.rs:68:31
+  --> $DIR/type-check-2.rs:66:31
    |
 LL |         asm!("{}", inout(reg) f);
    |                               ^
@@ -48,60 +72,12 @@ LL |         asm!("{}", inout(reg) f);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `&mut i32` for inline assembly
-  --> $DIR/type-check-2.rs:71:31
+  --> $DIR/type-check-2.rs:69:31
    |
 LL |         asm!("{}", inout(reg) r);
    |                               ^
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:37:20
-   |
-LL |         asm!("{}", sym C);
-   |                    ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:88:19
-   |
-LL | global_asm!("{}", sym C);
-   |                   ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/type-check-2.rs:15:28
-   |
-LL |         asm!("{}", in(reg) x);
-   |                            ^ use of possibly-uninitialized `x`
-
-error[E0381]: use of possibly-uninitialized variable: `y`
-  --> $DIR/type-check-2.rs:18:9
-   |
-LL |         asm!("{}", inout(reg) y);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:26:29
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-LL |         asm!("{}", in(reg) v[0]);
-LL |         asm!("{}", out(reg) v[0]);
-   |                             ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-2.rs:28:31
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-...
-LL |         asm!("{}", inout(reg) v[0]);
-   |                               ^ cannot borrow as mutable
-
-error: aborting due to 13 previous errors
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0381, E0596.
-For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/x86_64/type-check-3.rs b/src/test/ui/asm/x86_64/type-check-3.rs
index 595de55fd8bc8..89c849c75234e 100644
--- a/src/test/ui/asm/x86_64/type-check-3.rs
+++ b/src/test/ui/asm/x86_64/type-check-3.rs
@@ -71,21 +71,3 @@ fn main() {
         asm!("{:r}", inout(reg) main => val_u64);
     }
 }
-
-// Constants must be... constant
-
-static S: i32 = 1;
-const fn const_foo(x: i32) -> i32 {
-    x
-}
-const fn const_bar<T>(x: T) -> T {
-    x
-}
-global_asm!("{}", const S);
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_foo(0));
-global_asm!("{}", const const_foo(S));
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_bar(0));
-global_asm!("{}", const const_bar(S));
-//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/x86_64/type-check-3.stderr b/src/test/ui/asm/x86_64/type-check-3.stderr
index aeb638d6949ce..b38ea8cc4d8ee 100644
--- a/src/test/ui/asm/x86_64/type-check-3.stderr
+++ b/src/test/ui/asm/x86_64/type-check-3.stderr
@@ -114,30 +114,5 @@ LL |         asm!("{:r}", inout(reg) main => val_u32);
    |
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:84:25
-   |
-LL | global_asm!("{}", const S);
-   |                         ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:87:35
-   |
-LL | global_asm!("{}", const const_foo(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:90:35
-   |
-LL | global_asm!("{}", const const_bar(S));
-   |                                   ^
-   |
-   = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error: aborting due to 12 previous errors; 4 warnings emitted
+error: aborting due to 9 previous errors; 4 warnings emitted
 
-For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/x86_64/type-check-4.rs b/src/test/ui/asm/x86_64/type-check-4.rs
new file mode 100644
index 0000000000000..da3b76c3d23a6
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+fn main() {
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+    x
+}
+const fn const_bar<T>(x: T) -> T {
+    x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
diff --git a/src/test/ui/asm/x86_64/type-check-4.stderr b/src/test/ui/asm/x86_64/type-check-4.stderr
new file mode 100644
index 0000000000000..33f4638fb4b37
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:22:25
+   |
+LL | global_asm!("{}", const S);
+   |                         ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:25:35
+   |
+LL | global_asm!("{}", const const_foo(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-4.rs:28:35
+   |
+LL | global_asm!("{}", const const_bar(S));
+   |                                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs
new file mode 100644
index 0000000000000..474478f6a88e1
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.rs
@@ -0,0 +1,63 @@
+// only-x86_64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::asm;
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+    unsafe {
+        // Inputs must be initialized
+
+        let x: u64;
+        asm!("{}", in(reg) x);
+        //~^ ERROR use of possibly-uninitialized variable: `x`
+        let mut y: u64;
+        asm!("{}", inout(reg) y);
+        //~^ ERROR use of possibly-uninitialized variable: `y`
+        let _ = y;
+
+        // Outputs require mutable places
+
+        let v: Vec<u64> = vec![0, 1, 2];
+        asm!("{}", in(reg) v[0]);
+        asm!("{}", out(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+        asm!("{}", inout(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+        // Sym operands must point to a function or static
+
+        const C: i32 = 0;
+        static S: i32 = 0;
+        asm!("{}", sym S);
+        asm!("{}", sym main);
+
+        // Register operands must be Copy
+
+        // Register operands must be integers, floats, SIMD vectors, pointers or
+        // function pointers.
+
+        asm!("{}", in(reg) 0i64);
+        asm!("{}", in(reg) 0f64);
+        asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+        asm!("{}", in(reg) 0 as *const u8);
+        asm!("{}", in(reg) 0 as *mut u8);
+        asm!("{}", in(reg) main as fn());
+
+        // Register inputs (but not outputs) allow references and function types
+
+        let mut f = main;
+        let mut r = &mut 0;
+        asm!("{}", in(reg) f);
+        asm!("{}", in(reg) r);
+        let _ = (f, r);
+
+        // Type checks ignore never type
+
+        let u: ! = unreachable!();
+        asm!("{}", in(reg) u);
+    }
+}
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
new file mode 100644
index 0000000000000..181ecaf585585
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -0,0 +1,34 @@
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/type-check-5.rs:15:28
+   |
+LL |         asm!("{}", in(reg) x);
+   |                            ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/type-check-5.rs:18:9
+   |
+LL |         asm!("{}", inout(reg) y);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-5.rs:26:29
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         asm!("{}", in(reg) v[0]);
+LL |         asm!("{}", out(reg) v[0]);
+   |                             ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-5.rs:28:31
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         asm!("{}", inout(reg) v[0]);
+   |                               ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/consts/issue-91434.rs b/src/test/ui/consts/issue-91434.rs
index fc7731291b371..001dc708f8932 100644
--- a/src/test/ui/consts/issue-91434.rs
+++ b/src/test/ui/consts/issue-91434.rs
@@ -2,5 +2,4 @@ fn main() {
     [9; [[9E; h]]];
     //~^ ERROR: expected at least one digit in exponent
     //~| ERROR: cannot find value `h` in this scope [E0425]
-    //~| ERROR: constant expression depends on a generic parameter
 }
diff --git a/src/test/ui/consts/issue-91434.stderr b/src/test/ui/consts/issue-91434.stderr
index 9d3fe5f201656..08d3ad77053d5 100644
--- a/src/test/ui/consts/issue-91434.stderr
+++ b/src/test/ui/consts/issue-91434.stderr
@@ -10,14 +10,6 @@ error[E0425]: cannot find value `h` in this scope
 LL |     [9; [[9E; h]]];
    |               ^ not found in this scope
 
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-91434.rs:2:9
-   |
-LL |     [9; [[9E; h]]];
-   |         ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/consts/nested_erroneous_ctfe.rs b/src/test/ui/consts/nested_erroneous_ctfe.rs
new file mode 100644
index 0000000000000..1ec271401fb4c
--- /dev/null
+++ b/src/test/ui/consts/nested_erroneous_ctfe.rs
@@ -0,0 +1,4 @@
+fn main() {
+    [9; || [9; []]];
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/consts/nested_erroneous_ctfe.stderr b/src/test/ui/consts/nested_erroneous_ctfe.stderr
new file mode 100644
index 0000000000000..d579a54e9836f
--- /dev/null
+++ b/src/test/ui/consts/nested_erroneous_ctfe.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/nested_erroneous_ctfe.rs:2:16
+   |
+LL |     [9; || [9; []]];
+   |                ^^ expected `usize`, found array of 0 elements
+   |
+   = note: expected type `usize`
+             found array `[_; 0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
index 2e1d5d26b5c75..852a5b3b46a21 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
@@ -5,15 +5,9 @@
 
 fn main() {
     match &b""[..] {
-        ZST => {} //~ ERROR could not evaluate constant pattern
-                  //~| ERROR could not evaluate constant pattern
+        ZST => {}
     }
 }
 
 const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
-//~^ ERROR any use of this value will cause an error
-//~| ERROR cannot transmute between types of different sizes
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-// Once the `any use of this value will cause an error` disappears in this test, make sure to
-// remove the `TransmuteSizeDiff` error variant and make its emitter site an assertion again.
+//~^ ERROR cannot transmute between types of different sizes
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
index 27cc2f5e66a33..4e8470173a101 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -1,23 +1,5 @@
-error: any use of this value will cause an error
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
-   |
-LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             transmuting `usize` to `&[u8]` is not possible, because these types do not have the same size
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
-   |
-LL |         ZST => {}
-   |         ^^^
-
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:12:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
@@ -25,12 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    = note: source type: `usize` (word size)
    = note: target type: `&[u8]` (2 * word size)
 
-error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
-   |
-LL |         ZST => {}
-   |         ^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
index 0045d608133a6..43e33cbb12061 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -4,6 +4,7 @@
 use std::arch::asm;
 
 #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+//~^ ERROR `#[track_caller]` requires Rust ABI
 #[naked]
 extern "C" fn f() {
     asm!("", options(noreturn));
@@ -13,6 +14,7 @@ struct S;
 
 impl S {
     #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+    //~^ ERROR `#[track_caller]` requires Rust ABI
     #[naked]
     extern "C" fn g() {
         asm!("", options(noreturn));
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
index d33aecc0f97bf..3f7d0df42a00a 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
@@ -5,11 +5,24 @@ LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
 error[E0736]: cannot use `#[track_caller]` with `#[naked]`
-  --> $DIR/error-with-naked.rs:15:5
+  --> $DIR/error-with-naked.rs:16:5
    |
 LL |     #[track_caller]
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0737]: `#[track_caller]` requires Rust ABI
+  --> $DIR/error-with-naked.rs:6:1
+   |
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+
+error[E0737]: `#[track_caller]` requires Rust ABI
+  --> $DIR/error-with-naked.rs:16:5
+   |
+LL |     #[track_caller]
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0736`.
+Some errors have detailed explanations: E0736, E0737.
+For more information about an error, try `rustc --explain E0736`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.rs b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs
new file mode 100644
index 0000000000000..438ac35fdea51
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+type Bug<T, U> = impl Fn(T) -> U + Copy; //~ ERROR cycle detected
+
+const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+//~^ ERROR: cannot transmute
+
+fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+    |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
+}
+
+fn main() {
+    CONST_BUG(0);
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr
new file mode 100644
index 0000000000000..f4a0cdb1625b8
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -0,0 +1,55 @@
+error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:6:1
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `Bug<u8, ()>`...
+   = note: ...which requires normalizing `Bug<u8, ()>`...
+   = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/issue-53092-2.rs:1:1
+   |
+LL | / #![feature(type_alias_impl_trait)]
+LL | | #![allow(dead_code)]
+LL | |
+LL | | type Bug<T, U> = impl Fn(T) -> U + Copy;
+...  |
+LL | |     CONST_BUG(0);
+LL | | }
+   | |_^
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/issue-53092-2.rs:6:41
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   |                                         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:71]` (0 bits)
+   = note: target type: `Bug<u8, ()>` (size can vary because of [type error])
+
+error[E0277]: the trait bound `U: From<T>` is not satisfied
+  --> $DIR/issue-53092-2.rs:10:5
+   |
+LL |     |x| x.into()
+   |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
+   |
+note: required by a bound in `make_bug`
+  --> $DIR/issue-53092-2.rs:9:19
+   |
+LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+   |                   ^^^^^^^ required by this bound in `make_bug`
+help: consider restricting type parameter `U`
+   |
+LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
+   |              +++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0391, E0512.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092.rs b/src/test/ui/type-alias-impl-trait/issue-53092.rs
index 45792ba97a7a0..1be5b46d6df68 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53092.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53092.rs
@@ -3,7 +3,12 @@
 
 type Bug<T, U> = impl Fn(T) -> U + Copy;
 
-const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+union Moo {
+    x: Bug<u8, ()>,
+    y: (),
+}
+
+const CONST_BUG: Bug<u8, ()> = unsafe { Moo { y: () }.x };
 
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
     |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
diff --git a/src/test/ui/type-alias-impl-trait/issue-53092.stderr b/src/test/ui/type-alias-impl-trait/issue-53092.stderr
index 2d423a0c0dff5..2109cf8a784dc 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53092.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53092.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092.rs:9:5
+  --> $DIR/issue-53092.rs:14:5
    |
 LL |     |x| x.into()
    |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
 note: required by a bound in `make_bug`
-  --> $DIR/issue-53092.rs:8:19
+  --> $DIR/issue-53092.rs:13:19
    |
 LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |                   ^^^^^^^ required by this bound in `make_bug`
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
index fa578eced5f2b..46621362e4f73 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
@@ -3,13 +3,17 @@
 
 #![feature(type_alias_impl_trait)]
 
-type Foo = impl Copy; //~ unconstrained opaque type
+mod foo {
+    pub type Foo = impl Copy;
+    //~^ ERROR unconstrained opaque type
 
-// make compiler happy about using 'Foo'
-fn bar(x: Foo) -> Foo {
-    x
+    // make compiler happy about using 'Foo'
+    pub fn bar(x: Foo) -> Foo {
+        x
+    }
 }
 
 fn main() {
-    let _: Foo = std::mem::transmute(0u8);
+    let _: foo::Foo = std::mem::transmute(0u8);
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
 }
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index 009935347e66c..337708b876524 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,10 +1,20 @@
 error: unconstrained opaque type
-  --> $DIR/no_inferrable_concrete_type.rs:6:12
+  --> $DIR/no_inferrable_concrete_type.rs:7:20
    |
-LL | type Foo = impl Copy;
-   |            ^^^^^^^^^
+LL |     pub type Foo = impl Copy;
+   |                    ^^^^^^^^^
    |
    = note: `Foo` must be used in combination with a concrete type within the same module
 
-error: aborting due to previous error
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/no_inferrable_concrete_type.rs:17:23
+   |
+LL |     let _: foo::Foo = std::mem::transmute(0u8);
+   |                       ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `u8` (8 bits)
+   = note: target type: `Foo` (size can vary because of [type error])
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0512`.