authorbors <bors@rust-lang.org> 2026-04-04 11:03:56 UTC
committerbors <bors@rust-lang.org> 2026-04-04 11:03:56 UTC
log981cf69479ded5e2de0cf9e16111c19d65be0369
tree3555e48972ab6a32026f7856e7f5f3e8580c81a2
parent2972b5e59f1c5529b6ba770437812fd83ab4ebd4
parent7a68d3fa0b5921475b36002c1c5974a1741713db

Auto merge of #154773 - matthiaskrgr:rollup-DMnqd9w, r=matthiaskrgr

Rollup of 7 pull requests Successful merges: - rust-lang/rust#153286 (various fixes for scalable vectors) - rust-lang/rust#153592 (Add `min_adt_const_params` gate) - rust-lang/rust#154675 (Improve shadowed private field diagnostics) - rust-lang/rust#154653 (Remove rustc_on_unimplemented's append_const_msg) - rust-lang/rust#154743 (Remove an unused `StableHash` impl.) - rust-lang/rust#154752 (Add comment to borrow-checker) - rust-lang/rust#154764 (Add tests for three ICEs that have already been fixed)

65 files changed, 3244 insertions(+), 1167 deletions(-)

compiler/rustc_abi/src/layout.rs+14-7
...@@ -10,8 +10,8 @@ use tracing::{debug, trace};...@@ -10,8 +10,8 @@ use tracing::{debug, trace};
1010
11use crate::{11use crate::{
12 AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,12 AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
13 LayoutData, Niche, NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding,13 LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
14 TargetDataLayout, Variants, WrappingRange,14 StructKind, TagEncoding, TargetDataLayout, Variants, WrappingRange,
15};15};
1616
17mod coroutine;17mod coroutine;
...@@ -204,13 +204,19 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {...@@ -204,13 +204,19 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
204 &self,204 &self,
205 element: F,205 element: F,
206 count: u64,206 count: u64,
207 number_of_vectors: NumScalableVectors,
207 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>208 ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F>
208 where209 where
209 FieldIdx: Idx,210 FieldIdx: Idx,
210 VariantIdx: Idx,211 VariantIdx: Idx,
211 F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,212 F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
212 {213 {
213 vector_type_layout(SimdVectorKind::Scalable, self.cx.data_layout(), element, count)214 vector_type_layout(
215 SimdVectorKind::Scalable(number_of_vectors),
216 self.cx.data_layout(),
217 element,
218 count,
219 )
214 }220 }
215221
216 pub fn simd_type<FieldIdx, VariantIdx, F>(222 pub fn simd_type<FieldIdx, VariantIdx, F>(
...@@ -1526,7 +1532,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {...@@ -1526,7 +1532,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
15261532
1527enum SimdVectorKind {1533enum SimdVectorKind {
1528 /// `#[rustc_scalable_vector]`1534 /// `#[rustc_scalable_vector]`
1529 Scalable,1535 Scalable(NumScalableVectors),
1530 /// `#[repr(simd, packed)]`1536 /// `#[repr(simd, packed)]`
1531 PackedFixed,1537 PackedFixed,
1532 /// `#[repr(simd)]`1538 /// `#[repr(simd)]`
...@@ -1559,9 +1565,10 @@ where...@@ -1559,9 +1565,10 @@ where
1559 let size =1565 let size =
1560 elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;1566 elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;
1561 let (repr, align) = match kind {1567 let (repr, align) = match kind {
1562 SimdVectorKind::Scalable => {1568 SimdVectorKind::Scalable(number_of_vectors) => (
1563 (BackendRepr::SimdScalableVector { element, count }, dl.llvmlike_vector_align(size))1569 BackendRepr::SimdScalableVector { element, count, number_of_vectors },
1564 }1570 dl.llvmlike_vector_align(size),
1571 ),
1565 // Non-power-of-two vectors have padding up to the next power-of-two.1572 // Non-power-of-two vectors have padding up to the next power-of-two.
1566 // If we're a packed repr, remove the padding while keeping the alignment as close1573 // If we're a packed repr, remove the padding while keeping the alignment as close
1567 // to a vector as possible.1574 // to a vector as possible.
compiler/rustc_abi/src/lib.rs+30-3
...@@ -1696,6 +1696,28 @@ impl AddressSpace {...@@ -1696,6 +1696,28 @@ impl AddressSpace {
1696 pub const ZERO: Self = AddressSpace(0);1696 pub const ZERO: Self = AddressSpace(0);
1697}1697}
16981698
1699/// How many scalable vectors are in a `BackendRepr::ScalableVector`?
1700#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1701#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
1702pub struct NumScalableVectors(pub u8);
1703
1704impl NumScalableVectors {
1705 /// Returns a `NumScalableVector` for a non-tuple scalable vector (e.g. a single vector).
1706 pub fn for_non_tuple() -> Self {
1707 NumScalableVectors(1)
1708 }
1709
1710 // Returns `NumScalableVectors` for values of two through eight, which are a valid number of
1711 // fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors`
1712 // but not for a tuple which would have a field count.
1713 pub fn from_field_count(count: usize) -> Option<Self> {
1714 match count {
1715 2..8 => Some(NumScalableVectors(count as u8)),
1716 _ => None,
1717 }
1718 }
1719}
1720
1699/// The way we represent values to the backend1721/// The way we represent values to the backend
1700///1722///
1701/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.1723/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.
...@@ -1714,6 +1736,7 @@ pub enum BackendRepr {...@@ -1714,6 +1736,7 @@ pub enum BackendRepr {
1714 SimdScalableVector {1736 SimdScalableVector {
1715 element: Scalar,1737 element: Scalar,
1716 count: u64,1738 count: u64,
1739 number_of_vectors: NumScalableVectors,
1717 },1740 },
1718 SimdVector {1741 SimdVector {
1719 element: Scalar,1742 element: Scalar,
...@@ -1820,8 +1843,12 @@ impl BackendRepr {...@@ -1820,8 +1843,12 @@ impl BackendRepr {
1820 BackendRepr::SimdVector { element: element.to_union(), count }1843 BackendRepr::SimdVector { element: element.to_union(), count }
1821 }1844 }
1822 BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },1845 BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
1823 BackendRepr::SimdScalableVector { element, count } => {1846 BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
1824 BackendRepr::SimdScalableVector { element: element.to_union(), count }1847 BackendRepr::SimdScalableVector {
1848 element: element.to_union(),
1849 count,
1850 number_of_vectors,
1851 }
1825 }1852 }
1826 }1853 }
1827 }1854 }
...@@ -2161,7 +2188,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {...@@ -2161,7 +2188,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
2161 }2188 }
21622189
2163 /// Returns `true` if the size of the type is only known at runtime.2190 /// Returns `true` if the size of the type is only known at runtime.
2164 pub fn is_runtime_sized(&self) -> bool {2191 pub fn is_scalable_vector(&self) -> bool {
2165 matches!(self.backend_repr, BackendRepr::SimdScalableVector { .. })2192 matches!(self.backend_repr, BackendRepr::SimdScalableVector { .. })
2166 }2193 }
21672194
compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs+9-15
...@@ -3,8 +3,8 @@ use std::ops::Range;...@@ -3,8 +3,8 @@ use std::ops::Range;
3use rustc_errors::E0232;3use rustc_errors::E0232;
4use rustc_hir::AttrPath;4use rustc_hir::AttrPath;
5use rustc_hir::attrs::diagnostic::{5use rustc_hir::attrs::diagnostic::{
6 AppendConstMessage, Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg,6 Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue,
7 Name, NameValue, OnUnimplementedCondition, Piece, Predicate,7 OnUnimplementedCondition, Piece, Predicate,
8};8};
9use rustc_hir::lints::{AttributeLintKind, FormatWarning};9use rustc_hir::lints::{AttributeLintKind, FormatWarning};
10use rustc_macros::Diagnostic;10use rustc_macros::Diagnostic;
...@@ -92,7 +92,6 @@ fn parse_directive_items<'p, S: Stage>(...@@ -92,7 +92,6 @@ fn parse_directive_items<'p, S: Stage>(
92 let mut notes = ThinVec::new();92 let mut notes = ThinVec::new();
93 let mut parent_label = None;93 let mut parent_label = None;
94 let mut subcommands = ThinVec::new();94 let mut subcommands = ThinVec::new();
95 let mut append_const_msg = None;
9695
97 for item in items {96 for item in items {
98 let span = item.span();97 let span = item.span();
...@@ -131,7 +130,6 @@ fn parse_directive_items<'p, S: Stage>(...@@ -131,7 +130,6 @@ fn parse_directive_items<'p, S: Stage>(
131 let Some(ret) = (||{130 let Some(ret) = (||{
132 Some($($code)*)131 Some($($code)*)
133 })() else {132 })() else {
134
135 malformed!()133 malformed!()
136 };134 };
137 ret135 ret
...@@ -159,8 +157,13 @@ fn parse_directive_items<'p, S: Stage>(...@@ -159,8 +157,13 @@ fn parse_directive_items<'p, S: Stage>(
159 let item: &MetaItemParser = or_malformed!(item.meta_item()?);157 let item: &MetaItemParser = or_malformed!(item.meta_item()?);
160 let name = or_malformed!(item.ident()?).name;158 let name = or_malformed!(item.ident()?).name;
161159
162 // Some things like `message = "message"` must have a value.160 // Currently, as of April 2026, all arguments of all diagnostic attrs
163 // But with things like `append_const_msg` that is optional.161 // must have a value, like `message = "message"`. Thus in a well-formed
162 // diagnostic attribute this is never `None`.
163 //
164 // But we don't assert its presence yet because we don't want to mention it
165 // if someone does something like `#[diagnostic::on_unimplemented(doesnt_exist)]`.
166 // That happens in the big `match` below.
164 let value: Option<Ident> = match item.args().name_value() {167 let value: Option<Ident> = match item.args().name_value() {
165 Some(nv) => Some(or_malformed!(nv.value_as_ident()?)),168 Some(nv) => Some(or_malformed!(nv.value_as_ident()?)),
166 None => None,169 None => None,
...@@ -223,14 +226,6 @@ fn parse_directive_items<'p, S: Stage>(...@@ -223,14 +226,6 @@ fn parse_directive_items<'p, S: Stage>(
223 let value = or_malformed!(value?);226 let value = or_malformed!(value?);
224 notes.push(parse_format(value))227 notes.push(parse_format(value))
225 }228 }
226
227 (Mode::RustcOnUnimplemented, sym::append_const_msg) => {
228 append_const_msg = if let Some(msg) = value {
229 Some(AppendConstMessage::Custom(msg.name, item.span()))
230 } else {
231 Some(AppendConstMessage::Default)
232 }
233 }
234 (Mode::RustcOnUnimplemented, sym::parent_label) => {229 (Mode::RustcOnUnimplemented, sym::parent_label) => {
235 let value = or_malformed!(value?);230 let value = or_malformed!(value?);
236 if parent_label.is_none() {231 if parent_label.is_none() {
...@@ -290,7 +285,6 @@ fn parse_directive_items<'p, S: Stage>(...@@ -290,7 +285,6 @@ fn parse_directive_items<'p, S: Stage>(
290 label,285 label,
291 notes,286 notes,
292 parent_label,287 parent_label,
293 append_const_msg,
294 })288 })
295}289}
296290
compiler/rustc_borrowck/src/type_check/mod.rs+2
...@@ -447,6 +447,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {...@@ -447,6 +447,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
447 let tcx = self.infcx.tcx;447 let tcx = self.infcx.tcx;
448448
449 for proj in &user_ty.projs {449 for proj in &user_ty.projs {
450 // Necessary for non-trivial patterns whose user-type annotation is an opaque type,
451 // e.g. `let (_a,): Tait = whatever`, see #105897
450 if !self.infcx.next_trait_solver()452 if !self.infcx.next_trait_solver()
451 && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()453 && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
452 {454 {
compiler/rustc_codegen_gcc/src/builder.rs+4-3
...@@ -24,7 +24,8 @@ use rustc_data_structures::fx::FxHashSet;...@@ -24,7 +24,8 @@ use rustc_data_structures::fx::FxHashSet;
24use rustc_middle::bug;24use rustc_middle::bug;
25use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;25use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
26use rustc_middle::ty::layout::{26use rustc_middle::ty::layout::{
27 FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,27 FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
28 LayoutOfHelpers, TyAndLayout,
28};29};
29use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};30use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
30use rustc_span::Span;31use rustc_span::Span;
...@@ -943,8 +944,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {...@@ -943,8 +944,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
943 .get_address(self.location)944 .get_address(self.location)
944 }945 }
945946
946 fn scalable_alloca(&mut self, _elt: u64, _align: Align, _element_ty: Ty<'_>) -> RValue<'gcc> {947 fn alloca_with_ty(&mut self, ty: TyAndLayout<'tcx>) -> RValue<'gcc> {
947 todo!()948 self.alloca(ty.layout.size, ty.layout.align.abi)
948 }949 }
949950
950 fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {951 fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
compiler/rustc_codegen_gcc/src/common.rs+4
...@@ -145,6 +145,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {...@@ -145,6 +145,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
145 self.const_int(self.type_i32(), i as i64)145 self.const_int(self.type_i32(), i as i64)
146 }146 }
147147
148 fn const_i64(&self, i: i64) -> RValue<'gcc> {
149 self.const_int(self.type_i64(), i)
150 }
151
148 fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {152 fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
149 self.gcc_int(typ, int)153 self.gcc_int(typ, int)
150 }154 }
compiler/rustc_codegen_llvm/src/builder.rs+5-13
...@@ -7,8 +7,7 @@ pub(crate) mod autodiff;...@@ -7,8 +7,7 @@ pub(crate) mod autodiff;
7pub(crate) mod gpu_offload;7pub(crate) mod gpu_offload;
88
9use libc::{c_char, c_uint};9use libc::{c_char, c_uint};
10use rustc_abi as abi;10use rustc_abi::{self as abi, Align, Size, WrappingRange};
11use rustc_abi::{Align, Size, WrappingRange};
12use rustc_codegen_ssa::MemFlags;11use rustc_codegen_ssa::MemFlags;
13use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};12use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
14use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};13use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
...@@ -616,21 +615,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {...@@ -616,21 +615,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
616 }615 }
617 }616 }
618617
619 fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value {618 fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value {
620 let mut bx = Builder::with_cx(self.cx);619 let mut bx = Builder::with_cx(self.cx);
621 bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });620 bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
622 let llvm_ty = match element_ty.kind() {621 let scalable_vector_ty = layout.llvm_type(self.cx);
623 ty::Bool => bx.type_i1(),
624 ty::Int(int_ty) => self.cx.type_int_from_ty(*int_ty),
625 ty::Uint(uint_ty) => self.cx.type_uint_from_ty(*uint_ty),
626 ty::Float(float_ty) => self.cx.type_float_from_ty(*float_ty),
627 _ => unreachable!("scalable vectors can only contain a bool, int, uint or float"),
628 };
629622
630 unsafe {623 unsafe {
631 let ty = llvm::LLVMScalableVectorType(llvm_ty, elt.try_into().unwrap());624 let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, scalable_vector_ty, UNNAMED);
632 let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, ty, UNNAMED);625 llvm::LLVMSetAlignment(alloca, layout.align.abi.bytes() as c_uint);
633 llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
634 alloca626 alloca
635 }627 }
636 }628 }
compiler/rustc_codegen_llvm/src/common.rs+4
...@@ -159,6 +159,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {...@@ -159,6 +159,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
159 self.const_int(self.type_i32(), i as i64)159 self.const_int(self.type_i32(), i as i64)
160 }160 }
161161
162 fn const_i64(&self, i: i64) -> &'ll Value {
163 self.const_int(self.type_i64(), i as i64)
164 }
165
162 fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {166 fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
163 debug_assert!(167 debug_assert!(
164 self.type_kind(t) == TypeKind::Integer,168 self.type_kind(t) == TypeKind::Integer,
compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs+8
...@@ -35,6 +35,14 @@ declare_constant!(DW_OP_plus_uconst: u64);...@@ -35,6 +35,14 @@ declare_constant!(DW_OP_plus_uconst: u64);
35/// Double-checked by a static assertion in `RustWrapper.cpp`.35/// Double-checked by a static assertion in `RustWrapper.cpp`.
36#[allow(non_upper_case_globals)]36#[allow(non_upper_case_globals)]
37pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;37pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
38#[allow(non_upper_case_globals)]
39pub(crate) const DW_OP_constu: u64 = 0x10;
40#[allow(non_upper_case_globals)]
41pub(crate) const DW_OP_minus: u64 = 0x1c;
42#[allow(non_upper_case_globals)]
43pub(crate) const DW_OP_mul: u64 = 0x1e;
44#[allow(non_upper_case_globals)]
45pub(crate) const DW_OP_bregx: u64 = 0x92;
38// It describes the actual value of a source variable which might not exist in registers or in memory.46// It describes the actual value of a source variable which might not exist in registers or in memory.
39#[allow(non_upper_case_globals)]47#[allow(non_upper_case_globals)]
40pub(crate) const DW_OP_stack_value: u64 = 0x9f;48pub(crate) const DW_OP_stack_value: u64 = 0x9f;
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs+116-6
...@@ -3,10 +3,10 @@ use std::fmt::{self, Write};...@@ -3,10 +3,10 @@ use std::fmt::{self, Write};
3use std::hash::{Hash, Hasher};3use std::hash::{Hash, Hasher};
4use std::path::PathBuf;4use std::path::PathBuf;
5use std::sync::Arc;5use std::sync::Arc;
6use std::{iter, ptr};6use std::{assert_matches, iter, ptr};
77
8use libc::{c_longlong, c_uint};8use libc::{c_longlong, c_uint};
9use rustc_abi::{Align, Size};9use rustc_abi::{Align, Layout, NumScalableVectors, Size};
10use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};10use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
11use rustc_codegen_ssa::traits::*;11use rustc_codegen_ssa::traits::*;
12use rustc_hir::def::{CtorKind, DefKind};12use rustc_hir::def::{CtorKind, DefKind};
...@@ -16,12 +16,12 @@ use rustc_middle::ty::layout::{...@@ -16,12 +16,12 @@ use rustc_middle::ty::layout::{
16 HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,16 HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
17};17};
18use rustc_middle::ty::{18use rustc_middle::ty::{
19 self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,19 self, AdtDef, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
20};20};
21use rustc_session::config::{self, DebugInfo, Lto};21use rustc_session::config::{self, DebugInfo, Lto};
22use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};22use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
23use rustc_symbol_mangling::typeid_for_trait_ref;23use rustc_symbol_mangling::typeid_for_trait_ref;
24use rustc_target::spec::DebuginfoKind;24use rustc_target::spec::{Arch, DebuginfoKind};
25use smallvec::smallvec;25use smallvec::smallvec;
26use tracing::{debug, instrument};26use tracing::{debug, instrument};
2727
...@@ -33,7 +33,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na...@@ -33,7 +33,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
33use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};33use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
34use crate::common::{AsCCharPtr, CodegenCx};34use crate::common::{AsCCharPtr, CodegenCx};
35use crate::debuginfo::metadata::type_map::build_type_with_children;35use crate::debuginfo::metadata::type_map::build_type_with_children;
36use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};36use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind};
37use crate::debuginfo::{DIBuilderExt, dwarf_const};37use crate::debuginfo::{DIBuilderExt, dwarf_const};
38use crate::llvm::debuginfo::{38use crate::llvm::debuginfo::{
39 DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,39 DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,
...@@ -1039,6 +1039,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(...@@ -1039,6 +1039,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
1039 span: Span,1039 span: Span,
1040) -> DINodeCreationResult<'ll> {1040) -> DINodeCreationResult<'ll> {
1041 let struct_type = unique_type_id.expect_ty();1041 let struct_type = unique_type_id.expect_ty();
1042
1042 let ty::Adt(adt_def, _) = struct_type.kind() else {1043 let ty::Adt(adt_def, _) = struct_type.kind() else {
1043 bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);1044 bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
1044 };1045 };
...@@ -1051,6 +1052,21 @@ fn build_struct_type_di_node<'ll, 'tcx>(...@@ -1051,6 +1052,21 @@ fn build_struct_type_di_node<'ll, 'tcx>(
1051 } else {1052 } else {
1052 None1053 None
1053 };1054 };
1055 let name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
1056
1057 if struct_type.is_scalable_vector() {
1058 let parts = struct_type.scalable_vector_parts(cx.tcx).unwrap();
1059 return build_scalable_vector_di_node(
1060 cx,
1061 unique_type_id,
1062 name,
1063 *adt_def,
1064 parts,
1065 struct_type_and_layout.layout,
1066 def_location,
1067 containing_scope,
1068 );
1069 }
10541070
1055 type_map::build_type_with_children(1071 type_map::build_type_with_children(
1056 cx,1072 cx,
...@@ -1058,7 +1074,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(...@@ -1058,7 +1074,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
1058 cx,1074 cx,
1059 Stub::Struct,1075 Stub::Struct,
1060 unique_type_id,1076 unique_type_id,
1061 &compute_debuginfo_type_name(cx.tcx, struct_type, false),1077 &name,
1062 def_location,1078 def_location,
1063 size_and_align_of(struct_type_and_layout),1079 size_and_align_of(struct_type_and_layout),
1064 Some(containing_scope),1080 Some(containing_scope),
...@@ -1101,6 +1117,100 @@ fn build_struct_type_di_node<'ll, 'tcx>(...@@ -1101,6 +1117,100 @@ fn build_struct_type_di_node<'ll, 'tcx>(
1101 )1117 )
1102}1118}
11031119
1120/// Generate debuginfo for a `#[rustc_scalable_vector]` type.
1121///
1122/// Debuginfo for a scalable vector uses a derived type based on a composite type. The composite
1123/// type has the `DIFlagVector` flag set and is based on the element type of the scalable vector.
1124/// The composite type has a subrange from 0 to an expression that calculates the number of
1125/// elements in the vector.
1126///
1127/// ```text,ignore
1128/// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...)
1129/// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4)
1130/// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
1131/// !4 = !{!5}
1132/// !5 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
1133/// ```
1134///
1135/// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this
1136/// is generated for C and C++.
1137fn build_scalable_vector_di_node<'ll, 'tcx>(
1138 cx: &CodegenCx<'ll, 'tcx>,
1139 unique_type_id: UniqueTypeId<'tcx>,
1140 name: String,
1141 adt_def: AdtDef<'tcx>,
1142 (element_count, element_ty, number_of_vectors): (u16, Ty<'tcx>, NumScalableVectors),
1143 layout: Layout<'tcx>,
1144 def_location: Option<DefinitionLocation<'ll>>,
1145 containing_scope: &'ll DIScope,
1146) -> DINodeCreationResult<'ll> {
1147 use dwarf_const::{DW_OP_bregx, DW_OP_constu, DW_OP_minus, DW_OP_mul};
1148 assert!(adt_def.repr().scalable());
1149 // This logic is specific to AArch64 for the moment, but can be extended for other architectures
1150 // later.
1151 assert_matches!(cx.tcx.sess.target.arch, Arch::AArch64);
1152
1153 let (file_metadata, line_number) = if let Some(def_location) = def_location {
1154 (def_location.0, def_location.1)
1155 } else {
1156 (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
1157 };
1158
1159 let (bitstride, element_di_node) = if element_ty.is_bool() {
1160 (Some(llvm::LLVMValueAsMetadata(cx.const_i64(1))), type_di_node(cx, cx.tcx.types.u8))
1161 } else {
1162 (None, type_di_node(cx, element_ty))
1163 };
1164
1165 let number_of_elements: u64 = (element_count as u64) * (number_of_vectors.0 as u64);
1166 let number_of_elements_per_vg = number_of_elements / 2;
1167 let mut expr = smallvec::SmallVec::<[u64; 9]>::new();
1168 // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
1169 expr.push(DW_OP_constu); // Push a constant onto the stack
1170 expr.push(number_of_elements_per_vg);
1171 expr.push(DW_OP_bregx); // Push the value of a register + offset on to the stack
1172 expr.push(/* AArch64::VG */ 46u64);
1173 expr.push(0u64);
1174 expr.push(DW_OP_mul); // Multiply top two values on stack
1175 expr.push(DW_OP_constu); // Push a constant onto the stack
1176 expr.push(1u64);
1177 expr.push(DW_OP_minus); // Subtract top two values on stack
1178
1179 let di_builder = DIB(cx);
1180 let metadata = unsafe {
1181 let upper = llvm::LLVMDIBuilderCreateExpression(di_builder, expr.as_ptr(), expr.len());
1182 let subrange = llvm::LLVMRustDIGetOrCreateSubrange(
1183 di_builder,
1184 /* CountNode */ None,
1185 llvm::LLVMValueAsMetadata(cx.const_i64(0)),
1186 upper,
1187 /* Stride */ None,
1188 );
1189 let subscripts = create_DIArray(di_builder, &[Some(subrange)]);
1190 let vector_ty = llvm::LLVMRustDICreateVectorType(
1191 di_builder,
1192 /* Size */ 0,
1193 layout.align.bits() as u32,
1194 element_di_node,
1195 subscripts,
1196 bitstride,
1197 );
1198 llvm::LLVMDIBuilderCreateTypedef(
1199 di_builder,
1200 vector_ty,
1201 name.as_ptr(),
1202 name.len(),
1203 file_metadata,
1204 line_number,
1205 Some(containing_scope),
1206 layout.align.bits() as u32,
1207 )
1208 };
1209
1210 debug_context(cx).type_map.insert(unique_type_id, metadata);
1211 DINodeCreationResult { di_node: metadata, already_stored_in_typemap: true }
1212}
1213
1104//=-----------------------------------------------------------------------------1214//=-----------------------------------------------------------------------------
1105// Tuples1215// Tuples
1106//=-----------------------------------------------------------------------------1216//=-----------------------------------------------------------------------------
compiler/rustc_codegen_llvm/src/intrinsic.rs+225-90
...@@ -3,7 +3,8 @@ use std::ffi::c_uint;...@@ -3,7 +3,8 @@ use std::ffi::c_uint;
3use std::{assert_matches, ptr};3use std::{assert_matches, ptr};
44
5use rustc_abi::{5use rustc_abi::{
6 Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,6 Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size,
7 WrappingRange,
7};8};
8use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};9use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
9use rustc_codegen_ssa::common::{IntPredicate, TypeKind};10use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
...@@ -605,6 +606,136 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {...@@ -605,6 +606,136 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
605 self.pointercast(val, self.type_ptr())606 self.pointercast(val, self.type_ptr())
606 }607 }
607608
609 sym::sve_cast => {
610 let Some((in_cnt, in_elem, in_num_vecs)) =
611 args[0].layout.ty.scalable_vector_parts(self.cx.tcx)
612 else {
613 bug!("input parameter to `sve_cast` was not scalable vector");
614 };
615 let out_layout = self.layout_of(fn_args.type_at(1));
616 let Some((out_cnt, out_elem, out_num_vecs)) =
617 out_layout.ty.scalable_vector_parts(self.cx.tcx)
618 else {
619 bug!("output parameter to `sve_cast` was not scalable vector");
620 };
621 assert_eq!(in_cnt, out_cnt);
622 assert_eq!(in_num_vecs, out_num_vecs);
623 let out_llty = self.backend_type(out_layout);
624 match simd_cast(self, sym::simd_cast, args, out_llty, in_elem, out_elem) {
625 Some(val) => val,
626 _ => bug!("could not cast scalable vectors"),
627 }
628 }
629
630 sym::sve_tuple_create2 => {
631 assert_matches!(
632 self.layout_of(fn_args.type_at(0)).backend_repr,
633 BackendRepr::SimdScalableVector {
634 number_of_vectors: NumScalableVectors(1),
635 ..
636 }
637 );
638 let tuple_ty = self.layout_of(fn_args.type_at(1));
639 assert_matches!(
640 tuple_ty.backend_repr,
641 BackendRepr::SimdScalableVector {
642 number_of_vectors: NumScalableVectors(2),
643 ..
644 }
645 );
646 let ret = self.const_poison(self.backend_type(tuple_ty));
647 let ret = self.insert_value(ret, args[0].immediate(), 0);
648 self.insert_value(ret, args[1].immediate(), 1)
649 }
650
651 sym::sve_tuple_create3 => {
652 assert_matches!(
653 self.layout_of(fn_args.type_at(0)).backend_repr,
654 BackendRepr::SimdScalableVector {
655 number_of_vectors: NumScalableVectors(1),
656 ..
657 }
658 );
659 let tuple_ty = self.layout_of(fn_args.type_at(1));
660 assert_matches!(
661 tuple_ty.backend_repr,
662 BackendRepr::SimdScalableVector {
663 number_of_vectors: NumScalableVectors(3),
664 ..
665 }
666 );
667 let ret = self.const_poison(self.backend_type(tuple_ty));
668 let ret = self.insert_value(ret, args[0].immediate(), 0);
669 let ret = self.insert_value(ret, args[1].immediate(), 1);
670 self.insert_value(ret, args[2].immediate(), 2)
671 }
672
673 sym::sve_tuple_create4 => {
674 assert_matches!(
675 self.layout_of(fn_args.type_at(0)).backend_repr,
676 BackendRepr::SimdScalableVector {
677 number_of_vectors: NumScalableVectors(1),
678 ..
679 }
680 );
681 let tuple_ty = self.layout_of(fn_args.type_at(1));
682 assert_matches!(
683 tuple_ty.backend_repr,
684 BackendRepr::SimdScalableVector {
685 number_of_vectors: NumScalableVectors(4),
686 ..
687 }
688 );
689 let ret = self.const_poison(self.backend_type(tuple_ty));
690 let ret = self.insert_value(ret, args[0].immediate(), 0);
691 let ret = self.insert_value(ret, args[1].immediate(), 1);
692 let ret = self.insert_value(ret, args[2].immediate(), 2);
693 self.insert_value(ret, args[3].immediate(), 3)
694 }
695
696 sym::sve_tuple_get => {
697 assert_matches!(
698 self.layout_of(fn_args.type_at(0)).backend_repr,
699 BackendRepr::SimdScalableVector {
700 number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8),
701 ..
702 }
703 );
704 assert_matches!(
705 self.layout_of(fn_args.type_at(1)).backend_repr,
706 BackendRepr::SimdScalableVector {
707 number_of_vectors: NumScalableVectors(1),
708 ..
709 }
710 );
711 self.extract_value(
712 args[0].immediate(),
713 fn_args.const_at(2).to_leaf().to_i32() as u64,
714 )
715 }
716
717 sym::sve_tuple_set => {
718 assert_matches!(
719 self.layout_of(fn_args.type_at(0)).backend_repr,
720 BackendRepr::SimdScalableVector {
721 number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8),
722 ..
723 }
724 );
725 assert_matches!(
726 self.layout_of(fn_args.type_at(1)).backend_repr,
727 BackendRepr::SimdScalableVector {
728 number_of_vectors: NumScalableVectors(1),
729 ..
730 }
731 );
732 self.insert_value(
733 args[0].immediate(),
734 args[1].immediate(),
735 fn_args.const_at(2).to_leaf().to_i32() as u64,
736 )
737 }
738
608 _ if name.as_str().starts_with("simd_") => {739 _ if name.as_str().starts_with("simd_") => {
609 // Unpack non-power-of-2 #[repr(packed, simd)] arguments.740 // Unpack non-power-of-2 #[repr(packed, simd)] arguments.
610 // This gives them the expected layout of a regular #[repr(simd)] vector.741 // This gives them the expected layout of a regular #[repr(simd)] vector.
...@@ -2662,96 +2793,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(...@@ -2662,96 +2793,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
2662 out_len2793 out_len
2663 }2794 }
2664 );2795 );
2665 // casting cares about nominal type, not just structural type2796 match simd_cast(bx, name, args, llret_ty, in_elem, out_elem) {
2666 if in_elem == out_elem {2797 Some(val) => return Ok(val),
2667 return Ok(args[0].immediate());2798 None => return_error!(InvalidMonomorphization::UnsupportedCast {
2668 }2799 span,
26692800 name,
2670 #[derive(Copy, Clone)]2801 in_ty,
2671 enum Sign {2802 in_elem,
2672 Unsigned,2803 ret_ty,
2673 Signed,2804 out_elem
2674 }2805 }),
2675 use Sign::*;
2676
2677 enum Style {
2678 Float,
2679 Int(Sign),
2680 Unsupported,
2681 }
2682
2683 let (in_style, in_width) = match in_elem.kind() {
2684 // vectors of pointer-sized integers should've been
2685 // disallowed before here, so this unwrap is safe.
2686 ty::Int(i) => (
2687 Style::Int(Signed),
2688 i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
2689 ),
2690 ty::Uint(u) => (
2691 Style::Int(Unsigned),
2692 u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
2693 ),
2694 ty::Float(f) => (Style::Float, f.bit_width()),
2695 _ => (Style::Unsupported, 0),
2696 };
2697 let (out_style, out_width) = match out_elem.kind() {
2698 ty::Int(i) => (
2699 Style::Int(Signed),
2700 i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
2701 ),
2702 ty::Uint(u) => (
2703 Style::Int(Unsigned),
2704 u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
2705 ),
2706 ty::Float(f) => (Style::Float, f.bit_width()),
2707 _ => (Style::Unsupported, 0),
2708 };
2709
2710 match (in_style, out_style) {
2711 (Style::Int(sign), Style::Int(_)) => {
2712 return Ok(match in_width.cmp(&out_width) {
2713 Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
2714 Ordering::Equal => args[0].immediate(),
2715 Ordering::Less => match sign {
2716 Sign::Signed => bx.sext(args[0].immediate(), llret_ty),
2717 Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty),
2718 },
2719 });
2720 }
2721 (Style::Int(Sign::Signed), Style::Float) => {
2722 return Ok(bx.sitofp(args[0].immediate(), llret_ty));
2723 }
2724 (Style::Int(Sign::Unsigned), Style::Float) => {
2725 return Ok(bx.uitofp(args[0].immediate(), llret_ty));
2726 }
2727 (Style::Float, Style::Int(sign)) => {
2728 return Ok(match (sign, name == sym::simd_as) {
2729 (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty),
2730 (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty),
2731 (_, true) => bx.cast_float_to_int(
2732 matches!(sign, Sign::Signed),
2733 args[0].immediate(),
2734 llret_ty,
2735 ),
2736 });
2737 }
2738 (Style::Float, Style::Float) => {
2739 return Ok(match in_width.cmp(&out_width) {
2740 Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
2741 Ordering::Equal => args[0].immediate(),
2742 Ordering::Less => bx.fpext(args[0].immediate(), llret_ty),
2743 });
2744 }
2745 _ => { /* Unsupported. Fallthrough. */ }
2746 }2806 }
2747 return_error!(InvalidMonomorphization::UnsupportedCast {
2748 span,
2749 name,
2750 in_ty,
2751 in_elem,
2752 ret_ty,
2753 out_elem
2754 });
2755 }2807 }
2756 macro_rules! arith_binary {2808 macro_rules! arith_binary {
2757 ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {2809 ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
...@@ -2925,3 +2977,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>(...@@ -2925,3 +2977,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
29252977
2926 span_bug!(span, "unknown SIMD intrinsic");2978 span_bug!(span, "unknown SIMD intrinsic");
2927}2979}
2980
2981/// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`.
2982fn simd_cast<'ll, 'tcx>(
2983 bx: &mut Builder<'_, 'll, 'tcx>,
2984 name: Symbol,
2985 args: &[OperandRef<'tcx, &'ll Value>],
2986 llret_ty: &'ll Type,
2987 in_elem: Ty<'tcx>,
2988 out_elem: Ty<'tcx>,
2989) -> Option<&'ll Value> {
2990 // Casting cares about nominal type, not just structural type
2991 if in_elem == out_elem {
2992 return Some(args[0].immediate());
2993 }
2994
2995 #[derive(Copy, Clone)]
2996 enum Sign {
2997 Unsigned,
2998 Signed,
2999 }
3000 use Sign::*;
3001
3002 enum Style {
3003 Float,
3004 Int(Sign),
3005 Unsupported,
3006 }
3007
3008 let (in_style, in_width) = match in_elem.kind() {
3009 // vectors of pointer-sized integers should've been
3010 // disallowed before here, so this unwrap is safe.
3011 ty::Int(i) => (
3012 Style::Int(Signed),
3013 i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
3014 ),
3015 ty::Uint(u) => (
3016 Style::Int(Unsigned),
3017 u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
3018 ),
3019 ty::Float(f) => (Style::Float, f.bit_width()),
3020 _ => (Style::Unsupported, 0),
3021 };
3022 let (out_style, out_width) = match out_elem.kind() {
3023 ty::Int(i) => (
3024 Style::Int(Signed),
3025 i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
3026 ),
3027 ty::Uint(u) => (
3028 Style::Int(Unsigned),
3029 u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
3030 ),
3031 ty::Float(f) => (Style::Float, f.bit_width()),
3032 _ => (Style::Unsupported, 0),
3033 };
3034
3035 match (in_style, out_style) {
3036 (Style::Int(sign), Style::Int(_)) => Some(match in_width.cmp(&out_width) {
3037 Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
3038 Ordering::Equal => args[0].immediate(),
3039 Ordering::Less => match sign {
3040 Sign::Signed => bx.sext(args[0].immediate(), llret_ty),
3041 Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty),
3042 },
3043 }),
3044 (Style::Int(Sign::Signed), Style::Float) => Some(bx.sitofp(args[0].immediate(), llret_ty)),
3045 (Style::Int(Sign::Unsigned), Style::Float) => {
3046 Some(bx.uitofp(args[0].immediate(), llret_ty))
3047 }
3048 (Style::Float, Style::Int(sign)) => Some(match (sign, name == sym::simd_as) {
3049 (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty),
3050 (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty),
3051 (_, true) => {
3052 bx.cast_float_to_int(matches!(sign, Sign::Signed), args[0].immediate(), llret_ty)
3053 }
3054 }),
3055 (Style::Float, Style::Float) => Some(match in_width.cmp(&out_width) {
3056 Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
3057 Ordering::Equal => args[0].immediate(),
3058 Ordering::Less => bx.fpext(args[0].immediate(), llret_ty),
3059 }),
3060 _ => None,
3061 }
3062}
compiler/rustc_codegen_llvm/src/llvm/ffi.rs+17
...@@ -2302,6 +2302,23 @@ unsafe extern "C" {...@@ -2302,6 +2302,23 @@ unsafe extern "C" {
2302 Params: Option<&'a DIArray>,2302 Params: Option<&'a DIArray>,
2303 );2303 );
23042304
2305 pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>(
2306 Builder: &DIBuilder<'a>,
2307 CountNode: Option<&'a Metadata>,
2308 LB: &'a Metadata,
2309 UB: &'a Metadata,
2310 Stride: Option<&'a Metadata>,
2311 ) -> &'a Metadata;
2312
2313 pub(crate) fn LLVMRustDICreateVectorType<'a>(
2314 Builder: &DIBuilder<'a>,
2315 Size: u64,
2316 AlignInBits: u32,
2317 Type: &'a DIType,
2318 Subscripts: &'a DIArray,
2319 BitStride: Option<&'a Metadata>,
2320 ) -> &'a Metadata;
2321
2305 pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(2322 pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
2306 Location: &'a DILocation,2323 Location: &'a DILocation,
2307 BD: c_uint,2324 BD: c_uint,
compiler/rustc_codegen_llvm/src/type_of.rs+42-2
...@@ -24,14 +24,54 @@ fn uncached_llvm_type<'a, 'tcx>(...@@ -24,14 +24,54 @@ fn uncached_llvm_type<'a, 'tcx>(
24 let element = layout.scalar_llvm_type_at(cx, element);24 let element = layout.scalar_llvm_type_at(cx, element);
25 return cx.type_vector(element, count);25 return cx.type_vector(element, count);
26 }26 }
27 BackendRepr::SimdScalableVector { ref element, count } => {27 BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => {
28 let element = if element.is_bool() {28 let element = if element.is_bool() {
29 cx.type_i1()29 cx.type_i1()
30 } else {30 } else {
31 layout.scalar_llvm_type_at(cx, *element)31 layout.scalar_llvm_type_at(cx, *element)
32 };32 };
3333
34 return cx.type_scalable_vector(element, count);34 let vector_type = cx.type_scalable_vector(element, count);
35 return match number_of_vectors.0 {
36 1 => vector_type,
37 2 => cx.type_struct(&[vector_type, vector_type], false),
38 3 => cx.type_struct(&[vector_type, vector_type, vector_type], false),
39 4 => cx.type_struct(&[vector_type, vector_type, vector_type, vector_type], false),
40 5 => cx.type_struct(
41 &[vector_type, vector_type, vector_type, vector_type, vector_type],
42 false,
43 ),
44 6 => cx.type_struct(
45 &[vector_type, vector_type, vector_type, vector_type, vector_type, vector_type],
46 false,
47 ),
48 7 => cx.type_struct(
49 &[
50 vector_type,
51 vector_type,
52 vector_type,
53 vector_type,
54 vector_type,
55 vector_type,
56 vector_type,
57 ],
58 false,
59 ),
60 8 => cx.type_struct(
61 &[
62 vector_type,
63 vector_type,
64 vector_type,
65 vector_type,
66 vector_type,
67 vector_type,
68 vector_type,
69 vector_type,
70 ],
71 false,
72 ),
73 _ => bug!("`#[rustc_scalable_vector]` tuple struct with too many fields"),
74 };
35 }75 }
36 BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}76 BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
37 }77 }
compiler/rustc_codegen_ssa/src/mir/debuginfo.rs+2-2
...@@ -438,8 +438,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {...@@ -438,8 +438,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
438 if operand.layout.ty.is_scalable_vector()438 if operand.layout.ty.is_scalable_vector()
439 && bx.sess().target.arch == rustc_target::spec::Arch::AArch64439 && bx.sess().target.arch == rustc_target::spec::Arch::AArch64
440 {440 {
441 let (count, element_ty) =441 let (count, element_ty, _) =
442 operand.layout.ty.scalable_vector_element_count_and_type(bx.tcx());442 operand.layout.ty.scalable_vector_parts(bx.tcx()).unwrap();
443 // i.e. `<vscale x N x i1>` when `N != 16`443 // i.e. `<vscale x N x i1>` when `N != 16`
444 if element_ty.is_bool() && count != 16 {444 if element_ty.is_bool() && count != 16 {
445 return;445 return;
compiler/rustc_codegen_ssa/src/mir/place.rs+6-9
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1use std::ops::Deref as _;
2
1use rustc_abi::{3use rustc_abi::{
2 Align, BackendRepr, FieldIdx, FieldsShape, Size, TagEncoding, VariantIdx, Variants,4 Align, BackendRepr, FieldIdx, FieldsShape, Size, TagEncoding, VariantIdx, Variants,
3};5};
...@@ -109,8 +111,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {...@@ -109,8 +111,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
109 bx: &mut Bx,111 bx: &mut Bx,
110 layout: TyAndLayout<'tcx>,112 layout: TyAndLayout<'tcx>,
111 ) -> Self {113 ) -> Self {
112 if layout.is_runtime_sized() {114 if layout.deref().is_scalable_vector() {
113 Self::alloca_runtime_sized(bx, layout)115 Self::alloca_scalable(bx, layout)
114 } else {116 } else {
115 Self::alloca_size(bx, layout.size, layout)117 Self::alloca_size(bx, layout.size, layout)
116 }118 }
...@@ -151,16 +153,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {...@@ -151,16 +153,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
151 }153 }
152 }154 }
153155
154 fn alloca_runtime_sized<Bx: BuilderMethods<'a, 'tcx, Value = V>>(156 fn alloca_scalable<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
155 bx: &mut Bx,157 bx: &mut Bx,
156 layout: TyAndLayout<'tcx>,158 layout: TyAndLayout<'tcx>,
157 ) -> Self {159 ) -> Self {
158 let (element_count, ty) = layout.ty.scalable_vector_element_count_and_type(bx.tcx());160 PlaceValue::new_sized(bx.alloca_with_ty(layout), layout.align.abi).with_type(layout)
159 PlaceValue::new_sized(
160 bx.scalable_alloca(element_count as u64, layout.align.abi, ty),
161 layout.align.abi,
162 )
163 .with_type(layout)
164 }161 }
165}162}
166163
compiler/rustc_codegen_ssa/src/traits/builder.rs+1-1
...@@ -235,7 +235,7 @@ pub trait BuilderMethods<'a, 'tcx>:...@@ -235,7 +235,7 @@ pub trait BuilderMethods<'a, 'tcx>:
235 fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;235 fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
236236
237 fn alloca(&mut self, size: Size, align: Align) -> Self::Value;237 fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
238 fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value;238 fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value;
239239
240 fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;240 fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
241 fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;241 fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
compiler/rustc_codegen_ssa/src/traits/consts.rs+1
...@@ -20,6 +20,7 @@ pub trait ConstCodegenMethods: BackendTypes {...@@ -20,6 +20,7 @@ pub trait ConstCodegenMethods: BackendTypes {
20 fn const_i8(&self, i: i8) -> Self::Value;20 fn const_i8(&self, i: i8) -> Self::Value;
21 fn const_i16(&self, i: i16) -> Self::Value;21 fn const_i16(&self, i: i16) -> Self::Value;
22 fn const_i32(&self, i: i32) -> Self::Value;22 fn const_i32(&self, i: i32) -> Self::Value;
23 fn const_i64(&self, i: i64) -> Self::Value;
23 fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;24 fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
24 fn const_u8(&self, i: u8) -> Self::Value;25 fn const_u8(&self, i: u8) -> Self::Value;
25 fn const_u32(&self, i: u32) -> Self::Value;26 fn const_u32(&self, i: u32) -> Self::Value;
compiler/rustc_feature/src/unstable.rs+3
...@@ -581,6 +581,9 @@ declare_features! (...@@ -581,6 +581,9 @@ declare_features! (
581 (unstable, marker_trait_attr, "1.30.0", Some(29864)),581 (unstable, marker_trait_attr, "1.30.0", Some(29864)),
582 /// Enable mgca `type const` syntax before expansion.582 /// Enable mgca `type const` syntax before expansion.
583 (incomplete, mgca_type_const_syntax, "1.95.0", Some(132980)),583 (incomplete, mgca_type_const_syntax, "1.95.0", Some(132980)),
584 /// Allows additional const parameter types, such as [u8; 10] or user defined types.
585 /// User defined types must not have fields more private than the type itself.
586 (unstable, min_adt_const_params, "CURRENT_RUSTC_VERSION", Some(154042)),
584 /// Enables the generic const args MVP (only bare paths, not arbitrary computation).587 /// Enables the generic const args MVP (only bare paths, not arbitrary computation).
585 (incomplete, min_generic_const_args, "1.84.0", Some(132980)),588 (incomplete, min_generic_const_args, "1.84.0", Some(132980)),
586 /// A minimal, sound subset of specialization intended to be used by the589 /// A minimal, sound subset of specialization intended to be used by the
compiler/rustc_hir/src/attrs/diagnostic.rs-16
...@@ -19,7 +19,6 @@ pub struct Directive {...@@ -19,7 +19,6 @@ pub struct Directive {
19 pub label: Option<(Span, FormatString)>,19 pub label: Option<(Span, FormatString)>,
20 pub notes: ThinVec<FormatString>,20 pub notes: ThinVec<FormatString>,
21 pub parent_label: Option<FormatString>,21 pub parent_label: Option<FormatString>,
22 pub append_const_msg: Option<AppendConstMessage>,
23}22}
2423
25impl Directive {24impl Directive {
...@@ -63,7 +62,6 @@ impl Directive {...@@ -63,7 +62,6 @@ impl Directive {
63 let mut label = None;62 let mut label = None;
64 let mut notes = Vec::new();63 let mut notes = Vec::new();
65 let mut parent_label = None;64 let mut parent_label = None;
66 let mut append_const_msg = None;
67 info!(65 info!(
68 "evaluate_directive({:?}, trait_ref={:?}, options={:?}, args ={:?})",66 "evaluate_directive({:?}, trait_ref={:?}, options={:?}, args ={:?})",
69 self, trait_name, condition_options, args67 self, trait_name, condition_options, args
...@@ -91,8 +89,6 @@ impl Directive {...@@ -91,8 +89,6 @@ impl Directive {
91 if let Some(ref parent_label_) = command.parent_label {89 if let Some(ref parent_label_) = command.parent_label {
92 parent_label = Some(parent_label_.clone());90 parent_label = Some(parent_label_.clone());
93 }91 }
94
95 append_const_msg = command.append_const_msg;
96 }92 }
9793
98 OnUnimplementedNote {94 OnUnimplementedNote {
...@@ -100,7 +96,6 @@ impl Directive {...@@ -100,7 +96,6 @@ impl Directive {
100 message: message.map(|m| m.1.format(args)),96 message: message.map(|m| m.1.format(args)),
101 notes: notes.into_iter().map(|n| n.format(args)).collect(),97 notes: notes.into_iter().map(|n| n.format(args)).collect(),
102 parent_label: parent_label.map(|e_s| e_s.format(args)),98 parent_label: parent_label.map(|e_s| e_s.format(args)),
103 append_const_msg,
104 }99 }
105 }100 }
106}101}
...@@ -111,17 +106,6 @@ pub struct OnUnimplementedNote {...@@ -111,17 +106,6 @@ pub struct OnUnimplementedNote {
111 pub label: Option<String>,106 pub label: Option<String>,
112 pub notes: Vec<String>,107 pub notes: Vec<String>,
113 pub parent_label: Option<String>,108 pub parent_label: Option<String>,
114 // If none, should fall back to a generic message
115 pub append_const_msg: Option<AppendConstMessage>,
116}
117
118/// Append a message for `[const] Trait` errors.
119#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
120#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
121pub enum AppendConstMessage {
122 #[default]
123 Default,
124 Custom(Symbol, Span),
125}109}
126110
127/// Like [std::fmt::Arguments] this is a string that has been parsed into "pieces",111/// Like [std::fmt::Arguments] this is a string that has been parsed into "pieces",
compiler/rustc_hir_analysis/src/check/intrinsic.rs+7
...@@ -783,6 +783,13 @@ pub(crate) fn check_intrinsic_type(...@@ -783,6 +783,13 @@ pub(crate) fn check_intrinsic_type(
783 sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)),783 sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)),
784 sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)),784 sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)),
785785
786 sym::sve_cast => (2, 0, vec![param(0)], param(1)),
787 sym::sve_tuple_create2 => (2, 0, vec![param(0), param(0)], param(1)),
788 sym::sve_tuple_create3 => (2, 0, vec![param(0), param(0), param(0)], param(1)),
789 sym::sve_tuple_create4 => (2, 0, vec![param(0), param(0), param(0), param(0)], param(1)),
790 sym::sve_tuple_get => (2, 1, vec![param(0)], param(1)),
791 sym::sve_tuple_set => (2, 1, vec![param(0), param(1)], param(0)),
792
786 sym::atomic_cxchg | sym::atomic_cxchgweak => (793 sym::atomic_cxchg | sym::atomic_cxchgweak => (
787 1,794 1,
788 2,795 2,
compiler/rustc_hir_analysis/src/check/wfcheck.rs+1-1
...@@ -842,7 +842,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er...@@ -842,7 +842,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
842 let span = tcx.def_span(param.def_id);842 let span = tcx.def_span(param.def_id);
843 let def_id = param.def_id.expect_local();843 let def_id = param.def_id.expect_local();
844844
845 if tcx.features().adt_const_params() {845 if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() {
846 enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {846 enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
847 wfcx.register_bound(847 wfcx.register_bound(
848 ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),848 ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
compiler/rustc_hir_analysis/src/coherence/builtin.rs+20
...@@ -184,6 +184,26 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E...@@ -184,6 +184,26 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
184 return Ok(());184 return Ok(());
185 }185 }
186186
187 if !tcx.features().adt_const_params() {
188 match *self_type.kind() {
189 ty::Adt(adt, _) if adt.is_struct() => {
190 let struct_vis = tcx.visibility(adt.did());
191 for variant in adt.variants() {
192 for field in &variant.fields {
193 if !field.vis.is_at_least(struct_vis, tcx) {
194 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
195 return Err(tcx
196 .dcx()
197 .emit_err(errors::ConstParamTyFieldVisMismatch { span }));
198 }
199 }
200 }
201 }
202
203 _ => {}
204 }
205 }
206
187 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);207 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
188 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {208 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
189 Ok(()) => Ok(()),209 Ok(()) => Ok(()),
compiler/rustc_hir_analysis/src/errors.rs+8
...@@ -317,6 +317,14 @@ pub(crate) struct ConstParamTyImplOnNonAdt {...@@ -317,6 +317,14 @@ pub(crate) struct ConstParamTyImplOnNonAdt {
317 pub span: Span,317 pub span: Span,
318}318}
319319
320#[derive(Diagnostic)]
321#[diag("the trait `ConstParamTy` may not be implemented for this struct")]
322pub(crate) struct ConstParamTyFieldVisMismatch {
323 #[primary_span]
324 #[label("struct fields are less visible than the struct")]
325 pub span: Span,
326}
327
320#[derive(Diagnostic)]328#[derive(Diagnostic)]
321#[diag("at least one trait is required for an object type", code = E0224)]329#[diag("at least one trait is required for an object type", code = E0224)]
322pub(crate) struct TraitObjectDeclaredWithNoTraits {330pub(crate) struct TraitObjectDeclaredWithNoTraits {
compiler/rustc_hir_typeck/src/method/suggest.rs+7
...@@ -1214,6 +1214,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {...@@ -1214,6 +1214,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1214 unsatisfied_predicates,1214 unsatisfied_predicates,
1215 )1215 )
1216 };1216 };
1217 if let SelfSource::MethodCall(rcvr_expr) = source {
1218 self.err_ctxt().note_field_shadowed_by_private_candidate(
1219 &mut err,
1220 rcvr_expr.hir_id,
1221 self.param_env,
1222 );
1223 }
12171224
1218 self.set_label_for_method_error(1225 self.set_label_for_method_error(
1219 &mut err,1226 &mut err,
compiler/rustc_hir_typeck/src/op.rs+27
...@@ -249,6 +249,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {...@@ -249,6 +249,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
249 rhs_ty_var,249 rhs_ty_var,
250 Some(lhs_expr),250 Some(lhs_expr),
251 |err, ty| {251 |err, ty| {
252 self.err_ctxt().note_field_shadowed_by_private_candidate(
253 err,
254 rhs_expr.hir_id,
255 self.param_env,
256 );
252 if let Op::BinOp(binop) = op257 if let Op::BinOp(binop) = op
253 && binop.node == hir::BinOpKind::Eq258 && binop.node == hir::BinOpKind::Eq
254 {259 {
...@@ -331,6 +336,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {...@@ -331,6 +336,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
331 lhs_expr.span,336 lhs_expr.span,
332 format!("cannot use `{}` on type `{}`", s, lhs_ty_str),337 format!("cannot use `{}` on type `{}`", s, lhs_ty_str),
333 );338 );
339 let err_ctxt = self.err_ctxt();
340 err_ctxt.note_field_shadowed_by_private_candidate(
341 &mut err,
342 lhs_expr.hir_id,
343 self.param_env,
344 );
345 err_ctxt.note_field_shadowed_by_private_candidate(
346 &mut err,
347 rhs_expr.hir_id,
348 self.param_env,
349 );
334 self.note_unmet_impls_on_type(&mut err, &errors, false);350 self.note_unmet_impls_on_type(&mut err, &errors, false);
335 (err, None)351 (err, None)
336 }352 }
...@@ -391,6 +407,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {...@@ -391,6 +407,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
391 err.span_label(lhs_expr.span, lhs_ty_str.clone());407 err.span_label(lhs_expr.span, lhs_ty_str.clone());
392 err.span_label(rhs_expr.span, rhs_ty_str);408 err.span_label(rhs_expr.span, rhs_ty_str);
393 }409 }
410 let err_ctxt = self.err_ctxt();
411 err_ctxt.note_field_shadowed_by_private_candidate(
412 &mut err,
413 lhs_expr.hir_id,
414 self.param_env,
415 );
416 err_ctxt.note_field_shadowed_by_private_candidate(
417 &mut err,
418 rhs_expr.hir_id,
419 self.param_env,
420 );
394 let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);421 let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
395 self.note_unmet_impls_on_type(&mut err, &errors, suggest_derive);422 self.note_unmet_impls_on_type(&mut err, &errors, suggest_derive);
396 (err, output_def_id)423 (err, output_def_id)
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp+35-1
...@@ -70,6 +70,10 @@ using namespace llvm::object;...@@ -70,6 +70,10 @@ using namespace llvm::object;
70// This opcode is an LLVM detail that could hypothetically change (?), so70// This opcode is an LLVM detail that could hypothetically change (?), so
71// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.71// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.
72static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000);72static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000);
73static_assert(dwarf::DW_OP_constu == 0x10);
74static_assert(dwarf::DW_OP_minus == 0x1c);
75static_assert(dwarf::DW_OP_mul == 0x1e);
76static_assert(dwarf::DW_OP_bregx == 0x92);
73static_assert(dwarf::DW_OP_stack_value == 0x9f);77static_assert(dwarf::DW_OP_stack_value == 0x9f);
7478
75static LLVM_THREAD_LOCAL char *LastError;79static LLVM_THREAD_LOCAL char *LastError;
...@@ -731,7 +735,7 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,...@@ -731,7 +735,7 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
731}735}
732736
733template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {737template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
734 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);738 return (DIT *)(Ref ? unwrap<Metadata>(Ref) : nullptr);
735}739}
736740
737#define DIDescriptor DIScope741#define DIDescriptor DIScope
...@@ -1207,6 +1211,36 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays(...@@ -1207,6 +1211,36 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays(
1207 DINodeArray(unwrap<MDTuple>(Params)));1211 DINodeArray(unwrap<MDTuple>(Params)));
1208}1212}
12091213
1214// LLVM's C FFI bindings don't expose the overload of `GetOrCreateSubrange`
1215// which takes a metadata node as the upper bound.
1216extern "C" LLVMMetadataRef
1217LLVMRustDIGetOrCreateSubrange(LLVMDIBuilderRef Builder,
1218 LLVMMetadataRef CountNode, LLVMMetadataRef LB,
1219 LLVMMetadataRef UB, LLVMMetadataRef Stride) {
1220 return wrap(unwrap(Builder)->getOrCreateSubrange(
1221 unwrapDI<Metadata>(CountNode), unwrapDI<Metadata>(LB),
1222 unwrapDI<Metadata>(UB), unwrapDI<Metadata>(Stride)));
1223}
1224
1225// LLVM's CI FFI bindings don't expose the `BitStride` parameter of
1226// `createVectorType`.
1227extern "C" LLVMMetadataRef
1228LLVMRustDICreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size,
1229 uint32_t AlignInBits, LLVMMetadataRef Type,
1230 LLVMMetadataRef Subscripts,
1231 LLVMMetadataRef BitStride) {
1232#if LLVM_VERSION_GE(22, 0)
1233 return wrap(unwrap(Builder)->createVectorType(
1234 Size, AlignInBits, unwrapDI<DIType>(Type),
1235 DINodeArray(unwrapDI<MDTuple>(Subscripts)),
1236 unwrapDI<Metadata>(BitStride)));
1237#else
1238 return wrap(unwrap(Builder)->createVectorType(
1239 Size, AlignInBits, unwrapDI<DIType>(Type),
1240 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
1241#endif
1242}
1243
1210extern "C" LLVMMetadataRef1244extern "C" LLVMMetadataRef
1211LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,1245LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
1212 unsigned BD) {1246 unsigned BD) {
compiler/rustc_middle/src/ich/impls_syntax.rs+1-51
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4use rustc_ast as ast;4use rustc_ast as ast;
5use rustc_data_structures::stable_hasher::{HashStable, StableHasher};5use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6use rustc_hir as hir;6use rustc_hir as hir;
7use rustc_span::{SourceFile, Symbol, sym};7use rustc_span::{Symbol, sym};
8use smallvec::SmallVec;8use smallvec::SmallVec;
99
10use super::StableHashingContext;10use super::StableHashingContext;
...@@ -54,56 +54,6 @@ fn is_ignored_attr(name: Symbol) -> bool {...@@ -54,56 +54,6 @@ fn is_ignored_attr(name: Symbol) -> bool {
54 IGNORED_ATTRIBUTES.contains(&name)54 IGNORED_ATTRIBUTES.contains(&name)
55}55}
5656
57impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
58 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
59 let SourceFile {
60 name: _, // We hash the smaller stable_id instead of this
61 stable_id,
62 cnum,
63 // Do not hash the source as it is not encoded
64 src: _,
65 ref src_hash,
66 // Already includes src_hash, this is redundant
67 checksum_hash: _,
68 external_src: _,
69 start_pos: _,
70 normalized_source_len: _,
71 unnormalized_source_len: _,
72 lines: _,
73 ref multibyte_chars,
74 ref normalized_pos,
75 } = *self;
76
77 stable_id.hash_stable(hcx, hasher);
78
79 src_hash.hash_stable(hcx, hasher);
80
81 {
82 // We are always in `Lines` form by the time we reach here.
83 assert!(self.lines.read().is_lines());
84 let lines = self.lines();
85 // We only hash the relative position within this source_file
86 lines.len().hash_stable(hcx, hasher);
87 for &line in lines.iter() {
88 line.hash_stable(hcx, hasher);
89 }
90 }
91
92 // We only hash the relative position within this source_file
93 multibyte_chars.len().hash_stable(hcx, hasher);
94 for &char_pos in multibyte_chars.iter() {
95 char_pos.hash_stable(hcx, hasher);
96 }
97
98 normalized_pos.len().hash_stable(hcx, hasher);
99 for &char_pos in normalized_pos.iter() {
100 char_pos.hash_stable(hcx, hasher);
101 }
102
103 cnum.hash_stable(hcx, hasher);
104 }
105}
106
107impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {57impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
108 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {58 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
109 // Unfortunately we cannot exhaustively list fields here, since the59 // Unfortunately we cannot exhaustively list fields here, since the
compiler/rustc_middle/src/ty/sty.rs+17-7
...@@ -7,7 +7,7 @@ use std::debug_assert_matches;...@@ -7,7 +7,7 @@ use std::debug_assert_matches;
7use std::ops::{ControlFlow, Range};7use std::ops::{ControlFlow, Range};
88
9use hir::def::{CtorKind, DefKind};9use hir::def::{CtorKind, DefKind};
10use rustc_abi::{FIRST_VARIANT, FieldIdx, ScalableElt, VariantIdx};10use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx};
11use rustc_errors::{ErrorGuaranteed, MultiSpan};11use rustc_errors::{ErrorGuaranteed, MultiSpan};
12use rustc_hir as hir;12use rustc_hir as hir;
13use rustc_hir::LangItem;13use rustc_hir::LangItem;
...@@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> {...@@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> {
1261 }1261 }
1262 }1262 }
12631263
1264 pub fn scalable_vector_element_count_and_type(self, tcx: TyCtxt<'tcx>) -> (u16, Ty<'tcx>) {1264 pub fn scalable_vector_parts(
1265 self,
1266 tcx: TyCtxt<'tcx>,
1267 ) -> Option<(u16, Ty<'tcx>, NumScalableVectors)> {
1265 let Adt(def, args) = self.kind() else {1268 let Adt(def, args) = self.kind() else {
1266 bug!("`scalable_vector_size_and_type` called on invalid type")1269 return None;
1267 };1270 };
1268 let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else {1271 let (num_vectors, vec_def) = match def.repr().scalable? {
1269 bug!("`scalable_vector_size_and_type` called on non-scalable vector type");1272 ScalableElt::ElementCount(_) => (NumScalableVectors::for_non_tuple(), *def),
1273 ScalableElt::Container => (
1274 NumScalableVectors::from_field_count(def.non_enum_variant().fields.len())?,
1275 def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, args).ty_adt_def()?,
1276 ),
1270 };1277 };
1271 let variant = def.non_enum_variant();1278 let Some(ScalableElt::ElementCount(element_count)) = vec_def.repr().scalable else {
1279 return None;
1280 };
1281 let variant = vec_def.non_enum_variant();
1272 assert_eq!(variant.fields.len(), 1);1282 assert_eq!(variant.fields.len(), 1);
1273 let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);1283 let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
1274 (element_count, field_ty)1284 Some((element_count, field_ty, num_vectors))
1275 }1285 }
12761286
1277 pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {1287 pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
compiler/rustc_public/src/abi.rs+5
...@@ -232,6 +232,10 @@ pub enum TagEncoding {...@@ -232,6 +232,10 @@ pub enum TagEncoding {
232 },232 },
233}233}
234234
235/// How many scalable vectors are in a `ValueAbi::ScalableVector`?
236#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
237pub struct NumScalableVectors(pub(crate) u8);
238
235/// Describes how values of the type are passed by target ABIs,239/// Describes how values of the type are passed by target ABIs,
236/// in terms of categories of C types there are ABI rules for.240/// in terms of categories of C types there are ABI rules for.
237#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]241#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
...@@ -245,6 +249,7 @@ pub enum ValueAbi {...@@ -245,6 +249,7 @@ pub enum ValueAbi {
245 ScalableVector {249 ScalableVector {
246 element: Scalar,250 element: Scalar,
247 count: u64,251 count: u64,
252 number_of_vectors: NumScalableVectors,
248 },253 },
249 Aggregate {254 Aggregate {
250 /// If true, the size is exact, otherwise it's only a lower bound.255 /// If true, the size is exact, otherwise it's only a lower bound.
compiler/rustc_public/src/unstable/convert/stable/abi.rs+21-4
...@@ -10,8 +10,9 @@ use rustc_target::callconv;...@@ -10,8 +10,9 @@ use rustc_target::callconv;
1010
11use crate::abi::{11use crate::abi::{
12 AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,12 AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
13 IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,13 IntegerType, Layout, LayoutShape, NumScalableVectors, PassMode, Primitive, ReprFlags,
14 TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape, WrappingRange,14 ReprOptions, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape,
15 WrappingRange,
15};16};
16use crate::compiler_interface::BridgeTys;17use crate::compiler_interface::BridgeTys;
17use crate::target::MachineSize as Size;18use crate::target::MachineSize as Size;
...@@ -249,6 +250,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {...@@ -249,6 +250,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
249 }250 }
250}251}
251252
253impl<'tcx> Stable<'tcx> for rustc_abi::NumScalableVectors {
254 type T = NumScalableVectors;
255
256 fn stable<'cx>(
257 &self,
258 _tables: &mut Tables<'cx, BridgeTys>,
259 _cx: &CompilerCtxt<'cx, BridgeTys>,
260 ) -> Self::T {
261 NumScalableVectors(self.0)
262 }
263}
264
252impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {265impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
253 type T = ValueAbi;266 type T = ValueAbi;
254267
...@@ -265,8 +278,12 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {...@@ -265,8 +278,12 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
265 rustc_abi::BackendRepr::SimdVector { element, count } => {278 rustc_abi::BackendRepr::SimdVector { element, count } => {
266 ValueAbi::Vector { element: element.stable(tables, cx), count }279 ValueAbi::Vector { element: element.stable(tables, cx), count }
267 }280 }
268 rustc_abi::BackendRepr::SimdScalableVector { element, count } => {281 rustc_abi::BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
269 ValueAbi::ScalableVector { element: element.stable(tables, cx), count }282 ValueAbi::ScalableVector {
283 element: element.stable(tables, cx),
284 count,
285 number_of_vectors: number_of_vectors.stable(tables, cx),
286 }
270 }287 }
271 rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },288 rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
272 }289 }
compiler/rustc_resolve/src/late/diagnostics.rs+2-1
...@@ -1773,7 +1773,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {...@@ -1773,7 +1773,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
1773 // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the1773 // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
1774 // benefits of including them here outweighs the small number of false positives.1774 // benefits of including them here outweighs the small number of false positives.
1775 Some(Res::Def(DefKind::Struct | DefKind::Enum, _))1775 Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
1776 if self.r.tcx.features().adt_const_params() =>1776 if self.r.tcx.features().adt_const_params()
1777 || self.r.tcx.features().min_adt_const_params() =>
1777 {1778 {
1778 Applicability::MaybeIncorrect1779 Applicability::MaybeIncorrect
1779 }1780 }
compiler/rustc_span/src/symbol.rs+7-1
...@@ -399,7 +399,6 @@ symbols! {...@@ -399,7 +399,6 @@ symbols! {
399 anon_assoc,399 anon_assoc,
400 anonymous_lifetime_in_impl_trait,400 anonymous_lifetime_in_impl_trait,
401 any,401 any,
402 append_const_msg,
403 apx_target_feature,402 apx_target_feature,
404 arbitrary_enum_discriminant,403 arbitrary_enum_discriminant,
405 arbitrary_self_types,404 arbitrary_self_types,
...@@ -1245,6 +1244,7 @@ symbols! {...@@ -1245,6 +1244,7 @@ symbols! {
1245 meta_sized,1244 meta_sized,
1246 metadata_type,1245 metadata_type,
1247 mgca_type_const_syntax,1246 mgca_type_const_syntax,
1247 min_adt_const_params,
1248 min_const_fn,1248 min_const_fn,
1249 min_const_generics,1249 min_const_generics,
1250 min_const_unsafe_fn,1250 min_const_unsafe_fn,
...@@ -1979,6 +1979,12 @@ symbols! {...@@ -1979,6 +1979,12 @@ symbols! {
1979 suggestion,1979 suggestion,
1980 super_let,1980 super_let,
1981 supertrait_item_shadowing,1981 supertrait_item_shadowing,
1982 sve_cast,
1983 sve_tuple_create2,
1984 sve_tuple_create3,
1985 sve_tuple_create4,
1986 sve_tuple_get,
1987 sve_tuple_set,
1982 sym,1988 sym,
1983 sync,1989 sync,
1984 synthetic,1990 synthetic,
compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs+4
...@@ -1528,6 +1528,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -1528,6 +1528,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1528 label_or_note(span, terr.to_string(self.tcx));1528 label_or_note(span, terr.to_string(self.tcx));
1529 }1529 }
15301530
1531 if let Some(param_env) = param_env {
1532 self.note_field_shadowed_by_private_candidate_in_cause(diag, cause, param_env);
1533 }
1534
1531 if self.check_and_note_conflicting_crates(diag, terr) {1535 if self.check_and_note_conflicting_crates(diag, terr) {
1532 return;1536 return;
1533 }1537 }
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs+28-54
...@@ -14,7 +14,7 @@ use rustc_errors::{...@@ -14,7 +14,7 @@ use rustc_errors::{
14 Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg,14 Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg,
15 pluralize, struct_span_code_err,15 pluralize, struct_span_code_err,
16};16};
17use rustc_hir::attrs::diagnostic::{AppendConstMessage, OnUnimplementedNote};17use rustc_hir::attrs::diagnostic::OnUnimplementedNote;
18use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};18use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
19use rustc_hir::intravisit::Visitor;19use rustc_hir::intravisit::Visitor;
20use rustc_hir::{self as hir, LangItem, Node, find_attr};20use rustc_hir::{self as hir, LangItem, Node, find_attr};
...@@ -193,10 +193,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -193,10 +193,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
193 label,193 label,
194 notes,194 notes,
195 parent_label,195 parent_label,
196 append_const_msg,
197 } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);196 } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);
198197
199 let have_alt_message = message.is_some() || label.is_some();198 let have_alt_message = message.is_some() || label.is_some();
199
200 let message = message.unwrap_or_else(|| self.get_standard_error_message(
201 main_trait_predicate,
202 None,
203 post_message,
204 &mut long_ty_file,
205 ));
200 let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id());206 let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id());
201 let is_question_mark = matches!(207 let is_question_mark = matches!(
202 root_obligation.cause.code().peel_derives(),208 root_obligation.cause.code().peel_derives(),
...@@ -210,16 +216,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -210,16 +216,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
210 let question_mark_message = "the question mark operation (`?`) implicitly \216 let question_mark_message = "the question mark operation (`?`) implicitly \
211 performs a conversion on the error value \217 performs a conversion on the error value \
212 using the `From` trait";218 using the `From` trait";
213 let (message, notes, append_const_msg) = if is_try_conversion {219 let (message, notes) = if is_try_conversion {
214 let ty = self.tcx.short_string(220 let ty = self.tcx.short_string(
215 main_trait_predicate.skip_binder().self_ty(),221 main_trait_predicate.skip_binder().self_ty(),
216 &mut long_ty_file,222 &mut long_ty_file,
217 );223 );
218 // We have a `-> Result<_, E1>` and `gives_E2()?`.224 // We have a `-> Result<_, E1>` and `gives_E2()?`.
219 (225 (
220 Some(format!("`?` couldn't convert the error to `{ty}`")),226 format!("`?` couldn't convert the error to `{ty}`"),
221 vec![question_mark_message.to_owned()],227 vec![question_mark_message.to_owned()],
222 Some(AppendConstMessage::Default),
223 )228 )
224 } else if is_question_mark {229 } else if is_question_mark {
225 let main_trait_predicate =230 let main_trait_predicate =
...@@ -228,26 +233,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -228,26 +233,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
228 // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when233 // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when
229 // `E: Error` isn't met.234 // `E: Error` isn't met.
230 (235 (
231 Some(format!(236 format!(
232 "`?` couldn't convert the error: `{main_trait_predicate}` is \237 "`?` couldn't convert the error: `{main_trait_predicate}` is \
233 not satisfied",238 not satisfied",
234 )),239 ),
235 vec![question_mark_message.to_owned()],240 vec![question_mark_message.to_owned()],
236 Some(AppendConstMessage::Default),
237 )241 )
238 } else {242 } else {
239 (message, notes, append_const_msg)243 (message, notes)
240 };244 };
241245
242 let default_err_msg = || self.get_standard_error_message(
243 main_trait_predicate,
244 message,
245 None,
246 append_const_msg,
247 post_message,
248 &mut long_ty_file,
249 );
250
251 let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(246 let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(
252 main_trait_predicate.def_id(),247 main_trait_predicate.def_id(),
253 LangItem::TransmuteTrait,248 LangItem::TransmuteTrait,
...@@ -271,7 +266,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -271,7 +266,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
271 );266 );
272 }267 }
273 GetSafeTransmuteErrorAndReason::Default => {268 GetSafeTransmuteErrorAndReason::Default => {
274 (default_err_msg(), None)269 (message, None)
275 }270 }
276 GetSafeTransmuteErrorAndReason::Error {271 GetSafeTransmuteErrorAndReason::Error {
277 err_msg,272 err_msg,
...@@ -279,7 +274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -279,7 +274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
279 } => (err_msg, safe_transmute_explanation),274 } => (err_msg, safe_transmute_explanation),
280 }275 }
281 } else {276 } else {
282 (default_err_msg(), None)277 (message, None)
283 };278 };
284279
285 let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);280 let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
...@@ -393,7 +388,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -393,7 +388,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
393 if let Some(s) = label {388 if let Some(s) = label {
394 // If it has a custom `#[rustc_on_unimplemented]`389 // If it has a custom `#[rustc_on_unimplemented]`
395 // error message, let's display it as the label!390 // error message, let's display it as the label!
396 err.span_label(span, s.as_str().to_owned());391 err.span_label(span, s);
397 if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))392 if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))
398 // When the self type is a type param We don't need to "the trait393 // When the self type is a type param We don't need to "the trait
399 // `std::marker::Sized` is not implemented for `T`" as we will point394 // `std::marker::Sized` is not implemented for `T`" as we will point
...@@ -559,6 +554,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -559,6 +554,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
559 );554 );
560 }555 }
561556
557 self.note_field_shadowed_by_private_candidate_in_cause(
558 &mut err,
559 &obligation.cause,
560 obligation.param_env,
561 );
562 self.try_to_add_help_message(562 self.try_to_add_help_message(
563 &root_obligation,563 &root_obligation,
564 &obligation,564 &obligation,
...@@ -857,9 +857,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -857,9 +857,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
857857
858 let err_msg = self.get_standard_error_message(858 let err_msg = self.get_standard_error_message(
859 trait_ref,859 trait_ref,
860 None,
861 Some(predicate.constness()),860 Some(predicate.constness()),
862 None,
863 String::new(),861 String::new(),
864 &mut file,862 &mut file,
865 );863 );
...@@ -919,7 +917,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -919,7 +917,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
919 label,917 label,
920 notes,918 notes,
921 parent_label,919 parent_label,
922 append_const_msg: _,
923 } = note;920 } = note;
924921
925 if let Some(message) = message {922 if let Some(message) = message {
...@@ -2836,40 +2833,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {...@@ -2836,40 +2833,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2836 fn get_standard_error_message(2833 fn get_standard_error_message(
2837 &self,2834 &self,
2838 trait_predicate: ty::PolyTraitPredicate<'tcx>,2835 trait_predicate: ty::PolyTraitPredicate<'tcx>,
2839 message: Option<String>,
2840 predicate_constness: Option<ty::BoundConstness>,2836 predicate_constness: Option<ty::BoundConstness>,
2841 append_const_msg: Option<AppendConstMessage>,
2842 post_message: String,2837 post_message: String,
2843 long_ty_path: &mut Option<PathBuf>,2838 long_ty_path: &mut Option<PathBuf>,
2844 ) -> String {2839 ) -> String {
2845 message2840 format!(
2846 .and_then(|cannot_do_this| {2841 "the trait bound `{}` is not satisfied{post_message}",
2847 match (predicate_constness, append_const_msg) {2842 self.tcx.short_string(
2848 // do nothing if predicate is not const2843 trait_predicate.print_with_bound_constness(predicate_constness),
2849 (None, _) => Some(cannot_do_this),2844 long_ty_path,
2850 // suggested using default post message2845 ),
2851 (2846 )
2852 Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
2853 Some(AppendConstMessage::Default),
2854 ) => Some(format!("{cannot_do_this} in const contexts")),
2855 // overridden post message
2856 (
2857 Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
2858 Some(AppendConstMessage::Custom(custom_msg, _)),
2859 ) => Some(format!("{cannot_do_this}{custom_msg}")),
2860 // fallback to generic message
2861 (Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe), None) => None,
2862 }
2863 })
2864 .unwrap_or_else(|| {
2865 format!(
2866 "the trait bound `{}` is not satisfied{post_message}",
2867 self.tcx.short_string(
2868 trait_predicate.print_with_bound_constness(predicate_constness),
2869 long_ty_path,
2870 ),
2871 )
2872 })
2873 }2847 }
28742848
2875 fn select_transmute_obligation_for_reporting(2849 fn select_transmute_obligation_for_reporting(
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs+210-1
...@@ -22,8 +22,10 @@ use rustc_hir::{...@@ -22,8 +22,10 @@ use rustc_hir::{
22 expr_needs_parens,22 expr_needs_parens,
23};23};
24use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};24use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
25use rustc_infer::traits::ImplSource;
25use rustc_middle::middle::privacy::Level;26use rustc_middle::middle::privacy::Level;
26use rustc_middle::traits::IsConstable;27use rustc_middle::traits::IsConstable;
28use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
27use rustc_middle::ty::error::TypeError;29use rustc_middle::ty::error::TypeError;
28use rustc_middle::ty::print::{30use rustc_middle::ty::print::{
29 PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,31 PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
...@@ -49,7 +51,7 @@ use crate::error_reporting::TypeErrCtxt;...@@ -49,7 +51,7 @@ use crate::error_reporting::TypeErrCtxt;
49use crate::errors;51use crate::errors;
50use crate::infer::InferCtxtExt as _;52use crate::infer::InferCtxtExt as _;
51use crate::traits::query::evaluate_obligation::InferCtxtExt as _;53use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
52use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};54use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt, SelectionContext};
5355
54#[derive(Debug)]56#[derive(Debug)]
55pub enum CoroutineInteriorOrUpvar {57pub enum CoroutineInteriorOrUpvar {
...@@ -242,6 +244,213 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(...@@ -242,6 +244,213 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
242}244}
243245
244impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {246impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
247 pub fn note_field_shadowed_by_private_candidate_in_cause(
248 &self,
249 err: &mut Diag<'_>,
250 cause: &ObligationCause<'tcx>,
251 param_env: ty::ParamEnv<'tcx>,
252 ) {
253 let mut hir_ids = FxHashSet::default();
254 // Walk the parent chain so we can recover
255 // the source expression from whichever layer carries them.
256 let mut next_code = Some(cause.code());
257 while let Some(cause_code) = next_code {
258 match cause_code {
259 ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
260 hir_ids.insert(*lhs_hir_id);
261 hir_ids.insert(*rhs_hir_id);
262 }
263 ObligationCauseCode::FunctionArg { arg_hir_id, .. }
264 | ObligationCauseCode::ReturnValue(arg_hir_id)
265 | ObligationCauseCode::AwaitableExpr(arg_hir_id)
266 | ObligationCauseCode::BlockTailExpression(arg_hir_id, _)
267 | ObligationCauseCode::UnOp { hir_id: arg_hir_id } => {
268 hir_ids.insert(*arg_hir_id);
269 }
270 ObligationCauseCode::OpaqueReturnType(Some((_, hir_id))) => {
271 hir_ids.insert(*hir_id);
272 }
273 _ => {}
274 }
275 next_code = cause_code.parent();
276 }
277
278 if !cause.span.is_dummy()
279 && let Some(body) = self.tcx.hir_maybe_body_owned_by(cause.body_id)
280 {
281 let mut expr_finder = FindExprBySpan::new(cause.span, self.tcx);
282 expr_finder.visit_body(body);
283 if let Some(expr) = expr_finder.result {
284 hir_ids.insert(expr.hir_id);
285 }
286 }
287
288 // we will sort immediately by source order before emitting any diagnostics
289 #[allow(rustc::potential_query_instability)]
290 let mut hir_ids: Vec<_> = hir_ids.into_iter().collect();
291 let source_map = self.tcx.sess.source_map();
292 hir_ids.sort_by_cached_key(|hir_id| {
293 let span = self.tcx.hir_span(*hir_id);
294 let lo = source_map.lookup_byte_offset(span.lo());
295 let hi = source_map.lookup_byte_offset(span.hi());
296 (lo.sf.name.prefer_remapped_unconditionally().to_string(), lo.pos.0, hi.pos.0)
297 });
298
299 for hir_id in hir_ids {
300 self.note_field_shadowed_by_private_candidate(err, hir_id, param_env);
301 }
302 }
303
304 pub fn note_field_shadowed_by_private_candidate(
305 &self,
306 err: &mut Diag<'_>,
307 hir_id: hir::HirId,
308 param_env: ty::ParamEnv<'tcx>,
309 ) {
310 let Some(typeck_results) = &self.typeck_results else {
311 return;
312 };
313 let Node::Expr(expr) = self.tcx.hir_node(hir_id) else {
314 return;
315 };
316 let hir::ExprKind::Field(base_expr, field_ident) = expr.kind else {
317 return;
318 };
319
320 let Some(base_ty) = typeck_results.expr_ty_opt(base_expr) else {
321 return;
322 };
323 let base_ty = self.resolve_vars_if_possible(base_ty);
324 if base_ty.references_error() {
325 return;
326 }
327
328 let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(typeck_results.hir_owner.def_id);
329 let mut private_candidate: Option<(Ty<'tcx>, Ty<'tcx>, Span)> = None;
330
331 for (deref_base_ty, _) in (self.autoderef_steps)(base_ty) {
332 let ty::Adt(base_def, args) = deref_base_ty.kind() else {
333 continue;
334 };
335
336 if base_def.is_enum() {
337 continue;
338 }
339
340 let (adjusted_ident, def_scope) =
341 self.tcx.adjust_ident_and_get_scope(field_ident, base_def.did(), fn_body_hir_id);
342
343 let Some((_, field_def)) =
344 base_def.non_enum_variant().fields.iter_enumerated().find(|(_, field)| {
345 field.ident(self.tcx).normalize_to_macros_2_0() == adjusted_ident
346 })
347 else {
348 continue;
349 };
350 let field_span = self
351 .tcx
352 .def_ident_span(field_def.did)
353 .unwrap_or_else(|| self.tcx.def_span(field_def.did));
354
355 if field_def.vis.is_accessible_from(def_scope, self.tcx) {
356 let accessible_field_ty = field_def.ty(self.tcx, args);
357 if let Some((private_base_ty, private_field_ty, private_field_span)) =
358 private_candidate
359 && !self.can_eq(param_env, private_field_ty, accessible_field_ty)
360 {
361 let private_struct_span = match private_base_ty.kind() {
362 ty::Adt(private_base_def, _) => self
363 .tcx
364 .def_ident_span(private_base_def.did())
365 .unwrap_or_else(|| self.tcx.def_span(private_base_def.did())),
366 _ => DUMMY_SP,
367 };
368 let accessible_struct_span = self
369 .tcx
370 .def_ident_span(base_def.did())
371 .unwrap_or_else(|| self.tcx.def_span(base_def.did()));
372 let deref_impl_span = (typeck_results
373 .expr_adjustments(base_expr)
374 .iter()
375 .filter(|adj| {
376 matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))
377 })
378 .count()
379 == 1)
380 .then(|| {
381 self.probe(|_| {
382 let deref_trait_did =
383 self.tcx.require_lang_item(LangItem::Deref, DUMMY_SP);
384 let trait_ref =
385 ty::TraitRef::new(self.tcx, deref_trait_did, [private_base_ty]);
386 let obligation: Obligation<'tcx, ty::Predicate<'tcx>> =
387 Obligation::new(
388 self.tcx,
389 ObligationCause::dummy(),
390 param_env,
391 trait_ref,
392 );
393 let Ok(Some(ImplSource::UserDefined(impl_data))) =
394 SelectionContext::new(self)
395 .select(&obligation.with(self.tcx, trait_ref))
396 else {
397 return None;
398 };
399 Some(self.tcx.def_span(impl_data.impl_def_id))
400 })
401 })
402 .flatten();
403
404 let mut note_spans: MultiSpan = private_struct_span.into();
405 if private_struct_span != DUMMY_SP {
406 note_spans.push_span_label(private_struct_span, "in this struct");
407 }
408 if private_field_span != DUMMY_SP {
409 note_spans.push_span_label(
410 private_field_span,
411 "if this field wasn't private, it would be accessible",
412 );
413 }
414 if accessible_struct_span != DUMMY_SP {
415 note_spans.push_span_label(
416 accessible_struct_span,
417 "this struct is accessible through auto-deref",
418 );
419 }
420 if field_span != DUMMY_SP {
421 note_spans
422 .push_span_label(field_span, "this is the field that was accessed");
423 }
424 if let Some(deref_impl_span) = deref_impl_span
425 && deref_impl_span != DUMMY_SP
426 {
427 note_spans.push_span_label(
428 deref_impl_span,
429 "the field was accessed through this `Deref`",
430 );
431 }
432
433 err.span_note(
434 note_spans,
435 format!(
436 "there is a field `{field_ident}` on `{private_base_ty}` with type `{private_field_ty}` but it is private; `{field_ident}` from `{deref_base_ty}` was accessed through auto-deref instead"
437 ),
438 );
439 }
440
441 // we finally get to the accessible field,
442 // so we can return early without checking the rest of the autoderef candidates
443 return;
444 }
445
446 private_candidate.get_or_insert((
447 deref_base_ty,
448 field_def.ty(self.tcx, args),
449 field_span,
450 ));
451 }
452 }
453
245 pub fn suggest_restricting_param_bound(454 pub fn suggest_restricting_param_bound(
246 &self,455 &self,
247 err: &mut Diag<'_>,456 err: &mut Diag<'_>,
compiler/rustc_ty_utils/src/layout.rs+14-18
...@@ -4,8 +4,8 @@ use rustc_abi::Integer::{I8, I32};...@@ -4,8 +4,8 @@ use rustc_abi::Integer::{I8, I32};
4use rustc_abi::Primitive::{self, Float, Int, Pointer};4use rustc_abi::Primitive::{self, Float, Int, Pointer};
5use rustc_abi::{5use rustc_abi::{
6 AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout,6 AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout,
7 LayoutCalculatorError, LayoutData, Niche, ReprOptions, ScalableElt, Scalar, Size, StructKind,7 LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding,
8 TagEncoding, VariantIdx, Variants, WrappingRange,8 VariantIdx, Variants, WrappingRange,
9};9};
10use rustc_hashes::Hash64;10use rustc_hashes::Hash64;
11use rustc_hir as hir;11use rustc_hir as hir;
...@@ -572,30 +572,26 @@ fn layout_of_uncached<'tcx>(...@@ -572,30 +572,26 @@ fn layout_of_uncached<'tcx>(
572 // ```rust (ignore, example)572 // ```rust (ignore, example)
573 // #[rustc_scalable_vector(3)]573 // #[rustc_scalable_vector(3)]
574 // struct svuint32_t(u32);574 // struct svuint32_t(u32);
575 //
576 // #[rustc_scalable_vector]
577 // struct svuint32x2_t(svuint32_t, svuint32_t);
575 // ```578 // ```
576 ty::Adt(def, args)579 ty::Adt(def, _args) if def.repr().scalable() => {
577 if matches!(def.repr().scalable, Some(ScalableElt::ElementCount(..))) =>580 let Some((element_count, element_ty, number_of_vectors)) =
578 {581 ty.scalable_vector_parts(tcx)
579 let Some(element_ty) = def
580 .is_struct()
581 .then(|| &def.variant(FIRST_VARIANT).fields)
582 .filter(|fields| fields.len() == 1)
583 .map(|fields| fields[FieldIdx::ZERO].ty(tcx, args))
584 else {582 else {
585 let guar = tcx583 let guar = tcx
586 .dcx()584 .dcx()
587 .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");585 .delayed_bug("`#[rustc_scalable_vector]` was applied to an invalid type");
588 return Err(error(cx, LayoutError::ReferencesError(guar)));
589 };
590 let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else {
591 let guar = tcx
592 .dcx()
593 .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");
594 return Err(error(cx, LayoutError::ReferencesError(guar)));586 return Err(error(cx, LayoutError::ReferencesError(guar)));
595 };587 };
596588
597 let element_layout = cx.layout_of(element_ty)?;589 let element_layout = cx.layout_of(element_ty)?;
598 map_layout(cx.calc.scalable_vector_type(element_layout, element_count as u64))?590 map_layout(cx.calc.scalable_vector_type(
591 element_layout,
592 element_count as u64,
593 number_of_vectors,
594 ))?
599 }595 }
600596
601 // SIMD vector types.597 // SIMD vector types.
library/core/src/cmp.rs+4-6
...@@ -241,10 +241,9 @@ use crate::ops::ControlFlow;...@@ -241,10 +241,9 @@ use crate::ops::ControlFlow;
241#[stable(feature = "rust1", since = "1.0.0")]241#[stable(feature = "rust1", since = "1.0.0")]
242#[doc(alias = "==")]242#[doc(alias = "==")]
243#[doc(alias = "!=")]243#[doc(alias = "!=")]
244#[rustc_on_unimplemented(244#[diagnostic::on_unimplemented(
245 message = "can't compare `{Self}` with `{Rhs}`",245 message = "can't compare `{Self}` with `{Rhs}`",
246 label = "no implementation for `{Self} == {Rhs}`",246 label = "no implementation for `{Self} == {Rhs}`"
247 append_const_msg
248)]247)]
249#[rustc_diagnostic_item = "PartialEq"]248#[rustc_diagnostic_item = "PartialEq"]
250#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]249#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
...@@ -1356,10 +1355,9 @@ pub macro Ord($item:item) {...@@ -1356,10 +1355,9 @@ pub macro Ord($item:item) {
1356#[doc(alias = "<")]1355#[doc(alias = "<")]
1357#[doc(alias = "<=")]1356#[doc(alias = "<=")]
1358#[doc(alias = ">=")]1357#[doc(alias = ">=")]
1359#[rustc_on_unimplemented(1358#[diagnostic::on_unimplemented(
1360 message = "can't compare `{Self}` with `{Rhs}`",1359 message = "can't compare `{Self}` with `{Rhs}`",
1361 label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",1360 label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
1362 append_const_msg
1363)]1361)]
1364#[rustc_diagnostic_item = "PartialOrd"]1362#[rustc_diagnostic_item = "PartialOrd"]
1365#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this1363#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
library/core/src/intrinsics/simd.rs deleted-843
...@@ -1,843 +0,0 @@
1//! SIMD compiler intrinsics.
2//!
3//! In this module, a "vector" is any `repr(simd)` type.
4
5use crate::marker::ConstParamTy;
6
7/// Inserts an element into a vector, returning the updated vector.
8///
9/// `T` must be a vector with element type `U`, and `idx` must be `const`.
10///
11/// # Safety
12///
13/// `idx` must be in-bounds of the vector.
14#[rustc_intrinsic]
15#[rustc_nounwind]
16pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
17
18/// Extracts an element from a vector.
19///
20/// `T` must be a vector with element type `U`, and `idx` must be `const`.
21///
22/// # Safety
23///
24/// `idx` must be const and in-bounds of the vector.
25#[rustc_intrinsic]
26#[rustc_nounwind]
27pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
28
29/// Inserts an element into a vector, returning the updated vector.
30///
31/// `T` must be a vector with element type `U`.
32///
33/// If the index is `const`, [`simd_insert`] may emit better assembly.
34///
35/// # Safety
36///
37/// `idx` must be in-bounds of the vector.
38#[rustc_nounwind]
39#[rustc_intrinsic]
40pub const unsafe fn simd_insert_dyn<T, U>(x: T, idx: u32, val: U) -> T;
41
42/// Extracts an element from a vector.
43///
44/// `T` must be a vector with element type `U`.
45///
46/// If the index is `const`, [`simd_extract`] may emit better assembly.
47///
48/// # Safety
49///
50/// `idx` must be in-bounds of the vector.
51#[rustc_nounwind]
52#[rustc_intrinsic]
53pub const unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U;
54
55/// Creates a vector where every lane has the provided value.
56///
57/// `T` must be a vector with element type `U`.
58#[rustc_nounwind]
59#[rustc_intrinsic]
60pub const unsafe fn simd_splat<T, U>(value: U) -> T;
61
62/// Adds two simd vectors elementwise.
63///
64/// `T` must be a vector of integers or floats.
65/// For integers, wrapping arithmetic is used.
66#[rustc_intrinsic]
67#[rustc_nounwind]
68pub const unsafe fn simd_add<T>(x: T, y: T) -> T;
69
70/// Subtracts `rhs` from `lhs` elementwise.
71///
72/// `T` must be a vector of integers or floats.
73/// For integers, wrapping arithmetic is used.
74#[rustc_intrinsic]
75#[rustc_nounwind]
76pub const unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
77
78/// Multiplies two simd vectors elementwise.
79///
80/// `T` must be a vector of integers or floats.
81/// For integers, wrapping arithmetic is used.
82#[rustc_intrinsic]
83#[rustc_nounwind]
84pub const unsafe fn simd_mul<T>(x: T, y: T) -> T;
85
86/// Divides `lhs` by `rhs` elementwise.
87///
88/// `T` must be a vector of integers or floats.
89///
90/// # Safety
91/// For integers, `rhs` must not contain any zero elements.
92/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
93#[rustc_intrinsic]
94#[rustc_nounwind]
95pub const unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
96
97/// Returns remainder of two vectors elementwise.
98///
99/// `T` must be a vector of integers or floats.
100///
101/// # Safety
102/// For integers, `rhs` must not contain any zero elements.
103/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
104#[rustc_intrinsic]
105#[rustc_nounwind]
106pub const unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
107
108/// Shifts vector left elementwise, with UB on overflow.
109///
110/// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types.
111///
112/// `T` must be a vector of integers.
113///
114/// # Safety
115///
116/// Each element of `rhs` must be less than `<int>::BITS`.
117#[rustc_intrinsic]
118#[rustc_nounwind]
119pub const unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
120
121/// Shifts vector right elementwise, with UB on overflow.
122///
123/// `T` must be a vector of integers.
124///
125/// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types.
126///
127/// # Safety
128///
129/// Each element of `rhs` must be less than `<int>::BITS`.
130#[rustc_intrinsic]
131#[rustc_nounwind]
132pub const unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
133
134/// Funnel Shifts vector left elementwise, with UB on overflow.
135///
136/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
137/// creating a vector of the same length, but with each element being twice as
138/// wide. Then shift this vector left elementwise by `shift`, shifting in zeros,
139/// and extract the most significant half of each of the elements. If `a` and `b`
140/// are the same, this is equivalent to an elementwise rotate left operation.
141///
142/// `T` must be a vector of integers.
143///
144/// # Safety
145///
146/// Each element of `shift` must be less than `<int>::BITS`.
147#[rustc_intrinsic]
148#[rustc_nounwind]
149pub const unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
150
151/// Funnel Shifts vector right elementwise, with UB on overflow.
152///
153/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
154/// creating a vector of the same length, but with each element being twice as
155/// wide. Then shift this vector right elementwise by `shift`, shifting in zeros,
156/// and extract the least significant half of each of the elements. If `a` and `b`
157/// are the same, this is equivalent to an elementwise rotate right operation.
158///
159/// `T` must be a vector of integers.
160///
161/// # Safety
162///
163/// Each element of `shift` must be less than `<int>::BITS`.
164#[rustc_intrinsic]
165#[rustc_nounwind]
166pub const unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
167
168/// Compute the carry-less product.
169///
170/// This is similar to long multiplication except that the carry is discarded.
171///
172/// This operation can be used to model multiplication in `GF(2)[X]`, the polynomial
173/// ring over `GF(2)`.
174///
175/// `T` must be a vector of integers.
176#[rustc_intrinsic]
177#[rustc_nounwind]
178pub unsafe fn simd_carryless_mul<T>(a: T, b: T) -> T;
179
180/// "And"s vectors elementwise.
181///
182/// `T` must be a vector of integers.
183#[rustc_intrinsic]
184#[rustc_nounwind]
185pub const unsafe fn simd_and<T>(x: T, y: T) -> T;
186
187/// "Ors" vectors elementwise.
188///
189/// `T` must be a vector of integers.
190#[rustc_intrinsic]
191#[rustc_nounwind]
192pub const unsafe fn simd_or<T>(x: T, y: T) -> T;
193
194/// "Exclusive ors" vectors elementwise.
195///
196/// `T` must be a vector of integers.
197#[rustc_intrinsic]
198#[rustc_nounwind]
199pub const unsafe fn simd_xor<T>(x: T, y: T) -> T;
200
201/// Numerically casts a vector, elementwise.
202///
203/// `T` and `U` must be vectors of integers or floats, and must have the same length.
204///
205/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB.
206/// When casting integers to floats, the result is rounded.
207/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
208///
209/// # Safety
210/// Casting from integer types is always safe.
211/// Casting between two float types is also always safe.
212///
213/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`.
214/// Specifically, each element must:
215/// * Not be `NaN`
216/// * Not be infinite
217/// * Be representable in the return type, after truncating off its fractional part
218#[rustc_intrinsic]
219#[rustc_nounwind]
220pub const unsafe fn simd_cast<T, U>(x: T) -> U;
221
222/// Numerically casts a vector, elementwise.
223///
224/// `T` and `U` be a vectors of integers or floats, and must have the same length.
225///
226/// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0).
227/// This matches regular `as` and is always safe.
228///
229/// When casting floats to integers, the result is truncated.
230/// When casting integers to floats, the result is rounded.
231/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
232#[rustc_intrinsic]
233#[rustc_nounwind]
234pub const unsafe fn simd_as<T, U>(x: T) -> U;
235
236/// Negates a vector elementwise.
237///
238/// `T` must be a vector of integers or floats.
239/// For integers, wrapping arithmetic is used.
240#[rustc_intrinsic]
241#[rustc_nounwind]
242pub const unsafe fn simd_neg<T>(x: T) -> T;
243
244/// Returns absolute value of a vector, elementwise.
245///
246/// `T` must be a vector of floating-point primitive types.
247#[rustc_intrinsic]
248#[rustc_nounwind]
249pub const unsafe fn simd_fabs<T>(x: T) -> T;
250
251/// Returns the minimum of two vectors, elementwise.
252///
253/// `T` must be a vector of floating-point primitive types.
254///
255/// This behaves like IEEE 754-2019 minimumNumber, *except* that it does not order signed
256/// zeros deterministically. In particular, for each vector lane:
257/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If
258/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0`
259/// and `-0.0`), either input may be returned non-deterministically.
260#[rustc_intrinsic]
261#[rustc_nounwind]
262pub const unsafe fn simd_minimum_number_nsz<T>(x: T, y: T) -> T;
263
264/// Returns the maximum of two vectors, elementwise.
265///
266/// `T` must be a vector of floating-point primitive types.
267///
268/// This behaves like IEEE 754-2019 maximumNumber, *except* that it does not order signed
269/// zeros deterministically. In particular, for each vector lane:
270/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If
271/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0`
272/// and `-0.0`), either input may be returned non-deterministically.
273#[rustc_intrinsic]
274#[rustc_nounwind]
275pub const unsafe fn simd_maximum_number_nsz<T>(x: T, y: T) -> T;
276
277/// Tests elementwise equality of two vectors.
278///
279/// `T` must be a vector of integers or floats.
280///
281/// `U` must be a vector of integers with the same number of elements and element size as `T`.
282///
283/// Returns `0` for false and `!0` for true.
284#[rustc_intrinsic]
285#[rustc_nounwind]
286pub const unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
287
288/// Tests elementwise inequality equality of two vectors.
289///
290/// `T` must be a vector of integers or floats.
291///
292/// `U` must be a vector of integers with the same number of elements and element size as `T`.
293///
294/// Returns `0` for false and `!0` for true.
295#[rustc_intrinsic]
296#[rustc_nounwind]
297pub const unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
298
299/// Tests if `x` is less than `y`, elementwise.
300///
301/// `T` must be a vector of integers or floats.
302///
303/// `U` must be a vector of integers with the same number of elements and element size as `T`.
304///
305/// Returns `0` for false and `!0` for true.
306#[rustc_intrinsic]
307#[rustc_nounwind]
308pub const unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
309
310/// Tests if `x` is less than or equal to `y`, elementwise.
311///
312/// `T` must be a vector of integers or floats.
313///
314/// `U` must be a vector of integers with the same number of elements and element size as `T`.
315///
316/// Returns `0` for false and `!0` for true.
317#[rustc_intrinsic]
318#[rustc_nounwind]
319pub const unsafe fn simd_le<T, U>(x: T, y: T) -> U;
320
321/// Tests if `x` is greater than `y`, elementwise.
322///
323/// `T` must be a vector of integers or floats.
324///
325/// `U` must be a vector of integers with the same number of elements and element size as `T`.
326///
327/// Returns `0` for false and `!0` for true.
328#[rustc_intrinsic]
329#[rustc_nounwind]
330pub const unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
331
332/// Tests if `x` is greater than or equal to `y`, elementwise.
333///
334/// `T` must be a vector of integers or floats.
335///
336/// `U` must be a vector of integers with the same number of elements and element size as `T`.
337///
338/// Returns `0` for false and `!0` for true.
339#[rustc_intrinsic]
340#[rustc_nounwind]
341pub const unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
342
343/// Shuffles two vectors by const indices.
344///
345/// `T` must be a vector.
346///
347/// `U` must be a **const** vector of `u32`s. This means it must either refer to a named
348/// const or be given as an inline const expression (`const { ... }`).
349///
350/// `V` must be a vector with the same element type as `T` and the same length as `U`.
351///
352/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
353/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
354/// of `xy`.
355#[rustc_intrinsic]
356#[rustc_nounwind]
357pub const unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
358
359/// Reads a vector of pointers.
360///
361/// `T` must be a vector.
362///
363/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
364///
365/// `V` must be a vector of integers with the same length as `T` (but any element size).
366///
367/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer.
368/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
369/// `val`.
370///
371/// # Safety
372/// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element
373/// type).
374///
375/// `mask` must only contain `0` or `!0` values.
376#[rustc_intrinsic]
377#[rustc_nounwind]
378pub const unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
379
380/// Writes to a vector of pointers.
381///
382/// `T` must be a vector.
383///
384/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
385///
386/// `V` must be a vector of integers with the same length as `T` (but any element size).
387///
388/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the
389/// corresponding value in `val` to the pointer.
390/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
391///
392/// The stores happen in left-to-right order.
393/// (This is relevant in case two of the stores overlap.)
394///
395/// # Safety
396/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
397/// type).
398///
399/// `mask` must only contain `0` or `!0` values.
400#[rustc_intrinsic]
401#[rustc_nounwind]
402pub const unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
403
404/// A type for alignment options for SIMD masked load/store intrinsics.
405#[derive(Debug, ConstParamTy, PartialEq, Eq)]
406pub enum SimdAlign {
407 // These values must match the compiler's `SimdAlign` defined in
408 // `rustc_middle/src/ty/consts/int.rs`!
409 /// No alignment requirements on the pointer
410 Unaligned = 0,
411 /// The pointer must be aligned to the element type of the SIMD vector
412 Element = 1,
413 /// The pointer must be aligned to the SIMD vector type
414 Vector = 2,
415}
416
417/// Reads a vector of pointers.
418///
419/// `T` must be a vector.
420///
421/// `U` must be a pointer to the element type of `T`
422///
423/// `V` must be a vector of integers with the same length as `T` (but any element size).
424///
425/// For each element, if the corresponding value in `mask` is `!0`, read the corresponding
426/// pointer offset from `ptr`.
427/// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on.
428/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
429/// `val`.
430///
431/// # Safety
432/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
433///
434/// `mask` must only contain `0` or `!0` values.
435#[rustc_intrinsic]
436#[rustc_nounwind]
437pub const unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T)
438-> T;
439
440/// Writes to a vector of pointers.
441///
442/// `T` must be a vector.
443///
444/// `U` must be a pointer to the element type of `T`
445///
446/// `V` must be a vector of integers with the same length as `T` (but any element size).
447///
448/// For each element, if the corresponding value in `mask` is `!0`, write the corresponding
449/// value in `val` to the pointer offset from `ptr`.
450/// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on.
451/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
452///
453/// # Safety
454/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
455///
456/// `mask` must only contain `0` or `!0` values.
457#[rustc_intrinsic]
458#[rustc_nounwind]
459pub const unsafe fn simd_masked_store<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T);
460
461/// Adds two simd vectors elementwise, with saturation.
462///
463/// `T` must be a vector of integer primitive types.
464#[rustc_intrinsic]
465#[rustc_nounwind]
466pub const unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
467
468/// Subtracts two simd vectors elementwise, with saturation.
469///
470/// `T` must be a vector of integer primitive types.
471///
472/// Subtract `rhs` from `lhs`.
473#[rustc_intrinsic]
474#[rustc_nounwind]
475pub const unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
476
477/// Adds elements within a vector from left to right.
478///
479/// `T` must be a vector of integers or floats.
480///
481/// `U` must be the element type of `T`.
482///
483/// Starting with the value `y`, add the elements of `x` and accumulate.
484#[rustc_intrinsic]
485#[rustc_nounwind]
486pub const unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
487
488/// Adds elements within a vector in arbitrary order. May also be re-associated with
489/// unordered additions on the inputs/outputs.
490///
491/// `T` must be a vector of integers or floats.
492///
493/// `U` must be the element type of `T`.
494#[rustc_intrinsic]
495#[rustc_nounwind]
496pub unsafe fn simd_reduce_add_unordered<T, U>(x: T) -> U;
497
498/// Multiplies elements within a vector from left to right.
499///
500/// `T` must be a vector of integers or floats.
501///
502/// `U` must be the element type of `T`.
503///
504/// Starting with the value `y`, multiply the elements of `x` and accumulate.
505#[rustc_intrinsic]
506#[rustc_nounwind]
507pub const unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
508
509/// Multiplies elements within a vector in arbitrary order. May also be re-associated with
510/// unordered additions on the inputs/outputs.
511///
512/// `T` must be a vector of integers or floats.
513///
514/// `U` must be the element type of `T`.
515#[rustc_intrinsic]
516#[rustc_nounwind]
517pub unsafe fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
518
519/// Checks if all mask values are true.
520///
521/// `T` must be a vector of integer primitive types.
522///
523/// # Safety
524/// `x` must contain only `0` or `!0`.
525#[rustc_intrinsic]
526#[rustc_nounwind]
527pub const unsafe fn simd_reduce_all<T>(x: T) -> bool;
528
529/// Checks if any mask value is true.
530///
531/// `T` must be a vector of integer primitive types.
532///
533/// # Safety
534/// `x` must contain only `0` or `!0`.
535#[rustc_intrinsic]
536#[rustc_nounwind]
537pub const unsafe fn simd_reduce_any<T>(x: T) -> bool;
538
539/// Returns the maximum element of a vector.
540///
541/// `T` must be a vector of integers or floats.
542///
543/// `U` must be the element type of `T`.
544///
545/// For floating-point values, uses IEEE-754 `maxNum`.
546#[rustc_intrinsic]
547#[rustc_nounwind]
548pub const unsafe fn simd_reduce_max<T, U>(x: T) -> U;
549
550/// Returns the minimum element of a vector.
551///
552/// `T` must be a vector of integers or floats.
553///
554/// `U` must be the element type of `T`.
555///
556/// For floating-point values, uses IEEE-754 `minNum`.
557#[rustc_intrinsic]
558#[rustc_nounwind]
559pub const unsafe fn simd_reduce_min<T, U>(x: T) -> U;
560
561/// Logical "and"s all elements together.
562///
563/// `T` must be a vector of integers or floats.
564///
565/// `U` must be the element type of `T`.
566#[rustc_intrinsic]
567#[rustc_nounwind]
568pub const unsafe fn simd_reduce_and<T, U>(x: T) -> U;
569
570/// Logical "ors" all elements together.
571///
572/// `T` must be a vector of integers or floats.
573///
574/// `U` must be the element type of `T`.
575#[rustc_intrinsic]
576#[rustc_nounwind]
577pub const unsafe fn simd_reduce_or<T, U>(x: T) -> U;
578
579/// Logical "exclusive ors" all elements together.
580///
581/// `T` must be a vector of integers or floats.
582///
583/// `U` must be the element type of `T`.
584#[rustc_intrinsic]
585#[rustc_nounwind]
586pub const unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
587
588/// Truncates an integer vector to a bitmask.
589///
590/// `T` must be an integer vector.
591///
592/// `U` must be either the smallest unsigned integer with at least as many bits as the length
593/// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`.
594///
595/// Each element is truncated to a single bit and packed into the result.
596///
597/// No matter whether the output is an array or an unsigned integer, it is treated as a single
598/// contiguous list of bits. The bitmask is always packed on the least-significant side of the
599/// output, and padded with 0s in the most-significant bits. The order of the bits depends on
600/// endianness:
601///
602/// * On little endian, the least significant bit corresponds to the first vector element.
603/// * On big endian, the least significant bit corresponds to the last vector element.
604///
605/// For example, `[!0, 0, !0, !0]` packs to
606/// - `0b1101u8` or `[0b1101]` on little endian, and
607/// - `0b1011u8` or `[0b1011]` on big endian.
608///
609/// To consider a larger example,
610/// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to
611/// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and
612/// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian.
613///
614/// And finally, a non-power-of-2 example with multiple bytes:
615/// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to
616/// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and
617/// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian.
618///
619/// # Safety
620/// `x` must contain only `0` and `!0`.
621#[rustc_intrinsic]
622#[rustc_nounwind]
623pub const unsafe fn simd_bitmask<T, U>(x: T) -> U;
624
625/// Selects elements from a mask.
626///
627/// `T` must be a vector.
628///
629/// `M` must be an integer vector with the same length as `T` (but any element size).
630///
631/// For each element, if the corresponding value in `mask` is `!0`, select the element from
632/// `if_true`. If the corresponding value in `mask` is `0`, select the element from
633/// `if_false`.
634///
635/// # Safety
636/// `mask` must only contain `0` and `!0`.
637#[rustc_intrinsic]
638#[rustc_nounwind]
639pub const unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
640
641/// Selects elements from a bitmask.
642///
643/// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`.
644///
645/// `T` must be a vector.
646///
647/// For each element, if the bit in `mask` is `1`, select the element from
648/// `if_true`. If the corresponding bit in `mask` is `0`, select the element from
649/// `if_false`.
650/// The remaining bits of the mask are ignored.
651///
652/// The bitmask bit order matches `simd_bitmask`.
653#[rustc_intrinsic]
654#[rustc_nounwind]
655pub const unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
656
657/// Calculates the offset from a pointer vector elementwise, potentially
658/// wrapping.
659///
660/// `T` must be a vector of pointers.
661///
662/// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`.
663///
664/// Operates as if by `<ptr>::wrapping_offset`.
665#[rustc_intrinsic]
666#[rustc_nounwind]
667pub const unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
668
669/// Casts a vector of pointers.
670///
671/// `T` and `U` must be vectors of pointers with the same number of elements.
672#[rustc_intrinsic]
673#[rustc_nounwind]
674pub const unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
675
676/// Exposes a vector of pointers as a vector of addresses.
677///
678/// `T` must be a vector of pointers.
679///
680/// `U` must be a vector of `usize` with the same length as `T`.
681#[rustc_intrinsic]
682#[rustc_nounwind]
683pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U;
684
685/// Creates a vector of pointers from a vector of addresses.
686///
687/// `T` must be a vector of `usize`.
688///
689/// `U` must be a vector of pointers, with the same length as `T`.
690#[rustc_intrinsic]
691#[rustc_nounwind]
692pub const unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
693
694/// Swaps bytes of each element.
695///
696/// `T` must be a vector of integers.
697#[rustc_intrinsic]
698#[rustc_nounwind]
699pub const unsafe fn simd_bswap<T>(x: T) -> T;
700
701/// Reverses bits of each element.
702///
703/// `T` must be a vector of integers.
704#[rustc_intrinsic]
705#[rustc_nounwind]
706pub const unsafe fn simd_bitreverse<T>(x: T) -> T;
707
708/// Counts the leading zeros of each element.
709///
710/// `T` must be a vector of integers.
711#[rustc_intrinsic]
712#[rustc_nounwind]
713pub const unsafe fn simd_ctlz<T>(x: T) -> T;
714
715/// Counts the number of ones in each element.
716///
717/// `T` must be a vector of integers.
718#[rustc_intrinsic]
719#[rustc_nounwind]
720pub const unsafe fn simd_ctpop<T>(x: T) -> T;
721
722/// Counts the trailing zeros of each element.
723///
724/// `T` must be a vector of integers.
725#[rustc_intrinsic]
726#[rustc_nounwind]
727pub const unsafe fn simd_cttz<T>(x: T) -> T;
728
729/// Rounds up each element to the next highest integer-valued float.
730///
731/// `T` must be a vector of floats.
732#[rustc_intrinsic]
733#[rustc_nounwind]
734pub const unsafe fn simd_ceil<T>(x: T) -> T;
735
736/// Rounds down each element to the next lowest integer-valued float.
737///
738/// `T` must be a vector of floats.
739#[rustc_intrinsic]
740#[rustc_nounwind]
741pub const unsafe fn simd_floor<T>(x: T) -> T;
742
743/// Rounds each element to the closest integer-valued float.
744/// Ties are resolved by rounding away from 0.
745///
746/// `T` must be a vector of floats.
747#[rustc_intrinsic]
748#[rustc_nounwind]
749pub const unsafe fn simd_round<T>(x: T) -> T;
750
751/// Rounds each element to the closest integer-valued float.
752/// Ties are resolved by rounding to the number with an even least significant digit
753///
754/// `T` must be a vector of floats.
755#[rustc_intrinsic]
756#[rustc_nounwind]
757pub const unsafe fn simd_round_ties_even<T>(x: T) -> T;
758
759/// Returns the integer part of each element as an integer-valued float.
760/// In other words, non-integer values are truncated towards zero.
761///
762/// `T` must be a vector of floats.
763#[rustc_intrinsic]
764#[rustc_nounwind]
765pub const unsafe fn simd_trunc<T>(x: T) -> T;
766
767/// Takes the square root of each element.
768///
769/// `T` must be a vector of floats.
770#[rustc_intrinsic]
771#[rustc_nounwind]
772pub unsafe fn simd_fsqrt<T>(x: T) -> T;
773
774/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
775///
776/// `T` must be a vector of floats.
777#[rustc_intrinsic]
778#[rustc_nounwind]
779pub const unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
780
781/// Computes `(x*y) + z` for each element, non-deterministically executing either
782/// a fused multiply-add or two operations with rounding of the intermediate result.
783///
784/// The operation is fused if the code generator determines that target instruction
785/// set has support for a fused operation, and that the fused operation is more efficient
786/// than the equivalent, separate pair of mul and add instructions. It is unspecified
787/// whether or not a fused operation is selected, and that may depend on optimization
788/// level and context, for example. It may even be the case that some SIMD lanes get fused
789/// and others do not.
790///
791/// `T` must be a vector of floats.
792#[rustc_intrinsic]
793#[rustc_nounwind]
794pub const unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
795
796// Computes the sine of each element.
797///
798/// `T` must be a vector of floats.
799#[rustc_intrinsic]
800#[rustc_nounwind]
801pub unsafe fn simd_fsin<T>(a: T) -> T;
802
803// Computes the cosine of each element.
804///
805/// `T` must be a vector of floats.
806#[rustc_intrinsic]
807#[rustc_nounwind]
808pub unsafe fn simd_fcos<T>(a: T) -> T;
809
810// Computes the exponential function of each element.
811///
812/// `T` must be a vector of floats.
813#[rustc_intrinsic]
814#[rustc_nounwind]
815pub unsafe fn simd_fexp<T>(a: T) -> T;
816
817// Computes 2 raised to the power of each element.
818///
819/// `T` must be a vector of floats.
820#[rustc_intrinsic]
821#[rustc_nounwind]
822pub unsafe fn simd_fexp2<T>(a: T) -> T;
823
824// Computes the base 10 logarithm of each element.
825///
826/// `T` must be a vector of floats.
827#[rustc_intrinsic]
828#[rustc_nounwind]
829pub unsafe fn simd_flog10<T>(a: T) -> T;
830
831// Computes the base 2 logarithm of each element.
832///
833/// `T` must be a vector of floats.
834#[rustc_intrinsic]
835#[rustc_nounwind]
836pub unsafe fn simd_flog2<T>(a: T) -> T;
837
838// Computes the natural logarithm of each element.
839///
840/// `T` must be a vector of floats.
841#[rustc_intrinsic]
842#[rustc_nounwind]
843pub unsafe fn simd_flog<T>(a: T) -> T;
library/core/src/intrinsics/simd/mod.rs created+845
...@@ -0,0 +1,845 @@
1//! SIMD compiler intrinsics.
2//!
3//! In this module, a "vector" is any `repr(simd)` type.
4
5pub mod scalable;
6
7use crate::marker::ConstParamTy;
8
9/// Inserts an element into a vector, returning the updated vector.
10///
11/// `T` must be a vector with element type `U`, and `idx` must be `const`.
12///
13/// # Safety
14///
15/// `idx` must be in-bounds of the vector.
16#[rustc_intrinsic]
17#[rustc_nounwind]
18pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
19
20/// Extracts an element from a vector.
21///
22/// `T` must be a vector with element type `U`, and `idx` must be `const`.
23///
24/// # Safety
25///
26/// `idx` must be const and in-bounds of the vector.
27#[rustc_intrinsic]
28#[rustc_nounwind]
29pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
30
31/// Inserts an element into a vector, returning the updated vector.
32///
33/// `T` must be a vector with element type `U`.
34///
35/// If the index is `const`, [`simd_insert`] may emit better assembly.
36///
37/// # Safety
38///
39/// `idx` must be in-bounds of the vector.
40#[rustc_nounwind]
41#[rustc_intrinsic]
42pub const unsafe fn simd_insert_dyn<T, U>(x: T, idx: u32, val: U) -> T;
43
44/// Extracts an element from a vector.
45///
46/// `T` must be a vector with element type `U`.
47///
48/// If the index is `const`, [`simd_extract`] may emit better assembly.
49///
50/// # Safety
51///
52/// `idx` must be in-bounds of the vector.
53#[rustc_nounwind]
54#[rustc_intrinsic]
55pub const unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U;
56
57/// Creates a vector where every lane has the provided value.
58///
59/// `T` must be a vector with element type `U`.
60#[rustc_nounwind]
61#[rustc_intrinsic]
62pub const unsafe fn simd_splat<T, U>(value: U) -> T;
63
64/// Adds two simd vectors elementwise.
65///
66/// `T` must be a vector of integers or floats.
67/// For integers, wrapping arithmetic is used.
68#[rustc_intrinsic]
69#[rustc_nounwind]
70pub const unsafe fn simd_add<T>(x: T, y: T) -> T;
71
72/// Subtracts `rhs` from `lhs` elementwise.
73///
74/// `T` must be a vector of integers or floats.
75/// For integers, wrapping arithmetic is used.
76#[rustc_intrinsic]
77#[rustc_nounwind]
78pub const unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
79
80/// Multiplies two simd vectors elementwise.
81///
82/// `T` must be a vector of integers or floats.
83/// For integers, wrapping arithmetic is used.
84#[rustc_intrinsic]
85#[rustc_nounwind]
86pub const unsafe fn simd_mul<T>(x: T, y: T) -> T;
87
88/// Divides `lhs` by `rhs` elementwise.
89///
90/// `T` must be a vector of integers or floats.
91///
92/// # Safety
93/// For integers, `rhs` must not contain any zero elements.
94/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
95#[rustc_intrinsic]
96#[rustc_nounwind]
97pub const unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
98
99/// Returns remainder of two vectors elementwise.
100///
101/// `T` must be a vector of integers or floats.
102///
103/// # Safety
104/// For integers, `rhs` must not contain any zero elements.
105/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
106#[rustc_intrinsic]
107#[rustc_nounwind]
108pub const unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
109
110/// Shifts vector left elementwise, with UB on overflow.
111///
112/// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types.
113///
114/// `T` must be a vector of integers.
115///
116/// # Safety
117///
118/// Each element of `rhs` must be less than `<int>::BITS`.
119#[rustc_intrinsic]
120#[rustc_nounwind]
121pub const unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
122
123/// Shifts vector right elementwise, with UB on overflow.
124///
125/// `T` must be a vector of integers.
126///
127/// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types.
128///
129/// # Safety
130///
131/// Each element of `rhs` must be less than `<int>::BITS`.
132#[rustc_intrinsic]
133#[rustc_nounwind]
134pub const unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
135
136/// Funnel Shifts vector left elementwise, with UB on overflow.
137///
138/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
139/// creating a vector of the same length, but with each element being twice as
140/// wide. Then shift this vector left elementwise by `shift`, shifting in zeros,
141/// and extract the most significant half of each of the elements. If `a` and `b`
142/// are the same, this is equivalent to an elementwise rotate left operation.
143///
144/// `T` must be a vector of integers.
145///
146/// # Safety
147///
148/// Each element of `shift` must be less than `<int>::BITS`.
149#[rustc_intrinsic]
150#[rustc_nounwind]
151pub const unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
152
153/// Funnel Shifts vector right elementwise, with UB on overflow.
154///
155/// Concatenates `a` and `b` elementwise (with `a` in the most significant half),
156/// creating a vector of the same length, but with each element being twice as
157/// wide. Then shift this vector right elementwise by `shift`, shifting in zeros,
158/// and extract the least significant half of each of the elements. If `a` and `b`
159/// are the same, this is equivalent to an elementwise rotate right operation.
160///
161/// `T` must be a vector of integers.
162///
163/// # Safety
164///
165/// Each element of `shift` must be less than `<int>::BITS`.
166#[rustc_intrinsic]
167#[rustc_nounwind]
168pub const unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
169
170/// Compute the carry-less product.
171///
172/// This is similar to long multiplication except that the carry is discarded.
173///
174/// This operation can be used to model multiplication in `GF(2)[X]`, the polynomial
175/// ring over `GF(2)`.
176///
177/// `T` must be a vector of integers.
178#[rustc_intrinsic]
179#[rustc_nounwind]
180pub unsafe fn simd_carryless_mul<T>(a: T, b: T) -> T;
181
182/// "And"s vectors elementwise.
183///
184/// `T` must be a vector of integers.
185#[rustc_intrinsic]
186#[rustc_nounwind]
187pub const unsafe fn simd_and<T>(x: T, y: T) -> T;
188
189/// "Ors" vectors elementwise.
190///
191/// `T` must be a vector of integers.
192#[rustc_intrinsic]
193#[rustc_nounwind]
194pub const unsafe fn simd_or<T>(x: T, y: T) -> T;
195
196/// "Exclusive ors" vectors elementwise.
197///
198/// `T` must be a vector of integers.
199#[rustc_intrinsic]
200#[rustc_nounwind]
201pub const unsafe fn simd_xor<T>(x: T, y: T) -> T;
202
203/// Numerically casts a vector, elementwise.
204///
205/// `T` and `U` must be vectors of integers or floats, and must have the same length.
206///
207/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB.
208/// When casting integers to floats, the result is rounded.
209/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
210///
211/// # Safety
212/// Casting from integer types is always safe.
213/// Casting between two float types is also always safe.
214///
215/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`.
216/// Specifically, each element must:
217/// * Not be `NaN`
218/// * Not be infinite
219/// * Be representable in the return type, after truncating off its fractional part
220#[rustc_intrinsic]
221#[rustc_nounwind]
222pub const unsafe fn simd_cast<T, U>(x: T) -> U;
223
224/// Numerically casts a vector, elementwise.
225///
226/// `T` and `U` be a vectors of integers or floats, and must have the same length.
227///
228/// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0).
229/// This matches regular `as` and is always safe.
230///
231/// When casting floats to integers, the result is truncated.
232/// When casting integers to floats, the result is rounded.
233/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
234#[rustc_intrinsic]
235#[rustc_nounwind]
236pub const unsafe fn simd_as<T, U>(x: T) -> U;
237
238/// Negates a vector elementwise.
239///
240/// `T` must be a vector of integers or floats.
241/// For integers, wrapping arithmetic is used.
242#[rustc_intrinsic]
243#[rustc_nounwind]
244pub const unsafe fn simd_neg<T>(x: T) -> T;
245
246/// Returns absolute value of a vector, elementwise.
247///
248/// `T` must be a vector of floating-point primitive types.
249#[rustc_intrinsic]
250#[rustc_nounwind]
251pub const unsafe fn simd_fabs<T>(x: T) -> T;
252
253/// Returns the minimum of two vectors, elementwise.
254///
255/// `T` must be a vector of floating-point primitive types.
256///
257/// This behaves like IEEE 754-2019 minimumNumber, *except* that it does not order signed
258/// zeros deterministically. In particular, for each vector lane:
259/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If
260/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0`
261/// and `-0.0`), either input may be returned non-deterministically.
262#[rustc_intrinsic]
263#[rustc_nounwind]
264pub const unsafe fn simd_minimum_number_nsz<T>(x: T, y: T) -> T;
265
266/// Returns the maximum of two vectors, elementwise.
267///
268/// `T` must be a vector of floating-point primitive types.
269///
270/// This behaves like IEEE 754-2019 maximumNumber, *except* that it does not order signed
271/// zeros deterministically. In particular, for each vector lane:
272/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If
273/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0`
274/// and `-0.0`), either input may be returned non-deterministically.
275#[rustc_intrinsic]
276#[rustc_nounwind]
277pub const unsafe fn simd_maximum_number_nsz<T>(x: T, y: T) -> T;
278
279/// Tests elementwise equality of two vectors.
280///
281/// `T` must be a vector of integers or floats.
282///
283/// `U` must be a vector of integers with the same number of elements and element size as `T`.
284///
285/// Returns `0` for false and `!0` for true.
286#[rustc_intrinsic]
287#[rustc_nounwind]
288pub const unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
289
290/// Tests elementwise inequality equality of two vectors.
291///
292/// `T` must be a vector of integers or floats.
293///
294/// `U` must be a vector of integers with the same number of elements and element size as `T`.
295///
296/// Returns `0` for false and `!0` for true.
297#[rustc_intrinsic]
298#[rustc_nounwind]
299pub const unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
300
301/// Tests if `x` is less than `y`, elementwise.
302///
303/// `T` must be a vector of integers or floats.
304///
305/// `U` must be a vector of integers with the same number of elements and element size as `T`.
306///
307/// Returns `0` for false and `!0` for true.
308#[rustc_intrinsic]
309#[rustc_nounwind]
310pub const unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
311
312/// Tests if `x` is less than or equal to `y`, elementwise.
313///
314/// `T` must be a vector of integers or floats.
315///
316/// `U` must be a vector of integers with the same number of elements and element size as `T`.
317///
318/// Returns `0` for false and `!0` for true.
319#[rustc_intrinsic]
320#[rustc_nounwind]
321pub const unsafe fn simd_le<T, U>(x: T, y: T) -> U;
322
323/// Tests if `x` is greater than `y`, elementwise.
324///
325/// `T` must be a vector of integers or floats.
326///
327/// `U` must be a vector of integers with the same number of elements and element size as `T`.
328///
329/// Returns `0` for false and `!0` for true.
330#[rustc_intrinsic]
331#[rustc_nounwind]
332pub const unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
333
334/// Tests if `x` is greater than or equal to `y`, elementwise.
335///
336/// `T` must be a vector of integers or floats.
337///
338/// `U` must be a vector of integers with the same number of elements and element size as `T`.
339///
340/// Returns `0` for false and `!0` for true.
341#[rustc_intrinsic]
342#[rustc_nounwind]
343pub const unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
344
345/// Shuffles two vectors by const indices.
346///
347/// `T` must be a vector.
348///
349/// `U` must be a **const** vector of `u32`s. This means it must either refer to a named
350/// const or be given as an inline const expression (`const { ... }`).
351///
352/// `V` must be a vector with the same element type as `T` and the same length as `U`.
353///
354/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
355/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
356/// of `xy`.
357#[rustc_intrinsic]
358#[rustc_nounwind]
359pub const unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
360
361/// Reads a vector of pointers.
362///
363/// `T` must be a vector.
364///
365/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
366///
367/// `V` must be a vector of integers with the same length as `T` (but any element size).
368///
369/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer.
370/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
371/// `val`.
372///
373/// # Safety
374/// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element
375/// type).
376///
377/// `mask` must only contain `0` or `!0` values.
378#[rustc_intrinsic]
379#[rustc_nounwind]
380pub const unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
381
382/// Writes to a vector of pointers.
383///
384/// `T` must be a vector.
385///
386/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`.
387///
388/// `V` must be a vector of integers with the same length as `T` (but any element size).
389///
390/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the
391/// corresponding value in `val` to the pointer.
392/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
393///
394/// The stores happen in left-to-right order.
395/// (This is relevant in case two of the stores overlap.)
396///
397/// # Safety
398/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
399/// type).
400///
401/// `mask` must only contain `0` or `!0` values.
402#[rustc_intrinsic]
403#[rustc_nounwind]
404pub const unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
405
406/// A type for alignment options for SIMD masked load/store intrinsics.
407#[derive(Debug, ConstParamTy, PartialEq, Eq)]
408pub enum SimdAlign {
409 // These values must match the compiler's `SimdAlign` defined in
410 // `rustc_middle/src/ty/consts/int.rs`!
411 /// No alignment requirements on the pointer
412 Unaligned = 0,
413 /// The pointer must be aligned to the element type of the SIMD vector
414 Element = 1,
415 /// The pointer must be aligned to the SIMD vector type
416 Vector = 2,
417}
418
419/// Reads a vector of pointers.
420///
421/// `T` must be a vector.
422///
423/// `U` must be a pointer to the element type of `T`
424///
425/// `V` must be a vector of integers with the same length as `T` (but any element size).
426///
427/// For each element, if the corresponding value in `mask` is `!0`, read the corresponding
428/// pointer offset from `ptr`.
429/// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on.
430/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
431/// `val`.
432///
433/// # Safety
434/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
435///
436/// `mask` must only contain `0` or `!0` values.
437#[rustc_intrinsic]
438#[rustc_nounwind]
439pub const unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T)
440-> T;
441
442/// Writes to a vector of pointers.
443///
444/// `T` must be a vector.
445///
446/// `U` must be a pointer to the element type of `T`
447///
448/// `V` must be a vector of integers with the same length as `T` (but any element size).
449///
450/// For each element, if the corresponding value in `mask` is `!0`, write the corresponding
451/// value in `val` to the pointer offset from `ptr`.
452/// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on.
453/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
454///
455/// # Safety
456/// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details.
457///
458/// `mask` must only contain `0` or `!0` values.
459#[rustc_intrinsic]
460#[rustc_nounwind]
461pub const unsafe fn simd_masked_store<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T);
462
463/// Adds two simd vectors elementwise, with saturation.
464///
465/// `T` must be a vector of integer primitive types.
466#[rustc_intrinsic]
467#[rustc_nounwind]
468pub const unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
469
470/// Subtracts two simd vectors elementwise, with saturation.
471///
472/// `T` must be a vector of integer primitive types.
473///
474/// Subtract `rhs` from `lhs`.
475#[rustc_intrinsic]
476#[rustc_nounwind]
477pub const unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
478
479/// Adds elements within a vector from left to right.
480///
481/// `T` must be a vector of integers or floats.
482///
483/// `U` must be the element type of `T`.
484///
485/// Starting with the value `y`, add the elements of `x` and accumulate.
486#[rustc_intrinsic]
487#[rustc_nounwind]
488pub const unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
489
490/// Adds elements within a vector in arbitrary order. May also be re-associated with
491/// unordered additions on the inputs/outputs.
492///
493/// `T` must be a vector of integers or floats.
494///
495/// `U` must be the element type of `T`.
496#[rustc_intrinsic]
497#[rustc_nounwind]
498pub unsafe fn simd_reduce_add_unordered<T, U>(x: T) -> U;
499
500/// Multiplies elements within a vector from left to right.
501///
502/// `T` must be a vector of integers or floats.
503///
504/// `U` must be the element type of `T`.
505///
506/// Starting with the value `y`, multiply the elements of `x` and accumulate.
507#[rustc_intrinsic]
508#[rustc_nounwind]
509pub const unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
510
511/// Multiplies elements within a vector in arbitrary order. May also be re-associated with
512/// unordered additions on the inputs/outputs.
513///
514/// `T` must be a vector of integers or floats.
515///
516/// `U` must be the element type of `T`.
517#[rustc_intrinsic]
518#[rustc_nounwind]
519pub unsafe fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
520
521/// Checks if all mask values are true.
522///
523/// `T` must be a vector of integer primitive types.
524///
525/// # Safety
526/// `x` must contain only `0` or `!0`.
527#[rustc_intrinsic]
528#[rustc_nounwind]
529pub const unsafe fn simd_reduce_all<T>(x: T) -> bool;
530
531/// Checks if any mask value is true.
532///
533/// `T` must be a vector of integer primitive types.
534///
535/// # Safety
536/// `x` must contain only `0` or `!0`.
537#[rustc_intrinsic]
538#[rustc_nounwind]
539pub const unsafe fn simd_reduce_any<T>(x: T) -> bool;
540
541/// Returns the maximum element of a vector.
542///
543/// `T` must be a vector of integers or floats.
544///
545/// `U` must be the element type of `T`.
546///
547/// For floating-point values, uses IEEE-754 `maxNum`.
548#[rustc_intrinsic]
549#[rustc_nounwind]
550pub const unsafe fn simd_reduce_max<T, U>(x: T) -> U;
551
552/// Returns the minimum element of a vector.
553///
554/// `T` must be a vector of integers or floats.
555///
556/// `U` must be the element type of `T`.
557///
558/// For floating-point values, uses IEEE-754 `minNum`.
559#[rustc_intrinsic]
560#[rustc_nounwind]
561pub const unsafe fn simd_reduce_min<T, U>(x: T) -> U;
562
563/// Logical "and"s all elements together.
564///
565/// `T` must be a vector of integers or floats.
566///
567/// `U` must be the element type of `T`.
568#[rustc_intrinsic]
569#[rustc_nounwind]
570pub const unsafe fn simd_reduce_and<T, U>(x: T) -> U;
571
572/// Logical "ors" all elements together.
573///
574/// `T` must be a vector of integers or floats.
575///
576/// `U` must be the element type of `T`.
577#[rustc_intrinsic]
578#[rustc_nounwind]
579pub const unsafe fn simd_reduce_or<T, U>(x: T) -> U;
580
581/// Logical "exclusive ors" all elements together.
582///
583/// `T` must be a vector of integers or floats.
584///
585/// `U` must be the element type of `T`.
586#[rustc_intrinsic]
587#[rustc_nounwind]
588pub const unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
589
590/// Truncates an integer vector to a bitmask.
591///
592/// `T` must be an integer vector.
593///
594/// `U` must be either the smallest unsigned integer with at least as many bits as the length
595/// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`.
596///
597/// Each element is truncated to a single bit and packed into the result.
598///
599/// No matter whether the output is an array or an unsigned integer, it is treated as a single
600/// contiguous list of bits. The bitmask is always packed on the least-significant side of the
601/// output, and padded with 0s in the most-significant bits. The order of the bits depends on
602/// endianness:
603///
604/// * On little endian, the least significant bit corresponds to the first vector element.
605/// * On big endian, the least significant bit corresponds to the last vector element.
606///
607/// For example, `[!0, 0, !0, !0]` packs to
608/// - `0b1101u8` or `[0b1101]` on little endian, and
609/// - `0b1011u8` or `[0b1011]` on big endian.
610///
611/// To consider a larger example,
612/// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to
613/// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and
614/// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian.
615///
616/// And finally, a non-power-of-2 example with multiple bytes:
617/// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to
618/// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and
619/// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian.
620///
621/// # Safety
622/// `x` must contain only `0` and `!0`.
623#[rustc_intrinsic]
624#[rustc_nounwind]
625pub const unsafe fn simd_bitmask<T, U>(x: T) -> U;
626
627/// Selects elements from a mask.
628///
629/// `T` must be a vector.
630///
631/// `M` must be an integer vector with the same length as `T` (but any element size).
632///
633/// For each element, if the corresponding value in `mask` is `!0`, select the element from
634/// `if_true`. If the corresponding value in `mask` is `0`, select the element from
635/// `if_false`.
636///
637/// # Safety
638/// `mask` must only contain `0` and `!0`.
639#[rustc_intrinsic]
640#[rustc_nounwind]
641pub const unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
642
643/// Selects elements from a bitmask.
644///
645/// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`.
646///
647/// `T` must be a vector.
648///
649/// For each element, if the bit in `mask` is `1`, select the element from
650/// `if_true`. If the corresponding bit in `mask` is `0`, select the element from
651/// `if_false`.
652/// The remaining bits of the mask are ignored.
653///
654/// The bitmask bit order matches `simd_bitmask`.
655#[rustc_intrinsic]
656#[rustc_nounwind]
657pub const unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
658
659/// Calculates the offset from a pointer vector elementwise, potentially
660/// wrapping.
661///
662/// `T` must be a vector of pointers.
663///
664/// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`.
665///
666/// Operates as if by `<ptr>::wrapping_offset`.
667#[rustc_intrinsic]
668#[rustc_nounwind]
669pub const unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
670
671/// Casts a vector of pointers.
672///
673/// `T` and `U` must be vectors of pointers with the same number of elements.
674#[rustc_intrinsic]
675#[rustc_nounwind]
676pub const unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
677
678/// Exposes a vector of pointers as a vector of addresses.
679///
680/// `T` must be a vector of pointers.
681///
682/// `U` must be a vector of `usize` with the same length as `T`.
683#[rustc_intrinsic]
684#[rustc_nounwind]
685pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U;
686
687/// Creates a vector of pointers from a vector of addresses.
688///
689/// `T` must be a vector of `usize`.
690///
691/// `U` must be a vector of pointers, with the same length as `T`.
692#[rustc_intrinsic]
693#[rustc_nounwind]
694pub const unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
695
696/// Swaps bytes of each element.
697///
698/// `T` must be a vector of integers.
699#[rustc_intrinsic]
700#[rustc_nounwind]
701pub const unsafe fn simd_bswap<T>(x: T) -> T;
702
703/// Reverses bits of each element.
704///
705/// `T` must be a vector of integers.
706#[rustc_intrinsic]
707#[rustc_nounwind]
708pub const unsafe fn simd_bitreverse<T>(x: T) -> T;
709
710/// Counts the leading zeros of each element.
711///
712/// `T` must be a vector of integers.
713#[rustc_intrinsic]
714#[rustc_nounwind]
715pub const unsafe fn simd_ctlz<T>(x: T) -> T;
716
717/// Counts the number of ones in each element.
718///
719/// `T` must be a vector of integers.
720#[rustc_intrinsic]
721#[rustc_nounwind]
722pub const unsafe fn simd_ctpop<T>(x: T) -> T;
723
724/// Counts the trailing zeros of each element.
725///
726/// `T` must be a vector of integers.
727#[rustc_intrinsic]
728#[rustc_nounwind]
729pub const unsafe fn simd_cttz<T>(x: T) -> T;
730
731/// Rounds up each element to the next highest integer-valued float.
732///
733/// `T` must be a vector of floats.
734#[rustc_intrinsic]
735#[rustc_nounwind]
736pub const unsafe fn simd_ceil<T>(x: T) -> T;
737
738/// Rounds down each element to the next lowest integer-valued float.
739///
740/// `T` must be a vector of floats.
741#[rustc_intrinsic]
742#[rustc_nounwind]
743pub const unsafe fn simd_floor<T>(x: T) -> T;
744
745/// Rounds each element to the closest integer-valued float.
746/// Ties are resolved by rounding away from 0.
747///
748/// `T` must be a vector of floats.
749#[rustc_intrinsic]
750#[rustc_nounwind]
751pub const unsafe fn simd_round<T>(x: T) -> T;
752
753/// Rounds each element to the closest integer-valued float.
754/// Ties are resolved by rounding to the number with an even least significant digit
755///
756/// `T` must be a vector of floats.
757#[rustc_intrinsic]
758#[rustc_nounwind]
759pub const unsafe fn simd_round_ties_even<T>(x: T) -> T;
760
761/// Returns the integer part of each element as an integer-valued float.
762/// In other words, non-integer values are truncated towards zero.
763///
764/// `T` must be a vector of floats.
765#[rustc_intrinsic]
766#[rustc_nounwind]
767pub const unsafe fn simd_trunc<T>(x: T) -> T;
768
769/// Takes the square root of each element.
770///
771/// `T` must be a vector of floats.
772#[rustc_intrinsic]
773#[rustc_nounwind]
774pub unsafe fn simd_fsqrt<T>(x: T) -> T;
775
776/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
777///
778/// `T` must be a vector of floats.
779#[rustc_intrinsic]
780#[rustc_nounwind]
781pub const unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
782
783/// Computes `(x*y) + z` for each element, non-deterministically executing either
784/// a fused multiply-add or two operations with rounding of the intermediate result.
785///
786/// The operation is fused if the code generator determines that target instruction
787/// set has support for a fused operation, and that the fused operation is more efficient
788/// than the equivalent, separate pair of mul and add instructions. It is unspecified
789/// whether or not a fused operation is selected, and that may depend on optimization
790/// level and context, for example. It may even be the case that some SIMD lanes get fused
791/// and others do not.
792///
793/// `T` must be a vector of floats.
794#[rustc_intrinsic]
795#[rustc_nounwind]
796pub const unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
797
798// Computes the sine of each element.
799///
800/// `T` must be a vector of floats.
801#[rustc_intrinsic]
802#[rustc_nounwind]
803pub unsafe fn simd_fsin<T>(a: T) -> T;
804
805// Computes the cosine of each element.
806///
807/// `T` must be a vector of floats.
808#[rustc_intrinsic]
809#[rustc_nounwind]
810pub unsafe fn simd_fcos<T>(a: T) -> T;
811
812// Computes the exponential function of each element.
813///
814/// `T` must be a vector of floats.
815#[rustc_intrinsic]
816#[rustc_nounwind]
817pub unsafe fn simd_fexp<T>(a: T) -> T;
818
819// Computes 2 raised to the power of each element.
820///
821/// `T` must be a vector of floats.
822#[rustc_intrinsic]
823#[rustc_nounwind]
824pub unsafe fn simd_fexp2<T>(a: T) -> T;
825
826// Computes the base 10 logarithm of each element.
827///
828/// `T` must be a vector of floats.
829#[rustc_intrinsic]
830#[rustc_nounwind]
831pub unsafe fn simd_flog10<T>(a: T) -> T;
832
833// Computes the base 2 logarithm of each element.
834///
835/// `T` must be a vector of floats.
836#[rustc_intrinsic]
837#[rustc_nounwind]
838pub unsafe fn simd_flog2<T>(a: T) -> T;
839
840// Computes the natural logarithm of each element.
841///
842/// `T` must be a vector of floats.
843#[rustc_intrinsic]
844#[rustc_nounwind]
845pub unsafe fn simd_flog<T>(a: T) -> T;
library/core/src/intrinsics/simd/scalable.rs created+93
...@@ -0,0 +1,93 @@
1//! Scalable vector compiler intrinsics.
2//!
3//! In this module, a "vector" is any `#[rustc_scalable_vector]`-annotated type.
4
5/// Numerically casts a vector, elementwise.
6///
7/// `T` and `U` must be vectors of integers or floats, and must have the same length.
8///
9/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB.
10/// When casting integers to floats, the result is rounded.
11/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
12///
13/// # Safety
14/// Casting from integer types is always safe.
15/// Casting between two float types is also always safe.
16///
17/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`.
18/// Specifically, each element must:
19/// * Not be `NaN`
20/// * Not be infinite
21/// * Be representable in the return type, after truncating off its fractional part
22#[cfg(target_arch = "aarch64")]
23#[rustc_intrinsic]
24#[rustc_nounwind]
25pub unsafe fn sve_cast<T, U>(x: T) -> U;
26
27/// Create a tuple of two vectors.
28///
29/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
30/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
31/// type `SVec`.
32///
33/// Corresponds to Clang's `__builtin_sve_svcreate2*` builtins.
34#[cfg(target_arch = "aarch64")]
35#[rustc_nounwind]
36#[rustc_intrinsic]
37pub unsafe fn sve_tuple_create2<SVec, SVecTup>(x0: SVec, x1: SVec) -> SVecTup;
38
39/// Create a tuple of three vectors.
40///
41/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
42/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
43/// type `SVec`.
44///
45/// Corresponds to Clang's `__builtin_sve_svcreate3*` builtins.
46#[cfg(target_arch = "aarch64")]
47#[rustc_intrinsic]
48#[rustc_nounwind]
49pub unsafe fn sve_tuple_create3<SVec, SVecTup>(x0: SVec, x1: SVec, x2: SVec) -> SVecTup;
50
51/// Create a tuple of four vectors.
52///
53/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
54/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
55/// type `SVec`.
56///
57/// Corresponds to Clang's `__builtin_sve_svcreate4*` builtins.
58#[cfg(target_arch = "aarch64")]
59#[rustc_intrinsic]
60#[rustc_nounwind]
61pub unsafe fn sve_tuple_create4<SVec, SVecTup>(x0: SVec, x1: SVec, x2: SVec, x3: SVec) -> SVecTup;
62
63/// Get one vector from a tuple of vectors.
64///
65/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
66/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
67/// type `SVec`.
68///
69/// Corresponds to Clang's `__builtin_sve_svget*` builtins.
70///
71/// # Safety
72///
73/// `IDX` must be in-bounds of the tuple.
74#[cfg(target_arch = "aarch64")]
75#[rustc_intrinsic]
76#[rustc_nounwind]
77pub unsafe fn sve_tuple_get<SVecTup, SVec, const IDX: i32>(tuple: SVecTup) -> SVec;
78
79/// Change one vector in a tuple of vectors.
80///
81/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
82/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
83/// type `SVec`.
84///
85/// Corresponds to Clang's `__builtin_sve_svset*` builtins.
86///
87/// # Safety
88///
89/// `IDX` must be in-bounds of the tuple.
90#[cfg(target_arch = "aarch64")]
91#[rustc_intrinsic]
92#[rustc_nounwind]
93pub unsafe fn sve_tuple_set<SVecTup, SVec, const IDX: i32>(tuple: SVecTup, x: SVec) -> SVecTup;
library/core/src/iter/range.rs+1-1
...@@ -21,7 +21,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6...@@ -21,7 +21,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
21/// The *successor* operation moves towards values that compare greater.21/// The *successor* operation moves towards values that compare greater.
22/// The *predecessor* operation moves towards values that compare lesser.22/// The *predecessor* operation moves towards values that compare lesser.
23#[rustc_diagnostic_item = "range_step"]23#[rustc_diagnostic_item = "range_step"]
24#[rustc_on_unimplemented(24#[diagnostic::on_unimplemented(
25 message = "`std::ops::Range<{Self}>` is not an iterator",25 message = "`std::ops::Range<{Self}>` is not an iterator",
26 label = "`Range<{Self}>` is not an iterator",26 label = "`Range<{Self}>` is not an iterator",
27 note = "`Range` only implements `Iterator` for select types in the standard library, \27 note = "`Range` only implements `Iterator` for select types in the standard library, \
library/core/src/marker.rs+2-2
...@@ -1054,7 +1054,7 @@ marker_impls! {...@@ -1054,7 +1054,7 @@ marker_impls! {
1054#[unstable(feature = "const_destruct", issue = "133214")]1054#[unstable(feature = "const_destruct", issue = "133214")]
1055#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]1055#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
1056#[lang = "destruct"]1056#[lang = "destruct"]
1057#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]1057#[diagnostic::on_unimplemented(message = "can't drop `{Self}`")]
1058#[rustc_deny_explicit_impl]1058#[rustc_deny_explicit_impl]
1059#[rustc_dyn_incompatible_trait]1059#[rustc_dyn_incompatible_trait]
1060pub const trait Destruct: PointeeSized {}1060pub const trait Destruct: PointeeSized {}
...@@ -1088,7 +1088,7 @@ pub trait ConstParamTy_: StructuralPartialEq + Eq {}...@@ -1088,7 +1088,7 @@ pub trait ConstParamTy_: StructuralPartialEq + Eq {}
1088/// Derive macro generating an impl of the trait `ConstParamTy`.1088/// Derive macro generating an impl of the trait `ConstParamTy`.
1089#[rustc_builtin_macro]1089#[rustc_builtin_macro]
1090#[allow_internal_unstable(const_param_ty_trait)]1090#[allow_internal_unstable(const_param_ty_trait)]
1091#[unstable(feature = "adt_const_params", issue = "95174")]1091#[unstable(feature = "min_adt_const_params", issue = "154042", implied_by = "adt_const_params")]
1092pub macro ConstParamTy($item:item) {1092pub macro ConstParamTy($item:item) {
1093 /* compiler built-in */1093 /* compiler built-in */
1094}1094}
library/core/src/ops/arith.rs+3-5
...@@ -70,8 +70,7 @@...@@ -70,8 +70,7 @@
70 on(all(Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),70 on(all(Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
71 on(all(Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),71 on(all(Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
72 message = "cannot add `{Rhs}` to `{Self}`",72 message = "cannot add `{Rhs}` to `{Self}`",
73 label = "no implementation for `{Self} + {Rhs}`",73 label = "no implementation for `{Self} + {Rhs}`"
74 append_const_msg
75)]74)]
76#[doc(alias = "+")]75#[doc(alias = "+")]
77pub const trait Add<Rhs = Self> {76pub const trait Add<Rhs = Self> {
...@@ -181,10 +180,9 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128...@@ -181,10 +180,9 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
181#[lang = "sub"]180#[lang = "sub"]
182#[stable(feature = "rust1", since = "1.0.0")]181#[stable(feature = "rust1", since = "1.0.0")]
183#[rustc_const_unstable(feature = "const_ops", issue = "143802")]182#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
184#[rustc_on_unimplemented(183#[diagnostic::on_unimplemented(
185 message = "cannot subtract `{Rhs}` from `{Self}`",184 message = "cannot subtract `{Rhs}` from `{Self}`",
186 label = "no implementation for `{Self} - {Rhs}`",185 label = "no implementation for `{Self} - {Rhs}`"
187 append_const_msg
188)]186)]
189#[doc(alias = "-")]187#[doc(alias = "-")]
190pub const trait Sub<Rhs = Self> {188pub const trait Sub<Rhs = Self> {
tests/auxiliary/minicore.rs+1-1
...@@ -63,7 +63,7 @@ pub trait MetaSized: PointeeSized {}...@@ -63,7 +63,7 @@ pub trait MetaSized: PointeeSized {}
63pub trait Sized: MetaSized {}63pub trait Sized: MetaSized {}
6464
65#[lang = "destruct"]65#[lang = "destruct"]
66#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]66#[diagnostic::on_unimplemented(message = "can't drop `{Self}`")]
67pub trait Destruct: PointeeSized {}67pub trait Destruct: PointeeSized {}
6868
69#[lang = "legacy_receiver"]69#[lang = "legacy_receiver"]
tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs created+150
...@@ -0,0 +1,150 @@
1//@ only-aarch64
2//@ only-linux
3//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
4
5#![crate_type = "lib"]
6#![allow(incomplete_features, internal_features)]
7#![feature(rustc_attrs)]
8
9// Test that we generate the correct debuginfo for scalable vector types.
10
11#[rustc_scalable_vector(16)]
12#[allow(non_camel_case_types)]
13struct svint8_t(i8);
14
15#[rustc_scalable_vector]
16#[allow(non_camel_case_types)]
17struct svint8x2_t(svint8_t, svint8_t);
18
19#[rustc_scalable_vector(16)]
20#[allow(non_camel_case_types)]
21struct svuint8_t(u8);
22
23#[rustc_scalable_vector]
24#[allow(non_camel_case_types)]
25struct svuint8x2_t(svuint8_t, svuint8_t);
26
27#[rustc_scalable_vector(8)]
28#[allow(non_camel_case_types)]
29struct svint16_t(i16);
30
31#[rustc_scalable_vector]
32#[allow(non_camel_case_types)]
33struct svint16x2_t(svint16_t, svint16_t);
34
35#[rustc_scalable_vector(8)]
36#[allow(non_camel_case_types)]
37struct svuint16_t(u16);
38
39#[rustc_scalable_vector]
40#[allow(non_camel_case_types)]
41struct svuint16x2_t(svuint16_t, svuint16_t);
42
43#[rustc_scalable_vector(4)]
44#[allow(non_camel_case_types)]
45struct svint32_t(i32);
46
47#[rustc_scalable_vector]
48#[allow(non_camel_case_types)]
49struct svint32x2_t(svint32_t, svint32_t);
50
51#[rustc_scalable_vector(4)]
52#[allow(non_camel_case_types)]
53struct svuint32_t(u32);
54
55#[rustc_scalable_vector]
56#[allow(non_camel_case_types)]
57struct svuint32x2_t(svuint32_t, svuint32_t);
58
59#[rustc_scalable_vector(2)]
60#[allow(non_camel_case_types)]
61struct svint64_t(i64);
62
63#[rustc_scalable_vector]
64#[allow(non_camel_case_types)]
65struct svint64x2_t(svint64_t, svint64_t);
66
67#[rustc_scalable_vector(2)]
68#[allow(non_camel_case_types)]
69struct svuint64_t(u64);
70
71#[rustc_scalable_vector]
72#[allow(non_camel_case_types)]
73struct svuint64x2_t(svuint64_t, svuint64_t);
74
75#[rustc_scalable_vector(4)]
76#[allow(non_camel_case_types)]
77struct svfloat32_t(f32);
78
79#[rustc_scalable_vector]
80#[allow(non_camel_case_types)]
81struct svfloat32x2_t(svfloat32_t, svfloat32_t);
82
83#[rustc_scalable_vector(2)]
84#[allow(non_camel_case_types)]
85struct svfloat64_t(f64);
86
87#[rustc_scalable_vector]
88#[allow(non_camel_case_types)]
89struct svfloat64x2_t(svfloat64_t, svfloat64_t);
90
91#[target_feature(enable = "sve")]
92pub fn locals() {
93 // CHECK-DAG: name: "svint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
94 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2:[0-9]+]])
95 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
96 // CHECK-DAG: ![[ELTS8x2]] = !{![[REALELTS8x2:[0-9]+]]}
97 // CHECK-DAG: ![[REALELTS8x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 16, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
98 let s8: svint8x2_t;
99
100 // CHECK-DAG: name: "svuint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
101 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2]])
102 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
103 let u8: svuint8x2_t;
104
105 // CHECK-DAG: name: "svint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
106 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2:[0-9]+]])
107 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
108 // CHECK-DAG: ![[ELTS16x2]] = !{![[REALELTS16x2:[0-9]+]]}
109 // CHECK-DAG: ![[REALELTS16x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
110 let s16: svint16x2_t;
111
112 // CHECK-DAG: name: "svuint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
113 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2]])
114 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
115 let u16: svuint16x2_t;
116
117 // CHECK-DAG: name: "svint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
118 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2:[0-9]+]])
119 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
120 // CHECK-DAG: ![[ELTS32x2]] = !{![[REALELTS32x2:[0-9]+]]}
121 // CHECK-DAG: ![[REALELTS32x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
122 let s32: svint32x2_t;
123
124 // CHECK-DAG: name: "svuint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
125 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]])
126 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
127 let u32: svuint32x2_t;
128
129 // CHECK-DAG: name: "svint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
130 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64:[0-9]+]])
131 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
132 // CHECK-DAG: ![[ELTS1x2_64]] = !{![[REALELTS1x2_64:[0-9]+]]}
133 // CHECK-DAG: ![[REALELTS1x2_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
134 let s64: svint64x2_t;
135
136 // CHECK-DAG: name: "svuint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
137 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]])
138 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
139 let u64: svuint64x2_t;
140
141 // CHECK: name: "svfloat32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
142 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]])
143 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
144 let f32: svfloat32x2_t;
145
146 // CHECK: name: "svfloat64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
147 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]])
148 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
149 let f64: svfloat64x2_t;
150}
tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs created+150
...@@ -0,0 +1,150 @@
1//@ only-aarch64
2//@ only-linux
3//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
4
5#![crate_type = "lib"]
6#![allow(incomplete_features, internal_features)]
7#![feature(rustc_attrs)]
8
9// Test that we generate the correct debuginfo for scalable vector types.
10
11#[rustc_scalable_vector(16)]
12#[allow(non_camel_case_types)]
13struct svint8_t(i8);
14
15#[rustc_scalable_vector]
16#[allow(non_camel_case_types)]
17struct svint8x3_t(svint8_t, svint8_t, svint8_t);
18
19#[rustc_scalable_vector(16)]
20#[allow(non_camel_case_types)]
21struct svuint8_t(u8);
22
23#[rustc_scalable_vector]
24#[allow(non_camel_case_types)]
25struct svuint8x3_t(svuint8_t, svuint8_t, svuint8_t);
26
27#[rustc_scalable_vector(8)]
28#[allow(non_camel_case_types)]
29struct svint16_t(i16);
30
31#[rustc_scalable_vector]
32#[allow(non_camel_case_types)]
33struct svint16x3_t(svint16_t, svint16_t, svint16_t);
34
35#[rustc_scalable_vector(8)]
36#[allow(non_camel_case_types)]
37struct svuint16_t(u16);
38
39#[rustc_scalable_vector]
40#[allow(non_camel_case_types)]
41struct svuint16x3_t(svuint16_t, svuint16_t, svuint16_t);
42
43#[rustc_scalable_vector(4)]
44#[allow(non_camel_case_types)]
45struct svint32_t(i32);
46
47#[rustc_scalable_vector]
48#[allow(non_camel_case_types)]
49struct svint32x3_t(svint32_t, svint32_t, svint32_t);
50
51#[rustc_scalable_vector(4)]
52#[allow(non_camel_case_types)]
53struct svuint32_t(u32);
54
55#[rustc_scalable_vector]
56#[allow(non_camel_case_types)]
57struct svuint32x3_t(svuint32_t, svuint32_t, svuint32_t);
58
59#[rustc_scalable_vector(2)]
60#[allow(non_camel_case_types)]
61struct svint64_t(i64);
62
63#[rustc_scalable_vector]
64#[allow(non_camel_case_types)]
65struct svint64x3_t(svint64_t, svint64_t, svint64_t);
66
67#[rustc_scalable_vector(2)]
68#[allow(non_camel_case_types)]
69struct svuint64_t(u64);
70
71#[rustc_scalable_vector]
72#[allow(non_camel_case_types)]
73struct svuint64x3_t(svuint64_t, svuint64_t, svuint64_t);
74
75#[rustc_scalable_vector(4)]
76#[allow(non_camel_case_types)]
77struct svfloat32_t(f32);
78
79#[rustc_scalable_vector]
80#[allow(non_camel_case_types)]
81struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t);
82
83#[rustc_scalable_vector(2)]
84#[allow(non_camel_case_types)]
85struct svfloat64_t(f64);
86
87#[rustc_scalable_vector]
88#[allow(non_camel_case_types)]
89struct svfloat64x3_t(svfloat64_t, svfloat64_t, svfloat64_t);
90
91#[target_feature(enable = "sve")]
92pub fn locals() {
93 // CHECK-DAG: name: "svint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
94 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3:[0-9]+]])
95 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
96 // CHECK-DAG: ![[ELTS8x3]] = !{![[REALELTS8x3:[0-9]+]]}
97 // CHECK-DAG: ![[REALELTS8x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 24, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
98 let s8: svint8x3_t;
99
100 // CHECK-DAG: name: "svuint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
101 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3]])
102 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
103 let u8: svuint8x3_t;
104
105 // CHECK-DAG: name: "svint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
106 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3:[0-9]+]])
107 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
108 // CHECK-DAG: ![[ELTS16x3]] = !{![[REALELTS16x3:[0-9]+]]}
109 // CHECK-DAG: ![[REALELTS16x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 12, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
110 let s16: svint16x3_t;
111
112 // CHECK-DAG: name: "svuint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
113 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3]])
114 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
115 let u16: svuint16x3_t;
116
117 // CHECK-DAG: name: "svint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
118 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3:[0-9]+]])
119 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
120 // CHECK-DAG: ![[ELTS32x3]] = !{![[REALELTS32x3:[0-9]+]]}
121 // CHECK-DAG: ![[REALELTS32x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 6, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
122 let s32: svint32x3_t;
123
124 // CHECK-DAG: name: "svuint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
125 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]])
126 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
127 let u32: svuint32x3_t;
128
129 // CHECK-DAG: name: "svint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
130 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64:[0-9]+]])
131 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
132 // CHECK-DAG: ![[ELTS1x3_64]] = !{![[REALELTS1x3_64:[0-9]+]]}
133 // CHECK-DAG: ![[REALELTS1x3_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 3, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
134 let s64: svint64x3_t;
135
136 // CHECK-DAG: name: "svuint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
137 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]])
138 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
139 let u64: svuint64x3_t;
140
141 // CHECK: name: "svfloat32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
142 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]])
143 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
144 let f32: svfloat32x3_t;
145
146 // CHECK: name: "svfloat64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
147 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]])
148 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
149 let f64: svfloat64x3_t;
150}
tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs created+150
...@@ -0,0 +1,150 @@
1//@ only-aarch64
2//@ only-linux
3//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
4
5#![crate_type = "lib"]
6#![allow(incomplete_features, internal_features)]
7#![feature(rustc_attrs)]
8
9// Test that we generate the correct debuginfo for scalable vector types.
10
11#[rustc_scalable_vector(16)]
12#[allow(non_camel_case_types)]
13struct svint8_t(i8);
14
15#[rustc_scalable_vector]
16#[allow(non_camel_case_types)]
17struct svint8x4_t(svint8_t, svint8_t, svint8_t, svint8_t);
18
19#[rustc_scalable_vector(16)]
20#[allow(non_camel_case_types)]
21struct svuint8_t(u8);
22
23#[rustc_scalable_vector]
24#[allow(non_camel_case_types)]
25struct svuint8x4_t(svuint8_t, svuint8_t, svuint8_t, svuint8_t);
26
27#[rustc_scalable_vector(8)]
28#[allow(non_camel_case_types)]
29struct svint16_t(i16);
30
31#[rustc_scalable_vector]
32#[allow(non_camel_case_types)]
33struct svint16x4_t(svint16_t, svint16_t, svint16_t, svint16_t);
34
35#[rustc_scalable_vector(8)]
36#[allow(non_camel_case_types)]
37struct svuint16_t(u16);
38
39#[rustc_scalable_vector]
40#[allow(non_camel_case_types)]
41struct svuint16x4_t(svuint16_t, svuint16_t, svuint16_t, svuint16_t);
42
43#[rustc_scalable_vector(4)]
44#[allow(non_camel_case_types)]
45struct svint32_t(i32);
46
47#[rustc_scalable_vector]
48#[allow(non_camel_case_types)]
49struct svint32x4_t(svint32_t, svint32_t, svint32_t, svint32_t);
50
51#[rustc_scalable_vector(4)]
52#[allow(non_camel_case_types)]
53struct svuint32_t(u32);
54
55#[rustc_scalable_vector]
56#[allow(non_camel_case_types)]
57struct svuint32x4_t(svuint32_t, svuint32_t, svuint32_t, svuint32_t);
58
59#[rustc_scalable_vector(2)]
60#[allow(non_camel_case_types)]
61struct svint64_t(i64);
62
63#[rustc_scalable_vector]
64#[allow(non_camel_case_types)]
65struct svint64x4_t(svint64_t, svint64_t, svint64_t, svint64_t);
66
67#[rustc_scalable_vector(2)]
68#[allow(non_camel_case_types)]
69struct svuint64_t(u64);
70
71#[rustc_scalable_vector]
72#[allow(non_camel_case_types)]
73struct svuint64x4_t(svuint64_t, svuint64_t, svuint64_t, svuint64_t);
74
75#[rustc_scalable_vector(4)]
76#[allow(non_camel_case_types)]
77struct svfloat32_t(f32);
78
79#[rustc_scalable_vector]
80#[allow(non_camel_case_types)]
81struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t);
82
83#[rustc_scalable_vector(2)]
84#[allow(non_camel_case_types)]
85struct svfloat64_t(f64);
86
87#[rustc_scalable_vector]
88#[allow(non_camel_case_types)]
89struct svfloat64x4_t(svfloat64_t, svfloat64_t, svfloat64_t, svfloat64_t);
90
91#[target_feature(enable = "sve")]
92pub fn locals() {
93 // CHECK-DAG: name: "svint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
94 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4:[0-9]+]])
95 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
96 // CHECK-DAG: ![[ELTS8x4]] = !{![[REALELTS8x4:[0-9]+]]}
97 // CHECK-DAG: ![[REALELTS8x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 32, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
98 let s8: svint8x4_t;
99
100 // CHECK-DAG: name: "svuint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
101 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4]])
102 // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
103 let u8: svuint8x4_t;
104
105 // CHECK-DAG: name: "svint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
106 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4:[0-9]+]])
107 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
108 // CHECK-DAG: ![[ELTS16x4]] = !{![[REALELTS16x4:[0-9]+]]}
109 // CHECK-DAG: ![[REALELTS16x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 16, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
110 let s16: svint16x4_t;
111
112 // CHECK-DAG: name: "svuint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
113 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4]])
114 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
115 let u16: svuint16x4_t;
116
117 // CHECK-DAG: name: "svint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
118 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4:[0-9]+]])
119 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
120 // CHECK-DAG: ![[ELTS32x4]] = !{![[REALELTS32x4:[0-9]+]]}
121 // CHECK-DAG: ![[REALELTS32x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
122 let s32: svint32x4_t;
123
124 // CHECK-DAG: name: "svuint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
125 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]])
126 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
127 let u32: svuint32x4_t;
128
129 // CHECK-DAG: name: "svint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
130 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64:[0-9]+]])
131 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
132 // CHECK-DAG: ![[ELTS1x4_64]] = !{![[REALELTS1x4_64:[0-9]+]]}
133 // CHECK-DAG: ![[REALELTS1x4_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
134 let s64: svint64x4_t;
135
136 // CHECK-DAG: name: "svuint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
137 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]])
138 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
139 let u64: svuint64x4_t;
140
141 // CHECK: name: "svfloat32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
142 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]])
143 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
144 let f32: svfloat32x4_t;
145
146 // CHECK: name: "svfloat64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
147 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]])
148 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
149 let f64: svfloat64x4_t;
150}
tests/codegen-llvm/scalable-vectors/debuginfo.rs created+124
...@@ -0,0 +1,124 @@
1// ignore-tidy-linelength
2//@ only-aarch64
3//@ only-linux
4//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
5//@ revisions: POST-LLVM-22 PRE-LLVM-22
6//@ [PRE-LLVM-22] max-llvm-major-version: 21
7//@ [POST-LLVM-22] min-llvm-version: 22
8
9#![crate_type = "lib"]
10#![allow(incomplete_features, internal_features)]
11#![feature(rustc_attrs)]
12
13// Test that we generate the correct debuginfo for scalable vector types.
14
15#[rustc_scalable_vector(16)]
16#[allow(non_camel_case_types)]
17struct svbool_t(bool);
18
19#[rustc_scalable_vector(16)]
20#[allow(non_camel_case_types)]
21struct svint8_t(i8);
22
23#[rustc_scalable_vector(16)]
24#[allow(non_camel_case_types)]
25struct svuint8_t(u8);
26
27#[rustc_scalable_vector(8)]
28#[allow(non_camel_case_types)]
29struct svint16_t(i16);
30
31#[rustc_scalable_vector(8)]
32#[allow(non_camel_case_types)]
33struct svuint16_t(u16);
34
35#[rustc_scalable_vector(4)]
36#[allow(non_camel_case_types)]
37struct svint32_t(i32);
38
39#[rustc_scalable_vector(4)]
40#[allow(non_camel_case_types)]
41struct svuint32_t(u32);
42
43#[rustc_scalable_vector(2)]
44#[allow(non_camel_case_types)]
45struct svint64_t(i64);
46
47#[rustc_scalable_vector(2)]
48#[allow(non_camel_case_types)]
49struct svuint64_t(u64);
50
51#[rustc_scalable_vector(4)]
52#[allow(non_camel_case_types)]
53struct svfloat32_t(f32);
54
55#[rustc_scalable_vector(2)]
56#[allow(non_camel_case_types)]
57struct svfloat64_t(f64);
58
59#[target_feature(enable = "sve")]
60pub fn locals() {
61 // CHECK-DAG: name: "svbool_t",{{.*}}, baseType: ![[CT1:[0-9]+]]
62 // PRE-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]])
63 // POST-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]], bitStride: i64 1)
64 // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
65 // CHECK-DAG: ![[ELTS8]] = !{![[REALELTS8:[0-9]+]]}
66 // CHECK-DAG: ![[REALELTS8]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
67 let b8: svbool_t;
68
69 // CHECK-DAG: name: "svint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
70 // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYS8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]])
71 // CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
72 let s8: svint8_t;
73
74 // PRE-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT1:[0-9]+]]
75 // POST-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
76 // POST-LLVM-22-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8]])
77 let u8: svuint8_t;
78
79 // CHECK-DAG: name: "svint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
80 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16:[0-9]+]])
81 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
82 // CHECK-DAG: ![[ELTS16]] = !{![[REALELTS16:[0-9]+]]}
83 // CHECK-DAG: ![[REALELTS16]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
84 let s16: svint16_t;
85
86 // CHECK-DAG: name: "svuint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
87 // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16]])
88 // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
89 let u16: svuint16_t;
90
91 // CHECK-DAG: name: "svint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
92 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32:[0-9]+]])
93 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
94 // CHECK-DAG: ![[ELTS32]] = !{![[REALELTS32:[0-9]+]]}
95 // CHECK-DAG: ![[REALELTS32]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
96 let s32: svint32_t;
97
98 // CHECK-DAG: name: "svuint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
99 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]])
100 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
101 let u32: svuint32_t;
102
103 // CHECK-DAG: name: "svint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
104 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64:[0-9]+]])
105 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
106 // CHECK-DAG: ![[ELTS64]] = !{![[REALELTS64:[0-9]+]]}
107 // CHECK-DAG: ![[REALELTS64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 1, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
108 let s64: svint64_t;
109
110 // CHECK-DAG: name: "svuint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
111 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]])
112 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
113 let u64: svuint64_t;
114
115 // CHECK: name: "svfloat32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
116 // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]])
117 // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
118 let f32: svfloat32_t;
119
120 // CHECK: name: "svfloat64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
121 // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]])
122 // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
123 let f64: svfloat64_t;
124}
tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs created+100
...@@ -0,0 +1,100 @@
1//@ build-pass
2//@ only-aarch64
3#![crate_type = "lib"]
4#![allow(incomplete_features, internal_features)]
5#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)]
6
7// Tests that tuples of scalable vectors are passed as immediates and that the intrinsics for
8// creating/getting/setting tuples of scalable vectors generate the correct assembly
9
10#[derive(Copy, Clone)]
11#[rustc_scalable_vector(4)]
12#[allow(non_camel_case_types)]
13pub struct svfloat32_t(f32);
14
15#[derive(Copy, Clone)]
16#[rustc_scalable_vector]
17#[allow(non_camel_case_types)]
18pub struct svfloat32x2_t(svfloat32_t, svfloat32_t);
19
20#[derive(Copy, Clone)]
21#[rustc_scalable_vector]
22#[allow(non_camel_case_types)]
23pub struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t);
24
25#[derive(Copy, Clone)]
26#[rustc_scalable_vector]
27#[allow(non_camel_case_types)]
28pub struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t);
29
30#[inline(never)]
31#[target_feature(enable = "sve")]
32pub fn svdup_n_f32(op: f32) -> svfloat32_t {
33 extern "C" {
34 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4f32")]
35 fn _svdup_n_f32(op: f32) -> svfloat32_t;
36 }
37 unsafe { _svdup_n_f32(op) }
38}
39
40// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float> } @svcreate2_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1)
41#[no_mangle]
42#[target_feature(enable = "sve")]
43pub fn svcreate2_f32(x0: svfloat32_t, x1: svfloat32_t) -> svfloat32x2_t {
44 // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0
45 // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1
46 unsafe { std::intrinsics::simd::scalable::sve_tuple_create2(x0, x1) }
47}
48
49// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @svcreate3_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1, <vscale x 4 x float> %x2)
50#[no_mangle]
51#[target_feature(enable = "sve")]
52pub fn svcreate3_f32(x0: svfloat32_t, x1: svfloat32_t, x2: svfloat32_t) -> svfloat32x3_t {
53 // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate3_f32
54 // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0
55 // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1
56 // CHECK-NEXT: %3 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %2, <vscale x 4 x float> %x2, 2
57 unsafe { std::intrinsics::simd::scalable::sve_tuple_create3(x0, x1, x2) }
58}
59
60// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @svcreate4_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1, <vscale x 4 x float> %x2, <vscale x 4 x float> %x3)
61#[no_mangle]
62#[target_feature(enable = "sve")]
63pub fn svcreate4_f32(
64 x0: svfloat32_t,
65 x1: svfloat32_t,
66 x2: svfloat32_t,
67 x3: svfloat32_t,
68) -> svfloat32x4_t {
69 // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate4_f32
70 // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0
71 // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1
72 // CHECK-NEXT: %3 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %2, <vscale x 4 x float> %x2, 2
73 // CHECK-NEXT: %4 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %3, <vscale x 4 x float> %x3, 3
74 unsafe { std::intrinsics::simd::scalable::sve_tuple_create4(x0, x1, x2, x3) }
75}
76
77// CHECK: define <vscale x 4 x float> @svget2_f32({ <vscale x 4 x float>, <vscale x 4 x float> } %tup)
78#[no_mangle]
79#[target_feature(enable = "sve")]
80pub fn svget2_f32<const IDX: i32>(tup: svfloat32x2_t) -> svfloat32_t {
81 // CHECK: %1 = extractvalue { <vscale x 4 x float>, <vscale x 4 x float> } %tup, 0
82 unsafe { std::intrinsics::simd::scalable::sve_tuple_get::<_, _, { IDX }>(tup) }
83}
84
85// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float> } @svset2_f32({ <vscale x 4 x float>, <vscale x 4 x float> } %tup, <vscale x 4 x float> %x)
86#[no_mangle]
87#[target_feature(enable = "sve")]
88pub fn svset2_f32<const IDX: i32>(tup: svfloat32x2_t, x: svfloat32_t) -> svfloat32x2_t {
89 // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } %tup, <vscale x 4 x float> %x, 0
90 unsafe { std::intrinsics::simd::scalable::sve_tuple_set::<_, _, { IDX }>(tup, x) }
91}
92
93// This function exists only so there are calls to the generic functions
94#[target_feature(enable = "sve")]
95pub fn test() {
96 let x = svdup_n_f32(2f32);
97 let tup = svcreate2_f32(x, x);
98 let x = svget2_f32::<0>(tup);
99 let tup = svset2_f32::<0>(tup, x);
100}
tests/ui/const-generics/generic_const_exprs/escaping-late-bound-region-in-canonical-ice-113870.rs created+24
...@@ -0,0 +1,24 @@
1//! Regression test for https://github.com/rust-lang/rust/issues/113870
2
3#![feature(generic_const_exprs)]
4#![allow(incomplete_features)]
5
6const fn allow<'b, 'b>() -> usize
7//~^ ERROR the name `'b` is already used for a generic parameter in this item's generic parameters
8where
9 for<'b> [u8; foo::<'a, 'b>()]: Sized,
10 //~^ ERROR lifetime name `'b` shadows a lifetime name that is already in scope
11 //~| ERROR use of undeclared lifetime name `'a`
12 //~| ERROR cannot capture late-bound lifetime in constant
13{
14 4
15}
16
17const fn foo<'a, 'b>() -> usize
18where
19 &'a (): Sized,
20 &'b (): Sized,
21{
22 4
23}
24//~^ ERROR `main` function not found in crate
tests/ui/const-generics/generic_const_exprs/escaping-late-bound-region-in-canonical-ice-113870.stderr created+52
...@@ -0,0 +1,52 @@
1error[E0403]: the name `'b` is already used for a generic parameter in this item's generic parameters
2 --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:6:20
3 |
4LL | const fn allow<'b, 'b>() -> usize
5 | -- ^^ already used
6 | |
7 | first use of `'b`
8
9error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope
10 --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:9:9
11 |
12LL | const fn allow<'b, 'b>() -> usize
13 | -- first declared here
14...
15LL | for<'b> [u8; foo::<'a, 'b>()]: Sized,
16 | ^^ lifetime `'b` already in scope
17
18error[E0261]: use of undeclared lifetime name `'a`
19 --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:9:24
20 |
21LL | for<'b> [u8; foo::<'a, 'b>()]: Sized,
22 | ^^ undeclared lifetime
23 |
24 = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
25help: consider making the bound lifetime-generic with a new `'a` lifetime
26 |
27LL | for<'a, 'b> [u8; foo::<'a, 'b>()]: Sized,
28 | +++
29help: consider introducing lifetime `'a` here
30 |
31LL | const fn allow<'a, 'b, 'b>() -> usize
32 | +++
33
34error[E0601]: `main` function not found in crate `escaping_late_bound_region_in_canonical_ice_113870`
35 --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:23:2
36 |
37LL | }
38 | ^ consider adding a `main` function to `$DIR/escaping-late-bound-region-in-canonical-ice-113870.rs`
39
40error: cannot capture late-bound lifetime in constant
41 --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:9:28
42 |
43LL | const fn allow<'b, 'b>() -> usize
44 | -- lifetime defined here
45...
46LL | for<'b> [u8; foo::<'a, 'b>()]: Sized,
47 | ^^
48
49error: aborting due to 5 previous errors
50
51Some errors have detailed explanations: E0261, E0403, E0496, E0601.
52For more information about an error, try `rustc --explain E0261`.
tests/ui/const-generics/generic_const_exprs/ice-wrapper-impl-trait-with-const-bound-118278.rs created+28
...@@ -0,0 +1,28 @@
1//! Regression test for https://github.com/rust-lang/rust/issues/118278
2
3//@ check-pass
4
5#![allow(incomplete_features)]
6#![feature(generic_const_exprs)]
7
8pub trait Foo {
9 const SIZE: usize;
10}
11
12impl Foo for u64 {
13 const SIZE: usize = 8;
14}
15
16pub struct Wrapper<T>
17where
18 T: Foo,
19 [(); T::SIZE]:,
20{
21 pub t: T,
22}
23
24pub fn bar() -> Wrapper<impl Foo> {
25 Wrapper { t: 10 }
26}
27
28fn main() {}
tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.rs created+17
...@@ -0,0 +1,17 @@
1//! Ensure we enforce `min_adt_const_params` rules on any adt `ConstParamTy_`
2//! implementation unless `adt_const_params` feature is used.
3#![allow(incomplete_features)]
4#![feature(const_param_ty_trait)]
5
6use std::marker::ConstParamTy_;
7
8#[derive(PartialEq, Eq)]
9pub struct Fumo {
10 cirno: i32,
11 pub(crate) reimu: i32
12}
13
14impl ConstParamTy_ for Fumo {}
15 //~^ ERROR: the trait `ConstParamTy` may not be implemented for this struct
16
17fn main() {}
tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.stderr created+8
...@@ -0,0 +1,8 @@
1error: the trait `ConstParamTy` may not be implemented for this struct
2 --> $DIR/const_param_ty-on-adt-without-adt-gate.rs:14:24
3 |
4LL | impl ConstParamTy_ for Fumo {}
5 | ^^^^ struct fields are less visible than the struct
6
7error: aborting due to 1 previous error
8
tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.rs created+35
...@@ -0,0 +1,35 @@
1//! Ensure min_adt_const_params enforce
2//! struct's visibility on its fields
3#![allow(incomplete_features)]
4#![feature(min_adt_const_params)]
5#![feature(const_param_ty_trait)]
6
7use std::marker::ConstParamTy_;
8
9#[derive(PartialEq, Eq)]
10pub struct Meowl {
11 pub public: i32,
12 private: i32
13}
14
15#[derive(PartialEq, Eq)]
16pub struct Meowl2 {
17 pub a: i32,
18 pub b: i32
19}
20
21#[derive(PartialEq, Eq)]
22pub(crate) struct Meowl3 {
23 pub(crate) a: i32,
24 pub b: i32
25}
26
27impl ConstParamTy_ for Meowl {}
28 //~^ ERROR the trait `ConstParamTy` may not be implemented for this struct
29impl ConstParamTy_ for Meowl2 {}
30impl ConstParamTy_ for Meowl3 {}
31
32fn something<const N: Meowl2>() {}
33fn something2<const N: Meowl3>() {}
34
35fn main() {}
tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.stderr created+8
...@@ -0,0 +1,8 @@
1error: the trait `ConstParamTy` may not be implemented for this struct
2 --> $DIR/min_adt_const_params-gate-fail.rs:27:24
3 |
4LL | impl ConstParamTy_ for Meowl {}
5 | ^^^^^ struct fields are less visible than the struct
6
7error: aborting due to 1 previous error
8
tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate.rs created+18
...@@ -0,0 +1,18 @@
1// gate-test-min_adt_const_params
2//@run-pass
3#![feature(min_adt_const_params, const_param_ty_trait)]
4#![allow(incomplete_features, dead_code)]
5
6use std::marker::ConstParamTy_;
7
8#[derive(PartialEq, Eq)]
9pub struct Meowl {
10 pub public: i32,
11 pub also_public: i32
12}
13
14impl ConstParamTy_ for Meowl {}
15
16fn meoow<const N: Meowl>() {}
17
18fn main() {}
tests/ui/const-generics/min_adt_const_params/type-field-more-visible-than-type.rs created+12
...@@ -0,0 +1,12 @@
1//@run-pass
2#![feature(min_adt_const_params)]
3
4use std::marker::ConstParamTy;
5
6#[derive(ConstParamTy, Eq, PartialEq)]
7#[allow(dead_code)]
8struct Foo {
9 pub field: u32,
10}
11
12fn main() {}
tests/ui/privacy/private-field-deref-confusion-issue-149546.rs created+88
...@@ -0,0 +1,88 @@
1// Field lookup still resolves to the public field on the Deref target, but
2// follow-up diagnostics should explain that the original type has a same-named
3// private field with a different type.
4//@ dont-require-annotations: ERROR
5
6mod structs {
7 pub struct A {
8 field: usize,
9 b: B,
10 }
11
12 pub struct B {
13 pub field: bool,
14 }
15
16 impl std::ops::Deref for A {
17 type Target = B;
18
19 fn deref(&self) -> &Self::Target {
20 &self.b
21 }
22 }
23}
24
25use structs::A;
26
27fn takes_usize(_: usize) {}
28
29trait Marker {}
30
31impl Marker for usize {}
32
33struct Wrapper(i32);
34
35impl<T: Marker> std::ops::Add<T> for Wrapper {
36 type Output = ();
37
38 fn add(self, _: T) {}
39}
40
41fn by_value(a: A) {
42 a.field + 5;
43}
44
45fn by_ref(a: &A) {
46 a.field + 5;
47}
48
49fn rhs_by_value(a: A) {
50 5 + a.field;
51}
52
53fn rhs_by_ref(a: &A) {
54 5 + a.field;
55}
56
57fn rhs_assign_op_by_value(a: A) {
58 let mut n = 5;
59 n += a.field;
60}
61
62fn rhs_assign_op_by_ref(a: &A) {
63 let mut n = 5;
64 n += a.field;
65}
66
67fn rhs_nested_obligation(a: A) {
68 Wrapper(5) + a.field;
69}
70
71fn method_call(a: A) {
72 a.field.count_ones();
73}
74
75fn type_mismatch(a: A) {
76 let value: usize = a.field;
77 eprintln!("value: {value}");
78}
79
80fn function_arg(a: A) {
81 takes_usize(a.field);
82}
83
84fn return_value(a: &A) -> usize {
85 a.field
86}
87
88fn main() {}
tests/ui/privacy/private-field-deref-confusion-issue-149546.stderr created+317
...@@ -0,0 +1,317 @@
1error[E0369]: cannot add `{integer}` to `bool`
2 --> $DIR/private-field-deref-confusion-issue-149546.rs:42:13
3 |
4LL | a.field + 5;
5 | ------- ^ - {integer}
6 | |
7 | bool
8 |
9note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
10 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
11 |
12LL | pub struct A {
13 | ^ in this struct
14LL | field: usize,
15 | ----- if this field wasn't private, it would be accessible
16...
17LL | pub struct B {
18 | - this struct is accessible through auto-deref
19LL | pub field: bool,
20 | ----- this is the field that was accessed
21...
22LL | impl std::ops::Deref for A {
23 | -------------------------- the field was accessed through this `Deref`
24
25error[E0369]: cannot add `{integer}` to `bool`
26 --> $DIR/private-field-deref-confusion-issue-149546.rs:46:13
27 |
28LL | a.field + 5;
29 | ------- ^ - {integer}
30 | |
31 | bool
32 |
33note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
34 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
35 |
36LL | pub struct A {
37 | ^ in this struct
38LL | field: usize,
39 | ----- if this field wasn't private, it would be accessible
40...
41LL | pub struct B {
42 | - this struct is accessible through auto-deref
43LL | pub field: bool,
44 | ----- this is the field that was accessed
45...
46LL | impl std::ops::Deref for A {
47 | -------------------------- the field was accessed through this `Deref`
48
49error[E0277]: cannot add `bool` to `{integer}`
50 --> $DIR/private-field-deref-confusion-issue-149546.rs:50:7
51 |
52LL | 5 + a.field;
53 | ^ no implementation for `{integer} + bool`
54 |
55 = help: the trait `Add<bool>` is not implemented for `{integer}`
56note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
57 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
58 |
59LL | pub struct A {
60 | ^ in this struct
61LL | field: usize,
62 | ----- if this field wasn't private, it would be accessible
63...
64LL | pub struct B {
65 | - this struct is accessible through auto-deref
66LL | pub field: bool,
67 | ----- this is the field that was accessed
68...
69LL | impl std::ops::Deref for A {
70 | -------------------------- the field was accessed through this `Deref`
71 = help: the following other types implement trait `Add<Rhs>`:
72 `&f128` implements `Add<f128>`
73 `&f128` implements `Add`
74 `&f16` implements `Add<f16>`
75 `&f16` implements `Add`
76 `&f32` implements `Add<f32>`
77 `&f32` implements `Add`
78 `&f64` implements `Add<f64>`
79 `&f64` implements `Add`
80 and 56 others
81
82error[E0277]: cannot add `bool` to `{integer}`
83 --> $DIR/private-field-deref-confusion-issue-149546.rs:54:7
84 |
85LL | 5 + a.field;
86 | ^ no implementation for `{integer} + bool`
87 |
88 = help: the trait `Add<bool>` is not implemented for `{integer}`
89note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
90 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
91 |
92LL | pub struct A {
93 | ^ in this struct
94LL | field: usize,
95 | ----- if this field wasn't private, it would be accessible
96...
97LL | pub struct B {
98 | - this struct is accessible through auto-deref
99LL | pub field: bool,
100 | ----- this is the field that was accessed
101...
102LL | impl std::ops::Deref for A {
103 | -------------------------- the field was accessed through this `Deref`
104 = help: the following other types implement trait `Add<Rhs>`:
105 `&f128` implements `Add<f128>`
106 `&f128` implements `Add`
107 `&f16` implements `Add<f16>`
108 `&f16` implements `Add`
109 `&f32` implements `Add<f32>`
110 `&f32` implements `Add`
111 `&f64` implements `Add<f64>`
112 `&f64` implements `Add`
113 and 56 others
114
115error[E0277]: cannot add-assign `bool` to `{integer}`
116 --> $DIR/private-field-deref-confusion-issue-149546.rs:59:7
117 |
118LL | n += a.field;
119 | ^^ no implementation for `{integer} += bool`
120 |
121 = help: the trait `AddAssign<bool>` is not implemented for `{integer}`
122note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
123 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
124 |
125LL | pub struct A {
126 | ^ in this struct
127LL | field: usize,
128 | ----- if this field wasn't private, it would be accessible
129...
130LL | pub struct B {
131 | - this struct is accessible through auto-deref
132LL | pub field: bool,
133 | ----- this is the field that was accessed
134...
135LL | impl std::ops::Deref for A {
136 | -------------------------- the field was accessed through this `Deref`
137 = help: the following other types implement trait `AddAssign<Rhs>`:
138 `f128` implements `AddAssign<&f128>`
139 `f128` implements `AddAssign`
140 `f16` implements `AddAssign<&f16>`
141 `f16` implements `AddAssign`
142 `f32` implements `AddAssign<&f32>`
143 `f32` implements `AddAssign`
144 `f64` implements `AddAssign<&f64>`
145 `f64` implements `AddAssign`
146 and 24 others
147
148error[E0277]: cannot add-assign `bool` to `{integer}`
149 --> $DIR/private-field-deref-confusion-issue-149546.rs:64:7
150 |
151LL | n += a.field;
152 | ^^ no implementation for `{integer} += bool`
153 |
154 = help: the trait `AddAssign<bool>` is not implemented for `{integer}`
155note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
156 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
157 |
158LL | pub struct A {
159 | ^ in this struct
160LL | field: usize,
161 | ----- if this field wasn't private, it would be accessible
162...
163LL | pub struct B {
164 | - this struct is accessible through auto-deref
165LL | pub field: bool,
166 | ----- this is the field that was accessed
167...
168LL | impl std::ops::Deref for A {
169 | -------------------------- the field was accessed through this `Deref`
170 = help: the following other types implement trait `AddAssign<Rhs>`:
171 `f128` implements `AddAssign<&f128>`
172 `f128` implements `AddAssign`
173 `f16` implements `AddAssign<&f16>`
174 `f16` implements `AddAssign`
175 `f32` implements `AddAssign<&f32>`
176 `f32` implements `AddAssign`
177 `f64` implements `AddAssign<&f64>`
178 `f64` implements `AddAssign`
179 and 24 others
180
181error[E0277]: the trait bound `bool: Marker` is not satisfied
182 --> $DIR/private-field-deref-confusion-issue-149546.rs:68:16
183 |
184LL | Wrapper(5) + a.field;
185 | ^ the trait `Marker` is not implemented for `bool`
186 |
187note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
188 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
189 |
190LL | pub struct A {
191 | ^ in this struct
192LL | field: usize,
193 | ----- if this field wasn't private, it would be accessible
194...
195LL | pub struct B {
196 | - this struct is accessible through auto-deref
197LL | pub field: bool,
198 | ----- this is the field that was accessed
199...
200LL | impl std::ops::Deref for A {
201 | -------------------------- the field was accessed through this `Deref`
202help: the trait `Marker` is implemented for `usize`
203 --> $DIR/private-field-deref-confusion-issue-149546.rs:31:1
204 |
205LL | impl Marker for usize {}
206 | ^^^^^^^^^^^^^^^^^^^^^
207note: required for `Wrapper` to implement `Add<bool>`
208 --> $DIR/private-field-deref-confusion-issue-149546.rs:35:17
209 |
210LL | impl<T: Marker> std::ops::Add<T> for Wrapper {
211 | ------ ^^^^^^^^^^^^^^^^ ^^^^^^^
212 | |
213 | unsatisfied trait bound introduced here
214
215error[E0599]: no method named `count_ones` found for type `bool` in the current scope
216 --> $DIR/private-field-deref-confusion-issue-149546.rs:72:13
217 |
218LL | a.field.count_ones();
219 | ^^^^^^^^^^ method not found in `bool`
220 |
221note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
222 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
223 |
224LL | pub struct A {
225 | ^ in this struct
226LL | field: usize,
227 | ----- if this field wasn't private, it would be accessible
228...
229LL | pub struct B {
230 | - this struct is accessible through auto-deref
231LL | pub field: bool,
232 | ----- this is the field that was accessed
233...
234LL | impl std::ops::Deref for A {
235 | -------------------------- the field was accessed through this `Deref`
236
237error[E0308]: mismatched types
238 --> $DIR/private-field-deref-confusion-issue-149546.rs:76:24
239 |
240LL | let value: usize = a.field;
241 | ----- ^^^^^^^ expected `usize`, found `bool`
242 | |
243 | expected due to this
244 |
245note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
246 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
247 |
248LL | pub struct A {
249 | ^ in this struct
250LL | field: usize,
251 | ----- if this field wasn't private, it would be accessible
252...
253LL | pub struct B {
254 | - this struct is accessible through auto-deref
255LL | pub field: bool,
256 | ----- this is the field that was accessed
257...
258LL | impl std::ops::Deref for A {
259 | -------------------------- the field was accessed through this `Deref`
260
261error[E0308]: mismatched types
262 --> $DIR/private-field-deref-confusion-issue-149546.rs:81:17
263 |
264LL | takes_usize(a.field);
265 | ----------- ^^^^^^^ expected `usize`, found `bool`
266 | |
267 | arguments to this function are incorrect
268 |
269note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
270 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
271 |
272LL | pub struct A {
273 | ^ in this struct
274LL | field: usize,
275 | ----- if this field wasn't private, it would be accessible
276...
277LL | pub struct B {
278 | - this struct is accessible through auto-deref
279LL | pub field: bool,
280 | ----- this is the field that was accessed
281...
282LL | impl std::ops::Deref for A {
283 | -------------------------- the field was accessed through this `Deref`
284note: function defined here
285 --> $DIR/private-field-deref-confusion-issue-149546.rs:27:4
286 |
287LL | fn takes_usize(_: usize) {}
288 | ^^^^^^^^^^^ --------
289
290error[E0308]: mismatched types
291 --> $DIR/private-field-deref-confusion-issue-149546.rs:85:5
292 |
293LL | fn return_value(a: &A) -> usize {
294 | ----- expected `usize` because of return type
295LL | a.field
296 | ^^^^^^^ expected `usize`, found `bool`
297 |
298note: there is a field `field` on `A` with type `usize` but it is private; `field` from `B` was accessed through auto-deref instead
299 --> $DIR/private-field-deref-confusion-issue-149546.rs:7:16
300 |
301LL | pub struct A {
302 | ^ in this struct
303LL | field: usize,
304 | ----- if this field wasn't private, it would be accessible
305...
306LL | pub struct B {
307 | - this struct is accessible through auto-deref
308LL | pub field: bool,
309 | ----- this is the field that was accessed
310...
311LL | impl std::ops::Deref for A {
312 | -------------------------- the field was accessed through this `Deref`
313
314error: aborting due to 11 previous errors
315
316Some errors have detailed explanations: E0277, E0308, E0369, E0599.
317For more information about an error, try `rustc --explain E0277`.
tests/ui/scalable-vectors/cast-intrinsic.rs created+65
...@@ -0,0 +1,65 @@
1//@ check-pass
2//@ only-aarch64
3#![crate_type = "lib"]
4#![allow(incomplete_features, internal_features, improper_ctypes)]
5#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)]
6
7use std::intrinsics::simd::scalable::sve_cast;
8
9#[derive(Copy, Clone)]
10#[rustc_scalable_vector(16)]
11#[allow(non_camel_case_types)]
12pub struct svbool_t(bool);
13
14#[derive(Copy, Clone)]
15#[rustc_scalable_vector(2)]
16#[allow(non_camel_case_types)]
17pub struct svbool2_t(bool);
18
19#[derive(Copy, Clone)]
20#[rustc_scalable_vector(2)]
21#[allow(non_camel_case_types)]
22pub struct svint64_t(i64);
23
24#[derive(Copy, Clone)]
25#[rustc_scalable_vector(2)]
26#[allow(non_camel_case_types)]
27pub struct nxv2i16(i16);
28
29pub trait SveInto<T>: Sized {
30 unsafe fn sve_into(self) -> T;
31}
32
33impl SveInto<svbool2_t> for svbool_t {
34 #[target_feature(enable = "sve")]
35 unsafe fn sve_into(self) -> svbool2_t {
36 unsafe extern "C" {
37 #[cfg_attr(
38 target_arch = "aarch64",
39 link_name = concat!("llvm.aarch64.sve.convert.from.svbool.nxv2i1")
40 )]
41 fn convert_from_svbool(b: svbool_t) -> svbool2_t;
42 }
43 unsafe { convert_from_svbool(self) }
44 }
45}
46
47#[target_feature(enable = "sve")]
48pub unsafe fn svld1sh_gather_s64offset_s64(
49 pg: svbool_t,
50 base: *const i16,
51 offsets: svint64_t,
52) -> svint64_t {
53 unsafe extern "unadjusted" {
54 #[cfg_attr(
55 target_arch = "aarch64",
56 link_name = "llvm.aarch64.sve.ld1.gather.nxv2i16"
57 )]
58 fn _svld1sh_gather_s64offset_s64(
59 pg: svbool2_t,
60 base: *const i16,
61 offsets: svint64_t,
62 ) -> nxv2i16;
63 }
64 sve_cast(_svld1sh_gather_s64offset_s64(pg.sve_into(), base, offsets))
65}
tests/ui/simd/masked-load-store-check-fail.stderr+2-2
...@@ -21,7 +21,7 @@ LL | | Simd::<u8, 4>([9; 4]),...@@ -21,7 +21,7 @@ LL | | Simd::<u8, 4>([9; 4]),
21LL | | );21LL | | );
22 | |_________^22 | |_________^
23note: function defined here23note: function defined here
24 --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL24 --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL
2525
26error[E0308]: mismatched types26error[E0308]: mismatched types
27 --> $DIR/masked-load-store-check-fail.rs:25:1327 --> $DIR/masked-load-store-check-fail.rs:25:13
...@@ -46,7 +46,7 @@ LL | | default,...@@ -46,7 +46,7 @@ LL | | default,
46LL | | );46LL | | );
47 | |_________^47 | |_________^
48note: function defined here48note: function defined here
49 --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL49 --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL
5050
51error: aborting due to 2 previous errors51error: aborting due to 2 previous errors
5252
tests/ui/typeck/index-out-of-bounds-on-partial-cmp-ice-114056.rs created+12
...@@ -0,0 +1,12 @@
1//! Regression test for https://github.com/rust-lang/rust/issues/114056
2
3struct P<Q>(Q);
4
5impl<Q> P<Q> {
6 fn foo(&self) {
7 self.partial_cmp(())
8 //~^ ERROR the method `partial_cmp` exists for reference `&P<Q>`, but its trait bounds were not satisfied
9 }
10}
11
12fn main() {}
tests/ui/typeck/index-out-of-bounds-on-partial-cmp-ice-114056.stderr created+27
...@@ -0,0 +1,27 @@
1error[E0599]: the method `partial_cmp` exists for reference `&P<Q>`, but its trait bounds were not satisfied
2 --> $DIR/index-out-of-bounds-on-partial-cmp-ice-114056.rs:7:14
3 |
4LL | struct P<Q>(Q);
5 | ----------- doesn't satisfy `P<Q>: Iterator` or `P<Q>: PartialOrd<_>`
6...
7LL | self.partial_cmp(())
8 | ^^^^^^^^^^^ method cannot be called on `&P<Q>` due to unsatisfied trait bounds
9 |
10 = note: the following trait bounds were not satisfied:
11 `P<Q>: PartialOrd<_>`
12 which is required by `&P<Q>: PartialOrd<&_>`
13 `&P<Q>: Iterator`
14 which is required by `&mut &P<Q>: Iterator`
15 `P<Q>: Iterator`
16 which is required by `&mut P<Q>: Iterator`
17note: the trait `Iterator` must be implemented
18 --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
19help: consider annotating `P<Q>` with `#[derive(PartialEq, PartialOrd)]`
20 |
21LL + #[derive(PartialEq, PartialOrd)]
22LL | struct P<Q>(Q);
23 |
24
25error: aborting due to 1 previous error
26
27For more information about this error, try `rustc --explain E0599`.
triagebot.toml+1-1
...@@ -1077,7 +1077,7 @@ cc = ["@Amanieu", "@folkertdev", "@sayantn"]...@@ -1077,7 +1077,7 @@ cc = ["@Amanieu", "@folkertdev", "@sayantn"]
1077message = "Some changes occurred in `std_detect`"1077message = "Some changes occurred in `std_detect`"
1078cc = ["@Amanieu", "@folkertdev", "@sayantn"]1078cc = ["@Amanieu", "@folkertdev", "@sayantn"]
10791079
1080[mentions."library/core/src/intrinsics/simd.rs"]1080[mentions."library/core/src/intrinsics/simd/mod.rs"]
1081message = """1081message = """
1082Some changes occurred to the platform-builtins intrinsics. Make sure the1082Some changes occurred to the platform-builtins intrinsics. Make sure the
1083LLVM backend as well as portable-simd gets adapted for the changes.1083LLVM backend as well as portable-simd gets adapted for the changes.