about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs155
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs13
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs124
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs65
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs129
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs30
-rw-r--r--src/bootstrap/bootstrap.py19
-rw-r--r--src/bootstrap/download.rs4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs16
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr15
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs7
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr15
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.rs)0
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.stderr)4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.rs)0
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.stderr)4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.rs)0
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.stderr)4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.rs)0
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.stderr)4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.rs)0
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr (renamed from src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.stderr)4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs11
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr15
-rw-r--r--src/tools/miri/tests/pass/function_calls/abi_compat.rs28
-rw-r--r--tests/run-make/pgo-branch-weights/Makefile1
-rw-r--r--tests/run-make/pgo-gen-lto/Makefile1
-rw-r--r--tests/run-make/pgo-gen/Makefile1
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/Makefile1
-rw-r--r--tests/run-make/pgo-use/Makefile1
-rw-r--r--tests/run-make/pointer-auth-link-with-c/Makefile1
-rw-r--r--tests/run-make/profile/Makefile1
-rw-r--r--tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr4
-rw-r--r--tests/ui/mir/mir-inlining/always-encode-mirs.rs12
-rw-r--r--tests/ui/mir/mir-inlining/auxiliary/internal.rs7
-rw-r--r--tests/ui/traits/issue-105231.rs2
-rw-r--r--tests/ui/traits/issue-105231.stderr8
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs2
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr8
42 files changed, 448 insertions, 278 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 279a06d3868..a016bfa5cf8 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -2,12 +2,13 @@ use std::borrow::Cow;
 
 use either::Either;
 use rustc_ast::ast::InlineAsmOptions;
-use rustc_middle::mir::ProjectionElem;
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
-use rustc_middle::ty::Instance;
 use rustc_middle::{
     mir,
-    ty::{self, Ty},
+    ty::{
+        self,
+        layout::{FnAbiOf, LayoutOf, TyAndLayout},
+        Instance, Ty,
+    },
 };
 use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode};
 use rustc_target::abi::{self, FieldIdx};
@@ -252,11 +253,43 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .collect()
     }
 
