mirror of https://github.com/rust-lang/rust.git
Auto merge of #124972 - matthiaskrgr:rollup-3fablim, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #124615 (coverage: Further simplify extraction of mapping info from MIR) - #124778 (Fix parse error message for meta items) - #124797 (Refactor float `Primitive`s to a separate `Float` type) - #124888 (Migrate `run-make/rustdoc-output-path` to rmake) - #124957 (Make `Ty::builtin_deref` just return a `Ty`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
6a19a87097
|
@ -926,6 +926,41 @@ impl Integer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Floating-point types.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||
pub enum Float {
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F128,
|
||||
}
|
||||
|
||||
impl Float {
|
||||
pub fn size(self) -> Size {
|
||||
use Float::*;
|
||||
|
||||
match self {
|
||||
F16 => Size::from_bits(16),
|
||||
F32 => Size::from_bits(32),
|
||||
F64 => Size::from_bits(64),
|
||||
F128 => Size::from_bits(128),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
||||
use Float::*;
|
||||
let dl = cx.data_layout();
|
||||
|
||||
match self {
|
||||
F16 => dl.f16_align,
|
||||
F32 => dl.f32_align,
|
||||
F64 => dl.f64_align,
|
||||
F128 => dl.f128_align,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fundamental unit of memory access and layout.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||
|
@ -938,10 +973,7 @@ pub enum Primitive {
|
|||
/// a negative integer passed by zero-extension will appear positive in
|
||||
/// the callee, and most operations on it will produce the wrong values.
|
||||
Int(Integer, bool),
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F128,
|
||||
Float(Float),
|
||||
Pointer(AddressSpace),
|
||||
}
|
||||
|
||||
|
@ -952,10 +984,7 @@ impl Primitive {
|
|||
|
||||
match self {
|
||||
Int(i, _) => i.size(),
|
||||
F16 => Size::from_bits(16),
|
||||
F32 => Size::from_bits(32),
|
||||
F64 => Size::from_bits(64),
|
||||
F128 => Size::from_bits(128),
|
||||
Float(f) => f.size(),
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different sizes
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
|
@ -969,10 +998,7 @@ impl Primitive {
|
|||
|
||||
match self {
|
||||
Int(i, _) => i.align(dl),
|
||||
F16 => dl.f16_align,
|
||||
F32 => dl.f32_align,
|
||||
F64 => dl.f64_align,
|
||||
F128 => dl.f128_align,
|
||||
Float(f) => f.align(dl),
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different alignments
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
|
|
|
@ -1483,10 +1483,9 @@ fn suggest_ampmut<'tcx>(
|
|||
} else {
|
||||
// otherwise, suggest that the user annotates the binding; we provide the
|
||||
// type of the local.
|
||||
let ty_mut = decl_ty.builtin_deref(true).unwrap();
|
||||
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
|
||||
let ty = decl_ty.builtin_deref(true).unwrap();
|
||||
|
||||
(false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty_mut.ty))
|
||||
(false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
|
||||
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap().ty;
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
|
||||
|
||||
if let Err(terr) = self.cx.eq_types(
|
||||
literal_ty,
|
||||
|
@ -637,7 +637,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
match pi {
|
||||
ProjectionElem::Deref => {
|
||||
let deref_ty = base_ty.builtin_deref(true);
|
||||
PlaceTy::from_ty(deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
||||
PlaceTy::from_ty(deref_ty.unwrap_or_else(|| {
|
||||
span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -670,11 +670,8 @@ fn codegen_stmt<'tcx>(
|
|||
let to_ty = fx.monomorphize(to_ty);
|
||||
|
||||
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.builtin_deref(true).is_some_and(
|
||||
|ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
|
||||
has_ptr_meta(fx.tcx, pointee_ty)
|
||||
},
|
||||
)
|
||||
ty.builtin_deref(true)
|
||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||
}
|
||||
|
||||
if is_fat_ptr(fx, from_ty) {
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_middle::ty::layout::{
|
|||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::abi::{Integer, Primitive};
|
||||
use rustc_target::abi::{Float, Integer, Primitive};
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
|
@ -32,10 +32,12 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
|
|||
Integer::I64 => types::I64,
|
||||
Integer::I128 => types::I128,
|
||||
},
|
||||
Primitive::F16 => unimplemented!("f16_f128"),
|
||||
Primitive::F32 => types::F32,
|
||||
Primitive::F64 => types::F64,
|
||||
Primitive::F128 => unimplemented!("f16_f128"),
|
||||
Primitive::Float(float) => match float {
|
||||
Float::F16 => unimplemented!("f16_f128"),
|
||||
Float::F32 => types::F32,
|
||||
Float::F64 => types::F64,
|
||||
Float::F128 => unimplemented!("f16_f128"),
|
||||
},
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Primitive::Pointer(_) => pointer_ty(tcx),
|
||||
}
|
||||
|
|
|
@ -586,7 +586,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
intrinsic_args!(fx, args => (base, offset); intrinsic);
|
||||
let offset = offset.load_scalar(fx);
|
||||
|
||||
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let ptr_diff = if pointee_size != 1 {
|
||||
fx.bcx.ins().imul_imm(offset, pointee_size as i64)
|
||||
|
@ -610,7 +610,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
let val = val.load_scalar(fx);
|
||||
let count = count.load_scalar(fx);
|
||||
|
||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let count = if pointee_size != 1 {
|
||||
fx.bcx.ins().imul_imm(count, pointee_size as i64)
|
||||
|
@ -715,7 +715,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
|
||||
// Cranelift treats loads as volatile by default
|
||||
// FIXME correctly handle unaligned_volatile_load
|
||||
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap());
|
||||
let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout);
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
|
|
@ -974,7 +974,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
intrinsic_args!(fx, args => (ptr, offset); intrinsic);
|
||||
|
||||
let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let ret_lane_layout = fx.layout_of(ret_lane_ty);
|
||||
|
|
|
@ -95,7 +95,7 @@ mod prelude {
|
|||
pub(crate) use rustc_middle::mir::{self, *};
|
||||
pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
pub(crate) use rustc_middle::ty::{
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, UintTy,
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
|
||||
};
|
||||
pub(crate) use rustc_span::Span;
|
||||
pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
|
||||
|
|
|
@ -388,12 +388,8 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
|
|||
in_lhs: CValue<'tcx>,
|
||||
in_rhs: CValue<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let is_thin_ptr = in_lhs
|
||||
.layout()
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.map(|TypeAndMut { ty, mutbl: _ }| !has_ptr_meta(fx.tcx, ty))
|
||||
.unwrap_or(true);
|
||||
let is_thin_ptr =
|
||||
in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
|
||||
|
||||
if is_thin_ptr {
|
||||
match bin_op {
|
||||
|
@ -404,7 +400,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
|
|||
codegen_compare_bin_op(fx, bin_op, false, lhs, rhs)
|
||||
}
|
||||
BinOp::Offset => {
|
||||
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap();
|
||||
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
|
||||
|
|
|
@ -127,7 +127,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
|||
let dst_ty = dst.layout().ty;
|
||||
let mut coerce_ptr = || {
|
||||
let (base, info) =
|
||||
if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() {
|
||||
if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap()).is_unsized() {
|
||||
let (old_base, old_info) = src.load_scalar_pair(fx);
|
||||
unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
|
||||
} else {
|
||||
|
|
|
@ -819,7 +819,7 @@ impl<'tcx> CPlace<'tcx> {
|
|||
}
|
||||
|
||||
pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
|
||||
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
|
||||
if has_ptr_meta(fx.tcx, inner_layout.ty) {
|
||||
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
|
||||
CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
|
||||
|
|
|
@ -59,7 +59,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
|||
|
||||
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
|
||||
let vtable =
|
||||
|
|
|
@ -8,8 +8,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
use rustc_target::abi::{
|
||||
self, Abi, Align, FieldsShape, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
||||
Variants, F128, F16, F32, F64,
|
||||
self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
||||
Variants,
|
||||
};
|
||||
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
|
@ -283,10 +283,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
match scalar.primitive() {
|
||||
Int(i, true) => cx.type_from_integer(i),
|
||||
Int(i, false) => cx.type_from_unsigned_integer(i),
|
||||
F16 => cx.type_f16(),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
F128 => cx.type_f128(),
|
||||
Float(f) => cx.type_from_float(f),
|
||||
Pointer(address_space) => {
|
||||
// If we know the alignment, pick something better than i8.
|
||||
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
|
||||
|
|
|
@ -583,7 +583,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
|
||||
if element_type_index >= 0 {
|
||||
let arg_ty = self.args[element_type_index as usize].layout.ty;
|
||||
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument").ty;
|
||||
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
|
||||
let element_type_attr = unsafe {
|
||||
llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
|
||||
};
|
||||
|
|
|
@ -904,8 +904,8 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
|
|||
Primitive::Int(Integer::I16, _) => cx.type_i16(),
|
||||
Primitive::Int(Integer::I32, _) => cx.type_i32(),
|
||||
Primitive::Int(Integer::I64, _) => cx.type_i64(),
|
||||
Primitive::F32 => cx.type_f32(),
|
||||
Primitive::F64 => cx.type_f64(),
|
||||
Primitive::Float(Float::F32) => cx.type_f32(),
|
||||
Primitive::Float(Float::F64) => cx.type_f64(),
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()),
|
||||
_ => unreachable!(),
|
||||
|
@ -950,7 +950,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
|||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||
{
|
||||
bx.bitcast(value, bx.cx.type_i64())
|
||||
}
|
||||
|
@ -986,8 +986,8 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
|||
match s.primitive() {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
|
||||
Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_i32()),
|
||||
Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_i64()),
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
|
@ -1027,7 +1027,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
|||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||
{
|
||||
bx.bitcast(value, bx.cx.type_f64())
|
||||
}
|
||||
|
@ -1064,8 +1064,8 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
|||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
||||
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
|
||||
Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_f32()),
|
||||
Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_f64()),
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
|
@ -1100,7 +1100,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
|||
cx.type_vector(elem_ty, count * 2)
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||
{
|
||||
cx.type_i64()
|
||||
}
|
||||
|
@ -1136,8 +1136,8 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
|||
match s.primitive() {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
||||
Primitive::F32 => cx.type_i32(),
|
||||
Primitive::F64 => cx.type_i64(),
|
||||
Primitive::Float(Float::F32) => cx.type_i32(),
|
||||
Primitive::Float(Float::F64) => cx.type_i64(),
|
||||
_ => layout.llvm_type(cx),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -576,7 +576,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {}
|
||||
abi::Float(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,10 +122,7 @@ fn tag_base_type<'ll, 'tcx>(
|
|||
// Niche tags are always normalized to unsized integers of the correct size.
|
||||
match tag.primitive() {
|
||||
Primitive::Int(t, _) => t,
|
||||
Primitive::F16 => Integer::I16,
|
||||
Primitive::F32 => Integer::I32,
|
||||
Primitive::F64 => Integer::I64,
|
||||
Primitive::F128 => Integer::I128,
|
||||
Primitive::Float(f) => Integer::from_size(f.size()).unwrap(),
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Primitive::Pointer(_) => {
|
||||
// If the niche is the NULL value of a reference, then `discr_enum_ty` will be
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
|
|||
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
|
||||
use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size};
|
||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
@ -231,13 +231,17 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
emit_va_arg(self, args[0], ret_ty)
|
||||
}
|
||||
}
|
||||
Primitive::F16 => bug!("the va_arg intrinsic does not work with `f16`"),
|
||||
Primitive::F64 | Primitive::Pointer(_) => {
|
||||
Primitive::Float(Float::F16) => {
|
||||
bug!("the va_arg intrinsic does not work with `f16`")
|
||||
}
|
||||
Primitive::Float(Float::F64) | Primitive::Pointer(_) => {
|
||||
emit_va_arg(self, args[0], ret_ty)
|
||||
}
|
||||
// `va_arg` should never be used with the return type f32.
|
||||
Primitive::F32 => bug!("the va_arg intrinsic does not work with `f32`"),
|
||||
Primitive::F128 => {
|
||||
Primitive::Float(Float::F32) => {
|
||||
bug!("the va_arg intrinsic does not work with `f32`")
|
||||
}
|
||||
Primitive::Float(Float::F128) => {
|
||||
bug!("the va_arg intrinsic does not work with `f128`")
|
||||
}
|
||||
}
|
||||
|
@ -2383,7 +2387,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
|
||||
span_bug!(span, "must be called with a vector of pointer types as first argument")
|
||||
});
|
||||
let layout = bx.layout_of(pointee.ty);
|
||||
let layout = bx.layout_of(pointee);
|
||||
let ptrs = args[0].immediate();
|
||||
// The second argument must be a ptr-sized integer.
|
||||
// (We don't care about the signedness, this is wrapping anyway.)
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
|||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape};
|
||||
use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
|
||||
use rustc_target::abi::{Float, Int, Pointer};
|
||||
use rustc_target::abi::{Scalar, Size, Variants};
|
||||
|
||||
use std::fmt::Write;
|
||||
|
@ -272,10 +272,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
|
||||
match scalar.primitive() {
|
||||
Int(i, _) => cx.type_from_integer(i),
|
||||
F16 => cx.type_f16(),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
F128 => cx.type_f128(),
|
||||
Float(f) => cx.type_from_float(f),
|
||||
Pointer(address_space) => cx.type_ptr_ext(address_space),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1060,7 +1060,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
// Make sure that we've actually unwrapped the rcvr down
|
||||
// to a pointer or ref to `dyn* Trait`.
|
||||
if !op.layout.ty.builtin_deref(true).unwrap().ty.is_dyn_star() {
|
||||
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
|
||||
span_bug!(span, "can't codegen a virtual call on {:#?}", op);
|
||||
}
|
||||
let place = op.deref(bx.cx());
|
||||
|
|
|
@ -120,7 +120,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
|||
{
|
||||
fn deref(&self, bx: &mut Bx) -> Self {
|
||||
bx.cx().layout_of(
|
||||
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
|
||||
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -215,8 +215,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
.layout
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));
|
||||
|
||||
let (llptr, llextra) = match self.val {
|
||||
OperandValue::Immediate(llptr) => (llptr, None),
|
||||
|
@ -455,8 +454,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
.layout
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest));
|
||||
|
||||
let OperandValue::Ref(PlaceValue { llval: llptr, llextra: Some(llextra), .. }) = self
|
||||
else {
|
||||
|
|
|
@ -306,17 +306,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
|
||||
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
|
||||
(Int(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => {
|
||||
bx.bitcast(imm, to_backend_ty)
|
||||
}
|
||||
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
|
||||
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
|
||||
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
|
||||
(Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
|
||||
(F16 | F32 | F64 | F128, Pointer(..)) => {
|
||||
(Float(_), Pointer(..)) => {
|
||||
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
||||
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
|
||||
}
|
||||
(Pointer(..), F16 | F32 | F64 | F128) => {
|
||||
(Pointer(..), Float(_)) => {
|
||||
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
|
||||
bx.bitcast(int_imm, to_backend_ty)
|
||||
}
|
||||
|
@ -870,8 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::BinOp::Offset => {
|
||||
let pointee_type = input_ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty));
|
||||
let pointee_layout = bx.cx().layout_of(pointee_type);
|
||||
if pointee_layout.is_zst() {
|
||||
// `Offset` works in terms of the size of pointee,
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
|
||||
use rustc_target::abi::{AddressSpace, Integer};
|
||||
use rustc_target::abi::{AddressSpace, Float, Integer};
|
||||
|
||||
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
||||
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
||||
|
@ -65,6 +65,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn type_from_float(&self, f: Float) -> Self::Type {
|
||||
use Float::*;
|
||||
match f {
|
||||
F16 => self.type_f16(),
|
||||
F32 => self.type_f32(),
|
||||
F64 => self.type_f64(),
|
||||
F128 => self.type_f128(),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ pub(super) fn op_to_const<'tcx>(
|
|||
// This codepath solely exists for `valtree_to_const_value` to not need to generate
|
||||
// a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
|
||||
// that case.
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap().ty; // `false` = no raw ptrs
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
|
||||
debug_assert!(
|
||||
matches!(
|
||||
ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
|
||||
|
|
|
@ -605,7 +605,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_target_usize(count)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
|
||||
// but no actual allocation can be big enough for the difference to be noticeable.
|
||||
|
@ -649,7 +649,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
|
||||
|
||||
let dst = self.read_pointer(dst)?;
|
||||
let byte = self.read_scalar(byte)?.to_u8()?;
|
||||
|
@ -688,7 +688,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
|
||||
assert!(layout.is_sized());
|
||||
|
||||
let get_bytes = |this: &InterpCx<'mir, 'tcx, M>,
|
||||
|
|
|
@ -357,7 +357,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Offset => {
|
||||
let ptr = left.to_scalar().to_pointer(self)?;
|
||||
let offset_count = right.to_scalar().to_target_isize(self)?;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
||||
|
||||
// We cannot overflow i64 as a type's size must be <= isize::MAX.
|
||||
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
||||
|
|
|
@ -415,7 +415,7 @@ where
|
|||
val: &ImmTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
|
||||
let pointee_type =
|
||||
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
|
||||
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type");
|
||||
let layout = self.layout_of(pointee_type)?;
|
||||
let (ptr, meta) = val.to_scalar_and_meta();
|
||||
|
||||
|
|
|
@ -1291,7 +1291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
)) => {
|
||||
let src_ty = src.ty(&self.body.local_decls, self.tcx);
|
||||
let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) {
|
||||
src_deref.ty
|
||||
src_deref
|
||||
} else {
|
||||
self.fail(
|
||||
location,
|
||||
|
@ -1301,7 +1301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
};
|
||||
let dst_ty = dst.ty(&self.body.local_decls, self.tcx);
|
||||
let op_dst_ty = if let Some(dst_deref) = dst_ty.builtin_deref(true) {
|
||||
dst_deref.ty
|
||||
dst_deref
|
||||
} else {
|
||||
self.fail(
|
||||
location,
|
||||
|
|
|
@ -115,7 +115,7 @@ fn might_permit_raw_init_lax<'tcx>(
|
|||
|
||||
// Special magic check for references and boxes (i.e., special pointer types).
|
||||
if let Some(pointee) = this.ty.builtin_deref(false) {
|
||||
let pointee = cx.layout_of(pointee.ty)?;
|
||||
let pointee = cx.layout_of(pointee)?;
|
||||
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
|
||||
if pointee.align.abi.bytes() > 1 {
|
||||
// 0x01-filling is not aligned.
|
||||
|
|
|
@ -68,28 +68,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Otherwise, deref if type is derefable:
|
||||
let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
|
||||
self.state.cur_ty.builtin_deref(self.include_raw_pointers)
|
||||
{
|
||||
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
|
||||
// NOTE: we may still need to normalize the built-in deref in case
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
(AutoderefKind::Builtin, normalized_ty)
|
||||
let (kind, new_ty) =
|
||||
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
|
||||
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
|
||||
// NOTE: we may still need to normalize the built-in deref in case
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
(AutoderefKind::Builtin, normalized_ty)
|
||||
} else {
|
||||
(AutoderefKind::Builtin, ty)
|
||||
}
|
||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||
// The overloaded deref check already normalizes the pointee type.
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
} else {
|
||||
(AutoderefKind::Builtin, ty)
|
||||
}
|
||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||
// The overloaded deref check already normalizes the pointee type.
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
return None;
|
||||
};
|
||||
|
||||
self.state.steps.push((self.state.cur_ty, kind));
|
||||
debug!(
|
||||
|
|
|
@ -624,10 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// returns a type of `&T`, but the actual type we assign to the
|
||||
/// *expression* is `T`. So this function just peels off the return
|
||||
/// type by one layer to yield `T`.
|
||||
pub(crate) fn make_overloaded_place_return_type(
|
||||
&self,
|
||||
method: MethodCallee<'tcx>,
|
||||
) -> ty::TypeAndMut<'tcx> {
|
||||
pub(crate) fn make_overloaded_place_return_type(&self, method: MethodCallee<'tcx>) -> Ty<'tcx> {
|
||||
// extract method return type, which will be &T;
|
||||
let ret_ty = method.sig.output();
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
match base_ty.builtin_deref(false) {
|
||||
Some(t) => Ok(t.ty),
|
||||
Some(ty) => Ok(ty),
|
||||
None => {
|
||||
debug!("By-ref binding of non-derefable type");
|
||||
Err(())
|
||||
|
@ -485,7 +485,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
let base_curr_ty = base_place.place.ty();
|
||||
let deref_ty = match base_curr_ty.builtin_deref(true) {
|
||||
Some(mt) => mt.ty,
|
||||
Some(pointee_ty) => pointee_ty,
|
||||
None => {
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||
return Err(());
|
||||
|
|
|
@ -918,8 +918,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
inner: &Pat<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let PatKind::Binding(..) = inner.kind
|
||||
&& let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = mt.ty.kind()
|
||||
&& let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = pointee_ty.kind()
|
||||
{
|
||||
// This is "x = dyn SomeTrait" being reduced from
|
||||
// "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
|
||||
|
|
|
@ -19,8 +19,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
oprnd_expr: &'tcx hir::Expr<'tcx>,
|
||||
oprnd_ty: Ty<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
if let Some(mt) = oprnd_ty.builtin_deref(true) {
|
||||
return Some(mt.ty);
|
||||
if let Some(ty) = oprnd_ty.builtin_deref(true) {
|
||||
return Some(ty);
|
||||
}
|
||||
|
||||
let ok = self.try_overloaded_deref(expr.span, oprnd_ty)?;
|
||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
span_bug!(expr.span, "input to deref is not a ref?");
|
||||
}
|
||||
let ty = self.make_overloaded_place_return_type(method).ty;
|
||||
let ty = self.make_overloaded_place_return_type(method);
|
||||
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
|
||||
Some(ty)
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
|
||||
|
||||
return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
|
||||
return Some((input_ty, self.make_overloaded_place_return_type(method)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,8 +342,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.borrow()
|
||||
.expr_ty_adjusted(base_expr)
|
||||
.builtin_deref(false)
|
||||
.expect("place op takes something that is not a ref")
|
||||
.ty;
|
||||
.expect("place op takes something that is not a ref");
|
||||
|
||||
let arg_ty = match op {
|
||||
PlaceOp::Deref => None,
|
||||
|
|
|
@ -78,13 +78,9 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
}
|
||||
let answer = match *elem {
|
||||
ProjectionElem::Deref => {
|
||||
let ty = self
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferenceable ty {:?}", self)
|
||||
})
|
||||
.ty;
|
||||
let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferenceable ty {:?}", self)
|
||||
});
|
||||
PlaceTy::from_ty(ty)
|
||||
}
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
|
||||
|
|
|
@ -114,16 +114,35 @@ impl Integer {
|
|||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait FloatExt)]
|
||||
impl Float {
|
||||
#[inline]
|
||||
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
match *self {
|
||||
F16 => tcx.types.f16,
|
||||
F32 => tcx.types.f32,
|
||||
F64 => tcx.types.f64,
|
||||
F128 => tcx.types.f128,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_float_ty(fty: ty::FloatTy) -> Self {
|
||||
match fty {
|
||||
ty::FloatTy::F16 => F16,
|
||||
ty::FloatTy::F32 => F32,
|
||||
ty::FloatTy::F64 => F64,
|
||||
ty::FloatTy::F128 => F128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait PrimitiveExt)]
|
||||
impl Primitive {
|
||||
#[inline]
|
||||
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
match *self {
|
||||
Int(i, signed) => i.to_ty(tcx, signed),
|
||||
F16 => tcx.types.f16,
|
||||
F32 => tcx.types.f32,
|
||||
F64 => tcx.types.f64,
|
||||
F128 => tcx.types.f128,
|
||||
Float(f) => f.to_ty(tcx),
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit),
|
||||
}
|
||||
|
@ -140,7 +159,7 @@ impl Primitive {
|
|||
let signed = false;
|
||||
tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
|
||||
}
|
||||
F16 | F32 | F64 | F128 => bug!("floats do not have an int type"),
|
||||
Float(_) => bug!("floats do not have an int type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2164,13 +2164,11 @@ impl<'tcx> Ty<'tcx> {
|
|||
///
|
||||
/// The parameter `explicit` indicates if this is an *explicit* dereference.
|
||||
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
|
||||
pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
|
||||
match self.kind() {
|
||||
Adt(def, _) if def.is_box() => {
|
||||
Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not })
|
||||
}
|
||||
Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
RawPtr(ty, mutbl) if explicit => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
|
||||
match *self.kind() {
|
||||
Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
|
||||
Ref(_, ty, _) => Some(ty),
|
||||
RawPtr(ty, _) if explicit => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::query::{IntoQueryParam, Providers};
|
||||
use crate::ty::layout::IntegerExt;
|
||||
use crate::ty::layout::{FloatExt, IntegerExt};
|
||||
use crate::ty::{
|
||||
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
|
@ -20,7 +20,7 @@ use rustc_index::bit_set::GrowableBitSet;
|
|||
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
|
||||
use rustc_target::abi::{Float, Integer, IntegerType, Size};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::{fmt, iter};
|
||||
|
@ -1145,8 +1145,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
ty::Char => Size::from_bytes(4),
|
||||
ty::Int(ity) => Integer::from_int_ty(&tcx, ity).size(),
|
||||
ty::Uint(uty) => Integer::from_uint_ty(&tcx, uty).size(),
|
||||
ty::Float(ty::FloatTy::F32) => Primitive::F32.size(&tcx),
|
||||
ty::Float(ty::FloatTy::F64) => Primitive::F64.size(&tcx),
|
||||
ty::Float(fty) => Float::from_float_ty(fty).size(),
|
||||
_ => bug!("non primitive type"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
|
|||
}
|
||||
|
||||
let pointee_ty =
|
||||
pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty;
|
||||
pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer");
|
||||
// Ideally we'd support this in the future, but for now we are limited to sized types.
|
||||
if !pointee_ty.is_sized(self.tcx, self.param_env) {
|
||||
debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
|
||||
|
|
|
@ -52,104 +52,104 @@ pub(super) struct MCDCDecision {
|
|||
pub(super) decision_depth: u16,
|
||||
}
|
||||
|
||||
pub(super) struct CoverageSpans {
|
||||
bcb_has_mappings: BitSet<BasicCoverageBlock>,
|
||||
#[derive(Default)]
|
||||
pub(super) struct ExtractedMappings {
|
||||
pub(super) code_mappings: Vec<CodeMapping>,
|
||||
pub(super) branch_pairs: Vec<BranchPair>,
|
||||
test_vector_bitmap_bytes: u32,
|
||||
pub(super) mcdc_bitmap_bytes: u32,
|
||||
pub(super) mcdc_branches: Vec<MCDCBranch>,
|
||||
pub(super) mcdc_decisions: Vec<MCDCDecision>,
|
||||
}
|
||||
|
||||
impl CoverageSpans {
|
||||
pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
|
||||
self.bcb_has_mappings.contains(bcb)
|
||||
}
|
||||
|
||||
pub(super) fn test_vector_bitmap_bytes(&self) -> u32 {
|
||||
self.test_vector_bitmap_bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts coverage-relevant spans from MIR, and associates them with
|
||||
/// their corresponding BCBs.
|
||||
///
|
||||
/// Returns `None` if no coverage-relevant spans could be extracted.
|
||||
pub(super) fn generate_coverage_spans(
|
||||
pub(super) fn extract_all_mapping_info_from_mir(
|
||||
mir_body: &mir::Body<'_>,
|
||||
hir_info: &ExtractedHirInfo,
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
) -> Option<CoverageSpans> {
|
||||
let mut code_mappings = vec![];
|
||||
let mut branch_pairs = vec![];
|
||||
let mut mcdc_branches = vec![];
|
||||
let mut mcdc_decisions = vec![];
|
||||
|
||||
) -> ExtractedMappings {
|
||||
if hir_info.is_async_fn {
|
||||
// An async function desugars into a function that returns a future,
|
||||
// with the user code wrapped in a closure. Any spans in the desugared
|
||||
// outer function will be unhelpful, so just keep the signature span
|
||||
// and ignore all of the spans in the MIR body.
|
||||
let mut mappings = ExtractedMappings::default();
|
||||
if let Some(span) = hir_info.fn_sig_span_extended {
|
||||
code_mappings.push(CodeMapping { span, bcb: START_BCB });
|
||||
mappings.code_mappings.push(CodeMapping { span, bcb: START_BCB });
|
||||
}
|
||||
} else {
|
||||
extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut code_mappings);
|
||||
|
||||
branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
|
||||
|
||||
extract_mcdc_mappings(
|
||||
mir_body,
|
||||
hir_info.body_span,
|
||||
basic_coverage_blocks,
|
||||
&mut mcdc_branches,
|
||||
&mut mcdc_decisions,
|
||||
);
|
||||
return mappings;
|
||||
}
|
||||
|
||||
if code_mappings.is_empty()
|
||||
&& branch_pairs.is_empty()
|
||||
&& mcdc_branches.is_empty()
|
||||
&& mcdc_decisions.is_empty()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let mut code_mappings = vec![];
|
||||
let mut branch_pairs = vec![];
|
||||
let mut mcdc_bitmap_bytes = 0;
|
||||
let mut mcdc_branches = vec![];
|
||||
let mut mcdc_decisions = vec![];
|
||||
|
||||
// Identify which BCBs have one or more mappings.
|
||||
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
||||
let mut insert = |bcb| {
|
||||
bcb_has_mappings.insert(bcb);
|
||||
};
|
||||
extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut code_mappings);
|
||||
|
||||
for &CodeMapping { span: _, bcb } in &code_mappings {
|
||||
insert(bcb);
|
||||
}
|
||||
for &BranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
|
||||
insert(true_bcb);
|
||||
insert(false_bcb);
|
||||
}
|
||||
for &MCDCBranch { true_bcb, false_bcb, .. } in &mcdc_branches {
|
||||
insert(true_bcb);
|
||||
insert(false_bcb);
|
||||
}
|
||||
branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
|
||||
|
||||
// Determine the length of the test vector bitmap.
|
||||
let test_vector_bitmap_bytes = mcdc_decisions
|
||||
.iter()
|
||||
.map(|&MCDCDecision { bitmap_idx, conditions_num, .. }| {
|
||||
bitmap_idx + (1_u32 << u32::from(conditions_num)).div_ceil(8)
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
extract_mcdc_mappings(
|
||||
mir_body,
|
||||
hir_info.body_span,
|
||||
basic_coverage_blocks,
|
||||
&mut mcdc_bitmap_bytes,
|
||||
&mut mcdc_branches,
|
||||
&mut mcdc_decisions,
|
||||
);
|
||||
|
||||
Some(CoverageSpans {
|
||||
bcb_has_mappings,
|
||||
ExtractedMappings {
|
||||
code_mappings,
|
||||
branch_pairs,
|
||||
test_vector_bitmap_bytes,
|
||||
mcdc_bitmap_bytes,
|
||||
mcdc_branches,
|
||||
mcdc_decisions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractedMappings {
|
||||
pub(super) fn all_bcbs_with_counter_mappings(
|
||||
&self,
|
||||
basic_coverage_blocks: &CoverageGraph, // Only used for allocating a correctly-sized set
|
||||
) -> BitSet<BasicCoverageBlock> {
|
||||
// Fully destructure self to make sure we don't miss any fields that have mappings.
|
||||
let Self {
|
||||
code_mappings,
|
||||
branch_pairs,
|
||||
mcdc_bitmap_bytes: _,
|
||||
mcdc_branches,
|
||||
mcdc_decisions,
|
||||
} = self;
|
||||
|
||||
// Identify which BCBs have one or more mappings.
|
||||
let mut bcbs_with_counter_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
|
||||
let mut insert = |bcb| {
|
||||
bcbs_with_counter_mappings.insert(bcb);
|
||||
};
|
||||
|
||||
for &CodeMapping { span: _, bcb } in code_mappings {
|
||||
insert(bcb);
|
||||
}
|
||||
for &BranchPair { true_bcb, false_bcb, .. } in branch_pairs {
|
||||
insert(true_bcb);
|
||||
insert(false_bcb);
|
||||
}
|
||||
for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_branches {
|
||||
insert(true_bcb);
|
||||
insert(false_bcb);
|
||||
}
|
||||
|
||||
// MC/DC decisions refer to BCBs, but don't require those BCBs to have counters.
|
||||
if bcbs_with_counter_mappings.is_empty() {
|
||||
debug_assert!(
|
||||
mcdc_decisions.is_empty(),
|
||||
"A function with no counter mappings shouldn't have any decisions: {mcdc_decisions:?}",
|
||||
);
|
||||
}
|
||||
|
||||
bcbs_with_counter_mappings
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_block_markers(
|
||||
|
@ -215,6 +215,7 @@ pub(super) fn extract_mcdc_mappings(
|
|||
mir_body: &mir::Body<'_>,
|
||||
body_span: Span,
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
mcdc_bitmap_bytes: &mut u32,
|
||||
mcdc_branches: &mut impl Extend<MCDCBranch>,
|
||||
mcdc_decisions: &mut impl Extend<MCDCDecision>,
|
||||
) {
|
||||
|
@ -253,8 +254,6 @@ pub(super) fn extract_mcdc_mappings(
|
|||
},
|
||||
));
|
||||
|
||||
let mut next_bitmap_idx = 0;
|
||||
|
||||
mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map(
|
||||
|decision: &mir::coverage::MCDCDecisionSpan| {
|
||||
let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
|
||||
|
@ -265,8 +264,11 @@ pub(super) fn extract_mcdc_mappings(
|
|||
.map(|&marker| bcb_from_marker(marker))
|
||||
.collect::<Option<_>>()?;
|
||||
|
||||
let bitmap_idx = next_bitmap_idx;
|
||||
next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
|
||||
// Each decision containing N conditions needs 2^N bits of space in
|
||||
// the bitmap, rounded up to a whole number of bytes.
|
||||
// The decision's "bitmap index" points to its first byte in the bitmap.
|
||||
let bitmap_idx = *mcdc_bitmap_bytes;
|
||||
*mcdc_bitmap_bytes += (1_u32 << decision.conditions_num).div_ceil(8);
|
||||
|
||||
Some(MCDCDecision {
|
||||
span,
|
||||
|
|
|
@ -7,13 +7,9 @@ mod spans;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use self::counters::{CounterIncrementSite, CoverageCounters};
|
||||
use self::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
use self::mappings::CoverageSpans;
|
||||
|
||||
use crate::MirPass;
|
||||
|
||||
use rustc_middle::mir::coverage::*;
|
||||
use rustc_middle::mir::coverage::{
|
||||
CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind,
|
||||
};
|
||||
use rustc_middle::mir::{
|
||||
self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator,
|
||||
TerminatorKind,
|
||||
|
@ -23,6 +19,11 @@ use rustc_span::def_id::LocalDefId;
|
|||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{BytePos, Pos, RelativeBytePos, Span, Symbol};
|
||||
|
||||
use crate::coverage::counters::{CounterIncrementSite, CoverageCounters};
|
||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
use crate::coverage::mappings::ExtractedMappings;
|
||||
use crate::MirPass;
|
||||
|
||||
/// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
|
||||
/// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
|
||||
/// to construct the coverage map.
|
||||
|
@ -69,24 +70,27 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Compute coverage spans from the `CoverageGraph`.
|
||||
let Some(coverage_spans) =
|
||||
mappings::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks)
|
||||
else {
|
||||
// No relevant spans were found in MIR, so skip instrumenting this function.
|
||||
return;
|
||||
};
|
||||
// Extract coverage spans and other mapping info from MIR.
|
||||
let extracted_mappings =
|
||||
mappings::extract_all_mapping_info_from_mir(mir_body, &hir_info, &basic_coverage_blocks);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure
|
||||
// every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock`
|
||||
// and all `Expression` dependencies (operands) are also generated, for any other
|
||||
// `BasicCoverageBlock`s not already associated with a coverage span.
|
||||
let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
|
||||
let coverage_counters =
|
||||
CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans);
|
||||
let bcbs_with_counter_mappings =
|
||||
extracted_mappings.all_bcbs_with_counter_mappings(&basic_coverage_blocks);
|
||||
if bcbs_with_counter_mappings.is_empty() {
|
||||
// No relevant spans were found in MIR, so skip instrumenting this function.
|
||||
return;
|
||||
}
|
||||
|
||||
let mappings = create_mappings(tcx, &hir_info, &coverage_spans, &coverage_counters);
|
||||
let bcb_has_counter_mappings = |bcb| bcbs_with_counter_mappings.contains(bcb);
|
||||
let coverage_counters =
|
||||
CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_counter_mappings);
|
||||
|
||||
let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters);
|
||||
if mappings.is_empty() {
|
||||
// No spans could be converted into valid mappings, so skip this function.
|
||||
debug!("no spans could be converted into valid mappings; skipping");
|
||||
|
@ -96,13 +100,13 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
inject_coverage_statements(
|
||||
mir_body,
|
||||
&basic_coverage_blocks,
|
||||
bcb_has_coverage_spans,
|
||||
bcb_has_counter_mappings,
|
||||
&coverage_counters,
|
||||
);
|
||||
|
||||
inject_mcdc_statements(mir_body, &basic_coverage_blocks, &coverage_spans);
|
||||
inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings);
|
||||
|
||||
let mcdc_num_condition_bitmaps = coverage_spans
|
||||
let mcdc_num_condition_bitmaps = extracted_mappings
|
||||
.mcdc_decisions
|
||||
.iter()
|
||||
.map(|&mappings::MCDCDecision { decision_depth, .. }| decision_depth)
|
||||
|
@ -112,7 +116,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
|
||||
function_source_hash: hir_info.function_source_hash,
|
||||
num_counters: coverage_counters.num_counters(),
|
||||
mcdc_bitmap_bytes: coverage_spans.test_vector_bitmap_bytes(),
|
||||
mcdc_bitmap_bytes: extracted_mappings.mcdc_bitmap_bytes,
|
||||
expressions: coverage_counters.into_expressions(),
|
||||
mappings,
|
||||
mcdc_num_condition_bitmaps,
|
||||
|
@ -127,7 +131,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||
fn create_mappings<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_info: &ExtractedHirInfo,
|
||||
coverage_spans: &CoverageSpans,
|
||||
extracted_mappings: &ExtractedMappings,
|
||||
coverage_counters: &CoverageCounters,
|
||||
) -> Vec<Mapping> {
|
||||
let source_map = tcx.sess.source_map();
|
||||
|
@ -148,9 +152,18 @@ fn create_mappings<'tcx>(
|
|||
};
|
||||
let region_for_span = |span: Span| make_code_region(source_map, file_name, span, body_span);
|
||||
|
||||
// Fully destructure the mappings struct to make sure we don't miss any kinds.
|
||||
let ExtractedMappings {
|
||||
code_mappings,
|
||||
branch_pairs,
|
||||
mcdc_bitmap_bytes: _,
|
||||
mcdc_branches,
|
||||
mcdc_decisions,
|
||||
} = extracted_mappings;
|
||||
let mut mappings = Vec::new();
|
||||
|
||||
mappings.extend(coverage_spans.code_mappings.iter().filter_map(
|
||||
mappings.extend(code_mappings.iter().filter_map(
|
||||
// Ordinary code mappings are the simplest kind.
|
||||
|&mappings::CodeMapping { span, bcb }| {
|
||||
let code_region = region_for_span(span)?;
|
||||
let kind = MappingKind::Code(term_for_bcb(bcb));
|
||||
|
@ -158,7 +171,7 @@ fn create_mappings<'tcx>(
|
|||
},
|
||||
));
|
||||
|
||||
mappings.extend(coverage_spans.branch_pairs.iter().filter_map(
|
||||
mappings.extend(branch_pairs.iter().filter_map(
|
||||
|&mappings::BranchPair { span, true_bcb, false_bcb }| {
|
||||
let true_term = term_for_bcb(true_bcb);
|
||||
let false_term = term_for_bcb(false_bcb);
|
||||
|
@ -168,7 +181,7 @@ fn create_mappings<'tcx>(
|
|||
},
|
||||
));
|
||||
|
||||
mappings.extend(coverage_spans.mcdc_branches.iter().filter_map(
|
||||
mappings.extend(mcdc_branches.iter().filter_map(
|
||||
|&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| {
|
||||
let code_region = region_for_span(span)?;
|
||||
let true_term = term_for_bcb(true_bcb);
|
||||
|
@ -181,7 +194,7 @@ fn create_mappings<'tcx>(
|
|||
},
|
||||
));
|
||||
|
||||
mappings.extend(coverage_spans.mcdc_decisions.iter().filter_map(
|
||||
mappings.extend(mcdc_decisions.iter().filter_map(
|
||||
|&mappings::MCDCDecision { span, bitmap_idx, conditions_num, .. }| {
|
||||
let code_region = region_for_span(span)?;
|
||||
let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num });
|
||||
|
@ -249,12 +262,8 @@ fn inject_coverage_statements<'tcx>(
|
|||
fn inject_mcdc_statements<'tcx>(
|
||||
mir_body: &mut mir::Body<'tcx>,
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
coverage_spans: &CoverageSpans,
|
||||
extracted_mappings: &ExtractedMappings,
|
||||
) {
|
||||
if coverage_spans.test_vector_bitmap_bytes() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Inject test vector update first because `inject_statement` always insert new statement at head.
|
||||
for &mappings::MCDCDecision {
|
||||
span: _,
|
||||
|
@ -262,7 +271,7 @@ fn inject_mcdc_statements<'tcx>(
|
|||
bitmap_idx,
|
||||
conditions_num: _,
|
||||
decision_depth,
|
||||
} in &coverage_spans.mcdc_decisions
|
||||
} in &extracted_mappings.mcdc_decisions
|
||||
{
|
||||
for end in end_bcbs {
|
||||
let end_bb = basic_coverage_blocks[*end].leader_bb();
|
||||
|
@ -275,7 +284,7 @@ fn inject_mcdc_statements<'tcx>(
|
|||
}
|
||||
|
||||
for &mappings::MCDCBranch { span: _, true_bcb, false_bcb, condition_info, decision_depth } in
|
||||
&coverage_spans.mcdc_branches
|
||||
&extracted_mappings.mcdc_branches
|
||||
{
|
||||
let Some(condition_info) = condition_info else { continue };
|
||||
let id = condition_info.condition_id;
|
||||
|
|
|
@ -202,7 +202,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
if let Some(target_len) = self.map().find_len(target.as_ref())
|
||||
&& let operand_ty = operand.ty(self.local_decls, self.tcx)
|
||||
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = operand_ty.ty.kind()
|
||||
&& let ty::Array(_, len) = operand_ty.kind()
|
||||
&& let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
|
||||
{
|
||||
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
|
||||
|
|
|
@ -594,7 +594,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
let ty = place.ty(self.local_decls, self.tcx).ty;
|
||||
if let Some(Mutability::Not) = ty.ref_mutability()
|
||||
&& let Some(pointee_ty) = ty.builtin_deref(true)
|
||||
&& pointee_ty.ty.is_freeze(self.tcx, self.param_env)
|
||||
&& pointee_ty.is_freeze(self.tcx, self.param_env)
|
||||
{
|
||||
// An immutable borrow `_x` always points to the same value for the
|
||||
// lifetime of the borrow, so we can merge all instances of `*_x`.
|
||||
|
@ -1133,9 +1133,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
|
||||
&& let Some(from) = from.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = from.ty.kind()
|
||||
&& let ty::Array(_, len) = from.kind()
|
||||
&& let Some(to) = to.builtin_deref(true)
|
||||
&& let ty::Slice(..) = to.ty.kind()
|
||||
&& let ty::Slice(..) = to.kind()
|
||||
{
|
||||
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
|
||||
}
|
||||
|
|
|
@ -79,8 +79,8 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
// add everything that may involve a vtable.
|
||||
let source_ty = operand.ty(self.body, self.tcx);
|
||||
let may_involve_vtable = match (
|
||||
source_ty.builtin_deref(true).map(|t| t.ty.kind()),
|
||||
target_ty.builtin_deref(true).map(|t| t.ty.kind()),
|
||||
source_ty.builtin_deref(true).map(|t| t.kind()),
|
||||
target_ty.builtin_deref(true).map(|t| t.kind()),
|
||||
) {
|
||||
(Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing
|
||||
_ => true,
|
||||
|
|
|
@ -48,9 +48,9 @@ fn compute_slice_length<'tcx>(
|
|||
let operand_ty = operand.ty(body, tcx);
|
||||
debug!(?operand_ty);
|
||||
if let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = operand_ty.ty.kind()
|
||||
&& let ty::Array(_, len) = operand_ty.kind()
|
||||
&& let Some(cast_ty) = cast_ty.builtin_deref(true)
|
||||
&& let ty::Slice(..) = cast_ty.ty.kind()
|
||||
&& let ty::Slice(..) = cast_ty.kind()
|
||||
{
|
||||
slice_lengths[local] = Some(*len);
|
||||
}
|
||||
|
|
|
@ -401,10 +401,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
|
|||
.use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
|
||||
.use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
|
||||
|
||||
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
|
||||
|
||||
parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}`
|
||||
.suggestion = surround the identifier with quotation marks to parse it as a string
|
||||
parse_invalid_meta_item = expected unsuffixed literal, found `{$token}`
|
||||
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
|
||||
|
||||
parse_invalid_offset_of = offset_of expects dot-separated field and variant names
|
||||
|
||||
|
|
|
@ -978,21 +978,13 @@ pub(crate) struct InvalidMetaItem {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub token: Token,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_invalid_meta_item_unquoted_ident)]
|
||||
pub(crate) struct InvalidMetaItemUnquotedIdent {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub token: Token,
|
||||
#[subdiagnostic]
|
||||
pub sugg: InvalidMetaItemSuggQuoteIdent,
|
||||
pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
|
||||
pub(crate) struct InvalidMetaItemSuggQuoteIdent {
|
||||
#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")]
|
||||
pub(crate) struct InvalidMetaItemQuoteIdentSugg {
|
||||
#[suggestion_part(code = "\"")]
|
||||
pub before: Span,
|
||||
#[suggestion_part(code = "\"")]
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use crate::errors::{
|
||||
InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent,
|
||||
SuffixedLiteralInAttribute,
|
||||
};
|
||||
use crate::errors;
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::maybe_whole;
|
||||
|
||||
|
@ -318,7 +315,7 @@ impl<'a> Parser<'a> {
|
|||
debug!("checking if {:?} is unsuffixed", lit);
|
||||
|
||||
if !lit.kind.is_unsuffixed() {
|
||||
self.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
|
||||
self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span });
|
||||
}
|
||||
|
||||
Ok(lit)
|
||||
|
@ -356,10 +353,11 @@ impl<'a> Parser<'a> {
|
|||
Ok(nmis)
|
||||
}
|
||||
|
||||
/// Matches the following grammar (per RFC 1559).
|
||||
/// Parse a meta item per RFC 1559.
|
||||
///
|
||||
/// ```ebnf
|
||||
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
|
||||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||
/// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
|
||||
/// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
|
||||
/// ```
|
||||
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
|
||||
// We can't use `maybe_whole` here because it would bump in the `None`
|
||||
|
@ -387,7 +385,6 @@ impl<'a> Parser<'a> {
|
|||
Ok(if self.eat(&token::Eq) {
|
||||
ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
|
||||
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||
// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
|
||||
let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
|
||||
ast::MetaItemKind::List(list)
|
||||
} else {
|
||||
|
@ -395,38 +392,45 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
|
||||
/// Parse an inner meta item per RFC 1559.
|
||||
///
|
||||
/// ```ebnf
|
||||
/// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
|
||||
/// ```
|
||||
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
||||
match self.parse_unsuffixed_meta_item_lit() {
|
||||
Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
|
||||
Err(err) => err.cancel(),
|
||||
Err(err) => err.cancel(), // we provide a better error below
|
||||
}
|
||||
|
||||
match self.parse_meta_item() {
|
||||
Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
|
||||
Err(err) => err.cancel(),
|
||||
Err(err) => err.cancel(), // we provide a better error below
|
||||
}
|
||||
|
||||
let token = self.token.clone();
|
||||
let mut err = errors::InvalidMetaItem {
|
||||
span: self.token.span,
|
||||
token: self.token.clone(),
|
||||
quote_ident_sugg: None,
|
||||
};
|
||||
|
||||
// Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)]
|
||||
// `from_expansion()` ensures we don't suggest for cases such as
|
||||
// `#[cfg(feature = $expr)]` in macros
|
||||
if self.prev_token == token::Eq && !self.token.span.from_expansion() {
|
||||
// Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
|
||||
// don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
|
||||
// when macro metavariables are involved.
|
||||
if self.prev_token == token::Eq
|
||||
&& let token::Ident(..) = self.token.kind
|
||||
{
|
||||
let before = self.token.span.shrink_to_lo();
|
||||
while matches!(self.token.kind, token::Ident(..)) {
|
||||
while let token::Ident(..) = self.token.kind {
|
||||
self.bump();
|
||||
}
|
||||
let after = self.prev_token.span.shrink_to_hi();
|
||||
let sugg = InvalidMetaItemSuggQuoteIdent { before, after };
|
||||
return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent {
|
||||
span: token.span,
|
||||
token,
|
||||
sugg,
|
||||
}));
|
||||
err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg {
|
||||
before,
|
||||
after: self.prev_token.span.shrink_to_hi(),
|
||||
});
|
||||
}
|
||||
|
||||
Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token }))
|
||||
Err(self.dcx().create_err(err))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -256,10 +256,9 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
|
|||
rustc_abi::Primitive::Int(length, signed) => {
|
||||
Primitive::Int { length: length.stable(tables), signed: *signed }
|
||||
}
|
||||
rustc_abi::Primitive::F16 => Primitive::Float { length: FloatLength::F16 },
|
||||
rustc_abi::Primitive::F32 => Primitive::Float { length: FloatLength::F32 },
|
||||
rustc_abi::Primitive::F64 => Primitive::Float { length: FloatLength::F64 },
|
||||
rustc_abi::Primitive::F128 => Primitive::Float { length: FloatLength::F128 },
|
||||
rustc_abi::Primitive::Float(length) => {
|
||||
Primitive::Float { length: length.stable(tables) }
|
||||
}
|
||||
rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +286,19 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::Float {
|
||||
type T = FloatLength;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Float::F16 => FloatLength::F16,
|
||||
rustc_abi::Float::F32 => FloatLength::F32,
|
||||
rustc_abi::Float::F64 => FloatLength::F64,
|
||||
rustc_abi::Float::F128 => FloatLength::F128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
|
||||
type T = WrappingRange;
|
||||
|
||||
|
|
|
@ -630,8 +630,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
let pointee_ty = ct
|
||||
.ty()
|
||||
.builtin_deref(true)
|
||||
.expect("tried to dereference on non-ptr type")
|
||||
.ty;
|
||||
.expect("tried to dereference on non-ptr type");
|
||||
// FIXME(const_generics): add an assert that we only do this for valtrees.
|
||||
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
|
||||
dereferenced_const.print(self)?;
|
||||
|
|
|
@ -59,7 +59,7 @@ where
|
|||
_ => return Err(CannotUseFpConv),
|
||||
}
|
||||
}
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
|
||||
abi::Float(_) => {
|
||||
if arg_layout.size.bits() > flen {
|
||||
return Err(CannotUseFpConv);
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ where
|
|||
{
|
||||
match ret.layout.field(cx, i).abi {
|
||||
abi::Abi::Scalar(scalar) => match scalar.primitive() {
|
||||
abi::F32 => Some(Reg::f32()),
|
||||
abi::F64 => Some(Reg::f64()),
|
||||
abi::Float(abi::F32) => Some(Reg::f32()),
|
||||
abi::Float(abi::F64) => Some(Reg::f64()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -110,7 +110,7 @@ where
|
|||
|
||||
// We only care about aligned doubles
|
||||
if let abi::Abi::Scalar(scalar) = field.abi {
|
||||
if let abi::F64 = scalar.primitive() {
|
||||
if scalar.primitive() == abi::Float(abi::F64) {
|
||||
if offset.is_aligned(dl.f64_align.abi) {
|
||||
// Insert enough integers to cover [last_offset, offset)
|
||||
assert!(last_offset.is_aligned(dl.f64_align.abi));
|
||||
|
|
|
@ -443,7 +443,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||
Abi::Scalar(scalar) => {
|
||||
let kind = match scalar.primitive() {
|
||||
abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => RegKind::Float,
|
||||
abi::Float(_) => RegKind::Float,
|
||||
};
|
||||
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ where
|
|||
_ => return Err(CannotUseFpConv),
|
||||
}
|
||||
}
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
|
||||
abi::Float(_) => {
|
||||
if arg_layout.size.bits() > flen {
|
||||
return Err(CannotUseFpConv);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ where
|
|||
{
|
||||
let dl = cx.data_layout();
|
||||
|
||||
if !matches!(scalar.primitive(), abi::F32 | abi::F64) {
|
||||
if !matches!(scalar.primitive(), abi::Float(abi::F32 | abi::F64)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ where
|
|||
return data;
|
||||
}
|
||||
|
||||
if scalar.primitive() == abi::F32 {
|
||||
if scalar.primitive() == abi::Float(abi::F32) {
|
||||
data.arg_attribute = ArgAttribute::InReg;
|
||||
data.prefix[data.prefix_index] = Some(Reg::f32());
|
||||
data.last_offset = offset + Reg::f32().size;
|
||||
|
@ -80,14 +80,14 @@ where
|
|||
{
|
||||
data = arg_scalar(cx, scalar1, offset, data);
|
||||
match (scalar1.primitive(), scalar2.primitive()) {
|
||||
(abi::F32, _) => offset += Reg::f32().size,
|
||||
(_, abi::F64) => offset += Reg::f64().size,
|
||||
(abi::Float(abi::F32), _) => offset += Reg::f32().size,
|
||||
(_, abi::Float(abi::F64)) => offset += Reg::f64().size,
|
||||
(abi::Int(i, _signed), _) => offset += i.size(),
|
||||
(abi::Pointer(_), _) => offset += Reg::i64().size,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::F32 | abi::F64) {
|
||||
if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::Float(abi::F32 | abi::F64)) {
|
||||
offset += Size::from_bytes(4 - (offset.bytes() % 4));
|
||||
}
|
||||
data = arg_scalar(cx, scalar2, offset, data);
|
||||
|
|
|
@ -51,7 +51,7 @@ where
|
|||
|
||||
Abi::Scalar(scalar) => match scalar.primitive() {
|
||||
abi::Int(..) | abi::Pointer(_) => Class::Int,
|
||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => Class::Sse,
|
||||
abi::Float(_) => Class::Sse,
|
||||
},
|
||||
|
||||
Abi::Vector { .. } => Class::Sse,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_data_structures::intern::Interned;
|
||||
pub use Float::*;
|
||||
pub use Integer::*;
|
||||
pub use Primitive::*;
|
||||
|
||||
|
@ -11,7 +12,8 @@ use rustc_macros::HashStable_Generic;
|
|||
|
||||
pub mod call;
|
||||
|
||||
pub use rustc_abi::*;
|
||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||
pub use rustc_abi::{Float, *};
|
||||
|
||||
impl ToJson for Endian {
|
||||
fn to_json(&self) -> Json {
|
||||
|
@ -207,7 +209,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||
C: HasDataLayout,
|
||||
{
|
||||
match self.abi {
|
||||
Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64),
|
||||
Abi::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
|
||||
Abi::Aggregate { .. } => {
|
||||
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
|
||||
self.field(cx, 0).is_single_fp_element(cx)
|
||||
|
|
|
@ -5,7 +5,7 @@ use rustc_index::{IndexSlice, IndexVec};
|
|||
use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::layout::{
|
||||
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
|
||||
FloatExt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
|
||||
};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
|
@ -180,12 +180,7 @@ fn layout_of_uncached<'tcx>(
|
|||
)),
|
||||
ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
|
||||
ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
|
||||
ty::Float(fty) => scalar(match fty {
|
||||
ty::FloatTy::F16 => F16,
|
||||
ty::FloatTy::F32 => F32,
|
||||
ty::FloatTy::F64 => F64,
|
||||
ty::FloatTy::F128 => F128,
|
||||
}),
|
||||
ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))),
|
||||
ty::FnPtr(_) => {
|
||||
let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
|
||||
ptr.valid_range_mut().start = 1;
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diag};
|
|||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty::{GenericArgKind, Ty, TypeAndMut};
|
||||
use rustc_middle::ty::{GenericArgKind, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::SIGNIFICANT_DROP_IN_SCRUTINEE;
|
||||
|
@ -234,9 +234,9 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
|
|||
}
|
||||
let ty = self.sig_drop_checker.get_type(expr);
|
||||
if ty.is_ref() {
|
||||
// We checked that the type was ref, so builtin_deref will return Some TypeAndMut,
|
||||
// but let's avoid any chance of an ICE
|
||||
if let Some(TypeAndMut { ty, .. }) = ty.builtin_deref(true) {
|
||||
// We checked that the type was ref, so builtin_deref will return Some,
|
||||
// but let's avoid any chance of an ICE.
|
||||
if let Some(ty) = ty.builtin_deref(true) {
|
||||
if ty.is_trivially_pure_clone_copy() {
|
||||
self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndDerefToCopy);
|
||||
} else if allow_move_and_clone {
|
||||
|
|
|
@ -70,7 +70,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
|
|||
let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default();
|
||||
let with_deref = arg_ty
|
||||
.builtin_deref(true)
|
||||
.and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty))
|
||||
.and_then(|ty| symmetric_partial_eq(cx, ty, other_ty))
|
||||
.unwrap_or_default();
|
||||
|
||||
if !with_deref.is_implemented() && !without_deref.is_implemented() {
|
||||
|
|
|
@ -134,7 +134,7 @@ fn check_rvalue<'tcx>(
|
|||
) => Err((span, "function pointer casts are not allowed in const fn".into())),
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => {
|
||||
let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) {
|
||||
deref_ty.ty
|
||||
deref_ty
|
||||
} else {
|
||||
// We cannot allow this for now.
|
||||
return Err((span, "unsizing casts are only allowed for references right now".into()));
|
||||
|
|
|
@ -136,7 +136,7 @@ impl NewPermission {
|
|||
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
) -> Self {
|
||||
// `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
|
||||
let pointee = ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee = ty.builtin_deref(true).unwrap();
|
||||
if pointee.is_unpin(*cx.tcx, cx.param_env()) {
|
||||
// A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
|
||||
// a weak protector).
|
||||
|
|
|
@ -173,7 +173,7 @@ impl<'tcx> NewPermission {
|
|||
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
zero_size: bool,
|
||||
) -> Option<Self> {
|
||||
let pointee = ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee = ty.builtin_deref(true).unwrap();
|
||||
pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| {
|
||||
// Regular `Unpin` box, give it `noalias` but only a weak protector
|
||||
// because it is valid to deallocate it within the function.
|
||||
|
|
|
@ -117,7 +117,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
"write_bytes" | "volatile_set_memory" => {
|
||||
let [ptr, val_byte, count] = check_arg_count(args)?;
|
||||
let ty = ptr.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let ty = ptr.layout.ty.builtin_deref(true).unwrap();
|
||||
let ty_layout = this.layout_of(ty)?;
|
||||
let val_byte = this.read_scalar(val_byte)?.to_u8()?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
|
|
|
@ -267,7 +267,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
Op::WrappingOffset => {
|
||||
let ptr = left.to_scalar().to_pointer(this)?;
|
||||
let offset_count = right.to_scalar().to_target_isize(this)?;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
||||
|
||||
let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
||||
let offset_bytes = offset_count.wrapping_mul(pointee_size);
|
||||
|
|
|
@ -378,8 +378,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
.builtin_deref(true)
|
||||
.ok_or_else(|| err_ub_format!(
|
||||
"wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
|
||||
))?
|
||||
.ty;
|
||||
))?;
|
||||
let key_layout = this.layout_of(key_type)?;
|
||||
|
||||
// Create key and write it into the memory where `key_ptr` wants it.
|
||||
|
|
|
@ -6,8 +6,8 @@ use base_db::salsa::Cycle;
|
|||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||
use hir_def::{
|
||||
layout::{
|
||||
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
||||
StructKind, TargetDataLayout, WrappingRange,
|
||||
Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions,
|
||||
Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
|
||||
},
|
||||
LocalFieldId, StructId,
|
||||
};
|
||||
|
@ -264,10 +264,10 @@ pub fn layout_of_ty_query(
|
|||
),
|
||||
chalk_ir::Scalar::Float(f) => scalar(
|
||||
dl,
|
||||
match f {
|
||||
FloatTy::F32 => Primitive::F32,
|
||||
FloatTy::F64 => Primitive::F64,
|
||||
},
|
||||
Primitive::Float(match f {
|
||||
FloatTy::F32 => Float::F32,
|
||||
FloatTy::F64 => Float::F64,
|
||||
}),
|
||||
),
|
||||
},
|
||||
TyKind::Tuple(len, tys) => {
|
||||
|
|
|
@ -245,7 +245,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile
|
|||
run-make/rmeta-preferred/Makefile
|
||||
run-make/rustc-macro-dep-files/Makefile
|
||||
run-make/rustdoc-io-error/Makefile
|
||||
run-make/rustdoc-output-path/Makefile
|
||||
run-make/rustdoc-scrape-examples-invalid-expr/Makefile
|
||||
run-make/rustdoc-scrape-examples-macros/Makefile
|
||||
run-make/rustdoc-scrape-examples-multiple/Makefile
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs
|
|
@ -0,0 +1,9 @@
|
|||
// Checks that if the output folder doesn't exist, rustdoc will create it.
|
||||
|
||||
use run_make_support::{rustdoc, tmp_dir};
|
||||
|
||||
fn main() {
|
||||
let out_dir = tmp_dir().join("foo/bar/doc");
|
||||
rustdoc().input("foo.rs").output(&out_dir).run();
|
||||
assert!(out_dir.exists());
|
||||
}
|
|
@ -576,7 +576,9 @@ error: ABIs are not compatible
|
|||
},
|
||||
abi: Scalar(
|
||||
Initialized {
|
||||
value: F32,
|
||||
value: Float(
|
||||
F32,
|
||||
),
|
||||
valid_range: $FULL,
|
||||
},
|
||||
),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
macro_rules! pass_nonterminal {
|
||||
($n:expr) => {
|
||||
#[repr(align($n))]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `n!()`
|
||||
//~^ ERROR expected unsuffixed literal, found `n!()`
|
||||
struct S;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: expected unsuffixed literal or identifier, found `n!()`
|
||||
error: expected unsuffixed literal, found `n!()`
|
||||
--> $DIR/nonterminal-expansion.rs:7:22
|
||||
|
|
||||
LL | #[repr(align($n))]
|
||||
|
|
|
@ -28,8 +28,8 @@ struct S9;
|
|||
macro_rules! generate_s10 {
|
||||
($expr: expr) => {
|
||||
#[cfg(feature = $expr)]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
//~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
//~^ ERROR expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
//~| ERROR expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
struct S10;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")]
|
|||
| |
|
||||
| help: consider removing the prefix
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
error: expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
||||
|
|
||||
LL | #[cfg(feature = $expr)]
|
||||
|
@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
|
|||
|
|
||||
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
error: expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
||||
|
|
||||
LL | #[cfg(feature = $expr)]
|
||||
|
|
|
@ -4,7 +4,7 @@ error: expected unsuffixed literal, found `test`
|
|||
LL | #[deprecated(note = test)]
|
||||
| ^^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[deprecated(note = "test")]
|
||||
| + +
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
macro_rules! mac {
|
||||
($attr_item: meta) => {
|
||||
#[cfg($attr_item)]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
//~| ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
//~^ ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
//~| ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
struct S;
|
||||
}
|
||||
}
|
||||
|
||||
mac!(an(arbitrary token stream));
|
||||
|
||||
#[cfg(feature = -1)]
|
||||
//~^ ERROR expected unsuffixed literal, found `-`
|
||||
//~| ERROR expected unsuffixed literal, found `-`
|
||||
fn handler() {}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
error: expected unsuffixed literal, found `-`
|
||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
||||
|
|
||||
LL | #[cfg(feature = -1)]
|
||||
| ^
|
||||
|
||||
error: expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
--> $DIR/attr-bad-meta-4.rs:3:15
|
||||
|
|
||||
LL | #[cfg($attr_item)]
|
||||
|
@ -9,7 +15,7 @@ LL | mac!(an(arbitrary token stream));
|
|||
|
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
error: expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
--> $DIR/attr-bad-meta-4.rs:3:15
|
||||
|
|
||||
LL | #[cfg($attr_item)]
|
||||
|
@ -21,5 +27,13 @@ LL | mac!(an(arbitrary token stream));
|
|||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected unsuffixed literal, found `-`
|
||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
||||
|
|
||||
LL | #[cfg(feature = -1)]
|
||||
| ^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
fn main() {
|
||||
#[cfg(key="foo")]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
println!();
|
||||
#[cfg(key="bar")]
|
||||
println!();
|
||||
#[cfg(key="foo bar baz")]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
println!();
|
||||
}
|
|
@ -1,17 +1,25 @@
|
|||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
fn main() {
|
||||
#[cfg(key=foo)]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
//~| HELP surround the identifier with quotation marks to make it into a string literal
|
||||
println!();
|
||||
#[cfg(key="bar")]
|
||||
println!();
|
||||
#[cfg(key=foo bar baz)]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
//~| HELP surround the identifier with quotation marks to make it into a string literal
|
||||
println!();
|
||||
}
|
||||
|
||||
// Don't suggest surrounding `$name` or `nickname` with quotes:
|
||||
|
||||
macro_rules! make {
|
||||
($name:ident) => { #[doc(alias = $name)] pub struct S; }
|
||||
//~^ ERROR expected unsuffixed literal, found `nickname`
|
||||
}
|
||||
|
||||
make!(nickname); //~ NOTE in this expansion
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
error: expected unsuffixed literal, found `foo`
|
||||
--> $DIR/attr-unquoted-ident.rs:7:15
|
||||
--> $DIR/attr-unquoted-ident.rs:6:15
|
||||
|
|
||||
LL | #[cfg(key=foo)]
|
||||
| ^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[cfg(key="foo")]
|
||||
| + +
|
||||
|
||||
error: expected unsuffixed literal, found `foo`
|
||||
--> $DIR/attr-unquoted-ident.rs:13:15
|
||||
--> $DIR/attr-unquoted-ident.rs:12:15
|
||||
|
|
||||
LL | #[cfg(key=foo bar baz)]
|
||||
| ^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[cfg(key="foo bar baz")]
|
||||
| + +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected unsuffixed literal, found `nickname`
|
||||
--> $DIR/attr-unquoted-ident.rs:21:38
|
||||
|
|
||||
LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; }
|
||||
| ^^^^^
|
||||
...
|
||||
LL | make!(nickname);
|
||||
| --------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
Loading…
Reference in New Issue