| author | bors <bors@rust-lang.org> 2026-04-04 11:03:56 UTC |
| committer | bors <bors@rust-lang.org> 2026-04-04 11:03:56 UTC |
| log | 981cf69479ded5e2de0cf9e16111c19d65be0369 |
| tree | 3555e48972ab6a32026f7856e7f5f3e8580c81a2 |
| parent | 2972b5e59f1c5529b6ba770437812fd83ab4ebd4 |
| parent | 7a68d3fa0b5921475b36002c1c5974a1741713db |
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}; |
| 10 | 10 | ||
| 11 | use crate::{ | 11 | use 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 | }; |
| 16 | 16 | ||
| 17 | mod coroutine; | 17 | mod 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 | where | 209 | 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 | } |
| 215 | 221 | ||
| 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> { |
| 1526 | 1532 | ||
| 1527 | enum SimdVectorKind { | 1533 | enum 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 close | 1573 | // 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 | } |
| 1698 | 1698 | ||
| 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))] | ||
| 1702 | pub struct NumScalableVectors(pub u8); | ||
| 1703 | |||
| 1704 | impl 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 backend | 1721 | /// 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 | } |
| 2162 | 2189 | ||
| 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 | } |
| 2167 | 2194 |
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; |
| 3 | use rustc_errors::E0232; | 3 | use rustc_errors::E0232; |
| 4 | use rustc_hir::AttrPath; | 4 | use rustc_hir::AttrPath; |
| 5 | use rustc_hir::attrs::diagnostic::{ | 5 | use 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 | }; |
| 9 | use rustc_hir::lints::{AttributeLintKind, FormatWarning}; | 9 | use rustc_hir::lints::{AttributeLintKind, FormatWarning}; |
| 10 | use rustc_macros::Diagnostic; | 10 | use 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; | ||
| 96 | 95 | ||
| 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 | ret | 135 | 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; |
| 161 | 159 | ||
| 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 | } |
| 296 | 290 |
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; |
| 448 | 448 | ||
| 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; |
| 24 | use rustc_middle::bug; | 24 | use rustc_middle::bug; |
| 25 | use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; | 25 | use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; |
| 26 | use rustc_middle::ty::layout::{ | 26 | use rustc_middle::ty::layout::{ |
| 27 | FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, | 27 | FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, |
| 28 | LayoutOfHelpers, TyAndLayout, | ||
| 28 | }; | 29 | }; |
| 29 | use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; | 30 | use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; |
| 30 | use rustc_span::Span; | 31 | use 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 | } |
| 945 | 946 | ||
| 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 | } |
| 949 | 950 | ||
| 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 | } |
| 147 | 147 | ||
| 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; |
| 7 | pub(crate) mod gpu_offload; | 7 | pub(crate) mod gpu_offload; |
| 8 | 8 | ||
| 9 | use libc::{c_char, c_uint}; | 9 | use libc::{c_char, c_uint}; |
| 10 | use rustc_abi as abi; | 10 | use rustc_abi::{self as abi, Align, Size, WrappingRange}; |
| 11 | use rustc_abi::{Align, Size, WrappingRange}; | ||
| 12 | use rustc_codegen_ssa::MemFlags; | 11 | use rustc_codegen_ssa::MemFlags; |
| 13 | use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; | 12 | use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; |
| 14 | use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; | 13 | use 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 | } |
| 618 | 617 | ||
| 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 | }; | ||
| 629 | 622 | ||
| 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 | alloca | 626 | 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 | } |
| 161 | 161 | ||
| 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)] |
| 37 | pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000; | 37 | pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000; |
| 38 | #[allow(non_upper_case_globals)] | ||
| 39 | pub(crate) const DW_OP_constu: u64 = 0x10; | ||
| 40 | #[allow(non_upper_case_globals)] | ||
| 41 | pub(crate) const DW_OP_minus: u64 = 0x1c; | ||
| 42 | #[allow(non_upper_case_globals)] | ||
| 43 | pub(crate) const DW_OP_mul: u64 = 0x1e; | ||
| 44 | #[allow(non_upper_case_globals)] | ||
| 45 | pub(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)] |
| 40 | pub(crate) const DW_OP_stack_value: u64 = 0x9f; | 48 | pub(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}; |
| 3 | use std::hash::{Hash, Hasher}; | 3 | use std::hash::{Hash, Hasher}; |
| 4 | use std::path::PathBuf; | 4 | use std::path::PathBuf; |
| 5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
| 6 | use std::{iter, ptr}; | 6 | use std::{assert_matches, iter, ptr}; |
| 7 | 7 | ||
| 8 | use libc::{c_longlong, c_uint}; | 8 | use libc::{c_longlong, c_uint}; |
| 9 | use rustc_abi::{Align, Size}; | 9 | use rustc_abi::{Align, Layout, NumScalableVectors, Size}; |
| 10 | use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; | 10 | use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; |
| 11 | use rustc_codegen_ssa::traits::*; | 11 | use rustc_codegen_ssa::traits::*; |
| 12 | use rustc_hir::def::{CtorKind, DefKind}; | 12 | use 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 | }; |
| 18 | use rustc_middle::ty::{ | 18 | use rustc_middle::ty::{ |
| 19 | self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, | 19 | self, AdtDef, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, |
| 20 | }; | 20 | }; |
| 21 | use rustc_session::config::{self, DebugInfo, Lto}; | 21 | use rustc_session::config::{self, DebugInfo, Lto}; |
| 22 | use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene}; | 22 | use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene}; |
| 23 | use rustc_symbol_mangling::typeid_for_trait_ref; | 23 | use rustc_symbol_mangling::typeid_for_trait_ref; |
| 24 | use rustc_target::spec::DebuginfoKind; | 24 | use rustc_target::spec::{Arch, DebuginfoKind}; |
| 25 | use smallvec::smallvec; | 25 | use smallvec::smallvec; |
| 26 | use tracing::{debug, instrument}; | 26 | use tracing::{debug, instrument}; |
| 27 | 27 | ||
| ... | @@ -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 |
| 33 | use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit}; | 33 | use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit}; |
| 34 | use crate::common::{AsCCharPtr, CodegenCx}; | 34 | use crate::common::{AsCCharPtr, CodegenCx}; |
| 35 | use crate::debuginfo::metadata::type_map::build_type_with_children; | 35 | use crate::debuginfo::metadata::type_map::build_type_with_children; |
| 36 | use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind}; | 36 | use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind}; |
| 37 | use crate::debuginfo::{DIBuilderExt, dwarf_const}; | 37 | use crate::debuginfo::{DIBuilderExt, dwarf_const}; |
| 38 | use crate::llvm::debuginfo::{ | 38 | use 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 | None | 1053 | 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 | } | ||
| 1054 | 1070 | ||
| 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 | } |
| 1103 | 1119 | ||
| 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++. | ||
| 1137 | fn 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 | // Tuples | 1215 | // 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; |
| 3 | use std::{assert_matches, ptr}; | 3 | use std::{assert_matches, ptr}; |
| 4 | 4 | ||
| 5 | use rustc_abi::{ | 5 | use rustc_abi::{ |
| 6 | Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange, | 6 | Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size, |
| 7 | WrappingRange, | ||
| 7 | }; | 8 | }; |
| 8 | use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; | 9 | use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; |
| 9 | use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; | 10 | use 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 | } |
| 607 | 608 | ||
| 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_len | 2793 | out_len |
| 2663 | } | 2794 | } |
| 2664 | ); | 2795 | ); |
| 2665 | // casting cares about nominal type, not just structural type | 2796 | 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, |
| 2669 | 2800 | 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>( |
| 2925 | 2977 | ||
| 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`. | ||
| 2982 | fn 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 | ); |
| 2304 | 2304 | ||
| 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 | }; |
| 33 | 33 | ||
| 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::AArch64 | 439 | && 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 @@ |
| 1 | use std::ops::Deref as _; | ||
| 2 | |||
| 1 | use rustc_abi::{ | 3 | use 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 | } |
| 153 | 155 | ||
| 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 | } |
| 166 | 163 |
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; |
| 236 | 236 | ||
| 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; |
| 239 | 239 | ||
| 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 the | 589 | /// 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 | } |
| 24 | 23 | ||
| 25 | impl Directive { | 24 | impl 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, args | 67 | 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 | } |
| 97 | 93 | ||
| 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)] | ||
| 121 | pub enum AppendConstMessage { | ||
| 122 | #[default] | ||
| 123 | Default, | ||
| 124 | Custom(Symbol, Span), | ||
| 125 | } | 109 | } |
| 126 | 110 | ||
| 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)), |
| 785 | 785 | ||
| 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(); |
| 844 | 844 | ||
| 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 | } |
| 186 | 186 | ||
| 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 | } |
| 319 | 319 | ||
| 320 | #[derive(Diagnostic)] | ||
| 321 | #[diag("the trait `ConstParamTy` may not be implemented for this struct")] | ||
| 322 | pub(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)] |
| 322 | pub(crate) struct TraitObjectDeclaredWithNoTraits { | 330 | pub(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 | } | ||
| 1217 | 1224 | ||
| 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) = op | 257 | if let Op::BinOp(binop) = op |
| 253 | && binop.node == hir::BinOpKind::Eq | 258 | && 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 (?), so | 70 | // 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. |
| 72 | static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000); | 72 | static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000); |
| 73 | static_assert(dwarf::DW_OP_constu == 0x10); | ||
| 74 | static_assert(dwarf::DW_OP_minus == 0x1c); | ||
| 75 | static_assert(dwarf::DW_OP_mul == 0x1e); | ||
| 76 | static_assert(dwarf::DW_OP_bregx == 0x92); | ||
| 73 | static_assert(dwarf::DW_OP_stack_value == 0x9f); | 77 | static_assert(dwarf::DW_OP_stack_value == 0x9f); |
| 74 | 78 | ||
| 75 | static LLVM_THREAD_LOCAL char *LastError; | 79 | static 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 | } |
| 732 | 736 | ||
| 733 | template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { | 737 | template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { |
| 734 | return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr); | 738 | return (DIT *)(Ref ? unwrap<Metadata>(Ref) : nullptr); |
| 735 | } | 739 | } |
| 736 | 740 | ||
| 737 | #define DIDescriptor DIScope | 741 | #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 | } |
| 1209 | 1213 | ||
| 1214 | // LLVM's C FFI bindings don't expose the overload of `GetOrCreateSubrange` | ||
| 1215 | // which takes a metadata node as the upper bound. | ||
| 1216 | extern "C" LLVMMetadataRef | ||
| 1217 | LLVMRustDIGetOrCreateSubrange(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`. | ||
| 1227 | extern "C" LLVMMetadataRef | ||
| 1228 | LLVMRustDICreateVectorType(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 | |||
| 1210 | extern "C" LLVMMetadataRef | 1244 | extern "C" LLVMMetadataRef |
| 1211 | LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location, | 1245 | LLVMRustDILocationCloneWithBaseDiscriminator(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 @@ |
| 4 | use rustc_ast as ast; | 4 | use rustc_ast as ast; |
| 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; | 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
| 6 | use rustc_hir as hir; | 6 | use rustc_hir as hir; |
| 7 | use rustc_span::{SourceFile, Symbol, sym}; | 7 | use rustc_span::{Symbol, sym}; |
| 8 | use smallvec::SmallVec; | 8 | use smallvec::SmallVec; |
| 9 | 9 | ||
| 10 | use super::StableHashingContext; | 10 | use 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 | } |
| 56 | 56 | ||
| 57 | impl<'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 | |||
| 107 | impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features { | 57 | impl<'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 the | 59 | // 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; |
| 7 | use std::ops::{ControlFlow, Range}; | 7 | use std::ops::{ControlFlow, Range}; |
| 8 | 8 | ||
| 9 | use hir::def::{CtorKind, DefKind}; | 9 | use hir::def::{CtorKind, DefKind}; |
| 10 | use rustc_abi::{FIRST_VARIANT, FieldIdx, ScalableElt, VariantIdx}; | 10 | use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx}; |
| 11 | use rustc_errors::{ErrorGuaranteed, MultiSpan}; | 11 | use rustc_errors::{ErrorGuaranteed, MultiSpan}; |
| 12 | use rustc_hir as hir; | 12 | use rustc_hir as hir; |
| 13 | use rustc_hir::LangItem; | 13 | use rustc_hir::LangItem; |
| ... | @@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> { | ... | @@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> { |
| 1261 | } | 1261 | } |
| 1262 | } | 1262 | } |
| 1263 | 1263 | ||
| 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 | } |
| 1276 | 1286 | ||
| 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 | } |
| 234 | 234 | ||
| 235 | /// How many scalable vectors are in a `ValueAbi::ScalableVector`? | ||
| 236 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] | ||
| 237 | pub 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; |
| 10 | 10 | ||
| 11 | use crate::abi::{ | 11 | use 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 | }; |
| 16 | use crate::compiler_interface::BridgeTys; | 17 | use crate::compiler_interface::BridgeTys; |
| 17 | use crate::target::MachineSize as Size; | 18 | use 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 | } |
| 251 | 252 | ||
| 253 | impl<'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 | |||
| 252 | impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { | 265 | impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { |
| 253 | type T = ValueAbi; | 266 | type T = ValueAbi; |
| 254 | 267 | ||
| ... | @@ -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 the | 1773 | // 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::MaybeIncorrect | 1779 | 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 | } |
| 1530 | 1530 | ||
| 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 | }; |
| 17 | use rustc_hir::attrs::diagnostic::{AppendConstMessage, OnUnimplementedNote}; | 17 | use rustc_hir::attrs::diagnostic::OnUnimplementedNote; |
| 18 | use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; | 18 | use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; |
| 19 | use rustc_hir::intravisit::Visitor; | 19 | use rustc_hir::intravisit::Visitor; |
| 20 | use rustc_hir::{self as hir, LangItem, Node, find_attr}; | 20 | use 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); |
| 198 | 197 | ||
| 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()?` when | 233 | // 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 | }; |
| 241 | 245 | ||
| 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 | }; |
| 284 | 279 | ||
| 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 trait | 393 | // 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 point | 394 | // `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 | } |
| 561 | 556 | ||
| 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> { |
| 857 | 857 | ||
| 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; |
| 924 | 921 | ||
| 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 | message | 2840 | 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 const | 2843 | trait_predicate.print_with_bound_constness(predicate_constness), |
| 2849 | (None, _) => Some(cannot_do_this), | 2844 | long_ty_path, |
| 2850 | // suggested using default post message | 2845 | ), |
| 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 | } |
| 2874 | 2848 | ||
| 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 | }; |
| 24 | use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk}; | 24 | use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk}; |
| 25 | use rustc_infer::traits::ImplSource; | ||
| 25 | use rustc_middle::middle::privacy::Level; | 26 | use rustc_middle::middle::privacy::Level; |
| 26 | use rustc_middle::traits::IsConstable; | 27 | use rustc_middle::traits::IsConstable; |
| 28 | use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; | ||
| 27 | use rustc_middle::ty::error::TypeError; | 29 | use rustc_middle::ty::error::TypeError; |
| 28 | use rustc_middle::ty::print::{ | 30 | use 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; |
| 49 | use crate::errors; | 51 | use crate::errors; |
| 50 | use crate::infer::InferCtxtExt as _; | 52 | use crate::infer::InferCtxtExt as _; |
| 51 | use crate::traits::query::evaluate_obligation::InferCtxtExt as _; | 53 | use crate::traits::query::evaluate_obligation::InferCtxtExt as _; |
| 52 | use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt}; | 54 | use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt, SelectionContext}; |
| 53 | 55 | ||
| 54 | #[derive(Debug)] | 56 | #[derive(Debug)] |
| 55 | pub enum CoroutineInteriorOrUpvar { | 57 | pub 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 | } |
| 243 | 245 | ||
| 244 | impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | 246 | impl<'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}; |
| 4 | use rustc_abi::Primitive::{self, Float, Int, Pointer}; | 4 | use rustc_abi::Primitive::{self, Float, Int, Pointer}; |
| 5 | use rustc_abi::{ | 5 | use 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 | }; |
| 10 | use rustc_hashes::Hash64; | 10 | use rustc_hashes::Hash64; |
| 11 | use rustc_hir as hir; | 11 | use 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 = tcx | 583 | 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 | }; |
| 596 | 588 | ||
| 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 | } |
| 600 | 596 | ||
| 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 this | 1363 | #[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 | |||
| 5 | use 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] | ||
| 16 | pub 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] | ||
| 27 | pub 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] | ||
| 40 | pub 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] | ||
| 53 | pub 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] | ||
| 60 | pub 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] | ||
| 68 | pub 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] | ||
| 76 | pub 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] | ||
| 84 | pub 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] | ||
| 95 | pub 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] | ||
| 106 | pub 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] | ||
| 119 | pub 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] | ||
| 132 | pub 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] | ||
| 149 | pub 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] | ||
| 166 | pub 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] | ||
| 178 | pub 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] | ||
| 185 | pub 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] | ||
| 192 | pub 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] | ||
| 199 | pub 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] | ||
| 220 | pub 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] | ||
| 234 | pub 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] | ||
| 242 | pub 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] | ||
| 249 | pub 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] | ||
| 262 | pub 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] | ||
| 275 | pub 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] | ||
| 286 | pub 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] | ||
| 297 | pub 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] | ||
| 308 | pub 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] | ||
| 319 | pub 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] | ||
| 330 | pub 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] | ||
| 341 | pub 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] | ||
| 357 | pub 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] | ||
| 378 | pub 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] | ||
| 402 | pub 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)] | ||
| 406 | pub 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] | ||
| 437 | pub 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] | ||
| 459 | pub 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] | ||
| 466 | pub 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] | ||
| 475 | pub 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] | ||
| 486 | pub 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] | ||
| 496 | pub 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] | ||
| 507 | pub 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] | ||
| 517 | pub 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] | ||
| 527 | pub 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] | ||
| 537 | pub 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] | ||
| 548 | pub 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] | ||
| 559 | pub 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] | ||
| 568 | pub 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] | ||
| 577 | pub 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] | ||
| 586 | pub 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] | ||
| 623 | pub 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] | ||
| 639 | pub 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] | ||
| 655 | pub 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] | ||
| 667 | pub 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] | ||
| 674 | pub 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] | ||
| 683 | pub 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] | ||
| 692 | pub 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] | ||
| 699 | pub 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] | ||
| 706 | pub 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] | ||
| 713 | pub 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] | ||
| 720 | pub 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] | ||
| 727 | pub 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] | ||
| 734 | pub 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] | ||
| 741 | pub 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] | ||
| 749 | pub 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] | ||
| 757 | pub 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] | ||
| 765 | pub 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] | ||
| 772 | pub 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] | ||
| 779 | pub 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] | ||
| 794 | pub 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] | ||
| 801 | pub 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] | ||
| 808 | pub 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] | ||
| 815 | pub 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] | ||
| 822 | pub 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] | ||
| 829 | pub 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] | ||
| 836 | pub 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] | ||
| 843 | pub 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 | |||
| 5 | pub mod scalable; | ||
| 6 | |||
| 7 | use 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] | ||
| 18 | pub 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] | ||
| 29 | pub 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] | ||
| 42 | pub 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] | ||
| 55 | pub 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] | ||
| 62 | pub 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] | ||
| 70 | pub 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] | ||
| 78 | pub 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] | ||
| 86 | pub 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] | ||
| 97 | pub 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] | ||
| 108 | pub 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] | ||
| 121 | pub 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] | ||
| 134 | pub 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] | ||
| 151 | pub 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] | ||
| 168 | pub 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] | ||
| 180 | pub 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] | ||
| 187 | pub 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] | ||
| 194 | pub 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] | ||
| 201 | pub 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] | ||
| 222 | pub 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] | ||
| 236 | pub 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] | ||
| 244 | pub 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] | ||
| 251 | pub 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] | ||
| 264 | pub 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] | ||
| 277 | pub 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] | ||
| 288 | pub 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] | ||
| 299 | pub 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] | ||
| 310 | pub 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] | ||
| 321 | pub 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] | ||
| 332 | pub 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] | ||
| 343 | pub 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] | ||
| 359 | pub 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] | ||
| 380 | pub 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] | ||
| 404 | pub 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)] | ||
| 408 | pub 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] | ||
| 439 | pub 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] | ||
| 461 | pub 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] | ||
| 468 | pub 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] | ||
| 477 | pub 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] | ||
| 488 | pub 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] | ||
| 498 | pub 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] | ||
| 509 | pub 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] | ||
| 519 | pub 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] | ||
| 529 | pub 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] | ||
| 539 | pub 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] | ||
| 550 | pub 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] | ||
| 561 | pub 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] | ||
| 570 | pub 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] | ||
| 579 | pub 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] | ||
| 588 | pub 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] | ||
| 625 | pub 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] | ||
| 641 | pub 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] | ||
| 657 | pub 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] | ||
| 669 | pub 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] | ||
| 676 | pub 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] | ||
| 685 | pub 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] | ||
| 694 | pub 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] | ||
| 701 | pub 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] | ||
| 708 | pub 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] | ||
| 715 | pub 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] | ||
| 722 | pub 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] | ||
| 729 | pub 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] | ||
| 736 | pub 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] | ||
| 743 | pub 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] | ||
| 751 | pub 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] | ||
| 759 | pub 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] | ||
| 767 | pub 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] | ||
| 774 | pub 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] | ||
| 781 | pub 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] | ||
| 796 | pub 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] | ||
| 803 | pub 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] | ||
| 810 | pub 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] | ||
| 817 | pub 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] | ||
| 824 | pub 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] | ||
| 831 | pub 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] | ||
| 838 | pub 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] | ||
| 845 | pub 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] | ||
| 25 | pub 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] | ||
| 37 | pub 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] | ||
| 49 | pub 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] | ||
| 61 | pub 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] | ||
| 77 | pub 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] | ||
| 93 | pub 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] |
| 1060 | pub const trait Destruct: PointeeSized {} | 1060 | pub 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")] |
| 1092 | pub macro ConstParamTy($item:item) { | 1092 | pub 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 = "+")] |
| 77 | pub const trait Add<Rhs = Self> { | 76 | pub 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 = "-")] |
| 190 | pub const trait Sub<Rhs = Self> { | 188 | pub 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 {} |
| 63 | pub trait Sized: MetaSized {} | 63 | pub trait Sized: MetaSized {} |
| 64 | 64 | ||
| 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}`")] |
| 67 | pub trait Destruct: PointeeSized {} | 67 | pub trait Destruct: PointeeSized {} |
| 68 | 68 | ||
| 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)] | ||
| 13 | struct svint8_t(i8); | ||
| 14 | |||
| 15 | #[rustc_scalable_vector] | ||
| 16 | #[allow(non_camel_case_types)] | ||
| 17 | struct svint8x2_t(svint8_t, svint8_t); | ||
| 18 | |||
| 19 | #[rustc_scalable_vector(16)] | ||
| 20 | #[allow(non_camel_case_types)] | ||
| 21 | struct svuint8_t(u8); | ||
| 22 | |||
| 23 | #[rustc_scalable_vector] | ||
| 24 | #[allow(non_camel_case_types)] | ||
| 25 | struct svuint8x2_t(svuint8_t, svuint8_t); | ||
| 26 | |||
| 27 | #[rustc_scalable_vector(8)] | ||
| 28 | #[allow(non_camel_case_types)] | ||
| 29 | struct svint16_t(i16); | ||
| 30 | |||
| 31 | #[rustc_scalable_vector] | ||
| 32 | #[allow(non_camel_case_types)] | ||
| 33 | struct svint16x2_t(svint16_t, svint16_t); | ||
| 34 | |||
| 35 | #[rustc_scalable_vector(8)] | ||
| 36 | #[allow(non_camel_case_types)] | ||
| 37 | struct svuint16_t(u16); | ||
| 38 | |||
| 39 | #[rustc_scalable_vector] | ||
| 40 | #[allow(non_camel_case_types)] | ||
| 41 | struct svuint16x2_t(svuint16_t, svuint16_t); | ||
| 42 | |||
| 43 | #[rustc_scalable_vector(4)] | ||
| 44 | #[allow(non_camel_case_types)] | ||
| 45 | struct svint32_t(i32); | ||
| 46 | |||
| 47 | #[rustc_scalable_vector] | ||
| 48 | #[allow(non_camel_case_types)] | ||
| 49 | struct svint32x2_t(svint32_t, svint32_t); | ||
| 50 | |||
| 51 | #[rustc_scalable_vector(4)] | ||
| 52 | #[allow(non_camel_case_types)] | ||
| 53 | struct svuint32_t(u32); | ||
| 54 | |||
| 55 | #[rustc_scalable_vector] | ||
| 56 | #[allow(non_camel_case_types)] | ||
| 57 | struct svuint32x2_t(svuint32_t, svuint32_t); | ||
| 58 | |||
| 59 | #[rustc_scalable_vector(2)] | ||
| 60 | #[allow(non_camel_case_types)] | ||
| 61 | struct svint64_t(i64); | ||
| 62 | |||
| 63 | #[rustc_scalable_vector] | ||
| 64 | #[allow(non_camel_case_types)] | ||
| 65 | struct svint64x2_t(svint64_t, svint64_t); | ||
| 66 | |||
| 67 | #[rustc_scalable_vector(2)] | ||
| 68 | #[allow(non_camel_case_types)] | ||
| 69 | struct svuint64_t(u64); | ||
| 70 | |||
| 71 | #[rustc_scalable_vector] | ||
| 72 | #[allow(non_camel_case_types)] | ||
| 73 | struct svuint64x2_t(svuint64_t, svuint64_t); | ||
| 74 | |||
| 75 | #[rustc_scalable_vector(4)] | ||
| 76 | #[allow(non_camel_case_types)] | ||
| 77 | struct svfloat32_t(f32); | ||
| 78 | |||
| 79 | #[rustc_scalable_vector] | ||
| 80 | #[allow(non_camel_case_types)] | ||
| 81 | struct svfloat32x2_t(svfloat32_t, svfloat32_t); | ||
| 82 | |||
| 83 | #[rustc_scalable_vector(2)] | ||
| 84 | #[allow(non_camel_case_types)] | ||
| 85 | struct svfloat64_t(f64); | ||
| 86 | |||
| 87 | #[rustc_scalable_vector] | ||
| 88 | #[allow(non_camel_case_types)] | ||
| 89 | struct svfloat64x2_t(svfloat64_t, svfloat64_t); | ||
| 90 | |||
| 91 | #[target_feature(enable = "sve")] | ||
| 92 | pub 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)] | ||
| 13 | struct svint8_t(i8); | ||
| 14 | |||
| 15 | #[rustc_scalable_vector] | ||
| 16 | #[allow(non_camel_case_types)] | ||
| 17 | struct svint8x3_t(svint8_t, svint8_t, svint8_t); | ||
| 18 | |||
| 19 | #[rustc_scalable_vector(16)] | ||
| 20 | #[allow(non_camel_case_types)] | ||
| 21 | struct svuint8_t(u8); | ||
| 22 | |||
| 23 | #[rustc_scalable_vector] | ||
| 24 | #[allow(non_camel_case_types)] | ||
| 25 | struct svuint8x3_t(svuint8_t, svuint8_t, svuint8_t); | ||
| 26 | |||
| 27 | #[rustc_scalable_vector(8)] | ||
| 28 | #[allow(non_camel_case_types)] | ||
| 29 | struct svint16_t(i16); | ||
| 30 | |||
| 31 | #[rustc_scalable_vector] | ||
| 32 | #[allow(non_camel_case_types)] | ||
| 33 | struct svint16x3_t(svint16_t, svint16_t, svint16_t); | ||
| 34 | |||
| 35 | #[rustc_scalable_vector(8)] | ||
| 36 | #[allow(non_camel_case_types)] | ||
| 37 | struct svuint16_t(u16); | ||
| 38 | |||
| 39 | #[rustc_scalable_vector] | ||
| 40 | #[allow(non_camel_case_types)] | ||
| 41 | struct svuint16x3_t(svuint16_t, svuint16_t, svuint16_t); | ||
| 42 | |||
| 43 | #[rustc_scalable_vector(4)] | ||
| 44 | #[allow(non_camel_case_types)] | ||
| 45 | struct svint32_t(i32); | ||
| 46 | |||
| 47 | #[rustc_scalable_vector] | ||
| 48 | #[allow(non_camel_case_types)] | ||
| 49 | struct svint32x3_t(svint32_t, svint32_t, svint32_t); | ||
| 50 | |||
| 51 | #[rustc_scalable_vector(4)] | ||
| 52 | #[allow(non_camel_case_types)] | ||
| 53 | struct svuint32_t(u32); | ||
| 54 | |||
| 55 | #[rustc_scalable_vector] | ||
| 56 | #[allow(non_camel_case_types)] | ||
| 57 | struct svuint32x3_t(svuint32_t, svuint32_t, svuint32_t); | ||
| 58 | |||
| 59 | #[rustc_scalable_vector(2)] | ||
| 60 | #[allow(non_camel_case_types)] | ||
| 61 | struct svint64_t(i64); | ||
| 62 | |||
| 63 | #[rustc_scalable_vector] | ||
| 64 | #[allow(non_camel_case_types)] | ||
| 65 | struct svint64x3_t(svint64_t, svint64_t, svint64_t); | ||
| 66 | |||
| 67 | #[rustc_scalable_vector(2)] | ||
| 68 | #[allow(non_camel_case_types)] | ||
| 69 | struct svuint64_t(u64); | ||
| 70 | |||
| 71 | #[rustc_scalable_vector] | ||
| 72 | #[allow(non_camel_case_types)] | ||
| 73 | struct svuint64x3_t(svuint64_t, svuint64_t, svuint64_t); | ||
| 74 | |||
| 75 | #[rustc_scalable_vector(4)] | ||
| 76 | #[allow(non_camel_case_types)] | ||
| 77 | struct svfloat32_t(f32); | ||
| 78 | |||
| 79 | #[rustc_scalable_vector] | ||
| 80 | #[allow(non_camel_case_types)] | ||
| 81 | struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t); | ||
| 82 | |||
| 83 | #[rustc_scalable_vector(2)] | ||
| 84 | #[allow(non_camel_case_types)] | ||
| 85 | struct svfloat64_t(f64); | ||
| 86 | |||
| 87 | #[rustc_scalable_vector] | ||
| 88 | #[allow(non_camel_case_types)] | ||
| 89 | struct svfloat64x3_t(svfloat64_t, svfloat64_t, svfloat64_t); | ||
| 90 | |||
| 91 | #[target_feature(enable = "sve")] | ||
| 92 | pub 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)] | ||
| 13 | struct svint8_t(i8); | ||
| 14 | |||
| 15 | #[rustc_scalable_vector] | ||
| 16 | #[allow(non_camel_case_types)] | ||
| 17 | struct svint8x4_t(svint8_t, svint8_t, svint8_t, svint8_t); | ||
| 18 | |||
| 19 | #[rustc_scalable_vector(16)] | ||
| 20 | #[allow(non_camel_case_types)] | ||
| 21 | struct svuint8_t(u8); | ||
| 22 | |||
| 23 | #[rustc_scalable_vector] | ||
| 24 | #[allow(non_camel_case_types)] | ||
| 25 | struct svuint8x4_t(svuint8_t, svuint8_t, svuint8_t, svuint8_t); | ||
| 26 | |||
| 27 | #[rustc_scalable_vector(8)] | ||
| 28 | #[allow(non_camel_case_types)] | ||
| 29 | struct svint16_t(i16); | ||
| 30 | |||
| 31 | #[rustc_scalable_vector] | ||
| 32 | #[allow(non_camel_case_types)] | ||
| 33 | struct svint16x4_t(svint16_t, svint16_t, svint16_t, svint16_t); | ||
| 34 | |||
| 35 | #[rustc_scalable_vector(8)] | ||
| 36 | #[allow(non_camel_case_types)] | ||
| 37 | struct svuint16_t(u16); | ||
| 38 | |||
| 39 | #[rustc_scalable_vector] | ||
| 40 | #[allow(non_camel_case_types)] | ||
| 41 | struct svuint16x4_t(svuint16_t, svuint16_t, svuint16_t, svuint16_t); | ||
| 42 | |||
| 43 | #[rustc_scalable_vector(4)] | ||
| 44 | #[allow(non_camel_case_types)] | ||
| 45 | struct svint32_t(i32); | ||
| 46 | |||
| 47 | #[rustc_scalable_vector] | ||
| 48 | #[allow(non_camel_case_types)] | ||
| 49 | struct svint32x4_t(svint32_t, svint32_t, svint32_t, svint32_t); | ||
| 50 | |||
| 51 | #[rustc_scalable_vector(4)] | ||
| 52 | #[allow(non_camel_case_types)] | ||
| 53 | struct svuint32_t(u32); | ||
| 54 | |||
| 55 | #[rustc_scalable_vector] | ||
| 56 | #[allow(non_camel_case_types)] | ||
| 57 | struct svuint32x4_t(svuint32_t, svuint32_t, svuint32_t, svuint32_t); | ||
| 58 | |||
| 59 | #[rustc_scalable_vector(2)] | ||
| 60 | #[allow(non_camel_case_types)] | ||
| 61 | struct svint64_t(i64); | ||
| 62 | |||
| 63 | #[rustc_scalable_vector] | ||
| 64 | #[allow(non_camel_case_types)] | ||
| 65 | struct svint64x4_t(svint64_t, svint64_t, svint64_t, svint64_t); | ||
| 66 | |||
| 67 | #[rustc_scalable_vector(2)] | ||
| 68 | #[allow(non_camel_case_types)] | ||
| 69 | struct svuint64_t(u64); | ||
| 70 | |||
| 71 | #[rustc_scalable_vector] | ||
| 72 | #[allow(non_camel_case_types)] | ||
| 73 | struct svuint64x4_t(svuint64_t, svuint64_t, svuint64_t, svuint64_t); | ||
| 74 | |||
| 75 | #[rustc_scalable_vector(4)] | ||
| 76 | #[allow(non_camel_case_types)] | ||
| 77 | struct svfloat32_t(f32); | ||
| 78 | |||
| 79 | #[rustc_scalable_vector] | ||
| 80 | #[allow(non_camel_case_types)] | ||
| 81 | struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t); | ||
| 82 | |||
| 83 | #[rustc_scalable_vector(2)] | ||
| 84 | #[allow(non_camel_case_types)] | ||
| 85 | struct svfloat64_t(f64); | ||
| 86 | |||
| 87 | #[rustc_scalable_vector] | ||
| 88 | #[allow(non_camel_case_types)] | ||
| 89 | struct svfloat64x4_t(svfloat64_t, svfloat64_t, svfloat64_t, svfloat64_t); | ||
| 90 | |||
| 91 | #[target_feature(enable = "sve")] | ||
| 92 | pub 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)] | ||
| 17 | struct svbool_t(bool); | ||
| 18 | |||
| 19 | #[rustc_scalable_vector(16)] | ||
| 20 | #[allow(non_camel_case_types)] | ||
| 21 | struct svint8_t(i8); | ||
| 22 | |||
| 23 | #[rustc_scalable_vector(16)] | ||
| 24 | #[allow(non_camel_case_types)] | ||
| 25 | struct svuint8_t(u8); | ||
| 26 | |||
| 27 | #[rustc_scalable_vector(8)] | ||
| 28 | #[allow(non_camel_case_types)] | ||
| 29 | struct svint16_t(i16); | ||
| 30 | |||
| 31 | #[rustc_scalable_vector(8)] | ||
| 32 | #[allow(non_camel_case_types)] | ||
| 33 | struct svuint16_t(u16); | ||
| 34 | |||
| 35 | #[rustc_scalable_vector(4)] | ||
| 36 | #[allow(non_camel_case_types)] | ||
| 37 | struct svint32_t(i32); | ||
| 38 | |||
| 39 | #[rustc_scalable_vector(4)] | ||
| 40 | #[allow(non_camel_case_types)] | ||
| 41 | struct svuint32_t(u32); | ||
| 42 | |||
| 43 | #[rustc_scalable_vector(2)] | ||
| 44 | #[allow(non_camel_case_types)] | ||
| 45 | struct svint64_t(i64); | ||
| 46 | |||
| 47 | #[rustc_scalable_vector(2)] | ||
| 48 | #[allow(non_camel_case_types)] | ||
| 49 | struct svuint64_t(u64); | ||
| 50 | |||
| 51 | #[rustc_scalable_vector(4)] | ||
| 52 | #[allow(non_camel_case_types)] | ||
| 53 | struct svfloat32_t(f32); | ||
| 54 | |||
| 55 | #[rustc_scalable_vector(2)] | ||
| 56 | #[allow(non_camel_case_types)] | ||
| 57 | struct svfloat64_t(f64); | ||
| 58 | |||
| 59 | #[target_feature(enable = "sve")] | ||
| 60 | pub 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)] | ||
| 13 | pub struct svfloat32_t(f32); | ||
| 14 | |||
| 15 | #[derive(Copy, Clone)] | ||
| 16 | #[rustc_scalable_vector] | ||
| 17 | #[allow(non_camel_case_types)] | ||
| 18 | pub struct svfloat32x2_t(svfloat32_t, svfloat32_t); | ||
| 19 | |||
| 20 | #[derive(Copy, Clone)] | ||
| 21 | #[rustc_scalable_vector] | ||
| 22 | #[allow(non_camel_case_types)] | ||
| 23 | pub struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t); | ||
| 24 | |||
| 25 | #[derive(Copy, Clone)] | ||
| 26 | #[rustc_scalable_vector] | ||
| 27 | #[allow(non_camel_case_types)] | ||
| 28 | pub struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t); | ||
| 29 | |||
| 30 | #[inline(never)] | ||
| 31 | #[target_feature(enable = "sve")] | ||
| 32 | pub 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")] | ||
| 43 | pub 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")] | ||
| 52 | pub 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")] | ||
| 63 | pub 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")] | ||
| 80 | pub 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")] | ||
| 88 | pub 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")] | ||
| 95 | pub 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 | |||
| 6 | const fn allow<'b, 'b>() -> usize | ||
| 7 | //~^ ERROR the name `'b` is already used for a generic parameter in this item's generic parameters | ||
| 8 | where | ||
| 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 | |||
| 17 | const fn foo<'a, 'b>() -> usize | ||
| 18 | where | ||
| 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 @@ | ||
| 1 | error[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 | | | ||
| 4 | LL | const fn allow<'b, 'b>() -> usize | ||
| 5 | | -- ^^ already used | ||
| 6 | | | | ||
| 7 | | first use of `'b` | ||
| 8 | |||
| 9 | error[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 | | | ||
| 12 | LL | const fn allow<'b, 'b>() -> usize | ||
| 13 | | -- first declared here | ||
| 14 | ... | ||
| 15 | LL | for<'b> [u8; foo::<'a, 'b>()]: Sized, | ||
| 16 | | ^^ lifetime `'b` already in scope | ||
| 17 | |||
| 18 | error[E0261]: use of undeclared lifetime name `'a` | ||
| 19 | --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:9:24 | ||
| 20 | | | ||
| 21 | LL | 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 | ||
| 25 | help: consider making the bound lifetime-generic with a new `'a` lifetime | ||
| 26 | | | ||
| 27 | LL | for<'a, 'b> [u8; foo::<'a, 'b>()]: Sized, | ||
| 28 | | +++ | ||
| 29 | help: consider introducing lifetime `'a` here | ||
| 30 | | | ||
| 31 | LL | const fn allow<'a, 'b, 'b>() -> usize | ||
| 32 | | +++ | ||
| 33 | |||
| 34 | error[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 | | | ||
| 37 | LL | } | ||
| 38 | | ^ consider adding a `main` function to `$DIR/escaping-late-bound-region-in-canonical-ice-113870.rs` | ||
| 39 | |||
| 40 | error: cannot capture late-bound lifetime in constant | ||
| 41 | --> $DIR/escaping-late-bound-region-in-canonical-ice-113870.rs:9:28 | ||
| 42 | | | ||
| 43 | LL | const fn allow<'b, 'b>() -> usize | ||
| 44 | | -- lifetime defined here | ||
| 45 | ... | ||
| 46 | LL | for<'b> [u8; foo::<'a, 'b>()]: Sized, | ||
| 47 | | ^^ | ||
| 48 | |||
| 49 | error: aborting due to 5 previous errors | ||
| 50 | |||
| 51 | Some errors have detailed explanations: E0261, E0403, E0496, E0601. | ||
| 52 | For 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 | |||
| 8 | pub trait Foo { | ||
| 9 | const SIZE: usize; | ||
| 10 | } | ||
| 11 | |||
| 12 | impl Foo for u64 { | ||
| 13 | const SIZE: usize = 8; | ||
| 14 | } | ||
| 15 | |||
| 16 | pub struct Wrapper<T> | ||
| 17 | where | ||
| 18 | T: Foo, | ||
| 19 | [(); T::SIZE]:, | ||
| 20 | { | ||
| 21 | pub t: T, | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn bar() -> Wrapper<impl Foo> { | ||
| 25 | Wrapper { t: 10 } | ||
| 26 | } | ||
| 27 | |||
| 28 | fn 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 | |||
| 6 | use std::marker::ConstParamTy_; | ||
| 7 | |||
| 8 | #[derive(PartialEq, Eq)] | ||
| 9 | pub struct Fumo { | ||
| 10 | cirno: i32, | ||
| 11 | pub(crate) reimu: i32 | ||
| 12 | } | ||
| 13 | |||
| 14 | impl ConstParamTy_ for Fumo {} | ||
| 15 | //~^ ERROR: the trait `ConstParamTy` may not be implemented for this struct | ||
| 16 | |||
| 17 | fn main() {} | ||
tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.stderr created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | error: the trait `ConstParamTy` may not be implemented for this struct | ||
| 2 | --> $DIR/const_param_ty-on-adt-without-adt-gate.rs:14:24 | ||
| 3 | | | ||
| 4 | LL | impl ConstParamTy_ for Fumo {} | ||
| 5 | | ^^^^ struct fields are less visible than the struct | ||
| 6 | |||
| 7 | error: 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 | |||
| 7 | use std::marker::ConstParamTy_; | ||
| 8 | |||
| 9 | #[derive(PartialEq, Eq)] | ||
| 10 | pub struct Meowl { | ||
| 11 | pub public: i32, | ||
| 12 | private: i32 | ||
| 13 | } | ||
| 14 | |||
| 15 | #[derive(PartialEq, Eq)] | ||
| 16 | pub struct Meowl2 { | ||
| 17 | pub a: i32, | ||
| 18 | pub b: i32 | ||
| 19 | } | ||
| 20 | |||
| 21 | #[derive(PartialEq, Eq)] | ||
| 22 | pub(crate) struct Meowl3 { | ||
| 23 | pub(crate) a: i32, | ||
| 24 | pub b: i32 | ||
| 25 | } | ||
| 26 | |||
| 27 | impl ConstParamTy_ for Meowl {} | ||
| 28 | //~^ ERROR the trait `ConstParamTy` may not be implemented for this struct | ||
| 29 | impl ConstParamTy_ for Meowl2 {} | ||
| 30 | impl ConstParamTy_ for Meowl3 {} | ||
| 31 | |||
| 32 | fn something<const N: Meowl2>() {} | ||
| 33 | fn something2<const N: Meowl3>() {} | ||
| 34 | |||
| 35 | fn main() {} | ||
tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.stderr created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | error: the trait `ConstParamTy` may not be implemented for this struct | ||
| 2 | --> $DIR/min_adt_const_params-gate-fail.rs:27:24 | ||
| 3 | | | ||
| 4 | LL | impl ConstParamTy_ for Meowl {} | ||
| 5 | | ^^^^^ struct fields are less visible than the struct | ||
| 6 | |||
| 7 | error: 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 | |||
| 6 | use std::marker::ConstParamTy_; | ||
| 7 | |||
| 8 | #[derive(PartialEq, Eq)] | ||
| 9 | pub struct Meowl { | ||
| 10 | pub public: i32, | ||
| 11 | pub also_public: i32 | ||
| 12 | } | ||
| 13 | |||
| 14 | impl ConstParamTy_ for Meowl {} | ||
| 15 | |||
| 16 | fn meoow<const N: Meowl>() {} | ||
| 17 | |||
| 18 | fn 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 | |||
| 4 | use std::marker::ConstParamTy; | ||
| 5 | |||
| 6 | #[derive(ConstParamTy, Eq, PartialEq)] | ||
| 7 | #[allow(dead_code)] | ||
| 8 | struct Foo { | ||
| 9 | pub field: u32, | ||
| 10 | } | ||
| 11 | |||
| 12 | fn 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 | |||
| 6 | mod 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 | |||
| 25 | use structs::A; | ||
| 26 | |||
| 27 | fn takes_usize(_: usize) {} | ||
| 28 | |||
| 29 | trait Marker {} | ||
| 30 | |||
| 31 | impl Marker for usize {} | ||
| 32 | |||
| 33 | struct Wrapper(i32); | ||
| 34 | |||
| 35 | impl<T: Marker> std::ops::Add<T> for Wrapper { | ||
| 36 | type Output = (); | ||
| 37 | |||
| 38 | fn add(self, _: T) {} | ||
| 39 | } | ||
| 40 | |||
| 41 | fn by_value(a: A) { | ||
| 42 | a.field + 5; | ||
| 43 | } | ||
| 44 | |||
| 45 | fn by_ref(a: &A) { | ||
| 46 | a.field + 5; | ||
| 47 | } | ||
| 48 | |||
| 49 | fn rhs_by_value(a: A) { | ||
| 50 | 5 + a.field; | ||
| 51 | } | ||
| 52 | |||
| 53 | fn rhs_by_ref(a: &A) { | ||
| 54 | 5 + a.field; | ||
| 55 | } | ||
| 56 | |||
| 57 | fn rhs_assign_op_by_value(a: A) { | ||
| 58 | let mut n = 5; | ||
| 59 | n += a.field; | ||
| 60 | } | ||
| 61 | |||
| 62 | fn rhs_assign_op_by_ref(a: &A) { | ||
| 63 | let mut n = 5; | ||
| 64 | n += a.field; | ||
| 65 | } | ||
| 66 | |||
| 67 | fn rhs_nested_obligation(a: A) { | ||
| 68 | Wrapper(5) + a.field; | ||
| 69 | } | ||
| 70 | |||
| 71 | fn method_call(a: A) { | ||
| 72 | a.field.count_ones(); | ||
| 73 | } | ||
| 74 | |||
| 75 | fn type_mismatch(a: A) { | ||
| 76 | let value: usize = a.field; | ||
| 77 | eprintln!("value: {value}"); | ||
| 78 | } | ||
| 79 | |||
| 80 | fn function_arg(a: A) { | ||
| 81 | takes_usize(a.field); | ||
| 82 | } | ||
| 83 | |||
| 84 | fn return_value(a: &A) -> usize { | ||
| 85 | a.field | ||
| 86 | } | ||
| 87 | |||
| 88 | fn main() {} | ||
tests/ui/privacy/private-field-deref-confusion-issue-149546.stderr created+317| ... | @@ -0,0 +1,317 @@ | ||
| 1 | error[E0369]: cannot add `{integer}` to `bool` | ||
| 2 | --> $DIR/private-field-deref-confusion-issue-149546.rs:42:13 | ||
| 3 | | | ||
| 4 | LL | a.field + 5; | ||
| 5 | | ------- ^ - {integer} | ||
| 6 | | | | ||
| 7 | | bool | ||
| 8 | | | ||
| 9 | note: 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 | | | ||
| 12 | LL | pub struct A { | ||
| 13 | | ^ in this struct | ||
| 14 | LL | field: usize, | ||
| 15 | | ----- if this field wasn't private, it would be accessible | ||
| 16 | ... | ||
| 17 | LL | pub struct B { | ||
| 18 | | - this struct is accessible through auto-deref | ||
| 19 | LL | pub field: bool, | ||
| 20 | | ----- this is the field that was accessed | ||
| 21 | ... | ||
| 22 | LL | impl std::ops::Deref for A { | ||
| 23 | | -------------------------- the field was accessed through this `Deref` | ||
| 24 | |||
| 25 | error[E0369]: cannot add `{integer}` to `bool` | ||
| 26 | --> $DIR/private-field-deref-confusion-issue-149546.rs:46:13 | ||
| 27 | | | ||
| 28 | LL | a.field + 5; | ||
| 29 | | ------- ^ - {integer} | ||
| 30 | | | | ||
| 31 | | bool | ||
| 32 | | | ||
| 33 | note: 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 | | | ||
| 36 | LL | pub struct A { | ||
| 37 | | ^ in this struct | ||
| 38 | LL | field: usize, | ||
| 39 | | ----- if this field wasn't private, it would be accessible | ||
| 40 | ... | ||
| 41 | LL | pub struct B { | ||
| 42 | | - this struct is accessible through auto-deref | ||
| 43 | LL | pub field: bool, | ||
| 44 | | ----- this is the field that was accessed | ||
| 45 | ... | ||
| 46 | LL | impl std::ops::Deref for A { | ||
| 47 | | -------------------------- the field was accessed through this `Deref` | ||
| 48 | |||
| 49 | error[E0277]: cannot add `bool` to `{integer}` | ||
| 50 | --> $DIR/private-field-deref-confusion-issue-149546.rs:50:7 | ||
| 51 | | | ||
| 52 | LL | 5 + a.field; | ||
| 53 | | ^ no implementation for `{integer} + bool` | ||
| 54 | | | ||
| 55 | = help: the trait `Add<bool>` is not implemented for `{integer}` | ||
| 56 | note: 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 | | | ||
| 59 | LL | pub struct A { | ||
| 60 | | ^ in this struct | ||
| 61 | LL | field: usize, | ||
| 62 | | ----- if this field wasn't private, it would be accessible | ||
| 63 | ... | ||
| 64 | LL | pub struct B { | ||
| 65 | | - this struct is accessible through auto-deref | ||
| 66 | LL | pub field: bool, | ||
| 67 | | ----- this is the field that was accessed | ||
| 68 | ... | ||
| 69 | LL | 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 | |||
| 82 | error[E0277]: cannot add `bool` to `{integer}` | ||
| 83 | --> $DIR/private-field-deref-confusion-issue-149546.rs:54:7 | ||
| 84 | | | ||
| 85 | LL | 5 + a.field; | ||
| 86 | | ^ no implementation for `{integer} + bool` | ||
| 87 | | | ||
| 88 | = help: the trait `Add<bool>` is not implemented for `{integer}` | ||
| 89 | note: 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 | | | ||
| 92 | LL | pub struct A { | ||
| 93 | | ^ in this struct | ||
| 94 | LL | field: usize, | ||
| 95 | | ----- if this field wasn't private, it would be accessible | ||
| 96 | ... | ||
| 97 | LL | pub struct B { | ||
| 98 | | - this struct is accessible through auto-deref | ||
| 99 | LL | pub field: bool, | ||
| 100 | | ----- this is the field that was accessed | ||
| 101 | ... | ||
| 102 | LL | 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 | |||
| 115 | error[E0277]: cannot add-assign `bool` to `{integer}` | ||
| 116 | --> $DIR/private-field-deref-confusion-issue-149546.rs:59:7 | ||
| 117 | | | ||
| 118 | LL | n += a.field; | ||
| 119 | | ^^ no implementation for `{integer} += bool` | ||
| 120 | | | ||
| 121 | = help: the trait `AddAssign<bool>` is not implemented for `{integer}` | ||
| 122 | note: 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 | | | ||
| 125 | LL | pub struct A { | ||
| 126 | | ^ in this struct | ||
| 127 | LL | field: usize, | ||
| 128 | | ----- if this field wasn't private, it would be accessible | ||
| 129 | ... | ||
| 130 | LL | pub struct B { | ||
| 131 | | - this struct is accessible through auto-deref | ||
| 132 | LL | pub field: bool, | ||
| 133 | | ----- this is the field that was accessed | ||
| 134 | ... | ||
| 135 | LL | 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 | |||
| 148 | error[E0277]: cannot add-assign `bool` to `{integer}` | ||
| 149 | --> $DIR/private-field-deref-confusion-issue-149546.rs:64:7 | ||
| 150 | | | ||
| 151 | LL | n += a.field; | ||
| 152 | | ^^ no implementation for `{integer} += bool` | ||
| 153 | | | ||
| 154 | = help: the trait `AddAssign<bool>` is not implemented for `{integer}` | ||
| 155 | note: 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 | | | ||
| 158 | LL | pub struct A { | ||
| 159 | | ^ in this struct | ||
| 160 | LL | field: usize, | ||
| 161 | | ----- if this field wasn't private, it would be accessible | ||
| 162 | ... | ||
| 163 | LL | pub struct B { | ||
| 164 | | - this struct is accessible through auto-deref | ||
| 165 | LL | pub field: bool, | ||
| 166 | | ----- this is the field that was accessed | ||
| 167 | ... | ||
| 168 | LL | 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 | |||
| 181 | error[E0277]: the trait bound `bool: Marker` is not satisfied | ||
| 182 | --> $DIR/private-field-deref-confusion-issue-149546.rs:68:16 | ||
| 183 | | | ||
| 184 | LL | Wrapper(5) + a.field; | ||
| 185 | | ^ the trait `Marker` is not implemented for `bool` | ||
| 186 | | | ||
| 187 | note: 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 | | | ||
| 190 | LL | pub struct A { | ||
| 191 | | ^ in this struct | ||
| 192 | LL | field: usize, | ||
| 193 | | ----- if this field wasn't private, it would be accessible | ||
| 194 | ... | ||
| 195 | LL | pub struct B { | ||
| 196 | | - this struct is accessible through auto-deref | ||
| 197 | LL | pub field: bool, | ||
| 198 | | ----- this is the field that was accessed | ||
| 199 | ... | ||
| 200 | LL | impl std::ops::Deref for A { | ||
| 201 | | -------------------------- the field was accessed through this `Deref` | ||
| 202 | help: the trait `Marker` is implemented for `usize` | ||
| 203 | --> $DIR/private-field-deref-confusion-issue-149546.rs:31:1 | ||
| 204 | | | ||
| 205 | LL | impl Marker for usize {} | ||
| 206 | | ^^^^^^^^^^^^^^^^^^^^^ | ||
| 207 | note: required for `Wrapper` to implement `Add<bool>` | ||
| 208 | --> $DIR/private-field-deref-confusion-issue-149546.rs:35:17 | ||
| 209 | | | ||
| 210 | LL | impl<T: Marker> std::ops::Add<T> for Wrapper { | ||
| 211 | | ------ ^^^^^^^^^^^^^^^^ ^^^^^^^ | ||
| 212 | | | | ||
| 213 | | unsatisfied trait bound introduced here | ||
| 214 | |||
| 215 | error[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 | | | ||
| 218 | LL | a.field.count_ones(); | ||
| 219 | | ^^^^^^^^^^ method not found in `bool` | ||
| 220 | | | ||
| 221 | note: 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 | | | ||
| 224 | LL | pub struct A { | ||
| 225 | | ^ in this struct | ||
| 226 | LL | field: usize, | ||
| 227 | | ----- if this field wasn't private, it would be accessible | ||
| 228 | ... | ||
| 229 | LL | pub struct B { | ||
| 230 | | - this struct is accessible through auto-deref | ||
| 231 | LL | pub field: bool, | ||
| 232 | | ----- this is the field that was accessed | ||
| 233 | ... | ||
| 234 | LL | impl std::ops::Deref for A { | ||
| 235 | | -------------------------- the field was accessed through this `Deref` | ||
| 236 | |||
| 237 | error[E0308]: mismatched types | ||
| 238 | --> $DIR/private-field-deref-confusion-issue-149546.rs:76:24 | ||
| 239 | | | ||
| 240 | LL | let value: usize = a.field; | ||
| 241 | | ----- ^^^^^^^ expected `usize`, found `bool` | ||
| 242 | | | | ||
| 243 | | expected due to this | ||
| 244 | | | ||
| 245 | note: 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 | | | ||
| 248 | LL | pub struct A { | ||
| 249 | | ^ in this struct | ||
| 250 | LL | field: usize, | ||
| 251 | | ----- if this field wasn't private, it would be accessible | ||
| 252 | ... | ||
| 253 | LL | pub struct B { | ||
| 254 | | - this struct is accessible through auto-deref | ||
| 255 | LL | pub field: bool, | ||
| 256 | | ----- this is the field that was accessed | ||
| 257 | ... | ||
| 258 | LL | impl std::ops::Deref for A { | ||
| 259 | | -------------------------- the field was accessed through this `Deref` | ||
| 260 | |||
| 261 | error[E0308]: mismatched types | ||
| 262 | --> $DIR/private-field-deref-confusion-issue-149546.rs:81:17 | ||
| 263 | | | ||
| 264 | LL | takes_usize(a.field); | ||
| 265 | | ----------- ^^^^^^^ expected `usize`, found `bool` | ||
| 266 | | | | ||
| 267 | | arguments to this function are incorrect | ||
| 268 | | | ||
| 269 | note: 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 | | | ||
| 272 | LL | pub struct A { | ||
| 273 | | ^ in this struct | ||
| 274 | LL | field: usize, | ||
| 275 | | ----- if this field wasn't private, it would be accessible | ||
| 276 | ... | ||
| 277 | LL | pub struct B { | ||
| 278 | | - this struct is accessible through auto-deref | ||
| 279 | LL | pub field: bool, | ||
| 280 | | ----- this is the field that was accessed | ||
| 281 | ... | ||
| 282 | LL | impl std::ops::Deref for A { | ||
| 283 | | -------------------------- the field was accessed through this `Deref` | ||
| 284 | note: function defined here | ||
| 285 | --> $DIR/private-field-deref-confusion-issue-149546.rs:27:4 | ||
| 286 | | | ||
| 287 | LL | fn takes_usize(_: usize) {} | ||
| 288 | | ^^^^^^^^^^^ -------- | ||
| 289 | |||
| 290 | error[E0308]: mismatched types | ||
| 291 | --> $DIR/private-field-deref-confusion-issue-149546.rs:85:5 | ||
| 292 | | | ||
| 293 | LL | fn return_value(a: &A) -> usize { | ||
| 294 | | ----- expected `usize` because of return type | ||
| 295 | LL | a.field | ||
| 296 | | ^^^^^^^ expected `usize`, found `bool` | ||
| 297 | | | ||
| 298 | note: 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 | | | ||
| 301 | LL | pub struct A { | ||
| 302 | | ^ in this struct | ||
| 303 | LL | field: usize, | ||
| 304 | | ----- if this field wasn't private, it would be accessible | ||
| 305 | ... | ||
| 306 | LL | pub struct B { | ||
| 307 | | - this struct is accessible through auto-deref | ||
| 308 | LL | pub field: bool, | ||
| 309 | | ----- this is the field that was accessed | ||
| 310 | ... | ||
| 311 | LL | impl std::ops::Deref for A { | ||
| 312 | | -------------------------- the field was accessed through this `Deref` | ||
| 313 | |||
| 314 | error: aborting due to 11 previous errors | ||
| 315 | |||
| 316 | Some errors have detailed explanations: E0277, E0308, E0369, E0599. | ||
| 317 | For 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 | |||
| 7 | use std::intrinsics::simd::scalable::sve_cast; | ||
| 8 | |||
| 9 | #[derive(Copy, Clone)] | ||
| 10 | #[rustc_scalable_vector(16)] | ||
| 11 | #[allow(non_camel_case_types)] | ||
| 12 | pub struct svbool_t(bool); | ||
| 13 | |||
| 14 | #[derive(Copy, Clone)] | ||
| 15 | #[rustc_scalable_vector(2)] | ||
| 16 | #[allow(non_camel_case_types)] | ||
| 17 | pub struct svbool2_t(bool); | ||
| 18 | |||
| 19 | #[derive(Copy, Clone)] | ||
| 20 | #[rustc_scalable_vector(2)] | ||
| 21 | #[allow(non_camel_case_types)] | ||
| 22 | pub struct svint64_t(i64); | ||
| 23 | |||
| 24 | #[derive(Copy, Clone)] | ||
| 25 | #[rustc_scalable_vector(2)] | ||
| 26 | #[allow(non_camel_case_types)] | ||
| 27 | pub struct nxv2i16(i16); | ||
| 28 | |||
| 29 | pub trait SveInto<T>: Sized { | ||
| 30 | unsafe fn sve_into(self) -> T; | ||
| 31 | } | ||
| 32 | |||
| 33 | impl 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")] | ||
| 48 | pub 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]), |
| 21 | LL | | ); | 21 | LL | | ); |
| 22 | | |_________^ | 22 | | |_________^ |
| 23 | note: function defined here | 23 | note: function defined here |
| 24 | --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL | 24 | --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL |
| 25 | 25 | ||
| 26 | error[E0308]: mismatched types | 26 | error[E0308]: mismatched types |
| 27 | --> $DIR/masked-load-store-check-fail.rs:25:13 | 27 | --> $DIR/masked-load-store-check-fail.rs:25:13 |
| ... | @@ -46,7 +46,7 @@ LL | | default, | ... | @@ -46,7 +46,7 @@ LL | | default, |
| 46 | LL | | ); | 46 | LL | | ); |
| 47 | | |_________^ | 47 | | |_________^ |
| 48 | note: function defined here | 48 | note: function defined here |
| 49 | --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL | 49 | --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL |
| 50 | 50 | ||
| 51 | error: aborting due to 2 previous errors | 51 | error: aborting due to 2 previous errors |
| 52 | 52 |
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 | |||
| 3 | struct P<Q>(Q); | ||
| 4 | |||
| 5 | impl<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 | |||
| 12 | fn main() {} | ||
tests/ui/typeck/index-out-of-bounds-on-partial-cmp-ice-114056.stderr created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | error[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 | | | ||
| 4 | LL | struct P<Q>(Q); | ||
| 5 | | ----------- doesn't satisfy `P<Q>: Iterator` or `P<Q>: PartialOrd<_>` | ||
| 6 | ... | ||
| 7 | LL | 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` | ||
| 17 | note: the trait `Iterator` must be implemented | ||
| 18 | --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | ||
| 19 | help: consider annotating `P<Q>` with `#[derive(PartialEq, PartialOrd)]` | ||
| 20 | | | ||
| 21 | LL + #[derive(PartialEq, PartialOrd)] | ||
| 22 | LL | struct P<Q>(Q); | ||
| 23 | | | ||
| 24 | |||
| 25 | error: aborting due to 1 previous error | ||
| 26 | |||
| 27 | For 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"] |
| 1077 | message = "Some changes occurred in `std_detect`" | 1077 | message = "Some changes occurred in `std_detect`" |
| 1078 | cc = ["@Amanieu", "@folkertdev", "@sayantn"] | 1078 | cc = ["@Amanieu", "@folkertdev", "@sayantn"] |
| 1079 | 1079 | ||
| 1080 | [mentions."library/core/src/intrinsics/simd.rs"] | 1080 | [mentions."library/core/src/intrinsics/simd/mod.rs"] |
| 1081 | message = """ | 1081 | message = """ |
| 1082 | Some changes occurred to the platform-builtins intrinsics. Make sure the | 1082 | Some changes occurred to the platform-builtins intrinsics. Make sure the |
| 1083 | LLVM backend as well as portable-simd gets adapted for the changes. | 1083 | LLVM backend as well as portable-simd gets adapted for the changes. |