-    fn check_argument_compat(
-        caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
-        callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+    /// Find the wrapped inner type of a transparent wrapper.
+    fn unfold_transparent(&self, layout: TyAndLayout<'tcx>) -> TyAndLayout<'tcx> {
+        match layout.ty.kind() {
+            ty::Adt(adt_def, _) if adt_def.repr().transparent() => {
+                assert!(!adt_def.is_enum());
+                // Find the non-1-ZST field.
+                let mut non_1zst_fields = (0..layout.fields.count()).filter_map(|idx| {
+                    let field = layout.field(self, idx);
+                    if field.is_1zst() { None } else { Some(field) }
+                });
+                let Some(first) = non_1zst_fields.next() else {
+                    // All fields are 1-ZST, so this is basically the same as `()`.
+                    // (We still also compare the `PassMode`, so if this target does something strange with 1-ZST there, we'll know.)
+                    return self.layout_of(self.tcx.types.unit).unwrap();
+                };
+                assert!(
+                    non_1zst_fields.next().is_none(),
+                    "more than one non-1-ZST field in a transparent type"
+                );
+
+                // Found it!
+                self.unfold_transparent(first)
+            }
+            // Not a transparent type, no further unfolding.
+            _ => layout,
+        }
+    }
+
+    /// Check if these two layouts look like they are fn-ABI-compatible.
+    /// (We also compare the `PassMode`, so this doesn't have to check everything. But it turns out
+    /// that only checking the `PassMode` is insufficient.)
+    fn layout_compat(
+        &self,
+        caller_layout: TyAndLayout<'tcx>,
+        callee_layout: TyAndLayout<'tcx>,
     ) -> bool {
-        let primitive_abi_compat = |a1: abi::Primitive, a2: abi::Primitive| -> bool {
+        fn primitive_abi_compat(a1: abi::Primitive, a2: abi::Primitive) -> bool {
             match (a1, a2) {
                 // For integers, ignore the sign.
                 (abi::Primitive::Int(int_ty1, _sign1), abi::Primitive::Int(int_ty2, _sign2)) => {
@@ -265,40 +298,49 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // For everything else we require full equality.
                 _ => a1 == a2,
             }
-        };
-        // Heuristic for type comparison.
-        let layout_compat = || {
-            if caller_abi.layout.ty == callee_abi.layout.ty {
-                // No question
-                return true;
+        }
+
+        if caller_layout.ty == callee_layout.ty {
+            // Fast path: equal types are definitely compatible.
+            return true;
+        }
+
+        match (caller_layout.abi, callee_layout.abi) {
+            // If both sides have Scalar/Vector/ScalarPair ABI, we can easily directly compare them.
+            // Different valid ranges are okay (the validity check will complain if this leads to
+            // invalid transmutes).
+            (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => {
+                primitive_abi_compat(caller.primitive(), callee.primitive())
             }
-            if caller_abi.layout.is_unsized() || callee_abi.layout.is_unsized() {
-                // No, no, no. We require the types to *exactly* match for unsized arguments. If
-                // these are somehow unsized "in a different way" (say, `dyn Trait` vs `[i32]`),
-                // then who knows what happens.
-                return false;
+            (
+                abi::Abi::Vector { element: caller_element, count: caller_count },
+                abi::Abi::Vector { element: callee_element, count: callee_count },
+            ) => {
+                primitive_abi_compat(caller_element.primitive(), callee_element.primitive())
+                    && caller_count == callee_count
             }
-            // This is tricky. Some ABIs split aggregates up into multiple registers etc, so we have
-            // to be super careful here. For the scalar ABIs we conveniently already have all the
-            // newtypes unwrapped etc, so in those cases we can just compare the scalar components.
-            // Everything else we just reject for now.
-            match (caller_abi.layout.abi, callee_abi.layout.abi) {
-                // Different valid ranges are okay (the validity check will complain if this leads
-                // to invalid transmutes).
-                (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => {
-                    primitive_abi_compat(caller.primitive(), callee.primitive())
-                }
-                (
-                    abi::Abi::ScalarPair(caller1, caller2),
-                    abi::Abi::ScalarPair(callee1, callee2),
-                ) => {
-                    primitive_abi_compat(caller1.primitive(), callee1.primitive())
-                        && primitive_abi_compat(caller2.primitive(), callee2.primitive())
-                }
-                // Be conservative.
-                _ => false,
+            (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => {
+                primitive_abi_compat(caller1.primitive(), callee1.primitive())
+                    && primitive_abi_compat(caller2.primitive(), callee2.primitive())
             }
-        };
+            (abi::Abi::Aggregate { .. }, abi::Abi::Aggregate { .. }) => {
+                // Aggregates are compatible only if they newtype-wrap the same type.
+                // This is conservative, but also means that our check isn't quite so heavily dependent on the `PassMode`,
+                // which means having ABI-compatibility on one target is much more likely to imply compatibility for other targets.
+                self.unfold_transparent(caller_layout).ty
+                    == self.unfold_transparent(callee_layout).ty
+            }
+            // What remains is `Abi::Uninhabited` (which can never be passed anyway) and
+            // mismatching ABIs, that should all be rejected.
+            _ => false,
+        }
+    }
+
+    fn check_argument_compat(
+        &self,
+        caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+        callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+    ) -> bool {
         // When comparing the PassMode, we have to be smart about comparing the attributes.
         let arg_attr_compat = |a1: &ArgAttributes, a2: &ArgAttributes| {
             // There's only one regular attribute that matters for the call ABI: InReg.
@@ -333,23 +375,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             _ => false,
         };
 
-        // We have to check both. `layout_compat` is needed to reject e.g. `i32` vs `f32`,
-        // which is not reflected in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`,
-        // which have the same `abi::Primitive` but different `arg_ext`.
-        if layout_compat() && mode_compat() {
+        // Ideally `PassMode` would capture everything there is about argument passing, but that is
+        // not the case: in `FnAbi::llvm_type`, also parts of the layout and type information are
+        // used. So we need to check that *both* sufficiently agree to ensures the arguments are
+        // compatible.
+        // For instance, `layout_compat` is needed to reject `i32` vs `f32`, which is not reflected
+        // in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`, which have the same
+        // `abi::Primitive` but different `arg_ext`.
+        if self.layout_compat(caller_abi.layout, callee_abi.layout) && mode_compat() {
             // Something went very wrong if our checks don't even imply that the layout is the same.
             assert!(
                 caller_abi.layout.size == callee_abi.layout.size
                     && caller_abi.layout.align.abi == callee_abi.layout.align.abi
+                    && caller_abi.layout.is_sized() == callee_abi.layout.is_sized()
             );
             return true;
+        } else {
+            trace!(
+                "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
+                caller_abi,
+                callee_abi
+            );
+            return false;
         }
-        trace!(
-            "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
-            caller_abi,
-            callee_abi
-        );
-        return false;
     }
 
     /// Initialize a single callee argument, checking the types for compatibility.
@@ -379,7 +427,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             throw_ub_custom!(fluent::const_eval_not_enough_caller_args);
         };
         // Check compatibility
-        if !Self::check_argument_compat(caller_abi, callee_abi) {
+        if !self.check_argument_compat(caller_abi, callee_abi) {
             let callee_ty = format!("{}", callee_ty);
             let caller_ty = format!("{}", caller_arg.layout().ty);
             throw_ub_custom!(
@@ -612,7 +660,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             };
                             for (i, field_ty) in fields.iter().enumerate() {
                                 let dest = dest.project_deeper(
-                                    &[ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)],
+                                    &[mir::ProjectionElem::Field(
+                                        FieldIdx::from_usize(i),
+                                        field_ty,
+                                    )],
                                     *self.tcx,
                                 );
                                 let callee_abi = callee_args_abis.next().unwrap();
@@ -649,7 +700,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         throw_ub_custom!(fluent::const_eval_too_many_caller_args);
                     }
                     // Don't forget to check the return type!
-                    if !Self::check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret) {
+                    if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret) {
                         let callee_ty = format!("{}", callee_fn_abi.ret.layout.ty);
                         let caller_ty = format!("{}", caller_fn_abi.ret.layout.ty);
                         throw_ub_custom!(
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 39f440e31e0..c2fe942fe37 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -55,7 +55,7 @@ use std::num::NonZeroUsize;
 use std::panic;
 use std::path::{Path, PathBuf};
 
-use termcolor::{Color, ColorSpec};
+pub use termcolor::{Color, ColorSpec, WriteColor};
 
 pub mod annotate_snippet_emitter_writer;
 mod diagnostic;
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8fedf4dca95..283c52a5538 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -238,7 +238,7 @@ pub struct ImplHeader<'tcx> {
     pub impl_def_id: DefId,
     pub self_ty: Ty<'tcx>,
     pub trait_ref: Option<TraitRef<'tcx>>,
-    pub predicates: Vec<(Predicate<'tcx>, Span)>,
+    pub predicates: Vec<Predicate<'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 9551c7a2a8d..7d4c4a823a8 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -388,14 +388,11 @@ impl<'tcx> Inliner<'tcx> {
             return Err("never inline hint");
         }
 
-        // Only inline local functions if they would be eligible for cross-crate
-        // inlining. This is to ensure that the final crate doesn't have MIR that
-        // reference unexported symbols
-        if callsite.callee.def_id().is_local() {
-            let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();
-            if !is_generic && !callee_attrs.requests_inline() {
-                return Err("not exported");
-            }
+        // Reachability pass defines which functions are eligible for inlining. Generally inlining
+        // other functions is incorrect because they could reference symbols that aren't exported.
+        let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();
+        if !is_generic && !callee_attrs.requests_inline() {
+            return Err("not exported");
         }
 
         if callsite.fn_sig.c_variadic() {
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
new file mode 100644
index 00000000000..33c75250adc
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -0,0 +1,124 @@
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
+
+use crate::{
+    rustc_internal::opaque,
+    rustc_smir::{Stable, Tables},
+    stable_mir::mir::Mutability,
+    stable_mir::ty::{Allocation, ProvenanceMap},
+};
+
+/// Creates new empty `Allocation` from given `Align`.
+fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
+    Allocation {
+        bytes: Vec::new(),
+        provenance: ProvenanceMap { ptrs: Vec::new() },
+        align: align.bytes(),
+        mutability: Mutability::Not,
+    }
+}
+
+// We need this method instead of a Stable implementation
+// because we need to get `Ty` of the const we are trying to create, to do that
+// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
+#[allow(rustc::usage_of_qualified_ty)]
+pub fn new_allocation<'tcx>(
+    ty: rustc_middle::ty::Ty<'tcx>,
+    const_value: ConstValue<'tcx>,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    match const_value {
+        ConstValue::Scalar(scalar) => {
+            let size = scalar.size();
+            let align = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
+                .unwrap()
+                .align;
+            let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
+            allocation
+                .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ZeroSized => {
+            let align =
+                tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align;
+            new_empty_allocation(align.abi)
+        }
+        ConstValue::Slice { data, start, end } => {
+            let alloc_id = tables.tcx.create_memory_alloc(data);
+            let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
+            let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
+            let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
+                (end - start) as u64,
+                &tables.tcx,
+            );
+            let layout =
+                tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap();
+            let mut allocation =
+                rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+                    scalar_ptr,
+                )
+                .unwrap();
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
+                    scalar_len,
+                )
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ByRef { alloc, offset } => {
+            let ty_size = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
+                .unwrap()
+                .size;
+            allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
+        }
+    }
+}
+
+/// Creates an `Allocation` only from information within the `AllocRange`.
+pub(super) fn allocation_filter<'tcx>(
+    alloc: &rustc_middle::mir::interpret::Allocation,
+    alloc_range: AllocRange,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    let mut bytes: Vec<Option<u8>> = alloc
+        .inspect_with_uninit_and_ptr_outside_interpreter(
+            alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
+        )
+        .iter()
+        .copied()
+        .map(Some)
+        .collect();
+    for (i, b) in bytes.iter_mut().enumerate() {
+        if !alloc
+            .init_mask()
+            .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
+        {
+            *b = None;
+        }
+    }
+    let mut ptrs = Vec::new();
+    for (offset, prov) in alloc
+        .provenance()
+        .ptrs()
+        .iter()
+        .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
+    {
+        ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
+    }
+    Allocation {
+        bytes: bytes,
+        provenance: ProvenanceMap { ptrs },
+        align: alloc.align.bytes(),
+        mutability: alloc.mutability.stable(tables),
+    }
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 7877c91c2cf..d36835d37f5 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -9,10 +9,7 @@
 
 use crate::rustc_internal::{self, opaque};
 use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
-use crate::stable_mir::ty::{
-    allocation_filter, new_allocation, Const, FloatTy, GenericParamDef, IntTy, Movability, RigidTy,
-    TyKind, UintTy,
-};
+use crate::stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, TyKind, UintTy};
 use crate::stable_mir::{self, Context};
 use rustc_hir as hir;
 use rustc_middle::mir::interpret::alloc_range;
@@ -22,6 +19,8 @@ use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
 use tracing::debug;
 
+mod alloc;
+
 impl<'tcx> Context for Tables<'tcx> {
     fn local_crate(&self) -> stable_mir::Crate {
         smir_crate(self.tcx, LOCAL_CRATE)
@@ -205,8 +204,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
         match self {
             Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
             Repeat(op, len) => {
-                let cnst = ConstantKind::from_const(*len, tables.tcx);
-                let len = Const { literal: cnst.stable(tables) };
+                let len = len.stable(tables);
                 stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
             }
             Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
@@ -394,8 +392,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
         match self {
             ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
             ty::TermKind::Const(cnst) => {
-                let cnst = ConstantKind::from_const(*cnst, tables.tcx);
-                let cnst = Const { literal: cnst.stable(tables) };
+                let cnst = cnst.stable(tables);
                 TermKind::Const(cnst)
             }
         }
@@ -1083,8 +1080,32 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
     type T = stable_mir::ty::Const;
 
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        let cnst = ConstantKind::from_const(*self, tables.tcx);
-        stable_mir::ty::Const { literal: cnst.stable(tables) }
+        stable_mir::ty::Const {
+            literal: match self.kind() {
+                ty::Value(val) => {
+                    let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
+                    stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
+                        self.ty(),
+                        const_val,
+                        tables,
+                    ))
+                }
+                ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
+                ty::ErrorCt(_) => unreachable!(),
+                ty::InferCt(_) => unreachable!(),
+                ty::BoundCt(_, _) => unimplemented!(),
+                ty::PlaceholderCt(_) => unimplemented!(),
+                ty::Unevaluated(uv) => {
+                    stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
+                        ty: tables.intern_ty(self.ty()),
+                        def: tables.const_def(uv.def),
+                        args: uv.args.stable(tables),
+                        promoted: None,
+                    })
+                }
+                ty::ExprCt(_) => unimplemented!(),
+            },
+        }
     }
 }
 
@@ -1108,7 +1129,11 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
     type T = stable_mir::ty::Allocation;
 
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
+        alloc::allocation_filter(
+            self,
+            alloc_range(rustc_target::abi::Size::ZERO, self.size()),
+            tables,
+        )
     }
 }
 
@@ -1155,26 +1180,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
     type T = stable_mir::ty::ConstantKind;
 
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        match self {
-            ConstantKind::Ty(c) => match c.kind() {
-                ty::Value(val) => {
-                    let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
-                    stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
-                }
-                ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
-                ty::ErrorCt(_) => unreachable!(),
-                _ => unimplemented!(),
-            },
+        match *self {
+            ConstantKind::Ty(c) => c.stable(tables).literal,
             ConstantKind::Unevaluated(unev_const, ty) => {
                 stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
-                    ty: tables.intern_ty(*ty),
+                    ty: tables.intern_ty(ty),
                     def: tables.const_def(unev_const.def),
                     args: unev_const.args.stable(tables),
                     promoted: unev_const.promoted.map(|u| u.as_u32()),
                 })
             }
-            ConstantKind::Val(val, _) => {
-                stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
+            ConstantKind::Val(val, ty) => {
+                stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables))
             }
         }
     }
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index fce5375f848..d49f3243777 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,10 +1,5 @@
-use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
-
 use super::{mir::Mutability, mir::Safety, with, DefId};
