diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index c272d2685cfa8..2f18b2f56a5f4 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -10,9 +10,9 @@ use rustc_index::bit_set::BitMatrix; use tracing::{debug, trace}; use crate::{ - AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, - IndexVec, Integer, LayoutData, Niche, NicheOptimizations, NumScalableVectors, Primitive, - ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, + Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, + Integer, LayoutData, Niche, NicheOptimizations, NumScalableVectors, Primitive, ReprOptions, + Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange, }; @@ -197,7 +197,7 @@ impl LayoutCalculator { align: element.align, size, max_repr_align: None, - unadjusted_abi_align: element.align.abi, + unadjusted_abi_align: element.align, repr_c: element.repr_c, randomization_seed: element.randomization_seed.wrapping_add(Hash64::new(count)), }) @@ -426,7 +426,7 @@ impl LayoutCalculator { return Err(LayoutCalculatorError::UnexpectedUnsized(*field)); } - align = align.max(field.align.abi); + align = align.max(field.align); max_repr_align = max_repr_align.max(field.max_repr_align); size = cmp::max(size, field.size); @@ -448,14 +448,14 @@ impl LayoutCalculator { // have the same alignment if !matches!(common_abi, BackendRepr::Memory { .. }) { assert_eq!( - common_align, field.align.abi, + common_align, field.align, "non-Aggregate field with matching ABI but differing alignment" ); } } } else { // First non-ZST field: record its ABI and alignment - common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi))); + common_non_zst_repr_and_align = Ok(Some((field_abi, field.align))); } } } @@ -517,7 +517,7 @@ impl LayoutCalculator { backend_repr, largest_niche: None, uninhabited: false, - align: AbiAlign::new(align), + align, size: size.align_to(align), max_repr_align, unadjusted_abi_align, @@ -622,9 +622,9 @@ impl LayoutCalculator { .map(|v| { let st = self.layout_of_univariant(v, repr, StructKind::AlwaysSized).ok()?; - variants_info.push(VariantLayoutInfo { align_abi: st.align.abi }); + variants_info.push(VariantLayoutInfo { align_abi: st.align }); - align = align.max(st.align.abi); + align = align.max(st.align); max_repr_align = max_repr_align.max(st.max_repr_align); unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); combined_seed = combined_seed.wrapping_add(st.randomization_seed); @@ -750,7 +750,7 @@ impl LayoutCalculator { largest_niche, uninhabited, size, - align: AbiAlign::new(align), + align, max_repr_align, unadjusted_abi_align, repr_c: repr.c(), @@ -814,7 +814,7 @@ impl LayoutCalculator { if repr.c() { for fields in variants { for field in fields { - prefix_align = prefix_align.max(field.align.abi); + prefix_align = prefix_align.max(field.align); } } } @@ -833,12 +833,12 @@ impl LayoutCalculator { for field_idx in st.fields.index_by_increasing_offset() { let field = &field_layouts[FieldIdx::new(field_idx)]; if !field.is_1zst() { - start_align = start_align.min(field.align.abi); + start_align = start_align.min(field.align); break; } } size = cmp::max(size, st.size); - align = align.max(st.align.abi); + align = align.max(st.align); max_repr_align = max_repr_align.max(st.max_repr_align); unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); combined_seed = combined_seed.wrapping_add(st.randomization_seed); @@ -1016,7 +1016,7 @@ impl LayoutCalculator { }; if pair_offsets[FieldIdx::new(0)] == Size::ZERO && pair_offsets[FieldIdx::new(1)] == *offset - && align == pair.align.abi + && align == pair.align && size == pair.size { // We can use `ScalarPair` only when it matches our @@ -1058,7 +1058,7 @@ impl LayoutCalculator { largest_niche, uninhabited, backend_repr: abi, - align: AbiAlign::new(align), + align, size, max_repr_align, unadjusted_abi_align, @@ -1157,7 +1157,7 @@ impl LayoutCalculator { // `alignment_group_key`, one or the other branch will be taken, so this is okay. if let Some(pack) = pack { // Return the packed alignment in bytes. - layout.align.abi.min(pack).bytes() + layout.align.min(pack).bytes() } else { // Returns `log2(effective-align)`. The calculation assumes that size is an // integer multiple of align, except for ZSTs. @@ -1276,13 +1276,10 @@ impl LayoutCalculator { } // Invariant: offset < dl.obj_size_bound() <= 1<<61 - let field_align = if let Some(pack) = pack { - field.align.min(AbiAlign::new(pack)) - } else { - field.align - }; - offset = offset.align_to(field_align.abi); - align = align.max(field_align.abi); + let field_align = + if let Some(pack) = pack { field.align.min(pack) } else { field.align }; + offset = offset.align_to(field_align); + align = align.max(field_align); max_repr_align = max_repr_align.max(field.max_repr_align); debug!("univariant offset: {:?} field: {:#?}", offset, field); @@ -1341,7 +1338,7 @@ impl LayoutCalculator { layout_of_single_non_zst_field = Some(field); // Field fills the struct and it has a scalar or scalar pair ABI. - if offsets[i].bytes() == 0 && align == field.align.abi && size == field.size { + if offsets[i].bytes() == 0 && align == field.align && size == field.size { match field.backend_repr { // For plain scalars, or vectors of them, we can't unpack // newtypes for `#[repr(C)]`, as that affects C ABIs. @@ -1388,7 +1385,7 @@ impl LayoutCalculator { }; if offsets[i] == pair_offsets[FieldIdx::new(0)] && offsets[j] == pair_offsets[FieldIdx::new(1)] - && align == pair.align.abi + && align == pair.align && size == pair.size { // We can use `ScalarPair` only when it matches our @@ -1428,7 +1425,7 @@ impl LayoutCalculator { backend_repr: abi, largest_niche, uninhabited, - align: AbiAlign::new(align), + align, size, max_repr_align, unadjusted_abi_align, @@ -1528,9 +1525,9 @@ where largest_niche: elt.largest_niche, uninhabited: false, size, - align: AbiAlign::new(align), + align, max_repr_align: None, - unadjusted_abi_align: elt.align.abi, + unadjusted_abi_align: elt.align, repr_c: false, randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count.as_u64())), }) diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs index 66119ac2f0b5a..bc301869f5ce9 100644 --- a/compiler/rustc_abi/src/layout/coroutine.rs +++ b/compiler/rustc_abi/src/layout/coroutine.rs @@ -231,7 +231,7 @@ where let mut variant = calc.layout_of_univariant( &variant_only_tys.collect::>(), &ReprOptions::default(), - StructKind::Prefixed(prefix_size, prefix_align.abi), + StructKind::Prefixed(prefix_size, prefix_align), )?; let FieldsShape::Arbitrary { offsets, in_memory_order } = variant.fields else { @@ -287,7 +287,7 @@ where }) .collect::, _>>()?; - size = size.align_to(align.abi); + size = size.align_to(align); let uninhabited = prefix.uninhabited || variants.iter().all(|v| v.is_uninhabited()); let abi = BackendRepr::Memory { sized: true }; @@ -312,7 +312,7 @@ where size, align, max_repr_align: None, - unadjusted_abi_align: align.abi, + unadjusted_abi_align: align, repr_c: false, randomization_seed: Default::default(), }) diff --git a/compiler/rustc_abi/src/layout/simple.rs b/compiler/rustc_abi/src/layout/simple.rs index a4636ea1b116f..f16daccc3c526 100644 --- a/compiler/rustc_abi/src/layout/simple.rs +++ b/compiler/rustc_abi/src/layout/simple.rs @@ -4,8 +4,7 @@ use rustc_hashes::Hash64; use rustc_index::{Idx, IndexVec}; use crate::{ - AbiAlign, BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size, - Variants, + BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size, Variants, }; /// "Simple" layout constructors that cannot fail. @@ -21,7 +20,7 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized }, largest_niche: None, uninhabited: false, - align: AbiAlign::new(dl.i8_align), + align: dl.i8_align, size: Size::ZERO, max_repr_align: None, unadjusted_abi_align: dl.i8_align, @@ -39,7 +38,7 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, uninhabited: true, - align: AbiAlign::new(dl.i8_align), + align: dl.i8_align, size: Size::ZERO, max_repr_align: None, unadjusted_abi_align: dl.i8_align, @@ -83,7 +82,7 @@ impl LayoutData { largest_niche, uninhabited: false, size, - align: AbiAlign::new(align), + align, max_repr_align: None, unadjusted_abi_align: align, repr_c: false, @@ -116,7 +115,7 @@ impl LayoutData { backend_repr: BackendRepr::ScalarPair { a, b, b_offset }, largest_niche, uninhabited: false, - align: AbiAlign::new(align), + align, size, max_repr_align: None, unadjusted_abi_align: align, @@ -143,7 +142,7 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, uninhabited: true, - align: AbiAlign::new(dl.i8_align), + align: dl.i8_align, size: Size::ZERO, max_repr_align: None, unadjusted_abi_align: dl.i8_align, diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 821fa54e29fa7..64bc32ad7584a 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -49,7 +49,7 @@ impl<'a> Layout<'a> { } pub fn align(self) -> Align { - self.0.0.align.abi + self.0.0.align } pub fn size(self) -> Size { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index c6879dd11ac99..8e9f24e0feb82 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -41,7 +41,7 @@ use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; use std::num::{NonZero, ParseIntError}; -use std::ops::{Add, AddAssign, Deref, Mul, Sub}; +use std::ops::{Add, AddAssign, Mul, Sub}; use std::range::RangeInclusive; use std::str::FromStr; @@ -1216,52 +1216,6 @@ impl Align { } } -/// A pair of alignments, ABI-mandated and preferred. -/// -/// The "preferred" alignment is an LLVM concept that is virtually meaningless to Rust code: -/// it is not exposed semantically to programmers nor can they meaningfully affect it. -/// The only concern for us is that preferred alignment must not be less than the mandated alignment -/// and thus in practice the two values are almost always identical. -/// -/// An example of a rare thing actually affected by preferred alignment is aligning of statics. -/// It is of effectively no consequence for layout in structs and on the stack. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "nightly", derive(StableHash))] -pub struct AbiAlign { - pub abi: Align, -} - -impl fmt::Debug for AbiAlign { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.abi, f) - } -} - -impl AbiAlign { - #[inline] - pub fn new(align: Align) -> AbiAlign { - AbiAlign { abi: align } - } - - #[inline] - pub fn min(self, other: AbiAlign) -> AbiAlign { - AbiAlign { abi: self.abi.min(other.abi) } - } - - #[inline] - pub fn max(self, other: AbiAlign) -> AbiAlign { - AbiAlign { abi: self.abi.max(other.abi) } - } -} - -impl Deref for AbiAlign { - type Target = Align; - - fn deref(&self) -> &Self::Target { - &self.abi - } -} - /// Integers, also used for enum discriminants. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash))] @@ -2267,7 +2221,7 @@ pub struct LayoutData { /// especially in the case of by-pointer struct returns, which allocate stack even when unused. pub uninhabited: bool, - pub align: AbiAlign, + pub align: Align, pub size: Size, /// The largest alignment explicitly requested with `repr(align)` on this type or any field. diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5ccf0eaf02bd4..b5d8614804812 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1779,7 +1779,7 @@ pub enum ExprKind { Lit(token::Lit), /// A cast (e.g., `foo as f64`). Cast(Box, Box), - /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`). + /// A type ascription (e.g., `k#type_ascribe(42, usize)`). /// /// Usually not written directly in user code but /// indirectly via the macro `type_ascribe!(...)`. @@ -1871,7 +1871,7 @@ pub enum ExprKind { /// Output of the `asm!()` macro. InlineAsm(Box), - /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`). + /// An `offset_of` expression (e.g., `k#offset_of(Struct, field)`). /// /// Usually not written directly in user code but /// indirectly via the macro `core::mem::offset_of!(...)`. @@ -2570,7 +2570,7 @@ pub enum TyKind { /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero`, /// just as part of the type system. Pat(Box, Box), - /// A `field_of` expression (e.g., `builtin # field_of(Struct, field)`). + /// A `field_of` expression (e.g., `k#field_of(Struct, field)`). /// /// Usually not written directly in user code but indirectly via the macro /// `core::field::field_of!(...)`. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 20079dd039f6f..4ec5fe2a8bd84 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -313,6 +313,8 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `expr` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); // FIXME: Remove `box` from this list given we officially no longer support box expressions @@ -350,6 +352,8 @@ fn ident_can_begin_type(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `ty` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); !ident_token.is_reserved_ident() @@ -936,6 +940,10 @@ impl Token { self.non_raw_ident().is_some_and(|id| id.name == kw) } + pub fn is_forced_keyword(&self, kw: Symbol) -> bool { + self.ident().is_some_and(|(id, kind)| kind == IdentKind::ForcedKeyword && id.name == kw) + } + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this /// token is an identifier equal to `kw` ignoring the case. pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index bc0604cf96e95..862d4736ca33c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -431,7 +431,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { // 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"); @@ -452,6 +451,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { 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!(internal_syntax, "this syntax is internal"); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(move_expr, "`move(expr)` syntax is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a082300bb47ed..a5dbaf81376c1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1442,7 +1442,7 @@ impl<'a> State<'a> { self.print_ty_pat(pat); } ast::TyKind::FieldOf(ty, variant, field) => { - self.word("builtin # field_of"); + self.word("k#field_of"); self.popen(); let ib = self.ibox(0); self.print_type(ty); @@ -2012,6 +2012,11 @@ impl<'a> State<'a> { self.pclose(); } PatKind::Deref(inner) => { + // FIXME(deref_patterns, internal_syntax, forced_keywords, clippy): + // This should render `k#deref(...)` but unfortunately Clippy uses `pat_to_string` + // for the suggestions of its lint `unnested_or_patterns`. Smh fix Clippy to not + // rely on AST pretty printing `deref!(…)` for `Deref` patterns and please don't + // think about adding a flag to AST pretty to control the output. self.word("deref!"); self.popen(); self.print_pat(inner); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index d6e8f69dbfa03..51e3988577827 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -497,7 +497,7 @@ impl<'a> State<'a> { self.print_type(ty); } ast::ExprKind::Type(expr, ty) => { - self.word("builtin # type_ascribe"); + self.word("k#type_ascribe"); self.popen(); let ib = self.ibox(0); self.print_expr(expr, FixupContext::default()); @@ -777,12 +777,12 @@ impl<'a> State<'a> { self.print_expr(result, fixup.rightmost_subexpression()); } ast::ExprKind::InlineAsm(a) => { - // FIXME: Print `builtin # asm` once macro `asm` uses `builtin_syntax`. + // FIXME: Print `k#asm` once macro `asm` uses `internal_syntax`. self.word(format!("{}!", a.asm_macro.macro_name())); self.print_inline_asm(a); } ast::ExprKind::FormatArgs(fmt) => { - // FIXME: Print `builtin # format_args` once macro `format_args` uses `builtin_syntax`. + // FIXME: Print `k#format_args` once macro `format_args` uses `internal_syntax`. self.word("format_args!"); self.popen(); let ib = self.ibox(0); @@ -795,7 +795,7 @@ impl<'a> State<'a> { self.pclose(); } ast::ExprKind::OffsetOf(container, fields) => { - self.word("builtin # offset_of"); + self.word("k#offset_of"); self.popen(); let ib = self.ibox(0); self.print_type(container); @@ -855,10 +855,9 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs, cb, ib) } ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => { - self.word("builtin # "); match kind { - ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"), - ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"), + ast::UnsafeBinderCastKind::Wrap => self.word("k#wrap_binder"), + ast::UnsafeBinderCastKind::Unwrap => self.word("k#unwrap_binder"), } self.popen(); let ib = self.ibox(0); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6ce34cecc7e97..84d620b9b5250 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -288,7 +288,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty, cb); } ast::ItemKind::GlobalAsm(asm) => { - // FIXME: Print `builtin # global_asm` once macro `global_asm` uses `builtin_syntax`. + // FIXME: Print `k#global_asm` once macro `global_asm` uses `internal_syntax`. let (cb, ib) = self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); self.word(";"); diff --git a/compiler/rustc_attr_ir/src/lang_items.rs b/compiler/rustc_attr_ir/src/lang_items.rs index d715a6d3af8c5..56fb1a4b6c865 100644 --- a/compiler/rustc_attr_ir/src/lang_items.rs +++ b/compiler/rustc_attr_ir/src/lang_items.rs @@ -163,7 +163,7 @@ language_item_table! { Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); AlignOf, sym::mem_align_const, align_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); SizeOf, sym::mem_size_const, size_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); - OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1); + OffsetOf, kw::OffsetOf, offset_of, Target::Fn, GenericRequirement::Exact(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); @@ -239,7 +239,7 @@ language_item_table! { Complex, sym::complex, complex, Target::Struct, GenericRequirement::Exact(1); PpcF128, sym::ppcf128, ppcf128, Target::Struct, GenericRequirement::None; - Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); + Deref, kw::Deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy(AssocCtxt::Trait), GenericRequirement::None; diff --git a/compiler/rustc_attr_parsing/src/attributes/lint.rs b/compiler/rustc_attr_parsing/src/attributes/lint.rs index e0607c49124d9..938de1a8597ab 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint.rs @@ -8,6 +8,7 @@ use thin_vec::ThinVec; use crate::attributes::{AcceptMapping, AttributeParser, AttributeStability}; use crate::context::{AcceptContext, ExpectStringLiteral, FinalizeContext}; +use crate::diagnostics::{MalformedLintAttributeInput, MalformedLintAttributeInputHelp}; use crate::parser::{ArgParser, MetaItemOrLitParser}; use crate::target_checking::AllowedTargets; use crate::target_checking::Policy::{Allow, Warn}; @@ -36,9 +37,11 @@ impl LintParser { let p = parsers.last()?.meta_item()?; let nv = p.args().as_name_value()?; if !p.path().word_is(sym::reason) { - cx.emit_err(diagnostics::MalformedAttribute { + // FIXME: We should recommend `reason` here + cx.emit_err(MalformedLintAttributeInput { span: p.span(), - kind: diagnostics::MalformedAttributeKind::BadAttributeArgument(p.span()), + help: MalformedLintAttributeInputHelp::Other { kind: kind.sym() }, + kind: kind.sym(), }); } else { parsers = &parsers[..(parsers.len() - 1)]; @@ -78,26 +81,28 @@ impl LintParser { nv.expect_string_literal(cx); } ArgParser::NameValue(_) | ArgParser::List(_) => { - cx.emit_err(diagnostics::MalformedAttribute { + cx.emit_err(MalformedLintAttributeInput { span: p.span(), - kind: diagnostics::MalformedAttributeKind::BadAttributeArgument( - item.span(), - ), + help: MalformedLintAttributeInputHelp::Other { + kind: kind.sym(), + }, + kind: kind.sym(), }); } } } MetaItemOrLitParser::Lit(lit) => { - cx.emit_err(diagnostics::BadAttributeLit { + cx.emit_err(MalformedLintAttributeInput { span: item.span(), help: if lit.kind.is_str() { - diagnostics::BadAttributeLitHelp::StrLit { + MalformedLintAttributeInputHelp::StrLit { sym: lit.symbol, kind: kind.sym(), } } else { - diagnostics::BadAttributeLitHelp::Other { kind: kind.sym() } + MalformedLintAttributeInputHelp::Other { kind: kind.sym() } }, + kind: kind.sym(), }); } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 127b0e4f14de8..d33c52fb061c8 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -2196,24 +2196,23 @@ pub(crate) struct MalformedAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedAttributeKind { - #[label("bad attribute argument")] - BadAttributeArgument(#[primary_span] Span), #[label("reason in lint attribute must come last")] ReasonMustComeLast(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag("expected a lint, found literal")] -pub(crate) struct BadAttributeLit { +#[diag("malformed `{$kind}` attribute input")] +pub(crate) struct MalformedLintAttributeInput { #[primary_span] #[label("not the name of a lint")] pub span: Span, + pub kind: Symbol, #[subdiagnostic] - pub help: BadAttributeLitHelp, + pub help: MalformedLintAttributeInputHelp, } #[derive(Subdiagnostic)] -pub(crate) enum BadAttributeLitHelp { +pub(crate) enum MalformedLintAttributeInputHelp { #[help("try using `#[{$kind}({$sym})]`")] StrLit { sym: Symbol, kind: Symbol }, #[help("for example, write `#[{$kind}(dead_code)]` for `dead_code`")] diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index a83592248a512..5df3bd2015af9 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -330,7 +330,7 @@ pub(super) fn cvalue_for_param<'tcx>( PassMode::Indirect { attrs, address_space: _, mode: _ } => { assert_eq!(block_params.len(), 1, "{:?}", block_params); if let Some(pointee_align) = attrs.pointee_align - && pointee_align < arg_abi.layout.align.abi + && pointee_align < arg_abi.layout.align && arg_abi.layout.is_sized() && arg_abi.layout.size != Size::ZERO { diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 5fc02a19c0094..8a8fa47d67b59 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -291,7 +291,6 @@ fn data_id_for_static( .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .unwrap() .align - .abi .bytes(); let linkage = if import_linkage == rustc_attr_ir::Linkage::ExternalWeak diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index a4af73cbc3f20..d8841a7e3d8cb 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -96,7 +96,7 @@ impl<'tcx> CValue<'tcx> { /// The ZST is represented by a dangling pointer of suitable alignment. pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> { assert!(layout.is_zst()); - CValue::by_ref(crate::Pointer::dangling(layout.align.abi), layout) + CValue::by_ref(crate::Pointer::dangling(layout.align), layout) } pub(crate) fn layout(&self) -> TyAndLayout<'tcx> { @@ -372,7 +372,7 @@ impl<'tcx> CPlace<'tcx> { assert!(layout.is_sized()); if layout.size.bytes() == 0 { return CPlace { - inner: CPlaceInner::Addr(Pointer::dangling(layout.align.abi), None), + inner: CPlaceInner::Addr(Pointer::dangling(layout.align), None), layout, }; } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 9cc8cd43c483a..999fa3edacaa4 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1013,7 +1013,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn alloca_with_ty(&mut self, ty: TyAndLayout<'tcx>) -> RValue<'gcc> { - self.alloca(ty.layout.size, ty.layout.align.abi) + self.alloca(ty.layout.size, ty.layout.align) } fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index fc9292ea5e815..f6b6793fb77c9 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -264,8 +264,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { int128_align: tcx .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.i128)) .expect("Can't get the layout of `i128`") - .align - .abi, + .align, const_cache: Default::default(), codegen_unit, context, diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index ab1c886d3f9ea..5c616c60003b0 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -233,7 +233,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::volatile_load | sym::unaligned_volatile_load => { let ptr = args[0].immediate(); - let abi_align = result_layout.align.abi; + let abi_align = result_layout.align; let ptr_align = if name == sym::volatile_load { abi_align } else { Align::ONE }; let load = self.volatile_load(result.layout.gcc_type(self), ptr, ptr_align); if let BackendRepr::Scalar(scalar) = result.layout.backend_repr { @@ -720,7 +720,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { return; } if self.is_sized_indirect() { - OperandValue::Ref(PlaceValue::new_sized(val, self.layout.align.abi)).store(bx, dst) + OperandValue::Ref(PlaceValue::new_sized(val, self.layout.align)).store(bx, dst) } else if self.is_unsized_indirect() { bug!("unsized `ArgAbi` cannot be stored"); } else if let PassMode::Cast { ref cast, .. } = self.mode { @@ -730,7 +730,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { if can_store_through_cast_ptr { let cast_ptr_llty = bx.type_ptr_to(cast.gcc_type(bx)); let cast_dst = bx.pointercast(dst.val.llval, cast_ptr_llty); - bx.store(val, cast_dst, self.layout.align.abi); + bx.store(val, cast_dst, self.layout.align); } else { // The actual return type is a struct, but the ABI // adaptation code has cast it into some scalar type. The @@ -758,7 +758,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { // ... and then memcpy it to the intended destination. bx.memcpy( dst.val.llval, - self.layout.align.abi, + self.layout.align, scratch, scratch_align, bx.const_usize(self.layout.size.bytes()), diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 8cc10a5750079..6d815b9111600 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -396,14 +396,14 @@ pub fn struct_fields<'gcc, 'tcx>( let mut packed = false; let mut offset = Size::ZERO; - let mut prev_effective_align = layout.align.abi; + let mut prev_effective_align = layout.align; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i); let field = layout.field(cx, i); let effective_field_align = - layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); - packed |= effective_field_align < field.align.abi; + layout.align.min(field.align).restrict_for_offset(target_offset); + packed |= effective_field_align < field.align; assert!(target_offset >= offset); let padding = target_offset - offset; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 1c28c8944e17d..4b4267768141f 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -81,7 +81,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( layout.scalar_pair_element_gcc_type(cx, 0), layout.scalar_pair_element_gcc_type(cx, 1), ], - &struct_attributes(false, Some(layout.align.abi)), + &struct_attributes(false, Some(layout.align)), ); } BackendRepr::Memory { .. } => {} @@ -127,9 +127,9 @@ fn uncached_gcc_type<'gcc, 'tcx>( match layout.fields { FieldsShape::Primitive | FieldsShape::Union(_) => { - let fill = cx.type_padding_filler(layout.size, layout.align.abi); + let fill = cx.type_padding_filler(layout.size, layout.align); let packed = false; - let attributes = struct_attributes(packed, Some(layout.align.abi)); + let attributes = struct_attributes(packed, Some(layout.align)); match name { None => cx.type_struct(&[fill], &attributes), Some(ref name) => { @@ -143,7 +143,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Arbitrary { .. } => match name { None => { let (gcc_fields, packed) = struct_fields(cx, layout); - cx.type_struct(&gcc_fields, &struct_attributes(packed, Some(layout.align.abi))) + cx.type_struct(&gcc_fields, &struct_attributes(packed, Some(layout.align))) } Some(ref name) => { let gcc_type = cx.type_named_struct(name); @@ -244,7 +244,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { cx.set_struct_body( deferred_ty, &fields, - &struct_attributes(packed, Some(layout.align.abi)), + &struct_attributes(packed, Some(layout.align)), ); } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 49bcd7aad6895..6a80d14363c95 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -251,7 +251,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Ignore => {} // Sized indirect arguments PassMode::Indirect { attrs, address_space: _, mode: _ } => { - let align = attrs.pointee_align.unwrap_or(self.layout.align.abi); + let align = attrs.pointee_align.unwrap_or(self.layout.align); OperandValue::Ref(PlaceValue::new_sized(val, align)).store(bx, dst); } // Unsized indirect arguments cannot be stored @@ -280,7 +280,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { // ... and then memcpy it to the intended destination. bx.memcpy( dst.val.llval, - self.layout.align.abi, + self.layout.align, llscratch, scratch_align, bx.const_usize(copy_bytes), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index b8237443cccc3..7e71755ed4e70 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -657,22 +657,17 @@ pub(crate) unsafe fn llvm_optimize<'ll>( None }; - fn handle_offload<'ll>(cx: &SimpleCx<'ll>, old_fn: &'ll llvm::Value) { + // Wraps `old_fn` into a new kernel that takes the implicit `dyn_ptr` as its first argument. + // Returns the new function, or `None` if nothing was wrapped + fn handle_offload<'ll>( + cx: &SimpleCx<'ll>, + old_fn: &'ll llvm::Value, + ) -> Option<&'ll llvm::Value> { let old_fn_ty = cx.get_type_of_global(old_fn); let old_param_types = cx.func_params_types(old_fn_ty); let old_param_count = old_param_types.len(); if old_param_count == 0 { - return; - } - - let first_param = llvm::get_param(old_fn, 0); - let c_name = llvm::get_value_name(first_param); - let first_arg_name = str::from_utf8(&c_name).unwrap(); - // We might call llvm_optimize (and thus this code) multiple times on the same IR, - // but we shouldn't add this helper ptr multiple times. - // FIXME(offload): This could break if the user calls his first argument `dyn_ptr`. - if first_arg_name == "dyn_ptr" { - return; + return None; } // Create the new parameter list, with ptr as the first argument @@ -747,6 +742,7 @@ pub(crate) unsafe fn llvm_optimize<'ll>( } // Now we can re-use the old name, without name collision. llvm::set_value_name(new_fn, &name); + Some(new_fn) } if cgcx.target_is_like_gpu @@ -755,10 +751,13 @@ pub(crate) unsafe fn llvm_optimize<'ll>( let cx = SimpleCx::new(llmod, llcx, cgcx.pointer_size); for func in cx.get_functions() { let offload_kernel = "offload-kernel"; - if attributes::has_string_attr(func, offload_kernel) { - handle_offload(&cx, func); + if !attributes::has_string_attr(func, offload_kernel) { + continue; + } + match handle_offload(&cx, func) { + Some(new_fn) => attributes::remove_string_attr_from_llfn(new_fn, offload_kernel), + None => attributes::remove_string_attr_from_llfn(func, offload_kernel), } - attributes::remove_string_attr_from_llfn(func, offload_kernel); } } @@ -822,8 +821,9 @@ pub(crate) unsafe fn llvm_optimize<'ll>( }; // This assumes that we previously compiled our kernels for a gpu target, which created a - // `.bc` artifact. The user is supposed to provide us with a path to this artifact, we - // don't need any other artifacts from the previous run. + // `.ptx` (NVPTX) or `.elf` (AMDGPU) artifact. + // The user is supposed to provide us with a path to this artifact, + // we don't need any other artifacts from the previous run. if !cgcx.target_is_like_gpu && is_final_stage { if let Some(device_path) = config .offload @@ -833,15 +833,18 @@ pub(crate) unsafe fn llvm_optimize<'ll>( let device_pathbuf = PathBuf::from(device_path); if device_pathbuf.is_relative() { dcx.emit_err(crate::diagnostics::OffloadWithoutAbsPath); - } else if device_pathbuf.extension().and_then(|e| e.to_str()) != Some("bc") { + } else if !matches!( + device_pathbuf.extension().and_then(|e| e.to_str()), + Some("ptx" | "elf") + ) { dcx.emit_err(crate::diagnostics::OffloadWrongFileName); } else if !device_pathbuf.exists() { dcx.emit_err(crate::diagnostics::OffloadNonexistingPath); } - let device_bitcode_c = path_to_c_string(device_pathbuf.as_path()); + let device_image_c = path_to_c_string(device_pathbuf.as_path()); let ok = unsafe { llvm::RustOffloadWrapper::get_instance() - .llvm_rust_offload_wrap_images(llmod, device_bitcode_c.as_c_str()) + .llvm_rust_offload_wrap_images(llmod, device_image_c.as_c_str()) }; if !ok { dcx.emit_err(crate::diagnostics::OffloadWrapImagesFailed); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8b68d2233de89..41b26e33e3c38 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -719,7 +719,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { let alloca = llvm::LLVMBuildAlloca(bx.llbuilder(), scalable_vector_ty, UNNAMED); - llvm::LLVMSetAlignment(alloca, layout.align.abi.bytes() as c_uint); + llvm::LLVMSetAlignment(alloca, layout.align.bytes() as c_uint); alloca } } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 2089f2b2008be..30b8b3682c3b1 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -22,7 +22,6 @@ use tracing::{debug, instrument, trace}; use crate::common::CodegenCx; use crate::diagnostics::SymbolAlreadyDefined; use crate::llvm::{self, Type, Value, const_ptr_auth}; -use crate::type_of::LayoutLlvmExt; use crate::{base, debuginfo}; /// Indicates whether a value originates from a `static`. @@ -200,7 +199,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( let mut should_sign = false; // Declare a symbol `foo`. If `foo` is an extern_weak symbol, we declare // an extern_weak function, otherwise a global with the desired linkage. - let g1 = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) { + let actual_global = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) { // An `extern_weak` function is represented as an `Option`, // we extract the function signature and declare it as an extern_weak function // instead of an extern_weak i8. @@ -224,28 +223,11 @@ fn check_and_apply_linkage<'ll, 'tcx>( } else { cx.declare_global(sym, cx.type_i8()) }; - llvm::set_linkage(g1, base::linkage_to_llvm(linkage)); + llvm::set_linkage(actual_global, base::linkage_to_llvm(linkage)); // Normally this is done in `get_static_inner`, but when as we generate an internal global, // it will apply the dso_local to the internal global instead, so do it here, too. - cx.assume_dso_local(g1, true); - - // Declare an internal global `extern_with_linkage_foo` which - // is initialized with the address of `foo`. If `foo` is - // discarded during linking (for example, if `foo` has weak - // linkage and there are no definitions), then - // `extern_with_linkage_foo` will instead be initialized to - // zero. - let real_name = - format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); - let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { - cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { - span: cx.tcx.def_span(def_id), - symbol_name: sym, - }) - }); - llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); - llvm::set_unnamed_address(g2, llvm::UnnamedAddr::Global); + cx.assume_dso_local(actual_global, true); // Sign the function pointer that is used to initialize the global let initializer = if should_sign { @@ -256,18 +238,36 @@ fn check_and_apply_linkage<'ll, 'tcx>( .expect("pointer authentication functions must be available when signing"); const_ptr_auth( - cx.const_bitcast(g1, llty), + actual_global, schema.key as u32, schema.constant_discriminator as u64, None, /* address_diversity */ ) } else { - g1 + actual_global }; - llvm::set_initializer(g2, initializer); - - g2 + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let real_name = + format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); + let pointer_global = + cx.define_global(&real_name, cx.val_ty(initializer)).unwrap_or_else(|| { + cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { + span: cx.tcx.def_span(def_id), + symbol_name: sym, + }) + }); + llvm::set_linkage(pointer_global, llvm::Linkage::InternalLinkage); + llvm::set_unnamed_address(pointer_global, llvm::UnnamedAddr::Global); + + llvm::set_initializer(pointer_global, initializer); + + pointer_global } else if cx.tcx.sess.target.arch == Arch::X86 && common::is_using_dlltool(&cx.tcx.sess.target) && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym) @@ -358,7 +358,7 @@ impl<'ll> CodegenCx<'ll, '_> { } else { let ty = instance.ty(self.tcx, self.typing_env()); trace!(?ty); - self.layout_of(ty).llvm_type(self) + self.type_array(self.type_i8(), self.layout_of(ty).size.bytes()) }; self.get_static_inner(def_id, llty) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 8c7e21666aa41..752cbc67d5637 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -90,7 +90,7 @@ macro_rules! return_if_di_node_created_in_meantime { /// Extract size and alignment from a TyAndLayout. #[inline] fn size_and_align_of(ty_and_layout: TyAndLayout<'_>) -> (Size, Align) { - (ty_and_layout.size, ty_and_layout.align.abi) + (ty_and_layout.size, ty_and_layout.align) } /// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`). @@ -243,7 +243,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( cx, pointee_type_di_node, addr_field.size, - addr_field.align.abi, + addr_field.align, "", ); @@ -1593,7 +1593,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( let usize_di_node = type_di_node(cx, tcx.types.usize); let pointer_layout = cx.layout_of(void_pointer_ty); let pointer_size = pointer_layout.size; - let pointer_align = pointer_layout.align.abi; + let pointer_align = pointer_layout.align; // If `usize` is not pointer-sized and -aligned then the size and alignment computations // for the vtable as a whole would be wrong. Let's make sure this holds even on weird // platforms. diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 094b683ded56b..19b2f68107e6c 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -73,7 +73,7 @@ pub(crate) struct RustOffloadComponentMissing { #[derive(Diagnostic)] #[diag( - "using the offload feature requires -Z offload=.bc>" + "using the offload feature requires -Z offload=.ptx or .elf>" )] pub(crate) struct OffloadWithoutEnable; @@ -82,18 +82,20 @@ pub(crate) struct OffloadWithoutEnable; pub(crate) struct OffloadWithoutFatLTO; #[derive(Diagnostic)] -#[diag("using the `-Z offload=Host=/absolute/path/to/.bc` flag requires an absolute path")] +#[diag( + "using the `-Z offload=Host=/absolute/path/to/.ptx` or `.elf` flag requires an absolute path" +)] pub(crate) struct OffloadWithoutAbsPath; #[derive(Diagnostic)] #[diag( - "using the `-Z offload=Host=/absolute/path/to/.bc` flag must point to a .bc file produced by the device compilation (--emit=llvm-bc)" + "using the `-Z offload=Host=/absolute/path/to/.ptx` or `.elf` flag must point to a .ptx or .elf file produced by the device compilation" )] pub(crate) struct OffloadWrongFileName; #[derive(Diagnostic)] #[diag( - "the given path/file to `.bc` does not exist. Did you forget to run the device compilation first?" + "the given path/file to `.ptx` or `.elf` does not exist. Did you forget to run the device compilation first?" )] pub(crate) struct OffloadNonexistingPath; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 891a48c6701e3..594f4cbcf759d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -312,7 +312,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // `MaybeUninint<&dyn Trait>` would load as `{ [i64x2] }` which gives assertions later // (if we're lucky) from things not being pointers that ought to be. let ptr = args[0].immediate(); - let abi_align = result_layout.align.abi; + let abi_align = result_layout.align; let ptr_align = if name == sym::volatile_load { abi_align } else { Align::ONE }; let need_black_box = llvm_version < (23, 0, 0); if result_layout.is_zst() { diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 0cd26ca835971..f9863da230dfb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -262,6 +262,12 @@ pub(crate) fn add_global<'ll>(llmod: Module<'ll>, ty: &'ll Type, name_cstr: &CSt } pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) { + unsafe { + assert_eq!( + crate::llvm::LLVMGlobalGetValueType(llglobal), + crate::llvm::LLVMTypeOf(constant_val) + ); + } unsafe { LLVMSetInitializer(llglobal, constant_val); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs index 60e0836a35d88..4f2369aef0d53 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/offload_ffi.rs @@ -6,9 +6,8 @@ use super::ffi::{Module, Value}; type LLVMRustOffloadMapperFn = unsafe extern "C" fn(&Value, &Value, *const &Value); type LLVMRustOffloadWrapImagesFn = - for<'ll> unsafe extern "C" fn(Module<'ll>, *const c_char, *const c_char) -> bool; + for<'ll> unsafe extern "C" fn(Module<'ll>, *const c_char) -> bool; -use rustc_fs_util::path_to_c_string; use rustc_session::config::host_tuple; use rustc_session::filesearch; @@ -17,7 +16,6 @@ use crate::llvm; pub(crate) struct RustOffloadWrapper { LLVMRustOffloadMapper: LLVMRustOffloadMapperFn, LLVMRustOffloadWrapImages: LLVMRustOffloadWrapImagesFn, - lld_path: Option, // Keep the dynamic library loaded while the function pointers are used. _lib: libloading::Library, } @@ -59,18 +57,15 @@ impl RustOffloadWrapper { pub(crate) unsafe fn llvm_rust_offload_wrap_images<'ll>( &self, host_m: Module<'ll>, - device_bitcode_path: &CStr, + device_image_path: &CStr, ) -> bool { - let lld_c = self.lld_path.as_deref().map(path_to_c_string).unwrap_or_default(); - unsafe { - (self.LLVMRustOffloadWrapImages)(host_m, lld_c.as_ptr(), device_bitcode_path.as_ptr()) - } + unsafe { (self.LLVMRustOffloadWrapImages)(host_m, device_image_path.as_ptr()) } } fn call_dynamic( sysroot: &rustc_session::config::Sysroot, ) -> Result { - let (rust_offload_path, lld_path) = Self::get_offload_and_lld_paths(sysroot)?; + let rust_offload_path = Self::get_offload_path(sysroot)?; let lib = unsafe { libloading::Library::new(rust_offload_path)? }; let llvm_rust_offload_wrapper = @@ -81,14 +76,13 @@ impl RustOffloadWrapper { Ok(Self { LLVMRustOffloadMapper: llvm_rust_offload_wrapper, LLVMRustOffloadWrapImages: llvm_rust_offload_wrap_images, - lld_path, _lib: lib, }) } - fn get_offload_and_lld_paths( + fn get_offload_path( sysroot: &rustc_session::config::Sysroot, - ) -> Result<(PathBuf, Option), RustOffloadLibraryError> { + ) -> Result { let llvm_version_major = llvm::LLVMRustVersionMajor(); let mut searched = Vec::new(); @@ -102,11 +96,7 @@ impl RustOffloadWrapper { continue; } - let lld_path = filesearch::make_target_bin_path(root, host_tuple()) - .join(format!("rust-lld{}", std::env::consts::EXE_SUFFIX)); - let lld_path = lld_path.is_file().then_some(lld_path); - - return Ok((rust_offload_path, lld_path)); + return Ok(rust_offload_path); } Err(RustOffloadLibraryError::NotFound { diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 2d64c63cf9ae4..82bd5584211c0 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -20,7 +20,6 @@ use crate::abi::FnAbiLlvmExt; use crate::builder::Builder; use crate::context::CodegenCx; use crate::diagnostics::SymbolAlreadyDefined; -use crate::type_of::LayoutLlvmExt; use crate::{base, llvm}; impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { @@ -37,7 +36,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { // out the llvm type from the actual evaluated initializer. let ty = if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; - let llty = self.layout_of(ty).llvm_type(self); + let llty = self.type_array(self.type_i8(), self.layout_of(ty).size.bytes()); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { self.sess() diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 79eeae4c977a2..d72441264873c 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -74,7 +74,7 @@ fn uncached_llvm_type<'a, 'tcx>( match layout.fields { FieldsShape::Primitive | FieldsShape::Union(_) => { - let fill = cx.type_padding_filler(layout.size, layout.align.abi); + let fill = cx.type_padding_filler(layout.size, layout.align); match name { None => cx.type_struct(&[fill]), Some(ref name) => { @@ -109,14 +109,14 @@ fn struct_llfields<'a, 'tcx>( let mut packed = false; let mut offset = Size::ZERO; - let mut prev_effective_align = layout.align.abi; + let mut prev_effective_align = layout.align; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i as usize); let field = layout.field(cx, i); let effective_field_align = - layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); - packed |= effective_field_align < field.align.abi; + layout.align.min(field.align).restrict_for_offset(target_offset); + packed |= effective_field_align < field.align; debug!( "struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ @@ -161,7 +161,7 @@ fn struct_llfields<'a, 'tcx>( impl<'a, 'tcx> CodegenCx<'a, 'tcx> { pub(crate) fn align_of(&self, ty: Ty<'tcx>) -> Align { - self.layout_of(ty).align.abi + self.layout_of(ty).align } pub(crate) fn size_of(&self, ty: Ty<'tcx>) -> Size { @@ -174,7 +174,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { pub(crate) fn spanned_size_and_align_of(&self, ty: Ty<'tcx>, span: Span) -> (Size, Align) { let layout = self.spanned_layout_of(ty, span); - (layout.size, layout.align.abi) + (layout.size, layout.align) } } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index d9c57fca401e4..760badd28ad1e 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -110,7 +110,7 @@ fn get_param_type_alignment<'ll, 'tcx>( _ => { /* fall through */ } } - layout.align.abi + layout.align } enum PassMode { @@ -274,7 +274,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( reg_addr = bx.ptradd(reg_addr, offset); } let reg_type = layout.llvm_type(bx); - let reg_value = bx.load(reg_type, reg_addr, layout.align.abi); + let reg_value = bx.load(reg_type, reg_addr, layout.align); bx.br(end); // On Stack block @@ -543,7 +543,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>( let val_type = layout.llvm_type(bx); let val_addr = if indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr }; - bx.load(val_type, val_addr, layout.align.abi) + bx.load(val_type, val_addr, layout.align) } fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( @@ -625,7 +625,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( } BackendRepr::Memory { .. } => { let mem_addr = x86_64_sysv64_va_arg_from_memory(bx, va_list_addr, layout); - return bx.load(layout.llvm_type(bx), mem_addr, layout.align.abi); + return bx.load(layout.llvm_type(bx), mem_addr, layout.align); } }; @@ -710,7 +710,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( let reg_hi_addr = bx.inbounds_ptradd(reg_lo_addr, bx.const_i32(16)); let align = layout.layout.align(); - let tmp = bx.alloca(layout.size, layout.align.abi); + let tmp = bx.alloca(layout.size, layout.align); let reg_lo = bx.load(ty_lo, reg_lo_addr, align_lo); let reg_hi = bx.load(ty_hi, reg_hi_addr, align_hi); @@ -732,7 +732,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( Primitive::Int(_, _) | Primitive::Pointer(_) => (gp_addr, fp_addr), }; - let tmp = bx.alloca(layout.size, layout.align.abi); + let tmp = bx.alloca(layout.size, layout.align); let reg_lo = bx.load(ty_lo, reg_lo_addr, align_lo); let reg_hi = bx.load(ty_hi, reg_hi_addr, align_hi); @@ -788,7 +788,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( let val_type = layout.llvm_type(bx); let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]); - bx.load(val_type, val_addr, layout.align.abi) + bx.load(val_type, val_addr, layout.align) } /// Copy into a temporary if the type is more aligned than the register save area. @@ -798,13 +798,13 @@ fn copy_to_temporary_if_more_aligned<'ll, 'tcx>( layout: TyAndLayout<'tcx>, src_align: Align, ) -> &'ll Value { - if layout.layout.align.abi > src_align { + if layout.layout.align > src_align { assert!(layout.ty.is_integral()); // A memcpy below optimizes poorly for 128-bit integers. - let tmp = bx.alloca(layout.size, layout.align.abi); + let tmp = bx.alloca(layout.size, layout.align); let val = bx.load(layout.llvm_type(bx), reg_addr, src_align); - bx.store(val, tmp, layout.align.abi); + bx.store(val, tmp, layout.align); tmp } else { reg_addr @@ -830,7 +830,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>( // this behavior for 32+ alignment matches clang. // It currently (2026 July) can only occur for 16-byte-aligned types. let overflow_arg_area_v = if layout.layout.align.bytes() > 8 { - round_pointer_up_to_alignment(bx, overflow_arg_area_v, layout.layout.align.abi) + round_pointer_up_to_alignment(bx, overflow_arg_area_v, layout.layout.align) } else { overflow_arg_area_v }; @@ -926,7 +926,7 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>( bx.switch_to_block(end); let value_addr = bx.phi(bx.type_ptr(), &[reg_value_addr, overflow_value_addr], &[maybe_reg, from_overflow]); - bx.load(layout.llvm_type(bx), value_addr, layout.align.abi) + bx.load(layout.llvm_type(bx), value_addr, layout.align) } fn emit_hexagon_va_arg_bare_metal<'ll, 'tcx>( @@ -945,7 +945,7 @@ fn emit_hexagon_va_arg_bare_metal<'ll, 'tcx>( let current_ptr = bx.load(bx.type_ptr(), va_list_addr, ptr_align_abi); // Handle address alignment for types with alignment > 4 bytes - let ty_align = layout.align.abi; + let ty_align = layout.align; let aligned_ptr = if ty_align.bytes() > 4 { // Ensure alignment is a power of 2 debug_assert!(ty_align.bytes().is_power_of_two(), "Alignment is not power of 2!"); @@ -963,7 +963,7 @@ fn emit_hexagon_va_arg_bare_metal<'ll, 'tcx>( bx.store(next_ptr, va_list_addr, ptr_align_abi); // Load and return the argument value - bx.load(layout.llvm_type(bx), aligned_ptr, layout.align.abi) + bx.load(layout.llvm_type(bx), aligned_ptr, layout.align) } fn emit_xtensa_va_arg<'ll, 'tcx>( @@ -1000,7 +1000,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( let offset_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_ndx_offset)); let offset = bx.load(bx.type_i32(), offset_ptr, bx.tcx().data_layout.i32_align); - let offset = round_up_to_alignment(bx, offset, layout.align.abi); + let offset = round_up_to_alignment(bx, offset, layout.align); let slot_size = layout.size.align_to(Align::FOUR).bytes() as i32; @@ -1060,7 +1060,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( assert!(bx.tcx().sess.target.endian == Endian::Little); let value_ptr = bx.phi(bx.type_ptr(), &[regsave_value_ptr, stack_value_ptr], &[from_regsave, from_stack]); - return bx.load(layout.llvm_type(bx), value_ptr, layout.align.abi); + return bx.load(layout.llvm_type(bx), value_ptr, layout.align); } /// Determine the va_arg implementation to use. The LLVM va_arg instruction diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index c3bace9569dd0..10baf16915d15 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -72,8 +72,13 @@ fn process_builtin_attrs( AttributeKind::Cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, AttributeKind::ExportName { name, .. } => codegen_fn_attrs.symbol_name = Some(*name), AttributeKind::Inline(inline, span) => { - codegen_fn_attrs.inline = *inline; - interesting_spans.inline = Some(*span); + // On an `async fn` (or similar), inlining hints are meant for the code the user + // wrote, which lives in the body coroutine. The constructor is trivial and left to + // the usual heuristics. + if !constructs_desugared_body_coroutine(tcx, did) { + codegen_fn_attrs.inline = *inline; + interesting_spans.inline = Some(*span); + } } AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::RustcAlign { align, .. } => codegen_fn_attrs.alignment = Some(*align), @@ -297,9 +302,54 @@ fn process_builtin_attrs( } } + // The body coroutine can't carry attributes of its own, so it takes the ones describing the + // code the user wrote from the `async fn` (or similar) it was desugared from. This makes e.g. + // `#[inline(never)] async fn` affect `Future::poll`. See #129347. + if is_desugared_body_coroutine(tcx, did) { + let parent = tcx.local_parent(did); + // `#[rustc_force_inline]` is already rejected on the parent. Propagating it would only + // cause `CheckForceInline` to report the same attribute again for the coroutine. + if let Some((inline, span)) = find_attr!( + tcx, + parent, + Inline(inline, span) if !matches!(inline, InlineAttr::Force { .. }) => (*inline, *span) + ) { + codegen_fn_attrs.inline = inline; + interesting_spans.inline = Some(span); + } + // Unlike inlining hints, `#[cold]` stays on the constructor as well: calling it is just as + // unlikely, and its call sites are only recognized as cold through that. + if find_attr!(tcx, parent, Cold) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; + } + } + interesting_spans } +/// Whether `did` is the coroutine holding the body of an `async fn`, `gen fn`, `async gen fn`, or +/// `async` closure, as opposed to one written as an `async {}` block. +fn is_desugared_body_coroutine(tcx: TyCtxt<'_>, did: LocalDefId) -> bool { + matches!( + tcx.coroutine_kind(did), + Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Fn | hir::CoroutineSource::Closure + )) + ) +} + +/// Whether `did` is an `async fn`, `gen fn`, `async gen fn`, or `async` closure, i.e. its body +/// does nothing but construct a [desugared body coroutine](is_desugared_body_coroutine). +fn constructs_desugared_body_coroutine(tcx: TyCtxt<'_>, did: LocalDefId) -> bool { + tcx.hir_maybe_body_owned_by(did).is_some_and(|body| { + matches!( + body.value.kind, + hir::ExprKind::Closure(closure) if is_desugared_body_coroutine(tcx, closure.def_id) + ) + }) +} + /// Applies overrides for codegen fn attrs. These often have a specific reason why they're necessary. /// Please comment why when adding a new one! fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut CodegenFnAttrs) { @@ -336,7 +386,17 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code // its parent function, which effectively inherits the features anyway. Boxing this closure // would result in this closure being compiled without the inherited target features, but this // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. - if tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always { + // + // That reasoning doesn't hold for the body coroutine of an `async fn` or `gen fn`: it is never + // inlined into the function constructing it, yet its body was checked as part of that function. + // It always inherits, so it is compiled with the same features as the function itself. + if tcx.is_closure_like(did.to_def_id()) + && (codegen_fn_attrs.inline != InlineAttr::Always + || matches!( + tcx.coroutine_kind(did), + Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Fn)) + )) + { let owner_id = tcx.parent(did.to_def_id()); if tcx.def_kind(owner_id).has_codegen_attrs() { codegen_fn_attrs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 600afb04962f8..f5a6575e3c848 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -628,10 +628,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scratch.val.llval } Ref(place_val) => { - assert_eq!( - place_val.align, op.layout.align.abi, - "return place is unaligned!" - ); + assert_eq!(place_val.align, op.layout.align, "return place is unaligned!"); place_val.llval } ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"), @@ -644,7 +641,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.clear_padding_cmse(bx, llslot, ret_layout.size, ret_layout); } - load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi) + load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align) } PassMode::IndirectUnsized { .. } => bug!("unsized returns are not supported"), }; @@ -1037,7 +1034,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; if let Some(place) = result_place - && place.align < result_layout.align.abi + && place.align < result_layout.align { // Currently, MIR code generation does not create calls // that store directly to fields of packed structs (in @@ -1943,7 +1940,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let discr_ty = layout.ty.discriminant_ty(bx.tcx()); let enum_ptr = bx.inbounds_ptradd(base_ptr, bx.const_usize(base_offset.bytes())); let operand = OperandRef { - val: OperandValue::Ref(PlaceValue::new_sized(enum_ptr, layout.align.abi)), + val: OperandValue::Ref(PlaceValue::new_sized(enum_ptr, layout.align)), layout, move_annotation: None, }; @@ -2010,8 +2007,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // alignment. This can happen, e.g. when passing types with <4 byte alignment // on the stack on x86. let required_align = match attrs.pointee_align { - Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi), - None => arg.layout.align.abi, + Some(pointee_align) => cmp::max(pointee_align, arg.layout.align), + None => arg.layout.align, }; let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align); bx.lifetime_start(scratch.llval, arg.layout.size); @@ -2027,8 +2024,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // alignment requirements may be higher than the type's alignment, so copy // to a higher-aligned alloca. let required_align = match attrs.pointee_align { - Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi), - None => arg.layout.align.abi, + Some(pointee_align) => cmp::max(pointee_align, arg.layout.align), + None => arg.layout.align, }; // Copy to an alloca when the argument is neither by-val nor by-move. if op_place_val.align < required_align @@ -2473,7 +2470,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place(bx, dest.as_ref()) }; if fn_ret.is_indirect() { - if dest.val.align < dest.layout.align.abi { + if dest.val.align < dest.layout.align { // Currently, MIR code generation does not create calls // that store directly to fields of packed structs (in // fact, the calls it creates write only to temps). diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index d930ac8e686da..3504823450e75 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -25,7 +25,7 @@ fn copy_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) { let layout = bx.layout_of(ty); let size = layout.size; - let align = layout.align.abi; + let align = layout.align; let size = bx.unchecked_sumul(bx.const_usize(size.bytes()), count); let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() }; if allow_overlap { @@ -45,7 +45,7 @@ fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) { let layout = bx.layout_of(ty); let size = layout.size; - let align = layout.align.abi; + let align = layout.align; let size = bx.mul(bx.const_usize(size.bytes()), count); let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() }; bx.memset(dst, val, size, align, flags); @@ -94,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // into the (unoptimized) direct swapping implementation, so we disable it. || bx.sess().target.arch == Arch::SpirV { - let align = pointee_layout.align.abi; + let align = pointee_layout.align; let x_place = args[0].val.deref(align); let y_place = args[1].val.deref(align); bx.typed_place_swap(x_place, y_place, pointee_layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 6cb9e33f4680d..2826952a3bec3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -571,7 +571,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // FIXME: lifetimes let mut needs_alloca = mode == IndirectMode::AmdgpuKernelArg; if let Some(pointee_align) = attrs.pointee_align - && pointee_align < arg.layout.align.abi + && pointee_align < arg.layout.align { needs_alloca = true; } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index ad8c02551570c..7164bf51e7049 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -217,7 +217,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { offset: Size, ) -> Self { let alloc_align = alloc.inner().align; - assert!(alloc_align >= layout.align.abi, "{alloc_align:?} < {:?}", layout.align.abi); + assert!(alloc_align >= layout.align, "{alloc_align:?} < {:?}", layout.align); let read_scalar = |start, size, s: abi::Scalar, ty| { match alloc.0.read_scalar( @@ -307,7 +307,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)); let layout = cx.layout_of(projected_ty); - self.val.deref(layout.align.abi).with_type(layout) + self.val.deref(layout.align).with_type(layout) } /// Store this operand into a place, applying move/copy annotation if present. @@ -996,7 +996,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } BackendRepr::Memory { .. } => { let ptr = bx.cx().type_ptr(); - OperandValue::Ref(PlaceValue::new_sized(bx.const_poison(ptr), layout.align.abi)) + OperandValue::Ref(PlaceValue::new_sized(bx.const_poison(ptr), layout.align)) } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index ce166fbe59fd9..d9eccae7fc50e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -94,7 +94,7 @@ pub struct PlaceRef<'tcx, V> { impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized(llval: V, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> { - PlaceRef::new_sized_aligned(llval, layout, layout.align.abi) + PlaceRef::new_sized_aligned(llval, layout, layout.align) } pub fn new_sized_aligned( @@ -127,7 +127,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout: TyAndLayout<'tcx>, ) -> Self { assert!(layout.is_sized(), "tried to statically allocate unsized place"); - PlaceValue::alloca(bx, size, layout.align.abi).with_type(layout) + PlaceValue::alloca(bx, size, layout.align).with_type(layout) } /// Returns a place for an indirect reference to an unsized place. @@ -164,7 +164,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // FIXME why is this peeling at all? The LLVM type should be the same for the // transparent wrapper and the inner type. bx.alloca_with_ty(layout.peel_transparent_wrappers_from_non_1zst(bx)), - layout.align.abi, + layout.align, ) .with_type(layout) } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index e1718374af58c..642ee3badbf29 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Notably, Scalar ⇌ ScalarPair cases go here to avoid padding // and endianness issues, as do SimdVector ones to avoid worrying // about things like f32x8 ⇌ ptrx4 that would need multiple steps. - let align = Ord::max(operand.layout.align.abi, cast.align.abi); + let align = Ord::max(operand.layout.align, cast.align); let size = Ord::max(operand.layout.size, cast.size); let temp = PlaceValue::alloca(bx, size, align); bx.lifetime_start(temp.llval, size); diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 14eec4a0195e0..bf5b51a168165 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let elem_size = pointee_layout.layout.size().bytes(); let bytes = bx.unchecked_sumul(count, bx.const_usize(elem_size)); - let align = pointee_layout.layout.align.abi; + let align = pointee_layout.layout.align; let dst = dst_val.immediate(); let src = src_val.immediate(); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a3cac4525d988..aeac556aad82b 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -423,7 +423,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: &TyAndLayout<'tcx>, ) -> InterpResult<'tcx, Option<(Size, Align)>> { if layout.is_sized() { - return interp_ok(Some((layout.size, layout.align.abi))); + return interp_ok(Some((layout.size, layout.align))); } match layout.ty.kind() { ty::Adt(..) | ty::Tuple(..) => { @@ -436,7 +436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("DST layout: {:?}", layout); let unsized_offset_unadjusted = layout.fields.offset(layout.fields.count() - 1); - let sized_align = layout.align.abi; + let sized_align = layout.align; // Recurse to get the size of the dynamically sized field (must be // the last field). Can't have foreign types here, how would we @@ -496,7 +496,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if size > self.max_size_of_val() { throw_ub!(InvalidMeta(InvalidMetaKind::SliceTooBig)); } - interp_ok(Some((size, elem.align.abi))) + interp_ok(Some((size, elem.align))) } ty::Foreign(_) => interp_ok(None), diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 941af4a4ab01d..a5f02b4a5d157 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_targ use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{Symbol, bug, span_bug, sym}; +use rustc_span::{Symbol, bug, kw, span_bug, sym}; use tracing::trace; use super::memory::MemoryKind; @@ -231,7 +231,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = layout.align.bytes(); self.write_scalar(Scalar::from_target_usize(val, self), dest)?; } - sym::offset_of => { + kw::OffsetOf => { let tp_ty = instance.args.type_at(0); let variant = self.read_scalar(&args[0])?.to_u32()?; @@ -1050,7 +1050,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { let count = self.read_target_usize(count)?; let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?; - let (size, align) = (layout.size, layout.align.abi); + let (size, align) = (layout.size, layout.align); let size = self.compute_size_in_bytes(size, count).ok_or_else(|| { err_ub_format!( @@ -1122,7 +1122,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .ok_or_else(|| err_ub_format!("overflow computing total size of `{name}`"))?; // Check alignment as well. We set the attribute in LLVM. - self.check_ptr_align(dst, layout.align.abi)?; + self.check_ptr_align(dst, layout.align)?; let bytes = std::iter::repeat_n(byte, len.bytes_usize()); self.write_bytes_ptr(dst, bytes) @@ -1158,7 +1158,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { op: &OpTy<'tcx, >::Provenance>| -> InterpResult<'tcx, &[u8]> { let ptr = this.read_pointer(op)?; - this.check_ptr_align(ptr, layout.align.abi)?; + this.check_ptr_align(ptr, layout.align)?; let Some(alloc_ref) = self.get_ptr_alloc(ptr, layout.size)? else { // zero-sized access return interp_ok(&[]); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index 89574528c88bb..9250aed30276e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -844,9 +844,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::SimdAlign::Element => { // Take the alignment of the only field, which is an array and therefore has the same // alignment as the element type. - vector_layout.field(self, 0).align.abi + vector_layout.field(self, 0).align } - ty::SimdAlign::Vector => vector_layout.align.abi, + ty::SimdAlign::Vector => vector_layout.align, }; self.check_ptr_align(ptr, align) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index ed73a76da8bf0..00c3e96203545 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -121,7 +121,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> { #[inline] pub fn fake_alloc_zst(layout: TyAndLayout<'tcx>) -> Self { assert!(layout.is_zst()); - let align = layout.align.abi; + let align = layout.align; let ptr = Pointer::without_provenance(align.bytes()); // no provenance, absolute address MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None, misaligned: None }, layout } } @@ -396,8 +396,7 @@ where layout: TyAndLayout<'tcx>, unaligned: bool, ) -> MPlaceTy<'tcx, M::Provenance> { - let misaligned = - if unaligned { None } else { self.is_ptr_misaligned(ptr, layout.align.abi) }; + let misaligned = if unaligned { None } else { self.is_ptr_misaligned(ptr, layout.align) }; MPlaceTy { mplace: MemPlace { ptr, meta, misaligned }, layout } } @@ -505,7 +504,7 @@ where // Dereferencability and alignment check. This also implicitly checks metadata validity. let (size, align) = self .size_and_align_of_val(&mplace)? - .unwrap_or_else(|| (mplace.layout.size, mplace.layout.align.abi)); + .unwrap_or_else(|| (mplace.layout.size, mplace.layout.align)); self.check_ptr_access(mplace.ptr(), size, CheckInAllocMsg::Dereferenceable(kind))?; self.check_ptr_align(mplace.ptr(), align).map_err_kind(|err| { let err_ub!(AlignmentCheckFailed(Misalignment { required, has }, _msg)) = err else { bug!() }; @@ -546,7 +545,7 @@ where { let (size, _align) = self .size_and_align_of_val(mplace)? - .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + .unwrap_or((mplace.layout.size, mplace.layout.align)); // We check alignment separately, and *after* checking everything else. // If an access is both OOB and misaligned, we want to see the bounds error. let a = self.get_ptr_alloc(mplace.ptr(), size)?; @@ -562,7 +561,7 @@ where { let (size, _align) = self .size_and_align_of_val(mplace)? - .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + .unwrap_or((mplace.layout.size, mplace.layout.align)); // We check alignment separately, and raise that error *after* checking everything else. // If an access is both OOB and misaligned, we want to see the bounds error. // However we have to call `check_misalign` first to make the borrow checker happy. diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 836037d4d22a7..bada9f7cae182 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -43,7 +43,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let ty = self.get_ptr_vtable_ty(vtable, expected_trait)?; let layout = self.layout_of(ty)?; assert!(layout.is_sized(), "there are no vtables for unsized types"); - interp_ok((layout.size, layout.align.abi)) + interp_ok((layout.size, layout.align)) } pub(super) fn vtable_entries( diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 416207371e51c..2a5b0ce5650d4 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -86,7 +86,7 @@ pub(crate) fn create_static_alloc<'tcx>( let (size, align) = GlobalAlloc::Static(static_def_id.into()).size_and_align(*ecx.tcx, ecx.typing_env); assert_eq!(size, layout.size); - assert!(align >= layout.align.abi); + assert!(align >= layout.align); let alloc = Allocation::try_new(size, align, AllocInit::Uninit, ())?; let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into()); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 3b6424819a1da..67fe133f147f3 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -595,7 +595,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). - .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); + .unwrap_or_else(|| (place.layout.size, place.layout.align)); // If we're not allow to dangle, make sure this is dereferenceable and retag it for // the aliasing model. @@ -1120,7 +1120,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let (size, _align) = self .ecx .size_and_align_of_val(&mplace)? - .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + .unwrap_or((mplace.layout.size, mplace.layout.align)); // If there is no padding at all, we can skip the rest: check for // a single data range covering the entire value. if data_bytes.0 == &[(start_offset, size)] { diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 0fab4b288d18f..24352f6da0af3 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -25,7 +25,7 @@ where let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) - if layout.align.abi <= pack + if layout.align <= pack && (layout.is_sized() || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) => { diff --git a/compiler/rustc_error_codes/src/error_codes/E0452.md b/compiler/rustc_error_codes/src/error_codes/E0452.md index 429813a7cdd4e..581687e86974a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0452.md +++ b/compiler/rustc_error_codes/src/error_codes/E0452.md @@ -3,7 +3,7 @@ An invalid lint attribute has been given. Erroneous code example: ```compile_fail,E0452 -#![allow(foo = "")] // error: malformed lint attribute +#![allow(reason = "", foo)] // error: malformed lint attribute ``` Lint attributes only accept a list of identifiers (where each identifier is a diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3472180ae26dc..66687cfcbb06e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -301,8 +301,6 @@ declare_features! ( /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (unstable, auto_traits, "1.50.0", Some(13231)), - /// Allows builtin # foo() syntax - (internal, builtin_syntax, "1.71.0", Some(110680)), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (unstable, doc_notable_trait, "1.52.0", Some(45040)), @@ -310,6 +308,8 @@ declare_features! ( (unstable, dropck_eyepatch, "1.10.0", Some(34761)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), + /// Allows internal syntax. + (internal, internal_syntax, "CURRENT_RUSTC_VERSION", Some(110680)), /// Allows using `#[link_name="llvm.*"]`. (internal, link_llvm_intrinsics, "1.0.0", Some(29602)), /// Allows using the `#[linkage = ".."]` attribute. diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 85b666372074a..8b55734d90c8f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol, kw, sym}; use crate::check::check_function_signature; use crate::diagnostics::{UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic}; @@ -66,6 +66,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi // safe extern fns are otherwise unprecedented. // tidy-alphabetical-start + | kw::OffsetOf | sym::abort_immediate | sym::add_with_overflow | sym::aggregate_raw_ptr @@ -141,7 +142,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::needs_drop | sym::offload | sym::offload_get_num_devices - | sym::offset_of | sym::overflow_checks | sym::powf | sym::powi @@ -271,7 +271,7 @@ pub(crate) fn check_intrinsic_type( (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } sym::type_id_size_of => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)), - sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), + kw::OffsetOf => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()), diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index bf0d64d78d395..02acd8dc58918 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -402,7 +402,9 @@ fn bounds_from_generic_clauses<'tcx>( ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); - if !tcx.is_default_trait(def_id) && !tcx.is_lang_item(def_id, LangItem::Sized) { + if !tcx.is_implicit_trait(def_id, ty::IncludeSizedImplicitBounds::No) + && !tcx.is_lang_item(def_id, LangItem::Sized) + { // Do not add that restriction to the list if it is a positive requirement. entry.push(trait_predicate.def_id()); } diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index ae384a67ee6aa..ba1c1197bee92 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -7,7 +7,8 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{ - self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, + self, GenericClauses, ImplTraitInTraitData, IncludeSizedImplicitBounds, Ty, TyCtxt, + TypeVisitable, TypeVisitor, Upcast, }; use rustc_span::{DUMMY_SP, Ident, Span, bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -195,19 +196,13 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - tcx.types.self_param, - self_bounds, - ImpliedBoundsContext::TraitDef(def_id), - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, tcx.types.self_param, self_bounds, ImpliedBoundsContext::TraitDef(def_id), span, + IncludeSizedImplicitBounds::Yes, ); clauses.extend(bounds); } @@ -234,19 +229,13 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi let param_ty = icx.lowerer().lower_ty_param(param.hir_id); let mut bounds = Vec::new(); // Implicit bounds are added to type params unless a `?Trait` bound is found - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - param_ty, - &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), - param.span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, param_ty, &[], ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), param.span, + IncludeSizedImplicitBounds::Yes, ); trace!(?bounds); clauses.extend(bounds); @@ -690,19 +679,13 @@ pub(super) fn implied_clauses_with_filter<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - self_param_ty, - superbounds, - ImpliedBoundsContext::TraitDef(trait_def_id), - item.span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, self_param_ty, superbounds, ImpliedBoundsContext::TraitDef(trait_def_id), item.span, + IncludeSizedImplicitBounds::Yes, ); } //`ConstIfConst` is only interested in `[const]` bounds. @@ -992,19 +975,13 @@ impl<'tcx> ItemCtxt<'tcx> { match param.kind { hir::GenericParamKind::Type { .. } => { let param_ty = self.lowerer().lower_ty_param(param.hir_id); - self.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - param_ty, - &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), - param.span, - ); - self.lowerer().add_default_traits( + self.lowerer().add_implicit_bounds( &mut bounds, param_ty, &[], ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), param.span, + IncludeSizedImplicitBounds::Yes, ); } hir::GenericParamKind::Lifetime { .. } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 5ed5745310f16..131af48cd52bd 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -2,8 +2,8 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::{ - self, GenericArgs, PredicateProxy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, Upcast, shift_vars, + self, GenericArgs, IncludeSizedImplicitBounds, PredicateProxy, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, shift_vars, }; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{Span, bug, span_bug}; @@ -54,19 +54,13 @@ fn associated_type_bounds<'tcx>( | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { // Implicit bounds are added to associated types unless a `?Trait` bound is found. - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - item_ty, - hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, item_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::Yes, ); // Also collect `where Self::Assoc: Trait` from the parent trait's where clauses. @@ -381,19 +375,13 @@ fn opaque_type_bounds<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - item_ty, - hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, item_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::Yes, ); } //`ConstIfConst` is only interested in `[const]` bounds. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 0b7df89551da8..88924a9d6a98e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -10,8 +10,8 @@ use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::ty::{ - self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self as ty, IncludeSizedImplicitBounds, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_span::{ErrorGuaranteed, Ident, Span, bug, kw}; use rustc_trait_selection::traits; @@ -138,6 +138,29 @@ fn add_trait_bound<'tcx>( } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Adds implicit sizedness, and in the future `Move` and `Forget`, and default trait bounds. + pub(crate) fn add_implicit_bounds( + &self, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'_>], + context: ImpliedBoundsContext<'tcx>, + span: Span, + // Sized is treated slightly more specially than the other implicit bounds. + include_sized: IncludeSizedImplicitBounds, + ) { + // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` + if find_attr!(self.tcx(), crate, RustcNoImplicitBounds) { + return; + } + + self.add_default_traits(bounds, self_ty, hir_bounds, context, span); + + if let IncludeSizedImplicitBounds::Yes = include_sized { + self.add_implicit_sizedness_bounds(bounds, self_ty, hir_bounds, context, span); + } + } + /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. /// /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit @@ -146,7 +169,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// bounds are present. /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if /// a `?Sized` bound is present. - pub(crate) fn add_implicit_sizedness_bounds( + fn add_implicit_sizedness_bounds( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, @@ -156,11 +179,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { let tcx = self.tcx(); - // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` - if find_attr!(tcx, crate, RustcNoImplicitBounds) { - return; - } - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); @@ -208,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - pub(crate) fn add_default_traits( + fn add_default_traits( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, @@ -224,7 +242,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate. /// /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`. - pub(crate) fn add_default_trait( + fn add_default_trait( &self, trait_: LangItem, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, @@ -244,23 +262,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if let Some(trait_did) = tcx.lang_items().get(trait_) - && self.should_add_default_traits(trait_did, hir_bounds, context) + && !collect_bounds(hir_bounds, context, trait_did).any() { add_trait_bound(tcx, bounds, self_ty, trait_did, span); } } - /// Returns `true` if default trait bound should be added. - fn should_add_default_traits( - &self, - trait_def_id: DefId, - hir_bounds: &[hir::GenericBound<'_>], - context: ImpliedBoundsContext<'tcx>, - ) -> bool { - let collected = collect_bounds(hir_bounds, context, trait_def_id); - !find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any() - } - pub(crate) fn require_bound_to_relax_default_trait( &self, trait_ref: hir::TraitRef<'_>, @@ -269,7 +276,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res - && (tcx.is_lang_item(def_id, LangItem::Sized) || tcx.is_default_trait(def_id)) + && (tcx.is_lang_item(def_id, LangItem::Sized) + || tcx.is_implicit_trait(def_id, IncludeSizedImplicitBounds::No)) { return; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index c652174f9ba68..4a763e5b89316 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -9,8 +9,8 @@ use rustc_hir::{self as hir, HirId}; use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS}; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; use rustc_middle::ty::{ - self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, Upcast, + self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, IncludeSizedImplicitBounds, Ty, + TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{ErrorGuaranteed, Span}; @@ -75,7 +75,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - self.add_default_traits( + self.add_implicit_bounds( &mut user_written_bounds, dummy_self, &hir_bounds @@ -84,6 +84,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect::>(), ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::No, ); let (mut elaborated_trait_bounds, elaborated_projection_bounds) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5edf50d5cb33b..f15b8c81c51d2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -15,7 +15,7 @@ //! [^1]: This includes types, lifetimes / regions, constants in type positions, //! trait references and bounds. -mod bounds; +pub(crate) mod bounds; mod cmse; mod dyn_trait; pub mod errors; @@ -43,9 +43,9 @@ use rustc_lint_defs::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ - self, Const, FnSigKind, GenericArgKind, GenericParamDefKind, LitToConstInput, Ty, TyCtxt, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, const_lit_matches_ty, - fold_regions, + self, Const, FnSigKind, GenericArgKind, GenericParamDefKind, IncludeSizedImplicitBounds, + LitToConstInput, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, + Upcast, const_lit_matches_ty, fold_regions, }; use rustc_session::diagnostics::feature_err; use rustc_span::def_id::{LocalModId, ModId}; @@ -3326,12 +3326,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); - self.add_implicit_sizedness_bounds( + self.add_implicit_bounds( &mut bounds, self_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, hir_ty.span, + IncludeSizedImplicitBounds::Yes, ); self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); self_ty diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index f3cba3a27d69f..7ccd7eb435d03 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::adjustment::{ OverloadedDeref, PointerCoercion, }; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, span_bug, sym}; +use rustc_span::{Span, kw, span_bug, sym}; use tracing::debug; use crate::method::{MethodCallee, TreatNotYetDefinedOpaques}; @@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op); let (Some(imm_tr), imm_op) = (match op { - PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref), + PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), kw::Deref), PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index), }) else { // Bail if `Deref` or `Index` isn't defined. diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7df2ede5053b2..6dc3f74f054f1 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -36,7 +36,7 @@ use rustc_parse::lexer::StripTokens; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::{Resolver, ResolverOutputs}; -use rustc_session::config::{Input, OutFileName, OutputFilenames, OutputType}; +use rustc_session::config::{Input, Offload, OutFileName, OutputFilenames, OutputType}; use rustc_session::diagnostics::feature_err; use rustc_session::output::{filename_for_input, invalid_output_for_target}; use rustc_session::search_paths::PathKind; @@ -1485,6 +1485,16 @@ pub fn collect_crate_types( } } + // GPU code is never run as a binary; the offload runtime looks up kernels by + // name, and only cdylibs export their symbols. + if session.opts.unstable_opts.offload.iter().any(|o| matches!(o, Offload::Device(_))) { + for crate_type in &mut base { + if *crate_type == CrateType::Executable { + *crate_type = CrateType::Cdylib; + } + } + } + base.retain(|crate_type| { if invalid_output_for_target(session, *crate_type) { session.dcx().emit_warn(diagnostics::UnsupportedCrateTypeForTarget { diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 75552ab759fd5..12b52f4e2801e 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -1,7 +1,7 @@ use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; use rustc_lint_defs::{declare_lint, declare_lint_pass}; -use rustc_middle::ty::Unnormalized; +use rustc_middle::ty::{IncludeSizedImplicitBounds, Unnormalized}; use crate::{LateContext, LateLintPass, LintContext}; @@ -51,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .map(Unnormalized::skip_norm_wip) .filter_map(|(clause, _)| clause.as_trait_clause()) .filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), LangItem::MetaSized)) - .filter(|pred| !cx.tcx.is_default_trait(pred.def_id())); + .filter(|pred| { + !cx.tcx.is_implicit_trait(pred.def_id(), IncludeSizedImplicitBounds::No) + }); if direct_super_traits_iter.count() > 1 { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, diff --git a/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp index 5c0fabb3fcee8..6a51e58f896be 100644 --- a/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/offload/OffloadWrapper.cpp @@ -1,29 +1,22 @@ #include "../SuppressLLVMWarnings.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Frontend/Offloading/OffloadWrapper.h" #include "llvm/Frontend/Offloading/Utility.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/MC/TargetRegistry.h" -#include "llvm/Support/CodeGen.h" #include "llvm/Support/Error.h" -#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBufferRef.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -34,18 +27,6 @@ using namespace llvm; -static Error writeFile(StringRef Filename, StringRef Data) { - Expected> OutputOrErr = - FileOutputBuffer::create(Filename, Data.size()); - if (!OutputOrErr) - return OutputOrErr.takeError(); - std::unique_ptr Output = std::move(*OutputOrErr); - llvm::copy(Data, Output->getBufferStart()); - if (Error E = Output->commit()) - return E; - return Error::success(); -} - // Clone OldFn into NewFn, remapping its arguments to RebuiltArgs. // Each arg of OldFn is replaced with the corresponding value in RebuiltArgs. // For scalars, RebuiltArgs contains the value cast and/or truncated to the @@ -96,37 +77,44 @@ static bool reportAndFailWrappingImages(Error E, const char *What) { return false; } +/// Returns the target architecture (e.g. "sm_86") named by the `.target` +/// directive of the given PTX text. The result points into `PtxBuf`. +static Expected getPtxArch(MemoryBufferRef PtxBuf) { + const Regex TargetRe("^\\.target[[:space:]]+([^,[:space:]]+)", + Regex::Newline); + + SmallVector M; + if (!TargetRe.match(PtxBuf.getBuffer(), &M)) + return createStringError("no .target directive in %s", + PtxBuf.getBufferIdentifier().str().c_str()); + + return M[1]; +} + static Expected> -assembleWithPtxas(StringRef Ptx, StringRef Arch) { +assembleWithPtxas(MemoryBufferRef PtxBuf) { + Expected ArchOrErr = getPtxArch(PtxBuf); + if (!ArchOrErr) + return ArchOrErr.takeError(); + const ErrorOr Ptxas = sys::findProgramByName("ptxas"); if (!Ptxas) return createStringError(Ptxas.getError(), "ptxas not found in PATH"); - SmallString<128> PtxFilePath; - if (std::error_code E = - sys::fs::createTemporaryFile("rust-offload", "ptx", PtxFilePath)) - return errorCodeToError(E); - SmallString<128> CubinFilePath; if (std::error_code E = sys::fs::createTemporaryFile("rust-offload", "cubin", CubinFilePath)) return errorCodeToError(E); auto Cleanup = scope_exit([&] { - if (std::error_code E = sys::fs::remove(PtxFilePath)) - (void)reportAndFailWrappingImages( - errorCodeToError(E), "assembleWithPtxas: PtxFilePath cleanup"); if (std::error_code E = sys::fs::remove(CubinFilePath)) (void)reportAndFailWrappingImages( errorCodeToError(E), "assembleWithPtxas: CubinFilePath cleanup"); }); - if (Error E = writeFile(PtxFilePath, Ptx)) - return std::move(E); - const StringRef Args[] = { - *Ptxas, "-m64", "-O3", "--gpu-name", - Arch, "--output-file", CubinFilePath, PtxFilePath, + *Ptxas, "-m64", "-O3", "--gpu-name", + *ArchOrErr, "--output-file", CubinFilePath, PtxBuf.getBufferIdentifier(), }; std::string ErrorMsg; @@ -145,130 +133,37 @@ assembleWithPtxas(StringRef Ptx, StringRef Arch) { return std::move(*CubinOrError); } -static Expected> -linkWithRustLld(StringRef Obj, StringRef LldPath) { - SmallString<128> ObjFilePath; - if (std::error_code E = - sys::fs::createTemporaryFile("rust-offload", "o", ObjFilePath)) - return errorCodeToError(E); - - SmallString<128> SoFilePath; - if (std::error_code E = - sys::fs::createTemporaryFile("rust-offload", "so", SoFilePath)) - return errorCodeToError(E); - - auto Cleanup = scope_exit([&] { - if (std::error_code E = sys::fs::remove(ObjFilePath)) - (void)reportAndFailWrappingImages(errorCodeToError(E), - "linkWithRustLld: ObjFilePath cleanup"); - if (std::error_code E = sys::fs::remove(SoFilePath)) - (void)reportAndFailWrappingImages(errorCodeToError(E), - "linkWithRustLld: SoFilePath cleanup"); - }); - - if (Error E = writeFile(ObjFilePath, Obj)) - return std::move(E); - - const StringRef Args[] = { - LldPath, "-flavor", "gnu", "-shared", - "--no-undefined", "-o", SoFilePath, ObjFilePath, - }; - - std::string ErrorMsg; - const int Status = - sys::ExecuteAndWait(LldPath, Args, std::nullopt, {}, 0, 0, &ErrorMsg); - - if (Status != 0) - return createStringError("linkWithRustLld: status %d: %s", Status, - ErrorMsg.c_str()); - - ErrorOr> ElfOrError = - MemoryBuffer::getFileAsStream(SoFilePath); - if (!ElfOrError) - return errorCodeToError(ElfOrError.getError()); - - return std::move(*ElfOrError); -} - -static Expected> -compileDeviceImage(MemoryBufferRef Input, const char *LldPath) { - LLVMContext Ctx; - Expected> ModOrErr = parseBitcodeFile(Input, Ctx); - if (!ModOrErr) - return ModOrErr.takeError(); - Module &M = **ModOrErr; - - const Triple &DeviceTriple = M.getTargetTriple(); - StringRef Arch; - for (Function &F : M) - if (F.hasFnAttribute("target-cpu")) { - Arch = F.getFnAttribute("target-cpu").getValueAsString(); - break; - } - - if (Arch.empty()) - return createStringError("no target-cpu attribute in device bitcode"); - - std::string ErrorMsg; - const Target *DeviceTarget = - TargetRegistry::lookupTarget(DeviceTriple, ErrorMsg); - if (!DeviceTarget) - return createStringError(ErrorMsg); - - std::unique_ptr TM(DeviceTarget->createTargetMachine( - DeviceTriple, Arch, /*Features=*/"", TargetOptions(), Reloc::PIC_)); - if (!TM) - return createStringError("createTargetMachine failed for %s", - DeviceTriple.str().c_str()); - - const bool IsNvptx = DeviceTriple.isNVPTX(); - - legacy::PassManager PM; - SmallString<0> Emitted; - raw_svector_ostream OS(Emitted); - const CodeGenFileType FileType = - IsNvptx ? CodeGenFileType::AssemblyFile : CodeGenFileType::ObjectFile; - if (TM->addPassesToEmitFile(PM, OS, nullptr, FileType)) - return createStringError("target %s cannot emit %s", - DeviceTriple.str().c_str(), - IsNvptx ? "assembly" : "object"); - - PM.run(**ModOrErr); - - if (IsNvptx) - return assembleWithPtxas(Emitted, Arch); - if (DeviceTriple.isAMDGPU()) { - if (!LldPath || !*LldPath) - return createStringError("rust-lld path was not provided for %s", - DeviceTriple.str().c_str()); - return linkWithRustLld(Emitted, LldPath); - } - - return createStringError("unsupported offload target %s", - DeviceTriple.str().c_str()); -} - extern "C" bool LLVMRustOffloadWrapImages(LLVMModuleRef HostMRef, - const char *LldPath, - const char *DeviceBitcodePath) { + const char *DeviceImagePath) { Module &M = *unwrap(HostMRef); if (!hasOffloadEntries(M)) return true; ErrorOr> BufOrErr = - MemoryBuffer::getFile(DeviceBitcodePath); + MemoryBuffer::getFile(DeviceImagePath); if (std::error_code EC = BufOrErr.getError()) - return reportAndFailWrappingImages(createFileError(DeviceBitcodePath, EC), - "device bitcode"); + return reportAndFailWrappingImages(createFileError(DeviceImagePath, EC), + "device image"); std::unique_ptr Buf = std::move(*BufOrErr); - Expected> ImageOrErr = - compileDeviceImage(Buf->getMemBufferRef(), LldPath); - if (!ImageOrErr) - return reportAndFailWrappingImages(ImageOrErr.takeError(), - "device compile"); + std::unique_ptr DeviceImage; + StringRef Ext = sys::path::extension(DeviceImagePath); + if (Ext == ".ptx") { + Expected> CubinOrErr = + assembleWithPtxas(Buf->getMemBufferRef()); + if (!CubinOrErr) + return reportAndFailWrappingImages(CubinOrErr.takeError(), "ptxas"); + DeviceImage = std::move(*CubinOrErr); + } else if (Ext == ".elf") { + DeviceImage = std::move(Buf); + } else { + return reportAndFailWrappingImages( + createStringError("unsupported device image %s: expected .ptx or .elf", + DeviceImagePath), + "device image path"); + } - StringRef ImageBuf = (*ImageOrErr)->getBuffer(); + StringRef ImageBuf = DeviceImage->getBuffer(); ArrayRef Image(ImageBuf.data(), ImageBuf.size()); if (Error E = offloading::wrapOpenMPBinaries( diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index c583383414392..f7bfc78fa825a 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -384,10 +384,8 @@ impl<'tcx> GlobalAlloc<'tcx> { // Take over-alignment from attributes into account. let align = match tcx.codegen_fn_attrs(def_id).alignment { - Some(align_from_attribute) => { - Ord::max(align_from_attribute, layout.align.abi) - } - None => layout.align.abi, + Some(align_from_attribute) => Ord::max(align_from_attribute, layout.align), + None => layout.align, }; (layout.size, align) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3b96713305337..976512fba3f53 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -48,7 +48,8 @@ use rustc_structures::{CrateType, Limit}; use rustc_type_ir::TyKind::*; pub use rustc_type_ir::lift::Lift; use rustc_type_ir::{ - CollectAndApply, PlaceholderType, WithCachedTypeInfo, elaborate, search_graph, + CollectAndApply, IncludeSizedImplicitBounds, PlaceholderType, WithCachedTypeInfo, elaborate, + search_graph, }; use tracing::{debug, instrument}; @@ -955,6 +956,18 @@ impl<'tcx> TyCtxt<'tcx> { self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait)) } + /// Returns true if a trait is an "implicit trait", which is a trait which is added + /// to bounds on generic types automatically by the compiler. + pub fn is_implicit_trait( + self, + def_id: DefId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool { + self.is_default_trait(def_id) + // NOTE: add move and forget here later + || (matches!(including_sized, IncludeSizedImplicitBounds::Yes) && self.is_sizedness_trait(def_id)) + } + pub fn is_sizedness_trait(self, def_id: DefId) -> bool { matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized)) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index eb81ea291759b..c62bdcebec389 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -12,8 +12,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol, bug}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, - VisitorResult, WithCachedTypeInfo, search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, IncludeSizedImplicitBounds, Interner, RegionVid, + TypeFoldable, Unnormalized, VisitorResult, WithCachedTypeInfo, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -527,6 +527,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_default_trait(def_id) } + fn is_implicit_trait( + self, + def_id: Self::TraitId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool { + self.is_implicit_trait(def_id, including_sized) + } + fn is_sizedness_trait(self, def_id: DefId) -> bool { self.is_sizedness_trait(def_id) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3d560a9f18815..398633cb3311c 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -141,7 +141,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0 + self.instantiate_bound_regions_uncached(value, |_| self.lifetimes.re_erased) } /// Anonymize all bound variables in `value`, this is mostly used to improve caching. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 770bed217cdd6..ce1c36c5468a8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -387,7 +387,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let err = match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) => { if layout.is_sized() { - return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi))); + return Ok(SizeSkeleton::Known(layout.size, Some(layout.align))); } else { // Just to be safe, don't claim a known layout for unsized types. return Err(tcx.arena.alloc(LayoutError::Unknown(ty))); @@ -1098,7 +1098,7 @@ where } }; - PointeeInfo { safe: Some(kind), size, align: layout.align.abi } + PointeeInfo { safe: Some(kind), size, align: layout.align } }) } @@ -1116,7 +1116,7 @@ where PointeeInfo { safe: Some(PointerKind::Box { unpin, global: this.ty.is_box_global(tcx) }), size, - align: layout.align.abi, + align: layout.align, } }) } diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d116806fc0b73..a8ae60b4daba7 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, sym}; +use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, kw, sym}; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -343,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, ) { let (trait_item, method) = match mutability { - Mutability::Not => (LangItem::Deref, sym::deref), + Mutability::Not => (LangItem::Deref, kw::Deref), Mutability::Mut => (LangItem::DerefMut, sym::deref_mut), }; let borrow_kind = super::util::ref_pat_borrow_kind(mutability); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6519c2770c1fb..b29bf5636f66c 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1959,9 +1959,9 @@ fn op_to_prop_const<'tcx>( if let GlobalAlloc::Memory(alloc) = ecx.tcx.global_alloc(alloc_id) // Transmuting a constant is just an offset in the allocation. If the alignment of the // allocation is not enough, fallback to copying into a properly aligned value. - && alloc.inner().align >= op.layout.align.abi + && alloc.inner().align >= op.layout.align // If this is a packed field the offset must also be sufficiently aligned. - && offset.bytes().is_multiple_of(op.layout.align.abi.bytes()) + && offset.bytes().is_multiple_of(op.layout.align.bytes()) { return Some(ConstValue::Indirect { alloc_id, offset }); } diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 569fbd41e1b22..6b159074493f9 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -26,13 +26,15 @@ const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits( .unwrap(); #[derive(Debug, Clone, Copy)] -enum CanonicalizeInputKind { +enum CanonicalizeInputKind { /// When canonicalizing the `param_env`, we keep `'static` as merging /// trait candidates relies on it when deciding whether a where-bound /// is trivial. ParamEnv, /// When canonicalizing predicates, we don't keep `'static`. - Predicate, + /// `param_env_var_kinds` caches the interned variable kinds to be + /// reused if there are no new vars. + Predicate { param_env_var_kinds: Option }, } /// Whether we're canonicalizing a query input or the query response. @@ -41,8 +43,8 @@ enum CanonicalizeInputKind { /// while canonicalizing the response happens in the context of the /// query. #[derive(Debug, Clone, Copy)] -enum CanonicalizeMode { - Input(CanonicalizeInputKind), +enum CanonicalizeMode { + Input(CanonicalizeInputKind), /// FIXME: We currently return region constraints referring to /// placeholders and inference variables from a binder instantiated /// inside of the query. @@ -68,14 +70,14 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner delegate: &'a D, // Immutable field. - canonicalize_mode: CanonicalizeMode, + canonicalize_mode: CanonicalizeMode, // Mutable fields. state: Box>, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { - fn new(delegate: &'a D, canonicalize_mode: CanonicalizeMode) -> Self { + fn new(delegate: &'a D, canonicalize_mode: CanonicalizeMode) -> Self { Canonicalizer { delegate, canonicalize_mode, state: delegate.obtain_canonicalizer_state() } } @@ -105,15 +107,18 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { if !param_env.has_type_flags(NEEDS_CANONICAL) { let rest_canonicalizer = Canonicalizer::new( delegate, - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate), + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: None, + }), ); return (param_env, rest_canonicalizer); } // Do the `env` canonicalization, and then convert the canonicalizer to `rest` form for - // subsequent use. - let do_env_and_make_rest = || { + // subsequent use, also returning the optionally interned (i.e., uniquely identified) + // canonicalized variable kind list in case cache is used, so it can also be cached. + let do_env_and_make_rest = |intern_var_kinds: bool| { let mut env_canonicalizer = Canonicalizer::new( delegate, CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv), @@ -133,12 +138,17 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // // We clear the cache rather than deleting it or replacing it with an empty cache. This // lets the allocated capacity be reused later. - let mut rest_canonicalizer = env_canonicalizer; - rest_canonicalizer.canonicalize_mode = - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate); + let param_env_var_kinds = intern_var_kinds + .then(|| delegate.cx().mk_canonical_var_kinds(&env_canonicalizer.state.var_kinds)); + let mut rest_canonicalizer = Canonicalizer { + canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds, + }), + ..env_canonicalizer + }; rest_canonicalizer.state.cache.clear(); - (param_env, rest_canonicalizer) + (param_env, rest_canonicalizer, param_env_var_kinds) }; // Check whether we can use the global cache for this param_env. As we only use @@ -153,11 +163,11 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { Entry::Vacant(e) => { // Cache miss. Do `env` canonicalization and get `rest_canonicalizer`, and // fill in the cache entry. - let (param_env, rest_canonicalizer) = do_env_and_make_rest(); + let (param_env, rest_canonicalizer, var_kinds) = do_env_and_make_rest(true); e.insert(CanonicalParamEnvCacheEntry { param_env, variables: rest_canonicalizer.state.variables.clone(), - var_kinds: rest_canonicalizer.state.var_kinds.clone(), + var_kinds: var_kinds.unwrap(), // SAFETY: The iterated elements go straight back into a hashmap. #[allow(rustc::potential_query_instability)] variable_lookup_table: rest_canonicalizer @@ -174,10 +184,12 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let e = e.get(); let mut rest_canonicalizer = Canonicalizer::new( delegate, - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate), + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: Some(e.var_kinds), + }), ); rest_canonicalizer.state.variables.clone_from(&e.variables); - rest_canonicalizer.state.var_kinds.clone_from(&e.var_kinds); + e.var_kinds.as_slice().clone_into(&mut rest_canonicalizer.state.var_kinds); rest_canonicalizer .state .variable_lookup_table @@ -187,7 +199,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }) } else { // Do `env` canonicalization and get `rest_canonicalizer`. - do_env_and_make_rest() + let (param_env, rest_canonicalizer, _) = do_env_and_make_rest(false); + (param_env, rest_canonicalizer) } } @@ -278,7 +291,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // during canonicalization in the new solver. let max_universe = match self.canonicalize_mode { // All placeholders and vars are canonicalized in the root universe. - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { debug_assert!( self.state .var_kinds @@ -309,7 +322,15 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { .unwrap_or(ty::UniverseIndex::ROOT) } }; - let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&self.state.var_kinds); + let var_kinds = match self.canonicalize_mode { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: Some(cached), + }) if cached.len() == self.state.variables.len() => { + debug_assert_eq!(cached.as_slice(), self.state.var_kinds.as_slice()); + cached + } + _ => self.delegate.cx().mk_canonical_var_kinds(&self.state.var_kinds), + }; // We have finished with this canonicalizer and can return its state to the delegate for // later reuse. @@ -330,7 +351,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let sub_root = self.get_or_insert_sub_root(vid); let ui = match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT, + CanonicalizeMode::Input(_) => ty::UniverseIndex::ROOT, CanonicalizeMode::Response { .. } => self .delegate .universe_of_ty(vid) @@ -359,7 +380,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } }, ty::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -368,7 +389,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -429,7 +450,7 @@ impl, I: Interner> TypeFolder for Canonicaliz // We don't canonicalize `ReStatic` in the `param_env` as we use it // when checking whether a `ParamEnv` candidate is global. ty::ReStatic => match self.canonicalize_mode { - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { .. }) => { CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -541,7 +562,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ); match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::Const(ty::UniverseIndex::ROOT) } CanonicalizeMode::Response { .. } => { @@ -552,7 +573,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => unimplemented!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -563,7 +584,7 @@ impl, I: Interner> TypeFolder for Canonicaliz } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -592,7 +613,7 @@ impl, I: Interner> TypeFolder for Canonicaliz match self.canonicalize_mode { CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) | CanonicalizeMode::Response { max_input_universe: _ } => {} - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { .. }) => { panic!("erasing 'static in env") } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 5ae19b2eb6935..685897188a6bf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -10,9 +10,9 @@ use rustc_type_ir::solve::{ QueryResultOrRerunNonErased, RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, }; use rustc_type_ir::{ - self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability, - Region, TraitClause, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, - elaborate, + self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, IncludeSizedImplicitBounds, + Interner, MayBeErased, Movability, Region, TraitClause, TraitRef, TypeVisitableExt as _, + TypingMode, Unnormalized, Upcast as _, elaborate, }; use tracing::{debug, instrument, trace, warn}; @@ -1413,7 +1413,13 @@ where // Backward compatibility for default auto traits. // Test: ui/traits/default_auto_traits/extern-types.rs - ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(), + ty::Foreign(..) + if self + .cx() + .is_implicit_trait(goal.predicate.def_id(), IncludeSizedImplicitBounds::No) => + { + check_impls() + } // These types cannot be structurally decomposed into constituent // types, and therefore have no built-in auto impl. diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index ab220cc56a9e0..72947b1c576c8 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -4079,21 +4079,6 @@ impl IntoDiagArg for Case { } } -#[derive(Diagnostic)] -#[diag("unknown `builtin #` construct `{$name}`")] -pub(crate) struct UnknownBuiltinConstruct { - #[primary_span] - pub span: Span, - pub name: Ident, -} - -#[derive(Diagnostic)] -#[diag("expected identifier after `builtin #`")] -pub(crate) struct ExpectedBuiltinIdent { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("static items may not have generic parameters")] pub(crate) struct StaticWithGenerics { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 84aa391590041..e8c4ee4aae0f2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1315,8 +1315,6 @@ impl<'a> Parser<'a> { }) } else if this.check(exp!(OpenBracket)) { this.parse_expr_array_or_repeat(exp!(CloseBracket)) - } else if this.is_builtin() { - this.parse_expr_builtin() } else if this.check_path() { this.parse_expr_path_start() } else if this.token.is_keyword(kw::Move) @@ -1385,6 +1383,14 @@ impl<'a> Parser<'a> { return Ok(expr); } Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) + } else if this.eat_forced_keyword_noexpect(kw::OffsetOf) { + this.parse_expr_offset_of(lo) + } else if this.eat_forced_keyword_noexpect(kw::TypeAscribe) { + this.parse_expr_type_ascribe(lo) + } else if this.eat_forced_keyword_noexpect(kw::WrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap) + } else if this.eat_forced_keyword_noexpect(kw::UnwrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap) } else if this.token_uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. let at_async = this.check_keyword(exp!(Async)); @@ -1826,58 +1832,9 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - /// Parse `builtin # ident(args,*)`. - fn parse_expr_builtin(&mut self) -> PResult<'a, Box> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::offset_of => Some(this.parse_expr_offset_of(lo)?), - sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?), - sym::wrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?) - } - sym::unwrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?) - } - _ => None, - }) - }) - } - - pub(crate) fn parse_builtin( - &mut self, - parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option>, - ) -> PResult<'a, T> { - let lo = self.token.span; - - self.bump(); // `builtin` - self.bump(); // `#` - - let Some((ident, IdentKind::Normal)) = self.token.ident() else { - let err = self - .dcx() - .create_err(crate::diagnostics::ExpectedBuiltinIdent { span: self.token.span }); - return Err(err); - }; - self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); - self.bump(); - + pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { self.expect(exp!(OpenParen))?; - let ret = if let Some(res) = parse(self, lo, ident)? { - Ok(res) - } else { - let err = self.dcx().create_err(crate::diagnostics::UnknownBuiltinConstruct { - span: lo.to(ident.span), - name: ident, - }); - return Err(err); - }; - self.expect(exp!(CloseParen))?; - - ret - } - /// Built-in macro for `offset_of!` expressions. - pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -1900,16 +1857,26 @@ impl<'a> Parser<'a> { } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields))) } - /// Built-in macro for type ascription expressions. pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; let expr = self.parse_expr()?; self.expect(exp!(Comma))?; let ty = self.parse_ty()?; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::Type(expr, ty))) } @@ -1918,9 +1885,15 @@ impl<'a> Parser<'a> { lo: Span, kind: UnsafeBinderCastKind, ) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; + let expr = self.parse_expr()?; let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None }; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty))) } @@ -3423,10 +3396,6 @@ impl<'a> Parser<'a> { Ok(expr) } - pub(crate) fn is_builtin(&self) -> bool { - self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound) - } - /// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten). fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box> { let annotation = diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bc74ff14a1b3a..27646bac1c21e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -354,9 +354,6 @@ impl<'a> Parser<'a> { // UNION ITEM self.bump(); // `union` self.parse_item_union()? - } else if self.is_builtin() { - // BUILTIN# ITEM - return self.parse_item_builtin(); } else if self.eat_keyword_case(exp!(Macro), case) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? @@ -599,11 +596,6 @@ impl<'a> Parser<'a> { if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } - fn parse_item_builtin(&mut self) -> PResult<'a, Option> { - // To be expanded - Ok(None) - } - /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index fb26ef5e8ace6..a89fd9b6298f3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -630,6 +630,15 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) } } + #[must_use] + pub(crate) fn eat_forced_keyword_noexpect(&mut self, kw: Symbol) -> bool { + if self.token.is_forced_keyword(kw) { + self.bump(); + return true; + } + false + } + /// Consume a sequence produced by a metavar expansion, if present. pub fn eat_metavar_seq( &mut self, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9fd38aa0f3b8f..422e3cbfd082e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -801,8 +801,17 @@ impl<'a> Parser<'a> { } else { PatKind::Expr(const_expr) } - } else if self.is_builtin() { - self.parse_pat_builtin()? + } else if self.eat_forced_keyword_noexpect(kw::Deref) { + self.expect(exp!(OpenParen))?; + let pat = ast::PatKind::Deref(Box::new(self.parse_pat_allow_top_guard( + None, + RecoverComma::Yes, + RecoverColon::Yes, + CommaRecoveryMode::LikelyTuple, + )?)); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + pat } // Don't eagerly error on semantically invalid tokens when matching // declarative macros, as the input to those doesn't have to be @@ -1608,23 +1617,6 @@ impl<'a> Parser<'a> { .contains(&self.token.kind) } - fn parse_pat_builtin(&mut self) -> PResult<'a, PatKind> { - self.parse_builtin(|self_, _lo, ident| { - Ok(match ident.name { - // builtin#deref(PAT) - sym::deref => { - Some(ast::PatKind::Deref(Box::new(self_.parse_pat_allow_top_guard( - None, - RecoverComma::Yes, - RecoverColon::Yes, - CommaRecoveryMode::LikelyTuple, - )?))) - } - _ => None, - }) - }) - } - // FIXME: remove this entirely eventually /// Parses the removed `box pat` syntax to provide a more helpful error message. fn parse_pat_box(&mut self) -> PResult<'a, PatKind> { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 49bcdbbe8fa57..df2df24854ee1 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -126,11 +126,7 @@ impl<'a> Parser<'a> { diagnostics::InvalidVariableDeclarationSub::UseLetNotVar, force_collect, )? - } else if self.check_path() - && !self.token.is_qpath_start() - && !self.is_path_start_item() - && !self.is_builtin() - { + } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something // that starts like a path (1 token), but it fact not a path. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index e2187612f5d20..b66d7310dbea5 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -326,8 +326,6 @@ impl<'a> Parser<'a> { self.parse_borrowed_pointee()? } else if self.eat_keyword_noexpect(kw::Typeof) { self.parse_typeof_ty(lo)? - } else if self.is_builtin() { - self.parse_builtin_ty()? } else if self.eat_keyword(exp!(Underscore)) { // A type to be inferred `_` TyKind::Infer @@ -423,6 +421,8 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |tok| tok.kind == token::Lt) { self.parse_unsafe_binder_ty()? + } else if self.eat_forced_keyword_noexpect(kw::FieldOf) { + self.parse_ty_field_of(lo)? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(lo, msg); @@ -826,16 +826,9 @@ impl<'a> Parser<'a> { Ok(TyKind::Err(guar)) } - fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::field_of => Some(this.parse_ty_field_of(lo)?), - _ => None, - }) - }) - } + pub(crate) fn parse_ty_field_of(&mut self, lo: Span) -> PResult<'a, TyKind> { + self.expect(exp!(OpenParen))?; - pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -844,30 +837,36 @@ impl<'a> Parser<'a> { if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) { if trailing_comma { - e.note("unexpected third argument to field_of"); + e.note("unexpected third argument to `field_of`"); } else { - e.note("field_of expects dot-separated field and variant names"); + e.note("`field_of` expects dot-separated field and variant names"); } e.emit(); } - // Eat tokens until the macro call ends. + // Eat tokens until the construct ends. if self.may_recover() { while !self.token.kind.is_close_delim_or_eof() { self.bump(); } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. + let span = self.token.span; + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + match *fields { - [] => Err(self.dcx().struct_span_err( - self.token.span, - "`field_of!` expects dot-separated field and variant names", - )), + [] => Err(self + .dcx() + .struct_span_err(span, "`field_of` expects dot-separated field and variant names")), [field] => Ok(TyKind::FieldOf(container, None, field)), [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)), _ => Err(self.dcx().struct_span_err( fields.iter().map(|f| f.span).collect::>(), - "`field_of!` only supports a single field or a variant with a field", + "`field_of` only supports a single field or a variant with a field", )), } } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 31490a49b695c..82ef182301cf4 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -68,7 +68,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, kinds: &[RustcDumpLa Ok(ty_layout) => { for kind in kinds { let message = match kind { - RustcDumpLayoutKind::Align => format!("align: {:?}", *ty_layout.align), + RustcDumpLayoutKind::Align => format!("align: {:?}", ty_layout.align), RustcDumpLayoutKind::BackendRepr => { format!("backend_repr: {:?}", ty_layout.backend_repr) } diff --git a/compiler/rustc_public/src/alloc.rs b/compiler/rustc_public/src/alloc.rs index 0c35b3b25dfc0..768dfd3128021 100644 --- a/compiler/rustc_public/src/alloc.rs +++ b/compiler/rustc_public/src/alloc.rs @@ -53,7 +53,7 @@ pub(crate) fn try_new_allocation<'tcx>( ConstValue::Scalar(scalar) => { alloc::try_new_scalar(layout, scalar, cx).map(|alloc| alloc.stable(tables, cx)) } - ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)), + ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align)), ConstValue::Slice { alloc_id, meta } => { alloc::try_new_slice(layout, alloc_id, meta, cx).map(|alloc| alloc.stable(tables, cx)) } diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index a5e7302e9a4c7..45f3fa26ccc1b 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -75,7 +75,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData( cx: &CompilerCtxt<'tcx, B>, ) -> Result { let size = scalar.size(); - let mut allocation = Allocation::new(size, layout.align.abi, AllocInit::Uninit, ()); + let mut allocation = Allocation::new(size, layout.align, AllocInit::Uninit, ()); allocation .write_scalar(&cx.tcx, alloc_range(Size::ZERO, size), scalar) .map_err(|e| B::Error::from_internal(e))?; @@ -45,7 +45,7 @@ pub fn try_new_slice<'tcx, B: Bridge>( let ptr = Pointer::new(alloc_id.into(), Size::ZERO); let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx); let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx); - let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ()); + let mut allocation = Allocation::new(layout.size, layout.align, AllocInit::Uninit, ()); let ptr_size = cx.tcx.data_layout.pointer_size(); allocation .write_scalar(&cx.tcx, alloc_range(Size::ZERO, ptr_size), scalar_ptr) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6f078fef4892b..6c0a9cab34f8e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -125,17 +125,22 @@ symbols! { // Matching predicates: `is_weak` // tidy-alphabetical-start Auto: "auto", - Builtin: "builtin", Catch: "catch", ContractEnsures: "contract_ensures", ContractRequires: "contract_requires", Default: "default", + Deref: "deref", + FieldOf: "field_of", MacroRules: "macro_rules", + OffsetOf: "offset_of", Pin: "pin", Raw: "raw", Reuse: "reuse", Safe: "safe", + TypeAscribe: "type_ascribe", Union: "union", + UnwrapBinder: "unwrap_binder", + WrapBinder: "wrap_binder", Yeet: "yeet", // tidy-alphabetical-end } @@ -580,7 +585,6 @@ symbols! { bridge, bswap, built, - builtin_syntax, bundle, c_dash_variadic, c_str_literals, @@ -828,7 +832,6 @@ symbols! { deprecated, deprecated_safe, deprecated_suggestion, - deref, deref_method, deref_mut, deref_patterns, @@ -990,7 +993,6 @@ symbols! { field, field_base, field_init_shorthand, - field_of, field_offset, field_projections, field_representing_type, @@ -1173,6 +1175,7 @@ symbols! { integral, internal_eq_trait_method_impls, internal_features, + internal_syntax, interrupt, into_async_iter_into_iter, into_future, @@ -1507,7 +1510,6 @@ symbols! { offload_kernel, offload_region, offset, - offset_of, offset_of_enum, offset_of_nested, offset_of_slice, @@ -2204,7 +2206,6 @@ symbols! { ty, type_alias_enum_variants, type_alias_impl_trait, - type_ascribe, type_ascription, type_changing_struct_update, type_id, @@ -2333,7 +2334,6 @@ symbols! { unwind_attributes, unwind_safe_trait, unwrap, - unwrap_binder, unwrap_or, update, use_cloned, @@ -2419,7 +2419,6 @@ symbols! { windows, windows_subsystem, with_negative_coherence, - wrap_binder, wrapping_add, wrapping_div, wrapping_mul, diff --git a/compiler/rustc_target/src/callconv/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs index 9e78de4b229b9..be7420b3ac32b 100644 --- a/compiler/rustc_target/src/callconv/aarch64.rs +++ b/compiler/rustc_target/src/callconv/aarch64.rs @@ -145,7 +145,7 @@ where // See: arg.layout.unadjusted_abi_align } else { - arg.layout.align.abi + arg.layout.align }; if size.bits() <= 128 { if align.bits() == 128 { diff --git a/compiler/rustc_target/src/callconv/mips.rs b/compiler/rustc_target/src/callconv/mips.rs index 3cce9095bd847..720d17d5dbf99 100644 --- a/compiler/rustc_target/src/callconv/mips.rs +++ b/compiler/rustc_target/src/callconv/mips.rs @@ -52,7 +52,7 @@ where return; } let dl = cx.data_layout(); - let align = arg.layout.align.abi.max(dl.i32_align).min(dl.i64_align); + let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align); if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { arg.make_indirect(); diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 196d68389ac72..8c141bc7de616 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -114,7 +114,7 @@ where let mut prefix = ArrayVec::new(); // Detect need for padding - let align = Ord::clamp(arg.layout.align.abi, dl.i64_align, dl.i128_align); + let align = Ord::clamp(arg.layout.align, dl.i64_align, dl.i128_align); let pad_i32 = u8::from(!offset.is_aligned(align)); if !arg.layout.is_aggregate() { diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 635f4e5b0e226..8d76fa6dbf9cf 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -436,7 +436,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { .set(ArgAttribute::NoUndef) .set(ArgAttribute::NoFree); attrs.pointee_size = layout.size; - attrs.pointee_align = Some(layout.align.abi); + attrs.pointee_align = Some(layout.align); if layout.is_unsized() { PassMode::IndirectUnsized { attrs, meta_attrs: ArgAttributes::new() } diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index 61a0ae982d050..00b9ef25e9fbc 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -118,7 +118,7 @@ fn classify_arg<'a, Ty, C>( // arguments to be inserted where necessary to ensure that 16-aligned arguments are passed in an // aligned set of registers. - let pad = !total_double_word_count.is_multiple_of(2) && arg.layout.align.abi.bytes() == 16; + let pad = !total_double_word_count.is_multiple_of(2) && arg.layout.align.bytes() == 16; // The number of double words used by this argument. let double_word_count = arg.layout.size.bytes_usize().div_ceil(8); // The number of double words before this argument, including any padding. diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index fdfcbec18eb95..d19f3f0db715b 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -143,7 +143,7 @@ where } } - let byval_align = if arg.layout.align.abi < align_4 { + let byval_align = if arg.layout.align < align_4 { // (1.) align_4 } else if t.is_like_darwin && contains_vector(cx, arg.layout) { diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index 98f3a626155a8..e495afc803b2d 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -44,7 +44,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if !off.is_aligned(layout.align.abi) { + if !off.is_aligned(layout.align) { if !layout.is_zst() { return Err(Memory); } diff --git a/compiler/rustc_target/src/callconv/x86_win32.rs b/compiler/rustc_target/src/callconv/x86_win32.rs index 9303711b7f6ad..cddb6cd5d9b03 100644 --- a/compiler/rustc_target/src/callconv/x86_win32.rs +++ b/compiler/rustc_target/src/callconv/x86_win32.rs @@ -71,9 +71,9 @@ pub(crate) fn compute_abi_info<'a, Ty, C>( // on stack (via `byval`). For example, this includes `double`, `int64_t`, // and structs containing them, provided they lack an explicit alignment attribute. assert!( - arg.layout.align.abi >= max_repr_align, + arg.layout.align >= max_repr_align, "abi alignment {:?} less than requested alignment {max_repr_align:?}", - arg.layout.align.abi, + arg.layout.align, ); arg.make_indirect(); } else if arg.layout.is_aggregate() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index a0e1267ed16e1..d4ff3af28ed7f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -66,8 +66,8 @@ use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; use rustc_middle::ty::{ - self, List, Mutability, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, Unnormalized, + self, IsRigid, List, Mutability, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, Unnormalized, }; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, bug, sym}; use thin_vec::ThinVec; @@ -2479,6 +2479,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. + /// Non-rigid aliases are treated just like TyVar since normalization can be ambiguous here. pub fn same_type_modulo_infer>>(&self, a: T, b: T) -> bool { let (a, b) = self.deeply_resolve_ignoring_regions((a, b)); SameTypeModuloInfer(self).relate(a, b).is_ok() @@ -2528,7 +2529,9 @@ impl<'tcx> TypeRelation> for SameTypeModuloInfer<'_, 'tcx> { ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)), ) | (ty::Infer(ty::InferTy::TyVar(_)), _) - | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a), + | (_, ty::Infer(ty::InferTy::TyVar(_))) + | (ty::Alias(IsRigid::No, _), _) + | (_, ty::Alias(IsRigid::No, _)) => Ok(a), (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch), _ => relate::structurally_relate_tys(self, a, b), } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c55c43e18d2bf..be07ff71ccf34 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -33,7 +33,7 @@ use thin_vec::{ThinVec, thin_vec}; use super::inspect::InferCtxtProofTreeExt; use crate::solve::inspect::{self, InspectConfig, ProofTreeVisitor}; -use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph}; +use crate::traits::{EvaluateConstErr, ObligationCause, implicit_fast_path, specialization_graph}; #[repr(transparent)] pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>); @@ -178,7 +178,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< match self.0.tcx.as_lang_item(trait_pred.def_id()) { Some(LangItem::Sized) | Some(LangItem::MetaSized) => { let predicate = self.deeply_resolve_ignoring_regions(goal.predicate); - if sizedness_fast_path(self.tcx, predicate, goal.param_env) { + if implicit_fast_path(self.tcx, predicate, goal.param_env) { Outcome::TriviallyHolds } else { Outcome::NoFastPath diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3a1ad2ee5feab..56e80958e6892 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -33,7 +33,7 @@ use crate::infer::InferCtxt; use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{EvaluateConstErr, sizedness_fast_path}; +use crate::traits::{EvaluateConstErr, implicit_fast_path}; pub(crate) type PendingPredicateObligations<'tcx> = ThinVec>; @@ -398,7 +398,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; if !infcx.disable_trait_solver_fast_paths() - && sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) + && implicit_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) { return ProcessResult::Changed(thin_vec![]); } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 7076ec99c141c..326710007564c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -66,7 +66,7 @@ pub use self::specialize::{ pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final, - sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, + implicit_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars, }; use crate::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 148f75e0a6308..b8c2a3078e8cb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use crate::infer::InferCtxt; use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse}; -use crate::traits::{ObligationCtxt, sizedness_fast_path}; +use crate::traits::{ObligationCtxt, implicit_fast_path}; impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { type QueryResponse = (); @@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { infcx: &InferCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if sizedness_fast_path(infcx.tcx, key.value.predicate, key.param_env) { + if implicit_fast_path(infcx.tcx, key.value.predicate, key.param_env) { return Some(()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8a770bea8468b..0d497fe86cf44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -15,8 +15,8 @@ use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, PredicateObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{ - self, ExistentialPredicate, FieldInfo, SizedTraitKind, TraitRef, Ty, TypeVisitableExt, - elaborate, + self, ExistentialPredicate, FieldInfo, IncludeSizedImplicitBounds, SizedTraitKind, TraitRef, + Ty, TypeVisitableExt, elaborate, }; use rustc_span::{DUMMY_SP, bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -782,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Backward compatibility for default auto traits. // Test: ui/traits/default_auto_traits/extern-types.rs - if self.tcx().is_default_trait(def_id) { + if self.tcx().is_implicit_trait(def_id, IncludeSizedImplicitBounds::No) { check_impls() } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e280184169844..279392221a33c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -47,7 +47,7 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::solve::InferCtxtSelectExt as _; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt}; -use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, sizedness_fast_path}; +use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, implicit_fast_path}; mod _match; mod candidate_assembly; @@ -537,7 +537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if !self.infcx.disable_trait_solver_fast_paths() - && sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) + && implicit_fast_path(self.tcx(), obligation.predicate, obligation.param_env) { return Ok(EvaluatedToOk); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c60ebc4758ead..9cbb53c6f63bd 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -217,7 +217,7 @@ pub fn with_replaced_escaping_bound_vars< } } -pub fn sizedness_fast_path<'tcx>( +pub fn implicit_fast_path<'tcx>( tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 6bc6543a0a01b..ac5df8b93f482 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -5,7 +5,7 @@ use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::CanonicalPredicateGoal; use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, - sizedness_fast_path, + implicit_fast_path, }; use tracing::debug; @@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>( debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; - if !tcx.disable_trait_solver_fast_paths() && sizedness_fast_path(tcx, predicate, param_env) { + if !tcx.disable_trait_solver_fast_paths() && implicit_fast_path(tcx, predicate, param_env) { return Ok(EvaluationResult::EvaluatedToOk); } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 7e202d8614034..926314b2c5cf7 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -3,9 +3,9 @@ use std::range::{RangeFrom, RangeToInclusive}; use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ - self as abi, AbiAlign, AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, - HasDataLayout, Layout, LayoutCalculatorError, LayoutData, Niche, NicheOptimizations, - ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, + self as abi, AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, + Layout, LayoutCalculatorError, LayoutData, Niche, NicheOptimizations, ReprOptions, Scalar, + Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; @@ -819,14 +819,14 @@ fn layout_of_uncached<'tcx>( if tcx.is_lang_item(def.did(), LangItem::F16B) { let bfloat = scalar_unit(Primitive::Float(abi::Float::F16B)); assert_eq!(layout.size, abi::Float::F16B.size()); - layout.align = AbiAlign::new(abi::Float::F16B.align(cx)); + layout.align = abi::Float::F16B.align(cx); layout.backend_repr = BackendRepr::Scalar(bfloat); } if tcx.is_lang_item(def.did(), LangItem::PpcF128) { let ppcf128 = scalar_unit(Primitive::Float(abi::Float::PpcF128)); assert_eq!(layout.size, abi::Float::PpcF128.size()); - layout.align = AbiAlign::new(abi::Float::PpcF128.align(cx)); + layout.align = abi::Float::PpcF128.align(cx); layout.backend_repr = BackendRepr::Scalar(ppcf128); } @@ -885,7 +885,7 @@ fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tc cx.tcx().sess.code_stats.record_type_size( kind, type_desc, - layout.align.abi, + layout.align, layout.size, packed, opt_discr_size, diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 29e1407e0211f..4cc01d74ccf29 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -156,7 +156,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou ); assert_eq!(field.size, size, "`Scalar` field with bad size in {inner:#?}",); assert_eq!( - field.align.abi, align, + field.align, align, "`Scalar` field with bad align in {inner:#?}", ); assert!( @@ -238,7 +238,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou "`ScalarPair` first field with bad size in {inner:#?}", ); assert_eq!( - field1.align.abi, align1, + field1.align, align1, "`ScalarPair` first field with bad align in {inner:#?}", ); assert_matches!( @@ -260,7 +260,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou "`ScalarPair` second field with bad size in {inner:#?}", ); assert_eq!( - field2.align.abi, align2, + field2.align, align2, "`ScalarPair` second field with bad align in {inner:#?}", ); assert_matches!( @@ -270,7 +270,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou ); } BackendRepr::SimdVector { element, count } => { - let align = layout.align.abi; + let align = layout.align; let size = layout.size; let element_align = element.default_align(cx); let element_size = element.size(cx); diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 7aa3d87328fe7..edcc0082a942f 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -317,7 +317,7 @@ pub struct CanonicalParamEnvCacheEntry { pub param_env: I::ParamEnv, pub variables: Vec, pub variable_lookup_table: HashMap, - pub var_kinds: Vec>, + pub var_kinds: I::CanonicalVarKinds, } /// State used and modified by a canonicalizer during canonicalization. To avoid many allocations, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index be0114b8f3af3..4de18651b3520 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -461,6 +461,12 @@ pub trait Interner: fn is_default_trait(self, def_id: Self::TraitId) -> bool; + fn is_implicit_trait( + self, + def_id: Self::TraitId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool; + fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool; fn as_projection_lang_item( @@ -786,3 +792,8 @@ impl search_graph::Cx for I { self.assert_evaluation_is_concurrent() } } + +pub enum IncludeSizedImplicitBounds { + Yes, + No, +} diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 53afc311cc623..e300b94cbc438 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -461,9 +461,8 @@ pub enum CandidatePreferenceMode { impl CandidatePreferenceMode { /// Given `trait_def_id`, which candidate preference mode should be used? pub fn compute(cx: I, trait_id: I::TraitId) -> CandidatePreferenceMode { - let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_id) - || cx.trait_is_auto(trait_id) - || cx.is_default_trait(trait_id); + let is_sizedness_or_auto_or_default_goal = cx.trait_is_auto(trait_id) + || cx.is_implicit_trait(trait_id, ty::IncludeSizedImplicitBounds::Yes); if is_sizedness_or_auto_or_default_goal { CandidatePreferenceMode::Marker } else { diff --git a/library/core/src/field.rs b/library/core/src/field.rs index 5a8ae7759bc1e..b17a78846ce2a 100644 --- a/library/core/src/field.rs +++ b/library/core/src/field.rs @@ -124,7 +124,7 @@ impl Ord /// The container type may be a tuple, `struct`, `union` or `enum`. In the case of an enum, the /// variant must also be specified. Only a single field is supported. #[unstable(feature = "field_projections", issue = "145383")] -#[allow_internal_unstable(field_representing_type_raw, builtin_syntax)] +#[allow_internal_unstable(field_representing_type_raw, internal_syntax)] #[diagnostic::on_unmatched_args( note = "this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)`" )] @@ -134,7 +134,7 @@ impl Ord // it to `FieldRepresentingType<...>`. Thus stabilizing this requires careful thought about the // completeness of the trait impls for `FieldRepresentingType`. pub macro field_of($Container:ty, $($fields:expr)+ $(,)?) { - builtin # field_of($Container, $($fields)+) + k#field_of($Container, $($fields)+) } /// Type representing a field of a `struct`, `union`, `enum` variant or tuple. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 36a19f89e58cd..67c216053f7b1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -129,6 +129,7 @@ #![feature(f128)] #![feature(field_projections)] #![feature(final_associated_functions)] +#![feature(forced_keywords)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(impl_restriction)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b378078d3284..789119fb20052 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1907,7 +1907,7 @@ pub(crate) mod builtin { } /// Unstable placeholder for type ascription. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "type_ascription", issue = "101728", @@ -1915,11 +1915,11 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro type_ascribe($expr:expr, $ty:ty) { - builtin # type_ascribe($expr, $ty) + k#type_ascribe($expr, $ty) } /// Unstable placeholder for deref patterns. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "deref_patterns", issue = "87121", @@ -1927,7 +1927,7 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro deref($pat:pat) { - builtin # deref($pat) + k#deref($pat) } /// Derive macro generating an impl of the trait `From`. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b38557779092c..39b07963fb9a9 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1664,10 +1664,10 @@ impl SizedTypeProperties for T {} note = "this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)`" )] #[doc(alias = "memoffset")] -#[allow_internal_unstable(builtin_syntax, core_intrinsics)] +#[allow_internal_unstable(core_intrinsics, internal_syntax)] #[diagnostic::opaque] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { - const { builtin # offset_of($Container, $($fields)+) } + const { k#offset_of($Container, $($fields)+) } } /// Create a fresh instance of the inhabited ZST type `T`. diff --git a/library/core/src/unsafe_binder.rs b/library/core/src/unsafe_binder.rs index 3d2a04e95f078..bb7144fc5dddd 100644 --- a/library/core/src/unsafe_binder.rs +++ b/library/core/src/unsafe_binder.rs @@ -1,27 +1,17 @@ //! Operators used to turn types into unsafe binders and back. /// Unwrap an unsafe binder into its underlying type. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro unwrap_binder { - ($expr:expr) => { - builtin # unwrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # unwrap_binder ( $expr, $ty ) - }, +pub macro unwrap_binder($expr:expr $( ; $ty:ty )?) { + k#unwrap_binder($expr $( , $ty )?) } /// Wrap a type into an unsafe binder. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro wrap_binder { - ($expr:expr) => { - builtin # wrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # wrap_binder ( $expr, $ty ) - }, +pub macro wrap_binder($expr:expr $( ; $ty:ty )?) { + k#wrap_binder($expr $( , $ty )?) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8ed3a46bf3189..cd3fc8fda587b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -287,7 +287,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(exact_div)] #![feature(f16)] #![feature(f128)] #![feature(ffi_const)] diff --git a/library/std/src/sys/paths/unix.rs b/library/std/src/sys/paths/unix.rs index cee799c36c79b..756c5ec26f127 100644 --- a/library/std/src/sys/paths/unix.rs +++ b/library/std/src/sys/paths/unix.rs @@ -253,37 +253,14 @@ pub fn current_exe() -> io::Result { #[cfg(target_os = "openbsd")] pub fn current_exe() -> io::Result { + let mut path = vec![0u8; libc::PATH_MAX as usize]; unsafe { - let mut mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, libc::getpid(), libc::KERN_PROC_ARGV]; - let mib = mib.as_mut_ptr(); - - // Determine the required size (in bytes) for the argument array ... - let mut argv_size = 0; - cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_size, ptr::null_mut(), 0))?; - - // ... allocate a buffer for it ... - let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap(); - let mut argv = Vec::<*const libc::c_char>::with_capacity(argc); - - // ... and retrieve the argument array. - cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_size, ptr::null_mut(), 0))?; - let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap(); - argv.set_len(argc); - - if argv[0].is_null() { - return Err(io::const_error!(io::ErrorKind::Uncategorized, "no current exe available")); - } - let argv0 = CStr::from_ptr(argv[0]).to_bytes(); - if argv0.iter().any(|b| *b == b'/') { - // The program name is path-like, so try to canonicalize it. - crate::fs::canonicalize(OsStr::from_bytes(argv0)) - } else { - // The program was probably found in the PATH. Instead of trying to - // find it again (which might not succeed if PATH has changed), just - // return the program name – this function is best-effort anyway. - Ok(PathBuf::from(OsStr::from_bytes(argv0))) - } + cvt(libc::getexecpath(path.as_mut_ptr().cast(), path.len()))?; + // SAFETY: getexecpath(3) NUL-terminates the buffer on success. + let len = CStr::from_ptr(path.as_ptr().cast()).count_bytes(); + path.truncate(len); } + Ok(PathBuf::from(OsString::from_vec(path))) } #[cfg(any( diff --git a/library/std/src/sys/thread_local/guard/aix.rs b/library/std/src/sys/thread_local/guard/aix.rs new file mode 100644 index 0000000000000..9b945456bf790 --- /dev/null +++ b/library/std/src/sys/thread_local/guard/aix.rs @@ -0,0 +1,30 @@ +//! AIX registers thread destructors using `__pt_atexit_np`. +//! Calling it registers a callback that runs on thread termination +//! and upon process exit (for the main thread). + +use crate::cell::Cell; +use crate::sys::thread_local::destructors; + +pub fn enable() { + #[thread_local] + static REGISTERED: Cell = Cell::new(false); + + unsafe extern "C" { + fn __pt_atexit_np(flags: i32, dtor: unsafe extern "C" fn(i32) -> i32) -> i32; + } + + if !REGISTERED.replace(true) { + let ret = unsafe { __pt_atexit_np(0, run_dtors) }; + if ret != 0 { + rtabort!("failed to register thread destructor"); + } + } + + unsafe extern "C" fn run_dtors(_: i32) -> i32 { + unsafe { + destructors::run(); + crate::rt::thread_cleanup(); + } + 0 + } +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 5d3c23ce04678..1c137e52d9319 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -101,6 +101,10 @@ pub(crate) mod guard { mod apple; pub(crate) use apple::enable; } + all(target_thread_local, target_os = "aix") => { + mod aix; + pub(crate) use aix::enable; + } target_os = "windows" => { mod windows; pub(crate) use windows::enable; diff --git a/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile b/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile index d248faaabca6c..2a721006bfdc0 100644 --- a/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile +++ b/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile @@ -42,7 +42,7 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ --set llvm.libzstd=true" ENV SCRIPT="python3 ../x.py \ --stage 2 \ - test tests \ + test tests compiler/rustc_codegen_gcc \ --test-codegen-backend gcc \ --skip tests/coverage \ --skip tests/coverage-run-rustdoc \ diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index dd5e307fdfca5..2dcf3d51fc509 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1821,7 +1821,7 @@ impl PrimitiveType { Char => sym::char, Array => sym::array, Pat => sym::pat, - FieldOf => sym::field_of, + FieldOf => kw::FieldOf, Slice => sym::slice, Tuple => sym::tuple, Unit => sym::unit, diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index a41f6b4cc0e99..693ca21fe8a29 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -30,7 +30,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f && let ty::RawPtr(to_ptr_ty, _) = *cast_to.kind() && let Ok(from_layout) = cx.layout_of(from_ptr_ty) && let Ok(to_layout) = cx.layout_of(to_ptr_ty) - && from_layout.align.abi < to_layout.align.abi + && from_layout.align < to_layout.align // with c_void, we inherently need to trust the user && !is_c_void(cx, from_ptr_ty) // when casting from a ZST, we don't know enough to properly lint diff --git a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs index c233fe3f28ed5..2536ad574239b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs +++ b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs @@ -112,7 +112,7 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ ShouldImplTraitCase::new("std::clone::Clone", sym::clone, 1, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::cmp::Ord", sym::cmp, 2, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::default::Default", kw::Default, 0, SelfKind::No, OutType::Any, true, Edition2015), - ShouldImplTraitCase::new("std::ops::Deref", sym::deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), + ShouldImplTraitCase::new("std::ops::Deref", kw::Deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::DerefMut", sym::deref_mut, 1, SelfKind::RefMut, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::Div", sym::div, 2, SelfKind::Value, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::ops::Drop", sym::drop, 1, SelfKind::RefMut, OutType::Unit, true, Edition2015), diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 0306e6c2015bb..800b2e57dee6f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -14,7 +14,7 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx && let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from)) && let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to)) { - from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi + from_layout.size != to_layout.size || from_layout.align != to_layout.align } else { // no idea about layout, so don't lint false diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 7778677b454be..9ab122ecfc7c5 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -832,7 +832,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { this.libc_ty_layout("wchar_t") }; - self.read_c_str_with_char_size(ptr, wchar_t.size, wchar_t.align.abi) + self.read_c_str_with_char_size(ptr, wchar_t.size, wchar_t.align) } fn frame_in_std(&self) -> bool { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 6f62e717cbcb4..281c8c38eb63d 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1483,7 +1483,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { panic!("extern_statics cannot contain wildcards") }; let info = ecx.get_alloc_info(alloc_id); - if extern_decl_layout.size > info.size || extern_decl_layout.align.abi > info.align { + if extern_decl_layout.size > info.size || extern_decl_layout.align > info.align { throw_ub_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ with a size of {decl_size} bytes and alignment of {decl_align} bytes, \ @@ -1527,7 +1527,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { // Validate the allocation matches the declared size and alignment. let alloc_id = static_ptr.provenance.get_alloc_id().unwrap(); let info = ecx.get_alloc_info(alloc_id); - if extern_decl_layout.size > info.size || extern_decl_layout.align.abi > info.align { + if extern_decl_layout.size > info.size || extern_decl_layout.align > info.align { throw_ub_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ with a size of {decl_size} bytes and alignment of {decl_align} bytes, \ diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 43e4a55e72684..2ea6d31d5cea1 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1487,7 +1487,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let entry = this.allocate_ptr( Size::from_bytes(size), - dirent_layout.align.abi, + dirent_layout.align, MiriMemoryKind::Runtime.into(), AllocInit::Uninit, )?; diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 28c2740444822..6451595449046 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1015,14 +1015,6 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Ok("...".to_owned()), - ast::TyKind::FieldOf(ref ty, ref variant, ref field) => { - let ty = ty.rewrite_result(context, shape)?; - if let Some(variant) = variant { - Ok(format!("builtin # field_of({ty}, {variant}.{field})")) - } else { - Ok(format!("builtin # field_of({ty}, {field})")) - } - } ast::TyKind::UnsafeBinder(ref binder) => { let mut result = String::new(); if binder.generic_params.is_empty() { @@ -1049,7 +1041,10 @@ impl Rewrite for ast::Ty { result.push_str(&rewrite); Ok(result) } - ast::TyKind::Pat(..) | ast::TyKind::View(..) | ast::TyKind::GcaMacro(..) => { + ast::TyKind::FieldOf(..) + | ast::TyKind::GcaMacro(..) + | ast::TyKind::Pat(..) + | ast::TyKind::View(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not // totally impossible for rustfmt to come across these nodes when formatting a file. diff --git a/src/tools/rustfmt/tests/target/field-representing-types.rs b/src/tools/rustfmt/tests/target/field-representing-types.rs index a31ccbfb461f2..c5b400c6b3442 100644 --- a/src/tools/rustfmt/tests/target/field-representing-types.rs +++ b/src/tools/rustfmt/tests/target/field-representing-types.rs @@ -1,2 +1,4 @@ -type FRT = builtin # field_of(Type, ident); -type FRT2 = builtin # field_of(Type, ident); +//@ rustfmt-edition: 2021 + +type FRT = k#field_of(Type, ident); +type FRT2 = k#field_of(Type, ident); diff --git a/src/tools/rustfmt/tests/target/issue-6105.rs b/src/tools/rustfmt/tests/target/issue-6105.rs index 1eb0ce89f7812..cb73fc6042e24 100644 --- a/src/tools/rustfmt/tests/target/issue-6105.rs +++ b/src/tools/rustfmt/tests/target/issue-6105.rs @@ -1 +1,3 @@ -const _: () = builtin # offset_of(x, x); +//@ rustfmt-edition: 2021 + +const _: () = k#offset_of(x, x); diff --git a/src/tools/rustfmt/tests/target/issue_6159.rs b/src/tools/rustfmt/tests/target/issue_6159.rs index 49fd539d3ef5a..35047aadcec6b 100644 --- a/src/tools/rustfmt/tests/target/issue_6159.rs +++ b/src/tools/rustfmt/tests/target/issue_6159.rs @@ -1,3 +1,5 @@ +//@ rustfmt-edition: 2021 + fn main() { - builtin # type_ascribe(10, usize) + k#type_ascribe(10, usize) } diff --git a/tests/assembly-llvm/cstring-merging.rs b/tests/assembly-llvm/cstring-merging.rs index 9c1af4ebb4c05..e198a49c52216 100644 --- a/tests/assembly-llvm/cstring-merging.rs +++ b/tests/assembly-llvm/cstring-merging.rs @@ -14,7 +14,7 @@ use std::ffi::CStr; #[unsafe(no_mangle)] static CSTR: &[u8; 4] = b"foo\0"; -// CHECK-NOT: .section +// CHECK: .section .rodata.str1.{{[12]}},"aMS" // CHECK: {{(\.L|\$)}}anon.{{.+}}: // CHECK-NEXT: .{{asciz|string}} "bar" #[unsafe(no_mangle)] diff --git a/tests/assembly-llvm/static-relocation-model.rs b/tests/assembly-llvm/static-relocation-model.rs index a47681f4532a9..66bc992219527 100644 --- a/tests/assembly-llvm/static-relocation-model.rs +++ b/tests/assembly-llvm/static-relocation-model.rs @@ -47,7 +47,8 @@ pub fn peach() -> u8 { // x64: movq EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]] // x64-NEXT: {{movb|movzbl}} (%[[REG]]), %{{[a-z0-9]+}} // A64: adrp [[REG2:[a-z0-9]+]], EXOCHORDA -// A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA] +// A64-NEXT: add [[REG2]], [[REG2]], :lo12:EXOCHORDA +// A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]]{{\]}} #[no_mangle] pub fn mango() -> u8 { unsafe { *EXOCHORDA } diff --git a/tests/codegen-llvm/async-fn-cold-attr.rs b/tests/codegen-llvm/async-fn-cold-attr.rs new file mode 100644 index 0000000000000..3f4925d9208d4 --- /dev/null +++ b/tests/codegen-llvm/async-fn-cold-attr.rs @@ -0,0 +1,51 @@ +// Checks that `#[cold]` on `async fn`s and async closures applies to the coroutine holding their +// body (i.e. the `Future::poll` implementation), in addition to the function or closure that +// constructs it. +// +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] +#![feature(stmt_expr_attributes)] + +use std::future::Future; +use std::pin::pin; +use std::task::Context; + +// CHECK: ; async_fn_cold_attr::cold{{$}} +// CHECK-NEXT: ; Function Attrs: cold +// CHECK: ; async_fn_cold_attr::cold::{closure#0} +// CHECK-NEXT: ; Function Attrs: cold +#[cold] +pub async fn cold() {} + +// CHECK: ; async_fn_cold_attr::not_cold::{closure#0} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: cold +// CHECK-SAME: {{$}} +pub async fn not_cold() {} + +pub struct S; + +impl S { + // CHECK: ; ::method{{$}} + // CHECK-NEXT: ; Function Attrs: cold + // CHECK: ; ::method::{closure#0} + // CHECK-NEXT: ; Function Attrs: cold + #[cold] + pub async fn method(&self) {} +} + +// CHECK: ; async_fn_cold_attr::poll_all{{$}} +pub fn poll_all(cx: &mut Context<'_>) { + let _ = pin!(cold()).poll(cx); + let _ = pin!(not_cold()).poll(cx); + let _ = pin!(S.method()).poll(cx); + + // CHECK: ; async_fn_cold_attr::poll_all::{closure#0}{{$}} + // CHECK-NEXT: ; Function Attrs: cold + // CHECK: ; async_fn_cold_attr::poll_all::{closure#0}::{closure#0}:: + // CHECK-NEXT: ; Function Attrs: cold + let closure = #[cold] + async || {}; + let _ = pin!(closure()).poll(cx); +} diff --git a/tests/codegen-llvm/async-fn-inline-always-target-feature.rs b/tests/codegen-llvm/async-fn-inline-always-target-feature.rs new file mode 100644 index 0000000000000..83e635c03a50d --- /dev/null +++ b/tests/codegen-llvm/async-fn-inline-always-target-feature.rs @@ -0,0 +1,32 @@ +// `#[inline(always)]` on an `async fn` applies to its body coroutine (#129347). Unlike a closure +// marked `#[inline(always)]`, that coroutine is never inlined into the function it was written +// in, so it must still inherit that function's `#[target_feature]`s. +// +//@ revisions: x86_64 aarch64 +//@[x86_64] only-x86_64 +//@[aarch64] only-aarch64 +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] + +use std::future::Future; +use std::pin::pin; +use std::task::{Context, Waker}; + +// CHECK: ; async_fn_inline_always_target_feature::always::{closure#0} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define {{.*}} #[[ATTRS:[0-9]+]] +#[inline(always)] +#[cfg_attr(target_arch = "x86_64", target_feature(enable = "avx2"))] +#[cfg_attr(target_arch = "aarch64", target_feature(enable = "sha3"))] +pub async fn always() {} + +#[cfg_attr(target_arch = "x86_64", target_feature(enable = "avx2"))] +#[cfg_attr(target_arch = "aarch64", target_feature(enable = "sha3"))] +pub fn poll_always() { + let mut cx = Context::from_waker(Waker::noop()); + let _ = pin!(always()).poll(&mut cx); +} + +// x86_64: attributes #[[ATTRS]] = {{{.*}}"target-features"="{{[^"]*}}+avx2 +// aarch64: attributes #[[ATTRS]] = {{{.*}}"target-features"="{{[^"]*}}+sha3 diff --git a/tests/codegen-llvm/async-fn-inline-attr.rs b/tests/codegen-llvm/async-fn-inline-attr.rs new file mode 100644 index 0000000000000..d97300dd6046c --- /dev/null +++ b/tests/codegen-llvm/async-fn-inline-attr.rs @@ -0,0 +1,71 @@ +// Checks that inline attributes on `async fn`s and async closures apply to the coroutine holding +// their body (i.e. the `Future::poll` implementation) rather than to the function or closure that +// merely constructs it. See #129347. +// +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] +#![feature(stmt_expr_attributes)] + +use std::future::Future; +use std::pin::pin; +use std::task::Context; + +// CHECK: ; async_fn_inline_attr::never{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: noinline +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::never::{closure#0} +// CHECK-NEXT: ; Function Attrs: noinline +#[inline(never)] +pub async fn never() {} + +// CHECK: ; async_fn_inline_attr::always{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: alwaysinline +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::always::{closure#0} +// CHECK-NEXT: ; Function Attrs: alwaysinline +#[inline(always)] +pub async fn always() {} + +// The body coroutine would get an inline hint regardless, like all closures. +// CHECK: ; async_fn_inline_attr::hint{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: inlinehint +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::hint::{closure#0} +// CHECK-NEXT: ; Function Attrs: inlinehint +#[inline] +pub async fn hint() {} + +pub struct S; + +impl S { + // CHECK: ; ::method{{$}} + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: noinline + // CHECK-SAME: {{$}} + // CHECK: ; ::method::{closure#0} + // CHECK-NEXT: ; Function Attrs: noinline + #[inline(never)] + pub async fn method(&self) {} +} + +// CHECK: ; async_fn_inline_attr::poll_all{{$}} +pub fn poll_all(cx: &mut Context<'_>) { + let _ = pin!(never()).poll(cx); + let _ = pin!(always()).poll(cx); + let _ = pin!(hint()).poll(cx); + let _ = pin!(S.method()).poll(cx); + + // CHECK: ; async_fn_inline_attr::poll_all::{closure#0}{{$}} + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: noinline + // CHECK-SAME: {{$}} + // CHECK: ; async_fn_inline_attr::poll_all::{closure#0}::{closure#0}:: + // CHECK-NEXT: ; Function Attrs: noinline + let closure = #[inline(never)] + async || {}; + let _ = pin!(closure()).poll(cx); +} diff --git a/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs b/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs index 64bc58e1df7af..f43566ba88118 100644 --- a/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs +++ b/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs @@ -22,13 +22,13 @@ //@ edition: 2021 // non_generic_closure() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], -// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], -// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure" +// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// CHECK-DAG: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure" -// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure" -// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function" -// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block" +// CHECK-DAG: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure" +// CHECK-DAG: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function" +// CHECK-DAG: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block" // function_containing_closure() // NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[function_containing_closure_NAMESPACE]] diff --git a/tests/codegen-llvm/direct-access-external-data.rs b/tests/codegen-llvm/direct-access-external-data.rs index 43ee290d3a058..135c7e32b4a5d 100644 --- a/tests/codegen-llvm/direct-access-external-data.rs +++ b/tests/codegen-llvm/direct-access-external-data.rs @@ -17,7 +17,7 @@ unsafe extern "C" { // PIE-NOT: dso_local // DIRECT-SAME: dso_local // INDIRECT-NOT: dso_local - // CHECK-SAME: global i32 + // CHECK-SAME: global [4 x i8] safe static VAR: i32; // When "linkage" is used, we generate an indirection global. diff --git a/tests/codegen-llvm/thread-local.rs b/tests/codegen-llvm/thread-local.rs index 70b655fd5cf61..a3584154e079d 100644 --- a/tests/codegen-llvm/thread-local.rs +++ b/tests/codegen-llvm/thread-local.rs @@ -16,8 +16,8 @@ use std::cell::Cell; thread_local!(static A: Cell = const { Cell::new(1) }); -// CHECK: [[TLS_AUX:@.+]] = external thread_local{{.*}} global i64 // CHECK: [[TLS:@.+]] = internal thread_local{{.*}} global +// CHECK: [[TLS_AUX:@.+]] = external thread_local{{.*}} global [8 x i8] // CHECK-LABEL: @get #[no_mangle] diff --git a/tests/crashes/158773.rs b/tests/crashes/158773.rs deleted file mode 100644 index 3020ab6206e4b..0000000000000 --- a/tests/crashes/158773.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #158773 -//@ needs-rustc-debug-assertions -//@ compile-flags: -Znext-solver=globally -trait HasLifetime { - type AtLifetime<'a>; -} - -pub struct ExistentialLifetime(S::AtLifetime<'static>); - -impl ExistentialLifetime { - fn new() -> ExistentialLifetime { - ExistentialLifetime(ExistentialLifetime(())) - } -} - -fn main() {} diff --git a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs index eb1baea93dc00..38669eb1a21d7 100644 --- a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs +++ b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs @@ -48,6 +48,8 @@ mod libloading { use std::ffi::{c_char, c_int, c_void}; const RTLD_NOW: c_int = 2; + #[cfg(target_os = "aix")] + const RTLD_MEMBER: c_int = 0x00040000; fn cstr_null(s: &str) -> Vec { assert!(!s.as_bytes().contains(&0), "string must not contain interior NUL"); @@ -58,10 +60,17 @@ mod libloading { #[cfg(target_os = "macos")] let filename = cstr_null(&format!("lib{}.dylib", lib_name)); - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "aix")] + let filename = cstr_null(&format!("./lib{0}.a(lib{0}.so)", lib_name)); + + #[cfg(not(any(target_os = "macos", target_os = "aix")))] let filename = cstr_null(&format!("./lib{}.so", lib_name)); - let handle = unsafe { dlopen(filename.as_ptr(), RTLD_NOW) }; + let flags = RTLD_NOW; + #[cfg(target_os = "aix")] + let flags = flags | RTLD_MEMBER; + + let handle = unsafe { dlopen(filename.as_ptr(), flags) }; if handle.is_null() { None } else { Some(handle) } } diff --git a/tests/run-make/dynamic-loading-cdylib/rmake.rs b/tests/run-make/dynamic-loading-cdylib/rmake.rs index 975722da75d6b..b931863b694a8 100644 --- a/tests/run-make/dynamic-loading-cdylib/rmake.rs +++ b/tests/run-make/dynamic-loading-cdylib/rmake.rs @@ -5,21 +5,29 @@ // - `foo.rs` is a cdylib. // - `load_and_unload.rs` is a binary that loads and unloads the cdylib. // -// This test is ignored on musl hosts because musl's dlclose is a no-op and -// therefore destructors won't run when the library is unloaded. -// See https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries //@ ignore-cross-compile -//@ ignore-musl use run_make_support::{diff, run_with_args, rustc}; +// On musl and AIX, `dlclose` does not invoke TLS destructors upon unloading, +// so only the `load_only` case is tested on those platforms. +// +// Reference for musl: +// https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries + +#[cfg(any(target_env = "musl", target_os = "aix"))] +const TEST_MODES: &[&str] = &["load_only"]; + +#[cfg(not(any(target_env = "musl", target_os = "aix")))] +const TEST_MODES: &[&str] = &["unload", "load_only"]; + fn main() { rustc().input("foo.rs").run(); rustc().crate_type("bin").crate_name("load_and_unload_bin").input("load_and_unload.rs").run(); - for command_arg in ["unload", "load_only"] { + for command_arg in TEST_MODES { let out_raw = run_with_args("load_and_unload_bin", &[command_arg]).stdout_utf8(); #[cfg(windows)] diff --git a/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr b/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr index 923972d02b713..f8d9b80ddbf62 100644 --- a/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr +++ b/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr @@ -48,6 +48,11 @@ LL | fn sub(self, rhs: Self) -> Self::Output {} found unit type `()` = help: consider constraining the associated type `<(dyn Vector2 + 'static) as Sub>::Output` to `()` or calling a method that returns `<(dyn Vector2 + 'static) as Sub>::Output` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: consider returning one of these bindings + --> $DIR/dyn-impl-missing-assoc-type-ice-152668.rs:10:12 + | +LL | fn sub(self, rhs: Self) -> Self::Output {} + | ^^^^ ^^^ error[E0277]: the size for values of type `(dyn Vector2 + 'static)` cannot be known at compilation time --> $DIR/dyn-impl-missing-assoc-type-ice-152668.rs:10:12 diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index 33324685a84f4..f84f0bcbd34d4 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -33,9 +33,9 @@ pub fn e() {} //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: expected identifier, found keyword `unsafe` -//~| ERROR: malformed lint attribute input -//~| ERROR: malformed lint attribute input -//~| ERROR: malformed lint attribute input +//~| ERROR: malformed +//~| ERROR: malformed +//~| ERROR: malformed pub fn f() {} fn main() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 04e8c4d2dd453..cd73156eff453 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -25,11 +25,13 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` error: the `proc_macro` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/proc-unsafe-attributes.rs:1:10 @@ -85,12 +87,13 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `proc_macro` is not an unsafe attribute @@ -176,15 +179,15 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 21 previous errors -Some errors have detailed explanations: E0452, E0565. -For more information about an error, try `rustc --explain E0452`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr index 114c37188a9ef..ff82a449d83ba 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr index 66d0d94c0e815..3c7ce1686080c 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] @@ -20,7 +20,7 @@ LL | #[derive(Unresolved)] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] @@ -29,7 +29,7 @@ LL | #[deny("literal")] = help: try using `#[deny(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs index b070ec0f7dd93..437ed20acbeb9 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs @@ -7,7 +7,7 @@ //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope struct S; -#[deny("literal")] //~ ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal +#[deny("literal")] //~ ERROR malformed + //[duplicate]~| ERROR malformed + //[duplicate]~| ERROR malformed fn main() {} diff --git a/tests/ui/error-codes/E0452.rs b/tests/ui/error-codes/E0452.rs index 4e5a6c9301467..6a0437df7b14e 100644 --- a/tests/ui/error-codes/E0452.rs +++ b/tests/ui/error-codes/E0452.rs @@ -1,8 +1,8 @@ -#![allow(foo = "")] //~ ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 +#![allow(foo = "")] //~ ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed fn main() { } diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr index c20429e363dda..c34d9a2a01b28 100644 --- a/tests/ui/error-codes/E0452.stderr +++ b/tests/ui/error-codes/E0452.stderr @@ -1,49 +1,55 @@ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs b/tests/ui/feature-gates/feature-gate-builtin_syntax.rs deleted file mode 100644 index 832bb5a96bc3d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs +++ /dev/null @@ -1,7 +0,0 @@ -struct Foo { - v: u8, - w: u8, -} -fn main() { - builtin # offset_of(Foo, v); //~ ERROR `builtin #` syntax is unstable -} diff --git a/tests/ui/feature-gates/feature-gate-internal_syntax.rs b/tests/ui/feature-gates/feature-gate-internal_syntax.rs new file mode 100644 index 0000000000000..5b4293d900923 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.rs @@ -0,0 +1,10 @@ +//@ edition: 2021.. +#![feature(forced_keywords)] + +struct Foo { + v: u8, + w: u8, +} +fn main() { + k#offset_of(Foo, v); //~ ERROR this syntax is internal +} diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr similarity index 56% rename from tests/ui/feature-gates/feature-gate-builtin_syntax.stderr rename to tests/ui/feature-gates/feature-gate-internal_syntax.stderr index 297363b3de711..9db1a51e0d999 100644 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr @@ -1,11 +1,11 @@ -error[E0658]: `builtin #` syntax is unstable - --> $DIR/feature-gate-builtin_syntax.rs:6:15 +error[E0658]: this syntax is internal + --> $DIR/feature-gate-internal_syntax.rs:9:5 | -LL | builtin # offset_of(Foo, v); - | ^^^^^^^^^ +LL | k#offset_of(Foo, v); + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #110680 for more information - = help: add `#![feature(builtin_syntax)]` to the crate attributes to enable + = help: add `#![feature(internal_syntax)]` 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 diff --git a/tests/ui/field_representing_types/invalid.next.stderr b/tests/ui/field_representing_types/invalid.next.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.next.stderr +++ b/tests/ui/field_representing_types/invalid.next.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.old.stderr b/tests/ui/field_representing_types/invalid.old.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.old.stderr +++ b/tests/ui/field_representing_types/invalid.old.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.rs b/tests/ui/field_representing_types/invalid.rs index 0d8c5d563401c..e0ba33dd4eb59 100644 --- a/tests/ui/field_representing_types/invalid.rs +++ b/tests/ui/field_representing_types/invalid.rs @@ -24,10 +24,10 @@ fn main() { let _: field_of!(Struct); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct,); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct, field, extra); //~ ERROR: no rules expected `extra` - // FIXME(FRTs): adjust error message to mention `field_of!` & prevent double errors + // FIXME(FRTs): adjust error message to mention `field_of` & prevent double errors let _: field_of!(Enum, Variant..field); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names + //~^ ERROR: `field_of` expects dot-separated field and variant names let _: field_of!(Struct, [42]); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names - let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of!` only supports a single field or a variant with a field + //~^ ERROR: `field_of` expects dot-separated field and variant names + let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of` only supports a single field or a variant with a field } diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr index 4a0991d0eb3cb..8015bc15f510c 100644 --- a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr @@ -11,6 +11,8 @@ LL | x = foo::<()>; | = note: expected fn item `fn(F) -> F {bar::}` found fn item `fn(()) -> () {foo::<()>}` + = note: different fn items have unique types, even if their signatures are the same + = help: consider casting both fn items to fn pointers using `as fn(Alias(No, Alias { kind: Opaque { def_id: DefId(0:8 ~ fn_def_opaque_coercion_to_fn_ptr[7fda]::F::{opaque#0}) }, args: [], .. })) -> Alias(No, Alias { kind: Opaque { def_id: DefId(0:8 ~ fn_def_opaque_coercion_to_fn_ptr[7fda]::F::{opaque#0}) }, args: [], .. })` error[E0308]: mismatched types --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:29:9 @@ -28,6 +30,8 @@ LL | x = foo::; | = note: expected fn item `fn(()) -> () {bar::<()>}` found fn item `fn(I) -> I {foo::}` + = note: different fn items have unique types, even if their signatures are the same + = help: consider casting both fn items to fn pointers using `as fn(())` help: use parentheses to call this function | LL | x = foo::(/* I */); diff --git a/tests/ui/force-inlining/invalid-async-cold.rs b/tests/ui/force-inlining/invalid-async-cold.rs new file mode 100644 index 0000000000000..f0a699ac1caa0 --- /dev/null +++ b/tests/ui/force-inlining/invalid-async-cold.rs @@ -0,0 +1,25 @@ +//@ edition: 2024 +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(gen_blocks)] +#![feature(rustc_attrs)] + +// `#[inline]` on an `async fn` or `gen fn` applies to its body coroutine, but +// `#[rustc_force_inline]` must not: it is already rejected on such functions, +// so it must not also be reported as incompatible with `#[cold]`, which both +// the function and its body coroutine get. + +#[rustc_force_inline] +//~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function +#[cold] +pub async fn async_cold() {} + +#[rustc_force_inline] +//~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function +#[cold] +pub gen fn gen_cold() {} + +pub fn caller() { + let _ = async_cold(); + let _ = gen_cold(); +} diff --git a/tests/ui/force-inlining/invalid-async-cold.stderr b/tests/ui/force-inlining/invalid-async-cold.stderr new file mode 100644 index 0000000000000..cc176458c0c13 --- /dev/null +++ b/tests/ui/force-inlining/invalid-async-cold.stderr @@ -0,0 +1,20 @@ +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid-async-cold.rs:12:1 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub async fn async_cold() {} + | ------------------------- `async`, `gen` or `async gen` function + +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid-async-cold.rs:17:1 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub gen fn gen_cold() {} + | --------------------- `async`, `gen` or `async gen` function + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index f9f39e34b658e..7339b9acaea56 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -6,8 +6,6 @@ LL | call(f, ()); | | | required by a bound introduced by this call | - = note: expected type with signature `for<'a> fn(<_ as ATC<'a>>::Type)` - found type parameter with signature `fn(())` note: required by a bound in `call` --> $DIR/issue-62529-3.rs:9:36 | diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.rs b/tests/ui/hygiene/unpretty-debug-lifetimes.rs index ee8be21b60d01..5f8a20281ab04 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.rs +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.rs @@ -4,8 +4,15 @@ // Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene // Previously, lifetimes were missing the #N syntax context suffix. -// Don't break whenever Symbol numbering changes -//@ normalize-stdout: "\d+#" -> "0#" +// This test deliberately has no `.stdout` snapshot. The hygiene annotations +// embed `Symbol` indices, whose width feeds into the pretty-printer's line +// breaking, so the layout shifts whenever a `Symbol` gains or loses a digit. +// `normalize-stdout` can't help, because the layout is decided before +// normalization runs. Assert the property this test is about instead: the two +// `'a` share their text but carry different syntax contexts. +//@ dont-check-compiler-stdout +//@ check-stdout +//@ regex-error-pattern: f\s*/\*\s*\d+#0\s*\*/<'a\s*/\*\s*\d+#0\s*\*/,\s*'a\s*/\*\s*\d+#1\s*\*/ #![feature(decl_macro)] #![feature(no_core)] diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout deleted file mode 100644 index c75cc7b2179d3..0000000000000 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout +++ /dev/null @@ -1,33 +0,0 @@ -//@ check-pass -//@ compile-flags: -Zunpretty=expanded,hygiene - -// Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene -// Previously, lifetimes were missing the #N syntax context suffix. - -// Don't break whenever Symbol numbering changes -//@ normalize-stdout: "\d+#" -> "0#" - -#![feature /* 0#0 */(decl_macro /* 0#0 */)] -#![feature /* 0#0 */(no_core /* 0#0 */)] -#![no_core /* 0#0 */] - -macro lifetime_hygiene - /* - 0#0 - */ { - ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 - */>) => - { fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } -} -fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {} - - -/* -Expansions: -crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root -crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "lifetime_hygiene") - -SyntaxContexts: -#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) -#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) -*/ diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index 5a8cc40d0276e..1f824bb23f0b7 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -11,6 +11,10 @@ LL | fn foo(&self) -> >::Bar {} | = note: expected opaque type `<() as Foo<()>>::Bar` found unit type `()` +help: consider returning the local binding `self` + | +LL | fn foo(&self) -> >::Bar { self } + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-attribute-literals.rs b/tests/ui/lint/lint-attribute-literals.rs index 34a4757adec3c..7adec75210108 100644 --- a/tests/ui/lint/lint-attribute-literals.rs +++ b/tests/ui/lint/lint-attribute-literals.rs @@ -1,11 +1,11 @@ // Checks that lint attributes with literals have an explanatory error #[allow("literal")] -//~^ ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal +//~^ ERROR malformed +//~| ERROR malformed +//~| ERROR malformed #[deny(1.0)] -//~^ ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal +//~^ ERROR malformed +//~| ERROR malformed +//~| ERROR malformed fn main() {} diff --git a/tests/ui/lint/lint-attribute-literals.stderr b/tests/ui/lint/lint-attribute-literals.stderr index 7434f8b5c5d4b..b06eac094f66d 100644 --- a/tests/ui/lint/lint-attribute-literals.stderr +++ b/tests/ui/lint/lint-attribute-literals.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -6,7 +6,7 @@ LL | #[allow("literal")] | = help: try using `#[allow(literal)]` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] @@ -14,7 +14,7 @@ LL | #[deny(1.0)] | = help: for example, write `#[deny(dead_code)]` for `dead_code` -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -23,7 +23,7 @@ LL | #[allow("literal")] = help: try using `#[allow(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] @@ -32,7 +32,7 @@ LL | #[deny(1.0)] = help: for example, write `#[deny(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -41,7 +41,7 @@ LL | #[allow("literal")] = help: try using `#[allow(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] diff --git a/tests/ui/lint/lint-malformed.rs b/tests/ui/lint/lint-malformed.rs index cf5570753d85d..5fd92170363f0 100644 --- a/tests/ui/lint/lint-malformed.rs +++ b/tests/ui/lint/lint-malformed.rs @@ -1,8 +1,8 @@ #![deny = "foo"] //~ ERROR malformed `deny` attribute input -#![allow(bar = "baz")] //~ ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute +#![allow(bar = "baz")] //~ ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed fn main() { } diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 7be928de86985..ceb7fe105bcd3 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -1,31 +1,36 @@ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0539]: malformed `deny` attribute input @@ -49,23 +54,24 @@ LL - #![deny = "foo"] LL + #![deny(lint1, lint2, lint3, reason = "...")] | -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 7 previous errors -Some errors have detailed explanations: E0452, E0539. -For more information about an error, try `rustc --explain E0452`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/lint/pre-expansion-parsing.rs b/tests/ui/lint/pre-expansion-parsing.rs index 7cfc57ff4e903..11a55beb77d65 100644 --- a/tests/ui/lint/pre-expansion-parsing.rs +++ b/tests/ui/lint/pre-expansion-parsing.rs @@ -3,7 +3,7 @@ #[expect] // OK #[expect[wut]] // OK #[expect(expect)] // OK -#[expect(expect(expect))] //~ ERROR malformed lint attribute input +#[expect(expect(expect))] //~ ERROR malformed #[deny(({!}))] // OK #[expect[helix::]] // OK #[cfg(false)] diff --git a/tests/ui/lint/pre-expansion-parsing.stderr b/tests/ui/lint/pre-expansion-parsing.stderr index ecc8b7017d92d..651fd5d4c8f38 100644 --- a/tests/ui/lint/pre-expansion-parsing.stderr +++ b/tests/ui/lint/pre-expansion-parsing.stderr @@ -1,9 +1,10 @@ -error[E0452]: malformed lint attribute input +error: malformed `expect` attribute input --> $DIR/pre-expansion-parsing.rs:6:10 | LL | #[expect(expect(expect))] - | ^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[expect(dead_code)]` for `dead_code` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index 38ad00da64cd7..4a0c458209ee6 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -8,14 +8,14 @@ //~^ ERROR malformed `warn` attribute input //~| NOTE expected a normal string literal, not a byte string literal #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] //~^ ERROR malformed lint attribute //~| NOTE reason in lint attribute must come last diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index d771366d6168e..3c52a0d8e25b4 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -29,23 +29,29 @@ LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condem | = note: expected a normal string literal, not a byte string literal -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:10:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:13:22 | LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:16:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` error[E0452]: malformed lint attribute input --> $DIR/reasons-erroneous.rs:19:44 diff --git a/tests/ui/offload/check_config.fail.stderr b/tests/ui/offload/check_config.fail.stderr index 87df9d42bafd1..6f4ae31491d86 100644 --- a/tests/ui/offload/check_config.fail.stderr +++ b/tests/ui/offload/check_config.fail.stderr @@ -1,4 +1,4 @@ -error: using the offload feature requires -Z offload=.bc> +error: using the offload feature requires -Z offload=.ptx or .elf> error: using the offload feature requires -C lto=fat diff --git a/tests/ui/offload/check_config.rs b/tests/ui/offload/check_config.rs index 9865d36049a8f..d28d27d2c9d10 100644 --- a/tests/ui/offload/check_config.rs +++ b/tests/ui/offload/check_config.rs @@ -6,7 +6,7 @@ //@[pass] compile-flags: -Zunstable-options -Zoffload=Device -Clto=fat --emit=metadata //@[fail] compile-flags: -Clto=thin -//[fail]~? ERROR: using the offload feature requires -Z offload=.bc> +//[fail]~? ERROR: using the offload feature requires -Z offload=.ptx or .elf> //[fail]~? ERROR: using the offload feature requires -C lto=fat #![feature(gpu_offload)] diff --git a/tests/ui/offset-of/offset-of-builtin.rs b/tests/ui/offset-of/offset-of-builtin.rs deleted file mode 100644 index 6664c10f905ef..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(builtin_syntax)] - -// For the exposed macro we already test these errors in the other files, -// but this test helps to make sure the builtin construct also errors. -// This has the same examples as offset-of-arg-count.rs - -fn main() { - builtin # offset_of(NotEnoughArguments); //~ ERROR expected one of -} -fn t1() { - builtin # offset_of(NotEnoughArgumentsWithAComma, ); //~ ERROR expected expression -} -fn t2() { - builtin # offset_of(S, f, too many arguments); //~ ERROR expected `)`, found `too` -} -fn t3() { - builtin # offset_of(S, f); // compiles fine -} -fn t4() { - builtin # offset_of(S, f.); //~ ERROR unexpected token -} -fn t5() { - builtin # offset_of(S, f.,); //~ ERROR unexpected token -} -fn t6() { - builtin # offset_of(S, f..); //~ ERROR offset_of expects dot-separated field and variant names -} -fn t7() { - builtin # offset_of(S, f..,); //~ ERROR offset_of expects dot-separated field and variant names -} - -struct S { f: u8, } diff --git a/tests/ui/offset-of/offset-of-builtin.stderr b/tests/ui/offset-of/offset-of-builtin.stderr deleted file mode 100644 index 5917ee2936361..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `)` - --> $DIR/offset-of-builtin.rs:8:43 - | -LL | builtin # offset_of(NotEnoughArguments); - | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `<` - -error: expected expression, found `)` - --> $DIR/offset-of-builtin.rs:11:55 - | -LL | builtin # offset_of(NotEnoughArgumentsWithAComma, ); - | ^ expected expression - -error: expected `)`, found `too` - --> $DIR/offset-of-builtin.rs:14:31 - | -LL | builtin # offset_of(S, f, too many arguments); - | ^^^ expected `)` - | - = note: unexpected third argument to offset_of - -error: unexpected token: `)` - --> $DIR/offset-of-builtin.rs:20:30 - | -LL | builtin # offset_of(S, f.); - | ^ - -error: unexpected token: `,` - --> $DIR/offset-of-builtin.rs:23:30 - | -LL | builtin # offset_of(S, f.,); - | ^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:26:28 - | -LL | builtin # offset_of(S, f..); - | ^^^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:29:28 - | -LL | builtin # offset_of(S, f..,); - | ^^^ - -error: aborting due to 7 previous errors - diff --git a/tests/ui/offset-of/offset-of-tuple-field.rs b/tests/ui/offset-of/offset-of-tuple-field.rs index 02d41f91a2563..755d61d18b739 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.rs +++ b/tests/ui/offset-of/offset-of-tuple-field.rs @@ -1,5 +1,3 @@ -#![feature(builtin_syntax)] - use std::mem::offset_of; fn main() { @@ -9,12 +7,6 @@ fn main() { offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_` //~| ERROR suffixes on a tuple index - builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2` - builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0` - builtin # offset_of((u8, u8), 01); //~ ERROR no field `01` - builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_` - //~| ERROR suffixes on a tuple index - offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2` offset_of!(((u8, u16), (u32, u16, u8)), 1.2); diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr index 01622c5fa2da6..052e4b0596fd6 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.stderr +++ b/tests/ui/offset-of/offset-of-tuple-field.stderr @@ -1,17 +1,11 @@ error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ invalid suffix `u8` - -error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:6:26 + --> $DIR/offset-of-tuple-field.rs:4:26 | LL | offset_of!((u8, u8), _0); | ^^ @@ -23,7 +17,7 @@ LL + offset_of!((u8, u8), 0); | error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:7:26 + --> $DIR/offset-of-tuple-field.rs:5:26 | LL | offset_of!((u8, u8), 01); | ^^ @@ -31,7 +25,7 @@ LL | offset_of!((u8, u8), 01); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:8:26 + --> $DIR/offset-of-tuple-field.rs:6:26 | LL | offset_of!((u8, u8), 1e2); | ^^^ @@ -39,7 +33,7 @@ LL | offset_of!((u8, u8), 1e2); = note: available fields are: `0`, `1` error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ @@ -50,48 +44,8 @@ LL - offset_of!((u8, u8), 1_u8); LL + offset_of!((u8, u8), 1); | -error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:12:35 - | -LL | builtin # offset_of((u8, u8), 1e2); - | ^^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:13:35 - | -LL | builtin # offset_of((u8, u8), _0); - | ^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), _0); -LL + builtin # offset_of((u8, u8), 0); - | - -error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:14:35 - | -LL | builtin # offset_of((u8, u8), 01); - | ^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), 1_u8); -LL + builtin # offset_of((u8, u8), 1); - | - error[E0609]: no field `2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:18:47 + --> $DIR/offset-of-tuple-field.rs:10:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); | ^ @@ -99,7 +53,7 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:19:47 + --> $DIR/offset-of-tuple-field.rs:11:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); | ^^^ @@ -107,11 +61,11 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); = note: available fields are: `0`, `1` error[E0609]: no field `0` on type `u8` - --> $DIR/offset-of-tuple-field.rs:21:49 + --> $DIR/offset-of-tuple-field.rs:13:49 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); | ^ -error: aborting due to 13 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index ddbaee97b1bb0..be668d9e08946 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,5 @@ -#![feature(builtin_syntax)] +//@ edition: 2021.. +#![feature(forced_keywords, internal_syntax)] use std::mem::offset_of; @@ -9,9 +10,9 @@ fn main() { offset_of!((u8, u8), 1 .); //~ ERROR unexpected token: `)` // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported - { builtin # offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names - { builtin # offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` + { k#offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported + { k#offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names + { k#offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` } type ComplexTup = (((u8, u8), u8), u8); @@ -26,14 +27,15 @@ fn nested() { offset_of!(ComplexTup, 0.0 . 1.); //~ ERROR unexpected token: `)` offset_of!(ComplexTup, 0.0. 1.); //~ ERROR unexpected token: `)` + // FIXME(fmease): Update comment. // Test for builtin too to ensure that the builtin syntax can also handle these cases // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` } diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index f90f2db1c6c35..db46373449218 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -1,71 +1,71 @@ error: leading `+` is not supported - --> $DIR/offset-of-tuple.rs:12:37 + --> $DIR/offset-of-tuple.rs:13:29 | -LL | { builtin # offset_of((u8, u8), +1) }; - | ^ unexpected `+` +LL | { k#offset_of((u8, u8), +1) }; + | ^ unexpected `+` | help: try removing the `+` | -LL - { builtin # offset_of((u8, u8), +1) }; -LL + { builtin # offset_of((u8, u8), 1) }; +LL - { k#offset_of((u8, u8), +1) }; +LL + { k#offset_of((u8, u8), 1) }; | error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:13:38 + --> $DIR/offset-of-tuple.rs:14:30 | -LL | { builtin # offset_of((u8, u8), 1.) }; - | ^ +LL | { k#offset_of((u8, u8), 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:14:40 + --> $DIR/offset-of-tuple.rs:15:32 | -LL | { builtin # offset_of((u8, u8), 1 .) }; - | ^ +LL | { k#offset_of((u8, u8), 1 .) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:32:45 + --> $DIR/offset-of-tuple.rs:34:37 | -LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:33:46 + --> $DIR/offset-of-tuple.rs:35:38 | -LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 .0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:34:47 + --> $DIR/offset-of-tuple.rs:36:39 | -LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 . 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:35:46 + --> $DIR/offset-of-tuple.rs:37:38 | -LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0. 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:36:46 + --> $DIR/offset-of-tuple.rs:38:38 | -LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 .1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:37:47 + --> $DIR/offset-of-tuple.rs:39:39 | -LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 . 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:38:46 + --> $DIR/offset-of-tuple.rs:40:38 | -LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0. 1.) }; + | ^ error: no rules expected `+` - --> $DIR/offset-of-tuple.rs:6:26 + --> $DIR/offset-of-tuple.rs:7:26 | LL | offset_of!((u8, u8), +1); | ^ no rules expected this token in macro call @@ -75,61 +75,61 @@ note: while trying to match meta-variable `$fields:expr` = note: this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)` error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:7:26 + --> $DIR/offset-of-tuple.rs:8:26 | LL | offset_of!((u8, u8), -1); | ^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:8:27 + --> $DIR/offset-of-tuple.rs:9:27 | LL | offset_of!((u8, u8), 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:9:29 + --> $DIR/offset-of-tuple.rs:10:29 | LL | offset_of!((u8, u8), 1 .); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:21:34 + --> $DIR/offset-of-tuple.rs:22:34 | LL | offset_of!(ComplexTup, 0.0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:22:35 + --> $DIR/offset-of-tuple.rs:23:35 | LL | offset_of!(ComplexTup, 0 .0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:23:36 + --> $DIR/offset-of-tuple.rs:24:36 | LL | offset_of!(ComplexTup, 0 . 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:24:35 + --> $DIR/offset-of-tuple.rs:25:35 | LL | offset_of!(ComplexTup, 0. 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:25:35 + --> $DIR/offset-of-tuple.rs:26:35 | LL | offset_of!(ComplexTup, 0.0 .1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:26:36 + --> $DIR/offset-of-tuple.rs:27:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:27:35 + --> $DIR/offset-of-tuple.rs:28:35 | LL | offset_of!(ComplexTup, 0.0. 1.); | ^ diff --git a/tests/ui/parser/builtin-syntax.rs b/tests/ui/parser/builtin-syntax.rs deleted file mode 100644 index 897dab8ec50ae..0000000000000 --- a/tests/ui/parser/builtin-syntax.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(builtin_syntax)] - -fn main() { - builtin # foobar(); //~ ERROR unknown `builtin #` construct -} - -fn not_identifier() { - builtin # {}(); //~ ERROR expected identifier after -} diff --git a/tests/ui/parser/builtin-syntax.stderr b/tests/ui/parser/builtin-syntax.stderr deleted file mode 100644 index ee3764a62216a..0000000000000 --- a/tests/ui/parser/builtin-syntax.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unknown `builtin #` construct `foobar` - --> $DIR/builtin-syntax.rs:4:5 - | -LL | builtin # foobar(); - | ^^^^^^^^^^^^^^^^ - -error: expected identifier after `builtin #` - --> $DIR/builtin-syntax.rs:8:15 - | -LL | builtin # {}(); - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr index 0556d6c50b1ce..105e2756fb1db 100644 --- a/tests/ui/suggestions/if-then-neeing-semi.stderr +++ b/tests/ui/suggestions/if-then-neeing-semi.stderr @@ -52,12 +52,10 @@ help: consider `await`ing on the `Future` | LL | async_dummy2().await | ++++++ -help: consider removing this semicolon and boxing the expressions +help: consider removing this semicolon | -LL ~ Box::new(async_dummy()) -LL | -LL | } else { -LL ~ Box::new(async_dummy2()) +LL - async_dummy(); +LL + async_dummy() | error[E0308]: `if` and `else` have incompatible types diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr index f70f6a1e1570b..c468433fd4421 100644 --- a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -52,12 +52,10 @@ help: consider `await`ing on the `Future` | LL | false => async_dummy2().await, | ++++++ -help: consider removing this semicolon and boxing the expressions +help: consider removing this semicolon | -LL ~ Box::new(async_dummy()) -LL | -LL | } -LL ~ false => Box::new(async_dummy2()), +LL - async_dummy(); +LL + async_dummy() | error[E0308]: `match` arms have incompatible types diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 03249bd39a8c7..196eafa5bba68 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -11,6 +11,10 @@ help: a method is available that returns `>::A` | LL | fn func(&self) -> Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` +help: consider returning the local binding `self` + | +LL | fn funq(&self) -> Self::A { self } + | ++++ error[E0308]: mismatched types --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9 diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr index 0ad8e3444600b..972a42d0f6621 100644 --- a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr @@ -13,6 +13,10 @@ LL | x = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition see issue #152409 for more information +help: use a trailing comma to create a tuple with one element + | +LL | (x,) + | + ++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr new file mode 100644 index 0000000000000..fe8ef6aff748d --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` + --> $DIR/rigid-alias-in-same-type-modulo-infer.rs:16:9 + | +LL | ExistentialLifetime(ExistentialLifetime(())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `ExistentialLifetime<_>`, found associated type + | + = note: expected struct `ExistentialLifetime<_>` + found associated type `::AtLifetime<'static>` +help: consider constraining the associated type `::AtLifetime<'static>` to `ExistentialLifetime<_>` + | +LL | impl = ExistentialLifetime<_>>> ExistentialLifetime { + | ++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr new file mode 100644 index 0000000000000..fe8ef6aff748d --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` + --> $DIR/rigid-alias-in-same-type-modulo-infer.rs:16:9 + | +LL | ExistentialLifetime(ExistentialLifetime(())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `ExistentialLifetime<_>`, found associated type + | + = note: expected struct `ExistentialLifetime<_>` + found associated type `::AtLifetime<'static>` +help: consider constraining the associated type `::AtLifetime<'static>` to `ExistentialLifetime<_>` + | +LL | impl = ExistentialLifetime<_>>> ExistentialLifetime { + | ++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs new file mode 100644 index 0000000000000..c083234411fe8 --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs @@ -0,0 +1,21 @@ +//! Regression test for . +// Avoids ICE on SameTypeModuloInfer assertion rigidity of two types. +// +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +trait HasLifetime { + type AtLifetime<'a>; +} + +pub struct ExistentialLifetime(S::AtLifetime<'static>); + +impl ExistentialLifetime { + fn new() -> ExistentialLifetime { + ExistentialLifetime(ExistentialLifetime(())) + //~^ ERROR: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` [E0271] + } +} + +fn main() {} diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index 7eca271aeda13..3551d40dffbfc 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -10,12 +10,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -131,7 +132,7 @@ mod expressions { fn expr_cast() { let expr; expr as T; expr as T; } /// ExprKind::Type - fn expr_type() { let expr; builtin # type_ascribe(expr, T); } + fn expr_type() { let expr; k#type_ascribe(expr, T); } /// ExprKind::Let fn expr_let() { @@ -315,7 +316,7 @@ mod expressions { - const { builtin # offset_of(T, field) }; + const { k#offset_of(T, field) }; } /// ExprKind::MacCall fn expr_mac_call() { "..."; "..."; "..."; } diff --git a/tests/ui/unpretty/exhaustive.hir.stderr b/tests/ui/unpretty/exhaustive.hir.stderr index 5ca4b080a95e5..276bc5b5d2573 100644 --- a/tests/ui/unpretty/exhaustive.hir.stderr +++ b/tests/ui/unpretty/exhaustive.hir.stderr @@ -1,17 +1,17 @@ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:209:9 + --> $DIR/exhaustive.rs:210:9 | LL | static || value; | ^^^^^^^^^ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:210:9 + --> $DIR/exhaustive.rs:211:9 | LL | static move || value; | ^^^^^^^^^^^^^^ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/exhaustive.rs:239:13 + --> $DIR/exhaustive.rs:240:13 | LL | fn expr_await() { | --------------- this is not `async` @@ -20,19 +20,19 @@ LL | fut.await; | ^^^^^ only allowed inside `async` functions and blocks error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/exhaustive.rs:290:9 + --> $DIR/exhaustive.rs:291:9 | LL | _; | ^ `_` not allowed here error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:300:9 + --> $DIR/exhaustive.rs:301:9 | LL | x::(); | ^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:301:9 + --> $DIR/exhaustive.rs:302:9 | LL | x::(T, T) -> T; | ^^^^^^^^^^^^^^ only `Fn` traits may use parentheses @@ -44,31 +44,31 @@ LL + x:: -> T; | error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:9 + --> $DIR/exhaustive.rs:303:9 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:26 + --> $DIR/exhaustive.rs:303:26 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:9 + --> $DIR/exhaustive.rs:306:9 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:19 + --> $DIR/exhaustive.rs:306:19 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^^^ only `Fn` traits may use parentheses error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - --> $DIR/exhaustive.rs:392:9 + --> $DIR/exhaustive.rs:393:9 | LL | yield; | ^^^^^ @@ -79,7 +79,7 @@ LL | #[coroutine] fn expr_yield() { | ++++++++++++ error[E0703]: invalid ABI: found `C++` - --> $DIR/exhaustive.rs:472:23 + --> $DIR/exhaustive.rs:473:23 | LL | unsafe extern "C++" {} | ^^^^^ invalid ABI @@ -87,7 +87,7 @@ LL | unsafe extern "C++" {} = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: `..` patterns are not allowed here - --> $DIR/exhaustive.rs:674:13 + --> $DIR/exhaustive.rs:675:13 | LL | let ..; | ^^ @@ -95,13 +95,13 @@ LL | let ..; = note: only allowed in tuple, tuple struct, and slice patterns error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:789:16 + --> $DIR/exhaustive.rs:790:16 | LL | let _: T() -> !; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:803:16 + --> $DIR/exhaustive.rs:804:16 | LL | let _: impl Send; | ^^^^^^^^^ @@ -112,7 +112,7 @@ LL | let _: impl Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:804:16 + --> $DIR/exhaustive.rs:805:16 | LL | let _: impl Send + 'static; | ^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL | let _: impl Send + 'static; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:805:16 + --> $DIR/exhaustive.rs:806:16 | LL | let _: impl 'static + Send; | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | let _: impl 'static + Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:806:16 + --> $DIR/exhaustive.rs:807:16 | LL | let _: impl ?Sized; | ^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | let _: impl ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:807:16 + --> $DIR/exhaustive.rs:808:16 | LL | let _: impl [const] Clone; | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let _: impl [const] Clone; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:808:16 + --> $DIR/exhaustive.rs:809:16 | LL | let _: impl for<'a> Send; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index b1c956c2fe9f1..6af4d3b5b81de 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -1,8 +1,9 @@ -#![attr = Feature([auto_traits#0, builtin_syntax#0, const_trait_impl#0, +#![attr = Feature([auto_traits#0, internal_syntax#0, const_trait_impl#0, coroutines#0, decl_macro#0, deref_patterns#0, explicit_tail_calls#0, -gen_blocks#0, more_qualified_paths#0, never_patterns#0, pattern_types#0, -pattern_type_macro#0, prelude_import#0, specialization#0, trace_macros#0, -trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, yeet_expr#0])] +forced_keywords#0, gen_blocks#0, more_qualified_paths#0, never_patterns#0, +pattern_types#0, pattern_type_macro#0, prelude_import#0, specialization#0, +trace_macros#0, trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, +yeet_expr#0])] #![attr = LintCheck([LintCheck {lint_name: LintName { tool: None, name: "incomplete_features" }, kind: Allow}, LintCheck {lint_name: LintName { tool: None, name: "unused_attributes" }, diff --git a/tests/ui/unpretty/exhaustive.rs b/tests/ui/unpretty/exhaustive.rs index 03ef63874ac0a..15f684fc3dd72 100644 --- a/tests/ui/unpretty/exhaustive.rs +++ b/tests/ui/unpretty/exhaustive.rs @@ -9,12 +9,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -144,7 +145,7 @@ mod expressions { /// ExprKind::Type fn expr_type() { let expr; - builtin # type_ascribe(expr, T); + k#type_ascribe(expr, T); } /// ExprKind::Let