diff options
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(¶m)), + 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(¶m)), - 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 { | ------------- ^^^^^^^^ ^ |