-use crate::{
-    rustc_internal::{opaque, Opaque},
-    rustc_smir::{Stable, Tables},
-};
+use crate::rustc_internal::Opaque;
 
 #[derive(Copy, Clone, Debug)]
 pub struct Ty(pub usize);
@@ -286,128 +281,6 @@ pub struct Allocation {
     pub mutability: Mutability,
 }
 
-impl Allocation {
-    /// Creates new empty `Allocation` from given `Align`.
-    fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
-        Allocation {
-            bytes: Vec::new(),
-            provenance: ProvenanceMap { ptrs: Vec::new() },
-            align: align.bytes(),
-            mutability: Mutability::Not,
-        }
-    }
-}
-
-// We need this method instead of a Stable implementation
-// because we need to get `Ty` of the const we are trying to create, to do that
-// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
-pub fn new_allocation<'tcx>(
-    const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
-    const_value: ConstValue<'tcx>,
-    tables: &mut Tables<'tcx>,
-) -> Allocation {
-    match const_value {
-        ConstValue::Scalar(scalar) => {
-            let size = scalar.size();
-            let align = tables
-                .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
-                .unwrap()
-                .align;
-            let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
-            allocation
-                .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
-                .unwrap();
-            allocation.stable(tables)
-        }
-        ConstValue::ZeroSized => {
-            let align = tables
-                .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
-                .unwrap()
-                .align;
-            Allocation::new_empty_allocation(align.abi)
-        }
-        ConstValue::Slice { data, start, end } => {
-            let alloc_id = tables.tcx.create_memory_alloc(data);
-            let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
-            let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
-            let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
-                (end - start) as u64,
-                &tables.tcx,
-            );
-            let layout = tables
-                .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
-                .unwrap();
-            let mut allocation =
-                rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
-            allocation
-                .write_scalar(
-                    &tables.tcx,
-                    alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
-                    scalar_ptr,
-                )
-                .unwrap();
-            allocation
-                .write_scalar(
-                    &tables.tcx,
-                    alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
-                    scalar_len,
-                )
-                .unwrap();
-            allocation.stable(tables)
-        }
-        ConstValue::ByRef { alloc, offset } => {
-            let ty_size = tables
-                .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
-                .unwrap()
-                .size;
-            allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
-        }
-    }
-}
-
-/// Creates an `Allocation` only from information within the `AllocRange`.
-pub fn allocation_filter<'tcx>(
-    alloc: &rustc_middle::mir::interpret::Allocation,
-    alloc_range: AllocRange,
-    tables: &mut Tables<'tcx>,
-) -> Allocation {
-    let mut bytes: Vec<Option<u8>> = alloc
-        .inspect_with_uninit_and_ptr_outside_interpreter(
-            alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
-        )
-        .iter()
-        .copied()
-        .map(Some)
-        .collect();
-    for (i, b) in bytes.iter_mut().enumerate() {
-        if !alloc
-            .init_mask()
-            .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
-        {
-            *b = None;
-        }
-    }
-    let mut ptrs = Vec::new();
-    for (offset, prov) in alloc
-        .provenance()
-        .ptrs()
-        .iter()
-        .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
-    {
-        ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
-    }
-    Allocation {
-        bytes: bytes,
-        provenance: ProvenanceMap { ptrs },
-        align: alloc.align.bytes(),
-        mutability: alloc.mutability.stable(tables),
-    }
-}
-
 #[derive(Clone, Debug)]
 pub enum ConstantKind {
     Allocated(Allocation),
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index ca3c64b428e..52a11abd545 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -51,13 +51,9 @@ pub(super) struct SearchGraph<'tcx> {
 
 impl<'tcx> SearchGraph<'tcx> {
     pub(super) fn new(tcx: TyCtxt<'tcx>, mode: SolverMode) -> SearchGraph<'tcx> {
-        let local_overflow_limit = {
-            let recursion_limit = tcx.recursion_limit().0;
-            if recursion_limit == 0 { 0 } else { recursion_limit.ilog2() as usize }
-        };
         Self {
             mode,
-            local_overflow_limit,
+            local_overflow_limit: tcx.recursion_limit().0.checked_ilog2().unwrap_or(0) as usize,
             stack: Default::default(),
             provisional_cache: ProvisionalCache::empty(),
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 5746781ae35..e90723b0ee8 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -152,16 +152,14 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
             .predicates_of(impl_def_id)
             .instantiate(tcx, impl_args)
             .iter()
-            .map(|(c, s)| (c.as_predicate(), s))
+            .map(|(c, _)| c.as_predicate())
             .collect(),
     };
 
-    let InferOk { value: mut header, obligations } = selcx
-        .infcx
-        .at(&ObligationCause::dummy_with_span(tcx.def_span(impl_def_id)), param_env)
-        .normalize(header);
+    let InferOk { value: mut header, obligations } =
+        selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
 
-    header.predicates.extend(obligations.into_iter().map(|o| (o.predicate, o.cause.span)));
+    header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
     header
 }
 
@@ -261,17 +259,11 @@ fn overlap<'tcx>(
                                 infcx.tcx.def_span(impl2_header.impl_def_id),
                                 "the second impl is here",
                             );
-                            if !failing_obligation.cause.span.is_dummy() {
-                                lint.span_label(
-                                    failing_obligation.cause.span,
-                                    format!(
-                                        "`{}` may be considered to hold in future releases, \
-                                        causing the impls to overlap",
-                                        infcx
-                                            .resolve_vars_if_possible(failing_obligation.predicate)
-                                    ),
-                                );
-                            }
+                            lint.note(format!(
+                                "`{}` may be considered to hold in future releases, \
+                                    causing the impls to overlap",
+                                infcx.resolve_vars_if_possible(failing_obligation.predicate)
+                            ));
                             lint
                         },
                     );
