diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index ca6128b6f1be4..cca1d499088f4 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -10,8 +10,8 @@ use tracing::{debug, trace};
use crate::{
AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
- LayoutData, Niche, NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding,
- TargetDataLayout, Variants, WrappingRange,
+ LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
+ StructKind, TagEncoding, TargetDataLayout, Variants, WrappingRange,
};
mod coroutine;
@@ -204,13 +204,19 @@ impl LayoutCalculator {
&self,
element: F,
count: u64,
+ number_of_vectors: NumScalableVectors,
) -> LayoutCalculatorResult
where
FieldIdx: Idx,
VariantIdx: Idx,
F: AsRef> + fmt::Debug,
{
- vector_type_layout(SimdVectorKind::Scalable, self.cx.data_layout(), element, count)
+ vector_type_layout(
+ SimdVectorKind::Scalable(number_of_vectors),
+ self.cx.data_layout(),
+ element,
+ count,
+ )
}
pub fn simd_type(
@@ -1526,7 +1532,7 @@ impl LayoutCalculator {
enum SimdVectorKind {
/// `#[rustc_scalable_vector]`
- Scalable,
+ Scalable(NumScalableVectors),
/// `#[repr(simd, packed)]`
PackedFixed,
/// `#[repr(simd)]`
@@ -1559,9 +1565,10 @@ where
let size =
elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;
let (repr, align) = match kind {
- SimdVectorKind::Scalable => {
- (BackendRepr::SimdScalableVector { element, count }, dl.llvmlike_vector_align(size))
- }
+ SimdVectorKind::Scalable(number_of_vectors) => (
+ BackendRepr::SimdScalableVector { element, count, number_of_vectors },
+ dl.llvmlike_vector_align(size),
+ ),
// Non-power-of-two vectors have padding up to the next power-of-two.
// If we're a packed repr, remove the padding while keeping the alignment as close
// to a vector as possible.
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 253dff6f8e75c..f148b776852aa 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -67,12 +67,6 @@ pub use layout::{FIRST_VARIANT, FieldIdx, LayoutCalculator, LayoutCalculatorErro
#[cfg(feature = "nightly")]
pub use layout::{Layout, TyAbiInterface, TyAndLayout};
-/// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in `rustc_middle`.
-#[cfg(feature = "nightly")]
-pub trait HashStableContext {}
-
#[derive(Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "nightly",
@@ -1702,6 +1696,28 @@ impl AddressSpace {
pub const ZERO: Self = AddressSpace(0);
}
+/// How many scalable vectors are in a `BackendRepr::ScalableVector`?
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub struct NumScalableVectors(pub u8);
+
+impl NumScalableVectors {
+ /// Returns a `NumScalableVector` for a non-tuple scalable vector (e.g. a single vector).
+ pub fn for_non_tuple() -> Self {
+ NumScalableVectors(1)
+ }
+
+ // Returns `NumScalableVectors` for values of two through eight, which are a valid number of
+ // fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors`
+ // but not for a tuple which would have a field count.
+ pub fn from_field_count(count: usize) -> Option {
+ match count {
+ 2..8 => Some(NumScalableVectors(count as u8)),
+ _ => None,
+ }
+ }
+}
+
/// The way we represent values to the backend
///
/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.
@@ -1720,6 +1736,7 @@ pub enum BackendRepr {
SimdScalableVector {
element: Scalar,
count: u64,
+ number_of_vectors: NumScalableVectors,
},
SimdVector {
element: Scalar,
@@ -1826,8 +1843,12 @@ impl BackendRepr {
BackendRepr::SimdVector { element: element.to_union(), count }
}
BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
- BackendRepr::SimdScalableVector { element, count } => {
- BackendRepr::SimdScalableVector { element: element.to_union(), count }
+ BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
+ BackendRepr::SimdScalableVector {
+ element: element.to_union(),
+ count,
+ number_of_vectors,
+ }
}
}
}
@@ -2167,7 +2188,7 @@ impl LayoutData {
}
/// Returns `true` if the size of the type is only known at runtime.
- pub fn is_runtime_sized(&self) -> bool {
+ pub fn is_scalable_vector(&self) -> bool {
matches!(self.backend_repr, BackendRepr::SimdScalableVector { .. })
}
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 71ec1c5042fda..87633cade1b6a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -31,7 +31,8 @@ use rustc_data_structures::tagged_ptr::Tag;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable};
pub use rustc_span::AttrId;
use rustc_span::{
- ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym,
+ ByteSymbol, DUMMY_SP, ErrorGuaranteed, HashStableContext, Ident, Span, Spanned, Symbol, kw,
+ respan, sym,
};
use thin_vec::{ThinVec, thin_vec};
@@ -120,7 +121,7 @@ impl PartialEq<&[Symbol]> for Path {
}
}
-impl HashStable for Path {
+impl HashStable for Path {
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index ac3e77b0b5d6f..4178db1bfb09d 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -36,8 +36,3 @@ pub mod visit;
pub use self::ast::*;
pub use self::ast_traits::{AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
-
-/// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in `rustc_middle`.
-pub trait HashStableContext: rustc_span::HashStableContext {}
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 8953391ac58bf..06bd6f03e9350 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable};
use rustc_serialize::{Decodable, Encodable};
-use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
+use rustc_span::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, Symbol, sym};
use thin_vec::ThinVec;
use crate::ast::AttrStyle;
@@ -826,7 +826,7 @@ impl FromIterator for TokenStream {
impl HashStable for TokenStream
where
- Hcx: crate::HashStableContext,
+ Hcx: HashStableContext,
{
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
for sub_tt in self.iter() {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 830eb3d6d8170..1b615b611258f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -14,31 +14,22 @@ use crate::errors;
/// The common case.
macro_rules! gate {
- ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
+ ($visitor:expr, $feature:ident, $span:expr, $explain:expr $(, $help:expr)?) => {{
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
- feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
- }
- }};
- ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
- if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
- feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
+ feature_err($visitor.sess, sym::$feature, $span, $explain)
+ $(.with_help($help))?
+ .emit();
}
}};
}
/// The unusual case, where the `has_feature` condition is non-standard.
macro_rules! gate_alt {
- ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
+ ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr $(, $notes:expr)?) => {{
if !$has_feature && !$span.allows_unstable($name) {
- feature_err(&$visitor.sess, $name, $span, $explain).emit();
- }
- }};
- ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr, $notes: expr) => {{
- if !$has_feature && !$span.allows_unstable($name) {
- let mut diag = feature_err(&$visitor.sess, $name, $span, $explain);
- for note in $notes {
- diag.note(*note);
- }
+ #[allow(unused_mut)]
+ let mut diag = feature_err($visitor.sess, $name, $span, $explain);
+ $(for ¬e in $notes { diag.note(note); })?
diag.emit();
}
}};
@@ -51,21 +42,12 @@ macro_rules! gate_multi {
let spans: Vec<_> =
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
if !spans.is_empty() {
- feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit();
+ feature_err($visitor.sess, sym::$feature, spans, $explain).emit();
}
}
}};
}
-/// The legacy case.
-macro_rules! gate_legacy {
- ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
- if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
- feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
- }
- }};
-}
-
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
PostExpansionVisitor { sess, features }.visit_attribute(attr)
}
@@ -77,6 +59,15 @@ struct PostExpansionVisitor<'a> {
features: &'a Features,
}
+// -----------------------------------------------------------------------------
+// POST-EXPANSION FEATURE GATES FOR UNSTABLE ATTRIBUTES ETC.
+// **LEGACY** POST-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY**
+// -----------------------------------------------------------------------------
+
+// IMPORTANT: Don't add any new post-expansion feature gates for new unstable syntax!
+// It's a legacy mechanism for them.
+// Instead, register a pre-expansion feature gate using `gate_all` in fn `check_crate`.
+
impl<'a> PostExpansionVisitor<'a> {
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) {
@@ -89,14 +80,14 @@ impl<'a> PostExpansionVisitor<'a> {
if let ast::TyKind::ImplTrait(..) = ty.kind {
if self.in_associated_ty {
gate!(
- &self.vis,
+ self.vis,
impl_trait_in_assoc_type,
ty.span,
"`impl Trait` in associated types is unstable"
);
} else {
gate!(
- &self.vis,
+ self.vis,
type_alias_impl_trait,
ty.span,
"`impl Trait` in type aliases is unstable"
@@ -211,7 +202,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(sym::simd) {
gate!(
- &self,
+ self,
repr_simd,
attr.span,
"SIMD types are experimental and possibly buggy"
@@ -224,35 +215,30 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) => {
if let ast::ImplPolarity::Negative(span) = of_trait.polarity {
gate!(
- &self,
+ self,
negative_impls,
span.to(of_trait.trait_ref.path.span),
- "negative trait bounds are not fully implemented; \
- use marker types for now"
+ "negative impls are experimental",
+ "use marker types for now"
);
}
if let ast::Defaultness::Default(_) = of_trait.defaultness {
- gate!(&self, specialization, i.span, "specialization is unstable");
+ gate!(self, specialization, i.span, "specialization is experimental");
}
}
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
- gate!(
- &self,
- auto_traits,
- i.span,
- "auto traits are experimental and possibly buggy"
- );
+ gate!(self, auto_traits, i.span, "auto traits are experimental and possibly buggy");
}
ast::ItemKind::TraitAlias(..) => {
- gate!(&self, trait_alias, i.span, "trait aliases are experimental");
+ gate!(self, trait_alias, i.span, "trait aliases are experimental");
}
ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => {
let msg = "`macro` is experimental";
- gate!(&self, decl_macro, i.span, msg);
+ gate!(self, decl_macro, i.span, msg);
}
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
@@ -264,7 +250,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}) => {
// Make sure this is only allowed if the feature gate is enabled.
// #![feature(min_generic_const_args)]
- gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable");
+ gate!(self, min_generic_const_args, i.span, "top-level `type const` are unstable");
}
_ => {}
@@ -280,7 +266,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
if links_to_llvm {
gate!(
- &self,
+ self,
link_llvm_intrinsics,
i.span,
"linking to LLVM intrinsics is experimental"
@@ -288,7 +274,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
ast::ForeignItemKind::TyAlias(..) => {
- gate!(&self, extern_types, i.span, "extern types are experimental");
+ gate!(self, extern_types, i.span, "extern types are experimental");
}
ast::ForeignItemKind::MacCall(..) => {}
}
@@ -303,10 +289,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
self.check_late_bound_lifetime_defs(&fn_ptr_ty.generic_params);
}
ast::TyKind::Never => {
- gate!(&self, never_type, ty.span, "the `!` type is experimental");
+ gate!(self, never_type, ty.span, "the `!` type is experimental");
}
ast::TyKind::Pat(..) => {
- gate!(&self, pattern_types, ty.span, "pattern types are unstable");
+ gate!(self, pattern_types, ty.span, "pattern types are unstable");
}
_ => {}
}
@@ -339,7 +325,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&& let ast::FnRetTy::Ty(ref ty) = generic_args.output
&& matches!(ty.kind, ast::TyKind::Never)
{
- gate!(&self, never_type, ty.span, "the `!` type is experimental");
+ gate!(self, never_type, ty.span, "the `!` type is experimental");
}
visit::walk_generic_args(self, args);
}
@@ -348,7 +334,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
match e.kind {
ast::ExprKind::TryBlock(_, None) => {
// `try { ... }` is old and is only gated post-expansion here.
- gate!(&self, try_blocks, e.span, "`try` expression is experimental");
+ gate!(self, try_blocks, e.span, "`try` expression is experimental");
}
ast::ExprKind::TryBlock(_, Some(_)) => {
// `try_blocks_heterogeneous` is new, and gated pre-expansion instead.
@@ -359,10 +345,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
..
}) => match suffix {
Some(sym::f16) => {
- gate!(&self, f16, e.span, "the type `f16` is unstable")
+ gate!(self, f16, e.span, "the type `f16` is unstable")
}
Some(sym::f128) => {
- gate!(&self, f128, e.span, "the type `f128` is unstable")
+ gate!(self, f128, e.span, "the type `f128` is unstable")
}
_ => (),
},
@@ -381,7 +367,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
};
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate!(
- &self,
+ self,
half_open_range_patterns_in_slices,
pat.span,
"`X..` patterns in slices are experimental"
@@ -390,7 +376,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
PatKind::Box(..) => {
- gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
+ gate!(self, box_patterns, pattern.span, "box pattern syntax is experimental");
}
_ => {}
}
@@ -412,7 +398,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
- gate!(&self, c_variadic, span, "C-variadic functions are unstable");
+ gate!(self, c_variadic, span, "C-variadic functions are unstable");
}
visit::walk_fn(self, fn_kind)
@@ -424,7 +410,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate!(
- &self,
+ self,
associated_type_defaults,
i.span,
"associated type defaults are unstable"
@@ -441,18 +427,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}) => {
// Make sure this is only allowed if the feature gate is enabled.
// #![feature(min_generic_const_args)]
- gate!(
- &self,
- min_generic_const_args,
- i.span,
- "associated `type const` are unstable"
- );
+ gate!(self, min_generic_const_args, i.span, "associated `type const` are unstable");
// Make sure associated `type const` defaults in traits are only allowed
// if the feature gate is enabled.
// #![feature(associated_type_defaults)]
if ctxt == AssocCtxt::Trait && rhs.is_some() {
gate!(
- &self,
+ self,
associated_type_defaults,
i.span,
"associated type defaults are unstable"
@@ -469,13 +450,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
self.features.specialization() || (is_fn && self.features.min_specialization()),
sym::specialization,
i.span,
- "specialization is unstable"
+ "specialization is experimental"
);
}
visit::walk_assoc_item(self, i, ctxt)
}
}
+// -----------------------------------------------------------------------------
+
pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
maybe_stage_features(sess, features, krate);
check_incompatible_features(sess, features);
@@ -484,166 +467,170 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
let mut visitor = PostExpansionVisitor { sess, features };
+ // -----------------------------------------------------------------------------
+ // PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX
+ // -----------------------------------------------------------------------------
+
let spans = sess.psess.gated_spans.spans.borrow();
macro_rules! gate_all {
- ($gate:ident, $msg:literal) => {
- if let Some(spans) = spans.get(&sym::$gate) {
- for span in spans {
- gate!(&visitor, $gate, *span, $msg);
- }
- }
- };
- ($gate:ident, $msg:literal, $help:literal) => {
- if let Some(spans) = spans.get(&sym::$gate) {
- for span in spans {
- gate!(&visitor, $gate, *span, $msg, $help);
- }
+ ($feature:ident, $explain:literal $(, $help:literal)?) => {
+ for &span in spans.get(&sym::$feature).into_iter().flatten() {
+ gate!(visitor, $feature, span, $explain $(, $help)?);
}
};
}
+
+ // tidy-alphabetical-start
+ gate_all!(async_for_loop, "`for await` loops are experimental");
+ gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
+ gate_all!(const_block_items, "const block items are experimental");
+ gate_all!(const_closures, "const closures are experimental");
+ gate_all!(const_trait_impl, "const trait impls are experimental");
+ gate_all!(contracts, "contracts are incomplete");
+ gate_all!(contracts_internals, "contract internal machinery is for internal use only");
+ gate_all!(coroutines, "coroutine syntax is experimental");
+ gate_all!(default_field_values, "default values on fields are experimental");
+ gate_all!(ergonomic_clones, "ergonomic clones are experimental");
+ gate_all!(explicit_tail_calls, "`become` expression is experimental");
+ gate_all!(final_associated_functions, "`final` on trait functions is experimental");
+ gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
+ gate_all!(frontmatter, "frontmatters are experimental");
+ gate_all!(gen_blocks, "gen blocks are experimental");
+ gate_all!(generic_const_items, "generic const items are experimental");
+ gate_all!(global_registration, "global registration is experimental");
+ gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
+ gate_all!(impl_restriction, "`impl` restrictions are experimental");
+ gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
+ gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
+ gate_all!(mut_ref, "mutable by-reference bindings are experimental");
+ gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
+ gate_all!(postfix_match, "postfix match is experimental");
+ gate_all!(return_type_notation, "return type notation is experimental");
+ gate_all!(super_let, "`super let` is experimental");
+ gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental");
+ gate_all!(unsafe_binders, "unsafe binder types are experimental");
+ gate_all!(unsafe_fields, "`unsafe` fields are experimental");
+ gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
+ gate_all!(yeet_expr, "`do yeet` expression is experimental");
+ // tidy-alphabetical-end
+
gate_all!(
async_trait_bounds,
"`async` trait bounds are unstable",
"use the desugared name of the async trait, such as `AsyncFn`"
);
- gate_all!(async_for_loop, "`for await` loops are experimental");
gate_all!(
closure_lifetime_binder,
"`for<...>` binders for closures are experimental",
"consider removing `for<...>`"
);
- gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
- // yield can be enabled either by `coroutines` or `gen_blocks`
- if let Some(spans) = spans.get(&sym::yield_expr) {
- for span in spans {
- if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
- && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
- && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
- {
- // Emit yield_expr as the error, since that will be sufficient. You can think of it
- // as coroutines and gen_blocks imply yield_expr.
- feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental")
- .emit();
- }
- }
- }
- gate_all!(gen_blocks, "gen blocks are experimental");
- gate_all!(const_trait_impl, "const trait impls are experimental");
gate_all!(
half_open_range_patterns_in_slices,
"half-open range patterns in slices are unstable"
);
- gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental");
- gate_all!(yeet_expr, "`do yeet` expression is experimental");
- gate_all!(const_closures, "const closures are experimental");
- gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
- gate_all!(ergonomic_clones, "ergonomic clones are experimental");
- gate_all!(explicit_tail_calls, "`become` expression is experimental");
- gate_all!(generic_const_items, "generic const items are experimental");
- gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
- gate_all!(default_field_values, "default values on fields are experimental");
- gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
- gate_all!(postfix_match, "postfix match is experimental");
- gate_all!(mut_ref, "mutable by-reference bindings are experimental");
- gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
- // associated_const_equality is stabilized as part of min_generic_const_args
- if let Some(spans) = spans.get(&sym::associated_const_equality) {
- for span in spans {
- if !visitor.features.min_generic_const_args()
- && !span.allows_unstable(sym::min_generic_const_args)
- {
- feature_err(
- &visitor.sess,
- sym::min_generic_const_args,
- *span,
- "associated const equality is incomplete",
- )
- .emit();
- }
- }
+
+ // `associated_const_equality` will be stabilized as part of `min_generic_const_args`.
+ for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() {
+ gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete");
}
- // `mgca_type_const_syntax` is part of `min_generic_const_args` so either
- // or both are enabled we don't need to emit a feature error.
- if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) {
- for span in spans {
- if visitor.features.min_generic_const_args()
- || visitor.features.mgca_type_const_syntax()
- || span.allows_unstable(sym::min_generic_const_args)
- || span.allows_unstable(sym::mgca_type_const_syntax)
- {
- continue;
- }
- feature_err(
- &visitor.sess,
- sym::min_generic_const_args,
- *span,
- "`type const` syntax is experimental",
- )
- .emit();
+
+ // `mgca_type_const_syntax` is part of `min_generic_const_args` so if
+ // either or both are enabled we don't need to emit a feature error.
+ for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() {
+ if visitor.features.min_generic_const_args()
+ || visitor.features.mgca_type_const_syntax()
+ || span.allows_unstable(sym::min_generic_const_args)
+ || span.allows_unstable(sym::mgca_type_const_syntax)
+ {
+ continue;
}
+ feature_err(
+ visitor.sess,
+ sym::min_generic_const_args,
+ span,
+ "`type const` syntax is experimental",
+ )
+ .emit();
}
- gate_all!(global_registration, "global registration is experimental");
- gate_all!(return_type_notation, "return type notation is experimental");
- gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
- gate_all!(unsafe_fields, "`unsafe` fields are experimental");
- gate_all!(unsafe_binders, "unsafe binder types are experimental");
- gate_all!(contracts, "contracts are incomplete");
- gate_all!(contracts_internals, "contract internal machinery is for internal use only");
- gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
- gate_all!(super_let, "`super let` is experimental");
- gate_all!(frontmatter, "frontmatters are experimental");
- gate_all!(coroutines, "coroutine syntax is experimental");
- gate_all!(const_block_items, "const block items are experimental");
- gate_all!(final_associated_functions, "`final` on trait functions is experimental");
- gate_all!(impl_restriction, "`impl` restrictions are experimental");
+ // Negative bounds are *super* internal.
+ // Under no circumstances do we want to advertise the feature name to users!
+ if !visitor.features.negative_bounds() {
+ for &span in spans.get(&sym::negative_bounds).into_iter().flatten() {
+ sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
+ }
+ }
if !visitor.features.never_patterns() {
- if let Some(spans) = spans.get(&sym::never_patterns) {
- for &span in spans {
- if span.allows_unstable(sym::never_patterns) {
- continue;
- }
- let sm = sess.source_map();
- // We gate two types of spans: the span of a `!` pattern, and the span of a
- // match arm without a body. For the latter we want to give the user a normal
- // error.
- if let Ok(snippet) = sm.span_to_snippet(span)
- && snippet == "!"
- {
- feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
- .emit();
- } else {
- let suggestion = span.shrink_to_hi();
- sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
- }
+ for &span in spans.get(&sym::never_patterns).into_iter().flatten() {
+ if span.allows_unstable(sym::never_patterns) {
+ continue;
+ }
+ // We gate two types of spans: the span of a `!` pattern, and the span of a
+ // match arm without a body. For the latter we want to give the user a normal
+ // error.
+ if let Ok("!") = sess.source_map().span_to_snippet(span).as_deref() {
+ feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
+ .emit();
+ } else {
+ let suggestion = span.shrink_to_hi();
+ sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
}
}
}
- if !visitor.features.negative_bounds() {
- for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
- sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
+ // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`.
+ for &span in spans.get(&sym::yield_expr).into_iter().flatten() {
+ if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
+ && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
+ && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
+ {
+ // Only mentioned `yield_expr` in the diagnostic since that'll be sufficient.
+ // You can think of it as `coroutines` and `gen_blocks` implying `yield_expr`.
+ feature_err(visitor.sess, sym::yield_expr, span, "yield syntax is experimental").emit();
}
}
- // All uses of `gate_all_legacy_dont_use!` below this point were added in #65742,
- // and subsequently disabled (with the non-early gating readded).
- // We emit an early future-incompatible warning for these.
- // New syntax gates should go above here to get a hard error gate.
- macro_rules! gate_all_legacy_dont_use {
- ($gate:ident, $msg:literal) => {
- for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
- gate_legacy!(&visitor, $gate, *span, $msg);
+ // -----------------------------------------------------------------------------
+ // **LEGACY** SOFT PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY**
+ // -----------------------------------------------------------------------------
+
+ // IMPORTANT: Do not extend the list below! New syntax should go above and use `gate_all`.
+
+ // FIXME(#154045): Migrate all of these to erroring feature gates and
+ // remove the corresponding post-expansion feature gates.
+
+ macro_rules! soft_gate_all_legacy_dont_use {
+ ($feature:ident, $explain:literal) => {
+ for &span in spans.get(&sym::$feature).into_iter().flatten() {
+ if !visitor.features.$feature() && !span.allows_unstable(sym::$feature) {
+ feature_warn(&visitor.sess, sym::$feature, span, $explain);
+ }
}
};
}
- gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
- gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
- gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
- gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
- gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
+ // tidy-alphabetical-start
+ soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
+ soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
+ soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
+ soft_gate_all_legacy_dont_use!(negative_impls, "negative impls are experimental");
+ soft_gate_all_legacy_dont_use!(specialization, "specialization is experimental");
+ soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
+ soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
+ // tidy-alphabetical-end
+
+ for &span in spans.get(&sym::min_specialization).into_iter().flatten() {
+ if !visitor.features.specialization()
+ && !visitor.features.min_specialization()
+ && !span.allows_unstable(sym::specialization)
+ && !span.allows_unstable(sym::min_specialization)
+ {
+ feature_warn(visitor.sess, sym::specialization, span, "specialization is experimental");
+ }
+ }
+
+ // -----------------------------------------------------------------------------
visit::walk_crate(&mut visitor, krate);
}
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 3eb0fd95284a1..08964113b944a 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -24,7 +24,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
+ LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
use rustc_span::Span;
@@ -943,8 +944,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
.get_address(self.location)
}
- fn scalable_alloca(&mut self, _elt: u64, _align: Align, _element_ty: Ty<'_>) -> RValue<'gcc> {
- todo!()
+ fn alloca_with_ty(&mut self, ty: TyAndLayout<'tcx>) -> RValue<'gcc> {
+ self.alloca(ty.layout.size, ty.layout.align.abi)
}
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 9e548ac0a8b01..dd0064d34bc4a 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -145,6 +145,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
self.const_int(self.type_i32(), i as i64)
}
+ fn const_i64(&self, i: i64) -> RValue<'gcc> {
+ self.const_int(self.type_i64(), i)
+ }
+
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
self.gcc_int(typ, int)
}
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index f3508c10d1f61..9e59d7aa7c20a 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -7,8 +7,7 @@ pub(crate) mod autodiff;
pub(crate) mod gpu_offload;
use libc::{c_char, c_uint};
-use rustc_abi as abi;
-use rustc_abi::{Align, Size, WrappingRange};
+use rustc_abi::{self as abi, Align, Size, WrappingRange};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
@@ -616,21 +615,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
}
- fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value {
+ fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value {
let mut bx = Builder::with_cx(self.cx);
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
- let llvm_ty = match element_ty.kind() {
- ty::Bool => bx.type_i1(),
- ty::Int(int_ty) => self.cx.type_int_from_ty(*int_ty),
- ty::Uint(uint_ty) => self.cx.type_uint_from_ty(*uint_ty),
- ty::Float(float_ty) => self.cx.type_float_from_ty(*float_ty),
- _ => unreachable!("scalable vectors can only contain a bool, int, uint or float"),
- };
+ let scalable_vector_ty = layout.llvm_type(self.cx);
unsafe {
- let ty = llvm::LLVMScalableVectorType(llvm_ty, elt.try_into().unwrap());
- let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, ty, UNNAMED);
- llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
+ let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, scalable_vector_ty, UNNAMED);
+ llvm::LLVMSetAlignment(alloca, layout.align.abi.bytes() as c_uint);
alloca
}
}
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index a134e97cc8915..dadf8e9e7d5fa 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -159,6 +159,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
self.const_int(self.type_i32(), i as i64)
}
+ fn const_i64(&self, i: i64) -> &'ll Value {
+ self.const_int(self.type_i64(), i as i64)
+ }
+
fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
debug_assert!(
self.type_kind(t) == TypeKind::Integer,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index e02c4ae6ea695..80d939a25701e 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -1134,11 +1134,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
fn_abi_request: FnAbiRequest<'tcx>,
) -> ! {
match err {
- FnAbiError::Layout(
- LayoutError::SizeOverflow(_)
- | LayoutError::Cycle(_)
- | LayoutError::InvalidSimd { .. },
- ) => {
+ FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => {
self.tcx.dcx().emit_fatal(Spanned { span, node: err });
}
_ => match fn_abi_request {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
index 52d04625749b9..1172660af4a29 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
@@ -35,6 +35,14 @@ declare_constant!(DW_OP_plus_uconst: u64);
/// Double-checked by a static assertion in `RustWrapper.cpp`.
#[allow(non_upper_case_globals)]
pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
+#[allow(non_upper_case_globals)]
+pub(crate) const DW_OP_constu: u64 = 0x10;
+#[allow(non_upper_case_globals)]
+pub(crate) const DW_OP_minus: u64 = 0x1c;
+#[allow(non_upper_case_globals)]
+pub(crate) const DW_OP_mul: u64 = 0x1e;
+#[allow(non_upper_case_globals)]
+pub(crate) const DW_OP_bregx: u64 = 0x92;
// It describes the actual value of a source variable which might not exist in registers or in memory.
#[allow(non_upper_case_globals)]
pub(crate) const DW_OP_stack_value: u64 = 0x9f;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 04c0b6953290c..c91d3ec63a028 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -3,10 +3,10 @@ use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::sync::Arc;
-use std::{iter, ptr};
+use std::{assert_matches, iter, ptr};
use libc::{c_longlong, c_uint};
-use rustc_abi::{Align, Size};
+use rustc_abi::{Align, Layout, NumScalableVectors, Size};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::{CtorKind, DefKind};
@@ -16,12 +16,12 @@ use rustc_middle::ty::layout::{
HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
};
use rustc_middle::ty::{
- self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
+ self, AdtDef, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
use rustc_symbol_mangling::typeid_for_trait_ref;
-use rustc_target::spec::DebuginfoKind;
+use rustc_target::spec::{Arch, DebuginfoKind};
use smallvec::smallvec;
use tracing::{debug, instrument};
@@ -33,7 +33,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
use crate::common::{AsCCharPtr, CodegenCx};
use crate::debuginfo::metadata::type_map::build_type_with_children;
-use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
+use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind};
use crate::debuginfo::{DIBuilderExt, dwarf_const};
use crate::llvm::debuginfo::{
DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,
@@ -1039,6 +1039,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
span: Span,
) -> DINodeCreationResult<'ll> {
let struct_type = unique_type_id.expect_ty();
+
let ty::Adt(adt_def, _) = struct_type.kind() else {
bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
};
@@ -1051,6 +1052,21 @@ fn build_struct_type_di_node<'ll, 'tcx>(
} else {
None
};
+ let name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
+
+ if struct_type.is_scalable_vector() {
+ let parts = struct_type.scalable_vector_parts(cx.tcx).unwrap();
+ return build_scalable_vector_di_node(
+ cx,
+ unique_type_id,
+ name,
+ *adt_def,
+ parts,
+ struct_type_and_layout.layout,
+ def_location,
+ containing_scope,
+ );
+ }
type_map::build_type_with_children(
cx,
@@ -1058,7 +1074,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
cx,
Stub::Struct,
unique_type_id,
- &compute_debuginfo_type_name(cx.tcx, struct_type, false),
+ &name,
def_location,
size_and_align_of(struct_type_and_layout),
Some(containing_scope),
@@ -1101,6 +1117,100 @@ fn build_struct_type_di_node<'ll, 'tcx>(
)
}
+/// Generate debuginfo for a `#[rustc_scalable_vector]` type.
+///
+/// Debuginfo for a scalable vector uses a derived type based on a composite type. The composite
+/// type has the `DIFlagVector` flag set and is based on the element type of the scalable vector.
+/// The composite type has a subrange from 0 to an expression that calculates the number of
+/// elements in the vector.
+///
+/// ```text,ignore
+/// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...)
+/// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4)
+/// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
+/// !4 = !{!5}
+/// !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))
+/// ```
+///
+/// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this
+/// is generated for C and C++.
+fn build_scalable_vector_di_node<'ll, 'tcx>(
+ cx: &CodegenCx<'ll, 'tcx>,
+ unique_type_id: UniqueTypeId<'tcx>,
+ name: String,
+ adt_def: AdtDef<'tcx>,
+ (element_count, element_ty, number_of_vectors): (u16, Ty<'tcx>, NumScalableVectors),
+ layout: Layout<'tcx>,
+ def_location: Option>,
+ containing_scope: &'ll DIScope,
+) -> DINodeCreationResult<'ll> {
+ use dwarf_const::{DW_OP_bregx, DW_OP_constu, DW_OP_minus, DW_OP_mul};
+ assert!(adt_def.repr().scalable());
+ // This logic is specific to AArch64 for the moment, but can be extended for other architectures
+ // later.
+ assert_matches!(cx.tcx.sess.target.arch, Arch::AArch64);
+
+ let (file_metadata, line_number) = if let Some(def_location) = def_location {
+ (def_location.0, def_location.1)
+ } else {
+ (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+ };
+
+ let (bitstride, element_di_node) = if element_ty.is_bool() {
+ (Some(llvm::LLVMValueAsMetadata(cx.const_i64(1))), type_di_node(cx, cx.tcx.types.u8))
+ } else {
+ (None, type_di_node(cx, element_ty))
+ };
+
+ let number_of_elements: u64 = (element_count as u64) * (number_of_vectors.0 as u64);
+ let number_of_elements_per_vg = number_of_elements / 2;
+ let mut expr = smallvec::SmallVec::<[u64; 9]>::new();
+ // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
+ expr.push(DW_OP_constu); // Push a constant onto the stack
+ expr.push(number_of_elements_per_vg);
+ expr.push(DW_OP_bregx); // Push the value of a register + offset on to the stack
+ expr.push(/* AArch64::VG */ 46u64);
+ expr.push(0u64);
+ expr.push(DW_OP_mul); // Multiply top two values on stack
+ expr.push(DW_OP_constu); // Push a constant onto the stack
+ expr.push(1u64);
+ expr.push(DW_OP_minus); // Subtract top two values on stack
+
+ let di_builder = DIB(cx);
+ let metadata = unsafe {
+ let upper = llvm::LLVMDIBuilderCreateExpression(di_builder, expr.as_ptr(), expr.len());
+ let subrange = llvm::LLVMRustDIGetOrCreateSubrange(
+ di_builder,
+ /* CountNode */ None,
+ llvm::LLVMValueAsMetadata(cx.const_i64(0)),
+ upper,
+ /* Stride */ None,
+ );
+ let subscripts = create_DIArray(di_builder, &[Some(subrange)]);
+ let vector_ty = llvm::LLVMRustDICreateVectorType(
+ di_builder,
+ /* Size */ 0,
+ layout.align.bits() as u32,
+ element_di_node,
+ subscripts,
+ bitstride,
+ );
+ llvm::LLVMDIBuilderCreateTypedef(
+ di_builder,
+ vector_ty,
+ name.as_ptr(),
+ name.len(),
+ file_metadata,
+ line_number,
+ Some(containing_scope),
+ layout.align.bits() as u32,
+ )
+ };
+
+ debug_context(cx).type_map.insert(unique_type_id, metadata);
+ DINodeCreationResult { di_node: metadata, already_stored_in_typemap: true }
+}
+
//=-----------------------------------------------------------------------------
// Tuples
//=-----------------------------------------------------------------------------
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 39bf4c10dab18..3e600914d6f42 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -3,7 +3,8 @@ use std::ffi::c_uint;
use std::{assert_matches, ptr};
use rustc_abi::{
- Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,
+ Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size,
+ WrappingRange,
};
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -605,6 +606,136 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
self.pointercast(val, self.type_ptr())
}
+ sym::sve_cast => {
+ let Some((in_cnt, in_elem, in_num_vecs)) =
+ args[0].layout.ty.scalable_vector_parts(self.cx.tcx)
+ else {
+ bug!("input parameter to `sve_cast` was not scalable vector");
+ };
+ let out_layout = self.layout_of(fn_args.type_at(1));
+ let Some((out_cnt, out_elem, out_num_vecs)) =
+ out_layout.ty.scalable_vector_parts(self.cx.tcx)
+ else {
+ bug!("output parameter to `sve_cast` was not scalable vector");
+ };
+ assert_eq!(in_cnt, out_cnt);
+ assert_eq!(in_num_vecs, out_num_vecs);
+ let out_llty = self.backend_type(out_layout);
+ match simd_cast(self, sym::simd_cast, args, out_llty, in_elem, out_elem) {
+ Some(val) => val,
+ _ => bug!("could not cast scalable vectors"),
+ }
+ }
+
+ sym::sve_tuple_create2 => {
+ assert_matches!(
+ self.layout_of(fn_args.type_at(0)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(1),
+ ..
+ }
+ );
+ let tuple_ty = self.layout_of(fn_args.type_at(1));
+ assert_matches!(
+ tuple_ty.backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(2),
+ ..
+ }
+ );
+ let ret = self.const_poison(self.backend_type(tuple_ty));
+ let ret = self.insert_value(ret, args[0].immediate(), 0);
+ self.insert_value(ret, args[1].immediate(), 1)
+ }
+
+ sym::sve_tuple_create3 => {
+ assert_matches!(
+ self.layout_of(fn_args.type_at(0)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(1),
+ ..
+ }
+ );
+ let tuple_ty = self.layout_of(fn_args.type_at(1));
+ assert_matches!(
+ tuple_ty.backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(3),
+ ..
+ }
+ );
+ let ret = self.const_poison(self.backend_type(tuple_ty));
+ let ret = self.insert_value(ret, args[0].immediate(), 0);
+ let ret = self.insert_value(ret, args[1].immediate(), 1);
+ self.insert_value(ret, args[2].immediate(), 2)
+ }
+
+ sym::sve_tuple_create4 => {
+ assert_matches!(
+ self.layout_of(fn_args.type_at(0)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(1),
+ ..
+ }
+ );
+ let tuple_ty = self.layout_of(fn_args.type_at(1));
+ assert_matches!(
+ tuple_ty.backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(4),
+ ..
+ }
+ );
+ let ret = self.const_poison(self.backend_type(tuple_ty));
+ let ret = self.insert_value(ret, args[0].immediate(), 0);
+ let ret = self.insert_value(ret, args[1].immediate(), 1);
+ let ret = self.insert_value(ret, args[2].immediate(), 2);
+ self.insert_value(ret, args[3].immediate(), 3)
+ }
+
+ sym::sve_tuple_get => {
+ assert_matches!(
+ self.layout_of(fn_args.type_at(0)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8),
+ ..
+ }
+ );
+ assert_matches!(
+ self.layout_of(fn_args.type_at(1)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(1),
+ ..
+ }
+ );
+ self.extract_value(
+ args[0].immediate(),
+ fn_args.const_at(2).to_leaf().to_i32() as u64,
+ )
+ }
+
+ sym::sve_tuple_set => {
+ assert_matches!(
+ self.layout_of(fn_args.type_at(0)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8),
+ ..
+ }
+ );
+ assert_matches!(
+ self.layout_of(fn_args.type_at(1)).backend_repr,
+ BackendRepr::SimdScalableVector {
+ number_of_vectors: NumScalableVectors(1),
+ ..
+ }
+ );
+ self.insert_value(
+ args[0].immediate(),
+ args[1].immediate(),
+ fn_args.const_at(2).to_leaf().to_i32() as u64,
+ )
+ }
+
_ if name.as_str().starts_with("simd_") => {
// Unpack non-power-of-2 #[repr(packed, simd)] arguments.
// This gives them the expected layout of a regular #[repr(simd)] vector.
@@ -2662,96 +2793,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
out_len
}
);
- // casting cares about nominal type, not just structural type
- if in_elem == out_elem {
- return Ok(args[0].immediate());
- }
-
- #[derive(Copy, Clone)]
- enum Sign {
- Unsigned,
- Signed,
- }
- use Sign::*;
-
- enum Style {
- Float,
- Int(Sign),
- Unsupported,
- }
-
- let (in_style, in_width) = match in_elem.kind() {
- // vectors of pointer-sized integers should've been
- // disallowed before here, so this unwrap is safe.
- ty::Int(i) => (
- Style::Int(Signed),
- i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
- ),
- ty::Uint(u) => (
- Style::Int(Unsigned),
- u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
- ),
- ty::Float(f) => (Style::Float, f.bit_width()),
- _ => (Style::Unsupported, 0),
- };
- let (out_style, out_width) = match out_elem.kind() {
- ty::Int(i) => (
- Style::Int(Signed),
- i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
- ),
- ty::Uint(u) => (
- Style::Int(Unsigned),
- u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
- ),
- ty::Float(f) => (Style::Float, f.bit_width()),
- _ => (Style::Unsupported, 0),
- };
-
- match (in_style, out_style) {
- (Style::Int(sign), Style::Int(_)) => {
- return Ok(match in_width.cmp(&out_width) {
- Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
- Ordering::Equal => args[0].immediate(),
- Ordering::Less => match sign {
- Sign::Signed => bx.sext(args[0].immediate(), llret_ty),
- Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty),
- },
- });
- }
- (Style::Int(Sign::Signed), Style::Float) => {
- return Ok(bx.sitofp(args[0].immediate(), llret_ty));
- }
- (Style::Int(Sign::Unsigned), Style::Float) => {
- return Ok(bx.uitofp(args[0].immediate(), llret_ty));
- }
- (Style::Float, Style::Int(sign)) => {
- return Ok(match (sign, name == sym::simd_as) {
- (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty),
- (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty),
- (_, true) => bx.cast_float_to_int(
- matches!(sign, Sign::Signed),
- args[0].immediate(),
- llret_ty,
- ),
- });
- }
- (Style::Float, Style::Float) => {
- return Ok(match in_width.cmp(&out_width) {
- Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
- Ordering::Equal => args[0].immediate(),
- Ordering::Less => bx.fpext(args[0].immediate(), llret_ty),
- });
- }
- _ => { /* Unsupported. Fallthrough. */ }
+ match simd_cast(bx, name, args, llret_ty, in_elem, out_elem) {
+ Some(val) => return Ok(val),
+ None => return_error!(InvalidMonomorphization::UnsupportedCast {
+ span,
+ name,
+ in_ty,
+ in_elem,
+ ret_ty,
+ out_elem
+ }),
}
- return_error!(InvalidMonomorphization::UnsupportedCast {
- span,
- name,
- in_ty,
- in_elem,
- ret_ty,
- out_elem
- });
}
macro_rules! arith_binary {
($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
@@ -2925,3 +2977,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
span_bug!(span, "unknown SIMD intrinsic");
}
+
+/// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`.
+fn simd_cast<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
+ name: Symbol,
+ args: &[OperandRef<'tcx, &'ll Value>],
+ llret_ty: &'ll Type,
+ in_elem: Ty<'tcx>,
+ out_elem: Ty<'tcx>,
+) -> Option<&'ll Value> {
+ // Casting cares about nominal type, not just structural type
+ if in_elem == out_elem {
+ return Some(args[0].immediate());
+ }
+
+ #[derive(Copy, Clone)]
+ enum Sign {
+ Unsigned,
+ Signed,
+ }
+ use Sign::*;
+
+ enum Style {
+ Float,
+ Int(Sign),
+ Unsupported,
+ }
+
+ let (in_style, in_width) = match in_elem.kind() {
+ // vectors of pointer-sized integers should've been
+ // disallowed before here, so this unwrap is safe.
+ ty::Int(i) => (
+ Style::Int(Signed),
+ i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+ ),
+ ty::Uint(u) => (
+ Style::Int(Unsigned),
+ u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+ ),
+ ty::Float(f) => (Style::Float, f.bit_width()),
+ _ => (Style::Unsupported, 0),
+ };
+ let (out_style, out_width) = match out_elem.kind() {
+ ty::Int(i) => (
+ Style::Int(Signed),
+ i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+ ),
+ ty::Uint(u) => (
+ Style::Int(Unsigned),
+ u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+ ),
+ ty::Float(f) => (Style::Float, f.bit_width()),
+ _ => (Style::Unsupported, 0),
+ };
+
+ match (in_style, out_style) {
+ (Style::Int(sign), Style::Int(_)) => Some(match in_width.cmp(&out_width) {
+ Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty),
+ Ordering::Equal => args[0].immediate(),
+ Ordering::Less => match sign {
+ Sign::Signed => bx.sext(args[0].immediate(), llret_ty),
+ Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty),
+ },
+ }),
+ (Style::Int(Sign::Signed), Style::Float) => Some(bx.sitofp(args[0].immediate(), llret_ty)),
+ (Style::Int(Sign::Unsigned), Style::Float) => {
+ Some(bx.uitofp(args[0].immediate(), llret_ty))
+ }
+ (Style::Float, Style::Int(sign)) => Some(match (sign, name == sym::simd_as) {
+ (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty),
+ (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty),
+ (_, true) => {
+ bx.cast_float_to_int(matches!(sign, Sign::Signed), args[0].immediate(), llret_ty)
+ }
+ }),
+ (Style::Float, Style::Float) => Some(match in_width.cmp(&out_width) {
+ Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty),
+ Ordering::Equal => args[0].immediate(),
+ Ordering::Less => bx.fpext(args[0].immediate(), llret_ty),
+ }),
+ _ => None,
+ }
+}
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 7355d11367920..0ad74c9ca43a7 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2302,6 +2302,23 @@ unsafe extern "C" {
Params: Option<&'a DIArray>,
);
+ pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>(
+ Builder: &DIBuilder<'a>,
+ CountNode: Option<&'a Metadata>,
+ LB: &'a Metadata,
+ UB: &'a Metadata,
+ Stride: Option<&'a Metadata>,
+ ) -> &'a Metadata;
+
+ pub(crate) fn LLVMRustDICreateVectorType<'a>(
+ Builder: &DIBuilder<'a>,
+ Size: u64,
+ AlignInBits: u32,
+ Type: &'a DIType,
+ Subscripts: &'a DIArray,
+ BitStride: Option<&'a Metadata>,
+ ) -> &'a Metadata;
+
pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
Location: &'a DILocation,
BD: c_uint,
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index e586ed0dd6b07..6d0490e4a1f79 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -24,14 +24,54 @@ fn uncached_llvm_type<'a, 'tcx>(
let element = layout.scalar_llvm_type_at(cx, element);
return cx.type_vector(element, count);
}
- BackendRepr::SimdScalableVector { ref element, count } => {
+ BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => {
let element = if element.is_bool() {
cx.type_i1()
} else {
layout.scalar_llvm_type_at(cx, *element)
};
- return cx.type_scalable_vector(element, count);
+ let vector_type = cx.type_scalable_vector(element, count);
+ return match number_of_vectors.0 {
+ 1 => vector_type,
+ 2 => cx.type_struct(&[vector_type, vector_type], false),
+ 3 => cx.type_struct(&[vector_type, vector_type, vector_type], false),
+ 4 => cx.type_struct(&[vector_type, vector_type, vector_type, vector_type], false),
+ 5 => cx.type_struct(
+ &[vector_type, vector_type, vector_type, vector_type, vector_type],
+ false,
+ ),
+ 6 => cx.type_struct(
+ &[vector_type, vector_type, vector_type, vector_type, vector_type, vector_type],
+ false,
+ ),
+ 7 => cx.type_struct(
+ &[
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ ],
+ false,
+ ),
+ 8 => cx.type_struct(
+ &[
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ vector_type,
+ ],
+ false,
+ ),
+ _ => bug!("`#[rustc_scalable_vector]` tuple struct with too many fields"),
+ };
}
BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 2f93f688c316d..60ab13dbc6f76 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -438,8 +438,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if operand.layout.ty.is_scalable_vector()
&& bx.sess().target.arch == rustc_target::spec::Arch::AArch64
{
- let (count, element_ty) =
- operand.layout.ty.scalable_vector_element_count_and_type(bx.tcx());
+ let (count, element_ty, _) =
+ operand.layout.ty.scalable_vector_parts(bx.tcx()).unwrap();
// i.e. `` when `N != 16`
if element_ty.is_bool() && count != 16 {
return;
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index d62e622b6fed3..53518fd816f31 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -1,3 +1,5 @@
+use std::ops::Deref as _;
+
use rustc_abi::{
Align, BackendRepr, FieldIdx, FieldsShape, Size, TagEncoding, VariantIdx, Variants,
};
@@ -109,8 +111,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
bx: &mut Bx,
layout: TyAndLayout<'tcx>,
) -> Self {
- if layout.is_runtime_sized() {
- Self::alloca_runtime_sized(bx, layout)
+ if layout.deref().is_scalable_vector() {
+ Self::alloca_scalable(bx, layout)
} else {
Self::alloca_size(bx, layout.size, layout)
}
@@ -151,16 +153,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
}
}
- fn alloca_runtime_sized>(
+ fn alloca_scalable>(
bx: &mut Bx,
layout: TyAndLayout<'tcx>,
) -> Self {
- let (element_count, ty) = layout.ty.scalable_vector_element_count_and_type(bx.tcx());
- PlaceValue::new_sized(
- bx.scalable_alloca(element_count as u64, layout.align.abi, ty),
- layout.align.abi,
- )
- .with_type(layout)
+ PlaceValue::new_sized(bx.alloca_with_ty(layout), layout.align.abi).with_type(layout)
}
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 05e94b8019f49..5092f28a33f7b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -235,7 +235,7 @@ pub trait BuilderMethods<'a, 'tcx>:
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
- fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value;
+ fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value;
fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index 4178a9742e268..22784a8868ab5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -20,6 +20,7 @@ pub trait ConstCodegenMethods: BackendTypes {
fn const_i8(&self, i: i8) -> Self::Value;
fn const_i16(&self, i: i16) -> Self::Value;
fn const_i32(&self, i: i32) -> Self::Value;
+ fn const_i64(&self, i: i64) -> Self::Value;
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
fn const_u8(&self, i: u8) -> Self::Value;
fn const_u32(&self, i: u32) -> Self::Value;
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 0bfe012bfe7a4..04f0e7099d840 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -107,8 +107,7 @@ impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
| LayoutError::SizeOverflow(_)
| LayoutError::InvalidSimd { .. }
| LayoutError::TooGeneric(_)
- | LayoutError::ReferencesError(_)
- | LayoutError::Cycle(_) => {}
+ | LayoutError::ReferencesError(_) => {}
}
err_inval!(Layout(err))
}
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 78bd709dd4844..cae8bb89233b2 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -8,9 +8,9 @@ use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_data_structures::unord::UnordMap;
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
+use rustc_span::{HashStableContext, Symbol};
use crate::definitions::DefPathData;
use crate::hir;
@@ -712,7 +712,7 @@ impl IntoDiagArg for Namespace {
}
}
-impl ToStableHashKey for Namespace {
+impl ToStableHashKey for Namespace {
type KeyType = Namespace;
#[inline]
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 9c2fec8677854..c2d9f879cd601 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -43,7 +43,6 @@ pub use hir::*;
pub use lang_items::{LangItem, LanguageItems};
pub use rustc_ast::attr::version::*;
pub use stability::*;
-pub use stable_hash_impls::HashStableContext;
pub use target::{MethodKind, Target};
arena_types!(rustc_arena::declare_arena);
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 58649a694880b..a157fc0ccbb0c 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -1,4 +1,5 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_span::HashStableContext;
use rustc_span::def_id::DefPathHash;
use crate::HashIgnoredAttrId;
@@ -8,53 +9,48 @@ use crate::hir::{
use crate::hir_id::ItemLocalId;
use crate::lints::DelayedLints;
-/// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in `rustc_middle`.
-pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {}
-
-impl ToStableHashKey for BodyId {
+impl ToStableHashKey for BodyId {
type KeyType = (DefPathHash, ItemLocalId);
#[inline]
- fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+ fn to_stable_hash_key(&self, hcx: &Hcx) -> (DefPathHash, ItemLocalId) {
let BodyId { hir_id } = *self;
hir_id.to_stable_hash_key(hcx)
}
}
-impl ToStableHashKey for ItemId {
+impl ToStableHashKey for ItemId {
type KeyType = DefPathHash;
#[inline]
- fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+ fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash {
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
-impl ToStableHashKey for TraitItemId {
+impl ToStableHashKey for TraitItemId {
type KeyType = DefPathHash;
#[inline]
- fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+ fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash {
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
-impl ToStableHashKey for ImplItemId {
+impl ToStableHashKey for ImplItemId {
type KeyType = DefPathHash;
#[inline]
- fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+ fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash {
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
-impl ToStableHashKey for ForeignItemId {
+impl ToStableHashKey for ForeignItemId {
type KeyType = DefPathHash;
#[inline]
- fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+ fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash {
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@@ -66,8 +62,8 @@ impl ToStableHashKey for ForeignItemId
// want to pick up on a reference changing its target, so we hash the NodeIds
// in "DefPath Mode".
-impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> {
- fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+impl<'tcx, Hcx: HashStableContext> HashStable for OwnerNodes<'tcx> {
+ fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
// We ignore the `nodes` and `bodies` fields since these refer to information included in
// `hash` which is hashed in the collector and used for the crate hash.
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
@@ -78,15 +74,15 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'
}
}
-impl HashStable for DelayedLints {
- fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+impl HashStable for DelayedLints {
+ fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
let DelayedLints { opt_hash, .. } = *self;
opt_hash.unwrap().hash_stable(hcx, hasher);
}
}
-impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap<'tcx> {
- fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+impl<'tcx, Hcx: HashStableContext> HashStable for AttributeMap<'tcx> {
+ fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
// We ignore the `map` since it refers to information included in `opt_hash` which is
// hashed in the collector and used for the crate hash.
let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self;
@@ -94,8 +90,8 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap
}
}
-impl HashStable for HashIgnoredAttrId {
- fn hash_stable(&self, _hcx: &mut HirCtx, _hasher: &mut StableHasher) {
+impl HashStable for HashIgnoredAttrId {
+ fn hash_stable(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {
/* we don't hash HashIgnoredAttrId, we ignore them */
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index b1dc593331c6c..58454cfc489c6 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -783,6 +783,13 @@ pub(crate) fn check_intrinsic_type(
sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)),
sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)),
+ sym::sve_cast => (2, 0, vec![param(0)], param(1)),
+ sym::sve_tuple_create2 => (2, 0, vec![param(0), param(0)], param(1)),
+ sym::sve_tuple_create3 => (2, 0, vec![param(0), param(0), param(0)], param(1)),
+ sym::sve_tuple_create4 => (2, 0, vec![param(0), param(0), param(0), param(0)], param(1)),
+ sym::sve_tuple_get => (2, 1, vec![param(0)], param(1)),
+ sym::sve_tuple_set => (2, 1, vec![param(0), param(1)], param(0)),
+
sym::atomic_cxchg | sym::atomic_cxchgweak => (
1,
2,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 58c296d92c24e..a1b169c6a1661 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -194,8 +194,7 @@ fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<
| SizeOverflow(..)
| InvalidSimd { .. }
| NormalizationFailure(..)
- | ReferencesError(..)
- | Cycle(..) => {
+ | ReferencesError(..) => {
false // not our job to report these
}
}
diff --git a/compiler/rustc_hir_id/src/lib.rs b/compiler/rustc_hir_id/src/lib.rs
index ffff3f979f9e3..064ce4ed4cafe 100644
--- a/compiler/rustc_hir_id/src/lib.rs
+++ b/compiler/rustc_hir_id/src/lib.rs
@@ -8,7 +8,7 @@ use std::fmt::{self, Debug};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-pub use rustc_span::HashStableContext;
+use rustc_span::HashStableContext;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
@@ -176,7 +176,7 @@ pub const CRATE_HIR_ID: HirId =
pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };
-impl ToStableHashKey for HirId {
+impl ToStableHashKey for HirId {
type KeyType = (DefPathHash, ItemLocalId);
#[inline]
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index af1d1854fa5a0..1c86d553f9b6a 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -8,11 +8,11 @@ use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey,
};
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
-use rustc_hir_id::{HashStableContext, HirId, ItemLocalId};
+use rustc_hir_id::{HirId, ItemLocalId};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::def_id::DefPathHash;
pub use rustc_span::edition::Edition;
-use rustc_span::{Ident, Span, Symbol, sym};
+use rustc_span::{HashStableContext, Ident, Span, Symbol, sym};
use serde::{Deserialize, Serialize};
pub use self::Level::*;
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 63ff0b2a0a0df..f0cda4493c851 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -70,6 +70,10 @@ using namespace llvm::object;
// This opcode is an LLVM detail that could hypothetically change (?), so
// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.
static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000);
+static_assert(dwarf::DW_OP_constu == 0x10);
+static_assert(dwarf::DW_OP_minus == 0x1c);
+static_assert(dwarf::DW_OP_mul == 0x1e);
+static_assert(dwarf::DW_OP_bregx == 0x92);
static_assert(dwarf::DW_OP_stack_value == 0x9f);
static LLVM_THREAD_LOCAL char *LastError;
@@ -731,7 +735,7 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
}
template DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
- return (DIT *)(Ref ? unwrap(Ref) : nullptr);
+ return (DIT *)(Ref ? unwrap(Ref) : nullptr);
}
#define DIDescriptor DIScope
@@ -1207,6 +1211,36 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays(
DINodeArray(unwrap(Params)));
}
+// LLVM's C FFI bindings don't expose the overload of `GetOrCreateSubrange`
+// which takes a metadata node as the upper bound.
+extern "C" LLVMMetadataRef
+LLVMRustDIGetOrCreateSubrange(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef CountNode, LLVMMetadataRef LB,
+ LLVMMetadataRef UB, LLVMMetadataRef Stride) {
+ return wrap(unwrap(Builder)->getOrCreateSubrange(
+ unwrapDI(CountNode), unwrapDI(LB),
+ unwrapDI(UB), unwrapDI(Stride)));
+}
+
+// LLVM's CI FFI bindings don't expose the `BitStride` parameter of
+// `createVectorType`.
+extern "C" LLVMMetadataRef
+LLVMRustDICreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size,
+ uint32_t AlignInBits, LLVMMetadataRef Type,
+ LLVMMetadataRef Subscripts,
+ LLVMMetadataRef BitStride) {
+#if LLVM_VERSION_GE(22, 0)
+ return wrap(unwrap(Builder)->createVectorType(
+ Size, AlignInBits, unwrapDI(Type),
+ DINodeArray(unwrapDI(Subscripts)),
+ unwrapDI(BitStride)));
+#else
+ return wrap(unwrap(Builder)->createVectorType(
+ Size, AlignInBits, unwrapDI(Type),
+ DINodeArray(unwrapDI(Subscripts))));
+#endif
+}
+
extern "C" LLVMMetadataRef
LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
unsigned BD) {
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs
index fa67adb406ed2..adb93e375c32c 100644
--- a/compiler/rustc_macros/src/hash_stable.rs
+++ b/compiler/rustc_macros/src/hash_stable.rs
@@ -84,7 +84,7 @@ fn hash_stable_derive_with_mode(
match mode {
HashStableMode::Normal => {}
HashStableMode::Generic => {
- s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
+ s.add_where_predicate(parse_quote! { __CTX: ::rustc_span::HashStableContext });
}
HashStableMode::NoContext => {}
}
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index ad56e462d2934..814b333cfb0f8 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -21,7 +21,7 @@ use rustc_hir::lints::DelayedLint;
use rustc_hir::*;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable};
-use rustc_span::{ErrorGuaranteed, ExpnId, Span};
+use rustc_span::{ErrorGuaranteed, ExpnId, HashStableContext, Span};
use crate::query::Providers;
use crate::ty::{ResolverAstLowering, TyCtxt};
@@ -77,8 +77,8 @@ impl<'hir> Crate<'hir> {
}
}
-impl HashStable for Crate<'_> {
- fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+impl HashStable for Crate<'_> {
+ fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
let Crate { opt_hir_hash, .. } = self;
opt_hir_hash.unwrap().hash_stable(hcx, hasher)
}
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 2e118dc3359fa..0e1cee2970f71 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -6,7 +6,7 @@ use rustc_hir::definitions::DefPathHash;
use rustc_session::Session;
use rustc_session::cstore::Untracked;
use rustc_span::source_map::SourceMap;
-use rustc_span::{CachingSourceMapView, DUMMY_SP, Pos, Span};
+use rustc_span::{CachingSourceMapView, DUMMY_SP, HashStableContext, Pos, Span};
// Very often, we are hashing something that does not need the `CachingSourceMapView`, so we
// initialize it lazily.
@@ -73,7 +73,7 @@ impl<'a> StableHashingContext<'a> {
}
}
-impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
+impl<'a> HashStableContext for StableHashingContext<'a> {
/// Hashes a span in a stable way. We can't directly hash the span's `BytePos` fields (that
/// would be similar to hashing pointers, since those are just offsets into the `SourceMap`).
/// Instead, we hash the (file name, line, column) triple, which stays the same even if the
@@ -189,8 +189,3 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
);
}
}
-
-impl<'a> rustc_abi::HashStableContext for StableHashingContext<'a> {}
-impl<'a> rustc_ast::HashStableContext for StableHashingContext<'a> {}
-impl<'a> rustc_hir::HashStableContext for StableHashingContext<'a> {}
-impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 4ca51c078bef5..46682abc823d8 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -260,8 +260,6 @@ pub enum LayoutError<'tcx> {
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
/// A non-layout error is reported elsewhere.
ReferencesError(ErrorGuaranteed),
- /// A type has cyclic layout, i.e. the type contains itself without indirection.
- Cycle(ErrorGuaranteed),
}
impl<'tcx> fmt::Display for LayoutError<'tcx> {
@@ -286,7 +284,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
t,
e.get_type_for_failure()
),
- LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"),
LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"),
}
}
@@ -358,8 +355,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
Err(err @ LayoutError::TooGeneric(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
- e @ LayoutError::Cycle(_)
- | e @ LayoutError::Unknown(_)
+ e @ LayoutError::Unknown(_)
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::InvalidSimd { .. }
| e @ LayoutError::NormalizationFailure(..)
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index a497501ef19d5..798b98c5def5c 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -291,7 +291,7 @@ impl<'tcx> Region<'tcx> {
}
ty::ReError(_) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_ERROR;
+ flags = flags | TypeFlags::HAS_RE_ERROR;
}
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 0d047b348d9e1..621ceeffac658 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -7,7 +7,7 @@ use std::debug_assert_matches;
use std::ops::{ControlFlow, Range};
use hir::def::{CtorKind, DefKind};
-use rustc_abi::{FIRST_VARIANT, FieldIdx, ScalableElt, VariantIdx};
+use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx};
use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::LangItem;
@@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> {
}
}
- pub fn scalable_vector_element_count_and_type(self, tcx: TyCtxt<'tcx>) -> (u16, Ty<'tcx>) {
+ pub fn scalable_vector_parts(
+ self,
+ tcx: TyCtxt<'tcx>,
+ ) -> Option<(u16, Ty<'tcx>, NumScalableVectors)> {
let Adt(def, args) = self.kind() else {
- bug!("`scalable_vector_size_and_type` called on invalid type")
+ return None;
};
- let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else {
- bug!("`scalable_vector_size_and_type` called on non-scalable vector type");
+ let (num_vectors, vec_def) = match def.repr().scalable? {
+ ScalableElt::ElementCount(_) => (NumScalableVectors::for_non_tuple(), *def),
+ ScalableElt::Container => (
+ NumScalableVectors::from_field_count(def.non_enum_variant().fields.len())?,
+ def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, args).ty_adt_def()?,
+ ),
};
- let variant = def.non_enum_variant();
+ let Some(ScalableElt::ElementCount(element_count)) = vec_def.repr().scalable else {
+ return None;
+ };
+ let variant = vec_def.non_enum_variant();
assert_eq!(variant.fields.len(), 1);
let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
- (element_count, field_ty)
+ Some((element_count, field_ty, num_vectors))
}
pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 0f4927432f6fa..79b79db6ccc07 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -248,10 +248,18 @@ impl<'a> Parser<'a> {
self.parse_use_item()?
} else if self.check_fn_front_matter(check_pub, case) {
// FUNCTION ITEM
+ let defaultness = def_();
+ if let Defaultness::Default(span) = defaultness {
+ // Default functions should only require feature `min_specialization`. We remove the
+ // `specialization` tag again as such spans *require* feature `specialization` to be
+ // enabled. In a later stage, we make `specialization` imply `min_specialization`.
+ self.psess.gated_spans.gate(sym::min_specialization, span);
+ self.psess.gated_spans.ungate_last(sym::specialization, span);
+ }
let (ident, sig, generics, contract, body) =
self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
ItemKind::Fn(Box::new(Fn {
- defaultness: def_(),
+ defaultness,
ident,
sig,
generics,
@@ -603,6 +611,7 @@ impl<'a> Parser<'a> {
fn parse_polarity(&mut self) -> ast::ImplPolarity {
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
+ self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
self.bump(); // `!`
ast::ImplPolarity::Negative(self.prev_token.span)
} else {
@@ -1015,6 +1024,7 @@ impl<'a> Parser<'a> {
if self.check_keyword(exp!(Default))
&& self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
{
+ self.psess.gated_spans.gate(sym::specialization, self.token.span);
self.bump(); // `default`
Defaultness::Default(self.prev_token_uninterpolated_span())
} else if self.eat_keyword(exp!(Final)) {
diff --git a/compiler/rustc_public/src/abi.rs b/compiler/rustc_public/src/abi.rs
index 1403e57a7e6a9..4a780d652df81 100644
--- a/compiler/rustc_public/src/abi.rs
+++ b/compiler/rustc_public/src/abi.rs
@@ -232,6 +232,10 @@ pub enum TagEncoding {
},
}
+/// How many scalable vectors are in a `ValueAbi::ScalableVector`?
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
+pub struct NumScalableVectors(pub(crate) u8);
+
/// Describes how values of the type are passed by target ABIs,
/// in terms of categories of C types there are ABI rules for.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
@@ -245,6 +249,7 @@ pub enum ValueAbi {
ScalableVector {
element: Scalar,
count: u64,
+ number_of_vectors: NumScalableVectors,
},
Aggregate {
/// If true, the size is exact, otherwise it's only a lower bound.
diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs
index b3edc6194c307..d8c4cee7abbe4 100644
--- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs
+++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs
@@ -10,8 +10,9 @@ use rustc_target::callconv;
use crate::abi::{
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
- IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
- TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape, WrappingRange,
+ IntegerType, Layout, LayoutShape, NumScalableVectors, PassMode, Primitive, ReprFlags,
+ ReprOptions, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape,
+ WrappingRange,
};
use crate::compiler_interface::BridgeTys;
use crate::target::MachineSize as Size;
@@ -249,6 +250,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding {
}
}
+impl<'tcx> Stable<'tcx> for rustc_abi::NumScalableVectors {
+ type T = NumScalableVectors;
+
+ fn stable<'cx>(
+ &self,
+ _tables: &mut Tables<'cx, BridgeTys>,
+ _cx: &CompilerCtxt<'cx, BridgeTys>,
+ ) -> Self::T {
+ NumScalableVectors(self.0)
+ }
+}
+
impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
type T = ValueAbi;
@@ -265,8 +278,12 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
rustc_abi::BackendRepr::SimdVector { element, count } => {
ValueAbi::Vector { element: element.stable(tables, cx), count }
}
- rustc_abi::BackendRepr::SimdScalableVector { element, count } => {
- ValueAbi::ScalableVector { element: element.stable(tables, cx), count }
+ rustc_abi::BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
+ ValueAbi::ScalableVector {
+ element: element.stable(tables, cx),
+ count,
+ number_of_vectors: number_of_vectors.stable(tables, cx),
+ }
}
rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
}
diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs
index 5676669bf1c0e..22f8ac9837f6d 100644
--- a/compiler/rustc_query_impl/src/handle_cycle_error.rs
+++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs
@@ -12,7 +12,6 @@ use rustc_middle::bug;
use rustc_middle::queries::{QueryVTables, TaggedQueryKey};
use rustc_middle::query::Cycle;
use rustc_middle::query::erase::erase_val;
-use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{ErrorGuaranteed, Span};
@@ -203,8 +202,7 @@ fn layout_of<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> &'tcx ty::layout::L
|| create_cycle_error(tcx, &cycle),
);
- let guar = diag.emit();
- tcx.arena.alloc(LayoutError::Cycle(guar))
+ diag.emit().raise_fatal()
}
// item_and_field_ids should form a cycle where each field contains the
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index de36f01b6d0e5..0acc42a6efbe1 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -209,12 +209,15 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
fn visit_fn(&mut self, fn_kind: FnKind<'a>, _: &AttrVec, span: Span, _: NodeId) {
match fn_kind {
FnKind::Fn(
- _ctxt,
+ ctxt,
_vis,
Fn {
sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, ..
},
- ) if let Some(coroutine_kind) = header.coroutine_kind => {
+ ) if let Some(coroutine_kind) = header.coroutine_kind
+ // Foreign ones are denied, so don't create them here.
+ && ctxt != visit::FnCtxt::Foreign =>
+ {
self.visit_ident(ident);
self.visit_fn_header(header);
self.visit_generics(generics);
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e37247d7dd837..1e95482a8c7e6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -23,7 +23,8 @@ use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{
- FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym,
+ FileName, HashStableContext, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm,
+ Symbol, sym,
};
use rustc_target::spec::{
FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
@@ -38,7 +39,7 @@ use crate::errors::FileWriteFail;
pub use crate::options::*;
use crate::search_paths::SearchPath;
use crate::utils::CanonicalizedPath;
-use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
+use crate::{EarlyDiagCtxt, Session, filesearch, lint};
mod cfg;
mod externs;
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 1741dde90f5cf..04e12f1afce68 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -11,30 +11,21 @@
#![recursion_limit = "256"]
// tidy-alphabetical-end
-pub mod errors;
-
-pub mod utils;
+pub use getopts;
pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
pub use rustc_lint_defs as lint;
-pub mod parse;
+pub use session::*;
pub mod code_stats;
+pub mod errors;
+pub mod parse;
+pub mod utils;
#[macro_use]
pub mod config;
pub mod cstore;
pub mod filesearch;
mod macros;
mod options;
+pub mod output;
pub mod search_paths;
-
mod session;
-pub use session::*;
-
-pub mod output;
-
-pub use getopts;
-
-/// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in `rustc_middle`.
-pub trait HashStableContext: rustc_ast::HashStableContext + rustc_hir::HashStableContext {}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 6794ffb311e32..97de708290fb4 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -2796,10 +2796,10 @@ impl InnerSpan {
}
}
-/// Requirements for a `StableHashingContext` to be used in this crate.
-///
-/// This is a hack to allow using the [`HashStable_Generic`] derive macro
-/// instead of implementing everything in rustc_middle.
+/// This trait lets `HashStable` and `derive(HashStable_Generic)` be used in
+/// this crate (and other crates upstream of `rustc_middle`), while leaving
+/// certain operations to be defined in `rustc_middle` where more things are
+/// visible.
pub trait HashStableContext {
/// The main event: stable hashing of a span.
fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 30bf8dd7c2206..a4394af263870 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1979,6 +1979,12 @@ symbols! {
suggestion,
super_let,
supertrait_item_shadowing,
+ sve_cast,
+ sve_tuple_create2,
+ sve_tuple_create3,
+ sve_tuple_create4,
+ sve_tuple_get,
+ sve_tuple_set,
sym,
sync,
synthetic,
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 1dc62cb3659cc..d46802bf45d1a 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -24,8 +24,6 @@ pub mod target_features;
#[cfg(test)]
mod tests;
-use rustc_abi::HashStableContext;
-
/// The name of rustc's own place to organize libraries.
///
/// Used to be `rustc`, now the default is `rustlib`.
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 3df5c9e33438a..72d3ba9629f4d 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -659,7 +659,9 @@ fn project<'cx, 'tcx>(
)));
}
- if let Err(guar) = obligation.predicate.error_reported() {
+ // We can still compute a projection type when there are only region errors,
+ // but type/const errors require early return.
+ if let Err(guar) = obligation.predicate.non_region_error_reported() {
return Ok(Projected::Progress(Progress::error_for_term(
selcx.tcx(),
obligation.predicate,
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 1202ed2384315..1bfe6e94cc3b6 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -282,7 +282,6 @@ pub(crate) mod rustc {
| LayoutError::InvalidSimd { .. }
| LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
LayoutError::SizeOverflow(..) => Self::SizeOverflow,
- LayoutError::Cycle(err) => Self::TypeError(*err),
}
}
}
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 391f50edf23fa..136df923ee47a 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -4,8 +4,8 @@ use rustc_abi::Integer::{I8, I32};
use rustc_abi::Primitive::{self, Float, Int, Pointer};
use rustc_abi::{
AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout,
- LayoutCalculatorError, LayoutData, Niche, ReprOptions, ScalableElt, Scalar, Size, StructKind,
- TagEncoding, VariantIdx, Variants, WrappingRange,
+ LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding,
+ VariantIdx, Variants, WrappingRange,
};
use rustc_hashes::Hash64;
use rustc_hir as hir;
@@ -572,30 +572,26 @@ fn layout_of_uncached<'tcx>(
// ```rust (ignore, example)
// #[rustc_scalable_vector(3)]
// struct svuint32_t(u32);
+ //
+ // #[rustc_scalable_vector]
+ // struct svuint32x2_t(svuint32_t, svuint32_t);
// ```
- ty::Adt(def, args)
- if matches!(def.repr().scalable, Some(ScalableElt::ElementCount(..))) =>
- {
- let Some(element_ty) = def
- .is_struct()
- .then(|| &def.variant(FIRST_VARIANT).fields)
- .filter(|fields| fields.len() == 1)
- .map(|fields| fields[FieldIdx::ZERO].ty(tcx, args))
+ ty::Adt(def, _args) if def.repr().scalable() => {
+ let Some((element_count, element_ty, number_of_vectors)) =
+ ty.scalable_vector_parts(tcx)
else {
let guar = tcx
.dcx()
- .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");
- return Err(error(cx, LayoutError::ReferencesError(guar)));
- };
- let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else {
- let guar = tcx
- .dcx()
- .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");
+ .delayed_bug("`#[rustc_scalable_vector]` was applied to an invalid type");
return Err(error(cx, LayoutError::ReferencesError(guar)));
};
let element_layout = cx.layout_of(element_ty)?;
- map_layout(cx.calc.scalable_vector_type(element_layout, element_count as u64))?
+ map_layout(cx.calc.scalable_vector_type(
+ element_layout,
+ element_count as u64,
+ number_of_vectors,
+ ))?
}
// SIMD vector types.
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 6962a7ab1d727..f311298119649 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -91,19 +91,24 @@ bitflags::bitflags! {
| TypeFlags::HAS_TY_INHERENT.bits()
| TypeFlags::HAS_CT_PROJECTION.bits();
+ /// Is a type or const error reachable?
+ const HAS_NON_REGION_ERROR = 1 << 15;
+ /// Is a region error reachable?
+ const HAS_RE_ERROR = 1 << 16;
/// Is an error type/lifetime/const reachable?
- const HAS_ERROR = 1 << 15;
+ const HAS_ERROR = TypeFlags::HAS_NON_REGION_ERROR.bits()
+ | TypeFlags::HAS_RE_ERROR.bits();
/// Does this have any region that "appears free" in the type?
/// Basically anything but `ReBound` and `ReErased`.
- const HAS_FREE_REGIONS = 1 << 16;
+ const HAS_FREE_REGIONS = 1 << 17;
/// Does this have any `ReBound` regions?
- const HAS_RE_BOUND = 1 << 17;
+ const HAS_RE_BOUND = 1 << 18;
/// Does this have any `Bound` types?
- const HAS_TY_BOUND = 1 << 18;
+ const HAS_TY_BOUND = 1 << 19;
/// Does this have any `ConstKind::Bound` consts?
- const HAS_CT_BOUND = 1 << 19;
+ const HAS_CT_BOUND = 1 << 20;
/// Does this have any bound variables?
/// Used to check if a global bound is safe to evaluate.
const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits()
@@ -111,7 +116,7 @@ bitflags::bitflags! {
| TypeFlags::HAS_CT_BOUND.bits();
/// Does this have any `ReErased` regions?
- const HAS_RE_ERASED = 1 << 20;
+ const HAS_RE_ERASED = 1 << 21;
/// Does this value have parameters/placeholders/inference variables which could be
/// replaced later, in a way that would change the results of `impl` specialization?
@@ -123,19 +128,19 @@ bitflags::bitflags! {
| TypeFlags::HAS_CT_INFER.bits();
/// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
- const HAS_TY_FRESH = 1 << 21;
+ const HAS_TY_FRESH = 1 << 22;
/// Does this value have `InferConst::Fresh`?
- const HAS_CT_FRESH = 1 << 22;
+ const HAS_CT_FRESH = 1 << 23;
/// Does this have any binders with bound vars (e.g. that need to be anonymized)?
- const HAS_BINDER_VARS = 1 << 23;
+ const HAS_BINDER_VARS = 1 << 24;
/// Does this type have any coroutines in it?
- const HAS_TY_CORO = 1 << 24;
+ const HAS_TY_CORO = 1 << 25;
/// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`?
- const HAS_CANONICAL_BOUND = 1 << 25;
+ const HAS_CANONICAL_BOUND = 1 << 26;
}
}
@@ -240,7 +245,7 @@ impl FlagComputation {
| ty::Str
| ty::Foreign(..) => {}
- ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
+ ty::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR),
ty::Param(_) => {
self.add_flags(TypeFlags::HAS_TY_PARAM);
@@ -489,7 +494,7 @@ impl FlagComputation {
}
}
ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()),
- ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
+ ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR),
}
}
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 1ee4bff6b7a11..cfb4588965368 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -279,6 +279,8 @@ pub trait TypeVisitableExt: TypeVisitable {
fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
+ fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed>;
+
fn has_non_region_param(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
}
@@ -352,6 +354,11 @@ pub trait TypeVisitableExt: TypeVisitable {
fn still_further_specializable(&self) -> bool {
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
}
+
+ /// True if a type or const error is reachable
+ fn has_non_region_error(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR)
+ }
}
impl> TypeVisitableExt for T {
@@ -376,6 +383,18 @@ impl> TypeVisitableExt for T {
Ok(())
}
}
+
+ fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
+ if self.has_non_region_error() {
+ if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
+ Err(guar)
+ } else {
+ panic!("type flags said there was an non region error, but now there is not")
+ }
+ } else {
+ Ok(())
+ }
+ }
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index bcd9e092a310f..aff10c4320fe1 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -111,6 +111,7 @@
#![feature(core_intrinsics)]
#![feature(deprecated_suggestion)]
#![feature(deref_pure_trait)]
+#![feature(diagnostic_on_move)]
#![feature(dispatch_from_dyn)]
#![feature(ergonomic_clones)]
#![feature(error_generic_member_access)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index b3e49af868b8c..af1eaf2015e9d 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -261,6 +261,11 @@ macro_rules! acquire {
#[rustc_diagnostic_item = "Arc"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_insignificant_dtor]
+#[diagnostic::on_move(
+ message = "the type `{Self}` does not implement `Copy`",
+ label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive",
+ note = "consider using `Arc::clone`"
+)]
pub struct Arc<
T: ?Sized,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd/mod.rs
similarity index 99%
rename from library/core/src/intrinsics/simd.rs
rename to library/core/src/intrinsics/simd/mod.rs
index ae86690dc418d..084d8a3f1f247 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd/mod.rs
@@ -2,6 +2,8 @@
//!
//! In this module, a "vector" is any `repr(simd)` type.
+pub mod scalable;
+
use crate::marker::ConstParamTy;
/// Inserts an element into a vector, returning the updated vector.
diff --git a/library/core/src/intrinsics/simd/scalable.rs b/library/core/src/intrinsics/simd/scalable.rs
new file mode 100644
index 0000000000000..1a8e90012bce8
--- /dev/null
+++ b/library/core/src/intrinsics/simd/scalable.rs
@@ -0,0 +1,99 @@
+//! Scalable vector compiler intrinsics.
+//!
+//! In this module, a "vector" is any `#[rustc_scalable_vector]`-annotated type.
+
+/// Numerically casts a vector, elementwise.
+///
+/// `T` and `U` must be vectors of integers or floats, and must have the same length.
+///
+/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB.
+/// When casting integers to floats, the result is rounded.
+/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
+///
+/// # Safety
+/// Casting from integer types is always safe.
+/// Casting between two float types is also always safe.
+///
+/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`.
+/// Specifically, each element must:
+/// * Not be `NaN`
+/// * Not be infinite
+/// * Be representable in the return type, after truncating off its fractional part
+#[cfg(target_arch = "aarch64")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_cast(x: T) -> U;
+
+/// Create a tuple of two vectors.
+///
+/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
+/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
+/// type `SVec`.
+///
+/// Corresponds to Clang's `__builtin_sve_svcreate2*` builtins.
+#[cfg(target_arch = "aarch64")]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_tuple_create2(x0: SVec, x1: SVec) -> SVecTup;
+
+/// Create a tuple of three vectors.
+///
+/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
+/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
+/// type `SVec`.
+///
+/// Corresponds to Clang's `__builtin_sve_svcreate3*` builtins.
+#[cfg(target_arch = "aarch64")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_tuple_create3(x0: SVec, x1: SVec, x2: SVec) -> SVecTup;
+
+/// Create a tuple of four vectors.
+///
+/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
+/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
+/// type `SVec`.
+///
+/// Corresponds to Clang's `__builtin_sve_svcreate4*` builtins.
+#[cfg(target_arch = "aarch64")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_tuple_create4(x0: SVec, x1: SVec, x2: SVec, x3: SVec) -> SVecTup;
+
+/// Get one vector from a tuple of vectors.
+///
+/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
+/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
+/// type `SVec`.
+///
+/// Corresponds to Clang's `__builtin_sve_svget*` builtins.
+///
+/// # Safety
+///
+/// `IDX` must be in-bounds of the tuple.
+#[cfg(target_arch = "aarch64")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_tuple_get(tuple: SVecTup) -> SVec;
+
+/// Change one vector in a tuple of vectors.
+///
+/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a
+/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of
+/// type `SVec`.
+///
+/// Corresponds to Clang's `__builtin_sve_svset*` builtins.
+///
+/// # Safety
+///
+/// `IDX` must be in-bounds of the tuple.
+#[cfg(target_arch = "aarch64")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[target_feature(enable = "sve")]
+pub unsafe fn sve_tuple_set(tuple: SVecTup, x: SVec) -> SVecTup;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e0750f0784458..312295154dc52 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -236,6 +236,8 @@ pub mod autodiff {
#[unstable(feature = "contracts", issue = "128044")]
pub mod contracts;
+#[unstable(feature = "derive_macro_global_path", issue = "154645")]
+pub use crate::macros::builtin::derive;
#[stable(feature = "cfg_select", since = "1.95.0")]
pub use crate::macros::cfg_select;
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 7f35e94d3df30..33397e56b86c5 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1720,7 +1720,7 @@ pub(crate) mod builtin {
///
/// See [the reference] for more info.
///
- /// [the reference]: ../../../reference/attributes/derive.html
+ /// [the reference]: ../reference/attributes/derive.html
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
pub macro derive($item:item) {
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index f2eb047d342bc..6122ab12ec351 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -120,9 +120,13 @@ pub use crate::trace_macros;
// (no public module for them to be re-exported from).
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
pub use crate::macros::builtin::{
- alloc_error_handler, bench, derive, global_allocator, test, test_case,
+ alloc_error_handler, bench, global_allocator, test, test_case,
};
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[doc(no_inline)]
+pub use crate::macros::builtin::derive;
+
#[unstable(feature = "derive_const", issue = "118304")]
pub use crate::macros::builtin::derive_const;
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 1730742dffe93..70ccd3431a2ff 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -706,6 +706,8 @@ pub use core::cfg_select;
reason = "`concat_bytes` is not stable enough for use and is subject to change"
)]
pub use core::concat_bytes;
+#[unstable(feature = "derive_macro_global_path", issue = "154645")]
+pub use core::derive;
#[stable(feature = "matches_macro", since = "1.42.0")]
#[allow(deprecated, deprecated_in_future)]
pub use core::matches;
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index ee57e031c959c..aeefec8b9e084 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -115,9 +115,13 @@ pub use core::prelude::v1::trace_macros;
// (no public module for them to be re-exported from).
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
pub use core::prelude::v1::{
- alloc_error_handler, bench, derive, global_allocator, test, test_case,
+ alloc_error_handler, bench, global_allocator, test, test_case,
};
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[doc(no_inline)]
+pub use core::prelude::v1::derive;
+
#[unstable(feature = "derive_const", issue = "118304")]
pub use core::prelude::v1::derive_const;
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 847e688d03d0a..fc61103d939fb 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -203,7 +203,7 @@ fn clean_param_env<'tcx>(
let mut generics = clean::Generics { params, where_predicates };
simplify::sized_bounds(cx, &mut generics);
- generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates);
+ generics.where_predicates = simplify::where_clauses(cx.tcx, generics.where_predicates);
generics
}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 09b2bc5dcef1d..96e15eac0a920 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -137,7 +137,7 @@ pub(crate) fn try_inline(
})
}
Res::Def(DefKind::Macro(kinds), did) => {
- let mac = build_macro(cx, did, name, kinds);
+ let mac = build_macro(cx.tcx, did, name, kinds);
// FIXME: handle attributes and derives that aren't proc macros, and macros with
// multiple kinds
@@ -218,10 +218,10 @@ pub(crate) fn try_inline_glob(
}
}
-pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir::Attribute] {
+pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [hir::Attribute] {
// FIXME: all uses should use `find_attr`!
#[allow(deprecated)]
- cx.tcx.get_all_attrs(did)
+ tcx.get_all_attrs(did)
}
pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec {
@@ -289,7 +289,7 @@ pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
supertrait_bounds.retain(|b| {
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
// is shown and none of the new sizedness traits leak into documentation.
- !b.is_meta_sized_bound(cx)
+ !b.is_meta_sized_bound(cx.tcx)
});
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
@@ -302,7 +302,7 @@ fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
bounds.retain(|b| {
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
// is shown and none of the new sizedness traits leak into documentation.
- !b.is_meta_sized_bound(cx)
+ !b.is_meta_sized_bound(cx.tcx)
});
clean::TraitAlias { generics, bounds }
@@ -312,7 +312,7 @@ pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box)>,
ret: &mut Vec,
) {
- let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
let tcx = cx.tcx;
+ let _prof_timer = tcx.sess.prof.generic_activity("build_inherent_impls");
// for each implementation of an item represented by `did`, build the clean::Item for that impl
for &did in tcx.inherent_impls(did).iter() {
@@ -416,7 +416,7 @@ pub(crate) fn build_impls(
}
pub(crate) fn merge_attrs(
- cx: &mut DocContext<'_>,
+ tcx: TyCtxt<'_>,
old_attrs: &[hir::Attribute],
new_attrs: Option<(&[hir::Attribute], Option)>,
cfg_info: &mut CfgInfo,
@@ -434,13 +434,10 @@ pub(crate) fn merge_attrs(
} else {
Attributes::from_hir(&both)
},
- extract_cfg_from_attrs(both.iter(), cx.tcx, cfg_info),
+ extract_cfg_from_attrs(both.iter(), tcx, cfg_info),
)
} else {
- (
- Attributes::from_hir(old_attrs),
- extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, cfg_info),
- )
+ (Attributes::from_hir(old_attrs), extract_cfg_from_attrs(old_attrs.iter(), tcx, cfg_info))
}
}
@@ -623,7 +620,8 @@ pub(crate) fn build_impl(
// doesn't matter at this point.
//
// We need to pass this empty `CfgInfo` because `merge_attrs` is used when computing the `cfg`.
- let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs, &mut CfgInfo::default());
+ let (merged_attrs, cfg) =
+ merge_attrs(cx.tcx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default());
trace!("merged_attrs={merged_attrs:?}");
trace!(
@@ -771,17 +769,17 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St
}
fn build_macro(
- cx: &mut DocContext<'_>,
+ tcx: TyCtxt<'_>,
def_id: DefId,
name: Symbol,
macro_kinds: MacroKinds,
) -> clean::ItemKind {
- match CStore::from_tcx(cx.tcx).load_macro_untracked(cx.tcx, def_id) {
+ match CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id) {
// FIXME: handle attributes and derives that aren't proc macros, and macros with multiple
// kinds
LoadedMacro::MacroDef { def, .. } => match macro_kinds {
MacroKinds::BANG => clean::MacroItem(clean::Macro {
- source: utils::display_macro_source(cx, name, &def),
+ source: utils::display_macro_source(tcx, name, &def),
macro_rules: def.macro_rules,
}),
MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f54339429fa58..67eee30e99a9f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -184,7 +184,8 @@ fn generate_item_with_correct_attrs(
import_ids: &[LocalDefId],
renamed: Option,
) -> Item {
- let target_attrs = inline::load_attrs(cx, def_id);
+ let tcx = cx.tcx;
+ let target_attrs = inline::load_attrs(tcx, def_id);
let attrs = if !import_ids.is_empty() {
let mut attrs = Vec::with_capacity(import_ids.len());
let mut is_inline = false;
@@ -196,11 +197,11 @@ fn generate_item_with_correct_attrs(
// cfgs on the path up until the glob can be removed, and only cfgs on the globbed item
// itself matter), for non-inlined re-exports see #85043.
let import_is_inline = find_attr!(
- inline::load_attrs(cx, import_id.to_def_id()),
+ inline::load_attrs(tcx, import_id.to_def_id()),
Doc(d)
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
- ) || (is_glob_import(cx.tcx, import_id)
- && (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id)));
+ ) || (is_glob_import(tcx, import_id)
+ && (cx.document_hidden() || !tcx.is_doc_hidden(def_id)));
attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
is_inline = is_inline || import_is_inline;
}
@@ -272,7 +273,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>(
GenericBound::TraitBound(
PolyTrait {
trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints),
- generic_params: clean_bound_vars(poly_trait_ref.bound_vars(), cx),
+ generic_params: clean_bound_vars(poly_trait_ref.bound_vars(), cx.tcx),
},
hir::TraitBoundModifiers::NONE,
)
@@ -342,7 +343,6 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind
pub(crate) fn clean_middle_const<'tcx>(
constant: ty::Binder<'tcx, ty::Const<'tcx>>,
- _cx: &mut DocContext<'tcx>,
) -> ConstantKind {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }
@@ -350,9 +350,9 @@ pub(crate) fn clean_middle_const<'tcx>(
pub(crate) fn clean_middle_region<'tcx>(
region: ty::Region<'tcx>,
- cx: &mut DocContext<'tcx>,
+ tcx: TyCtxt<'tcx>,
) -> Option {
- region.get_name(cx.tcx).map(Lifetime)
+ region.get_name(tcx).map(Lifetime)
}
fn clean_where_predicate<'tcx>(
@@ -394,7 +394,7 @@ pub(crate) fn clean_predicate<'tcx>(
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx),
- ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx)),
+ ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx.tcx)),
ty::ClauseKind::TypeOutlives(pred) => {
Some(clean_type_outlives_predicate(bound_predicate.rebind(pred), cx))
}
@@ -431,14 +431,14 @@ fn clean_poly_trait_predicate<'tcx>(
fn clean_region_outlives_predicate<'tcx>(
pred: ty::RegionOutlivesPredicate<'tcx>,
- cx: &mut DocContext<'tcx>,
+ tcx: TyCtxt<'tcx>,
) -> WherePredicate {
let ty::OutlivesPredicate(a, b) = pred;
WherePredicate::RegionPredicate {
- lifetime: clean_middle_region(a, cx).expect("failed to clean lifetime"),
+ lifetime: clean_middle_region(a, tcx).expect("failed to clean lifetime"),
bounds: vec![GenericBound::Outlives(
- clean_middle_region(b, cx).expect("failed to clean bounds"),
+ clean_middle_region(b, tcx).expect("failed to clean bounds"),
)],
}
}
@@ -452,7 +452,7 @@ fn clean_type_outlives_predicate<'tcx>(
WherePredicate::BoundPredicate {
ty: clean_middle_ty(pred.rebind(ty), cx, None, None),
bounds: vec![GenericBound::Outlives(
- clean_middle_region(lt, cx).expect("failed to clean lifetimes"),
+ clean_middle_region(lt, cx.tcx).expect("failed to clean lifetimes"),
)],
bound_params: Vec::new(),
}
@@ -464,7 +464,7 @@ fn clean_middle_term<'tcx>(
) -> Term {
match term.skip_binder().kind() {
ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None, None)),
- ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
+ ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c))),
}
}
@@ -479,7 +479,7 @@ fn clean_hir_term<'tcx>(
// FIXME(generic_const_items): this should instantiate with the alias item's args
let ty = cx.tcx.type_of(assoc_item.unwrap()).instantiate_identity();
let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty);
- Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx))
+ Term::Constant(clean_middle_const(ty::Binder::dummy(ct)))
}
}
}
@@ -898,10 +898,10 @@ fn clean_ty_generics_inner<'tcx>(
for (idx, mut bounds) in impl_trait {
let mut has_sized = false;
bounds.retain(|b| {
- if b.is_sized_bound(cx) {
+ if b.is_sized_bound(cx.tcx) {
has_sized = true;
false
- } else if b.is_meta_sized_bound(cx) {
+ } else if b.is_meta_sized_bound(cx.tcx) {
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
// is shown and none of the new sizedness traits leak into documentation.
false
@@ -925,7 +925,7 @@ fn clean_ty_generics_inner<'tcx>(
if let Some(proj) = impl_trait_proj.remove(&idx) {
for (trait_did, name, rhs) in proj {
let rhs = clean_middle_term(rhs, cx);
- simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
+ simplify::merge_bounds(cx.tcx, &mut bounds, trait_did, name, &rhs);
}
}
@@ -939,7 +939,7 @@ fn clean_ty_generics_inner<'tcx>(
let mut generics = Generics { params, where_predicates };
simplify::sized_bounds(cx, &mut generics);
- generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates);
+ generics.where_predicates = simplify::where_clauses(cx.tcx, generics.where_predicates);
generics
}
@@ -1001,12 +1001,12 @@ fn clean_proc_macro<'tcx>(
item: &hir::Item<'tcx>,
name: &mut Symbol,
kind: MacroKind,
- cx: &mut DocContext<'tcx>,
+ tcx: TyCtxt<'tcx>,
) -> ItemKind {
if kind != MacroKind::Derive {
return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
}
- let attrs = cx.tcx.hir_attrs(item.hir_id());
+ let attrs = tcx.hir_attrs(item.hir_id());
let Some((trait_name, helper_attrs)) = find_attr!(attrs, ProcMacroDerive { trait_name, helper_attrs, ..} => (*trait_name, helper_attrs))
else {
return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
@@ -1037,7 +1037,7 @@ fn clean_fn_or_proc_macro<'tcx>(
};
match macro_kind {
- Some(kind) => clean_proc_macro(item, name, kind, cx),
+ Some(kind) => clean_proc_macro(item, name, kind, cx.tcx),
None => {
let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id));
clean_fn_decl_legacy_const_generics(&mut func, attrs);
@@ -1248,7 +1248,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
RequiredAssocTypeItem(generics, bounds)
}
};
- Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
+ Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx.tcx)
})
}
@@ -1289,7 +1289,7 @@ pub(crate) fn clean_impl_item<'tcx>(
}
};
- Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx)
+ Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx.tcx)
})
}
@@ -1459,7 +1459,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
bounds.retain(|b| {
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
// is shown and none of the new sizedness traits leak into documentation.
- !b.is_meta_sized_bound(cx)
+ !b.is_meta_sized_bound(tcx)
});
// Our Sized/?Sized bound didn't get handled when creating the generics
@@ -1467,7 +1467,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
// (some of them may have come from the trait). If we do have a sized
// bound, we remove it, and if we don't then we add the `?Sized` bound
// at the end.
- match bounds.iter().position(|b| b.is_sized_bound(cx)) {
+ match bounds.iter().position(|b| b.is_sized_bound(tcx)) {
Some(i) => {
bounds.remove(i);
}
@@ -1517,7 +1517,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
}
};
- Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx)
+ Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, tcx)
}
fn first_non_private_clean_path<'tcx>(
@@ -1831,7 +1831,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize);
let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
- print_const(cx, ct)
+ print_const(cx.tcx, ct)
}
hir::ConstArgKind::Struct(..)
| hir::ConstArgKind::Path(..)
@@ -1840,7 +1840,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
| hir::ConstArgKind::Array(..)
| hir::ConstArgKind::Literal { .. } => {
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize);
- print_const(cx, ct)
+ print_const(cx.tcx, ct)
}
};
Array(Box::new(clean_ty(ty, cx)), length.into())
@@ -2060,14 +2060,14 @@ pub(crate) fn clean_middle_ty<'tcx>(
),
ty::Array(ty, n) => {
let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n);
- let n = print_const(cx, n);
+ let n = print_const(cx.tcx, n);
Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into())
}
ty::RawPtr(ty, mutbl) => {
RawPointer(mutbl, Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)))
}
ty::Ref(r, ty, mutbl) => BorrowedRef {
- lifetime: clean_middle_region(r, cx),
+ lifetime: clean_middle_region(r, cx.tcx),
mutability: mutbl,
type_: Box::new(clean_middle_ty(
bound_ty.rebind(ty),
@@ -2080,7 +2080,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
// FIXME: should we merge the outer and inner binders somehow?
let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
let decl = clean_poly_fn_sig(cx, None, sig);
- let generic_params = clean_bound_vars(sig.bound_vars(), cx);
+ let generic_params = clean_bound_vars(sig.bound_vars(), cx.tcx);
BareFunction(Box::new(BareFunctionDecl {
safety: sig.safety(),
@@ -2090,7 +2090,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}))
}
ty::UnsafeBinder(inner) => {
- let generic_params = clean_bound_vars(inner.bound_vars(), cx);
+ let generic_params = clean_bound_vars(inner.bound_vars(), cx.tcx);
let ty = clean_middle_ty(inner.into(), cx, None, None);
UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty }))
}
@@ -2301,7 +2301,7 @@ fn clean_middle_opaque_bounds<'tcx>(
let trait_ref = match bound_predicate.skip_binder() {
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
- return clean_middle_region(reg, cx).map(GenericBound::Outlives);
+ return clean_middle_region(reg, cx.tcx).map(GenericBound::Outlives);
}
_ => return None,
};
@@ -2376,7 +2376,12 @@ fn clean_middle_opaque_bounds<'tcx>(
}
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
- clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx)
+ clean_field_with_def_id(
+ field.def_id.to_def_id(),
+ field.ident.name,
+ clean_ty(field.ty, cx),
+ cx.tcx,
+ )
}
pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) -> Item {
@@ -2389,7 +2394,7 @@ pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>)
Some(field.did),
None,
),
- cx,
+ cx.tcx,
)
}
@@ -2397,9 +2402,9 @@ pub(crate) fn clean_field_with_def_id(
def_id: DefId,
name: Symbol,
ty: Type,
- cx: &mut DocContext<'_>,
+ tcx: TyCtxt<'_>,
) -> Item {
- Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx)
+ Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), tcx)
}
pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item {
@@ -2422,7 +2427,7 @@ pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_
variant.def_id,
Some(variant.name),
VariantItem(Variant { kind, discriminant }),
- cx,
+ cx.tcx,
)
}
@@ -2463,7 +2468,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>(
field.did,
field.name,
clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None),
- cx,
+ cx.tcx,
)
})
.collect(),
@@ -2488,7 +2493,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>(
field.did,
field.name,
clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None),
- cx,
+ cx.tcx,
)
})
.collect(),
@@ -2499,7 +2504,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>(
variant.def_id,
Some(variant.name),
VariantItem(Variant { kind, discriminant }),
- cx,
+ cx.tcx,
)
}
@@ -2663,7 +2668,7 @@ fn get_all_import_attributes<'hir>(
.iter()
.flat_map(|reexport| reexport.id())
{
- let import_attrs = inline::load_attrs(cx, def_id);
+ let import_attrs = inline::load_attrs(cx.tcx, def_id);
if first {
// This is the "original" reexport so we get all its attributes without filtering them.
attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect();
@@ -2763,12 +2768,8 @@ fn clean_maybe_renamed_item<'tcx>(
import_ids: &[LocalDefId],
) -> Vec- {
use hir::ItemKind;
- fn get_name(
- cx: &DocContext<'_>,
- item: &hir::Item<'_>,
- renamed: Option,
- ) -> Option {
- renamed.or_else(|| cx.tcx.hir_opt_name(item.hir_id()))
+ fn get_name(tcx: TyCtxt<'_>, item: &hir::Item<'_>, renamed: Option) -> Option {
+ renamed.or_else(|| tcx.hir_opt_name(item.hir_id()))
}
let def_id = item.owner_id.to_def_id();
@@ -2785,7 +2786,7 @@ fn clean_maybe_renamed_item<'tcx>(
ItemKind::Use(path, kind) => {
return clean_use_statement(
item,
- get_name(cx, item, renamed),
+ get_name(cx.tcx, item, renamed),
path,
kind,
cx,
@@ -2795,7 +2796,7 @@ fn clean_maybe_renamed_item<'tcx>(
_ => {}
}
- let mut name = get_name(cx, item, renamed).unwrap();
+ let mut name = get_name(cx.tcx, item, renamed).unwrap();
let kind = match item.kind {
ItemKind::Static(mutability, _, ty, body_id) => StaticItem(Static {
@@ -2861,14 +2862,14 @@ fn clean_maybe_renamed_item<'tcx>(
// FIXME: handle attributes and derives that aren't proc macros, and macros with
// multiple kinds
ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
- source: display_macro_source(cx, name, macro_def),
+ source: display_macro_source(cx.tcx, name, macro_def),
macro_rules: macro_def.macro_rules,
}),
ItemKind::Macro(_, _, MacroKinds::ATTR) => {
- clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
+ clean_proc_macro(item, &mut name, MacroKind::Attr, cx.tcx)
}
ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
- clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
+ clean_proc_macro(item, &mut name, MacroKind::Derive, cx.tcx)
}
ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
// proc macros can have a name set by attributes
@@ -2907,7 +2908,7 @@ fn clean_maybe_renamed_item<'tcx>(
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
- Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx)
+ Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx.tcx)
}
fn clean_impl<'tcx>(
@@ -2928,7 +2929,7 @@ fn clean_impl<'tcx>(
def_id.to_def_id(),
None,
PlaceholderImplItem,
- cx,
+ tcx,
)];
}
Some(clean_trait_ref(&t.trait_ref, cx))
@@ -2983,7 +2984,7 @@ fn clean_impl<'tcx>(
},
is_deprecated,
}));
- Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx)
+ Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, tcx)
};
if let Some(type_alias) = type_alias {
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
@@ -3031,7 +3032,7 @@ fn clean_extern_crate<'tcx>(
krate_owner_def_id.to_def_id(),
Some(name),
ExternCrateItem { src: orig_name },
- cx,
+ cx.tcx,
)]
}
@@ -3160,14 +3161,14 @@ fn clean_use_statement_inner<'tcx>(
import_def_id.to_def_id(),
None,
ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
- cx,
+ cx.tcx,
));
return items;
}
Import::new_simple(name, resolve_use_source(cx, path), true)
};
- vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)]
+ vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx.tcx)]
}
fn clean_maybe_renamed_foreign_item<'tcx>(
@@ -3233,13 +3234,13 @@ fn clean_assoc_item_constraint<'tcx>(
fn clean_bound_vars<'tcx>(
bound_vars: &ty::List>,
- cx: &mut DocContext<'tcx>,
+ tcx: TyCtxt<'tcx>,
) -> Vec {
bound_vars
.into_iter()
.filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) => {
- let name = cx.tcx.item_name(def_id);
+ let name = tcx.item_name(def_id);
if name != kw::UnderscoreLifetime {
Some(GenericParamDef::lifetime(def_id, name))
} else {
@@ -3247,7 +3248,7 @@ fn clean_bound_vars<'tcx>(
}
}
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => {
- let name = cx.tcx.item_name(def_id);
+ let name = tcx.item_name(def_id);
Some(GenericParamDef {
name,
def_id,
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 6fb878ea54856..154f31e89dbff 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -15,12 +15,13 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::DefId;
+use rustc_middle::ty::TyCtxt;
use crate::clean;
use crate::clean::{GenericArgs as PP, WherePredicate as WP};
use crate::core::DocContext;
-pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVec {
+pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec) -> ThinVec {
// First, partition the where clause into its separate components.
//
// We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to
@@ -47,7 +48,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVe
// general bound predicates.
equalities.retain(|(lhs, rhs)| {
let Some((bounds, _)) = tybounds.get_mut(&lhs.self_type) else { return true };
- merge_bounds(cx, bounds, lhs.trait_.as_ref().unwrap().def_id(), lhs.assoc.clone(), rhs)
+ merge_bounds(tcx, bounds, lhs.trait_.as_ref().unwrap().def_id(), lhs.assoc.clone(), rhs)
});
// And finally, let's reassemble everything
@@ -65,7 +66,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVe
}
pub(crate) fn merge_bounds(
- cx: &clean::DocContext<'_>,
+ tcx: TyCtxt<'_>,
bounds: &mut [clean::GenericBound],
trait_did: DefId,
assoc: clean::PathSegment,
@@ -79,7 +80,7 @@ pub(crate) fn merge_bounds(
// If this QPath's trait `trait_did` is the same as, or a supertrait
// of, the bound's trait `did` then we can keep going, otherwise
// this is just a plain old equality bound.
- if !trait_is_same_or_supertrait(cx, trait_ref.trait_.def_id(), trait_did) {
+ if !trait_is_same_or_supertrait(tcx, trait_ref.trait_.def_id(), trait_did) {
return false;
}
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
@@ -108,15 +109,15 @@ pub(crate) fn merge_bounds(
})
}
-fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool {
+fn trait_is_same_or_supertrait(tcx: TyCtxt<'_>, child: DefId, trait_: DefId) -> bool {
if child == trait_ {
return true;
}
- let predicates = cx.tcx.explicit_super_predicates_of(child);
+ let predicates = tcx.explicit_super_predicates_of(child);
predicates
.iter_identity_copied()
.filter_map(|(pred, _)| Some(pred.as_trait_clause()?.def_id()))
- .any(|did| trait_is_same_or_supertrait(cx, did, trait_))
+ .any(|did| trait_is_same_or_supertrait(tcx, did, trait_))
}
pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generics) {
@@ -139,10 +140,10 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi
return true;
};
- if bounds.iter().any(|b| b.is_sized_bound(cx)) {
+ if bounds.iter().any(|b| b.is_sized_bound(cx.tcx)) {
sized_params.insert(*param);
false
- } else if bounds.iter().any(|b| b.is_meta_sized_bound(cx)) {
+ } else if bounds.iter().any(|b| b.is_meta_sized_bound(cx.tcx)) {
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
// is shown and none of the new sizedness traits leak into documentation.
false
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ad70fc1096691..04aeb19f242de 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -465,6 +465,15 @@ impl Item {
.unwrap_or(false)
}
+ /// Returns true if item is an associated function with a `self` parameter.
+ pub(crate) fn has_self_param(&self) -> bool {
+ if let ItemKind::MethodItem(box Function { decl, .. }, _) = &self.inner.kind {
+ decl.receiver_type().is_some()
+ } else {
+ false
+ }
+ }
+
pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option {
let kind = match &self.kind {
ItemKind::StrippedItem(k) => k,
@@ -514,10 +523,10 @@ impl Item {
def_id: DefId,
name: Option,
kind: ItemKind,
- cx: &mut DocContext<'_>,
+ tcx: TyCtxt<'_>,
) -> Item {
#[allow(deprecated)]
- let hir_attrs = cx.tcx.get_all_attrs(def_id);
+ let hir_attrs = tcx.get_all_attrs(def_id);
Self::from_def_id_and_attrs_and_parts(
def_id,
@@ -1119,20 +1128,20 @@ impl GenericBound {
matches!(self, Self::TraitBound(..))
}
- pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
- self.is_bounded_by_lang_item(cx, LangItem::Sized)
+ pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
+ self.is_bounded_by_lang_item(tcx, LangItem::Sized)
}
- pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
- self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
+ pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
+ self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
}
- fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
+ fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
if let GenericBound::TraitBound(
PolyTrait { ref trait_, .. },
rustc_hir::TraitBoundModifiers::NONE,
) = *self
- && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
+ && tcx.is_lang_item(trait_.def_id(), lang_item)
{
return true;
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 834b73997c959..2284b815a09a9 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -72,14 +72,14 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
def_id,
Some(prim.as_sym()),
ItemKind::PrimitiveItem(prim),
- cx,
+ cx.tcx,
)
}));
m.items.extend(keywords.map(|(def_id, kw)| {
- Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx)
+ Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx.tcx)
}));
m.items.extend(documented_attributes.into_iter().map(|(def_id, kw)| {
- Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx)
+ Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx.tcx)
}));
}
@@ -135,7 +135,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
match arg.skip_binder().kind() {
GenericArgKind::Lifetime(lt) => Some(GenericArg::Lifetime(
- clean_middle_region(lt, cx).unwrap_or(Lifetime::elided()),
+ clean_middle_region(lt, cx.tcx).unwrap_or(Lifetime::elided()),
)),
GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(
arg.rebind(ty),
@@ -148,7 +148,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
}),
))),
GenericArgKind::Const(ct) => {
- Some(GenericArg::Const(Box::new(clean_middle_const(arg.rebind(ct), cx))))
+ Some(GenericArg::Const(Box::new(clean_middle_const(arg.rebind(ct)))))
}
}
};
@@ -347,13 +347,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
})
}
-pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
+pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
if let Some(def) = def.as_local() {
- rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def)
+ rendered_const(tcx, tcx.hir_body_owned_by(def), def)
} else {
- inline::print_inlined_const(cx.tcx, def)
+ inline::print_inlined_const(tcx, def)
}
}
// array lengths are obviously usize
@@ -602,26 +602,21 @@ fn render_macro_arms<'a>(
out
}
-pub(super) fn display_macro_source(
- cx: &mut DocContext<'_>,
- name: Symbol,
- def: &ast::MacroDef,
-) -> String {
+pub(super) fn display_macro_source(tcx: TyCtxt<'_>, name: Symbol, def: &ast::MacroDef) -> String {
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
if def.macro_rules {
- format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ";"))
+ format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(tcx, matchers, ";"))
} else {
if matchers.len() <= 1 {
format!(
"macro {name}{matchers} {{\n ...\n}}",
- matchers = matchers
- .map(|matcher| render_macro_matcher(cx.tcx, matcher))
- .collect::(),
+ matchers =
+ matchers.map(|matcher| render_macro_matcher(tcx, matcher)).collect::(),
)
} else {
- format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ","))
+ format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(tcx, matchers, ","))
}
}
}
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index a4535792ac3ce..d40c9501cabc1 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -433,6 +433,7 @@ fn sidebar_assoc_items<'a>(
let mut assoc_consts = Vec::new();
let mut assoc_types = Vec::new();
+ let mut assoc_fns = Vec::new();
let mut methods = Vec::new();
if let Some(v) = cache.impls.get(&did) {
let mut used_links = FxHashSet::default();
@@ -443,7 +444,12 @@ fn sidebar_assoc_items<'a>(
for impl_ in v.iter().map(|i| i.inner_impl()).filter(|i| i.trait_.is_none()) {
assoc_consts.extend(get_associated_constants(impl_, used_links_bor));
assoc_types.extend(get_associated_types(impl_, used_links_bor));
- methods.extend(get_methods(impl_, false, used_links_bor, false, cx.tcx()));
+ methods.extend(get_methods(
+ impl_,
+ GetMethodsMode::AlsoCollectAssocFns { assoc_fns: &mut assoc_fns },
+ used_links_bor,
+ cx.tcx(),
+ ));
}
// We want links' order to be reproducible so we don't use unstable sort.
assoc_consts.sort();
@@ -462,6 +468,11 @@ fn sidebar_assoc_items<'a>(
"associatedtype",
assoc_types,
),
+ LinkBlock::new(
+ Link::new("implementations", "Associated Functions"),
+ "method",
+ assoc_fns,
+ ),
LinkBlock::new(Link::new("implementations", "Methods"), "method", methods),
];
@@ -546,7 +557,15 @@ fn sidebar_deref_methods<'a>(
i.inner_impl().trait_.is_none()
&& real_target.is_doc_subtype_of(&i.inner_impl().for_, c)
})
- .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
+ .flat_map(|i| {
+ get_methods(
+ i.inner_impl(),
+ GetMethodsMode::Deref { deref_mut },
+ used_links,
+ cx.tcx(),
+ )
+ .collect::>()
+ })
.collect::>();
if !ret.is_empty() {
let id = if let Some(target_def_id) = real_target.def_id(c) {
@@ -734,69 +753,82 @@ fn get_next_url(used_links: &mut FxHashSet, url: String) -> String {
format!("{url}-{add}")
}
+enum GetMethodsMode<'r, 'l> {
+ Deref { deref_mut: bool },
+ AlsoCollectAssocFns { assoc_fns: &'r mut Vec> },
+}
+
fn get_methods<'a>(
i: &'a clean::Impl,
- for_deref: bool,
+ mut mode: GetMethodsMode<'_, 'a>,
used_links: &mut FxHashSet,
- deref_mut: bool,
tcx: TyCtxt<'_>,
-) -> Vec> {
- i.items
- .iter()
- .filter_map(|item| {
- if let Some(ref name) = item.name
- && item.is_method()
- && (!for_deref || super::should_render_item(item, deref_mut, tcx))
- {
- Some(Link::new(
+) -> impl Iterator
- > {
+ i.items.iter().filter_map(move |item| {
+ if let Some(ref name) = item.name
+ && item.is_method()
+ {
+ let mut build_link = || {
+ Link::new(
get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)),
name.as_str(),
- ))
- } else {
- None
+ )
+ };
+ match &mut mode {
+ &mut GetMethodsMode::Deref { deref_mut } => {
+ if super::should_render_item(item, deref_mut, tcx) {
+ Some(build_link())
+ } else {
+ None
+ }
+ }
+ GetMethodsMode::AlsoCollectAssocFns { assoc_fns } => {
+ if item.has_self_param() {
+ Some(build_link())
+ } else {
+ assoc_fns.push(build_link());
+ None
+ }
+ }
}
- })
- .collect()
+ } else {
+ None
+ }
+ })
}
fn get_associated_constants<'a>(
i: &'a clean::Impl,
used_links: &mut FxHashSet,
-) -> Vec> {
- i.items
- .iter()
- .filter_map(|item| {
- if let Some(ref name) = item.name
- && item.is_associated_const()
- {
- Some(Link::new(
- get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)),
- name.as_str(),
- ))
- } else {
- None
- }
- })
- .collect()
+) -> impl Iterator
- > {
+ i.items.iter().filter_map(|item| {
+ if let Some(ref name) = item.name
+ && item.is_associated_const()
+ {
+ Some(Link::new(
+ get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)),
+ name.as_str(),
+ ))
+ } else {
+ None
+ }
+ })
}
fn get_associated_types<'a>(
i: &'a clean::Impl,
used_links: &mut FxHashSet,
-) -> Vec> {
- i.items
- .iter()
- .filter_map(|item| {
- if let Some(ref name) = item.name
- && item.is_associated_type()
- {
- Some(Link::new(
- get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
- name.as_str(),
- ))
- } else {
- None
- }
- })
- .collect()
+) -> impl Iterator
- > {
+ i.items.iter().filter_map(|item| {
+ if let Some(ref name) = item.name
+ && item.is_associated_type()
+ {
+ Some(Link::new(
+ get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
+ name.as_str(),
+ ))
+ } else {
+ None
+ }
+ })
}
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
index 49153d58fe98c..4d4222a34956a 100644
--- a/src/librustdoc/html/templates/type_layout.html
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -60,11 +60,6 @@
- {% when Err(LayoutError::Cycle(_)) %}
- {# #}
- Note: Encountered an error during type layout; {#+ #}
- the type's layout depended on the type's layout itself. {# #}
-
{% when Err(LayoutError::InvalidSimd {..}) %}
{# #}
Note: Encountered an error during type layout; {#+ #}
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index f73db253af062..92798bb9bb011 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -64,14 +64,14 @@ impl CfgPropagator<'_, '_> {
&& let Some(mut next_def_id) = item.item_id.as_local_def_id()
{
while let Some(parent_def_id) = self.cx.tcx.opt_local_parent(next_def_id) {
- let x = load_attrs(self.cx, parent_def_id.to_def_id());
+ let x = load_attrs(self.cx.tcx, parent_def_id.to_def_id());
add_only_cfg_attributes(&mut attrs, x);
next_def_id = parent_def_id;
}
}
let (_, cfg) = merge_attrs(
- self.cx,
+ self.cx.tcx,
item.attrs.other_attrs.as_slice(),
Some((&attrs, None)),
&mut self.cfg_info,
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 1e75df7d278fb..cf4f7d689ac22 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -10,6 +10,7 @@ use std::{iter, thread};
use rustc_abi::ExternAbi;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::FatalErrorMarker;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutCx};
@@ -477,7 +478,11 @@ pub fn eval_entry<'tcx>(
let res: thread::Result> =
panic::catch_unwind(AssertUnwindSafe(|| ecx.run_threads()));
let res = res.unwrap_or_else(|panic_payload| {
- ecx.handle_ice();
+ // rustc "handles" some errors by unwinding with FatalErrorMarker
+ // (after emitting suitable diagnostics), so do not treat those as ICEs.
+ if !panic_payload.is::() {
+ ecx.handle_ice();
+ }
panic::resume_unwind(panic_payload)
});
// Obtain the result of the execution. This is always an `Err`, but that doesn't necessarily
diff --git a/src/tools/miri/tests/fail/layout_cycle.rs b/src/tools/miri/tests/fail/layout_cycle.rs
index 3e0dd881db84e..8d5f1914d0c32 100644
--- a/src/tools/miri/tests/fail/layout_cycle.rs
+++ b/src/tools/miri/tests/fail/layout_cycle.rs
@@ -1,5 +1,4 @@
-//@error-in-other-file: a cycle occurred during layout computation
-//~^ ERROR: cycle detected when computing layout of
+//~ ERROR: cycle detected when computing layout of
use std::mem;
diff --git a/src/tools/miri/tests/fail/layout_cycle.stderr b/src/tools/miri/tests/fail/layout_cycle.stderr
index dae6934931228..f8d555e5a10b8 100644
--- a/src/tools/miri/tests/fail/layout_cycle.stderr
+++ b/src/tools/miri/tests/fail/layout_cycle.stderr
@@ -9,13 +9,6 @@ LL | const SIZE: usize = intrinsics::size_of::();
| ^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-error[E0080]: a cycle occurred during layout computation
- --> RUSTLIB/core/src/mem/mod.rs:LL:CC
- |
-LL | const SIZE: usize = intrinsics::size_of::();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `> as std::mem::SizedTypeProperties>::SIZE` failed here
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs
new file mode 100644
index 0000000000000..1aaba621d0e10
--- /dev/null
+++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs
@@ -0,0 +1,149 @@
+//@ only-aarch64
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features)]
+#![feature(rustc_attrs)]
+
+// Test that we generate the correct debuginfo for scalable vector types.
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svint8_t(i8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint8x2_t(svint8_t, svint8_t);
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svuint8_t(u8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint8x2_t(svuint8_t, svuint8_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svint16_t(i16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint16x2_t(svint16_t, svint16_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svuint16_t(u16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint16x2_t(svuint16_t, svuint16_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svint32_t(i32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint32x2_t(svint32_t, svint32_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svuint32_t(u32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint32x2_t(svuint32_t, svuint32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svint64_t(i64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint64x2_t(svint64_t, svint64_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svuint64_t(u64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint64x2_t(svuint64_t, svuint64_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svfloat32_t(f32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat32x2_t(svfloat32_t, svfloat32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svfloat64_t(f64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat64x2_t(svfloat64_t, svfloat64_t);
+
+#[target_feature(enable = "sve")]
+pub fn locals() {
+ // CHECK-DAG: name: "svint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS8x2]] = !{![[REALELTS8x2:[0-9]+]]}
+ // 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))
+ let s8: svint8x2_t;
+
+ // CHECK-DAG: name: "svuint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+ let u8: svuint8x2_t;
+
+ // CHECK-DAG: name: "svint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS16x2]] = !{![[REALELTS16x2:[0-9]+]]}
+ // 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))
+ let s16: svint16x2_t;
+
+ // CHECK-DAG: name: "svuint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
+ let u16: svuint16x2_t;
+
+ // CHECK-DAG: name: "svint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS32x2]] = !{![[REALELTS32x2:[0-9]+]]}
+ // 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))
+ let s32: svint32x2_t;
+
+ // CHECK-DAG: name: "svuint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
+ let u32: svuint32x2_t;
+
+ // CHECK-DAG: name: "svint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS1x2_64]] = !{![[REALELTS1x2_64:[0-9]+]]}
+ // 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))
+ let s64: svint64x2_t;
+
+ // CHECK-DAG: name: "svuint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+ let u64: svuint64x2_t;
+
+ // CHECK: name: "svfloat32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
+ let f32: svfloat32x2_t;
+
+ // CHECK: name: "svfloat64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
+ let f64: svfloat64x2_t;
+}
diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs
new file mode 100644
index 0000000000000..b19051e2c743d
--- /dev/null
+++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs
@@ -0,0 +1,149 @@
+//@ only-aarch64
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features)]
+#![feature(rustc_attrs)]
+
+// Test that we generate the correct debuginfo for scalable vector types.
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svint8_t(i8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint8x3_t(svint8_t, svint8_t, svint8_t);
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svuint8_t(u8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint8x3_t(svuint8_t, svuint8_t, svuint8_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svint16_t(i16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint16x3_t(svint16_t, svint16_t, svint16_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svuint16_t(u16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint16x3_t(svuint16_t, svuint16_t, svuint16_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svint32_t(i32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint32x3_t(svint32_t, svint32_t, svint32_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svuint32_t(u32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint32x3_t(svuint32_t, svuint32_t, svuint32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svint64_t(i64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint64x3_t(svint64_t, svint64_t, svint64_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svuint64_t(u64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint64x3_t(svuint64_t, svuint64_t, svuint64_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svfloat32_t(f32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svfloat64_t(f64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat64x3_t(svfloat64_t, svfloat64_t, svfloat64_t);
+
+#[target_feature(enable = "sve")]
+pub fn locals() {
+ // CHECK-DAG: name: "svint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS8x3]] = !{![[REALELTS8x3:[0-9]+]]}
+ // 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))
+ let s8: svint8x3_t;
+
+ // CHECK-DAG: name: "svuint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+ let u8: svuint8x3_t;
+
+ // CHECK-DAG: name: "svint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS16x3]] = !{![[REALELTS16x3:[0-9]+]]}
+ // 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))
+ let s16: svint16x3_t;
+
+ // CHECK-DAG: name: "svuint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
+ let u16: svuint16x3_t;
+
+ // CHECK-DAG: name: "svint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS32x3]] = !{![[REALELTS32x3:[0-9]+]]}
+ // 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))
+ let s32: svint32x3_t;
+
+ // CHECK-DAG: name: "svuint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
+ let u32: svuint32x3_t;
+
+ // CHECK-DAG: name: "svint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS1x3_64]] = !{![[REALELTS1x3_64:[0-9]+]]}
+ // 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))
+ let s64: svint64x3_t;
+
+ // CHECK-DAG: name: "svuint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+ let u64: svuint64x3_t;
+
+ // CHECK: name: "svfloat32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
+ let f32: svfloat32x3_t;
+
+ // CHECK: name: "svfloat64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
+ let f64: svfloat64x3_t;
+}
diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs
new file mode 100644
index 0000000000000..911af76f42ebb
--- /dev/null
+++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs
@@ -0,0 +1,149 @@
+//@ only-aarch64
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features)]
+#![feature(rustc_attrs)]
+
+// Test that we generate the correct debuginfo for scalable vector types.
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svint8_t(i8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint8x4_t(svint8_t, svint8_t, svint8_t, svint8_t);
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svuint8_t(u8);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint8x4_t(svuint8_t, svuint8_t, svuint8_t, svuint8_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svint16_t(i16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint16x4_t(svint16_t, svint16_t, svint16_t, svint16_t);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svuint16_t(u16);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint16x4_t(svuint16_t, svuint16_t, svuint16_t, svuint16_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svint32_t(i32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint32x4_t(svint32_t, svint32_t, svint32_t, svint32_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svuint32_t(u32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint32x4_t(svuint32_t, svuint32_t, svuint32_t, svuint32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svint64_t(i64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svint64x4_t(svint64_t, svint64_t, svint64_t, svint64_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svuint64_t(u64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svuint64x4_t(svuint64_t, svuint64_t, svuint64_t, svuint64_t);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svfloat32_t(f32);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svfloat64_t(f64);
+
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+struct svfloat64x4_t(svfloat64_t, svfloat64_t, svfloat64_t, svfloat64_t);
+
+#[target_feature(enable = "sve")]
+pub fn locals() {
+ // CHECK-DAG: name: "svint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS8x4]] = !{![[REALELTS8x4:[0-9]+]]}
+ // 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))
+ let s8: svint8x4_t;
+
+ // CHECK-DAG: name: "svuint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4]])
+ // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+ let u8: svuint8x4_t;
+
+ // CHECK-DAG: name: "svint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS16x4]] = !{![[REALELTS16x4:[0-9]+]]}
+ // 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))
+ let s16: svint16x4_t;
+
+ // CHECK-DAG: name: "svuint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
+ let u16: svuint16x4_t;
+
+ // CHECK-DAG: name: "svint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS32x4]] = !{![[REALELTS32x4:[0-9]+]]}
+ // 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))
+ let s32: svint32x4_t;
+
+ // CHECK-DAG: name: "svuint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
+ let u32: svuint32x4_t;
+
+ // CHECK-DAG: name: "svint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS1x4_64]] = !{![[REALELTS1x4_64:[0-9]+]]}
+ // 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))
+ let s64: svint64x4_t;
+
+ // CHECK-DAG: name: "svuint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+ let u64: svuint64x4_t;
+
+ // CHECK: name: "svfloat32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
+ let f32: svfloat32x4_t;
+
+ // CHECK: name: "svfloat64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
+ let f64: svfloat64x4_t;
+}
diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo.rs b/tests/codegen-llvm/scalable-vectors/debuginfo.rs
new file mode 100644
index 0000000000000..f4b34a5e1e7eb
--- /dev/null
+++ b/tests/codegen-llvm/scalable-vectors/debuginfo.rs
@@ -0,0 +1,123 @@
+// ignore-tidy-linelength
+//@ only-aarch64
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+//@ revisions: POST-LLVM-22 PRE-LLVM-22
+//@ [PRE-LLVM-22] max-llvm-major-version: 21
+//@ [POST-LLVM-22] min-llvm-version: 22
+
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features)]
+#![feature(rustc_attrs)]
+
+// Test that we generate the correct debuginfo for scalable vector types.
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svbool_t(bool);
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svint8_t(i8);
+
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+struct svuint8_t(u8);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svint16_t(i16);
+
+#[rustc_scalable_vector(8)]
+#[allow(non_camel_case_types)]
+struct svuint16_t(u16);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svint32_t(i32);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svuint32_t(u32);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svint64_t(i64);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svuint64_t(u64);
+
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+struct svfloat32_t(f32);
+
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+struct svfloat64_t(f64);
+
+#[target_feature(enable = "sve")]
+pub fn locals() {
+ // CHECK-DAG: name: "svbool_t",{{.*}}, baseType: ![[CT1:[0-9]+]]
+ // PRE-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]])
+ // POST-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]], bitStride: i64 1)
+ // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+ // CHECK-DAG: ![[ELTS8]] = !{![[REALELTS8:[0-9]+]]}
+ // 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))
+ let b8: svbool_t;
+
+ // CHECK-DAG: name: "svint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYS8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]])
+ // CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed)
+ let s8: svint8_t;
+
+ // PRE-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT1:[0-9]+]]
+ // POST-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
+ // POST-LLVM-22-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8]])
+ let u8: svuint8_t;
+
+ // CHECK-DAG: name: "svint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS16]] = !{![[REALELTS16:[0-9]+]]}
+ // 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))
+ let s16: svint16_t;
+
+ // CHECK-DAG: name: "svuint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]]
+ // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16]])
+ // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
+ let u16: svuint16_t;
+
+ // CHECK-DAG: name: "svint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS32]] = !{![[REALELTS32:[0-9]+]]}
+ // 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))
+ let s32: svint32_t;
+
+ // CHECK-DAG: name: "svuint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
+ let u32: svuint32_t;
+
+ // CHECK-DAG: name: "svint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64:[0-9]+]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed)
+ // CHECK-DAG: ![[ELTS64]] = !{![[REALELTS64:[0-9]+]]}
+ // 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))
+ let s64: svint64_t;
+
+ // CHECK-DAG: name: "svuint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+ let u64: svuint64_t;
+
+ // CHECK: name: "svfloat32_t",{{.*}}, baseType: ![[CT32:[0-9]+]]
+ // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]])
+ // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float)
+ let f32: svfloat32_t;
+
+ // CHECK: name: "svfloat64_t",{{.*}}, baseType: ![[CT64:[0-9]+]]
+ // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]])
+ // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
+ let f64: svfloat64_t;
+}
diff --git a/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs b/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs
new file mode 100644
index 0000000000000..e19fc40cb9d67
--- /dev/null
+++ b/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs
@@ -0,0 +1,100 @@
+//@ build-pass
+//@ only-aarch64
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features)]
+#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)]
+
+// Tests that tuples of scalable vectors are passed as immediates and that the intrinsics for
+// creating/getting/setting tuples of scalable vectors generate the correct assembly
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector(4)]
+#[allow(non_camel_case_types)]
+pub struct svfloat32_t(f32);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+pub struct svfloat32x2_t(svfloat32_t, svfloat32_t);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+pub struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector]
+#[allow(non_camel_case_types)]
+pub struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t);
+
+#[inline(never)]
+#[target_feature(enable = "sve")]
+pub fn svdup_n_f32(op: f32) -> svfloat32_t {
+ extern "C" {
+ #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4f32")]
+ fn _svdup_n_f32(op: f32) -> svfloat32_t;
+ }
+ unsafe { _svdup_n_f32(op) }
+}
+
+// CHECK: define { , } @svcreate2_f32( %x0, %x1)
+#[no_mangle]
+#[target_feature(enable = "sve")]
+pub fn svcreate2_f32(x0: svfloat32_t, x1: svfloat32_t) -> svfloat32x2_t {
+ // CHECK: %1 = insertvalue { , } poison, %x0, 0
+ // CHECK-NEXT: %2 = insertvalue { , } %1, %x1, 1
+ unsafe { std::intrinsics::simd::scalable::sve_tuple_create2(x0, x1) }
+}
+
+// CHECK: define { , , } @svcreate3_f32( %x0, %x1, %x2)
+#[no_mangle]
+#[target_feature(enable = "sve")]
+pub fn svcreate3_f32(x0: svfloat32_t, x1: svfloat32_t, x2: svfloat32_t) -> svfloat32x3_t {
+ // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate3_f32
+ // CHECK: %1 = insertvalue { , , } poison, %x0, 0
+ // CHECK-NEXT: %2 = insertvalue { , , } %1, %x1, 1
+ // CHECK-NEXT: %3 = insertvalue { , , } %2, %x2, 2
+ unsafe { std::intrinsics::simd::scalable::sve_tuple_create3(x0, x1, x2) }
+}
+
+// CHECK: define { , , , } @svcreate4_f32( %x0, %x1, %x2, %x3)
+#[no_mangle]
+#[target_feature(enable = "sve")]
+pub fn svcreate4_f32(
+ x0: svfloat32_t,
+ x1: svfloat32_t,
+ x2: svfloat32_t,
+ x3: svfloat32_t,
+) -> svfloat32x4_t {
+ // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate4_f32
+ // CHECK: %1 = insertvalue { , , , } poison, %x0, 0
+ // CHECK-NEXT: %2 = insertvalue { , , , } %1, %x1, 1
+ // CHECK-NEXT: %3 = insertvalue { , , , } %2, %x2, 2
+ // CHECK-NEXT: %4 = insertvalue { , , , } %3, %x3, 3
+ unsafe { std::intrinsics::simd::scalable::sve_tuple_create4(x0, x1, x2, x3) }
+}
+
+// CHECK: define @svget2_f32({ , } %tup)
+#[no_mangle]
+#[target_feature(enable = "sve")]
+pub fn svget2_f32(tup: svfloat32x2_t) -> svfloat32_t {
+ // CHECK: %1 = extractvalue { , } %tup, 0
+ unsafe { std::intrinsics::simd::scalable::sve_tuple_get::<_, _, { IDX }>(tup) }
+}
+
+// CHECK: define { , } @svset2_f32({ , } %tup, %x)
+#[no_mangle]
+#[target_feature(enable = "sve")]
+pub fn svset2_f32(tup: svfloat32x2_t, x: svfloat32_t) -> svfloat32x2_t {
+ // CHECK: %1 = insertvalue { , } %tup, %x, 0
+ unsafe { std::intrinsics::simd::scalable::sve_tuple_set::<_, _, { IDX }>(tup, x) }
+}
+
+// This function exists only so there are calls to the generic functions
+#[target_feature(enable = "sve")]
+pub fn test() {
+ let x = svdup_n_f32(2f32);
+ let tup = svcreate2_f32(x, x);
+ let x = svget2_f32::<0>(tup);
+ let tup = svset2_f32::<0>(tup, x);
+}
diff --git a/tests/rustdoc-gui/hash-item-expansion.goml b/tests/rustdoc-gui/hash-item-expansion.goml
index a7a5c3cb48345..8661641206685 100644
--- a/tests/rustdoc-gui/hash-item-expansion.goml
+++ b/tests/rustdoc-gui/hash-item-expansion.goml
@@ -5,7 +5,7 @@ assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"ope
// We first check that the impl block is open by default.
assert-attribute: ("#implementations-list details", {"open": ""})
// To ensure that we will click on the currently hidden method.
-assert-text: (".sidebar-elems section .block li > a", "must_use")
-click: ".sidebar-elems section .block li > a"
+assert-text: (".sidebar-elems section ul:nth-of-type(2) li > a", "must_use")
+click: ".sidebar-elems ul:nth-of-type(2) li > a"
// We check that the impl block was opened as expected so that we can see the method.
assert-attribute: ("#implementations-list > details", {"open": ""})
diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml
index 3183650b555a8..61c1555fbc0e3 100644
--- a/tests/rustdoc-gui/sidebar-mobile.goml
+++ b/tests/rustdoc-gui/sidebar-mobile.goml
@@ -48,7 +48,7 @@ assert-property: ("rustdoc-topbar", {"clientHeight": "45"})
// Check that clicking an element from the sidebar scrolls to the right place
// so the target is not obscured by the topbar.
click: ".sidebar-menu-toggle"
-click: ".sidebar-elems section .block li > a"
+click: ".sidebar-elems section ul:nth-of-type(2) li > a"
assert-position: ("#method\.must_use", {"y": 45})
// Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
diff --git a/tests/rustdoc-html/sidebar/sidebar-items.rs b/tests/rustdoc-html/sidebar/sidebar-items.rs
index 6e13457796e5e..bd0893dac3e36 100644
--- a/tests/rustdoc-html/sidebar/sidebar-items.rs
+++ b/tests/rustdoc-html/sidebar/sidebar-items.rs
@@ -42,6 +42,14 @@ pub struct Bar {
waza: u32,
}
+//@ has foo/struct.Bar.html
+//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#implementations"]' 'Associated Functions'
+//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#implementations"]' 'Methods'
+impl Bar {
+ pub fn method(&self) {}
+ pub fn assoc_fn() {}
+}
+
//@ has foo/enum.En.html
//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants'
//@ has - '//*[@class="sidebar-elems"]//section//a' 'Foo'
diff --git a/tests/rustdoc-html/typedef.rs b/tests/rustdoc-html/typedef.rs
index 3fdc2788bcacf..4eae3c7258213 100644
--- a/tests/rustdoc-html/typedef.rs
+++ b/tests/rustdoc-html/typedef.rs
@@ -13,7 +13,7 @@ impl MyStruct {
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias'
//@ hasraw - 'Alias docstring'
//@ has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias'
-//@ has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
+//@ has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Associated Functions'
//@ has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations'
/// Alias docstring
pub type MyAlias = MyStruct;
diff --git a/tests/ui/auto-traits/ungated-impl.rs b/tests/ui/auto-traits/ungated-impl.rs
deleted file mode 100644
index d46b4b01af9c7..0000000000000
--- a/tests/ui/auto-traits/ungated-impl.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-auto trait MyTrait {}
-//~^ ERROR auto traits are experimental and possibly buggy
-
-impl !MyTrait for *mut T {}
-//~^ ERROR negative trait bounds are not fully implemented
-
-fn main() {}
diff --git a/tests/ui/auto-traits/ungated-impl.stderr b/tests/ui/auto-traits/ungated-impl.stderr
deleted file mode 100644
index 9d10d46a90283..0000000000000
--- a/tests/ui/auto-traits/ungated-impl.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0658]: auto traits are experimental and possibly buggy
- --> $DIR/ungated-impl.rs:1:1
- |
-LL | auto trait MyTrait {}
- | ^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #13231 for more information
- = help: add `#![feature(auto_traits)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: negative trait bounds are not fully implemented; use marker types for now
- --> $DIR/ungated-impl.rs:4:9
- |
-LL | impl !MyTrait for *mut T {}
- | ^^^^^^^^
- |
- = note: see issue #68318 for more information
- = help: add `#![feature(negative_impls)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs
new file mode 100644
index 0000000000000..67aed9122e89f
--- /dev/null
+++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs
@@ -0,0 +1,15 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/127423
+
+#![allow(dead_code)]
+
+const fn add(a: &'self isize) -> usize {
+ //~^ ERROR use of undeclared lifetime name `'self`
+ //~| ERROR lifetimes cannot use keyword names
+ Qux + y
+ //~^ ERROR cannot find value `Qux` in this scope
+ //~| ERROR cannot find value `y` in this scope
+}
+
+const ARR: [i32; add(1, 2)] = [5, 6, 7];
+
+pub fn main() {}
diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr
new file mode 100644
index 0000000000000..f01e9bd51357d
--- /dev/null
+++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr
@@ -0,0 +1,39 @@
+error: lifetimes cannot use keyword names
+ --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:5:18
+ |
+LL | const fn add(a: &'self isize) -> usize {
+ | ^^^^^
+
+error[E0261]: use of undeclared lifetime name `'self`
+ --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:5:18
+ |
+LL | const fn add(a: &'self isize) -> usize {
+ | ^^^^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'self` here
+ |
+LL | const fn add<'self>(a: &'self isize) -> usize {
+ | +++++++
+
+error[E0425]: cannot find value `Qux` in this scope
+ --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:5
+ |
+LL | Qux + y
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:11
+ |
+LL | Qux + y
+ | ^
+ |
+help: a local variable with a similar name exists
+ |
+LL - Qux + y
+LL + Qux + a
+ |
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0261, E0425.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/dropck/dropck-after-failed-type-lowering.rs b/tests/ui/dropck/dropck-after-failed-type-lowering.rs
index 2441e26fec96c..ee55e0dcaa491 100644
--- a/tests/ui/dropck/dropck-after-failed-type-lowering.rs
+++ b/tests/ui/dropck/dropck-after-failed-type-lowering.rs
@@ -3,11 +3,12 @@
trait B {
type C<'a>;
fn d() -> F {
+ //~^ ERROR: the trait bound `E: B` is not satisfied
todo!()
}
}
struct F {
- h: Option<::C>,
+ h: Option<::C>, //~ ERROR: the trait bound `G: B` is not satisfied
//~^ ERROR missing generics for associated type `B::C`
}
diff --git a/tests/ui/dropck/dropck-after-failed-type-lowering.stderr b/tests/ui/dropck/dropck-after-failed-type-lowering.stderr
index 56ea72de0c5f2..0922d2e4340e8 100644
--- a/tests/ui/dropck/dropck-after-failed-type-lowering.stderr
+++ b/tests/ui/dropck/dropck-after-failed-type-lowering.stderr
@@ -1,5 +1,5 @@
error[E0107]: missing generics for associated type `B::C`
- --> $DIR/dropck-after-failed-type-lowering.rs:10:25
+ --> $DIR/dropck-after-failed-type-lowering.rs:11:25
|
LL | h: Option<::C>,
| ^ expected 1 lifetime argument
@@ -14,6 +14,24 @@ help: add missing lifetime argument
LL | h: Option<::C<'a>>,
| ++++
-error: aborting due to 1 previous error
+error[E0277]: the trait bound `G: B` is not satisfied
+ --> $DIR/dropck-after-failed-type-lowering.rs:11:8
+ |
+LL | h: Option<::C>,
+ | ^^^^^^^^^^^^^^^^^^^ the trait `B` is not implemented for `G`
+ |
+help: consider restricting type parameter `G` with trait `B`
+ |
+LL | struct F {
+ | +++
+
+error[E0277]: the trait bound `E: B` is not satisfied
+ --> $DIR/dropck-after-failed-type-lowering.rs:5:18
+ |
+LL | fn d() -> F {
+ | ^^^^ the trait `B` is not implemented for `E`
+
+error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0107, E0277.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/extern/bad-external-async-fn-issue-146754.rs b/tests/ui/extern/bad-external-async-fn-issue-146754.rs
new file mode 100644
index 0000000000000..394341c129654
--- /dev/null
+++ b/tests/ui/extern/bad-external-async-fn-issue-146754.rs
@@ -0,0 +1,8 @@
+//@ edition:2024
+#![crate_type = "lib"]
+
+unsafe extern "C" {
+ async fn function() -> [(); || {}];
+ //~^ ERROR functions in `extern` blocks cannot have `async` qualifier
+ //~^^ ERROR mismatched types
+}
diff --git a/tests/ui/extern/bad-external-async-fn-issue-146754.stderr b/tests/ui/extern/bad-external-async-fn-issue-146754.stderr
new file mode 100644
index 0000000000000..2a04b23630430
--- /dev/null
+++ b/tests/ui/extern/bad-external-async-fn-issue-146754.stderr
@@ -0,0 +1,21 @@
+error: functions in `extern` blocks cannot have `async` qualifier
+ --> $DIR/bad-external-async-fn-issue-146754.rs:5:5
+ |
+LL | unsafe extern "C" {
+ | ----------------- in this `extern` block
+LL | async fn function() -> [(); || {}];
+ | ^^^^^ help: remove the `async` qualifier
+
+error[E0308]: mismatched types
+ --> $DIR/bad-external-async-fn-issue-146754.rs:5:33
+ |
+LL | async fn function() -> [(); || {}];
+ | ^^^^^ expected `usize`, found closure
+ |
+ = note: expected type `usize`
+ found closure `{closure@$DIR/bad-external-async-fn-issue-146754.rs:5:33: 5:35}`
+ = note: array length can only be `usize`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.rs b/tests/ui/feature-gates/feature-gate-auto-traits.rs
index aab9e784fe9d7..e900fb84a02d9 100644
--- a/tests/ui/feature-gates/feature-gate-auto-traits.rs
+++ b/tests/ui/feature-gates/feature-gate-auto-traits.rs
@@ -1,12 +1,5 @@
-// Test that default and negative trait implementations are gated by
-// `auto_traits` feature gate
+auto trait DummyAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy
-struct DummyStruct;
-
-auto trait AutoDummyTrait {}
-//~^ ERROR auto traits are experimental and possibly buggy
-
-impl !AutoDummyTrait for DummyStruct {}
-//~^ ERROR negative trait bounds are not fully implemented; use marker types for now
+pub unsafe auto trait AnotherAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy
fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.stderr b/tests/ui/feature-gates/feature-gate-auto-traits.stderr
index 8fa5168b2d041..d476b4fecbe58 100644
--- a/tests/ui/feature-gates/feature-gate-auto-traits.stderr
+++ b/tests/ui/feature-gates/feature-gate-auto-traits.stderr
@@ -1,21 +1,21 @@
error[E0658]: auto traits are experimental and possibly buggy
- --> $DIR/feature-gate-auto-traits.rs:6:1
+ --> $DIR/feature-gate-auto-traits.rs:1:1
|
-LL | auto trait AutoDummyTrait {}
+LL | auto trait DummyAutoTrait {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #13231 for more information
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: negative trait bounds are not fully implemented; use marker types for now
- --> $DIR/feature-gate-auto-traits.rs:9:6
+error[E0658]: auto traits are experimental and possibly buggy
+ --> $DIR/feature-gate-auto-traits.rs:3:1
|
-LL | impl !AutoDummyTrait for DummyStruct {}
- | ^^^^^^^^^^^^^^^
+LL | pub unsafe auto trait AnotherAutoTrait {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: see issue #68318 for more information
- = help: add `#![feature(negative_impls)]` to the crate attributes to enable
+ = note: see issue #13231 for more information
+ = help: add `#![feature(auto_traits)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
diff --git a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs
index 0ccbaf1e476a9..01f44df0d7621 100644
--- a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs
+++ b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs
@@ -1,6 +1,6 @@
-// For historical reasons, auto traits don't have a proper pre-expansion feature gate.
-// We're now at least issuing a *warning* for those that only exist before macro expansion.
-// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
+// For historical reasons, auto traits don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
// As part of this, move these test cases into `feature-gate-auto-traits.rs`.
//@ check-pass
diff --git a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs
index 8ab0e80e6be31..9fdaa7a0ec08c 100644
--- a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs
+++ b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs
@@ -1,6 +1,6 @@
-// For historical reasons, box patterns don't have a proper pre-expansion feature gate.
-// We're now at least issuing a *warning* for those that only exist before macro expansion.
-// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
+// For historical reasons, box patterns don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
// As part of this, move these test cases into `feature-gate-box_patterns.rs`.
//@ check-pass
diff --git a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs
index 7d2d48503797a..dbc0b940265fc 100644
--- a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs
+++ b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs
@@ -1,6 +1,6 @@
-// For historical reasons, decl macros 2.0 don't have a proper pre-expansion feature gate.
-// We're now at least issuing a *warning* for those that only exist before macro expansion.
-// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
+// For historical reasons, decl macros 2.0 don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
// As part of this, move these test cases into `feature-gate-decl_macro.rs`.
//@ check-pass
diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs
new file mode 100644
index 0000000000000..0071ce6350b16
--- /dev/null
+++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs
@@ -0,0 +1,12 @@
+// For historical reasons, negative impls don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
+// As part of this, move these test cases into `feature-gate-negative_impls.rs`.
+//@ check-pass
+
+#[cfg(false)]
+impl !Trait for () {}
+//~^ WARN negative impls are experimental
+//~| WARN unstable syntax can change at any point in the future
+
+fn main() {}
diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr
new file mode 100644
index 0000000000000..35e125cb2d24c
--- /dev/null
+++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr
@@ -0,0 +1,14 @@
+warning: negative impls are experimental
+ --> $DIR/soft-feature-gate-negative_impls.rs:8:6
+ |
+LL | impl !Trait for () {}
+ | ^
+ |
+ = note: see issue #68318 for more information
+ = help: add `#![feature(negative_impls)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs
index 553e88375a2a7..7f929f5198a70 100644
--- a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs
+++ b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs
@@ -1,6 +1,6 @@
-// For historical reasons, trait aliases don't have a proper pre-expansion feature gate.
-// We're now at least issuing a *warning* for those that only exist before macro expansion.
-// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
+// For historical reasons, trait aliases don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
// As part of this, move these test cases into `feature-gate-trait-alias.rs`.
//@ check-pass
diff --git a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs
index aa51e60d56b4a..3f439d0c26893 100644
--- a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs
+++ b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs
@@ -1,6 +1,6 @@
-// For historical reasons, try blocks don't have a proper pre-expansion feature gate.
-// We're now at least issuing a *warning* for those that only exist before macro expansion.
-// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
+// For historical reasons, try blocks don't have an erroring pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
// As part of this, move these test cases into `feature-gate-try_blocks.rs`.
//@ edition: 2018
//@ check-pass
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
index deab31c251f83..4a0532284c176 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
@@ -46,6 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope
LL | fn binder() -> impl Sized + for<'a> use<> {}
| ^^^ not found in this scope
+error[E0658]: const trait impls are experimental
+ --> $DIR/bound-modifiers.rs:12:32
+ |
+LL | fn constness() -> impl Sized + const use<> {}
+ | ^^^^^
+ |
+ = note: see issue #143874 for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
error[E0658]: `async` trait bounds are unstable
--> $DIR/bound-modifiers.rs:7:32
|
@@ -57,16 +67,6 @@ LL | fn asyncness() -> impl Sized + async use<> {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: use the desugared name of the async trait, such as `AsyncFn`
-error[E0658]: const trait impls are experimental
- --> $DIR/bound-modifiers.rs:12:32
- |
-LL | fn constness() -> impl Sized + const use<> {}
- | ^^^^^
- |
- = note: see issue #143874 for more information
- = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0405, E0658.
diff --git a/tests/ui/imports/global-derive-path.rs b/tests/ui/imports/global-derive-path.rs
new file mode 100644
index 0000000000000..5f0a6bb86bf30
--- /dev/null
+++ b/tests/ui/imports/global-derive-path.rs
@@ -0,0 +1,10 @@
+//@ edition: 2024
+//@ check-pass
+#![crate_type = "lib"]
+#![feature(derive_macro_global_path)]
+
+#[::core::derive(Clone)]
+struct Y;
+
+#[::std::derive(Clone)]
+struct X;
diff --git a/tests/ui/layout/layout-cycle.rs b/tests/ui/layout/layout-cycle.rs
index b38bd52c6ade9..846ce0882cad1 100644
--- a/tests/ui/layout/layout-cycle.rs
+++ b/tests/ui/layout/layout-cycle.rs
@@ -1,6 +1,5 @@
//@ build-fail
//~^ ERROR: cycle detected when computing layout of
-//~? ERROR: a cycle occurred during layout computation
// Issue #111176 -- ensure that we do not emit ICE on layout cycles
diff --git a/tests/ui/layout/layout-cycle.stderr b/tests/ui/layout/layout-cycle.stderr
index e05ff614567c4..28c35d431226e 100644
--- a/tests/ui/layout/layout-cycle.stderr
+++ b/tests/ui/layout/layout-cycle.stderr
@@ -6,18 +6,6 @@ note: cycle used when const-evaluating + checking `core::mem::SizedTypePropertie
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-error[E0080]: a cycle occurred during layout computation
- --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
- = note: evaluation of `> as std::mem::SizedTypeProperties>::SIZE` failed here
-
-note: the above error was encountered while instantiating `fn std::mem::size_of::>>`
- --> $DIR/layout-cycle.rs:26:5
- |
-LL | mem::size_of::>()
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr
index 7f246b3d409ad..b9b1b988499e6 100644
--- a/tests/ui/layout/post-mono-layout-cycle.stderr
+++ b/tests/ui/layout/post-mono-layout-cycle.stderr
@@ -5,12 +5,6 @@ error[E0391]: cycle detected when computing layout of `Wrapper<()>`
= note: cycle used when computing layout of `core::option::Option>`
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-note: the above error was encountered while instantiating `fn abi::<()>`
- --> $DIR/post-mono-layout-cycle.rs:19:5
- |
-LL | abi::(None);
- | ^^^^^^^^^^^^^^
-
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index af2ba7a809ad0..46f50593c4e95 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -9,12 +9,13 @@
#![feature(const_trait_impl)]
#![feature(coroutines)]
#![feature(decl_macro)]
+#![feature(macro_guard_matcher)]
#![feature(more_qualified_paths)]
#![feature(never_patterns)]
+#![feature(specialization)]
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
-#![feature(macro_guard_matcher)]
#![deny(unused_macros)]
// These macros force the use of AST pretty-printing by converting the input to
diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.rs b/tests/ui/moves/arc-consumed-in-looped-closure.rs
index 8700c78508476..6016850838d3c 100644
--- a/tests/ui/moves/arc-consumed-in-looped-closure.rs
+++ b/tests/ui/moves/arc-consumed-in-looped-closure.rs
@@ -19,7 +19,7 @@ impl ThreadPool {
}
fn main() {
- let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE move occurs because
+ let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE this move could be avoided by cloning the original `Arc`, which is inexpensive
let pool = ThreadPool {
workers: vec![],
queue: Arc::new(()),
@@ -29,6 +29,7 @@ fn main() {
// let results = Arc::clone(&results); // Forgot this.
pool.execute(move || { //~ ERROR E0382
//~^ NOTE value moved into closure here, in previous iteration of loop
+ //~| NOTE consider using `Arc::clone`
//~| HELP consider cloning the value before moving it into the closure
let mut r = results.lock().unwrap(); //~ NOTE use occurs due to use in closure
r.push(i);
diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.stderr b/tests/ui/moves/arc-consumed-in-looped-closure.stderr
index 47d6fd6cbad3b..462eb274ce5af 100644
--- a/tests/ui/moves/arc-consumed-in-looped-closure.stderr
+++ b/tests/ui/moves/arc-consumed-in-looped-closure.stderr
@@ -1,8 +1,8 @@
-error[E0382]: use of moved value: `results`
+error[E0382]: the type `Arc` does not implement `Copy`
--> $DIR/arc-consumed-in-looped-closure.rs:30:22
|
LL | let results = Arc::new(Mutex::new(Vec::new()));
- | ------- move occurs because `results` has type `Arc>>`, which does not implement the `Copy` trait
+ | ------- this move could be avoided by cloning the original `Arc`, which is inexpensive
...
LL | for i in 0..20 {
| -------------- inside of this loop
@@ -13,12 +13,14 @@ LL | pool.execute(move || {
LL | let mut r = results.lock().unwrap();
| ------- use occurs due to use in closure
|
+ = note: consider using `Arc::clone`
help: consider cloning the value before moving it into the closure
|
LL ~ let value = results.clone();
LL ~ pool.execute(move || {
LL |
LL |
+LL |
LL ~ let mut r = value.lock().unwrap();
|
diff --git a/tests/ui/moves/no-capture-arc.rs b/tests/ui/moves/no-capture-arc.rs
index 9c957a4e01b41..eea9858532d4c 100644
--- a/tests/ui/moves/no-capture-arc.rs
+++ b/tests/ui/moves/no-capture-arc.rs
@@ -9,7 +9,7 @@ fn main() {
assert_eq!((*arc_v)[3], 4);
});
- assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v`
+ assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy`
println!("{:?}", *arc_v);
}
diff --git a/tests/ui/moves/no-capture-arc.stderr b/tests/ui/moves/no-capture-arc.stderr
index 6d4a867fa88d0..e0fce32ba7fc0 100644
--- a/tests/ui/moves/no-capture-arc.stderr
+++ b/tests/ui/moves/no-capture-arc.stderr
@@ -1,8 +1,8 @@
-error[E0382]: borrow of moved value: `arc_v`
+error[E0382]: the type `Arc` does not implement `Copy`
--> $DIR/no-capture-arc.rs:12:18
|
LL | let arc_v = Arc::new(v);
- | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait
+ | ----- this move could be avoided by cloning the original `Arc`, which is inexpensive
LL |
LL | thread::spawn(move|| {
| ------ value moved into closure here
@@ -12,6 +12,7 @@ LL | assert_eq!((*arc_v)[3], 4);
LL | assert_eq!((*arc_v)[2], 3);
| ^^^^^ value borrowed here after move
|
+ = note: consider using `Arc::clone`
= note: borrow occurs due to deref coercion to `Vec`
help: consider cloning the value before moving it into the closure
|
diff --git a/tests/ui/moves/no-reuse-move-arc.fixed b/tests/ui/moves/no-reuse-move-arc.fixed
index a5dac8cc14bf2..c9094cb78a391 100644
--- a/tests/ui/moves/no-reuse-move-arc.fixed
+++ b/tests/ui/moves/no-reuse-move-arc.fixed
@@ -11,7 +11,7 @@ fn main() {
assert_eq!((*value)[3], 4);
});
- assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v`
+ assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy`
println!("{:?}", *arc_v);
}
diff --git a/tests/ui/moves/no-reuse-move-arc.rs b/tests/ui/moves/no-reuse-move-arc.rs
index 0d67aa56489ce..29452220aebcc 100644
--- a/tests/ui/moves/no-reuse-move-arc.rs
+++ b/tests/ui/moves/no-reuse-move-arc.rs
@@ -10,7 +10,7 @@ fn main() {
assert_eq!((*arc_v)[3], 4);
});
- assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v`
+ assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy`
println!("{:?}", *arc_v);
}
diff --git a/tests/ui/moves/no-reuse-move-arc.stderr b/tests/ui/moves/no-reuse-move-arc.stderr
index aff979af905e4..8f56b32f96a89 100644
--- a/tests/ui/moves/no-reuse-move-arc.stderr
+++ b/tests/ui/moves/no-reuse-move-arc.stderr
@@ -1,8 +1,8 @@
-error[E0382]: borrow of moved value: `arc_v`
+error[E0382]: the type `Arc` does not implement `Copy`
--> $DIR/no-reuse-move-arc.rs:13:18
|
LL | let arc_v = Arc::new(v);
- | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait
+ | ----- this move could be avoided by cloning the original `Arc`, which is inexpensive
LL |
LL | thread::spawn(move|| {
| ------ value moved into closure here
@@ -12,6 +12,7 @@ LL | assert_eq!((*arc_v)[3], 4);
LL | assert_eq!((*arc_v)[2], 3);
| ^^^^^ value borrowed here after move
|
+ = note: consider using `Arc::clone`
= note: borrow occurs due to deref coercion to `Vec`
help: consider cloning the value before moving it into the closure
|
diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs
index 164d0b13b539c..e8452fcbd5f99 100644
--- a/tests/ui/parser/trait-item-with-defaultness-pass.rs
+++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs
@@ -1,4 +1,5 @@
//@ check-pass
+#![feature(specialization)]
fn main() {}
diff --git a/tests/ui/scalable-vectors/cast-intrinsic.rs b/tests/ui/scalable-vectors/cast-intrinsic.rs
new file mode 100644
index 0000000000000..f2157d8bcc14b
--- /dev/null
+++ b/tests/ui/scalable-vectors/cast-intrinsic.rs
@@ -0,0 +1,65 @@
+//@ check-pass
+//@ only-aarch64
+#![crate_type = "lib"]
+#![allow(incomplete_features, internal_features, improper_ctypes)]
+#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)]
+
+use std::intrinsics::simd::scalable::sve_cast;
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector(16)]
+#[allow(non_camel_case_types)]
+pub struct svbool_t(bool);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+pub struct svbool2_t(bool);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+pub struct svint64_t(i64);
+
+#[derive(Copy, Clone)]
+#[rustc_scalable_vector(2)]
+#[allow(non_camel_case_types)]
+pub struct nxv2i16(i16);
+
+pub trait SveInto: Sized {
+ unsafe fn sve_into(self) -> T;
+}
+
+impl SveInto for svbool_t {
+ #[target_feature(enable = "sve")]
+ unsafe fn sve_into(self) -> svbool2_t {
+ unsafe extern "C" {
+ #[cfg_attr(
+ target_arch = "aarch64",
+ link_name = concat!("llvm.aarch64.sve.convert.from.svbool.nxv2i1")
+ )]
+ fn convert_from_svbool(b: svbool_t) -> svbool2_t;
+ }
+ unsafe { convert_from_svbool(self) }
+ }
+}
+
+#[target_feature(enable = "sve")]
+pub unsafe fn svld1sh_gather_s64offset_s64(
+ pg: svbool_t,
+ base: *const i16,
+ offsets: svint64_t,
+) -> svint64_t {
+ unsafe extern "unadjusted" {
+ #[cfg_attr(
+ target_arch = "aarch64",
+ link_name = "llvm.aarch64.sve.ld1.gather.nxv2i16"
+ )]
+ fn _svld1sh_gather_s64offset_s64(
+ pg: svbool2_t,
+ base: *const i16,
+ offsets: svint64_t,
+ ) -> nxv2i16;
+ }
+ sve_cast(_svld1sh_gather_s64offset_s64(pg.sve_into(), base, offsets))
+}
diff --git a/tests/ui/simd/masked-load-store-check-fail.stderr b/tests/ui/simd/masked-load-store-check-fail.stderr
index 4e63d04a3b158..037855c8ec9ca 100644
--- a/tests/ui/simd/masked-load-store-check-fail.stderr
+++ b/tests/ui/simd/masked-load-store-check-fail.stderr
@@ -21,7 +21,7 @@ LL | | Simd::([9; 4]),
LL | | );
| |_________^
note: function defined here
- --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL
+ --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL
error[E0308]: mismatched types
--> $DIR/masked-load-store-check-fail.rs:25:13
@@ -46,7 +46,7 @@ LL | | default,
LL | | );
| |_________^
note: function defined here
- --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL
+ --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL
error: aborting due to 2 previous errors
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
deleted file mode 100644
index d097b809b5698..0000000000000
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0391]: cycle detected when computing layout of `Foo`
- |
- = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`...
- = note: ...which again requires computing layout of `Foo`, completing the cycle
-note: cycle used when const-evaluating + checking `_`
- --> $DIR/stack-overflow-trait-infer-98842.rs:14:1
- |
-LL | const _: *const Foo = 0 as _;
- | ^^^^^^^^^^^^^^^^^^^
- = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0080]: a cycle occurred during layout computation
- --> $DIR/stack-overflow-trait-infer-98842.rs:14:1
- |
-LL | const _: *const Foo = 0 as _;
- | ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
index 1c9f6c593f447..d6522e3cfb643 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
@@ -2,8 +2,7 @@
// issue: rust-lang/rust#98842
//@ check-fail
//@ edition:2021
-//@ stderr-per-bitwidth
-//~^^^^^ ERROR cycle detected when computing layout of `Foo`
+//~^^^^ ERROR cycle detected when computing layout of `Foo`
// If the inner `Foo` is named through an associated type,
// the "infinite size" error does not occur.
@@ -12,6 +11,5 @@ struct Foo(<&'static Foo as ::core::ops::Deref>::Target);
// and it will infinitely recurse somewhere trying to figure out the
// size of this pointer (is my guess):
const _: *const Foo = 0 as _;
-//~^ ERROR a cycle occurred during layout computation
pub fn main() {}
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
similarity index 55%
rename from tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
rename to tests/ui/sized/stack-overflow-trait-infer-98842.stderr
index d097b809b5698..5557a6fc45b89 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
@@ -3,19 +3,12 @@ error[E0391]: cycle detected when computing layout of `Foo`
= note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`...
= note: ...which again requires computing layout of `Foo`, completing the cycle
note: cycle used when const-evaluating + checking `_`
- --> $DIR/stack-overflow-trait-infer-98842.rs:14:1
+ --> $DIR/stack-overflow-trait-infer-98842.rs:13:1
|
LL | const _: *const Foo = 0 as _;
| ^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-error[E0080]: a cycle occurred during layout computation
- --> $DIR/stack-overflow-trait-infer-98842.rs:14:1
- |
-LL | const _: *const Foo = 0 as _;
- | ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/specialization/feature-gate-specialization.rs b/tests/ui/specialization/feature-gate-specialization.rs
new file mode 100644
index 0000000000000..82e467ad98d32
--- /dev/null
+++ b/tests/ui/specialization/feature-gate-specialization.rs
@@ -0,0 +1,21 @@
+trait Trait {
+ type Ty;
+ const CT: ();
+ fn fn_(&self);
+}
+
+impl Trait for T {
+ default type Ty = (); //~ ERROR specialization is experimental
+ default const CT: () = (); //~ ERROR specialization is experimental
+ default fn fn_(&self) {} //~ ERROR specialization is experimental
+}
+
+trait OtherTrait {
+ fn fn_();
+}
+
+default impl OtherTrait for T { //~ ERROR specialization is experimental
+ fn fn_() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/feature-gate-specialization.stderr b/tests/ui/specialization/feature-gate-specialization.stderr
new file mode 100644
index 0000000000000..2efc0faa7c23e
--- /dev/null
+++ b/tests/ui/specialization/feature-gate-specialization.stderr
@@ -0,0 +1,45 @@
+error[E0658]: specialization is experimental
+ --> $DIR/feature-gate-specialization.rs:8:5
+ |
+LL | default type Ty = ();
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: specialization is experimental
+ --> $DIR/feature-gate-specialization.rs:9:5
+ |
+LL | default const CT: () = ();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: specialization is experimental
+ --> $DIR/feature-gate-specialization.rs:10:5
+ |
+LL | default fn fn_(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: specialization is experimental
+ --> $DIR/feature-gate-specialization.rs:17:1
+ |
+LL | / default impl OtherTrait for T {
+LL | | fn fn_() {}
+LL | | }
+ | |_^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/specialization/soft-feature-gate-specialization.default.stderr b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr
new file mode 100644
index 0000000000000..f5961090947ed
--- /dev/null
+++ b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr
@@ -0,0 +1,62 @@
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:21:5
+ |
+LL | default type Ty = ();
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:24:5
+ |
+LL | default const CT: () = ();
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:40:1
+ |
+LL | default impl Trait for () {}
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:27:5
+ |
+LL | default fn fn_();
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:35:1
+ |
+LL | default fn fn_() {}
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: 5 warnings emitted
+
diff --git a/tests/ui/specialization/soft-feature-gate-specialization.min.stderr b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr
new file mode 100644
index 0000000000000..aa4ce0cc58be2
--- /dev/null
+++ b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr
@@ -0,0 +1,38 @@
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:21:5
+ |
+LL | default type Ty = ();
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:24:5
+ |
+LL | default const CT: () = ();
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: specialization is experimental
+ --> $DIR/soft-feature-gate-specialization.rs:40:1
+ |
+LL | default impl Trait for () {}
+ | ^^^^^^^
+ |
+ = note: see issue #31844 for more information
+ = help: add `#![feature(specialization)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = warning: unstable syntax can change at any point in the future, causing a hard error!
+ = note: for more information, see issue #65860
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/specialization/soft-feature-gate-specialization.rs b/tests/ui/specialization/soft-feature-gate-specialization.rs
new file mode 100644
index 0000000000000..46e4b28e61d23
--- /dev/null
+++ b/tests/ui/specialization/soft-feature-gate-specialization.rs
@@ -0,0 +1,44 @@
+// For historical reasons, item modifier `default` doesn't have a proper pre-expansion feature gate.
+// We're now at least issuing a warning for those that only exist before macro expansion.
+// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
+// As part of this, move these test cases into `feature-gate-specialization.rs`.
+//
+// Moreover, `specialization` implies `min_specialization` similar to the post-expansion gate.
+//
+// However, while we only gate `default` *associated* functions only behind `min_specialization` OR
+// `specialization` in the post-expansion case, in the pre-expansion case we gate all kinds of
+// functions (free, assoc, foreign) behind `min_specialization` OR `specialization` if marked with
+// `default` for simplicity of implementation. Ultimately it doesn't matter since we later reject
+// `default` on anything other than impls & impl assoc items during semantic analysis.
+//
+//@ revisions: default min full
+//@ check-pass
+#![cfg_attr(min, feature(min_specialization))]
+#![cfg_attr(full, feature(specialization))]
+
+#[cfg(false)]
+impl Trait for () {
+ default type Ty = ();
+ //[default,min]~^ WARN specialization is experimental
+ //[default,min]~| WARN unstable syntax can change at any point in the future
+ default const CT: () = ();
+ //[default,min]~^ WARN specialization is experimental
+ //[default,min]~| WARN unstable syntax can change at any point in the future
+ default fn fn_();
+ //[default]~^ WARN specialization is experimental
+ //[default]~| WARN unstable syntax can change at any point in the future
+}
+
+// While free ty/ct/fn items marked `default` are
+// semantically malformed we still need to gate the keyword!
+#[cfg(false)]
+default fn fn_() {}
+//[default]~^ WARN specialization is experimental
+//[default]~| WARN unstable syntax can change at any point in the future
+
+#[cfg(false)]
+default impl Trait for () {}
+//[default,min]~^ WARN specialization is experimental
+//[default,min]~| WARN unstable syntax can change at any point in the future
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs
deleted file mode 100644
index 8bad3ac0a1fb3..0000000000000
--- a/tests/ui/specialization/specialization-feature-gate-default.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Check that specialization must be ungated to use the `default` keyword
-
-// gate-test-specialization
-
-trait Foo {
- fn foo(&self);
-}
-
-impl Foo for T {
- default fn foo(&self) {} //~ ERROR specialization is unstable
-}
-
-fn main() {}
diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr
deleted file mode 100644
index 3e651b6ee4f37..0000000000000
--- a/tests/ui/specialization/specialization-feature-gate-default.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: specialization is unstable
- --> $DIR/specialization-feature-gate-default.rs:10:5
- |
-LL | default fn foo(&self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #31844 for more information
- = help: add `#![feature(specialization)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs
index aa75c5691e5f9..38d34f46270a4 100644
--- a/tests/ui/track-diagnostics/track6.rs
+++ b/tests/ui/track-diagnostics/track6.rs
@@ -12,7 +12,7 @@ pub trait Foo {
impl Foo for T {
default fn bar() {}
- //~^ ERROR specialization is unstable
+ //~^ ERROR specialization is experimental
//~| NOTE created at
}
diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr
index a61f7855e3231..30d518a69cadd 100644
--- a/tests/ui/track-diagnostics/track6.stderr
+++ b/tests/ui/track-diagnostics/track6.stderr
@@ -1,4 +1,4 @@
-error[E0658]: specialization is unstable
+error[E0658]: specialization is experimental
--> $DIR/track6.rs:LL:CC
|
LL | default fn bar() {}
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
index 8d3f6ff6d78c7..1b3c5abe10918 100644
--- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
@@ -1,3 +1,5 @@
trait MyTrait {}
-impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not fully implemented
+
+impl !MyTrait for u32 {} //~ ERROR negative impls are experimental
+
fn main() {}
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
index 1777dfcc993f1..36bc5bb4be2bc 100644
--- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
@@ -1,5 +1,5 @@
-error[E0658]: negative trait bounds are not fully implemented; use marker types for now
- --> $DIR/feature-gate-negative_impls.rs:2:6
+error[E0658]: negative impls are experimental
+ --> $DIR/feature-gate-negative_impls.rs:3:6
|
LL | impl !MyTrait for u32 {}
| ^^^^^^^^
@@ -7,6 +7,7 @@ LL | impl !MyTrait for u32 {}
= note: see issue #68318 for more information
= help: add `#![feature(negative_impls)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = help: use marker types for now
error: aborting due to 1 previous error
diff --git a/tests/ui/unsized/thin-ptr-to-unsized-projection.rs b/tests/ui/unsized/thin-ptr-to-unsized-projection.rs
new file mode 100644
index 0000000000000..79918e6a0722d
--- /dev/null
+++ b/tests/ui/unsized/thin-ptr-to-unsized-projection.rs
@@ -0,0 +1,6 @@
+// This is a regression test for
+struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
+ //~^ ERROR: missing lifetime specifier [E0106]
+const _: *const Foo = 0 as _;
+ //~^ ERROR: cannot cast `i32` to a pointer that is wide [E0606]
+fn main() {}
diff --git a/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr b/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr
new file mode 100644
index 0000000000000..256523c4a47ec
--- /dev/null
+++ b/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr
@@ -0,0 +1,23 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/thin-ptr-to-unsized-projection.rs:2:17
+ |
+LL | struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
+ | ^ expected named lifetime parameter
+ |
+help: consider using the `'a` lifetime
+ |
+LL | struct Foo<'a>(<&'a /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
+ | ++
+
+error[E0606]: cannot cast `i32` to a pointer that is wide
+ --> $DIR/thin-ptr-to-unsized-projection.rs:4:28
+ |
+LL | const _: *const Foo = 0 as _;
+ | - ^ creating a `*const Foo<'_>` requires both an address and a length
+ | |
+ | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0606.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/triagebot.toml b/triagebot.toml
index f99d700310dfe..719fe2a75c82b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1077,7 +1077,7 @@ cc = ["@Amanieu", "@folkertdev", "@sayantn"]
message = "Some changes occurred in `std_detect`"
cc = ["@Amanieu", "@folkertdev", "@sayantn"]
-[mentions."library/core/src/intrinsics/simd.rs"]
+[mentions."library/core/src/intrinsics/simd/mod.rs"]
message = """
Some changes occurred to the platform-builtins intrinsics. Make sure the
LLVM backend as well as portable-simd gets adapted for the changes.