@@ -355,8 +347,8 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
     [&impl1_header.predicates, &impl2_header.predicates]
         .into_iter()
         .flatten()
-        .map(|&(predicate, span)| {
-            Obligation::new(infcx.tcx, ObligationCause::dummy_with_span(span), param_env, predicate)
+        .map(|&predicate| {
+            Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
         })
         .chain(obligations.into_iter().cloned())
         .find(|obligation: &PredicateObligation<'tcx>| {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9dbc87c337c..e4c76226454 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -104,16 +104,15 @@ def _download(path, url, probably_big, verbose, exception):
         # If curl is not present on Win32, we should not sys.exit
         #   but raise `CalledProcessError` or `OSError` instead
         require(["curl", "--version"], exception=platform_is_win32())
-        with open(path, "wb") as outfile:
-            run(["curl", option,
-                "-L", # Follow redirect.
-                "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
-                "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
-                "--retry", "3", "-SRf", url],
-                stdout=outfile,    #Implements cli redirect operator '>'
-                verbose=verbose,
-                exception=True, # Will raise RuntimeError on failure
-            )
+        run(["curl", option,
+            "-L", # Follow redirect.
+            "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
+            "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
+            "-o", path,
+            "--retry", "3", "-SRf", url],
+            verbose=verbose,
+            exception=True, # Will raise RuntimeError on failure
+        )
     except (subprocess.CalledProcessError, OSError, RuntimeError):
         # see http://serverfault.com/questions/301128/how-to-download
         if platform_is_win32():
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 17c308e915b..9489297d67d 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -225,6 +225,8 @@ impl Config {
             "10", // timeout if speed is < 10 bytes/sec for > 30 seconds
             "--connect-timeout",
             "30", // timeout if cannot connect within 30 seconds
+            "-o",
+            tempfile.to_str().unwrap(),
             "--retry",
             "3",
             "-SRf",
@@ -236,8 +238,6 @@ impl Config {
             curl.arg("--progress-bar");
         }
         curl.arg(url);
-        let f = File::create(tempfile).unwrap();
-        curl.stdout(Stdio::from(f));
         if !self.check_run(&mut curl) {
             if self.build.contains("windows-msvc") {
                 eprintln!("Fallback to PowerShell");
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
new file mode 100644
index 00000000000..415e91b250f
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
@@ -0,0 +1,16 @@
+#![feature(portable_simd)]
+
+// Some targets treat arrays and structs very differently. We would probably catch that on those
+// targets since we check the `PassMode`; here we ensure that we catch it on *all* targets
+// (in particular, on x86-64 the pass mode is `Indirect` for both of these).
+struct S(i32, i32, i32, i32);
+type A = [i32; 4];
+
+fn main() {
+    fn f(_: S) {}
+
+    // These two types have the same size but are still not compatible.
+    let g = unsafe { std::mem::transmute::<fn(S), fn(A)>(f) };
+
+    g(Default::default()) //~ ERROR: calling a function with argument of type S passing data of type [i32; 4]
+}
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
new file mode 100644
index 00000000000..50d4228c111
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: calling a function with argument of type S passing data of type [i32; 4]
+  --> $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
+   |
+LL |     g(Default::default())
+   |     ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S passing data of type [i32; 4]
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
new file mode 100644
index 00000000000..a1fda329e8d
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
@@ -0,0 +1,7 @@
+fn main() {
+    fn f(_: f32) {}
+
+    let g = unsafe { std::mem::transmute::<fn(f32), fn(i32)>(f) };
+
+    g(42) //~ ERROR: calling a function with argument of type f32 passing data of type i32
+}
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
new file mode 100644
index 00000000000..a53126c733e
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: calling a function with argument of type f32 passing data of type i32
+  --> $DIR/abi_mismatch_int_vs_float.rs:LL:CC
+   |
+LL |     g(42)
+   |     ^^^^^ calling a function with argument of type f32 passing data of type i32
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs
index f0ea5ccfe0f..f0ea5ccfe0f 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
index 610425658fe..6eacfeece14 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr4.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: calling a function with argument of type *const [i32] passing data of type *const i32
-  --> $DIR/cast_fn_ptr4.rs:LL:CC
+  --> $DIR/abi_mismatch_raw_pointer.rs:LL:CC
    |
 LL |     g(&42 as *const i32)
    |     ^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type *const [i32] passing data of type *const i32
@@ -7,7 +7,7 @@ LL |     g(&42 as *const i32)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `main` at $DIR/cast_fn_ptr4.rs:LL:CC
+   = note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs
index 0fdab49b94b..0fdab49b94b 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
index c4e08b58430..eedc1235773 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr5.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: calling a function with return type u32 passing return place of type ()
-  --> $DIR/cast_fn_ptr5.rs:LL:CC
+  --> $DIR/abi_mismatch_return_type.rs:LL:CC
    |
 LL |     g()
    |     ^^^ calling a function with return type u32 passing return place of type ()
@@ -7,7 +7,7 @@ LL |     g()
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `main` at $DIR/cast_fn_ptr5.rs:LL:CC
+   = note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs
index 20384f0965b..20384f0965b 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
index 086712e0d13..bc500a90b77 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr2.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: calling a function with argument of type (i32, i32) passing data of type i32
-  --> $DIR/cast_fn_ptr2.rs:LL:CC
+  --> $DIR/abi_mismatch_simple.rs:LL:CC
    |
 LL |     g(42)
    |     ^^^^^ calling a function with argument of type (i32, i32) passing data of type i32
@@ -7,7 +7,7 @@ LL |     g(42)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC
+   = note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs
index 920fb51abb6..920fb51abb6 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr
index 55fd7d60720..558d83bcfd2 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr3.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: calling a function with fewer arguments than it requires
-  --> $DIR/cast_fn_ptr3.rs:LL:CC
+  --> $DIR/abi_mismatch_too_few_args.rs:LL:CC
    |
 LL |     g()
    |     ^^^ calling a function with fewer arguments than it requires
@@ -7,7 +7,7 @@ LL |     g()
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `main` at $DIR/cast_fn_ptr3.rs:LL:CC
+   = note: inside `main` at $DIR/abi_mismatch_too_few_args.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs
index c0e96a43cc5..c0e96a43cc5 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr
index bb2a2637959..dc12073952f 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_fn_ptr1.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: calling a function with more arguments than it expected
-  --> $DIR/cast_fn_ptr1.rs:LL:CC
+  --> $DIR/abi_mismatch_too_many_args.rs:LL:CC
    |
 LL |     g(42)
    |     ^^^^^ calling a function with more arguments than it expected
@@ -7,7 +7,7 @@ LL |     g(42)
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC
+   = note: inside `main` at $DIR/abi_mismatch_too_many_args.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs
new file mode 100644
index 00000000000..80f357b61ba
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs
@@ -0,0 +1,11 @@
+#![feature(portable_simd)]
+use std::simd;
+
+fn main() {
+    fn f(_: simd::u32x8) {}
+
+    // These two vector types have the same size but are still not compatible.
+    let g = unsafe { std::mem::transmute::<fn(simd::u32x8), fn(simd::u64x4)>(f) };
+
+    g(Default::default()) //~ ERROR: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
+}
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
new file mode 100644
index 00000000000..7dcca1e85b8
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
+  --> $DIR/abi_mismatch_vector.rs:LL:CC
+   |
+LL |     g(Default::default())
+   |     ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
index 67b87b46bd9..0786450f751 100644
--- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs
+++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
@@ -1,5 +1,7 @@
+#![feature(portable_simd)]
 use std::num;
 use std::mem;
+use std::simd;
 
 fn test_abi_compat<T, U>(t: T, u: U) {
     fn id<T>(x: T) -> T { x }
@@ -15,6 +17,23 @@ fn test_abi_compat<T, U>(t: T, u: U) {
     drop(f(t));
 }
 
+/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
+fn test_abi_newtype<T: Copy>(t: T) {
+    #[repr(transparent)]
+    struct Wrapper1<T>(T);
+    #[repr(transparent)]
+    struct Wrapper2<T>(T, ());
+    #[repr(transparent)]
+    struct Wrapper2a<T>((), T);
+    #[repr(transparent)]
+    struct Wrapper3<T>(T, [u8; 0]);
+
+    test_abi_compat(t, Wrapper1(t));
+    test_abi_compat(t, Wrapper2(t, ()));
+    test_abi_compat(t, Wrapper2a((), t));
+    test_abi_compat(t, Wrapper3(t, []));
+}
+
 fn main() {
     test_abi_compat(0u32, 'x');
     test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
@@ -22,6 +41,13 @@ fn main() {
     test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
     test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
     test_abi_compat(0u32, 0i32);
-    // Note that `bool` and `u8` are *not* compatible!
+    test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1));
+    // Note that `bool` and `u8` are *not* compatible, at least on x86-64!
     // One of them has `arg_ext: Zext`, the other does not.
+
+    test_abi_newtype(0u32);
+    test_abi_newtype(0f32);
+    test_abi_newtype((0u32, 1u32, 2u32));
+    test_abi_newtype([0u32, 1u32, 2u32]);
+    test_abi_newtype([0i32; 0]);
 }
diff --git a/tests/run-make/pgo-branch-weights/Makefile b/tests/run-make/pgo-branch-weights/Makefile
index c60206a1f34..4c9f8b2493a 100644
--- a/tests/run-make/pgo-branch-weights/Makefile
+++ b/tests/run-make/pgo-branch-weights/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/pgo-gen-lto/Makefile b/tests/run-make/pgo-gen-lto/Makefile
index 3f2f6a838b5..8b647846af3 100644
--- a/tests/run-make/pgo-gen-lto/Makefile
+++ b/tests/run-make/pgo-gen-lto/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/pgo-gen/Makefile b/tests/run-make/pgo-gen/Makefile
index 4623a74957b..bf32cfdb802 100644
--- a/tests/run-make/pgo-gen/Makefile
+++ b/tests/run-make/pgo-gen/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/pgo-indirect-call-promotion/Makefile b/tests/run-make/pgo-indirect-call-promotion/Makefile
index 45302215cc6..542eb244d39 100644
--- a/tests/run-make/pgo-indirect-call-promotion/Makefile
+++ b/tests/run-make/pgo-indirect-call-promotion/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/pgo-use/Makefile b/tests/run-make/pgo-use/Makefile
index 3bac9b77aa3..9f440118dae 100644
--- a/tests/run-make/pgo-use/Makefile
+++ b/tests/run-make/pgo-use/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/pointer-auth-link-with-c/Makefile b/tests/run-make/pointer-auth-link-with-c/Makefile
index dffbd303582..8fcf10e2096 100644
--- a/tests/run-make/pointer-auth-link-with-c/Makefile
+++ b/tests/run-make/pointer-auth-link-with-c/Makefile
@@ -1,6 +1,7 @@
 include ../tools.mk
 
 # only-aarch64
+# ignore-cross-compile
 
 all:
 	$(COMPILE_OBJ) $(TMPDIR)/test.o test.c
diff --git a/tests/run-make/profile/Makefile b/tests/run-make/profile/Makefile
index fffc051adbf..7919b18ba74 100644
--- a/tests/run-make/profile/Makefile
+++ b/tests/run-make/profile/Makefile
@@ -1,4 +1,5 @@
 # needs-profiler-support
+# ignore-cross-compile
 
 include ../tools.mk
 
diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr
index f315ba82130..89289767b83 100644
--- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr
+++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr
@@ -6,13 +6,11 @@ LL | #[derive(PartialEq, Default)]
 ...
 LL | impl<T, Q> PartialEq<Q> for Interval<T>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the first impl is here
-...
-LL |     Q: ?Sized + PartialOrd,
-   |                 ---------- `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
    |
    = 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 #114040 <https://github.com/rust-lang/rust/issues/114040>
    = note: impls that are not considered to overlap may be considered to overlap in the future
+   = note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
 note: the lint level is defined here
   --> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9
    |
diff --git a/tests/ui/mir/mir-inlining/always-encode-mirs.rs b/tests/ui/mir/mir-inlining/always-encode-mirs.rs
new file mode 100644
index 00000000000..f3731996cf2
--- /dev/null
+++ b/tests/ui/mir/mir-inlining/always-encode-mirs.rs
@@ -0,0 +1,12 @@
+// Regression test for MIR inlining with -Zalways-encode-mir enabled in the auxiliary crate.
+// Previously we inlined function not eligible for inlining which lead to linking error:
+// undefined reference to `internal::S'
+//
+// aux-build:internal.rs
+// build-pass
+// compile-flags: -O
+extern crate internal;
+
+fn main() {
+    println!("{}", internal::f());
+}
diff --git a/tests/ui/mir/mir-inlining/auxiliary/internal.rs b/tests/ui/mir/mir-inlining/auxiliary/internal.rs
new file mode 100644
index 00000000000..fa0f9c2da41
--- /dev/null
+++ b/tests/ui/mir/mir-inlining/auxiliary/internal.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Zalways-encode-mir
+
+static S: usize = 42;
+
+pub fn f() -> &'static usize {
+    &S
+}
diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs
index bb2b13664ba..74c7afd6b9e 100644
--- a/tests/ui/traits/issue-105231.rs
+++ b/tests/ui/traits/issue-105231.rs
@@ -1,9 +1,9 @@
+//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
 struct A<T>(B<T>);
 //~^ ERROR recursive types `A` and `B` have infinite size
 struct B<T>(A<A<T>>);
 trait Foo {}
 impl<T> Foo for T where T: Send {}
-//~^ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
 impl Foo for B<u8> {}
 
 fn main() {}
diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr
index 76a71067353..fe20c47c57a 100644
--- a/tests/ui/traits/issue-105231.stderr
+++ b/tests/ui/traits/issue-105231.stderr
@@ -1,5 +1,5 @@
 error[E0072]: recursive types `A` and `B` have infinite size
-  --> $DIR/issue-105231.rs:1:1
+  --> $DIR/issue-105231.rs:2:1
    |
 LL | struct A<T>(B<T>);
    | ^^^^^^^^^^^ ---- recursive without indirection
@@ -15,14 +15,10 @@ LL ~ struct B<T>(Box<A<A<T>>>);
    |
 
 error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
-  --> $DIR/issue-105231.rs:5:28
-   |
-LL | impl<T> Foo for T where T: Send {}
-   |                            ^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`)
 note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-105231.rs:3:8
+  --> $DIR/issue-105231.rs:4:8
    |
 LL | struct B<T>(A<A<T>>);
    |        ^
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
index 206ab07898b..d37943b929a 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -1,3 +1,4 @@
+//~ ERROR overflow
 // A regression test for #111729 checking that we correctly
 // track recursion depth for obligations returned by confirmation.
 use std::panic::RefUnwindSafe;
@@ -14,7 +15,6 @@ struct RootDatabase {
 }
 
 impl<T: RefUnwindSafe> Database for T {
-    //~^ ERROR overflow
     type Storage = SalsaStorage;
 }
 impl Database for RootDatabase {
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
index 4123a8199a0..8f9ce3ef1e9 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -1,17 +1,13 @@
 error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:16:9
-   |
-LL | impl<T: RefUnwindSafe> Database for T {
-   |         ^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
 note: required because it appears within the type `RootDatabase`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:12:8
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
    |
 LL | struct RootDatabase {
    |        ^^^^^^^^^^^^
 note: required for `RootDatabase` to implement `Database`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:16:24
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
    |
 LL | impl<T: RefUnwindSafe> Database for T {
    |         -------------  ^^^^^^^^     ^