diff --git a/Cargo.lock b/Cargo.lock index b398d06c347df..ec14ada71ee64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4055,19 +4055,29 @@ dependencies = [ "rustc_lexer", "rustc_lint_defs", "rustc_macros", - "rustc_middle", "rustc_parse", "rustc_proc_macro", "rustc_serialize", "rustc_session", "rustc_span", "rustc_structures", - "scoped-tls", "smallvec", "thin-vec", "tracing", ] +[[package]] +name = "rustc_expand_queries" +version = "0.0.0" +dependencies = [ + "rustc_ast", + "rustc_expand", + "rustc_middle", + "rustc_proc_macro", + "rustc_span", + "scoped-tls", +] + [[package]] name = "rustc_feature" version = "0.0.0" @@ -4271,6 +4281,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_expand", + "rustc_expand_queries", "rustc_feature", "rustc_fs_util", "rustc_hir", @@ -4909,6 +4920,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_index", "rustc_infer", "rustc_lint_defs", "rustc_macros", diff --git a/compiler/rustc_attr_ir/src/stability.rs b/compiler/rustc_attr_ir/src/stability.rs index 1cba0b59c0f6c..8d0551e92472d 100644 --- a/compiler/rustc_attr_ir/src/stability.rs +++ b/compiler/rustc_attr_ir/src/stability.rs @@ -139,8 +139,9 @@ pub enum StabilityLevel { /// Rust release which stabilized this feature. since: StableSince, /// This is `Some` if this item allowed to be referred to on stable via unstable modules; - /// the `Symbol` is the deprecation message printed in that case. - allowed_through_unstable_modules: Option, + /// the first `Symbol` is the deprecation message printed in that case, + /// the second `Symbol` is the correct module to use. + allowed_through_unstable_modules: Option<(Symbol, Symbol)>, }, } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6dbbe0bf4d0c8..29e288d858c37 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -10,6 +10,7 @@ use rustc_feature::{ACCEPTED_LANG_FEATURES, AttributeStability}; use super::prelude::*; use super::util::parse_version; +use crate::context::ExpectNameValue; use crate::diagnostics; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ @@ -49,7 +50,7 @@ const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ #[derive(Default)] pub(crate) struct StabilityParser { - allowed_through_unstable_modules: Option, + allowed_through_unstable_modules: Option<(Symbol, Symbol)>, stability: Option<(Stability, Span)>, } @@ -93,16 +94,51 @@ impl AttributeParser for StabilityParser { ), ( &[sym::rustc_allowed_through_unstable_modules], - template!(NameValueStr: "deprecation message"), + template!(List: &[r#"message = "...", module = "..."#]), unstable!(staged_api), |this, cx, args| { - let Some(nv) = cx.expect_name_value(args, cx.attr_span, None) else { - return; - }; - let Some(value_str) = cx.expect_string_literal(nv) else { - return; - }; - this.allowed_through_unstable_modules = Some(value_str); + let Some(list) = cx.expect_list(args, cx.attr_span) else { return }; + let mut message = None; + let mut module = None; + + for item in list.mixed() { + let Some((name, value)) = item.expect_name_value(cx, item.span(), None) else { + return; + }; + let Some(value) = cx.expect_string_literal(value) else { + return; + }; + + match name.name { + sym::message => { + if message.is_some() { + cx.adcx().duplicate_key(name.span, name.name); + } else { + message = Some(value) + } + } + sym::module => { + if module.is_some() { + cx.adcx().duplicate_key(name.span, name.name); + } else { + module = Some(value) + } + } + _ => { + cx.adcx().expected_specific_argument( + name.span, + &[sym::message, sym::module], + ); + } + } + } + + let allowed_through_unstable_modules = try { (message?, module?) }; + if allowed_through_unstable_modules.is_none() { + cx.emit_err(diagnostics::RustcAtumMissingParams { span: cx.attr_span }); + } + + this.allowed_through_unstable_modules = allowed_through_unstable_modules; }, ), ]; diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index a37d56419adac..663915e39dccd 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1136,6 +1136,15 @@ pub(crate) struct RustcAllowedUnstablePairing { pub span: Span, } +#[derive(Diagnostic)] +#[diag( + "`rustc_allowed_through_unstable_modules` attribute must have `message` and `module` params" +)] +pub(crate) struct RustcAtumMissingParams { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("suggestions on deprecated items are unstable")] pub(crate) struct DeprecatedItemSuggestion { diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index a8338c9e3c41f..8c9c444bd1793 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -14,7 +14,7 @@ use rustc_infer::traits::query::{ }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, RePlaceholder, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, + self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c22698003f7ee..97931fc76f152 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -26,7 +26,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, PredicateKind, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, + self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, suggest_constraining_type_params, }; use rustc_mir_dataflow::move_paths::{Init, InitKind, InitLocation, MoveOutIndex, MovePathIndex}; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b43694596d17c..a972b37cd42d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -15,8 +15,7 @@ use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{ - self, GenericArgs, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, - fold_regions, + self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions, }; use rustc_span::{Ident, Span, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5a1358b9a311e..1a328f62fc73e 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -12,7 +12,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, RegionExt, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 2b3d8b4fdac22..5285f724b02ec 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; -use rustc_middle::ty::{RegionExt, RegionVid, TyCtxt}; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 6583bc24e2015..ceb33d82deba8 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -7,7 +7,7 @@ use std::io::{self, Write}; use itertools::Itertools; use rustc_graphviz as dot; -use rustc_middle::ty::{RegionExt, UniverseIndex}; +use rustc_middle::ty::UniverseIndex; use super::*; diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d3fc7152acc44..534cd1327bbe5 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -17,9 +17,7 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{ - self, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions, -}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index e347dc2d13dfc..a154078b7ad86 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -11,7 +11,7 @@ use rustc_macros::extension; use rustc_middle::mir::{Body, ConstraintCategory}; use rustc_middle::ty::{ self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, Flags, GenericArg, - GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionExt, RegionVid, Ty, TyCtxt, + GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt, Unnormalized, fold_regions, }; use rustc_mir_dataflow::points::DenseLocationMap; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index f845d9137f759..e20f9a646a953 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,8 +6,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_middle::ty::{ - self, GenericArgKind, RegionExt, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, - fold_regions, + self, GenericArgKind, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions, }; use rustc_span::Span; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fbde85ef6aec4..f16c811031b08 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::RETURN_PLACE; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, BoundVariableKind, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, - List, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, + List, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, kw, sym}; diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index d4d64cb3fbaf2..cd2b06cc1defb 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -443,11 +443,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .supported_types(self.arch, true) .iter() .map(|(ty, _)| ty.size()) + .filter_map(InlineAsmSize::fixed_size_bytes) .max() - .unwrap(); - let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); + .expect("expected fixed-size type"); + let align = rustc_abi::Align::from_bytes(reg_size).unwrap(); let offset = slot_size.align_to(align); - *slot_size = offset + reg_size; + *slot_size = offset + rustc_abi::Size::from_bytes(reg_size); offset }; let mut new_slot = |x| new_slot_fn(&mut slot_size, x); diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 5b17b4f83fea2..8fd438d847d29 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -692,7 +692,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(_)) => "Sg", @@ -807,7 +809,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => cx.type_i32(), @@ -1056,7 +1060,9 @@ fn modifier_to_gcc( | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { if modifier == Some('v') { None } else { modifier } } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => None, diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 88049d67964b1..d42438ba92f59 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1850,6 +1850,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { self.fptoint_sat(true, val, dest_ty) } + + fn ptrauth_resign( + &mut self, + _value: Self::Value, + _old_key: u32, + _old_discriminator: u64, + _new_key: u32, + _new_discriminator: u64, + ) -> Self::Value { + bug!("Resigning of pointers not implemented"); + } } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 6bd186f1121fc..712a1c14ef8e6 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -323,7 +323,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>, - _schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 19fbe37c27b9e..8c1fc18ee7a78 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -405,7 +405,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - _pointer_auth_schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index dfae4eceebe44..fe0654c665c76 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -375,6 +375,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fixed_count: 3, conv: CanonAbi::C, can_unwind: false, + ptrauth_discriminator: None, }; fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index f9bcc6fe0b6ce..3d2362be02f27 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -732,18 +732,25 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> format!("{{{}{}}}", class, idx) } } else if let Some(idx) = a64_vreg_index(reg) { - let class = if let Some(layout) = layout { - match layout.size.bytes() { + let class = match layout { + Some(layout) + if matches!( + layout.backend_repr, + BackendRepr::SimdScalableVector { .. } + ) => + { + 'z' + } + Some(layout) => match layout.size.bytes() { 16 => 'q', 8 => 'd', 4 => 's', 2 => 'h', 1 => 'd', // We fixup i8 to i8x8 _ => unreachable!(), - } - } else { + }, // We use i64x2 as the type for discarded outputs - 'q' + None => 'q', }; format!("{{{}{}}}", class, idx) } else if let Some(idx) = hexagon_reg_pair_index(reg) { @@ -775,7 +782,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> AArch64(AArch64InlineAsmRegClass::reg) => "r", AArch64(AArch64InlineAsmRegClass::vreg) => "w", AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + // Although the above link suggests its just 'Upa', llvm's own tests seem to suggest its + // '@3Upa'. (see "src/llvm-project/clang/test/CodeGen/AArch64/sve-inline-asm-datatypes.c" line 139) + AArch64(AArch64InlineAsmRegClass::preg) => "@3Upa", + AArch64(AArch64InlineAsmRegClass::ffr) => unreachable!("clobber-only"), Arm(ArmInlineAsmRegClass::reg) => "r", Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::dreg_low16) @@ -885,7 +895,7 @@ fn modifier_to_llvm( modifier } } - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + AArch64(AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr) => None, Arm(ArmInlineAsmRegClass::reg) => None, Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => None, Arm(ArmInlineAsmRegClass::dreg) @@ -990,7 +1000,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' AArch64(AArch64InlineAsmRegClass::vreg) | AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + AArch64(AArch64InlineAsmRegClass::preg) => cx.type_scalable_vector(cx.type_i1(), 16), + AArch64(AArch64InlineAsmRegClass::ffr) => unreachable!("clobber-only"), Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), Arm(ArmInlineAsmRegClass::dreg) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index dae8b2d17e0e1..bd75e9635618b 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1553,6 +1553,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx); attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]); } + + fn ptrauth_resign( + &mut self, + value: &'ll Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> &'ll Value { + let ptr_as_int = self.ptrtoint(value, self.type_i64()); + let resigned_int = self.call_intrinsic( + "llvm.ptrauth.resign", + &[], + &[ + ptr_as_int, + self.const_i32(old_key as i32), + self.const_i64(old_discriminator as i64), + self.const_i32(new_key as i32), + self.const_i64(new_discriminator as i64), + ], + ); + + self.inttoptr(resigned_int, self.val_ty(value)) + } } impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { @@ -2185,8 +2209,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // bundles. // Once this is resolved, we should analyze each call and skip direct calls. See the // discussion in the rust-lang issue: - let key: u32 = 0; - let discriminator: u64 = 0; + + let key: u32 = self.sess().pointer_authentication_fn_ptr_key().unwrap() as u32; + // If sess().pointer_authentication_fn_ptr_type_discrimination() is enabled, this contains + // the function pointer type discriminator; otherwise, it is None. LLVM expects a u64 here, + // so use 0 when no discriminator is present. + let discriminator = fn_abi?.ptrauth_discriminator.unwrap_or(0); + Some(llvm::OperandBundleBox::new( "ptrauth", &[self.const_u32(key), self.const_u64(discriminator)], diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 3fe4550b6759e..8f63e409028ce 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -30,11 +30,9 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( cx: &CodegenCx<'ll, '_>, instance: Instance<'tcx>, llfn: &'ll llvm::Value, - schema: &PointerAuthSchema, + ptrauth_schema: PointerAuthSchema, ) -> &'ll llvm::Value { - if cx.tcx.sess.pointer_authentication_functions().is_none() { - return llfn; - } + assert!(cx.tcx.sess.pointer_authentication_functions().is_some()); // Only free functions or methods let def_id = instance.def_id(); @@ -54,7 +52,7 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( return llfn; } - let addr_diversity = match schema.is_address_discriminated { + let addr_diversity = match ptrauth_schema.is_address_discriminated { PointerAuthAddressDiscriminator::HardwareAddress(true) => Some(llfn), PointerAuthAddressDiscriminator::HardwareAddress(false) => None, PointerAuthAddressDiscriminator::Synthetic(val) => { @@ -63,7 +61,12 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( Some(unsafe { llvm::LLVMConstIntToPtr(llval, llty) }) } }; - const_ptr_auth(llfn, schema.key as u32, schema.constant_discriminator as u64, addr_diversity) + const_ptr_auth( + llfn, + ptrauth_schema.key as u32, + ptrauth_schema.constant_discriminator as u64, + addr_diversity, + ) } /* @@ -179,11 +182,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self, global_alloc: GlobalAlloc<'tcx>, need_symbol_name: bool, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Result<&'ll Value, u64> { let alloc = match global_alloc { GlobalAlloc::Function { instance, .. } => { - return Ok(self.get_fn_addr(instance, schema)); + return Ok(self.get_fn_addr(instance, ptrauth_schema)); } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); @@ -405,7 +408,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { cv: Scalar, layout: abi::Scalar, llty: &'ll Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { @@ -422,7 +425,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { let (prov, offset) = ptr.prov_and_relative_offset(); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); let base_addr_space = global_alloc.address_space(self); - let base_addr = match self.alloc_to_backend(global_alloc, false, schema) { + let base_addr = match self.alloc_to_backend(global_alloc, false, ptrauth_schema) { Ok(base_addr) => base_addr, Err(base_addr) => { let val = base_addr.wrapping_add(offset.bytes()); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index c737fad66e573..26c6f6d0e396a 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -970,7 +970,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { // When pointer authentication metadata is provided, `get_fn_addr` will // attempt to sign the pointer using LLVM's `ConstPtrAuth` constant @@ -985,7 +985,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { // , and comment in // builder's `ptrauth_operand_bundle`. let llfn = get_fn(self, instance); - match pointer_auth_schema { + match ptrauth_schema { Some(schema) => common::maybe_sign_fn_ptr(self, instance, llfn, schema), None => llfn, } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 25003e071beb7..8c6998407e89e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -4129,7 +4129,7 @@ fn add_lld_args( // `lld` as the linker. // // Note that wasm targets skip this step since the only option there anyway - // is to use LLD but the `wasm32-wasip2` target relies on a wrapper around + // is to use LLD but component-producing targets rely on a wrapper around // this, `wasm-component-ld`, which is overridden if this option is passed. if !sess.target.is_like_wasm { cmd.cc_arg("-fuse-ld=lld"); diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index 397fb423e8da3..a71a57f02c82a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx, V> RetagPlan { // the outermost `Box` is what determines the permission that gets created. ty::Adt(adt, _) if adt.is_box() => Self::visit_box(bx, layout, is_fn_entry), // Skip traversing for everything inside of `MaybeDangling` - ty::Adt(adt, _) if adt.is_maybe_dangling() => None, + _ if layout.ty.is_like_maybe_dangling() => None, _ => Self::walk_value(bx, layout, is_fn_entry), } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index cb0209a0ae369..0e37705ec82b5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -667,4 +667,13 @@ pub trait BuilderMethods<'a, 'tcx>: fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); + + fn ptrauth_resign( + &mut self, + value: Self::Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> Self::Value; } diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index b4eba38d39c19..b45b5667be6c9 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -47,7 +47,7 @@ pub trait ConstCodegenMethods: BackendTypes { cv: Scalar, layout: abi::Scalar, llty: Self::Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index add7128a2974b..3d1a931a12e83 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -22,7 +22,7 @@ pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn eh_personality(&self) -> Self::Function; fn sess(&self) -> &Session; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 2cd4caf5ba250..f388bb80b13ce 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -7,7 +7,6 @@ use std::borrow::Cow; use std::fmt::{self, Write}; use std::hash::Hash; -use std::mem; use std::num::NonZero; use either::{Left, Right}; @@ -1528,15 +1527,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, BackendRepr::Memory { .. } => unreachable!() } } - ty::Adt(adt, _) if adt.is_maybe_dangling() => { - let old_may_dangle = mem::replace(&mut self.may_dangle, true); - - let inner = self.ecx.project_field(val, FieldIdx::ZERO)?; - self.visit_value(&inner)?; - - self.may_dangle = old_may_dangle; - } _ => { + let old_may_dangle = self.may_dangle; + self.may_dangle |= val.layout.ty.is_like_maybe_dangling(); + // default handler try_validation!( self.walk_value(val), @@ -1546,6 +1540,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => InvalidMetaWrongTrait { expected_dyn_type, vtable_dyn_type }, ); + + self.may_dangle = old_may_dangle; } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0789.md b/compiler/rustc_error_codes/src/error_codes/E0789.md index c7bc6cfde5134..6cf0c7243d854 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0789.md +++ b/compiler/rustc_error_codes/src/error_codes/E0789.md @@ -14,7 +14,10 @@ Erroneous code example: #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules = "deprecation message"] +#[rustc_allowed_through_unstable_modules( + message = "deprecation message", + module = "stable_module", +)] // #[stable(feature = "foo", since = "1.0")] struct Foo; // ^^^ error: `rustc_allowed_through_unstable_modules` attribute must be diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 0f216aa9f68df..1d0864ff7b201 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -20,7 +20,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } -rustc_middle = { path = "../rustc_middle" } rustc_parse = { path = "../rustc_parse" } # We must use the proc_macro version that we will compile proc-macros against, # not the one from our own sysroot. @@ -29,7 +28,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_structures = { path = "../rustc_structures" } -scoped-tls = "1.0" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.19" tracing = "0.1" diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 8bbca0ddf0f90..c81d9eb12aa48 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -23,7 +23,3 @@ pub mod config; pub mod expand; pub mod module; pub mod proc_macro; - -pub fn provide(providers: &mut rustc_middle::query::Providers) { - providers.derive_macro_expansion = proc_macro::provide_derive_macro_expansion; -} diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 89b4aac3299fc..024a0542a5f64 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -6,7 +6,6 @@ use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, pluralize}; use rustc_macros::Subdiagnostic; -use rustc_middle::bug; use rustc_parse::parser::{Parser, Recovery, token_descr}; use rustc_session::parse::ParseSess; use rustc_span::source_map::SourceMap; @@ -203,7 +202,7 @@ impl BestFailure { impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'matcher> { fn prepare(&mut self, which_matcher: WhichMatcher, matcher: &'matcher [MatcherLoc]) { if self.current.is_some() { - bug!("`Self::after_arm()` was not called to clean up context"); + panic!("`Self::after_arm()` was not called to clean up context"); } self.current = Some((which_matcher, matcher)); @@ -236,12 +235,12 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match } Failure => { if self.best_failure.is_none() { - bug!("A matching failure occurred but `Self::failure()` was not called"); + panic!("A matching failure occurred but `Self::failure()` was not called"); } } Ambiguity => { if self.result.is_none() { - bug!("An ambiguity error occurred but `Self::ambiguity()` was not called"); + panic!("An ambiguity error occurred but `Self::ambiguity()` was not called"); } } ErrorReported(guar) => self.result = Some((self.root_span, guar)), @@ -253,7 +252,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match fn failure(&mut self, parser: &Parser<'_>) { let Some((which_matcher, _)) = self.current else { - bug!("`Self::prepare()` was not called to initialize context"); + panic!("`Self::prepare()` was not called to initialize context"); }; let mut token = parser.token; @@ -290,7 +289,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match fn ambiguity(&mut self, parser: &Parser<'_>) { let Some((_, matcher)) = self.current else { - bug!("`Self::prepare()` was not called to initialize context"); + panic!("`Self::prepare()` was not called to initialize context"); }; #[expect( diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 95a4ebc63d38b..3e94e0ca34773 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -80,7 +80,6 @@ pub(crate) use ParseResult::*; use rustc_ast::token::{self, DocComment, NonterminalKind, Token, TokenKind}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_middle::span_bug; use rustc_parse::parser::{ParseNtResult, Parser, token_descr}; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span}; @@ -732,17 +731,14 @@ impl TtParser { // `NamedParseResult`. Otherwise, it's an error. let mut ret_val = FxHashMap::default(); for loc in matcher { - if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc + if let &MatcherLoc::MetaVarDecl { bind, .. } = loc && ret_val .insert(MacroRulesNormalizedIdent::new(bind), res.next().unwrap()) .is_some() { // Duplicate binds are checked for when the macro definition is processed, // and should have prevented the definition from ever being used. - span_bug!( - span, - "duplicate meta-variable binding went undetected at macro definition" - ) + panic!("duplicate meta-variable binding went undetected at macro definition") } } ret_val diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 105d2d796aa80..5e01b851b75c7 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -1,8 +1,8 @@ use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; +use rustc_data_structures::AtomicRef; use rustc_data_structures::profiling::TimingGuard; use rustc_errors::ErrorGuaranteed; -use rustc_middle::ty::{self, TyCtxt}; use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser}; use rustc_proc_macro as pm; use rustc_session::Session; @@ -113,14 +113,7 @@ impl MultiItemModifier for DeriveProcMacro { let res = if ecx.sess.opts.incremental.is_some() && ecx.sess.opts.unstable_opts.cache_proc_macros { - ty::tls::with(|tcx| { - let input = &*tcx.arena.alloc(input); - let key: (LocalExpnId, &TokenStream) = (invoc_id, input); - - QueryDeriveExpandCtx::enter(ecx, self.client, move || { - tcx.derive_macro_expansion(key).cloned() - }) - }) + (*EXPAND_DERIVE_MACRO_CACHED)(invoc_id, input, ecx, self.client) } else { expand_derive_macro(invoc_id, input, ecx, self.client) }; @@ -163,24 +156,9 @@ impl MultiItemModifier for DeriveProcMacro { } } -/// Provide a query for computing the output of a derive macro. -pub(super) fn provide_derive_macro_expansion<'tcx>( - tcx: TyCtxt<'tcx>, - key: (LocalExpnId, &'tcx TokenStream), -) -> Result<&'tcx TokenStream, ()> { - let (invoc_id, input) = key; - - // Make sure that we invalidate the query when the crate defining the proc macro changes - let _ = tcx.crate_hash(invoc_id.expn_data().macro_def_id.unwrap().krate); - - QueryDeriveExpandCtx::with(|ecx, client| { - expand_derive_macro(invoc_id, input.clone(), ecx, client).map(|ts| &*tcx.arena.alloc(ts)) - }) -} - type DeriveClient = pm::bridge::client::Client; -fn expand_derive_macro( +pub fn expand_derive_macro( invoc_id: LocalExpnId, input: TokenStream, ecx: &mut ExtCtxt<'_>, @@ -216,47 +194,12 @@ fn expand_derive_macro( } } -/// Stores the context necessary to expand a derive proc macro via a query. -struct QueryDeriveExpandCtx { - /// Type-erased version of `&mut ExtCtxt` - expansion_ctx: *mut (), - client: DeriveClient, -} - -impl QueryDeriveExpandCtx { - /// Store the extension context and the client into the thread local value. - /// It will be accessible via the `with` method while `f` is active. - fn enter(ecx: &mut ExtCtxt<'_>, client: DeriveClient, f: F) -> R - where - F: FnOnce() -> R, - { - // We need erasure to get rid of the lifetime - let ctx = Self { expansion_ctx: ecx as *mut _ as *mut (), client }; - DERIVE_EXPAND_CTX.set(&ctx, f) - } - - /// Accesses the thread local value of the derive expansion context. - /// Must be called while the `enter` function is active. - fn with(f: F) -> R - where - F: for<'a, 'b> FnOnce(&'b mut ExtCtxt<'a>, DeriveClient) -> R, - { - DERIVE_EXPAND_CTX.with(|ctx| { - let ectx = { - let casted = ctx.expansion_ctx.cast::>(); - // SAFETY: We can only get the value from `with` while the `enter` function - // is active (on the callstack), and that function's signature ensures that the - // lifetime is valid. - // If `with` is called at some other time, it will panic due to usage of - // `scoped_tls::with`. - unsafe { casted.as_mut().unwrap() } - }; - - f(ectx, ctx.client) - }) - } -} - -// When we invoke a query to expand a derive proc macro, we need to provide it with the expansion -// context and derive Client. We do that using a thread-local. -scoped_tls::scoped_thread_local!(static DERIVE_EXPAND_CTX: QueryDeriveExpandCtx); +pub static EXPAND_DERIVE_MACRO_CACHED: AtomicRef< + fn(LocalExpnId, TokenStream, &mut ExtCtxt<'_>, DeriveClient) -> Result, +> = AtomicRef::new( + &(|_, _, _: &mut ExtCtxt<'_>, _| -> Result<_, _> { + panic!( + "`EXPAND_DERIVE_MACRO_CACHED` callback was not setup; it must be set in `rustc_interface::callbacks`" + ) + } as _), +); diff --git a/compiler/rustc_expand_queries/Cargo.toml b/compiler/rustc_expand_queries/Cargo.toml new file mode 100644 index 0000000000000..abf932e24716d --- /dev/null +++ b/compiler/rustc_expand_queries/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rustc_expand_queries" +version = "0.0.0" +edition = "2024" +build = false + +[lib] +doctest = false + +[dependencies] +# tidy-alphabetical-start +rustc_ast = { path = "../rustc_ast" } +rustc_expand = { path = "../rustc_expand" } +rustc_middle = { path = "../rustc_middle" } +# We must use the proc_macro version that we will compile proc-macros against, +# not the one from our own sysroot. +rustc_proc_macro = { path = "../rustc_proc_macro" } +rustc_span = { path = "../rustc_span" } +scoped-tls = "1.0" +# tidy-alphabetical-end diff --git a/compiler/rustc_expand_queries/src/derive.rs b/compiler/rustc_expand_queries/src/derive.rs new file mode 100644 index 0000000000000..1254013ad89bb --- /dev/null +++ b/compiler/rustc_expand_queries/src/derive.rs @@ -0,0 +1,82 @@ +use rustc_ast::tokenstream::TokenStream; +use rustc_expand::base::ExtCtxt; +use rustc_middle::ty::{TyCtxt, tls}; +use rustc_proc_macro as pm; +use rustc_span::LocalExpnId; + +type DeriveClient = pm::bridge::client::Client; + +/// Stores the context necessary to expand a derive proc macro via a query. +struct QueryDeriveExpandCtx { + /// Type-erased version of `&mut ExtCtxt` + expansion_ctx: *mut (), + client: DeriveClient, +} + +impl QueryDeriveExpandCtx { + /// Store the extension context and the client into the thread local value. + /// It will be accessible via the `with` method while `f` is active. + fn enter(ecx: &mut ExtCtxt<'_>, client: DeriveClient, f: F) -> R + where + F: FnOnce() -> R, + { + // We need erasure to get rid of the lifetime + let ctx = Self { expansion_ctx: ecx as *mut _ as *mut (), client }; + DERIVE_EXPAND_CTX.set(&ctx, f) + } + + /// Accesses the thread local value of the derive expansion context. + /// Must be called while the `enter` function is active. + fn with(f: F) -> R + where + F: for<'a, 'b> FnOnce(&'b mut ExtCtxt<'a>, DeriveClient) -> R, + { + DERIVE_EXPAND_CTX.with(|ctx| { + let ectx = { + let casted = ctx.expansion_ctx.cast::>(); + // SAFETY: We can only get the value from `with` while the `enter` function + // is active (on the callstack), and that function's signature ensures that the + // lifetime is valid. + // If `with` is called at some other time, it will panic due to usage of + // `scoped_tls::with`. + unsafe { casted.as_mut().unwrap() } + }; + + f(ectx, ctx.client) + }) + } +} + +// When we invoke a query to expand a derive proc macro, we need to provide it with the expansion +// context and derive Client. We do that using a thread-local. +scoped_tls::scoped_thread_local!(static DERIVE_EXPAND_CTX: QueryDeriveExpandCtx); + +pub(crate) fn expand_derive_macro_cached( + invoc_id: LocalExpnId, + input: TokenStream, + ecx: &mut ExtCtxt<'_>, + client: DeriveClient, +) -> Result { + tls::with(|tcx| { + let input = &*tcx.arena.alloc(input); + let key: (LocalExpnId, &TokenStream) = (invoc_id, input); + + QueryDeriveExpandCtx::enter(ecx, client, move || tcx.derive_macro_expansion(key).cloned()) + }) +} + +/// Provide a query for computing the output of a derive macro. +pub(crate) fn derive_macro_expansion<'tcx>( + tcx: TyCtxt<'tcx>, + key: (LocalExpnId, &'tcx TokenStream), +) -> Result<&'tcx TokenStream, ()> { + let (invoc_id, input) = key; + + // Make sure that we invalidate the query when the crate defining the proc macro changes + let _ = tcx.crate_hash(invoc_id.expn_data().macro_def_id.unwrap().krate); + + QueryDeriveExpandCtx::with(|ecx, client| { + rustc_expand::proc_macro::expand_derive_macro(invoc_id, input.clone(), ecx, client) + .map(|ts| &*tcx.arena.alloc(ts)) + }) +} diff --git a/compiler/rustc_expand_queries/src/lib.rs b/compiler/rustc_expand_queries/src/lib.rs new file mode 100644 index 0000000000000..ef669460aeec2 --- /dev/null +++ b/compiler/rustc_expand_queries/src/lib.rs @@ -0,0 +1,13 @@ +#![allow(internal_features, reason = "proc macro internals")] +#![feature(proc_macro_internals)] + +mod derive; + +pub fn setup_callbacks() { + rustc_expand::proc_macro::EXPAND_DERIVE_MACRO_CACHED + .swap(&(derive::expand_derive_macro_cached as _)); +} + +pub fn provide(providers: &mut rustc_middle::query::Providers) { + providers.derive_macro_expansion = derive::derive_macro_expansion; +} diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 60636a1164926..ca9874ac727a1 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::{self, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::sym; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e5d26cf72f9a5..ad34f327c3060 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -14,9 +14,9 @@ use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInfer use rustc_infer::traits::{TraitErrors, util}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, RegionExt, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, Unnormalized, Upcast, + self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + Unnormalized, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{BytePos, DUMMY_SP, Span}; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index eac3762ef9af8..9ce935c4389a5 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -89,7 +89,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_types_for_signature; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, OutlivesClause, Region, RegionExt, Ty, TyCtxt, TypingMode, + self, GenericArgs, GenericArgsRef, OutlivesClause, Region, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4b95f1e82cd9a..51c8437a3f627 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,9 +24,9 @@ use rustc_middle::traits::solve::NoSolution; use rustc_middle::ty::region_constraint::{And, LeafRegionConstraint, Or}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgs, GenericParamDefKind, RegionExt, Ty, TyCtxt, TypeFlags, - TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, - Unnormalized, Upcast, + self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, + Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 248e7aa583a19..491386cb692bb 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,8 +34,8 @@ use rustc_lint_defs::builtin::REPR_C_ENUMS_LARGER_THAN_INT; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - self, AdtKind, Const, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, fold_regions, + self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, + fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 488b9a09e6106..c12c4a199b250 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::find_attr; use rustc_middle::ty::{ - self, GenericClauses, ImplTraitInTraitData, RegionExt, Ty, TyCtxt, TypeVisitable, TypeVisitor, - Upcast, + self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index dbd210e08ea50..a3d91e834a3e8 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -33,7 +33,7 @@ use tracing::{debug, debug_span, instrument}; use crate::diagnostics; use crate::hir::definitions::PerParentDisambiguatorState; -#[extension(trait RegionExt)] +#[extension(trait ResolvedArgExt)] impl ResolvedArg { fn early(param: &GenericParam<'_>) -> ResolvedArg { ResolvedArg::EarlyBound(param.def_id) diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 5324b4d3552c6..1ae3fecf92096 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment}; use rustc_middle::ty::{ - self, EarlyBinder, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::{ErrorGuaranteed, Span, kw}; 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 cfff8d1768f0e..7f53a91d33d07 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -44,7 +44,7 @@ use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, - RegionExt, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, + Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, const_lit_matches_ty, fold_regions, }; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d5217ae5c31d9..3e2d35da5307d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -202,6 +202,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } steps }), + infer_closure_kind: Box::new(|closure_def_id| { + self.infer_closure_kind_for_diagnostic(closure_def_id) + }), } } } diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 0e522b58ea280..e0fccce9577eb 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -13,7 +13,8 @@ use rustc_middle::ty::{ use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use rustc_target::asm::{ - InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo, + InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmSize, InlineAsmType, + ModifierInfo, }; use rustc_trait_selection::infer::InferCtxtExt; @@ -158,6 +159,28 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { _ => Err(NonAsmTypeReason::InvalidElement(field.did, ty)), } } + ty::Adt(adt, _args) if adt.repr().scalable() => { + let (_element_count, elem_ty, _number_of_vectors) = + ty.scalable_vector_parts(self.tcx()).unwrap(); + + match elem_ty.kind() { + ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::SveVecI8), + ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::SveVecI16), + ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::SveVecI32), + ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::SveVecI64), + ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Ok(InlineAsmType::SveVecI128), + ty::Float(FloatTy::F16) => Ok(InlineAsmType::SveVecF16), + ty::Float(FloatTy::F32) => Ok(InlineAsmType::SveVecF32), + ty::Float(FloatTy::F64) => Ok(InlineAsmType::SveVecF64), + ty::Float(FloatTy::F128) => Ok(InlineAsmType::SveVecF128), + ty::Bool => Ok(InlineAsmType::SveVecBool), + _ => { + let fields = &adt.non_enum_variant().fields; + let field = &fields[FieldIdx::ZERO]; + Err(NonAsmTypeReason::InvalidElement(field.did, ty)) + } + } + } ty::Infer(_) => bug!("unexpected infer ty in asm operand"), _ => Err(NonAsmTypeReason::Invalid(ty)), } @@ -177,10 +200,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { idx: usize, suggested_modifier: char, suggested_result: &'a str, - suggested_size: u16, + suggested_size: InlineAsmSize, default_modifier: char, default_result: &'a str, - default_size: u16, + default_size: InlineAsmSize, } impl<'a, 'b> Diagnostic<'a, ()> for FormattingSubRegisterArg<'b> { @@ -195,13 +218,24 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { default_result, default_size, } = self; + + fn format_size(size: InlineAsmSize) -> String { + match size { + InlineAsmSize::FixedBytes(size) => format!("{size}-byte values"), + InlineAsmSize::Scalable => "scalable values".to_string(), + } + } Diag::new(dcx, level, "formatting may not be suitable for sub-register argument") .with_span_label(expr_span, "for this argument") .with_help(format!( - "use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}` (for {suggested_size}-bit values)", + "use `{{{idx}:{suggested_modifier}}}` to have the register formatted as \ + `{suggested_result}` (for {})", + format_size(suggested_size) )) .with_help(format!( - "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}` (for {default_size}-bit values)", + "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of \ + `{default_result}` (for {})", + format_size(default_size) )) } } @@ -239,8 +273,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { NonAsmTypeReason::Invalid(ty) => { let msg = format!("cannot use value of type `{ty}` for inline assembly"); self.fcx.dcx().struct_span_err(expr.span, msg).with_note( - "only integers, floats, SIMD vectors, pointers and function pointers \ - can be used as arguments for inline assembly", + "only integers, floats, SIMD vectors, scalable vectors, pointers and function \ + pointers can be used as arguments for inline assembly", ).emit(); } NonAsmTypeReason::NotSizedPtr(ty) => { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 05062155915d6..e59ca32aba116 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -31,9 +31,7 @@ use rustc_middle::ty::print::{ PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths, with_no_visible_paths_if_doc_hidden, }; -use rustc_middle::ty::{ - self, GenericArgKind, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, -}; +use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 72886730f18c5..38839c598f913 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -81,6 +81,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // it's our job to process these. assert!(self.deferred_call_resolutions.borrow().is_empty()); } + + pub(crate) fn infer_closure_kind_for_diagnostic( + &self, + closure_def_id: LocalDefId, + ) -> Option<(ty::ClosureKind, Option<(Span, Place<'tcx>)>)> { + let hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id); + let hir::Node::Expr(expr) = self.tcx.hir_node_by_def_id(closure_def_id) else { + return None; + }; + let hir::ExprKind::Closure(&hir::Closure { + capture_clause, + body: body_id, + explicit_captures, + .. + }) = expr.kind + else { + return None; + }; + let body = self.tcx.hir_body(body_id); + + // We cannot reliably infer the closure kind if there are nested closures whose + // captures have not yet been analyzed. + struct HasNestedClosure(bool); + impl<'v> Visitor<'v> for HasNestedClosure { + fn visit_expr(&mut self, expr: &'v hir::Expr<'v>) { + if matches!(expr.kind, hir::ExprKind::Closure(..)) { + self.0 = true; + return; + } + intravisit::walk_expr(self, expr); + } + } + let mut has_nested = HasNestedClosure(false); + has_nested.visit_body(body); + if has_nested.0 { + return None; + } + + let closure_fcx = FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id); + + let mut delegate = InferBorrowKind { + fcx: &closure_fcx, + closure_def_id, + capture_information: Default::default(), + fake_reads: Default::default(), + }; + + let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); + + for capture in explicit_captures { + let place = closure_fcx.place_for_root_variable(closure_def_id, capture.var_hir_id); + delegate.consume(&PlaceWithHirId { hir_id: capture.var_hir_id, place }, hir_id); + } + + let (_, closure_kind, mut origin) = self + .process_collected_capture_information(capture_clause, &delegate.capture_information); + + // Bail out if a by-value capture has unresolved inference variables, since + // fallback might later resolve the type to `Copy` (making the closure `Fn`). + if closure_kind == ty::ClosureKind::FnOnce { + for (place, capture_info) in &delegate.capture_information { + if matches!(capture_info.capture_kind, ty::UpvarCapture::ByValue) + && place.ty().has_infer() + { + return None; + } + } + } + + if !enable_precise_capture(expr.span) { + if let Some((_, ref mut place)) = origin { + place.projections.clear(); + } + } + + Some((closure_kind, origin)) + } } /// Intermediate format to store the hir_id pointing to the use that resulted in the diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 13f0dda180be9..97aad8e6e8c04 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -197,6 +197,11 @@ impl IndexVec { pub fn append(&mut self, other: &mut Self) { self.raw.append(&mut other.raw); } + + #[inline] + pub fn debug_map_view(&self) -> IndexSliceMapView<'_, I, T> { + IndexSliceMapView(self.as_slice()) + } } /// `IndexVec` is often used as a map, so it provides some map-like APIs. @@ -220,11 +225,44 @@ impl IndexVec> { pub fn contains(&self, index: I) -> bool { self.get(index).and_then(Option::as_ref).is_some() } + + /// This debug view will skip printing `None` entries. + /// This is useful when the slice is actually like a map and `None` means + /// a value is absent under that key. + #[inline] + pub fn debug_map_view_compact(&self) -> IndexSliceMapViewCompact<'_, I, T> { + IndexSliceMapViewCompact(self.as_slice()) + } } +pub struct IndexSliceMapView<'a, I: Idx, T>(&'a IndexSlice); +pub struct IndexSliceMapViewCompact<'a, I: Idx, T>(&'a IndexSlice>); + impl fmt::Debug for IndexVec { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.raw, fmt) + fmt::Debug::fmt(self.as_slice(), fmt) + } +} + +impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapView<'a, I, T> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut entries = fmt.debug_map(); + for (idx, val) in self.0.iter_enumerated() { + entries.entry(&idx, val); + } + entries.finish() + } +} + +impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapViewCompact<'a, I, T> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut entries = fmt.debug_map(); + for (idx, val) in self.0.iter_enumerated() { + if let Some(val) = val { + entries.entry(&idx, val); + } + } + entries.finish() } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e193f28f9738d..56fcc72bd9769 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -30,8 +30,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, GenericParamDefKind, InferConst, OpaqueTypeKey, ProvisionalHiddenType, - PseudoCanonicalInput, RegionExt, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + PseudoCanonicalInput, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, }; use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::{CanonicalizerState, MayBeErased}; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 42f686b39136b..cbbf5e3c91c42 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -65,8 +65,8 @@ use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionExt, RegionVid, Ty, - TyCtxt, TypeVisitableExt, eager_resolve_vars, + self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionVid, Ty, TyCtxt, + TypeVisitableExt, eager_resolve_vars, }; use rustc_span::Span; use rustc_type_ir::region_constraint::{self, LeafRegionConstraint}; diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 7db45fde6c8d7..240b288728832 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -8,7 +8,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_index::IndexVec; use rustc_macros::{TypeFoldable, TypeVisitable}; -use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionExt, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 4e99ba176d57b..cbf961f4cc58b 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -20,6 +20,7 @@ rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } +rustc_expand_queries = { path = "../rustc_expand_queries" } rustc_feature = { path = "../rustc_feature" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 2fad0297e31e0..a0a2317dc7532 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -91,4 +91,5 @@ pub fn setup_callbacks() { rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); rustc_errors::TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _)); rustc_feature::TRACK_FEATURE.swap(&(track_feature as _)); + rustc_expand_queries::setup_callbacks(); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c829864b02288..3a8a4224ffa95 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -907,7 +907,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { providers.queries.proc_macro_decls_static = |tcx, _| tcx.hir_crate_items(()).proc_macro_decls(); rustc_ast_lowering::provide(&mut providers.queries); limits::provide(&mut providers.queries); - rustc_expand::provide(&mut providers.queries); + rustc_expand_queries::provide(&mut providers.queries); rustc_const_eval::provide(providers); rustc_middle::hir::provide(&mut providers.queries); rustc_borrowck::provide(&mut providers.queries); diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 257b9e1db8e33..e5845e904229f 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::relate::{ structurally_relate_tys, }; use rustc_middle::ty::{ - self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, }; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 064d906293ae8..b85cc8ec951f7 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -482,8 +482,8 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, - live_args_for_alias_from_outlives_bounds: Table>>>>>, - args_known_to_outlive_alias_params: Table, Vec>)>>>>, + live_args_for_alias_from_outlives_bounds: Table>>, + args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 51f75367f11cf..099697c68464c 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -102,7 +102,7 @@ fn deprecation_lint(is_in_effect: bool) -> &'static Lint { style = "verbose", applicability = "machine-applicable" )] -pub struct DeprecationSuggestion { +pub(crate) struct DeprecationSuggestion { #[primary_span] pub span: Span, @@ -110,7 +110,7 @@ pub struct DeprecationSuggestion { pub suggestion: Symbol, } -pub struct Deprecated { +pub(crate) struct Deprecated { pub sub: Option, pub kind: String, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5794a6533bd1d..1721b36e7aecb 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2157,9 +2157,9 @@ rustc_queries! { desc { "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } } - /// For an opaque type or trait associated type, return the list of potentially live - /// (identity) generic args from the set of outlives bounds on that alias. Callers should - /// instantiate the returned args with the concrete args of the alias. + /// For an opaque type or trait associated type, return the indices of potentially live + /// generic args from the set of outlives bounds on that alias. Callers should use the + /// indices with the concrete args of the alias. /// ```ignore (illustrative) /// // Edition 2024: all args are captured /// fn foo<'a, 'b, T: 'static>(&'a &'b T) -> impl Sized + 'a {} @@ -2171,17 +2171,17 @@ rustc_queries! { /// - `foo` outlives `'a`, but we know that `'b: 'a` holds, so `'b` is *also* potentially live /// (and so is `T`, since `T: 'static` implies `T: 'a`) /// - `bar` outlives `'static`, so we know that no args are potentially live and we can return an empty set - /// - `baz` has no outlives bound, so return `None` and let the caller decide what to do - query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option>>> { + /// - `baz` has no outlives bound, so all args are potentially live + query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx rustc_index::bit_set::DenseBitSet { arena_cache desc { "identifying live args for alias `{:?}`", kind } } - /// For each region param of an alias, the identity args that are known to + /// For each region param of an alias, the indices of the identity args that are known to /// outlive it given only the alias's declared where-clauses. Used for liveness: /// these are the only args whose regions the underlying type of the alias /// could capture while satisfying an outlives bound on that param. - query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { + query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx Vec<(usize, rustc_index::bit_set::DenseBitSet)> { arena_cache desc { "computing the args known to outlive each region param of alias `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 0eea804b7cb53..af25d881f53bd 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -65,6 +65,8 @@ bitflags::bitflags! { /// Indicates whether the type is `FieldRepresentingType`. const IS_FIELD_REPRESENTING_TYPE = 1 << 13; /// Indicates whether the type is `MaybeDangling<_>`. + /// Note that this is not the only type with "maybe dangling" semantics! + /// Use `ty.is_like_maybe_dangling()` to check for that. const IS_MAYBE_DANGLING = 1 << 14; } } @@ -528,12 +530,6 @@ impl<'tcx> AdtDef<'tcx> { self.flags().contains(AdtFlags::IS_MANUALLY_DROP) } - /// Returns `true` if this is `MaybeDangling`. - #[inline] - pub fn is_maybe_dangling(self) -> bool { - self.flags().contains(AdtFlags::IS_MAYBE_DANGLING) - } - /// Returns `true` if this is `Pin`. #[inline] pub fn is_pin(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5b5656c05f10d..df46910c06e83 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -68,7 +68,6 @@ use crate::traits::solve::{ PredefinedOpaques, }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; -use crate::ty::region::RegionExt; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, ClausePolarity, Clauses, Const, FnSigKind, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..2522801e2f198 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}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, TypeFoldable, Unnormalized, VisitorResult, - search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, + VisitorResult, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -650,6 +650,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(span, msg.to_string()) + } + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { self.is_general_coroutine(coroutine_def_id) } @@ -733,6 +737,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.lifetimes.re_static } + fn intern_re_var(self, rv: RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + self.lifetimes + .re_vars + .get(rv.as_usize()) + .copied() + .unwrap_or_else(|| self.intern_region(ty::ReVar(rv))) + } + fn intern_region(self, region_kind: RegionKind<'tcx>) -> Region<'tcx> { self.intern_region(region_kind) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index c146e7c982de9..3d9148d6ed7ba 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; -use crate::ty::region::RegionExt; use crate::ty::{ self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index bfdb89dc409f6..f5e983ab48f92 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -9,7 +9,6 @@ use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor}; use tracing::instrument; use super::{Clause, InstantiatedClauses, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized}; -use crate::ty::region::RegionExt; use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind}; #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash)] @@ -152,6 +151,9 @@ impl<'tcx> rustc_type_ir::inherent::GenericsOf> for &'tcx Generics fn count(&self) -> usize { self.parent_count + self.own_params.len() } + fn param_region_def_id(self, tcx: TyCtxt<'tcx>, ebr: ty::EarlyParamRegion) -> DefId { + self.region_param(ebr, tcx).def_id + } } impl<'tcx> Generics { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 764f3b5b93318..c18bf81121377 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1090,20 +1090,6 @@ where }) } - ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => { - Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| { - PointeeInfo { - // Mark the pointer as raw - // (thus removing noalias/readonly/etc in case of the llvm backend) - safe: None, - // Make sure we don't assert dereferenceability of the pointer. - size: Size::ZERO, - // Preserve the alignment assertion! That is required even inside `MaybeDangling`. - align: info.align, - } - }) - } - _ => { let mut data_variant = match &this.variants { // Within the discriminant field, only the niche itself is @@ -1179,6 +1165,21 @@ where } } + // Patch result if we are a MaybeDangling-like type. + if this.ty.is_like_maybe_dangling() + && let Some(info) = result + { + result = Some(PointeeInfo { + // Mark the pointer as raw + // (thus removing noalias/readonly/etc in case of the llvm backend) + safe: None, + // Make sure we don't assert dereferenceability of the pointer. + size: Size::ZERO, + // Preserve the alignment assertion! That is required even inside `MaybeDangling`. + align: info.align, + }); + } + result } }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3db521dfb5dee..2edfba321d265 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -96,8 +96,7 @@ pub use self::predicate::{ TraitRef, TypeOutlivesClause, }; pub use self::region::{ - EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionExt, RegionKind, - RegionVid, + EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ Alias, AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, @@ -508,7 +507,7 @@ impl TyCtxt<'_> { /// Compare def-ids based on their position in def-id tree, ancestor def-ids are considered /// larger than descendant def-ids, and two different def-ids are considered unordered if /// neither of them is an ancestor of the other. - fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option { + pub fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option { // Def-ids from different crates are always unordered. if lhs.krate != rhs.krate { return None; diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d835a3d2153a..bf716e8027a0a 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -5,8 +5,7 @@ use tracing::{debug, instrument, trace}; use crate::diagnostics::ConstNotUsedTraitAlias; use crate::ty::{ - self, GenericArg, GenericArgKind, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, + self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, }; pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey>; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f5960e65c4493..07e935e265c8b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -24,7 +24,6 @@ use smallvec::SmallVec; use super::*; use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::{IntoQueryKey, Providers}; -use crate::ty::region::RegionExt; use crate::ty::{ ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitClause, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 154873c435e1c..fbb40465cd5fd 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -1,7 +1,6 @@ -use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; -use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Symbol, kw, sym}; +use rustc_macros::{StableHash, TyDecodable, TyEncodable}; +use rustc_span::{Symbol, kw}; pub use rustc_type_ir::RegionVid; use rustc_type_ir::{ LateParamRegion as IrLateParamRegion, Region as IrRegion, RegionKind as IrRegionKind, @@ -13,139 +12,6 @@ pub type Region<'tcx> = IrRegion>; pub type RegionKind<'tcx> = IrRegionKind>; pub type LateParamRegion<'tcx> = IrLateParamRegion>; -#[extension(pub trait RegionExt<'tcx>)] -impl<'tcx> Region<'tcx> { - #[inline] - fn new_early_param( - tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyParamRegion, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyParam(early_bound_region)) - } - - #[inline] - fn new_late_param(tcx: TyCtxt<'tcx>, scope: DefId, kind: LateParamRegionKind) -> Region<'tcx> { - let data = LateParamRegion { scope, kind }; - tcx.intern_region(ty::ReLateParam(data)) - } - - #[inline] - fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { - // Use a pre-interned one when possible. - tcx.lifetimes - .re_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) - } - - /// Constructs a `RegionKind::ReError` region. - #[track_caller] - fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Region<'tcx> { - tcx.intern_region(ty::ReError(guar)) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets - /// used. - #[track_caller] - fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { - Region::new_error_with_message( - tcx, - DUMMY_SP, - "RegionKind::ReError constructed but no error reported", - ) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` - /// to ensure it gets used. - #[track_caller] - fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: &'static str, - ) -> Region<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Region::new_error(tcx, reported) - } - - /// Avoid this in favour of more specific `new_*` methods, where possible, - /// to avoid the cost of the `match`. - fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - match kind { - ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), region) => { - Region::new_bound(tcx, debruijn, region) - } - ty::ReBound(ty::BoundVarIndexKind::Canonical, region) => { - Region::new_canonical_bound(tcx, region.var) - } - ty::ReLateParam(ty::LateParamRegion { scope, kind }) => { - Region::new_late_param(tcx, scope, kind) - } - ty::ReStatic => tcx.lifetimes.re_static, - ty::ReVar(vid) => Region::new_var(tcx, vid), - ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), - ty::ReErased => tcx.lifetimes.re_erased, - ty::ReError(reported) => Region::new_error(tcx, reported), - } - } - - fn get_name(self, tcx: TyCtxt<'tcx>) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named().then_some(ebr.name), - ty::ReBound(_, br) => br.kind.get_name(tcx), - ty::ReLateParam(fr) => fr.kind.get_name(tcx), - ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(tcx), - _ => None, - } - } - - fn get_name_or_anon(self, tcx: TyCtxt<'tcx>) -> Symbol { - match self.get_name(tcx) { - Some(name) => name, - None => sym::anon, - } - } - - /// Is this region named by the user? - fn is_named(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named(), - ty::ReBound(_, br) => br.kind.is_named(tcx), - ty::ReLateParam(fr) => fr.kind.is_named(tcx), - ty::ReStatic => true, - ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(tcx), - ty::ReErased => false, - ty::ReError(_) => false, - } - } - - #[inline] - fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match self.kind() { - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, - _ => false, - } - } - - /// Given some item `binding_item`, check if this region is a generic parameter introduced by it - /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. - fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => { - Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) - } - ty::ReLateParam(ty::LateParamRegion { - kind: ty::LateParamRegionKind::Named(def_id), - .. - }) => Some(def_id), - _ => None, - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(StableHash)] pub struct EarlyParamRegion { @@ -154,6 +20,12 @@ pub struct EarlyParamRegion { } impl EarlyParamRegion { + #[inline] + pub fn get_name(&self) -> Option { + if self.is_named() { Some(self.name) } else { None } + } + + #[inline] /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn is_named(&self) -> bool { @@ -167,6 +39,20 @@ impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for EarlyParamRegion { + #[inline] + fn get_name(&self, _tcx: TyCtxt<'tcx>) -> Option { + self.get_name() + } + + #[inline] + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + fn is_named(&self, _tcx: TyCtxt<'tcx>) -> bool { + self.is_named() + } +} + impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/#{}", self.name, self.index) @@ -237,6 +123,24 @@ impl LateParamRegionKind { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for LateParamRegionKind { + #[inline] + fn get_name(&self, tcx: TyCtxt<'tcx>) -> Option { + self.get_name(tcx) + } + + #[inline] + fn is_named(&self, tcx: TyCtxt<'tcx>) -> bool { + self.is_named(tcx) + } +} + +impl<'tcx> rustc_type_ir::inherent::DefIdGetter> for LateParamRegionKind { + fn get_def_id(self) -> Option { + self.get_id() + } +} + // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 013064b5cec4b..8014a52c9b4e1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -23,7 +23,7 @@ use rustc_type_ir::{ use tracing::instrument; use ty::util::IntTypeExt; -use super::GenericParamDefKind; +use super::{AdtFlags, GenericParamDefKind}; use crate::infer::canonical::Canonical; use crate::traits::ObligationCause; use crate::ty::InferTy::*; @@ -2183,6 +2183,22 @@ impl<'tcx> Ty<'tcx> { pub fn walk(self) -> TypeWalker> { TypeWalker::new(self.into()) } + + /// Returns `true` if this is a `MaybeDangling`-like type, i.e., a type whose inner + /// references are not required to be dereferenceable and are not reborrowed. + #[inline] + pub fn is_like_maybe_dangling(self) -> bool { + match self.kind() { + ty::Adt(def, _) => { + // ManuallyDrop is "natively" like maybe-dangling so that we don't have + // to nest field types even deeper. + def.flags().contains(AdtFlags::IS_MAYBE_DANGLING) + || def.flags().contains(AdtFlags::IS_MANUALLY_DROP) + } + ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineClosure(..) => true, + _ => false, + } + } } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { @@ -2196,9 +2212,9 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { - fn is_kw_underscore_lifetime(self) -> bool { - self == kw::UnderscoreLifetime - } + const KW_UNDERSCORE_LIFETIME: Self = kw::UnderscoreLifetime; + const KW_STATIC_LIFETIME: Self = kw::StaticLifetime; + const SYM_ANON: Self = sym::anon; } // Some types are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 72135df46e904..d5ce1dab1b417 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -457,9 +457,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = b.project_deeper(&[ProjectionElem::Deref], tcx); // Current type: `MaybeUninit`. Field #1 is `ManuallyDrop`. let place = place.project_to_field(FieldIdx::from_u32(1), decls, tcx); - // Current type: `ManuallyDrop`. Field #0 is `MaybeDangling`. - let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); - // Current type: `MaybeDangling`. Field #0 is `T`. + // Current type: `ManuallyDrop`. Field #0 is `T`. let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); // Sanity check. assert_eq!(place.ty(decls, tcx).ty, generic_args.type_at(0)); diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 7e5ea6bf3c22c..885ad6071d91c 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -65,9 +65,17 @@ fn do_check_simd_vector_abi<'tcx>( let size = arg_abi.layout.size; match passes_vectors_by_value(&arg_abi.mode, &arg_abi.layout.backend_repr) { UsesVectorRegisters::FixedVector => { + // Some targets use homogeneous aggregates, where the unit size counts. + let unit_size = match &arg_abi.mode { + PassMode::Cast { pad_i32_count: _, cast } if cast.prefix.is_empty() => { + cast.rest.unit.size + } + _ => size, + }; + let feature_def = tcx.sess.target.features_for_correct_fixed_length_vector_abi(); // Find the first feature that provides at least this vector size. - let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) { + let feature = match feature_def.iter().find(|(bits, _)| unit_size.bits() <= *bits) { Some((_, feature)) => feature, None => { let (span, _hir_id) = loc(); diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index c343d9c7078e7..5c2ba5b33f11f 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1164,3 +1164,20 @@ pub(crate) struct ConstFnLinkage { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("use of deprecated import through accidentally stabilized module `{$module}`")] +pub(crate) struct RustcAtumSuggestion { + #[primary_span] + pub import_span: Span, + pub message: Symbol, + pub suggestion: Symbol, + pub module: Ident, + #[suggestion( + "{$message}", + code = "{suggestion}", + style = "verbose", + applicability = "machine-applicable" + )] + pub unstable_mod_span: Span, +} diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 7404b466f1d54..23cc86ae6ae61 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -16,16 +16,15 @@ use rustc_hir::{ ItemKind, Path, Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason, UsePath, VERSION_PLACEHOLDER, Variant, find_attr, }; -use rustc_lint_defs as lint; use rustc_lint_defs::builtin::{ DEPRECATED, DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, STABLE_FEATURES, }; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::privacy::EffectiveVisibilities; -use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult}; +use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, EvalResult}; use rustc_middle::query::{LocalCrate, Providers}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::span_bug; use rustc_middle::ty::{AssocContainer, TyCtxt}; use rustc_span::{Span, Symbol, sym}; use tracing::instrument; @@ -790,7 +789,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if item_is_allowed { // The item itself is allowed; check whether the path there is also allowed. - let is_allowed_through_unstable_modules: Option = + let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { allowed_through_unstable_modules @@ -829,7 +828,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { }, ); } - Some(deprecation) => { + Some((message, suggestion)) => { // Call the stability check directly so that we can control which // diagnostic is emitted. let eval_result = self.tcx.eval_stability_allow_unstable( @@ -845,22 +844,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { ); let is_allowed = matches!(eval_result, EvalResult::Allow); if !is_allowed { - // Calculating message for lint involves calling `self.def_path_str`, - // which will by default invoke the expensive `visible_parent_map` query. - // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_spec_at_node(DEPRECATED, id).is_allow() { - return; - } // Show a deprecation message. - let def_path = - with_no_trimmed_paths!(self.tcx.def_path_str(def_id)); - let def_kind = self.tcx.def_descr(def_id); - let diag = Deprecated { - sub: None, - kind: def_kind.to_owned(), - path: def_path, - note: Some(deprecation), - since_kind: lint::DeprecatedSinceKind::InEffect, + let [.., intrinsics_module, _intrinsic] = path.segments else { + span_bug!( + path.span, + "no module for `is_allowed_through_unstable_modules` intrinsic {path:?}" + ) + }; + let diag = diagnostics::RustcAtumSuggestion { + message, + import_span: path.span, + unstable_mod_span: { intrinsics_module.ident.span }, + module: intrinsics_module.ident, + suggestion, }; self.tcx.emit_node_span_lint( DEPRECATED, diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 9a84985bed51a..a005824e5dbfa 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -50,7 +50,7 @@ use crate::diagnostics::{ }; use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::{Import, ImportKind, UnresolvedImportError, import_path_to_string}; -use crate::late::{DiagMetadata, PatternSource, Rib}; +use crate::late::{ConstantRequiresType, DiagMetadata, PatternSource, Rib}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind, DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, @@ -1188,6 +1188,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion, current, type_span, + requires_type, } => { // let foo =... // ^^^ given this Span @@ -1224,11 +1225,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if is_simple_binding { ( - Some(diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion { - span: sp, - suggestion, - current, - type_span, + Some(match requires_type { + ConstantRequiresType::Usize => { + diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Usize { + span: sp, + suggestion, + current, + type_span, + } + } + ConstantRequiresType::No => { + diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Placeholder { + span: sp, + suggestion, + current, + type_span, + } + } }), Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }), None, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index 624f180361f5b..dfa58ab73778f 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -288,19 +288,33 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - "consider using `{$suggestion}` instead of `{$current}`", - style = "verbose", - applicability = "has-placeholders" -)] -pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { - // #[primary_span] - #[suggestion_part(code = "{suggestion} ")] - pub(crate) span: Span, - pub(crate) suggestion: &'a str, - #[suggestion_part(code = ": /* Type */")] - pub(crate) type_span: Option, - pub(crate) current: &'a str, +pub(crate) enum AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { + #[multipart_suggestion( + "consider using `{$suggestion}` instead of `{$current}`", + style = "verbose", + applicability = "has-placeholders" + )] + Placeholder { + #[suggestion_part(code = "{suggestion} ")] + span: Span, + suggestion: &'a str, + #[suggestion_part(code = ": /* Type */")] + type_span: Option, + current: &'a str, + }, + #[multipart_suggestion( + "consider using `{$suggestion}` instead of `{$current}`", + style = "verbose", + applicability = "machine-applicable" + )] + Usize { + #[suggestion_part(code = "{suggestion} ")] + span: Span, + suggestion: &'a str, + #[suggestion_part(code = ": usize")] + type_span: Option, + current: &'a str, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index ebcdb8603eccd..994778da525ac 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1512,7 +1512,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem)); } } - RibKind::ConstantItem(_, item) => { + RibKind::ConstantItem(_, item, requires_type) => { // Still doesn't deal with upvars if let Some(span) = finalize { let (span, resolution_error) = match item { @@ -1541,6 +1541,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion: "const", current: "let", type_span, + requires_type, }, ) } @@ -1551,6 +1552,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion: "let", current: kind.as_str(), type_span: None, + requires_type, }, ), }; @@ -1621,7 +1623,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - RibKind::ConstantItem(trivial, _) => { + RibKind::ConstantItem(trivial, _, _) => { if let ConstantHasGenerics::No(cause) = trivial && !matches!(res, Res::SelfTyAlias { .. }) { @@ -1715,7 +1717,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - RibKind::ConstantItem(trivial, _) => { + RibKind::ConstantItem(trivial, _, _) => { if let ConstantHasGenerics::No(cause) = trivial { if let Some(span) = finalize { let error = match cause { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 396db754f7c96..79ebfef8466fd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -80,6 +80,7 @@ enum AnonConstKind { FieldDefaultValue, InlineConst, ConstArg(IsRepeatExpr), + ArrayLength, } impl PatternSource { @@ -137,6 +138,13 @@ pub(crate) enum ConstantHasGenerics { No(NoConstantGenericsReason), } +/// Does this constant requires an specific type? +#[derive(Copy, Clone, Debug)] +pub(crate) enum ConstantRequiresType { + Usize, + No, +} + impl ConstantHasGenerics { fn force_yes_if(self, b: bool) -> Self { if b { Self::Yes } else { self } @@ -215,7 +223,9 @@ pub(crate) enum RibKind<'ra> { /// /// The item may reference generic parameters in trivial constant expressions. /// All other constants aren't allowed to use generic params at all. - ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), + /// + /// If the constant comes from specific contexts (like array length) it might require an specific type. + ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>, ConstantRequiresType), /// We passed through a module item. Module(LocalModule<'ra>), @@ -1023,7 +1033,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc } TyKind::Array(element_ty, length) => { self.visit_ty(element_ty); - self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No)); + self.resolve_anon_const(length, AnonConstKind::ArrayLength); } TyKind::DirectConstArg(expr) => self.resolve_anon_const_manual( true, @@ -3028,6 +3038,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.with_constant_rib( IsRepeatExpr::No, ConstantHasGenerics::Yes, + ConstantRequiresType::No, Some((ConstBlockItem::IDENT, ConstantItemKind::Const)), |this| this.resolve_labeled_block(None, block.id, block), ) @@ -3306,22 +3317,31 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, is_repeat: IsRepeatExpr, may_use_generics: ConstantHasGenerics, + requires_type: ConstantRequiresType, item: Option<(Ident, ConstantItemKind)>, f: impl FnOnce(&mut Self), ) { let f = |this: &mut Self| { - this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| { - this.with_rib( - TypeNS, - RibKind::ConstantItem( - may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), - item, - ), - |this| { - this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f); - }, - ) - }) + this.with_rib( + ValueNS, + RibKind::ConstantItem(may_use_generics, item, requires_type), + |this| { + this.with_rib( + TypeNS, + RibKind::ConstantItem( + may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), + item, + requires_type, + ), + |this| { + this.with_label_rib( + RibKind::ConstantItem(may_use_generics, item, requires_type), + f, + ); + }, + ) + }, + ) }; if let ConstantHasGenerics::No(cause) = may_use_generics { @@ -3898,9 +3918,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_static_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) { self.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { - this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { - this.visit_expr(expr) - }); + this.with_constant_rib( + IsRepeatExpr::No, + ConstantHasGenerics::Yes, + ConstantRequiresType::No, + item, + |this| this.visit_expr(expr), + ); }) } @@ -3911,9 +3935,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) { if let Some(body) = body { self.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { - this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { - this.visit_expr(body) - }) + this.with_constant_rib( + IsRepeatExpr::No, + ConstantHasGenerics::Yes, + ConstantRequiresType::No, + item, + |this| this.visit_expr(body), + ) }) } } @@ -5177,7 +5205,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, - AnonConstKind::ConstArg(_) => { + AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() || self.r.features.min_generic_const_args() || is_trivial_const_arg @@ -5189,7 +5217,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }; - self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| { + let requires_type = match anon_const_kind { + AnonConstKind::ArrayLength | AnonConstKind::ConstArg(IsRepeatExpr::Yes) => { + ConstantRequiresType::Usize + } + _ => ConstantRequiresType::No, + }; + + self.with_constant_rib(is_repeat_expr, may_use_generics, requires_type, None, |this| { this.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Infer), |this| { resolve_expr(this); }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5e684cb81631..23efe70f8b71b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -32,8 +32,8 @@ use effective_visibilities::EffectiveVisibilitiesVisitor; use hygiene::Macros20NormalizedSyntaxContext; use imports::{Import, ImportData, ImportKind, NameResolution, PendingDecl}; use late::{ - ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource, - UnnecessaryQualification, + ConstantRequiresType, ForwardGenericParamBanReason, HasGenericParams, PathSource, + PatternSource, UnnecessaryQualification, }; pub use macros::registered_lint_tools_ast; use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; @@ -284,6 +284,7 @@ enum ResolutionError<'ra> { suggestion: &'static str, current: &'static str, type_span: Option, + requires_type: ConstantRequiresType, }, /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 71333dfdaff87..8fd9c4da967dc 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -94,13 +94,15 @@ mod target_modifier_consistency_check { l: &TargetModifier, r: Option<&TargetModifier>, ) -> bool { - let mut lparsed: SanitizerSet = sess.target.options.default_sanitizers; + let mut lparsed: SanitizerSet = SanitizerSet::empty(); let lval = if l.value_name.is_empty() { None } else { Some(l.value_name.as_str()) }; parse::parse_sanitizers(&mut lparsed, lval); + let lparsed = lparsed.combine_with_defaults(sess.target.options.default_sanitizers); - let mut rparsed: SanitizerSet = sess.target.options.default_sanitizers; + let mut rparsed: SanitizerSet = SanitizerSet::empty(); let rval = r.filter(|v| !v.value_name.is_empty()).map(|v| v.value_name.as_str()); parse::parse_sanitizers(&mut rparsed, rval); + let rparsed = rparsed.combine_with_defaults(sess.target.options.default_sanitizers); // Some sanitizers need to be target modifiers, and some do not. // For now, we should mark all sanitizers as target modifiers except for these: diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f04f40dd17168..87190e232c693 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -95,6 +95,7 @@ pub enum PointerAuthARM8_3Key { } /// Forms of extra discrimination. +#[derive(Clone, Debug, PartialEq)] pub enum PointerAuthDiscrimination { /// No additional discrimination. None, @@ -107,6 +108,7 @@ pub enum PointerAuthDiscrimination { } /// Types of address discrimination. +#[derive(Clone, Debug)] pub enum PointerAuthAddressDiscriminator { /// Enable/disable hardware address discrimination. HardwareAddress(bool), @@ -115,6 +117,7 @@ pub enum PointerAuthAddressDiscriminator { Synthetic(u64), } +#[derive(Clone, Debug)] pub struct PointerAuthSchema { pub is_address_discriminated: PointerAuthAddressDiscriminator, pub discrimination_kind: PointerAuthDiscrimination, @@ -929,7 +932,7 @@ impl Session { let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) || self.opts.output_types.contains_key(&OutputType::Bitcode) // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue. - || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); + || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); !more_names } } @@ -1178,19 +1181,36 @@ impl Session { } pub fn sanitizers(&self) -> SanitizerSet { - return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers; + self.opts + .unstable_opts + .sanitizer + .combine_with_defaults(self.target.options.default_sanitizers) } pub fn pointer_authentication(&self) -> bool { self.pointer_auth_config.is_some() } - pub fn pointer_authentication_functions(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.as_ref()) + pub fn pointer_authentication_functions(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.clone()) + } + + pub fn pointer_authentication_init_fini(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.clone()) } - pub fn pointer_authentication_init_fini(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.as_ref()) + pub fn pointer_authentication_fn_ptr_type_discrimination(&self) -> bool { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .is_some_and(|schema| schema.discrimination_kind == PointerAuthDiscrimination::Type) + } + + pub fn pointer_authentication_fn_ptr_key(&self) -> Option { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .map(|schema| schema.key) } } @@ -1497,7 +1517,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Sanitizers can only be used on platforms that we know have working sanitizer codegen. let supported_sanitizers = sess.target.options.supported_sanitizers; - let mut unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers; + let mut unsupported_sanitizers = sess.sanitizers() - supported_sanitizers; // Niche: if `fixed-x18`, or effectively switching on `reserved-x18` flag, is enabled // we should allow Shadow Call Stack sanitizer. if sess.opts.unstable_opts.fixed_x18 && sess.target.arch == Arch::AArch64 { @@ -1518,7 +1538,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } // Cannot mix and match mutually-exclusive sanitizers. - if let Some((first, second)) = sess.opts.unstable_opts.sanitizer.mutually_exclusive() { + if let Some((first, second)) = sess.sanitizers().mutually_exclusive() { sess.dcx().emit_err(diagnostics::CannotMixAndMatchSanitizers { first: first.to_string(), second: second.to_string(), @@ -1526,10 +1546,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } // Cannot enable crt-static with sanitizers on Linux - if sess.crt_static(None) - && !sess.opts.unstable_opts.sanitizer.is_empty() - && !sess.target.is_like_msvc - { + if sess.crt_static(None) && !sess.sanitizers().is_empty() && !sess.target.is_like_msvc { sess.dcx().emit_err(diagnostics::CannotEnableCrtStaticLinux); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 768f1be1cd48d..7665df4a4e5ae 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -957,6 +957,7 @@ symbols! { ffi_const, ffi_pure, ffi_returns_twice, + ffr, field, field_base, field_init_shorthand, @@ -2067,6 +2068,7 @@ symbols! { suggestion, super_let, supertrait_item_shadowing, + sve, sve_cast, sve_tuple_create2, sve_tuple_create3, diff --git a/compiler/rustc_structures/src/lib.rs b/compiler/rustc_structures/src/lib.rs index a7ebea5ba9943..cb5dccdfcd180 100644 --- a/compiler/rustc_structures/src/lib.rs +++ b/compiler/rustc_structures/src/lib.rs @@ -13,3 +13,6 @@ pub use crate_type::CrateType; pub use limit::Limit; pub use native_lib_kind::NativeLibKind; pub use sanitizer_set::SanitizerSet; + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_structures/src/sanitizer_set.rs b/compiler/rustc_structures/src/sanitizer_set.rs index bce77f3abc05b..a41577441de8c 100644 --- a/compiler/rustc_structures/src/sanitizer_set.rs +++ b/compiler/rustc_structures/src/sanitizer_set.rs @@ -95,6 +95,20 @@ impl SanitizerSet { .find(|&(a, b)| self.contains(*a) && self.contains(*b)) .copied() } + + /// Disable default sanitizers that are incompatible with explicitly requested ones, + /// matching Clang's `SanitizerArgs` driver logic. + pub fn combine_with_defaults(self, mut defaults: SanitizerSet) -> SanitizerSet { + for &(a, b) in Self::MUTUALLY_EXCLUSIVE { + if defaults.contains(a) && self.contains(b) { + defaults -= a; + } + if defaults.contains(b) && self.contains(a) { + defaults -= b; + } + } + self | defaults + } } /// Formats a sanitizer set as a comma separated list of sanitizers' names. diff --git a/compiler/rustc_structures/src/tests.rs b/compiler/rustc_structures/src/tests.rs new file mode 100644 index 0000000000000..3d61d5bf3331f --- /dev/null +++ b/compiler/rustc_structures/src/tests.rs @@ -0,0 +1,36 @@ +use super::*; + +#[test] +fn test_combine_with_defaults_no_conflict() { + let defaults = SanitizerSet::SHADOWCALLSTACK; + let explicit = SanitizerSet::ADDRESS; + assert_eq!( + explicit.combine_with_defaults(defaults), + SanitizerSet::ADDRESS | SanitizerSet::SHADOWCALLSTACK + ); +} + +#[test] +fn test_combine_with_defaults_safestack_address_conflict() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::ADDRESS; + // SafeStack should be implicitly disabled when Address is explicitly provided. + assert_eq!(explicit.combine_with_defaults(defaults), SanitizerSet::ADDRESS); +} + +#[test] +fn test_combine_with_defaults_empty_explicit() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::empty(); + assert_eq!(explicit.combine_with_defaults(defaults), SanitizerSet::SAFESTACK); +} + +#[test] +fn test_combine_with_defaults_safestack_cfi() { + let defaults = SanitizerSet::SAFESTACK; + let explicit = SanitizerSet::CFI; + assert_eq!( + explicit.combine_with_defaults(defaults), + SanitizerSet::CFI | SanitizerSet::SAFESTACK + ); +} diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 2db8a7ff3020d..83d249262c104 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,9 +1,10 @@ +use core::convert::Into; use std::fmt; use rustc_data_structures::fx::FxIndexSet; use rustc_span::{Symbol, sym}; -use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use super::{InlineAsmArch, InlineAsmSize, InlineAsmType, ModifierInfo}; use crate::spec::{Env, Os, RelocModel, Target}; def_reg_class! { @@ -12,6 +13,7 @@ def_reg_class! { vreg, vreg_low16, preg, + ffr, } } @@ -19,8 +21,8 @@ impl AArch64InlineAsmRegClass { pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { match self { Self::reg => &['w', 'x'], - Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'], - Self::preg => &[], + Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v', 'z'], + Self::preg | Self::ffr => &[], } } @@ -30,43 +32,67 @@ impl AArch64InlineAsmRegClass { pub fn suggest_modifier(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg => match ty.size().bits() { - 64 => None, - _ => Some(('w', "w0", 32).into()), + Self::reg => match ty.size() { + InlineAsmSize::FixedBytes(8) => None, + _ => Some(('w', "w0", InlineAsmSize::FixedBytes(4)).into()), }, - Self::vreg | Self::vreg_low16 => match ty.size().bits() { - 8 => Some(('b', "b0", 8).into()), - 16 => Some(('h', "h0", 16).into()), - 32 => Some(('s', "s0", 32).into()), - 64 => Some(('d', "d0", 64).into()), - 128 => Some(('q', "q0", 128).into()), + Self::vreg | Self::vreg_low16 => match ty.size() { + InlineAsmSize::FixedBytes(1) => Some(('b', "b0", ty.size()).into()), + InlineAsmSize::FixedBytes(2) => Some(('h', "h0", ty.size()).into()), + InlineAsmSize::FixedBytes(4) => Some(('s', "s0", ty.size()).into()), + InlineAsmSize::FixedBytes(8) => Some(('d', "d0", ty.size()).into()), + InlineAsmSize::FixedBytes(16) => Some(('q', "q0", ty.size()).into()), + InlineAsmSize::Scalable => Some(('z', "z0", InlineAsmSize::Scalable).into()), _ => None, }, - Self::preg => None, + Self::preg | Self::ffr => None, } } pub fn default_modifier(self, _arch: InlineAsmArch) -> Option { match self { - Self::reg => Some(('x', "x0", 64).into()), - Self::vreg | Self::vreg_low16 => Some(('v', "v0", 128).into()), - Self::preg => None, + Self::reg => Some(('x', "x0", InlineAsmSize::FixedBytes(8)).into()), + Self::vreg | Self::vreg_low16 => { + Some(('v', "v0", InlineAsmSize::FixedBytes(16)).into()) + } + Self::preg | Self::ffr => None, } } pub fn supported_types( self, _arch: InlineAsmArch, + allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg => types! { _: I8, I16, I32, I64, F16, F32, F64; }, - Self::vreg | Self::vreg_low16 => types! { - neon: I8, I16, I32, I64, F16, F32, F64, F128, - VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); - // Note: When adding support for SVE vector types, they must be rejected for Arm64EC. - }, - Self::preg => &[], + Self::vreg | Self::vreg_low16 => { + if allow_experimental_reg { + types! { + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); + sve: SveVecI8, SveVecI16, SveVecI32, SveVecI64, SveVecI128, SveVecF16, SveVecF32, + SveVecF64, SveVecI128, SveVecF128; + } + } else { + types! { + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); + } + } + } + Self::preg => { + if allow_experimental_reg { + types! { + sve: SveVecBool; + } + } else { + &[] + } + } + Self::ffr => &[], } } } @@ -190,7 +216,7 @@ def_regs! { p13: preg = ["p13"] % restricted_for_arm64ec, p14: preg = ["p14"] % restricted_for_arm64ec, p15: preg = ["p15"] % restricted_for_arm64ec, - ffr: preg = ["ffr"] % restricted_for_arm64ec, + ffr: ffr = ["ffr"] % restricted_for_arm64ec, #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff --git a/compiler/rustc_target/src/asm/amdgpu.rs b/compiler/rustc_target/src/asm/amdgpu.rs index 0f24ae5dea225..a344ad15bfa21 100644 --- a/compiler/rustc_target/src/asm/amdgpu.rs +++ b/compiler/rustc_target/src/asm/amdgpu.rs @@ -168,7 +168,7 @@ impl AmdgpuInlineAsmRegClass { return None; } - Some(Self::Vgpr(ty.size().bits().try_into().ok()?)) + Some(Self::Vgpr(ty.size().fixed_size_bytes().map(|byte| byte * 8)?.try_into().ok()?)) } pub fn suggest_modifier( diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 03301e50b489b..6f9751e807490 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use std::fmt; -use rustc_abi::Size; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::Symbol; @@ -11,11 +10,11 @@ use crate::spec::{Arch, RelocModel, Target}; pub struct ModifierInfo { pub modifier: char, pub result: &'static str, - pub size: u16, + pub size: InlineAsmSize, } -impl From<(char, &'static str, u16)> for ModifierInfo { - fn from((modifier, result, size): (char, &'static str, u16)) -> Self { +impl From<(char, &'static str, InlineAsmSize)> for ModifierInfo { + fn from((modifier, result, size): (char, &'static str, InlineAsmSize)) -> Self { Self { modifier, result, size } } } @@ -649,7 +648,7 @@ impl InlineAsmRegClass { match self { Self::X86(r) => r.supported_types(arch, allow_experimental_reg).into(), Self::Arm(r) => r.supported_types(arch).into(), - Self::AArch64(r) => r.supported_types(arch).into(), + Self::AArch64(r) => r.supported_types(arch, allow_experimental_reg).into(), Self::Amdgpu(r) => r.supported_types(arch).into(), Self::RiscV(r) => r.supported_types(arch).into(), Self::Nvptx(r) => r.supported_types(arch).into(), @@ -796,6 +795,31 @@ pub enum InlineAsmType { VecF32(u64), VecF64(u64), VecF128(u64), + SveVecI8, + SveVecI16, + SveVecI32, + SveVecI64, + SveVecI128, + SveVecF16, + SveVecF32, + SveVecF64, + SveVecF128, + SveVecBool, +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum InlineAsmSize { + FixedBytes(u64), + Scalable, +} + +impl InlineAsmSize { + pub fn fixed_size_bytes(self) -> Option { + match self { + Self::FixedBytes(size) => Some(size), + Self::Scalable => None, + } + } } impl InlineAsmType { @@ -803,27 +827,29 @@ impl InlineAsmType { matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128) } - pub fn size(self) -> Size { - Size::from_bytes(match self { - Self::I8 => 1, - Self::I16 => 2, - Self::I32 => 4, - Self::I64 => 8, - Self::I128 => 16, - Self::F16 => 2, - Self::F32 => 4, - Self::F64 => 8, - Self::F128 => 16, - Self::VecI8(n) => n * 1, - Self::VecI16(n) => n * 2, - Self::VecI32(n) => n * 4, - Self::VecI64(n) => n * 8, - Self::VecI128(n) => n * 16, - Self::VecF16(n) => n * 2, - Self::VecF32(n) => n * 4, - Self::VecF64(n) => n * 8, - Self::VecF128(n) => n * 16, - }) + pub fn size(self) -> InlineAsmSize { + match self { + Self::I8 => InlineAsmSize::FixedBytes(1), + Self::I16 | Self::F16 => InlineAsmSize::FixedBytes(2), + Self::I32 | Self::F32 => InlineAsmSize::FixedBytes(4), + Self::I64 | Self::F64 => InlineAsmSize::FixedBytes(8), + Self::I128 | Self::F128 => InlineAsmSize::FixedBytes(16), + Self::VecI8(n) => InlineAsmSize::FixedBytes(n), + Self::VecI16(n) | Self::VecF16(n) => InlineAsmSize::FixedBytes(n * 2), + Self::VecI32(n) | Self::VecF32(n) => InlineAsmSize::FixedBytes(n * 4), + Self::VecI64(n) | Self::VecF64(n) => InlineAsmSize::FixedBytes(n * 8), + Self::VecI128(n) | Self::VecF128(n) => InlineAsmSize::FixedBytes(n * 16), + Self::SveVecI8 + | Self::SveVecI16 + | Self::SveVecI32 + | Self::SveVecI64 + | Self::SveVecI128 + | Self::SveVecF16 + | Self::SveVecF32 + | Self::SveVecF64 + | Self::SveVecF128 + | Self::SveVecBool => InlineAsmSize::Scalable, + } } } @@ -848,6 +874,16 @@ impl fmt::Display for InlineAsmType { Self::VecF32(n) => write!(f, "f32x{n}"), Self::VecF64(n) => write!(f, "f64x{n}"), Self::VecF128(n) => write!(f, "f128x{n}"), + Self::SveVecI8 => f.write_str("svint8_t"), + Self::SveVecI16 => f.write_str("svint16_t"), + Self::SveVecI32 => f.write_str("svint32_t"), + Self::SveVecI64 => f.write_str("svint64_t"), + Self::SveVecI128 => f.write_str("svint128_t"), + Self::SveVecF16 => f.write_str("svfloat26_t"), + Self::SveVecF32 => f.write_str("svfloat32_t"), + Self::SveVecF64 => f.write_str("svfloat64_t"), + Self::SveVecF128 => f.write_str("svfloat128_t"), + Self::SveVecBool => f.write_str("svbool_t"), } } } diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index c582c06d8f4bb..a4775db7e79f8 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexSet; use rustc_span::Symbol; -use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use super::{InlineAsmArch, InlineAsmSize, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; def_reg_class! { @@ -49,33 +49,45 @@ impl X86InlineAsmRegClass { pub fn suggest_class(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg | Self::reg_abcd if ty.size().bits() == 8 => Some(Self::reg_byte), + Self::reg | Self::reg_abcd if ty.size() == InlineAsmSize::FixedBytes(1) => { + Some(Self::reg_byte) + } _ => None, } } pub fn suggest_modifier(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg => match ty.size().bits() { - 16 => Some(('x', "ax", 16).into()), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()), + Self::reg => match ty.size() { + InlineAsmSize::FixedBytes(2) => { + Some(('x', "ax", InlineAsmSize::FixedBytes(2)).into()) + } + InlineAsmSize::FixedBytes(4) if arch == InlineAsmArch::X86_64 => { + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) + } _ => None, }, - Self::reg_abcd => match ty.size().bits() { - 16 => Some(('x', "ax", 16).into()), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()), + Self::reg_abcd => match ty.size() { + InlineAsmSize::FixedBytes(2) => { + Some(('x', "ax", InlineAsmSize::FixedBytes(2)).into()) + } + InlineAsmSize::FixedBytes(4) if arch == InlineAsmArch::X86_64 => { + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) + } _ => None, }, Self::reg_byte => None, Self::xmm_reg => None, - Self::ymm_reg => match ty.size().bits() { - 256 => None, - _ => Some(('x', "xmm0", 128).into()), + Self::ymm_reg => match ty.size() { + InlineAsmSize::FixedBytes(32) => None, + _ => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), }, - Self::zmm_reg => match ty.size().bits() { - 512 => None, - 256 => Some(('y', "ymm0", 256).into()), - _ => Some(('x', "xmm0", 128).into()), + Self::zmm_reg => match ty.size() { + InlineAsmSize::FixedBytes(64) => None, + InlineAsmSize::FixedBytes(32) => { + Some(('y', "ymm0", InlineAsmSize::FixedBytes(32)).into()) + } + _ => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), }, Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, @@ -87,15 +99,15 @@ impl X86InlineAsmRegClass { match self { Self::reg | Self::reg_abcd => { if arch == InlineAsmArch::X86_64 { - Some(('r', "rax", 64).into()) + Some(('r', "rax", InlineAsmSize::FixedBytes(8)).into()) } else { - Some(('e', "eax", 32).into()) + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) } } Self::reg_byte => None, - Self::xmm_reg => Some(('x', "xmm0", 128).into()), - Self::ymm_reg => Some(('y', "ymm0", 256).into()), - Self::zmm_reg => Some(('z', "zmm0", 512).into()), + Self::xmm_reg => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), + Self::ymm_reg => Some(('y', "ymm0", InlineAsmSize::FixedBytes(32)).into()), + Self::zmm_reg => Some(('z', "zmm0", InlineAsmSize::FixedBytes(64)).into()), Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, Self::tmm_reg => None, diff --git a/compiler/rustc_target/src/callconv/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs index 0162aa838cb6b..09187836ee65a 100644 --- a/compiler/rustc_target/src/callconv/aarch64.rs +++ b/compiler/rustc_target/src/callconv/aarch64.rs @@ -35,7 +35,7 @@ where // The softfloat ABI treats floats like integers, so they // do not get homogeneous aggregate treatment. RegKind::Float => cx.target_spec().rustc_abi != Some(RustcAbi::Softfloat), - RegKind::Vector { .. } => size.bits() == 64 || size.bits() == 128, + RegKind::Vector { .. } => unit.size.bits() == 64 || unit.size.bits() == 128, }; valid_unit.then_some(Uniform::consecutive(unit, size)) diff --git a/compiler/rustc_target/src/callconv/arm.rs b/compiler/rustc_target/src/callconv/arm.rs index 66f0ded3874f9..615bd4f540068 100644 --- a/compiler/rustc_target/src/callconv/arm.rs +++ b/compiler/rustc_target/src/callconv/arm.rs @@ -26,7 +26,7 @@ where let valid_unit = match unit.kind { RegKind::Integer => false, RegKind::Float => true, - RegKind::Vector { .. } => size.bits() == 64 || size.bits() == 128, + RegKind::Vector { .. } => unit.size.bits() == 64 || unit.size.bits() == 128, }; valid_unit.then_some(Uniform::consecutive(unit, size)) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 26fedbd8a5481..14ad0eb477d5d 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -625,12 +625,15 @@ pub struct FnAbi<'a, Ty> { pub conv: CanonAbi, /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, + /// Computed type discriminator for pointer authentication purpose. + pub ptrauth_discriminator: Option, } // Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl. impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind } = self; + let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind, ptrauth_discriminator } = + self; f.debug_struct("FnAbi") .field("args", args) .field("ret", ret) @@ -638,6 +641,7 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { .field("fixed_count", fixed_count) .field("conv", conv) .field("can_unwind", can_unwind) + .field("ptrauth_discriminator", ptrauth_discriminator) .finish() } } @@ -950,6 +954,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ArgAbi<'_, usize>, 56); - static_assert_size!(FnAbi<'_, usize>, 80); + static_assert_size!(FnAbi<'_, usize>, 96); // tidy-alphabetical-end } diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 3eb40abe90f33..075e69f7d74d8 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -36,7 +36,7 @@ where let valid_unit = match unit.kind { RegKind::Integer => false, RegKind::Float => true, - RegKind::Vector { .. } => arg.layout.size.bits() == 128, + RegKind::Vector { .. } => unit.size.bits() == 128, }; valid_unit.then_some(Uniform::consecutive(unit, arg.layout.size)) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index a1c8fd304cd94..0f192379ce7fc 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1615,6 +1615,7 @@ supported_targets! { ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi), ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf), + ("powerpc64-sony-ps3", powerpc64_sony_ps3), ("mipsel-sony-psp", mipsel_sony_psp), ("mipsel-sony-psx", mipsel_sony_psx), ("mipsel-unknown-none", mipsel_unknown_none), @@ -1862,6 +1863,7 @@ crate::target_spec_enum! { Nto = "nto", NuttX = "nuttx", OpenBsd = "openbsd", + Ps3 = "ps3", Psp = "psp", Psx = "psx", Qnx = "qnx", diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs b/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs new file mode 100644 index 0000000000000..41c8b3b206395 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs @@ -0,0 +1,107 @@ +use crate::spec::{ + Arch, Cc, CfgAbi, CodeModel, Endian, FramePointer, LinkerFlavor, Lld, LlvmAbi, Os, + PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::No, Lld::No), + &[ + // We strictly need ELFv1 PPC64. + "-m", + "elf64ppc", + // PS3 LV2 reserves the first 64KB page for unmapped memory protection. + "--image-base=0x10000", + // Should be default, but relying on automatic behavior appears to be brittle. + "-e", + "_start", + // CellOS expects .rodata to be merged into the executable Text segment (RX) + // so there are only 2 loadable segments (RX and RW) + "--no-rosegment", + // CellOS uses 64 KB memory pages. Without this flag, `mold` might align data segments to 4 KB boundaries. + "-z", + "separate-loadable-segments", + // Prevents mold from creating a `PT_GNU_RELRO` segment that GameOS does not support. + "-z", + "norelro", + // CellOS's loader doesn't behave like `ld`. PRXs are stubbed in the binary already. + "-Bstatic", + // The following are segments that might never be referenced by the code, + // but are expected to exist by the PS3's loader. + "-u", + "sys_process_param", + "-u", + "sys_proc_prx_param", + "--undefined-glob=*_prx_header", + "--undefined-glob=*_fnid_table", + "--undefined-glob=*_name", + "--undefined-glob=*_fstub_table", + ], + ); + + Target { + // LLVM will default to a compatible ELF backend. + llvm_target: "powerpc64-sony-ps3".into(), + + metadata: TargetMetadata { + description: Some("PowerPC64 (big endian) Sony PlayStation 3 (PS3)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + + // We declare pointers to be 64-bit as the PPU _is_ a 64-bit core. + // However, for all real usage the OS limits us to **32-bit pointers**. + // SDKs should therefore take this into account, specifically when handling syscalls. + pointer_width: 64, + + data_layout: "E-m:e-Fi64-i64:64-i128:128-n32:64".into(), + arch: Arch::PowerPC64, + + options: TargetOptions { + // Base PS3 hardware. + vendor: "sony".into(), + endian: Endian::Big, + os: Os::Ps3, + cfg_abi: CfgAbi::ElfV1, + llvm_abiname: LlvmAbi::ElfV1, + features: "+altivec".into(), + + // CellOS requiring ELFv1 makes LLVM's `lld` incompatible. + // See: + // - [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589) + // - [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630) + linker: Some("mold".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), + + // CellOS _is_ case-sensitive, but the PS3's binaries vary + // in casing depending on whether they are games in `/dev_hdd0` + // or system binaries (such as PRX files). + // + // All games use the .ELF (uppercase) suffix, and Sony's own + // documentation and tools expect user app binaries to be uppercase. + exe_suffix: ".ELF".into(), + + // This limits us to 64KB of ToC, but yields smaller binaries and less assembly. + // Only becomes a problem for binaries with thousands of dependencies. + code_model: Some(CodeModel::Small), + // Prevents LLVM from emitting modern linker relaxation relocations. + relax_elf_relocations: false, + // CellOS main executables (`EBOOT.ELF`) **must be static executables** (ET_EXEC). + relocation_model: RelocModel::Static, + + // Locking defaults against future changes. + c_int_width: 32, + executables: true, + frame_pointer: FramePointer::MayOmit, + // Change this to `true` for developing kernel-mode applications. + // This target defaults to user-mode, and the kernel already handles + // this for us, so keeping it off is a performance gain. + disable_redzone: false, + + panic_strategy: PanicStrategy::Abort, + pre_link_args, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs index 9e981cd73f5a7..dea9a130e6e56 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs @@ -2,38 +2,44 @@ //! `wasm32-wasip2`, then WASIp3. The main feature of WASIp3 is native async //! support in the component model itself. //! -//! Like `wasm32-wasip2` this target produces a component by default. Support -//! for `wasm32-wasip3` is very early as of the time of this writing so -//! components produced will still import WASIp2 APIs, but that's ok since it's -//! all component-model-level imports anyway. Over time the imports of the -//! standard library will change to WASIp3. +//! Like `wasm32-wasip2` this target produces a component by default. use crate::spec::{Cc, Env, LinkerFlavor, Target, add_link_args}; pub(crate) fn target() -> Target { - // As of now WASIp3 is a lightly edited wasip2 target, so start with that - // and this may grow over time as more features are supported. + // For now wasip3 is a lightly-edited wasip2 target. let mut target = super::wasm32_wasip2::target(); target.llvm_target = "wasm32-wasip3".into(); target.metadata = crate::spec::TargetMetadata { description: Some("WebAssembly".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }; target.options.env = Env::P3; - // The `--cooperative-threading` flag to the linker dictates the ABI that's - // being used on this target which is to store the stack pointer in a - // component model intrinsic location, for example, rather than a wasm - // global. - // - // Note that this is only specified for `Cc::No`, because when `clang` is - // being used as a linker it'll already pass this. add_link_args( &mut target.pre_link_args, LinkerFlavor::WasmLld(Cc::No), - &["--cooperative-threading"], + &[ + // The `--cooperative-threading` flag to the linker dictates the ABI + // that's being used on this target which is to store the stack + // pointer in a component model intrinsic location, for example, + // rather than a wasm global. + // + // Note that this is only specified for `Cc::No`, because when + // `clang` is being used as a linker it'll already pass this. + "--cooperative-threading", + // This is used as the wasi-libc-defined symbol here is required for + // this target to function. The Rust compiler's symbol exports + // otherwise don't know about this symbol so it's manually exported + // here. + // + // Note that this additionally is only specified for `Cc::No` + // because when `clang` is used the symbol exports happen naturally + // and this isn't needed. + "--export-if-defined=__wasm_task_hook", + ], ); target diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 039856eeb4857..8eecfda24e557 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -12,6 +12,7 @@ rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 41ed83c11bbd5..f555f0435dd8f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -3,7 +3,6 @@ use rustc_errors::Diag; use rustc_middle::ty; -use rustc_middle::ty::RegionExt; use tracing::debug; use crate::diagnostics::ExplicitLifetimeRequired; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index ccbe23cf7a631..7f07fab6e8474 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -8,9 +8,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::bug; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; -use rustc_middle::ty::{ - self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, RegionExt, TyCtxt, -}; +use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; use rustc_structures::Limit; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 1d58e8518ba56..2d48b41bcb361 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -8,7 +8,7 @@ use rustc_hir::{ self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, }; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 87785c403fa4e..f1be118896b01 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -10,7 +10,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::{self, RegionExt, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 7f4ca7a572988..73b98b8eda1a6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -13,7 +13,7 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{ - self, IsSuggestable, Region, RegionExt, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, + self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, }; use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, kw, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index ff0ac4fcfbe6a..58964492c4837 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -25,6 +25,14 @@ pub struct TypeErrCtxt<'a, 'tcx> { pub diverging_fallback_has_occurred: bool, pub autoderef_steps: Box) -> Vec<(Ty<'tcx>, PredicateObligations<'tcx>)> + 'a>, + pub infer_closure_kind: Box< + dyn Fn( + rustc_hir::def_id::LocalDefId, + ) -> Option<( + ty::ClosureKind, + Option<(rustc_span::Span, rustc_middle::hir::place::Place<'tcx>)>, + )> + 'a, + >, } #[extension(pub trait InferCtxtErrorExt<'tcx>)] @@ -41,6 +49,7 @@ impl<'tcx> InferCtxt<'tcx> { debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck"); vec![(ty, PredicateObligations::new())] }), + infer_closure_kind: Box::new(|_| None), } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index e3cf38bb34c7c..a1aec33f81995 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1005,18 +1005,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let self_ty = trait_pred.self_ty().skip_binder(); + let original_self_ty = trait_pred.self_ty().skip_binder(); + let peeled_self_ty = original_self_ty.peel_refs(); - let (expected_kind, trait_prefix) = + let is_ref_to_closure = matches!(original_self_ty.kind(), ty::Ref(..)) + && matches!(peeled_self_ty.kind(), ty::Closure(..)); + + let self_ty = if is_ref_to_closure { peeled_self_ty } else { original_self_ty }; + + let (expected_kind, is_async) = if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) { - (expected_kind, "") + (expected_kind, false) } else if let Some(expected_kind) = self.tcx.async_fn_trait_kind_from_def_id(trait_pred.def_id()) { - (expected_kind, "Async") + (expected_kind, true) } else { return None; }; + let trait_prefix = if is_async { "Async" } else { "" }; let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() { ty::Closure(def_id, args) => { @@ -1045,7 +1052,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; } - if let Some(found_kind) = self.closure_kind(self_ty) + let mut found_kind = self.closure_kind(self_ty); + let mut kind_origin = None; + + if found_kind.is_none() + && is_ref_to_closure + && !is_async + && let Some(local_def_id) = closure_def_id.as_local() + && let Some((inferred_kind, origin)) = (self.infer_closure_kind)(local_def_id) + { + found_kind = Some(inferred_kind); + kind_origin = origin; + } + + if let Some(found_kind) = found_kind && !found_kind.extends(expected_kind) { let mut err = self.report_closure_error( @@ -1054,7 +1074,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_kind, expected_kind, trait_prefix, + kind_origin, ); + self.suggest_change_mut_ref_for_closure(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation); return Some(err.emit()); } @@ -3029,6 +3051,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + fn suggest_change_mut_ref_for_closure( + &self, + err: &mut Diag<'_>, + obligation: &PredicateObligation<'tcx>, + ) { + if let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() + && let (_, Some(root_trait_pred)) = + obligation.cause.code().peel_derives_with_predicate() + && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) = arg.kind + { + let mut obligation = obligation.clone(); + // Error reporting may narrow the cause span to the borrow's operand. + // Use the whole argument so `suggest_change_mut` can replace the shared borrow. + obligation.cause.span = arg.span; + self.suggest_change_mut(&obligation, err, root_trait_pred); + } + } + pub fn note_obligation_cause( &self, err: &mut Diag<'_>, @@ -3532,6 +3573,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_kind: ty::ClosureKind, kind: ty::ClosureKind, trait_prefix: &'static str, + kind_origin: Option<(Span, rustc_middle::hir::place::Place<'tcx>)>, ) -> Diag<'a> { let closure_span = self.tcx.def_span(closure_def_id); @@ -3547,27 +3589,30 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Additional context information explaining why the closure only implements // a particular trait. - if let Some(typeck_results) = &self.typeck_results { - let hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id.expect_local()); - match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) { - (ty::ClosureKind::FnOnce, Some((span, place))) => { - err.fn_once_label = Some(ClosureFnOnceLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, place), - trait_prefix, - }) - } - (ty::ClosureKind::FnMut, Some((span, place))) => { - err.fn_mut_label = Some(ClosureFnMutLabel { - span: *span, - place: ty::place_to_string_for_capture(self.tcx, place), - trait_prefix, - }) - } - _ => {} + let origin = kind_origin.or_else(|| { + let typeck_results = self.typeck_results.as_ref()?; + let local_def_id = closure_def_id.as_local()?; + let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id); + typeck_results.closure_kind_origins().get(hir_id).cloned() + }); + + match (found_kind, origin) { + (ty::ClosureKind::FnOnce, Some((span, place))) => { + err.fn_once_label = Some(ClosureFnOnceLabel { + span, + place: ty::place_to_string_for_capture(self.tcx, &place), + trait_prefix, + }) } + (ty::ClosureKind::FnMut, Some((span, place))) => { + err.fn_mut_label = Some(ClosureFnMutLabel { + span, + place: ty::place_to_string_for_capture(self.tcx, &place), + trait_prefix, + }) + } + _ => {} } - self.dcx().create_err(err) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4593ac035dc95..7357d1738d8c3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,7 +32,7 @@ use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeFoldable, + self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, }; diff --git a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs index 5cba32d742f62..eb89d79474d1c 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_index::bit_set::DenseBitSet; use rustc_middle::bug; use rustc_middle::ty::{ self, Flags, ImplTraitInTraitData, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, @@ -11,15 +12,15 @@ use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; -/// For a given alias type, this returns the set of (identity) generic args that +/// For a given alias type, this returns the set of indices into the identity generic args that /// are relevant for liveness, that can be inferred from outlives bounds on the /// alias itself, and the explicit and implicit outlives clauses of the alias. -/// Callers should instantiate the returned args with the concrete args of the alias. +/// Callers should use the indices with the concrete args of the alias. /// /// There are three cases to consider: -/// 1. If there are *no* outlives bounds, then we return None. +/// 1. If there are *no* outlives bounds, then all args are potentially live. /// 2. If there is a `'static` outlives bound, then we know that all args are -/// irrelevant, so we return an empty list. +/// irrelevant, so we return an empty set. /// 3. If there are *any* outlives bounds, then we find any args that are known /// to outlive those bounds, since those are the args whose regions the /// underlying type could capture. @@ -27,7 +28,7 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, kind: ty::AliasTyKind<'tcx>, -) -> Option>>> { +) -> DenseBitSet { let def_id = match kind { ty::AliasTyKind::Projection { def_id } | ty::AliasTyKind::Inherent { def_id } @@ -69,7 +70,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // If there are no outlives bounds, then all (non-bivariant) args are potentially live. if outlives_regions.is_empty() { - return None; + return DenseBitSet::new_filled(self_identity_args.len()); } // If any of the outlives bounds are `'static`, then we know the alias @@ -88,7 +89,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // regions are going to be instantiated with free regions. if outlives_regions.contains(&tcx.lifetimes.re_static) { tracing::debug!("alias has a 'static outlives bound, so skipping visiting any regions"); - return Some(ty::EarlyBinder::bind(tcx, vec![])); + return DenseBitSet::new_empty(self_identity_args.len()); } // Okay, so we know we have some outlives bounds, and that none of them are `'static`. @@ -96,37 +97,32 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // an outlives-bound region. `args_known_to_outlive_alias_params` does this // for us, and in the case of opaques only includes *captured* regions, too. - let args_known_to_outlive = - tcx.args_known_to_outlive_alias_params(def_id).as_ref().skip_binder(); + let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(def_id); tracing::debug!(?args_known_to_outlive); - let mut live_args: Option>> = None; + let mut live_args = DenseBitSet::new_filled(self_identity_args.len()); for outlives_region in outlives_regions { - let Some(outlives_params) = - args_known_to_outlive.iter().find(|(r, _)| *r == outlives_region) + let Some(outlives_params) = args_known_to_outlive + .iter() + .find(|(idx, _)| self_identity_args[*idx].as_region() == Some(outlives_region)) else { continue; }; - let new_live_args = outlives_params.1.iter().copied().collect(); - match &mut live_args { - None => live_args = Some(new_live_args), - Some(prev) => *prev = prev.intersection(&new_live_args).copied().collect(), - }; + live_args.intersect(&outlives_params.1); } - live_args.map(|c| ty::EarlyBinder::bind(tcx, c.into_iter().collect())) + live_args } -/// For each region param of this alias compute the identity args that are known -/// to outlive it, given only the alias's declared where-clauses. +/// For each region param of this alias compute the indices of the identity args +/// that are known to outlive it, given only the alias's declared where-clauses. /// /// Note: for opaques (including synthetic associated types from RPITITs), /// the outlives relationships are identified in the context of the *parent*, /// since bounds and well-formed types are not lowered. -// FIXME: this likely should return a `BitSet` instead of a `Vec>` #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_alias_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { match tcx.def_kind(def_id) { DefKind::OpaqueTy => args_known_to_outlive_opaque_params(tcx, def_id), DefKind::AssocTy @@ -171,7 +167,7 @@ pub(crate) fn args_known_to_outlive_alias_params<'tcx>( pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let mut result = Vec::new(); @@ -207,7 +203,9 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // build a `Region` from the opaque region's `LocalDefId`). let generics = tcx.generics_of(def_id); let mut parent_outlives_regions = Vec::with_capacity(generics.own_params.len()); - for opaque_arg in self_identity_args[generics.parent_count..].iter() { + for (opaque_arg_idx, opaque_arg) in + self_identity_args.iter().enumerate().skip(generics.parent_count) + { let Some(opaque_region) = opaque_arg.as_region() else { continue; }; @@ -218,7 +216,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( let parent_region = tcx.map_opaque_lifetime_to_parent_lifetime(region_def_id.expect_local()); tracing::debug!(?region_def_id, ?parent_region); - parent_outlives_regions.push((parent_region, opaque_region)); + parent_outlives_regions.push((parent_region, opaque_arg_idx)); } tracing::debug!(?parent_outlives_regions); @@ -227,9 +225,11 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // 2) *Captured Regions* // // In both cases, we need to check known outlives for the *parent* region, because that's where the param_env and wf_tys are. - for (parent_outlived_region, opaque_outlived_region) in parent_outlives_regions.iter() { - let mut opaque_outlives_args = Vec::with_capacity(self_identity_args.len()); - for parent_outlives_arg in self_identity_args[..generics.parent_count].iter() { + for (parent_outlived_region, opaque_outlived_arg_idx) in parent_outlives_regions.iter() { + let mut opaque_outlives_args = DenseBitSet::new_empty(self_identity_args.len()); + for (parent_outlived_arg_idx, parent_outlives_arg) in + self_identity_args[..generics.parent_count].iter().enumerate() + { let type_outlives = match parent_outlives_arg.kind() { // Consts don't have any non-static regions ty::GenericArgKind::Const(_) => continue, @@ -249,10 +249,10 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( } // Types aren't captured, so don't need to map to the opaque - opaque_outlives_args.push(*parent_outlives_arg); + opaque_outlives_args.insert(parent_outlived_arg_idx as u32); } - for &(parent_outlives_region, opaque_region) in parent_outlives_regions.iter() { + for &(parent_outlives_region, opaque_arg_idx) in parent_outlives_regions.iter() { let region_outlives = parent_outlives_region == *parent_outlived_region || region_known_to_outlive( tcx, @@ -266,32 +266,32 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( continue; } - opaque_outlives_args.push(opaque_region.into()); + opaque_outlives_args.insert(opaque_arg_idx as u32); } - result.push((*opaque_outlived_region, opaque_outlives_args)); + result.push((*opaque_outlived_arg_idx, opaque_outlives_args)); } - ty::EarlyBinder::bind(tcx, result) + result } #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let param_env = tcx.param_env(def_id); tracing::debug!(?param_env); let wf_tys = tcx.assumed_wf_types(def_id).iter().map(|(ty, _)| *ty).collect::>(); let mut result = Vec::new(); - for outlived_arg in self_identity_args.iter() { + for (outlived_arg_idx, outlived_arg) in self_identity_args.iter().enumerate() { let Some(outlived_region) = outlived_arg.as_region() else { continue; }; - let outliving_args = self_identity_args - .iter() - .filter(|arg| match arg.kind() { + let mut outliving_args = DenseBitSet::new_empty(self_identity_args.len()); + for (arg_idx, arg) in self_identity_args.iter().enumerate() { + let outlives = match arg.kind() { ty::GenericArgKind::Lifetime(r) => { region_known_to_outlive(tcx, def_id, param_env, &wf_tys, r, outlived_region) } @@ -299,16 +299,19 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( ty_known_to_outlive(tcx, def_id, param_env, &wf_tys, t, outlived_region) } ty::GenericArgKind::Const(_) => false, - }) - .collect(); - result.push((outlived_region, outliving_args)); + }; + if outlives { + outliving_args.insert(arg_idx as u32); + } + } + result.push((outlived_arg_idx, outliving_args)); } - ty::EarlyBinder::bind(tcx, result) + result } /// For a param-env clause `for<'v..> ::Assoc<..>: 'bound` that -/// applies to `ty` (an alias with `alias_def_id`), returns the set of (identity) args -/// that the underlying type could possibly capture, as restricted by this clause. +/// applies to `ty` (an alias with `alias_def_id`), returns the set of indices into the +/// identity args that the underlying type could possibly capture, as restricted by this clause. /// /// As an example, let's imagine we had the following associated type definition: /// ```ignore (illustrative) @@ -338,20 +341,24 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( /// some cases (like `for<'x, 'y, 'z> T::Assoc<'x, 'y, 'z>: 'x`) that won't /// be satisfiable today, but the logic here should hold whenever there *is*. /// -/// Returns `None` if the clause doesn't apply to `ty` or gives us no information. +/// Returns a filled set if the clause doesn't apply to `ty` or gives us no +/// information. #[tracing::instrument(level = "debug", skip(tcx), ret)] fn live_args_for_outlives_clause<'tcx>( tcx: TyCtxt<'tcx>, alias_def_id: DefId, ty: Ty<'tcx>, outlives: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, -) -> Option>>> { +) -> DenseBitSet { + let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); + let no_restriction = || DenseBitSet::new_filled(clause_identity_args.len()); + // N.B. it's okay to skip the binder here (and in the rest of the function), // because all variables under binders do not escape let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) = *outlives.skip_binder().0.kind() else { - return None; + return no_restriction(); }; let clause_def_id = match clause_alias_kind { ty::AliasTyKind::Projection { def_id } @@ -360,27 +367,28 @@ fn live_args_for_outlives_clause<'tcx>( | ty::AliasTyKind::Free { def_id } => def_id, }; if clause_def_id != alias_def_id { - return None; + return no_restriction(); } // Here, we're just using this to check if the clause *could apply* to `ty`, // but importantly we don't want to use the returned region, because that is // the "last visited" region in `ty` that matches the outlves bound. Actually, // we want *all* the identity regions in `ty` that match the outlives bound. - test_type_match::extract_verify_if_eq( + let Some(_) = test_type_match::extract_verify_if_eq( tcx, &outlives.map_bound(|ty::OutlivesClause(ty, bound)| VerifyIfEq { ty, bound }), ty, - )?; + ) else { + return no_restriction(); + }; let outlived_region = outlives.skip_binder().1; - let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); match outlived_region.kind() { // The underlying type must outlive `'static`, so it can't capture any of the args at all. // // Of course, you may ask: "what if the function has a `'a: 'static` bound?" See the corresponding // comment in `live_args_for_alias_from_outlives_bounds` for why we don't need to worry about that. - ty::ReStatic => Some(FxIndexSet::default()), + ty::ReStatic => DenseBitSet::new_empty(clause_identity_args.len()), ty::ReBound(_, br) => { // The bound is one of the clause's higher-ranked vars. Find the arg // positions it occupies, then (at the alias's identity level) find @@ -388,13 +396,15 @@ fn live_args_for_outlives_clause<'tcx>( // the alias's declared bounds -- only those can be captured by the // underlying type. let mut outlived_regions = Vec::new(); - for (clause_arg, identity_arg) in clause_args.iter().zip(clause_identity_args.iter()) { + for (clause_arg, (identity_arg_idx, _identity_arg)) in + clause_args.iter().zip(clause_identity_args.iter().enumerate()) + { match clause_arg.kind() { ty::GenericArgKind::Lifetime(r) => { if let ty::ReBound(_, arg_br) = r.kind() && arg_br.var == br.var { - outlived_regions.push(identity_arg.expect_region()); + outlived_regions.push(identity_arg_idx); } } ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) => { @@ -404,7 +414,7 @@ fn live_args_for_outlives_clause<'tcx>( // so conservatively treat the clause as giving no // restriction at all. if clause_arg.has_escaping_bound_vars() { - return None; + return no_restriction(); } } } @@ -413,7 +423,7 @@ fn live_args_for_outlives_clause<'tcx>( // The bound var doesn't appear in the args at all, so the clause // requires the underlying type to outlive *every* region, which // is equivalent to a `'static` bound. - return Some(FxIndexSet::default()); + return DenseBitSet::new_empty(clause_identity_args.len()); } // The underlying type can capture any arg that's known to outlive one @@ -421,22 +431,15 @@ fn live_args_for_outlives_clause<'tcx>( // region at any use site this clause applies to). let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(alias_def_id); tracing::debug!(?outlived_regions, ?args_known_to_outlive); - let mut capturable_args = FxIndexSet::default(); - for &outlived_region in &outlived_regions { - // There's a bit of a dance here around `Earlybinder::skip_binder` - // and then later a `Earlybinder::bind`. This is because there's - // no real good way today to move the `EarlyBinder` inward - // declaratively without cloning the entire thing. + let mut capturable_args = DenseBitSet::new_empty(clause_identity_args.len()); + for &outlived_arg_idx in &outlived_regions { let (_, outliving_args) = args_known_to_outlive - .as_ref() - .skip_binder() .iter() - .find(|(region, _)| *region == outlived_region) + .find(|(arg_idx, _)| *arg_idx == outlived_arg_idx) .unwrap(); - capturable_args - .extend(outliving_args.iter().copied().map(|a| ty::EarlyBinder::bind(tcx, a))); + capturable_args.union(outliving_args); } - Some(capturable_args) + capturable_args } // A free region (e.g. `for T::Assoc<'a, 'x>: 'x`, where `'x` is free). // This is effectively the same as `for<'a, 'b> T::Assoc<'a, 'b>: 'b`, @@ -459,9 +462,9 @@ fn live_args_for_outlives_clause<'tcx>( // } // ``` // So, we conservatively treat this as giving no restriction on which args can be captured. - ty::ReEarlyParam(..) => None, + ty::ReEarlyParam(..) => no_restriction(), // Don't know that we actually hit this (maybe `ReError`), go ahead and be conservative. - _ => None, + _ => no_restriction(), } } @@ -527,59 +530,22 @@ where | ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free { def_id } => def_id, }; - let mut capturable: Option< - FxIndexSet>>, - > = None; - let mut restrict = - |capturable_args: FxIndexSet>>| { - match &mut capturable { - None => capturable = Some(capturable_args), - Some(prev) => { - *prev = prev.intersection(&capturable_args).copied().collect() - } - }; - }; - - if let Some(live_args) = tcx.live_args_for_alias_from_outlives_bounds(kind) { - restrict( - live_args - .as_ref() - .skip_binder() - .iter() - .copied() - .map(|a| ty::EarlyBinder::bind(tcx, a)) - .collect(), - ); - } + let mut capturable = tcx.live_args_for_alias_from_outlives_bounds(kind).clone(); for clause in param_env.caller_bounds() { let Some(outlives) = clause.as_type_outlives_clause() else { continue; }; - if let Some(capturable_args) = - live_args_for_outlives_clause(tcx, def_id, ty, outlives) - { - restrict(capturable_args); - } + capturable.intersect(&live_args_for_outlives_clause(tcx, def_id, ty, outlives)); } tracing::debug!(?capturable); - match capturable { - Some(capturable_args) => { - for arg in capturable_args { - let arg = arg.instantiate(tcx, args).skip_norm_wip(); - arg.visit_with(self); - } - } - None => { - // Skip lifetime parameters that are not captured, since they do - // not need to be live. - let variances = tcx.opt_alias_variances(kind); - for (idx, s) in args.iter().enumerate() { - if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) { - s.visit_with(self); - } - } + // Skip lifetime parameters that are not captured, since they do + // not need to be live. + let variances = tcx.opt_alias_variances(kind); + for idx in capturable.iter() { + if variances.map(|variances| variances[idx as usize]) != Some(ty::Bivariant) { + args[idx as usize].visit_with(self); } } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 65d589cc35aa0..318b3273219a5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -6,6 +6,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{self as hir, find_attr}; use rustc_middle::bug; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; +use rustc_middle::ptrauth::ptrauth_compute_fn_ptr_type_discriminator_for; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, @@ -611,6 +612,11 @@ fn fn_abi_new_uncached<'tcx>( determined_fn_def_id, sig.abi(), ), + ptrauth_discriminator: if tcx.sess.pointer_authentication_fn_ptr_type_discrimination() { + Some(ptrauth_compute_fn_ptr_type_discriminator_for(tcx, sig).unwrap_or(0).into()) + } else { + None + }, }; fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi()); debug!("fn_abi_new_uncached = {:?}", fn_abi); diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 3653b6ee3670d..66ba76bcd6474 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, Unnormalized, fold_regions}; +use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_span::Span; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e54e8f098d175..056165d19ae04 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -6,8 +6,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, RegionExt, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, - Unnormalized, Upcast, fold_regions, + self, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Unnormalized, + Upcast, fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index db867364b3585..7fc29cd8ebcf1 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1028,7 +1028,7 @@ impl BoundRegionKind { match *self { ty::BoundRegionKind::Named(def_id) => { let name = tcx.item_name(def_id); - if name.is_kw_underscore_lifetime() { None } else { Some(name) } + if name == I::Symbol::KW_UNDERSCORE_LIFETIME { None } else { Some(name) } } ty::BoundRegionKind::NamedForPrinting(name) => Some(name), _ => None, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index b08cf4c5876a9..bf90ef707c051 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -286,6 +286,7 @@ pub trait ExprConst>: Copy + Debug + Hash + Eq + R #[rust_analyzer::prefer_underscore_import] pub trait GenericsOf> { fn count(&self) -> usize; + fn param_region_def_id(self, interner: I, ebr: I::EarlyParamRegion) -> I::DefId; } #[rust_analyzer::prefer_underscore_import] @@ -768,6 +769,17 @@ impl<'a, S: SliceLike> SliceLike for &'a S { } #[rust_analyzer::prefer_underscore_import] -pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { - fn is_kw_underscore_lifetime(self) -> bool; +pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { + const KW_UNDERSCORE_LIFETIME: Self; + const KW_STATIC_LIFETIME: Self; + const SYM_ANON: Self; +} + +pub trait RegionName: Copy + Hash + PartialEq + Eq + Debug { + fn get_name(&self, interner: I) -> Option; + fn is_named(&self, interner: I) -> bool; +} + +pub trait DefIdGetter: Copy + Hash + PartialEq + Eq + Debug { + fn get_def_id(self) -> Option; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..fe7f66f891e82 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -22,7 +22,7 @@ use crate::solve::{ use crate::visit::{Flags, TypeVisitable}; use crate::{ self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, DebruijnIndex, - Region, RegionKind, TraitRef, search_graph, + Region, RegionKind, RegionVid, TraitRef, search_graph, }; /// The central trait in the shared abstraction layer, specifying all implementation-specific @@ -211,16 +211,31 @@ pub trait Interner: /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . - type EarlyParamRegion: ParamLike; + type EarlyParamRegion: ParamLike + RegionName; /// (2026/08/13) /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . #[cfg(feature = "nightly")] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash + StableHash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + StableHash + + DefIdGetter + + RegionName; #[cfg(not(feature = "nightly"))] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + DefIdGetter + + RegionName; type InternedRegionKind: Interned>; @@ -491,6 +506,7 @@ pub trait Interner: fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool; fn coroutine_is_async(self, coroutine_def_id: Self::CoroutineId) -> bool; @@ -528,6 +544,8 @@ pub trait Interner: fn get_re_static_lifetime(self) -> Region; + fn intern_re_var(self, rv: RegionVid) -> Region; + fn intern_region(self, region_kind: RegionKind) -> Region; fn intern_bound_region( diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs index e82d062a155a6..0dfdda6af16cc 100644 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -24,6 +24,90 @@ pub struct Region(pub I::InternedRegionKind); // These are only the `inherent` trait methods that have been ported across impl Region { + #[inline] + pub fn new_var(interner: I, v: RegionVid) -> Self { + interner.intern_re_var(v) + } + + pub fn get_name(self, interner: I) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.get_name(interner), + RegionKind::ReBound(_, br) => br.kind.get_name(interner), + RegionKind::ReLateParam(fr) => fr.kind.get_name(interner), + RegionKind::ReStatic => Some(I::Symbol::KW_STATIC_LIFETIME), + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(interner), + _ => None, + } + } + + pub fn get_name_or_anon(self, interner: I) -> I::Symbol { + match self.get_name(interner) { + Some(name) => name, + None => I::Symbol::SYM_ANON, + } + } + + /// Given some item `binding_item`, check if this region is a generic parameter introduced by it + /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. + pub fn opt_param_def_id(self, interner: I, binding_item: I::DefId) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => { + Some(interner.generics_of(binding_item).param_region_def_id(interner, ebr)) + } + RegionKind::ReLateParam(param) => param.kind.get_def_id(), + _ => None, + } + } + + /// Is this region named by the user? + pub fn is_named(self, interner: I) -> bool { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.is_named(interner), + RegionKind::ReBound(_, br) => br.kind.is_named(interner), + RegionKind::ReLateParam(fr) => fr.kind.is_named(interner), + RegionKind::ReStatic => true, + RegionKind::ReVar(..) => false, + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(interner), + RegionKind::ReErased => false, + RegionKind::ReError(_) => false, + } + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets + /// used. + #[track_caller] + pub fn new_error_misc(interner: I) -> Self { + Self::new_error_with_message( + interner, + I::Span::dummy(), + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` + /// to ensure it gets used. + #[track_caller] + pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self { + let reported = interner.span_delayed_bug(span, msg); + Self::new_error(interner, reported) + } + + #[inline] + pub fn new_late_param(interner: I, scope: I::DefId, kind: I::LateParamRegionKind) -> Self { + interner.intern_region(RegionKind::ReLateParam(LateParamRegion { scope, kind })) + } + + #[inline] + pub fn new_early_param(interner: I, early_bound_region: I::EarlyParamRegion) -> Self { + interner.intern_region(RegionKind::ReEarlyParam(early_bound_region)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self { + interner.intern_region(RegionKind::ReError(guar)) + } + #[inline] pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_region: BoundRegion) -> Self { interner.intern_bound_region(debruijn, bound_region) @@ -159,6 +243,14 @@ impl Region { pub fn kind(self) -> RegionKind { self.0.get() } + + #[inline] + pub fn bound_at_or_above_binder(self, index: DebruijnIndex) -> bool { + match self.kind() { + RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, + _ => false, + } + } } impl Flags for Region { diff --git a/library/compiler-builtins/crates/symcheck/src/main.rs b/library/compiler-builtins/crates/symcheck/src/main.rs index a88aeed40fb0d..b5d5fecd63cb6 100644 --- a/library/compiler-builtins/crates/symcheck/src/main.rs +++ b/library/compiler-builtins/crates/symcheck/src/main.rs @@ -210,6 +210,7 @@ impl Target { "nto" => Os::Nto, "nuttx" => Os::Nuttx, "openbsd" => Os::OpenBsd, + "ps3" => Os::Ps3, "psp" => Os::Psp, "psx" => Os::Psx, "qurt" => Os::Qurt, @@ -324,6 +325,7 @@ enum Os { Nto, Nuttx, OpenBsd, + Ps3, Psp, Psx, Qurt, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ca29cf2e19681..a99633456de0b 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -862,7 +862,10 @@ pub const fn forget(_: T); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::mem` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `mem` module instead", + module = "mem" +)] #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] #[rustc_diagnostic_item = "transmute"] #[rustc_nounwind] @@ -3138,7 +3141,10 @@ pub const fn ptr_metadata + PointeeSized, M>(ptr: // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] @@ -3149,7 +3155,10 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] @@ -3160,7 +3169,10 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize); // debug assertions; if you are writing compiler tests or code inside the standard library // that wants to avoid those debug assertions, directly call this intrinsic instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] +#[rustc_allowed_through_unstable_modules( + message = "import this function via the `ptr` module instead", + module = "ptr" +)] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 6c2f77a373393..3fb844c7c2927 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -1,7 +1,5 @@ -use crate::cmp::Ordering; -use crate::hash::{Hash, Hasher}; -use crate::marker::{Destruct, StructuralPartialEq}; -use crate::mem::MaybeDangling; +use crate::hash::Hash; +use crate::marker::Destruct; use crate::ops::{Deref, DerefMut, DerefPure}; use crate::ptr; @@ -152,11 +150,11 @@ use crate::ptr; /// [`MaybeUninit`]: crate::mem::MaybeUninit #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] #[rustc_pub_transparent] pub struct ManuallyDrop { - value: MaybeDangling, + value: T, } impl ManuallyDrop { @@ -180,7 +178,7 @@ impl ManuallyDrop { #[inline(always)] #[rustc_no_writable] pub const fn new(value: T) -> ManuallyDrop { - ManuallyDrop { value: MaybeDangling::new(value) } + ManuallyDrop { value } } /// Extracts the value from the `ManuallyDrop` container. @@ -198,9 +196,7 @@ impl ManuallyDrop { #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { - // Cannot use `MaybeDangling::into_inner` as that does not yet have the desired semantics. - // SAFETY: We know this is a valid `T`. `slot` will not be dropped. - unsafe { (&raw const slot).cast::().read() } + slot.value } /// Takes the value from the `ManuallyDrop` container out. @@ -225,7 +221,7 @@ impl ManuallyDrop { pub const unsafe fn take(slot: &mut ManuallyDrop) -> T { // SAFETY: we are reading from a reference, which is guaranteed // to be valid for reads. - unsafe { ptr::read(slot.value.as_ref()) } + unsafe { ptr::read(&slot.value) } } } @@ -262,7 +258,7 @@ impl ManuallyDrop { // SAFETY: we are dropping the value pointed to by a mutable reference // which is guaranteed to be valid for writes. // It is up to the caller to make sure that `slot` isn't dropped again. - unsafe { ptr::drop_in_place(slot.value.as_mut()) } + unsafe { ptr::drop_in_place(&mut slot.value) } } } @@ -272,7 +268,7 @@ const impl Deref for ManuallyDrop { type Target = T; #[inline(always)] fn deref(&self) -> &T { - self.value.as_ref() + &self.value } } @@ -281,43 +277,9 @@ const impl Deref for ManuallyDrop { const impl DerefMut for ManuallyDrop { #[inline(always)] fn deref_mut(&mut self) -> &mut T { - self.value.as_mut() + &mut self.value } } #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Eq for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl PartialEq for ManuallyDrop { - fn eq(&self, other: &Self) -> bool { - self.value.as_ref().eq(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl StructuralPartialEq for ManuallyDrop {} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Ord for ManuallyDrop { - fn cmp(&self, other: &Self) -> Ordering { - self.value.as_ref().cmp(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl PartialOrd for ManuallyDrop { - fn partial_cmp(&self, other: &Self) -> Option { - self.value.as_ref().partial_cmp(other.value.as_ref()) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Hash for ManuallyDrop { - fn hash(&self, state: &mut H) { - self.value.as_ref().hash(state); - } -} diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs index f4115ca6124a7..5a91305c5b9f0 100644 --- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs @@ -253,11 +253,9 @@ where unsafe { // Mustn't call alloc with size 0. let ptr = if size > 0 { - // `copy_to_userspace` is more efficient when data is 8-byte aligned - let alignment = cmp::max(T::align_of(), 8); - rtunwrap!(Ok, super::alloc(size, alignment)) as _ + rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ } else { - T::align_of() as _ // dangling pointer ok for size 0 + crate::ptr::dangling_mut() // dangling pointer ok for size 0 }; if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) { User(NonNull::new_userref(v)) diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index d3a97bbf08fa2..11ab2190c5444 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -7,7 +7,6 @@ use super::thread::Thread; use super::{Result, spawnhook}; use crate::cell::UnsafeCell; use crate::marker::PhantomData; -use crate::mem::MaybeDangling; use crate::sync::Arc; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::{AsInner, IntoInner, thread as imp}; @@ -57,14 +56,9 @@ where Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData }); let their_packet = my_packet.clone(); - // Pass `f` in `MaybeDangling` because actually that closure might *run longer than the lifetime of `F`*. - // See for more details. - let f = MaybeDangling::new(f); - // The entrypoint of the Rust thread, after platform-specific thread // initialization is done. let rust_start = move || { - let f = f.into_inner(); let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.inherit_and_run()); crate::sys::backtrace::__rust_begin_short_backtrace(f) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index a729e1ebfb7bf..a85921214fe51 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -439,15 +439,6 @@ fn copy_self_contained_objects( ) }); - // wasm32-wasip3 doesn't exist in wasi-libc yet, so instead use libs - // from the wasm32-wasip2 target. Once wasi-libc supports wasip3 this - // should be deleted and the native objects should be used. - let srcdir = if target == "wasm32-wasip3" { - assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now"); - builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap() - } else { - srcdir - }; for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, @@ -2529,7 +2520,8 @@ impl CommandLineStep for Assemble { } // In addition to `rust-lld` also install `wasm-component-ld` when - // is enabled. This is used by the `wasm32-wasip2` target of Rust. + // is enabled. This is used by targets that produce WebAssembly + // components in Rust such as `wasm32-wasip{2,3}`. if builder.tool_enabled("wasm-component-ld") { let wasm_component = builder.ensure( crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler( diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 3d16806a9581f..0a6ae88316f56 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -5,6 +5,7 @@ use std::{env, fs}; use super::{Builder, Kind}; use crate::core::build_steps::compile::is_lto_stage; +use crate::core::build_steps::llvm::Llvm; use crate::core::build_steps::test; use crate::core::build_steps::tool::SourceType; use crate::core::compiler::Compiler; @@ -1243,12 +1244,18 @@ impl Builder<'_> { if (mode == Mode::ToolRustcPrivate || mode == Mode::Codegen) && self.is_llvm_enabled_for(target) { - let llvm_libdir_raw = command(self.host_llvm_config()) - .cached() - .arg("--libdir") - .run_capture_stdout(self) - .stdout(); - let llvm_libdir = llvm_libdir_raw.trim(); + let llvm_libdir = if self.config.is_host_target(target) { + command(self.host_llvm_config()) + .cached() + .arg("--libdir") + .run_capture_stdout(self) + .stdout() + .trim() + .to_owned() + } else { + let llvm_output = self.ensure(Llvm { target }); + llvm_output.root_dir().join("lib").to_string_lossy().into_owned() + }; if target.is_msvc() { rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}")); } else { diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap index bb55f31c405d6..c609f5ffd51fa 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap @@ -45,6 +45,7 @@ expression: bench - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap index 9d3ff75cc1cce..41529a664a189 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap @@ -27,6 +27,7 @@ expression: build compiler - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap index 812bc18078999..d5754846441a2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap @@ -29,6 +29,7 @@ expression: check - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap index dc069febfcebe..efedf514001c2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap @@ -29,6 +29,7 @@ expression: check compiler - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap index 921060318f5e5..cb48844356717 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap @@ -29,6 +29,7 @@ expression: check compiletest --include-default-paths - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap index dfb838638bf68..17b69d85ff821 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap @@ -44,6 +44,7 @@ expression: clippy - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap index 356be4863d1a6..8ed386a4f219a 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap @@ -29,6 +29,7 @@ expression: fix - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 49a1c04c6af63..32ed54050dc3d 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -93,6 +93,7 @@ expression: test - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index 397f8dbd794a3..d1cdf81a14e08 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -90,6 +90,7 @@ expression: test --skip=coverage - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap index d4723f9070859..df4b8a2ce1299 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap @@ -93,6 +93,7 @@ expression: test --skip=coverage-map - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap index 40d211627d7e0..75992df8aa616 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap @@ -93,6 +93,7 @@ expression: test --skip=coverage-run - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap index bdd627ae37cc3..72839a9dddb10 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap @@ -54,6 +54,7 @@ expression: test --skip=tests - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap index 7551afd31a79c..a44052fac41f9 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap @@ -90,6 +90,7 @@ expression: test --skip=tests/coverage - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap index 4457208ab56b9..ee846481847cd 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap @@ -38,6 +38,7 @@ expression: test --skip=tests --skip=library --skip=tidyselftest - Set({compiler/rustc_error_messages}) - Set({compiler/rustc_errors}) - Set({compiler/rustc_expand}) + - Set({compiler/rustc_expand_queries}) - Set({compiler/rustc_feature}) - Set({compiler/rustc_fs_util}) - Set({compiler/rustc_graphviz}) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4d8a7e58e19fd..6ef38d07e45bb 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1600,7 +1600,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("compiler") - .render_steps(), @"[check] rustc 0 -> rustc 1 (77 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); } #[test] @@ -1626,7 +1626,7 @@ mod snapshot { ctx.config("check") .path("compiler") .stage(1) - .render_steps(), @"[check] rustc 0 -> rustc 1 (77 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); } #[test] @@ -1640,7 +1640,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (77 crates) + [check] rustc 1 -> rustc 2 (78 crates) "); } @@ -1656,7 +1656,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [check] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (77 crates) + [check] rustc 1 -> rustc 2 (78 crates) [check] rustc 1 -> rustc 2 [check] rustc 1 -> Rustdoc 2 [check] rustc 1 -> rustc_codegen_cranelift 2 @@ -1753,7 +1753,7 @@ mod snapshot { ctx.config("check") .paths(&["library", "compiler"]) .args(&args) - .render_steps(), @"[check] rustc 0 -> rustc 1 (77 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); } #[test] @@ -2982,7 +2982,7 @@ mod snapshot { #[test] fn fix_compiler() { let ctx = TestCtx::new(); - insta::assert_snapshot!(ctx.config("fix").path("compiler").render_steps(), @"[fix] rustc 0 -> rustc 1 (77 crates)"); + insta::assert_snapshot!(ctx.config("fix").path("compiler").render_steps(), @"[fix] rustc 0 -> rustc 1 (78 crates)"); } } diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index efdbcbae63467..d753d16aff66c 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -104,6 +104,7 @@ ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasip1 ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,wasm32-wasip2 +ENV TARGETS=$TARGETS,wasm32-wasip3 ENV TARGETS=$TARGETS,wasm32v1-none ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b9c79ab0128e9..f15c712c32b91 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -110,6 +110,7 @@ - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md) - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md) - [powerpc64-ibm-aix](platform-support/aix.md) + - [powerpc64-sony-ps3](platform-support/powerpc64-sony-ps3.md) - [powerpc64-unknown-linux-gnuelfv2](platform-support/powerpc64-unknown-linux-gnuelfv2.md) - [powerpc64-unknown-linux-musl](platform-support/powerpc64-unknown-linux-musl.md) - [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 7518ee9fabbbc..54d9885c93955 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -218,6 +218,7 @@ target | std | notes [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASIp1 [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | WebAssembly with WASIp2 +[`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | WebAssembly with WASIp3 [`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS [`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64 @@ -388,6 +389,7 @@ target | std | host | notes [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | [`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) +[`powerpc64-sony-ps3`](platform-support/powerpc64-sony-ps3.md) | * | | PowerPC64 (BE) Sony PlayStation 3 (PS3) [`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2) [`powerpc64-unknown-linux-gnuelfv2`](platform-support/powerpc64-unknown-linux-gnuelfv2.md) | ✓ | ✓ | PPC64 Linux (ELFv2 ABI, kernel 3.2, glibc 2.17) [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 @@ -445,7 +447,6 @@ target | std | host | notes [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) -[`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | | WebAssembly with WASIp3 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-lynx-lynxos178`](platform-support/lynxos178.md) | | | x86_64 LynxOS-178 diff --git a/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md b/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md new file mode 100644 index 0000000000000..0c0c4327c355e --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md @@ -0,0 +1,93 @@ +# `powerpc64-sony-ps3` + +**Tier: 3** + +Target for the Sony PlayStation 3 (shortened to "PS3"), for the PowerPC Processor Element (PPU) of the [Cell Broadband Engine Architecture (CBEA)](https://ieeexplore.ieee.org/document/5388675). + +## Target maintainers + +- [@ZephyrCodesStuff](https://github.com/ZephyrCodesStuff) (Primary developer and maintainer) +- [@RipleyTom](https://github.com/RipleyTom) (Fallback maintainer) + +## Requirements + +The target is a **big-endian PowerPC64 ELFv1** platform (the Cell Broadband Engine's PPE), and intended only for use on Sony PlayStation 3 systems, under the official operating system, "CellOS". + +The linker must support **Big-Endian PowerPC64 ELFv1**: the recommended and tested linker is [mold](https://github.com/rui314/mold). LLVM's `lld` does not correctly handle ELFv1 call relocations in freestanding `no_std` environments, making it incompatible. (See: [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589), [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630)) + +Resulting binaries require additional patching after linking to adhere to the PlayStation 3 operating system, in order to be bootable. An open-source patcher is available [here](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier). Generally, a patcher must perform the following: + +- Rewrite the ELF OS/ABI to `0x66` (`ELFOSABI_CELLLV2`) +- Strip any GNU/Linux headers +- Add Sony-specific flags, sections (`.sys_proc_param` and `.sys_proc_prx_param`) and headers +- Add "stubs" for Sony SPRX dynamic-link libraries, by adding a section (`.lib.stub`) for CellOS to be able to link them +- Patch OPD function descriptors (in the `.opd` section) + +_**Note**: this list may not be exhaustive for all use cases, but is sufficient for producing a runnable binary. Producing a PRX dynamic library may require more/different steps._ + + +The target _fully supports_: + +- The Rust `core` features +- The Rust `alloc` feature, as the CellOS Lv2 kernel provides virtual memory allocation (`sys_memory_allocate`) on top of which a heap allocator (such as [talc](https://github.com/SFBdragon/talc)) can be implemented. +- AltiVec / VMX SIMD vector extensions (natively supported by LLVM via `+altivec`) + +## Building the target + +If `rustc` is built with this target enabled, no external C cross-compilation toolchain is strictly required to build the compiler host artifacts, but `mold` must be installed on the host system to perform linking. + +Support for using `lld` as a linker is unlikely, until support for ELFv1 is implemented on `lld`. + +## Building Rust programs + +Because this is a Tier 3 target, pre-compiled standard library artifacts (`core`, `alloc`) are not distributed via rustup. Programs must be built using a nightly toolchain with the `rust-src` component and `-Z build-std`. + +A Rust SDK ready for development exists open-sourced [here](https://github.com/Zephyrcodesstuff/rust-ps3) and is licensed `MIT OR Apache-2.0`. + +Configure your project `.cargo/config.toml`: +```toml +[target.powerpc64-sony-ps3] +linker = "mold" +rustflags = [ + "-C", "relocation-model=static", + "-C", "code-model=small", + "-C", "target-feature=+altivec", +] +``` + +**Prerequisites:** + +- A nightly Rust compiler with the `rust-src` component +- The [mold](https://github.com/rui314/mold) linker +- The [moldier](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier) post-linker tool +- *(Optional)* `make_fself` or `scetool` for converting the output `.ELF` into an encrypted/signed `EBOOT.BIN` for running on real hardware. + +**Build process:** + +```bash +# Compile the binary +cargo +nightly build \ + --target powerpc64-sony-ps3 \ + -Z build-std=core,alloc \ + --release + +# Patch the linked executable +moldier patch target/powerpc64-sony-ps3/release/my_program.ELF + +# (Optional) Sign the binary for official hardware +make_fself "target/powerpc64-sony-ps3/release/my_program.ELF" "target/powerpc64-sony-ps3/release/my_program.BIN" +``` + +## Testing + +The target fully supports running binaries (once they're patched), both on official hardware and on [open-source emulators](https://github.com/rpcs3/rpcs3). + +As official firmware for the system forbids running unsigned code, the system must first be jailbroken in order to run binaries. This is not optional. + +Emulators do not impose any requirement regarding codesigning, thus testing on emulators is straightforward. + +Debugging is fully possible, either via debug firmware APIs on the official hardware, or on emulators via either their integrated debuggers, or a GDB server the emulator provides. + +## Cross-compilation toolchains and C code + +The target fully supports C/C++ code. Any compiler capable of producing binaries for a PowerPC64 big-endian processor can produce code to be embedded into the Rust program. diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index 0d15097468b17..fcf6e42be224b 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -25,14 +25,15 @@ does not (easily) support interop with C/C++ code. Please refer to the [wasm-bindgen](https://crates.io/crates/wasm-bindgen) crate in case you want to interoperate with JavaScript with this target. -Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md) and -[`wasm32-wasip2`](./wasm32-wasip2.md) also provide access to the host environment, -support interop with C/C++ (and other languages), and support most of the Rust -standard library. While the WASI targets are portable across different hosts -(web and non-web), WASI has no standard way of accessing web APIs, whereas -Emscripten has the ability to run arbitrary JS from WASM and access many web APIs. -If you are only targeting the web and need to access web APIs, the -`wasm32-unknown-emscripten` target may be preferable. +Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md), +[`wasm32-wasip2`](./wasm32-wasip2.md), and +[`wasm32-wasip3`](./wasm32-wasip3.md), also provide access to the host +environment, support interop with C/C++ (and other languages), and support most +of the Rust standard library. While the WASI targets are portable across +different hosts (web and non-web), WASI has no standard way of accessing web +APIs, whereas Emscripten has the ability to run arbitrary JS from WASM and +access many web APIs. If you are only targeting the web and need to access web +APIs, the `wasm32-unknown-emscripten` target may be preferable. ## Target maintainers diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 3dc608e704308..362bf6f255d9d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -15,8 +15,9 @@ but many parts of the standard library do not work and return errors. For example `println!` does nothing, `std::fs` always return errors, and `std::thread::spawn` will panic. There is no means by which this can be overridden. For a WebAssembly target that more fully supports the standard -library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or -[`wasm32-wasip2`](./wasm32-wasip2.md) targets. +library see the [`wasm32-wasip1`](./wasm32-wasip1.md), +[`wasm32-wasip2`](./wasm32-wasip2.md), or +[`wasm32-wasip3`](./wasm32-wasip3.md), targets. The `wasm32-unknown-unknown` target has full support for the `core` and `alloc` crates. It additionally supports the `HashMap` type in the `std` crate, although diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip3.md b/src/doc/rustc/src/platform-support/wasm32-wasip3.md index e8063a1bdcfed..4807adc0c2982 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip3.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip3.md @@ -1,42 +1,49 @@ # `wasm32-wasip3` -**Tier: 3** +**Tier: 2** The `wasm32-wasip3` target is the next stage of evolution of the [`wasm32-wasip2`](./wasm32-wasip2.md) target. The `wasm32-wasip3` target enables the Rust standard library to use WASIp3 APIs to implement various pieces of functionality. WASIp3 brings native async support over WASIp2, which integrates -well with Rust's `async` ecosystem. - -> **Note**: As of 2025-10-01 WASIp3 has not yet been approved by the WASI -> subgroup of the WebAssembly Community Group. Development is expected to -> conclude in late 2025 or early 2026. Until then the Rust standard library -> won't actually use WASIp3 APIs on the `wasm32-wasip3` target as they are not -> yet stable and would reduce the stability of this target. Once WASIp3 is -> approved, however, the standard library will update to use WASIp3 natively. - -> **Note**: This target does not yet build as of 2025-10-01 due to and update -> needed in the `libc` crate. Using it will require a `[patch]` for now. - -> **Note**: Until the standard library is fully migrated to use the `wasip3` -> crate then components produced for `wasm32-wasip3` may import WASIp2 APIs. -> This is considered a transitionary phase until fully support of libstd is -> implemented. +well with Rust's `async` ecosystem. Additionally a future release of Rust's +`wasm32-wasip3` target will support cooperative threading and `std::thread` +APIs. + +The original proposal for adding this target can be found in +[rust-lang/compiler-team#1001] and this target is first available on stable in +Rust 1.100.0. A notable major change from historical WebAssembly targets is that +the ABI of this target is slightly different. The linear memory shadow stack +pointer is stored in a component model task context slot instead of a +WebAssembly` global`. Additionally the base pointer of TLS is managed +differently than other targets. These changes are made to enable cooperative +multithreading on this target. + +> **Note**: As of 2026-09-03 cooperative multithreading is not yet supported on +> this target in Rust. The component model specification and library support +> work for this is in-development and not yet complete, but it's expected to be +> complete before the end of the year. Before that time spawning a thread via +> `std::thread` will return an error. Note though that this support can be +> tested through the [instructions below](#testing-cooperative-multithreading). + +[rust-lang/compiler-team#1001]: https://github.com/rust-lang/compiler-team/issues/1001 ## Target maintainers [@alexcrichton](https://github.com/alexcrichton) +[@yoshuawuyts](https://github.com/yoshuawuyts) ## Requirements -This target is cross-compiled. The target supports `std` fully. +This target is cross-compiled. The target supports `std` fully. This target +requires LLVM 23 to be used and additionally requires `wasi-sdk-34`-or-later if +you're building it locally or linking with this externally. ## Platform requirements -The WebAssembly runtime should support both WASIp2 and WASIp3. Runtimes also -are required to support components since this target outputs a component as -opposed to a core wasm module. Two example runtimes for WASIp3 are [Wasmtime] -and [Jco]. +WebAssembly runtimes that want to execute components compiled for this target +must support WASI 0.3.0 and the requisite required component model features +(notably async). Two example runtimes for WASIp3 are [Wasmtime] and [Jco]. [Wasmtime]: https://wasmtime.dev/ [Jco]: https://github.com/bytecodealliance/jco @@ -44,14 +51,14 @@ and [Jco]. ## Building the target To build this target first acquire a copy of -[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 22 +[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 34 is the minimum needed. Next configure the `WASI_SDK_PATH` environment variable to point to where this is installed. For example: ```text -export WASI_SDK_PATH=/path/to/wasi-sdk-22.0 +export WASI_SDK_PATH=/path/to/wasi-sdk-34.0 ``` Next be sure to enable LLD when building Rust from source as LLVM's `wasm-ld` @@ -81,3 +88,91 @@ It's recommended to conditionally compile code for this target with: The default set of WebAssembly features enabled for compilation is currently the same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the documentation there for more information. + +## Testing Cooperative Multithreading + +The [component model specification][spec] is in the process of adding intrinsics +to support cooperative multithreading in a component guest. These intrinsics can +be found in the [explainer] and are all gated by the 🧵 emoji. Support for +cooperative multithreading is a work-in-progress and not yet complete, but the +adventurous can configure this target to go ahead and test things out. + +The majority of changes necessary to get cooperative multithreading lie within +Rust's [wasi-libc dependency][wasi-libc]. This means that to test cooperative +multithreading a different build than the default wasi-libc needs to be used. +Starting with [wasi-sdk-34] there is a temporary sysroot which contains support +for a wasip3 target that has multithreading enabled in wasi-libc. To test out +the `wasm32-wasip3` Rust target with threads your compilation needs to be +configured to use this sysroot. + +An example of doing this is this program: + +```rust +fn main() { + std::thread::spawn(|| { + println!("hi"); + }) + .join() + .unwrap(); +} +``` + +is compiled and run by default as: + +```console +$ rustc foo.rs --target wasm32-wasip3 +$ wasmtime foo.wasm + +thread 'main' (1) panicked at library/std/src/thread/functions.rs:131:29: +failed to spawn thread: Os { code: 58, kind: Unsupported, message: "Not supported" } +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +Error: failed to run main module `foo.wasm` + +... +``` + +which shows that by default threads cannot be spawned. By configuring a custom +sysroot to be used, however: + +```console +$ rustc foo.rs --target wasm32-wasip3 \ + -Clink-self-contained=n \ + -Clinker=$WASI_SDK_PATH/bin/wasm32-wasip3-clang \ + -Clink-arg=--sysroot=$WASI_SDK_PATH/share/wasi-sysroot/experimental-coop-threads \ + -Clink-arg=-Wl,--export=cabi_realloc +$ wasmtime -W component-model-threading foo.wasm +hi +``` + +Here `-Clink-self-contained=n` avoids the vendored files in the standard library +which come from a build of wasi-libc incompatible with cooperative +multithreading. The `-Clinker` flag changes to use `clang` to be able to pass a +custom `--sysroot` argument and follow its logic for startup objects. The +`--sysroot` flag then points to the experimental sysroot for coop threads and +`--export` is required right now as a minor workaround. + +When compiling with Cargo you can use these environment variables: + +```console +$ export CARGO_TARGET_WASM32_WASIP3_LINKER=$WASI_SDK_PATH/bin/wasm32-wasip3-clang +$ export CARGO_TARGET_WASM32_WASIP3_RUNNER='wasmtime -W component-model-threading' +$ export CARGO_TARGET_WASM32_WASIP3_RUSTFLAGS="\ + -Clink-self-contained=n \ + -Clink-arg=--sysroot=$WASI_SDK_PATH/share/wasi-sysroot/experimental-coop-threads \ + -Clink-arg=-Wl,--export=cabi_realloc" +$ cargo run --target wasm32-wasip3 +hi +``` + +Standard synchronization primitives in `std::thread` and `std::sync` should all +work on this target with cooperative multithreading. Should you run into any +issues please don't hesitate to file an issue and cc the target maintainers. + +Note that it is currently intended that by the end of 2026 this support will all +be enabled by default and this section of the documentation will be deleted +since working with threads should "just work". + +[spec]: https://github.com/webassembly/component-model +[explainer]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md +[wasi-libc]: https://github.com/webassembly/wasi-libc +[wasi-sdk-34]: https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-34 diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md index 854d66f96756c..89e82126ece3a 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md @@ -14,6 +14,7 @@ This tracks support for additional registers in architectures where inline assem | ------------ | -------------- | --------- | -------------------- | | LoongArch | `vreg` | `$vr[0-31]` | `f` | | LoongArch | `xreg` | `$xr[0-31]` | `f` | +| AArch64 | `preg` | `p[0-16]` | `Upa` | ## Register class supported types @@ -21,6 +22,8 @@ This tracks support for additional registers in architectures where inline assem | ------------ | -------------- | -------------- | ------------- | | LoongArch | `vreg` | `lsx` | `i128`, `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | LoongArch | `xreg` | `lasx` | `i128`, `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`,
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | +| AArch64 | `vreg` | `sve` | `i8xN`, `i16xB`, `i32xN`, `i64xN`, `f16xN`, `f32xN`, `f64xN` (scalable vector) | +| AArch64 | `preg` | `sve` | `i1xN` (scalable vector predicate) | ## Register aliases @@ -45,3 +48,4 @@ This tracks support for additional registers in architectures where inline assem | LoongArch | `vreg` | `u` | `$xr0` | `u` | | LoongArch | `xreg` | None | `$xr0` | `u` | | LoongArch | `xreg` | `w` | `$vr0` | `w` | +| AArch64 | `vreg` | `z` | `z0` | `z` | diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index a6ef59738c8c7..9c50d7e472000 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -330,7 +330,7 @@ def cast_to_internal(node): for i in xrange(0, length + 1): if height > 0: - child_ptr = edges[i]["value"]["value"][ZERO_FIELD] + child_ptr = edges[i]["value"]["value"] for child in children_of_node(child_ptr, height - 1): yield child if i < length: @@ -338,12 +338,12 @@ def cast_to_internal(node): key_type_size = keys.type.sizeof val_type_size = vals.type.sizeof key = ( - keys[i]["value"]["value"][ZERO_FIELD] + keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()") ) val = ( - vals[i]["value"]["value"][ZERO_FIELD] + vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()") ) diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 4e2f09743a031..20ce1cae447cf 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -35,9 +35,9 @@ - {value.__0} + {value} - value.__0 + value diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 04c54e134b48e..db63dbaa24663 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -685,6 +685,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> { Nto => "QNX SDP 7.x", NuttX => "NuttX", OpenBsd => "OpenBSD", + Ps3 => "Play Station 3", Psp => "Play Station Portable", Psx => "Play Station 1", Qnx => "QNX SDP 8.0+", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 784a80ef02cd2..f1b903bf5dd22 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -48,8 +48,7 @@ use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::{ - self, AdtKind, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, + self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_middle::{bug, span_bug}; use rustc_span::ExpnKind; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 47b701e3c42d7..7a99ce8d39e9c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -451,7 +451,7 @@ impl Item { // were never supposed to work at all. let stab = self.stability(tcx)?; if let rustc_hir::StabilityLevel::Stable { - allowed_through_unstable_modules: Some(note), + allowed_through_unstable_modules: Some((note, _)), .. } = stab.level { @@ -2534,7 +2534,7 @@ mod size_asserts { static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); static_assert_size!(Item, 8); - static_assert_size!(ItemInner, 136); + static_assert_size!(ItemInner, 144); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 32); static_assert_size!(Type, 32); diff --git a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr index bdd004d5da99f..4435541bc0a1c 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr @@ -9,12 +9,8 @@ LL | *x = 1; help: was created by a Unique retag at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | / core::future::poll_fn(move |_| { -LL | | *x = 1; -LL | | Poll::<()>::Pending -LL | | }) -LL | | .await - | |______________^ +LL | let x = &mut 0u8; + | ^^^^^^^^ help: was later invalidated at offsets [RANGE] by a SharedReadOnly retag --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr index f9e75082758dd..bbb62a7e27b2b 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr @@ -10,12 +10,8 @@ LL | *x = 1; help: the accessed tag was created here, in the initial state Reserved --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | / core::future::poll_fn(move |_| { -LL | | *x = 1; -LL | | Poll::<()>::Pending -LL | | }) -LL | | .await - | |______________^ +LL | let x = &mut 0u8; + | ^^^^^^^^ help: the accessed tag later transitioned to Unique due to a child write access at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr index 190976c4f046f..594c91352d796 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u16>: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u16>: at .0, encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) --> tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs:LL:CC | LL | transmute::, MaybeDangling<&u16>>(unaligned) diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr index 041a6b1b96e0c..da8c88e16a1fe 100644 --- a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u8>: encountered a null reference +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u8>: at .0, encountered a null reference --> tests/fail/validity/maybe_dangling_null.rs:LL:CC | LL | unsafe { transmute::, MaybeDangling<&u8>>(null) }; diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr index f0966586d4dc7..2c82b2719e711 100644 --- a/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_ref_too_big.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&i8>: encountered a reference that is too close to the end of the address space for a pointee of 1 bytes +error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&i8>: at .0, encountered a reference that is too close to the end of the address space for a pointee of 1 bytes --> tests/fail/validity/maybe_dangling_ref_too_big.rs:LL:CC | LL | let _x: MaybeDangling<&i8> = unsafe { transmute(usize::MAX) }; diff --git a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs index 028dcef8fa2d3..2d37344d24072 100644 --- a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs +++ b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs @@ -14,6 +14,7 @@ fn main() { reference(); write_through_shared_ref(); large(); + closure(); } fn boxy() { @@ -64,3 +65,16 @@ fn large() { // Used to be rejected due to faulty logic for the "does this fit the address space" check. let _x: MaybeDangling<&i8> = unsafe { mem::transmute(usize::MAX - 127) }; } + +// A closure acts like MaybeDangling. +fn closure() { + fn invoke(f: impl FnOnce()) { + // The closure has captured a reference that will be freed while `invoke` runs. + f() + } + + let p = Box::leak(Box::new(0i32)); + invoke(move || { + drop(unsafe { Box::from_raw(p) }); + }); +} diff --git a/src/tools/miri/tests/pass/generators.rs b/src/tools/miri/tests/pass/generators.rs new file mode 100644 index 0000000000000..c5ab3fcb8e28f --- /dev/null +++ b/src/tools/miri/tests/pass/generators.rs @@ -0,0 +1,115 @@ +//@edition: 2024 +//@revisions: stack tree tree_implicit_writes +//@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes +//@[tree]compile-flags: -Zmiri-tree-borrows + +#![feature(gen_blocks)] + +fn main() { + basic(); + iterate(); + movable_gen(); + movable_gen2(); +} + +fn basic() { + gen fn foo() -> i32 { + yield 42; + for i in 5..10 { + if i % 2 == 0 { + continue; + } + yield i * 2; + } + } + + let v = foo().collect::>(); + assert_eq!(v, &[42, 10, 14, 18]); +} + +fn iterate() { + fn foo() -> impl Iterator { + gen { + yield 42; + for x in 3..6 { + yield x + } + } + } + + fn moved() -> impl Iterator { + let mut x = "foo".to_string(); + gen move { + yield 42; + if x == "foo" { + return; + } + x.clear(); + for x in 3..6 { + yield x + } + } + } + + let mut iter = foo(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), Some(4)); + assert_eq!(iter.next(), Some(5)); + assert_eq!(iter.next(), None); + // `gen` blocks are fused + assert_eq!(iter.next(), None); + + let mut iter = moved(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), None); +} + +/// Ensure a generator can reborrow from a reference it captured. +/// Regression test for . +pub fn movable_gen() { + fn make_gen(r: &mut u8) -> impl Iterator { + gen move { + let a = r; + *a = 1; + yield 1; + *a = 2; + } + } + + let mut a = 1; + let mut i = make_gen(&mut a); + assert_eq!(i.next(), Some(1)); + let mut j = i; + assert_eq!(j.next(), None); +} + +/// Regression test for . +fn movable_gen2() { + // a struct that has a drop flag and contains a reference + struct DropMut(&'static mut T); + impl Drop for DropMut { + fn drop(&mut self) { + drop(unsafe { Box::from_raw(self.0) }); + } + } + + let mut a = gen { + let b = DropMut(Box::leak(Box::new(1))); + + // create a drop flag on `b` + let c; + if true { + c = b; // and ensure it's set to false + } else { + c = DropMut(Box::leak(Box::new(2))); + } + + *c.0 = 3; + 4.yield; + *c.0 = 5; + }; + let _ = a.next(); + let mut d = a; + let _ = d.next(); +} diff --git a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout index 296339e738455..838733078209d 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout @@ -1,6 +1,6 @@ 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] -0..1: [ SharedReadWrite Unique Unique Unique Unique Unique Unique Unique ] -0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] +0..1: [ SharedReadWrite Unique Unique Unique Unique Unique ] +0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] 0..1: [ unknown-bottom(..) ] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index 1672e8e7930e3..c314b3f37c04d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -114,7 +114,7 @@ const KNOWN_ARCH: [&str; 20] = [ const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"]; -const KNOWN_OS: [&str; 20] = [ +const KNOWN_OS: [&str; 21] = [ "cuda", "dragonfly", "emscripten", @@ -128,6 +128,7 @@ const KNOWN_OS: [&str; 20] = [ "netbsd", "none", "openbsd", + "ps3", "psp", "redox", "solaris", diff --git a/tests/assembly-llvm/asm/aarch64-modifiers.rs b/tests/assembly-llvm/asm/aarch64-modifiers.rs index 6cb028461ddd1..66be35de574f6 100644 --- a/tests/assembly-llvm/asm/aarch64-modifiers.rs +++ b/tests/assembly-llvm/asm/aarch64-modifiers.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -C panic=abort -//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: aarch64 @@ -85,6 +85,12 @@ check!(vreg_q vreg "ldr {:q}, [x0]"); // CHECK: //NO_APP check!(vreg_v vreg "add {0:v}.4s, {0:v}.4s, {0:v}.4s"); +// CHECK-LABEL: vreg_z: +// CHECK: //APP +// CHECK: mov z0.d, z0.d +// CHECK: //NO_APP +check!(vreg_z vreg "mov {0:z}.d, {0:z}.d"); + // CHECK-LABEL: vreg_low16: // CHECK: //APP // CHECK: add v0.4s, v0.4s, v0.4s diff --git a/tests/assembly-llvm/asm/aarch64-types.rs b/tests/assembly-llvm/asm/aarch64-types.rs index c171ba3b11e13..da625b1211602 100644 --- a/tests/assembly-llvm/asm/aarch64-types.rs +++ b/tests/assembly-llvm/asm/aarch64-types.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ revisions: aarch64 aarch64_be arm64ec //@ assembly-output: emit-asm -//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve //@ [aarch64] needs-llvm-components: aarch64 //@ [aarch64_be] compile-flags: --target aarch64_be-unknown-linux-gnu //@ [aarch64_be] needs-llvm-components: aarch64 @@ -9,7 +9,7 @@ //@ [arm64ec] needs-llvm-components: aarch64 //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, f16, f128)] +#![feature(asm_experimental_reg, no_core, f16, f128, rustc_attrs)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -20,6 +20,62 @@ use minicore::*; type ptr = *mut u8; +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(16)] +pub struct svint8_t(i8); + +#[cfg(target_feature = "sve")] +impl Copy for svint8_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(8)] +pub struct svint16_t(i16); + +#[cfg(target_feature = "sve")] +impl Copy for svint16_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(4)] +pub struct svint32_t(i32); + +#[cfg(target_feature = "sve")] +impl Copy for svint32_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(2)] +pub struct svint64_t(i64); + +#[cfg(target_feature = "sve")] +impl Copy for svint64_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(8)] +pub struct svfloat16_t(f16); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat16_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(4)] +pub struct svfloat32_t(f32); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat32_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(2)] +pub struct svfloat64_t(f64); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat64_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(16)] +pub struct svbool_t(bool); + +#[cfg(target_feature = "sve")] +impl Copy for svbool_t {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -74,6 +130,25 @@ macro_rules! check { }; } +macro_rules! check_sve { + ($func:ident $ty:ident $class:ident $suffix:literal $zm:literal) => { + #[cfg(target_feature = "sve")] + #[no_mangle] + pub unsafe fn $func(inp: &$ty, pred: &svbool_t) -> $ty { + let x = *inp; + let z = *pred; + let y; + asm!( + concat!("mov {0}.", $suffix, ", p0/", $zm, ", {1}.", $suffix), + out($class) y, + in($class) x, + in("p0") z + ); + y + } + }; +} + macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { // FIXME(f128): See FIXME in `check!` @@ -87,6 +162,25 @@ macro_rules! check_reg { }; } +macro_rules! check_reg_sve { + ($func:ident $ty:ident $reg:tt $suffix:literal $zm:literal) => { + #[cfg(target_feature = "sve")] + #[no_mangle] + pub unsafe fn $func(inp: &$ty, pred: &svbool_t) -> $ty { + let x = *inp; + let z = *pred; + let y; + asm!( + concat!("mov ", $reg, ".", $suffix, ", p0/", $zm, ", ", $reg, ".", $suffix), + in("p0") z, + lateout($reg) y, + in($reg) x + ); + y + } + }; +} + // CHECK-LABEL: {{("#)?}}reg_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -405,6 +499,96 @@ check!(vreg_low16_f32x4 f32x4 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_f64x2 f64x2 vreg_low16 "fmov" "s"); +// aarch64-LABEL: {{("#)?}}vreg_sve_i8{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.b, p0/m, z{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(vreg_sve_i8 svint8_t vreg "b" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_sve_i16 svint16_t vreg "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_sve_f16 svfloat16_t vreg "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_sve_i32 svint32_t vreg "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_sve_f32 svfloat32_t vreg "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_sve_i64 svint64_t vreg "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_sve_f64 svfloat64_t vreg "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i8{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.b, p0/m, z{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i8 svint8_t vreg_low16 "b" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i16 svint16_t vreg_low16 "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f16 svfloat16_t vreg_low16 "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i32 svint32_t vreg_low16 "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f32 svfloat32_t vreg_low16 "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i64 svint64_t vreg_low16 "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f64 svfloat64_t vreg_low16 "d" "m"); + +// aarch64-LABEL: {{("#)?}}preg_bool{{"?}} +// aarch64: //APP +// aarch64: mov p{{[0-9]+}}.b, p0/z, p{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(preg_bool svbool_t preg "b" "z"); + // CHECK-LABEL: {{("#)?}}x0_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -501,6 +685,62 @@ check_reg!(v0_f64 f64 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_f128 f128 "s0" "fmov"); +// aarch64-LABEL: {{("#)?}}z0_i8{{"?}} +// aarch64: //APP +// aarch64: mov z0.b, p0/m, z0.b +// aarch64: //NO_APP +check_reg_sve!(z0_i8 svint8_t "z0" "b" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i16{{"?}} +// aarch64: //APP +// aarch64: mov z0.h, p0/m, z0.h +// aarch64: //NO_APP +check_reg_sve!(z0_i16 svint16_t "z0" "h" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f16{{"?}} +// aarch64: //APP +// aarch64: mov z0.h, p0/m, z0.h +// aarch64: //NO_APP +check_reg_sve!(z0_f16 svfloat16_t "z0" "h" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i32{{"?}} +// aarch64: //APP +// aarch64: mov z0.s, p0/m, z0.s +// aarch64: //NO_APP +check_reg_sve!(z0_i32 svint32_t "z0" "s" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f32{{"?}} +// aarch64: //APP +// aarch64: mov z0.s, p0/m, z0.s +// aarch64: //NO_APP +check_reg_sve!(z0_f32 svfloat32_t "z0" "s" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i64{{"?}} +// aarch64: //APP +// aarch64: mov z0.d, p0/m, z0.d +// aarch64: //NO_APP +check_reg_sve!(z0_i64 svint64_t "z0" "d" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f64{{"?}} +// aarch64: //APP +// aarch64: mov z0.d, p0/m, z0.d +// aarch64: //NO_APP +check_reg_sve!(z0_f64 svfloat64_t "z0" "d" "m"); + +// aarch64-LABEL: {{("#)?}}p0_bool{{"?}} +// aarch64: //APP +// aarch64: mov p0.b, p1/z, p0.b +// aarch64: //NO_APP +#[cfg(target_feature = "sve")] +#[no_mangle] +pub unsafe fn p0_bool(inp: &svbool_t, pred: &svbool_t) -> svbool_t { + let x = *inp; + let z = *pred; + let y; + asm!("mov p0.b, p1/z, p0.b", in("p1") z, lateout("p0") y, in("p0") x); + y +} + // CHECK-LABEL: {{("#)?}}v0_ptr{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 49bced1dd5bd2..beefbdb889940 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -403,6 +403,9 @@ //@ revisions: msp430_none_elf //@ [msp430_none_elf] compile-flags: --target msp430-none-elf //@ [msp430_none_elf] needs-llvm-components: msp430 +//@ revisions: powerpc64_sony_ps3 +//@ [powerpc64_sony_ps3] compile-flags: --target powerpc64-sony-ps3 +//@ [powerpc64_sony_ps3] needs-llvm-components: powerpc //@ revisions: powerpc64_unknown_freebsd //@ [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd //@ [powerpc64_unknown_freebsd] needs-llvm-components: powerpc diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 04564049dbed2..2b7eb0b9afbcf 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -496,4 +496,5 @@ pub mod simd { pub type i64x8 = Simd; pub type u8x16 = Simd; + pub type u64x2 = Simd; } diff --git a/tests/codegen-llvm/aarch64-abi/homogeneous-aggregate.rs b/tests/codegen-llvm/aarch64-abi/homogeneous-aggregate.rs new file mode 100644 index 0000000000000..3d5ec10f2b2f7 --- /dev/null +++ b/tests/codegen-llvm/aarch64-abi/homogeneous-aggregate.rs @@ -0,0 +1,84 @@ +//@ add-minicore +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 +// +//@ revisions: linux win +//@[linux] compile-flags: --target aarch64-unknown-linux-gnu +//@[win] compile-flags: --target aarch64-pc-windows-msvc +// +//@ needs-llvm-components: aarch64 + +// Test that homogeneous aggregates are passed and returned with the correct ABI. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::simd::*; +use minicore::*; + +// A homogeneous float aggregate. +#[repr(C)] +pub struct Hfa { + pub a: f32, + pub b: f32, +} +impl Copy for Hfa {} + +// CHECK: define void @test_hfa([2 x float] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa(a: Hfa) { + hint::black_box(a); +} + +// Fields can be vectors too. +#[repr(C)] +pub struct Hfa2V2F64 { + pub a: f64x2, + pub b: f64x2, +} + +// CHECK: define void @test_hfa_2_f64x2([2 x <2 x double>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_f64x2(a: Hfa2V2F64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2U64 { + pub a: u64x2, + pub b: u64x2, +} + +// CHECK: define void @test_hfa_2_u64x2([2 x <16 x i8>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_u64x2(a: Hfa2V2U64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2F32 { + pub a: f32x2, + pub b: f32x2, +} + +// CHECK: define void @test_hfa_2_f32x2([2 x <2 x float>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_f32x2(a: Hfa2V2F32) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa4V2F64 { + pub a: f64x2, + pub b: f64x2, + pub c: f64x2, + pub d: f64x2, +} + +// CHECK: define void @test_hfa_4_f64x2([4 x <2 x double>] %0) +#[unsafe(no_mangle)] +#[target_feature(enable = "neon")] +pub extern "C" fn test_hfa_4_f64x2(a: Hfa4V2F64) { + hint::black_box(a); +} diff --git a/tests/codegen-llvm/arm-abi/homogeneous-aggregate.rs b/tests/codegen-llvm/arm-abi/homogeneous-aggregate.rs index c44dc4fa56f5f..272eb419494b0 100644 --- a/tests/codegen-llvm/arm-abi/homogeneous-aggregate.rs +++ b/tests/codegen-llvm/arm-abi/homogeneous-aggregate.rs @@ -11,10 +11,12 @@ // Test that homogeneous aggregates are passed and returned with the correct ABI on 32-bit arm. #![feature(no_core, lang_items)] +#![feature(arm_target_feature)] #![crate_type = "lib"] #![no_core] extern crate minicore; +use minicore::simd::*; use minicore::*; // A homogeneous float aggregate, which a hard-float ABI passes in VFP registers. @@ -68,6 +70,69 @@ pub extern "C" fn test_hfa_4_f64(a: Hfa4F64) { hint::black_box(a); } +// Fields can be vectors too. +#[repr(C)] +pub struct Hfa2V2F64 { + pub a: f64x2, + pub b: f64x2, +} + +// linux: define void @test_hfa_2_f64x2([2 x <2 x double>] %0) +// eabi: define dso_local void @test_hfa_2_f64x2([4 x i64] %0) +// watchos: define void @test_hfa_2_f64x2([2 x <2 x double>] %0) +#[unsafe(no_mangle)] +#[target_feature(enable = "neon")] +pub extern "C" fn test_hfa_2_f64x2(a: Hfa2V2F64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2U64 { + pub a: u64x2, + pub b: u64x2, +} + +// linux: define void @test_hfa_2_u64x2([2 x <16 x i8>] %0) +// eabi: define dso_local void @test_hfa_2_u64x2([4 x i64] %0) +// watchos: define void @test_hfa_2_u64x2([2 x <16 x i8>] %0) +#[unsafe(no_mangle)] +#[target_feature(enable = "neon")] +pub extern "C" fn test_hfa_2_u64x2(a: Hfa2V2U64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2F32 { + pub a: f32x2, + pub b: f32x2, +} + +// linux: define void @test_hfa_2_f32x2([2 x <2 x float>] %0) +// eabi: define dso_local void @test_hfa_2_f32x2([2 x i64] %0) +// watchos: define void @test_hfa_2_f32x2([2 x <2 x float>] %0) +#[unsafe(no_mangle)] +#[target_feature(enable = "neon")] +pub extern "C" fn test_hfa_2_f32x2(a: Hfa2V2F32) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa4V2F64 { + pub a: f64x2, + pub b: f64x2, + pub c: f64x2, + pub d: f64x2, +} + +// linux: define void @test_hfa_4_f64x2([4 x <2 x double>] %0) +// eabi: define dso_local void @test_hfa_4_f64x2([8 x i64] %0) +// watchos: define void @test_hfa_4_f64x2([4 x <2 x double>] %0) +#[unsafe(no_mangle)] +#[target_feature(enable = "neon")] +pub extern "C" fn test_hfa_4_f64x2(a: Hfa4V2F64) { + hint::black_box(a); +} + // A homogeneous aggregate can have at most 4 fields, so this does not qualify. #[repr(C)] pub struct Floats5 { diff --git a/tests/codegen-llvm/maybe_dangling_refs.rs b/tests/codegen-llvm/maybe_dangling_refs.rs index 07493ecac79c5..5d097151db4d7 100644 --- a/tests/codegen-llvm/maybe_dangling_refs.rs +++ b/tests/codegen-llvm/maybe_dangling_refs.rs @@ -7,7 +7,7 @@ #![crate_type = "lib"] #![feature(maybe_dangling)] -use std::mem::MaybeDangling; +use std::mem::{ManuallyDrop, MaybeDangling}; // CHECK: define {{(dso_local )?}}noundef nonnull ptr @f(ptr noundef nonnull %x) unnamed_addr #[no_mangle] @@ -15,6 +15,12 @@ pub fn f(x: MaybeDangling>) -> MaybeDangling> { x } +// CHECK: define {{(dso_local )?}}noundef nonnull ptr @f2(ptr noundef nonnull %x) unnamed_addr +#[no_mangle] +pub fn f2(x: ManuallyDrop>) -> ManuallyDrop> { + x +} + // CHECK: define {{(dso_local )?}}noundef nonnull ptr @g(ptr noundef nonnull %x) unnamed_addr #[no_mangle] pub fn g(x: MaybeDangling<&u8>) -> MaybeDangling<&u8> { diff --git a/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs new file mode 100644 index 0000000000000..dd053411aa4e5 --- /dev/null +++ b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs @@ -0,0 +1,96 @@ +//@ add-minicore +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 +// +//@ revisions: ppc64 ppc64_vsx ppc64le +//@[ppc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[ppc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -Ctarget-feature=+vsx +//@[ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu +// +//@ needs-llvm-components: powerpc + +// Test that homogeneous aggregates are passed and returned with the correct ABI. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::simd::*; +use minicore::*; + +// A homogeneous float aggregate. +#[repr(C)] +pub struct Hfa { + pub a: f32, + pub b: f32, +} +impl Copy for Hfa {} + +// ppc64: define void @test_hfa(i64 %0) +// ppc64_vsx: define void @test_hfa(i64 %0) +// ppc64le: define void @test_hfa([2 x float] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa(a: Hfa) { + hint::black_box(a); +} + +// Fields can be vectors too. +#[repr(C)] +pub struct Hfa2V2F64 { + pub a: f64x2, + pub b: f64x2, +} + +// ppc64: define void @test_hfa_2_f64x2([2 x i128] %0) +// ppc64_vsx: define void @test_hfa_2_f64x2([2 x i128] %0) +// ppc64le: define void @test_hfa_2_f64x2([2 x <2 x double>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_f64x2(a: Hfa2V2F64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2U64 { + pub a: u64x2, + pub b: u64x2, +} + +// ppc64: define void @test_hfa_2_u64x2([2 x i128] %0) +// ppc64_vsx: define void @test_hfa_2_u64x2([2 x i128] %0) +// ppc64le: define void @test_hfa_2_u64x2([2 x <16 x i8>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_u64x2(a: Hfa2V2U64) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa2V2F32 { + pub a: f32x2, + pub b: f32x2, +} + +// On PowerPC only 128-bit units are eligible for HVA. +// +// ppc64: define void @test_hfa_2_f32x2([2 x i64] %0) +// ppc64_vsx: define void @test_hfa_2_f32x2([2 x i64] %0) +// ppc64le: define void @test_hfa_2_f32x2([2 x i64] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_2_f32x2(a: Hfa2V2F32) { + hint::black_box(a); +} + +#[repr(C)] +pub struct Hfa4V2F64 { + pub a: f64x2, + pub b: f64x2, + pub c: f64x2, + pub d: f64x2, +} + +// ppc64: define void @test_hfa_4_f64x2([4 x i128] %0) +// ppc64_vsx: define void @test_hfa_4_f64x2([4 x i128] %0) +// ppc64le: define void @test_hfa_4_f64x2([4 x <2 x double>] %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_hfa_4_f64x2(a: Hfa4V2F64) { + hint::black_box(a); +} diff --git a/tests/codegen-llvm/preserve-vec-element-types.rs b/tests/codegen-llvm/preserve-vec-element-types.rs index b3908b1c24cc2..00f9ef6fab2a6 100644 --- a/tests/codegen-llvm/preserve-vec-element-types.rs +++ b/tests/codegen-llvm/preserve-vec-element-types.rs @@ -52,21 +52,22 @@ mod tests { // CHECK: define [2 x <1 x ptr>] @pair_ptrx1_t([2 x <1 x ptr>] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn pair_ptrx1_t(x: Pair>) -> Pair> { x } - // When it fits in a 128-bit register, it's passed directly. + // When the fields are not 64 or 128 bits in size, they do not qualify as a homogeneous + // aggregate, and passed as type-erased sequences of integers. - // CHECK: define [4 x <4 x i8>] @quad_int8x4_t([4 x <4 x i8>] {{.*}} %0) + // CHECK: define [2 x i64] @quad_int8x4_t([2 x i64] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn quad_int8x4_t(x: Quad>) -> Quad> { x } - // CHECK: define [4 x <2 x i16>] @quad_int16x2_t([4 x <2 x i16>] {{.*}} %0) + // CHECK: define [2 x i64] @quad_int16x2_t([2 x i64] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn quad_int16x2_t(x: Quad>) -> Quad> { x } - // CHECK: define [4 x <1 x i32>] @quad_int32x1_t([4 x <1 x i32>] {{.*}} %0) + // CHECK: define [2 x i64] @quad_int32x1_t([2 x i64] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn quad_int32x1_t(x: Quad>) -> Quad> { x } - // CHECK: define [4 x <2 x half>] @quad_float16x2_t([4 x <2 x half>] {{.*}} %0) + // CHECK: define [2 x i64] @quad_float16x2_t([2 x i64] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn quad_float16x2_t(x: Quad>) -> Quad> { x } - // CHECK: define [4 x <1 x float>] @quad_float32x1_t([4 x <1 x float>] {{.*}} %0) + // CHECK: define [2 x i64] @quad_float32x1_t([2 x i64] {{.*}} %0) #[unsafe(no_mangle)] extern "C" fn quad_float32x1_t(x: Quad>) -> Quad> { x } // When it doesn't quite fit, padding is added which does erase the type. @@ -74,23 +75,23 @@ mod tests { // CHECK: define [2 x i64] @triple_int8x4_t #[unsafe(no_mangle)] extern "C" fn triple_int8x4_t(x: Triple>) -> Triple> { x } - // Other configurations are not passed by-value but indirectly. + // Other configurations passed directly when they qualify as a homogeneous aggregate. - // CHECK: define void @pair_int128x1_t + // CHECK: define [2 x <1 x i128>] @pair_int128x1_t([2 x <1 x i128>] #[unsafe(no_mangle)] extern "C" fn pair_int128x1_t(x: Pair>) -> Pair> { x } - // CHECK: define void @pair_float128x1_t + // CHECK: define [2 x <1 x fp128>] @pair_float128x1_t([2 x <1 x fp128>] #[unsafe(no_mangle)] extern "C" fn pair_float128x1_t(x: Pair>) -> Pair> { x } - // CHECK: define void @pair_int8x16_t + // CHECK: define [2 x <16 x i8>] @pair_int8x16_t([2 x <16 x i8>] #[unsafe(no_mangle)] extern "C" fn pair_int8x16_t(x: Pair>) -> Pair> { x } - // CHECK: define void @pair_int16x8_t + // CHECK: define [2 x <8 x i16>] @pair_int16x8_t([2 x <8 x i16>] #[unsafe(no_mangle)] extern "C" fn pair_int16x8_t(x: Pair>) -> Pair> { x } - // CHECK: define void @triple_int16x8_t + // CHECK: define [3 x <8 x i16>] @triple_int16x8_t([3 x <8 x i16>] #[unsafe(no_mangle)] extern "C" fn triple_int16x8_t(x: Triple>) -> Triple> { x } - // CHECK: define void @quad_int16x8_t + // CHECK: define [4 x <8 x i16>] @quad_int16x8_t([4 x <8 x i16>] #[unsafe(no_mangle)] extern "C" fn quad_int16x8_t(x: Quad>) -> Quad> { x } } diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map index 543ab89628281..4500eab355739 100644 --- a/tests/coverage/assert.cov-map +++ b/tests/coverage/assert.cov-map @@ -1,42 +1,72 @@ -Function name: assert::main -Raw bytes (76): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 0c, 01, 09, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Function name: assert::assert_a_plain +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 06, 01, 00, 25, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 10, 01, 00, 11, 00, 18, 05, 01, 05, 00, 0f, 09, 01, 05, 00, 0f, 15, 01, 05, 00, 14, 0d, 00, 15, 00, 18, 11, 00, 1f, 00, 25, 15, 01, 01, 00, 02] Number of files: 1 - file 0 => $DIR/assert.rs -Number of expressions: 6 -- expression 0 operands: lhs = Counter(1), rhs = Counter(0) -- expression 1 operands: lhs = Counter(1), rhs = Expression(5, Add) -- expression 2 operands: lhs = Counter(0), rhs = Counter(2) -- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) -- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) -- expression 5 operands: lhs = Counter(0), rhs = Counter(2) -Number of file 0 mappings: 12 -- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 28) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) -- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) -- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) -- Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 26) - = (c1 - c0) -- Code(Counter(2)) at (prev + 0, 27) to (start + 2, 10) -- Code(Expression(1, Sub)) at (prev + 2, 19) to (start + 0, 32) - = (c1 - (c0 + c2)) -- Code(Counter(3)) at (prev + 0, 33) to (start + 2, 10) -- Code(Expression(3, Sub)) at (prev + 2, 9) to (start + 0, 10) - = (c1 - ((c0 + c2) + c3)) -- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) - = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) -- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) -Highest counter ID seen: c3 +Number of expressions: 0 +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 37) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 5) to (start + 0, 20) +- Code(Counter(3)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 37) +- Code(Counter(5)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 + +Function name: assert::assert_b_message +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 0d, 01, 00, 27, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 10, 01, 00, 11, 00, 18, 05, 01, 05, 00, 0f, 09, 01, 05, 00, 0f, 15, 01, 05, 00, 14, 0d, 00, 15, 00, 18, 11, 00, 1f, 00, 25, 15, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/assert.rs +Number of expressions: 0 +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 39) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 5) to (start + 0, 20) +- Code(Counter(3)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 37) +- Code(Counter(5)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 + +Function name: assert::assert_c_format_inline +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 14, 01, 00, 38, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 10, 01, 00, 11, 00, 18, 05, 01, 05, 00, 0f, 09, 01, 05, 00, 0f, 15, 01, 05, 00, 14, 0d, 00, 15, 00, 18, 11, 00, 1f, 00, 25, 15, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/assert.rs +Number of expressions: 0 +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 56) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 5) to (start + 0, 20) +- Code(Counter(3)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 37) +- Code(Counter(5)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 -Function name: assert::might_fail_assert -Raw bytes (24): 0x[01, 01, 00, 04, 01, 04, 01, 00, 28, 01, 01, 05, 00, 0d, 01, 01, 05, 00, 0f, 05, 01, 01, 00, 02] +Function name: assert::assert_d_format_arg +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 1b, 01, 00, 35, 01, 01, 05, 00, 0c, 01, 00, 0d, 00, 10, 01, 00, 11, 00, 18, 05, 01, 05, 00, 0f, 09, 01, 05, 00, 0f, 15, 01, 05, 00, 14, 0d, 00, 15, 00, 18, 11, 00, 1f, 00, 25, 15, 01, 01, 00, 02] Number of files: 1 - file 0 => $DIR/assert.rs Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 40) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) -- Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) -Highest counter ID seen: c1 +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 53) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 24) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 5) to (start + 0, 20) +- Code(Counter(3)) at (prev + 0, 21) to (start + 0, 24) +- Code(Counter(4)) at (prev + 0, 31) to (start + 0, 37) +- Code(Counter(5)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 diff --git a/tests/coverage/assert.coverage b/tests/coverage/assert.coverage index 29a5b48c0566a..d9171fd705c99 100644 --- a/tests/coverage/assert.coverage +++ b/tests/coverage/assert.coverage @@ -1,33 +1,42 @@ - LL| |#![allow(unused_assignments)] - LL| |//@ failure-status: 101 + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 LL| | - LL| 4|fn might_fail_assert(one_plus_one: u32) { - LL| 4| println!("does 1 + 1 = {}?", one_plus_one); - LL| 4| assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); - LL| 3|} + LL| |use core::assert_matches; LL| | - LL| 1|fn main() -> Result<(), u8> { - LL| 1| let mut countdown = 10; - LL| 10| while countdown > 0 { - LL| 9| if countdown == 1 { - LL| 1| might_fail_assert(3); - LL| 8| } else if countdown < 5 { - LL| 3| might_fail_assert(2); - LL| 5| } - LL| 9| countdown -= 1; - LL| | } - LL| 1| Ok(()) + LL| 1|fn assert_a_plain(opt: Option<&str>) { + LL| 1| assert!(opt.is_some()); + LL| 1| assert_eq!(opt, Some("true")); + LL| 1| assert_ne!(opt, None); + LL| 1| assert_matches!(opt, Some("true")); LL| 1|} LL| | - LL| |// Notes: - LL| |// 1. Compare this program and its coverage results to those of the very similar test - LL| |// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. - LL| |// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or - LL| |// related `assert_*!()` macro. - LL| |// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce - LL| |// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to - LL| |// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). - LL| |// 4. `TerminatorKind::Assert` is, however, also present in the MIR generated for this test - LL| |// (and in many other coverage tests). The `Assert` terminator is typically generated by the - LL| |// Rust compiler to check for runtime failures, such as numeric overflows. + LL| 1|fn assert_b_message(opt: Option<&str>) { + LL| 1| assert!(opt.is_some(), "message"); + LL| 1| assert_eq!(opt, Some("true"), "message"); + LL| 1| assert_ne!(opt, None, "message"); + LL| 1| assert_matches!(opt, Some("true"), "message"); + LL| 1|} + LL| | + LL| 1|fn assert_c_format_inline(opt: Option<&str>, msg: &str) { + LL| 1| assert!(opt.is_some(), "message: {msg}"); + LL| 1| assert_eq!(opt, Some("true"), "message: {msg}"); + LL| 1| assert_ne!(opt, None, "message: {msg}"); + LL| 1| assert_matches!(opt, Some("true"), "message: {msg}"); + LL| 1|} + LL| | + LL| 1|fn assert_d_format_arg(opt: Option<&str>, msg: &str) { + LL| 1| assert!(opt.is_some(), "message: {}", msg); + LL| 1| assert_eq!(opt, Some("true"), "message: {}", msg); + LL| 1| assert_ne!(opt, None, "message: {}", msg); + LL| 1| assert_matches!(opt, Some("true"), "message: {}", msg); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt = core::hint::black_box(Some("true")); + LL| | assert_a_plain(opt); + LL| | assert_b_message(opt); + LL| | assert_c_format_inline(opt, "message"); + LL| | assert_d_format_arg(opt, "message"); + LL| |} diff --git a/tests/coverage/assert.rs b/tests/coverage/assert.rs index 30d511f8f7a89..9c3151ba4ce17 100644 --- a/tests/coverage/assert.rs +++ b/tests/coverage/assert.rs @@ -1,32 +1,41 @@ -#![allow(unused_assignments)] -//@ failure-status: 101 +#![feature(coverage_attribute)] +//@ edition: 2024 -fn might_fail_assert(one_plus_one: u32) { - println!("does 1 + 1 = {}?", one_plus_one); - assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); +use core::assert_matches; + +fn assert_a_plain(opt: Option<&str>) { + assert!(opt.is_some()); + assert_eq!(opt, Some("true")); + assert_ne!(opt, None); + assert_matches!(opt, Some("true")); +} + +fn assert_b_message(opt: Option<&str>) { + assert!(opt.is_some(), "message"); + assert_eq!(opt, Some("true"), "message"); + assert_ne!(opt, None, "message"); + assert_matches!(opt, Some("true"), "message"); } -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - might_fail_assert(3); - } else if countdown < 5 { - might_fail_assert(2); - } - countdown -= 1; - } - Ok(()) +fn assert_c_format_inline(opt: Option<&str>, msg: &str) { + assert!(opt.is_some(), "message: {msg}"); + assert_eq!(opt, Some("true"), "message: {msg}"); + assert_ne!(opt, None, "message: {msg}"); + assert_matches!(opt, Some("true"), "message: {msg}"); } -// Notes: -// 1. Compare this program and its coverage results to those of the very similar test -// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or -// related `assert_*!()` macro. -// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce -// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to -// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). -// 4. `TerminatorKind::Assert` is, however, also present in the MIR generated for this test -// (and in many other coverage tests). The `Assert` terminator is typically generated by the -// Rust compiler to check for runtime failures, such as numeric overflows. +fn assert_d_format_arg(opt: Option<&str>, msg: &str) { + assert!(opt.is_some(), "message: {}", msg); + assert_eq!(opt, Some("true"), "message: {}", msg); + assert_ne!(opt, None, "message: {}", msg); + assert_matches!(opt, Some("true"), "message: {}", msg); +} + +#[coverage(off)] +fn main() { + let opt = core::hint::black_box(Some("true")); + assert_a_plain(opt); + assert_b_message(opt); + assert_c_format_inline(opt, "message"); + assert_d_format_arg(opt, "message"); +} diff --git a/tests/coverage/async.cov-map b/tests/coverage/async/async.cov-map similarity index 100% rename from tests/coverage/async.cov-map rename to tests/coverage/async/async.cov-map diff --git a/tests/coverage/async.coverage b/tests/coverage/async/async.coverage similarity index 100% rename from tests/coverage/async.coverage rename to tests/coverage/async/async.coverage diff --git a/tests/coverage/async.rs b/tests/coverage/async/async.rs similarity index 100% rename from tests/coverage/async.rs rename to tests/coverage/async/async.rs diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async/async2.cov-map similarity index 100% rename from tests/coverage/async2.cov-map rename to tests/coverage/async/async2.cov-map diff --git a/tests/coverage/async2.coverage b/tests/coverage/async/async2.coverage similarity index 100% rename from tests/coverage/async2.coverage rename to tests/coverage/async/async2.coverage diff --git a/tests/coverage/async2.rs b/tests/coverage/async/async2.rs similarity index 100% rename from tests/coverage/async2.rs rename to tests/coverage/async/async2.rs diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async/async_block.cov-map similarity index 100% rename from tests/coverage/async_block.cov-map rename to tests/coverage/async/async_block.cov-map diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async/async_block.coverage similarity index 100% rename from tests/coverage/async_block.coverage rename to tests/coverage/async/async_block.coverage diff --git a/tests/coverage/async_block.rs b/tests/coverage/async/async_block.rs similarity index 100% rename from tests/coverage/async_block.rs rename to tests/coverage/async/async_block.rs diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async/async_closure.cov-map similarity index 100% rename from tests/coverage/async_closure.cov-map rename to tests/coverage/async/async_closure.cov-map diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async/async_closure.coverage similarity index 100% rename from tests/coverage/async_closure.coverage rename to tests/coverage/async/async_closure.coverage diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async/async_closure.rs similarity index 100% rename from tests/coverage/async_closure.rs rename to tests/coverage/async/async_closure.rs diff --git a/tests/coverage/async_closure2.cov-map b/tests/coverage/async/async_closure2.cov-map similarity index 100% rename from tests/coverage/async_closure2.cov-map rename to tests/coverage/async/async_closure2.cov-map diff --git a/tests/coverage/async_closure2.coverage b/tests/coverage/async/async_closure2.coverage similarity index 100% rename from tests/coverage/async_closure2.coverage rename to tests/coverage/async/async_closure2.coverage diff --git a/tests/coverage/async_closure2.rs b/tests/coverage/async/async_closure2.rs similarity index 100% rename from tests/coverage/async_closure2.rs rename to tests/coverage/async/async_closure2.rs diff --git a/tests/coverage/auxiliary/executor.rs b/tests/coverage/async/auxiliary/executor.rs similarity index 100% rename from tests/coverage/auxiliary/executor.rs rename to tests/coverage/async/auxiliary/executor.rs diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/async/await_ready.cov-map similarity index 100% rename from tests/coverage/await_ready.cov-map rename to tests/coverage/async/await_ready.cov-map diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/async/await_ready.coverage similarity index 100% rename from tests/coverage/await_ready.coverage rename to tests/coverage/async/await_ready.coverage diff --git a/tests/coverage/await_ready.rs b/tests/coverage/async/await_ready.rs similarity index 100% rename from tests/coverage/await_ready.rs rename to tests/coverage/async/await_ready.rs diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/async/closure_macro_async.cov-map similarity index 100% rename from tests/coverage/closure_macro_async.cov-map rename to tests/coverage/async/closure_macro_async.cov-map diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/async/closure_macro_async.coverage similarity index 100% rename from tests/coverage/closure_macro_async.coverage rename to tests/coverage/async/closure_macro_async.coverage diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/async/closure_macro_async.rs similarity index 100% rename from tests/coverage/closure_macro_async.rs rename to tests/coverage/async/closure_macro_async.rs diff --git a/tests/coverage/call-method.cov-map b/tests/coverage/call-method.cov-map new file mode 100644 index 0000000000000..534cc4b6a58af --- /dev/null +++ b/tests/coverage/call-method.cov-map @@ -0,0 +1,19 @@ +Function name: call_method::call_method +Raw bytes (59): 0x[01, 01, 00, 0b, 01, 08, 01, 00, 11, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 16, 01, 02, 05, 00, 0a, 01, 02, 09, 00, 0f, 01, 02, 0d, 00, 12, 01, 04, 05, 05, 0a, 01, 00, 05, 00, 0a, 01, 07, 09, 00, 0f, 01, 02, 0d, 00, 12, 01, 03, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/call-method.rs +Number of expressions: 0 +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 22) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18) +- Code(Counter(0)) at (prev + 4, 5) to (start + 5, 10) +- Code(Counter(0)) at (prev + 0, 5) to (start + 0, 10) +- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 15) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/call-method.coverage b/tests/coverage/call-method.coverage new file mode 100644 index 0000000000000..afcdb0adc7b73 --- /dev/null +++ b/tests/coverage/call-method.coverage @@ -0,0 +1,46 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ min-llvm-version: 23 + LL| | + LL| |// Basic test for method calls and chained method calls. + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn call_method() { + LL| 1| let thing = Thing; + LL| | + LL| 1| thing + LL| | . + LL| 1| method + LL| | ( + LL| 1| "arg" + LL| | ) + LL| | ; + LL| | + LL| 1| thing + LL| 1| . + LL| 1| method + LL| 1| ( + LL| 1| "arg" + LL| 1| ) + LL| | . + LL| 1| method + LL| | ( + LL| 1| "arg" + LL| | ) + LL| | ; + LL| 1|} + LL| | + LL| |struct Thing; + LL| | + LL| |#[coverage(off)] + LL| |impl Thing { + LL| | fn method(&self, _arg: &str) -> &Self { + LL| | self + LL| | } + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | call_method(); + LL| |} + diff --git a/tests/coverage/call-method.rs b/tests/coverage/call-method.rs new file mode 100644 index 0000000000000..42b753503331b --- /dev/null +++ b/tests/coverage/call-method.rs @@ -0,0 +1,45 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ min-llvm-version: 23 + +// Basic test for method calls and chained method calls. + +#[rustfmt::skip] +fn call_method() { + let thing = Thing; + + thing + . + method + ( + "arg" + ) + ; + + thing + . + method + ( + "arg" + ) + . + method + ( + "arg" + ) + ; +} + +struct Thing; + +#[coverage(off)] +impl Thing { + fn method(&self, _arg: &str) -> &Self { + self + } +} + +#[coverage(off)] +fn main() { + call_method(); +} diff --git a/tests/coverage/for.many.coverage b/tests/coverage/for.many.coverage new file mode 100644 index 0000000000000..c6908b64cd615 --- /dev/null +++ b/tests/coverage/for.many.coverage @@ -0,0 +1,39 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: zero one many + LL| |//@[one] ignore-coverage-map + LL| |//@[many] ignore-coverage-map + LL| | + LL| |// Basic test of `for` loops. + LL| | + LL| 1|fn for_loop(items: &[&str]) { + LL| 1| say("hello"); + LL| | + LL| 3| for item in items { + ^1 + LL| 3| say(item); + LL| 3| } + LL| | + LL| 3| for item in items { + ^1 + LL| 3| say(item) + LL| | } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let items = cfg_select!( + LL| | zero => &[], + LL| | one => &["one"], + LL| | many => &["one", "two", "three"], + LL| | ); + LL| | for_loop(items); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/for.one.coverage b/tests/coverage/for.one.coverage new file mode 100644 index 0000000000000..285d379c526f9 --- /dev/null +++ b/tests/coverage/for.one.coverage @@ -0,0 +1,37 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: zero one many + LL| |//@[one] ignore-coverage-map + LL| |//@[many] ignore-coverage-map + LL| | + LL| |// Basic test of `for` loops. + LL| | + LL| 1|fn for_loop(items: &[&str]) { + LL| 1| say("hello"); + LL| | + LL| 1| for item in items { + LL| 1| say(item); + LL| 1| } + LL| | + LL| 1| for item in items { + LL| 1| say(item) + LL| | } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let items = cfg_select!( + LL| | zero => &[], + LL| | one => &["one"], + LL| | many => &["one", "two", "three"], + LL| | ); + LL| | for_loop(items); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/for.rs b/tests/coverage/for.rs new file mode 100644 index 0000000000000..55a2cfc2c18d2 --- /dev/null +++ b/tests/coverage/for.rs @@ -0,0 +1,36 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: zero one many +//@[one] ignore-coverage-map +//@[many] ignore-coverage-map + +// Basic test of `for` loops. + +fn for_loop(items: &[&str]) { + say("hello"); + + for item in items { + say(item); + } + + for item in items { + say(item) + } + + say("goodbye"); +} + +#[coverage(off)] +fn main() { + let items = cfg_select!( + zero => &[], + one => &["one"], + many => &["one", "two", "three"], + ); + for_loop(items); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/for.zero.cov-map b/tests/coverage/for.zero.cov-map new file mode 100644 index 0000000000000..4ac461b85719f --- /dev/null +++ b/tests/coverage/for.zero.cov-map @@ -0,0 +1,30 @@ +Function name: for::for_loop +Raw bytes (77): 0x[01, 01, 04, 05, 01, 09, 01, 09, 01, 09, 01, 0d, 01, 09, 01, 00, 1c, 01, 01, 05, 00, 08, 01, 00, 09, 00, 10, 02, 02, 09, 00, 0d, 01, 00, 11, 00, 16, 02, 00, 17, 02, 06, 0e, 04, 09, 00, 0d, 01, 00, 11, 00, 16, 0e, 01, 09, 00, 0c, 0e, 00, 0d, 00, 11, 01, 03, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/for.rs +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Counter(0) +- expression 1 operands: lhs = Counter(2), rhs = Counter(0) +- expression 2 operands: lhs = Counter(2), rhs = Counter(0) +- expression 3 operands: lhs = Counter(2), rhs = Counter(0) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 13) + = (c1 - c0) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 22) +- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 2, 6) + = (c1 - c0) +- Code(Expression(3, Sub)) at (prev + 4, 9) to (start + 0, 13) + = (c2 - c0) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 22) +- Code(Expression(3, Sub)) at (prev + 1, 9) to (start + 0, 12) + = (c2 - c0) +- Code(Expression(3, Sub)) at (prev + 0, 13) to (start + 0, 17) + = (c2 - c0) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/for.zero.coverage b/tests/coverage/for.zero.coverage new file mode 100644 index 0000000000000..9376a371275d4 --- /dev/null +++ b/tests/coverage/for.zero.coverage @@ -0,0 +1,39 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: zero one many + LL| |//@[one] ignore-coverage-map + LL| |//@[many] ignore-coverage-map + LL| | + LL| |// Basic test of `for` loops. + LL| | + LL| 1|fn for_loop(items: &[&str]) { + LL| 1| say("hello"); + LL| | + LL| 1| for item in items { + ^0 + LL| 0| say(item); + LL| 0| } + LL| | + LL| 1| for item in items { + ^0 + LL| 0| say(item) + LL| | } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let items = cfg_select!( + LL| | zero => &[], + LL| | one => &["one"], + LL| | many => &["one", "two", "three"], + LL| | ); + LL| | for_loop(items); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-let-chain.none.cov-map b/tests/coverage/if-let-chain.none.cov-map new file mode 100644 index 0000000000000..9626b6cc8553b --- /dev/null +++ b/tests/coverage/if-let-chain.none.cov-map @@ -0,0 +1,40 @@ +Function name: if_let_chain::if_let_chain +Raw bytes (105): 0x[01, 01, 08, 09, 05, 0b, 09, 01, 05, 11, 0d, 11, 0d, 11, 0d, 1f, 11, 01, 0d, 11, 01, 09, 01, 00, 33, 09, 01, 11, 00, 18, 01, 00, 1c, 00, 27, 02, 01, 15, 00, 18, 09, 00, 1c, 00, 23, 02, 01, 05, 02, 06, 06, 02, 05, 00, 06, 11, 02, 11, 00, 18, 01, 00, 1c, 00, 27, 16, 01, 15, 00, 18, 11, 00, 1c, 00, 23, 16, 02, 09, 00, 0c, 16, 00, 0d, 00, 10, 1a, 01, 05, 00, 06, 01, 02, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/if-let-chain.rs +Number of expressions: 8 +- expression 0 operands: lhs = Counter(2), rhs = Counter(1) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(4), rhs = Counter(3) +- expression 4 operands: lhs = Counter(4), rhs = Counter(3) +- expression 5 operands: lhs = Counter(4), rhs = Counter(3) +- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4) +- expression 7 operands: lhs = Counter(0), rhs = Counter(3) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 51) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 28) to (start + 0, 39) +- Code(Expression(0, Sub)) at (prev + 1, 21) to (start + 0, 24) + = (c2 - c1) +- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 35) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 2, 6) + = (c2 - c1) +- Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) + = ((c0 + c1) - c2) +- Code(Counter(4)) at (prev + 2, 17) to (start + 0, 24) +- Code(Counter(0)) at (prev + 0, 28) to (start + 0, 39) +- Code(Expression(5, Sub)) at (prev + 1, 21) to (start + 0, 24) + = (c4 - c3) +- Code(Counter(4)) at (prev + 0, 28) to (start + 0, 35) +- Code(Expression(5, Sub)) at (prev + 2, 9) to (start + 0, 12) + = (c4 - c3) +- Code(Expression(5, Sub)) at (prev + 0, 13) to (start + 0, 16) + = (c4 - c3) +- Code(Expression(6, Sub)) at (prev + 1, 5) to (start + 0, 6) + = ((c0 + c3) - c4) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 + diff --git a/tests/coverage/if-let-chain.none.coverage b/tests/coverage/if-let-chain.none.coverage new file mode 100644 index 0000000000000..a5aba75201ead --- /dev/null +++ b/tests/coverage/if-let-chain.none.coverage @@ -0,0 +1,41 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: none one two + LL| |//@[one] ignore-coverage-map + LL| |//@[two] ignore-coverage-map + LL| | + LL| |// Basic test for if-let chains. + LL| | + LL| 1|fn if_let_chain(opt_opt_msg: Option>) { + LL| 1| if let Some(opt_msg) = opt_opt_msg + ^0 + LL| 0| && let Some(msg) = opt_msg + LL| 0| { + LL| 0| say(msg); + LL| 1| } + LL| | + LL| 1| if let Some(opt_msg) = opt_opt_msg + ^0 + LL| 0| && let Some(msg) = opt_msg + LL| | { + LL| 0| say(msg) + LL| 1| } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt_opt_msg = cfg_select!( + LL| | none => None, + LL| | one => Some(None), + LL| | two => Some(Some("hello")), + LL| | ); + LL| | if_let_chain(opt_opt_msg); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-let-chain.one.coverage b/tests/coverage/if-let-chain.one.coverage new file mode 100644 index 0000000000000..b4789e8593af6 --- /dev/null +++ b/tests/coverage/if-let-chain.one.coverage @@ -0,0 +1,41 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: none one two + LL| |//@[one] ignore-coverage-map + LL| |//@[two] ignore-coverage-map + LL| | + LL| |// Basic test for if-let chains. + LL| | + LL| 1|fn if_let_chain(opt_opt_msg: Option>) { + LL| 1| if let Some(opt_msg) = opt_opt_msg + LL| 1| && let Some(msg) = opt_msg + ^0 + LL| 0| { + LL| 0| say(msg); + LL| 1| } + LL| | + LL| 1| if let Some(opt_msg) = opt_opt_msg + LL| 1| && let Some(msg) = opt_msg + ^0 + LL| | { + LL| 0| say(msg) + LL| 1| } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt_opt_msg = cfg_select!( + LL| | none => None, + LL| | one => Some(None), + LL| | two => Some(Some("hello")), + LL| | ); + LL| | if_let_chain(opt_opt_msg); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-let-chain.rs b/tests/coverage/if-let-chain.rs new file mode 100644 index 0000000000000..816a22015a4c7 --- /dev/null +++ b/tests/coverage/if-let-chain.rs @@ -0,0 +1,38 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: none one two +//@[one] ignore-coverage-map +//@[two] ignore-coverage-map + +// Basic test for if-let chains. + +fn if_let_chain(opt_opt_msg: Option>) { + if let Some(opt_msg) = opt_opt_msg + && let Some(msg) = opt_msg + { + say(msg); + } + + if let Some(opt_msg) = opt_opt_msg + && let Some(msg) = opt_msg + { + say(msg) + } + + say("goodbye"); +} + +#[coverage(off)] +fn main() { + let opt_opt_msg = cfg_select!( + none => None, + one => Some(None), + two => Some(Some("hello")), + ); + if_let_chain(opt_opt_msg); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/if-let-chain.two.coverage b/tests/coverage/if-let-chain.two.coverage new file mode 100644 index 0000000000000..491a704da1289 --- /dev/null +++ b/tests/coverage/if-let-chain.two.coverage @@ -0,0 +1,40 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: none one two + LL| |//@[one] ignore-coverage-map + LL| |//@[two] ignore-coverage-map + LL| | + LL| |// Basic test for if-let chains. + LL| | + LL| 1|fn if_let_chain(opt_opt_msg: Option>) { + LL| 1| if let Some(opt_msg) = opt_opt_msg + LL| 1| && let Some(msg) = opt_msg + LL| 1| { + LL| 1| say(msg); + LL| 1| } + ^0 + LL| | + LL| 1| if let Some(opt_msg) = opt_opt_msg + LL| 1| && let Some(msg) = opt_msg + LL| | { + LL| 1| say(msg) + LL| 0| } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt_opt_msg = cfg_select!( + LL| | none => None, + LL| | one => Some(None), + LL| | two => Some(Some("hello")), + LL| | ); + LL| | if_let_chain(opt_opt_msg); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-tail-expr.no.cov-map b/tests/coverage/if-tail-expr.no.cov-map new file mode 100644 index 0000000000000..3849ec62daae8 --- /dev/null +++ b/tests/coverage/if-tail-expr.no.cov-map @@ -0,0 +1,45 @@ +Function name: if_tail_expr::if_true +Raw bytes (135): 0x[01, 01, 08, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 1f, 0d, 11, 01, 1f, 0d, 11, 17, 01, 09, 01, 00, 24, 01, 01, 05, 00, 08, 01, 00, 09, 00, 10, 01, 02, 08, 00, 0c, 05, 01, 09, 00, 0c, 05, 00, 0d, 00, 13, 02, 01, 05, 00, 06, 01, 02, 08, 00, 0c, 09, 01, 09, 00, 0c, 09, 00, 0d, 00, 13, 0a, 02, 09, 00, 0c, 0a, 00, 0d, 00, 14, 01, 03, 08, 00, 0c, 0d, 01, 09, 00, 0c, 0d, 00, 0d, 00, 13, 0e, 01, 0f, 00, 14, 11, 01, 09, 00, 0c, 11, 00, 0d, 00, 14, 1a, 02, 09, 00, 0c, 1a, 00, 0d, 00, 16, 01, 03, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/if-tail-expr.rs +Number of expressions: 8 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(2) +- expression 3 operands: lhs = Counter(0), rhs = Counter(3) +- expression 4 operands: lhs = Counter(0), rhs = Expression(7, Add) +- expression 5 operands: lhs = Counter(3), rhs = Counter(4) +- expression 6 operands: lhs = Counter(0), rhs = Expression(7, Add) +- expression 7 operands: lhs = Counter(3), rhs = Counter(4) +Number of file 0 mappings: 23 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 19) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) + = (c0 - c1) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(2)) at (prev + 0, 13) to (start + 0, 19) +- Code(Expression(2, Sub)) at (prev + 2, 9) to (start + 0, 12) + = (c0 - c2) +- Code(Expression(2, Sub)) at (prev + 0, 13) to (start + 0, 20) + = (c0 - c2) +- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 12) +- Code(Counter(3)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(3)) at (prev + 0, 13) to (start + 0, 19) +- Code(Expression(3, Sub)) at (prev + 1, 15) to (start + 0, 20) + = (c0 - c3) +- Code(Counter(4)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(4)) at (prev + 0, 13) to (start + 0, 20) +- Code(Expression(6, Sub)) at (prev + 2, 9) to (start + 0, 12) + = (c0 - (c3 + c4)) +- Code(Expression(6, Sub)) at (prev + 0, 13) to (start + 0, 22) + = (c0 - (c3 + c4)) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 + diff --git a/tests/coverage/if-tail-expr.no.coverage b/tests/coverage/if-tail-expr.no.coverage new file mode 100644 index 0000000000000..a33a58a6c30e6 --- /dev/null +++ b/tests/coverage/if-tail-expr.no.coverage @@ -0,0 +1,46 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: no yes + LL| |//@[yes] ignore-coverage-map + LL| | + LL| |// A variety of simple `if` expressions, in which the then/else blocks end with + LL| |// an expression. Contrast with `if-tail-stmt.rs`. + LL| | + LL| 1|fn if_true(cond: bool, other: bool) { + LL| 1| say("hello"); + LL| | + LL| 1| if cond { + LL| 0| say("true") + LL| 1| } + LL| | + LL| 1| if cond { + LL| 0| say("true") + LL| | } else { + LL| 1| say("false") + LL| | } + LL| | + LL| 1| if cond { + LL| 0| say("cond") + LL| 1| } else if other { + LL| 1| say("other") + LL| | } else { + LL| 0| say("neither") + LL| | } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let cond = cfg_select!( + LL| | no => false, + LL| | yes => true, + LL| | ); + LL| | if_true(cond, !cond); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-tail-expr.rs b/tests/coverage/if-tail-expr.rs new file mode 100644 index 0000000000000..778a9ecc8380c --- /dev/null +++ b/tests/coverage/if-tail-expr.rs @@ -0,0 +1,45 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: no yes +//@[yes] ignore-coverage-map + +// A variety of simple `if` expressions, in which the then/else blocks end with +// an expression. Contrast with `if-tail-stmt.rs`. + +fn if_true(cond: bool, other: bool) { + say("hello"); + + if cond { + say("true") + } + + if cond { + say("true") + } else { + say("false") + } + + if cond { + say("cond") + } else if other { + say("other") + } else { + say("neither") + } + + say("goodbye"); +} + +#[coverage(off)] +fn main() { + let cond = cfg_select!( + no => false, + yes => true, + ); + if_true(cond, !cond); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/if-tail-expr.yes.coverage b/tests/coverage/if-tail-expr.yes.coverage new file mode 100644 index 0000000000000..111efccf59b15 --- /dev/null +++ b/tests/coverage/if-tail-expr.yes.coverage @@ -0,0 +1,46 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: no yes + LL| |//@[yes] ignore-coverage-map + LL| | + LL| |// A variety of simple `if` expressions, in which the then/else blocks end with + LL| |// an expression. Contrast with `if-tail-stmt.rs`. + LL| | + LL| 1|fn if_true(cond: bool, other: bool) { + LL| 1| say("hello"); + LL| | + LL| 1| if cond { + LL| 1| say("true") + LL| 0| } + LL| | + LL| 1| if cond { + LL| 1| say("true") + LL| | } else { + LL| 0| say("false") + LL| | } + LL| | + LL| 1| if cond { + LL| 1| say("cond") + LL| 0| } else if other { + LL| 0| say("other") + LL| | } else { + LL| 0| say("neither") + LL| | } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let cond = cfg_select!( + LL| | no => false, + LL| | yes => true, + LL| | ); + LL| | if_true(cond, !cond); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-tail-stmt.no.cov-map b/tests/coverage/if-tail-stmt.no.cov-map new file mode 100644 index 0000000000000..e5721e2dc4a74 --- /dev/null +++ b/tests/coverage/if-tail-stmt.no.cov-map @@ -0,0 +1,34 @@ +Function name: if_tail_stmt::if_true +Raw bytes (99): 0x[01, 01, 05, 01, 05, 01, 09, 01, 0d, 01, 13, 0d, 11, 11, 01, 09, 01, 00, 24, 01, 01, 05, 00, 08, 01, 00, 09, 00, 10, 01, 02, 08, 00, 0c, 05, 00, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 02, 08, 00, 0c, 09, 00, 0d, 02, 06, 06, 02, 0c, 02, 06, 01, 04, 08, 00, 0c, 0d, 00, 0d, 02, 06, 0a, 02, 0f, 00, 14, 11, 00, 15, 02, 06, 0e, 02, 0c, 02, 06, 01, 04, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/if-tail-stmt.rs +Number of expressions: 5 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(0), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(3) +- expression 3 operands: lhs = Counter(0), rhs = Expression(4, Add) +- expression 4 operands: lhs = Counter(3), rhs = Counter(4) +Number of file 0 mappings: 17 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) + = (c0 - c1) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 12) +- Code(Counter(2)) at (prev + 0, 13) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6) + = (c0 - c2) +- Code(Counter(0)) at (prev + 4, 8) to (start + 0, 12) +- Code(Counter(3)) at (prev + 0, 13) to (start + 2, 6) +- Code(Expression(2, Sub)) at (prev + 2, 15) to (start + 0, 20) + = (c0 - c3) +- Code(Counter(4)) at (prev + 0, 21) to (start + 2, 6) +- Code(Expression(3, Sub)) at (prev + 2, 12) to (start + 2, 6) + = (c0 - (c3 + c4)) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 + diff --git a/tests/coverage/if-tail-stmt.no.coverage b/tests/coverage/if-tail-stmt.no.coverage new file mode 100644 index 0000000000000..ca311f21ff229 --- /dev/null +++ b/tests/coverage/if-tail-stmt.no.coverage @@ -0,0 +1,46 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: no yes + LL| |//@[yes] ignore-coverage-map + LL| | + LL| |// A variety of simple `if` expressions, in which the then/else blocks end with + LL| |// a semicolon. Contrast with `if-tail-expr.rs`. + LL| | + LL| 1|fn if_true(cond: bool, other: bool) { + LL| 1| say("hello"); + LL| | + LL| 1| if cond { + LL| 0| say("true"); + LL| 1| } + LL| | + LL| 1| if cond { + LL| 0| say("true"); + LL| 1| } else { + LL| 1| say("false"); + LL| 1| } + LL| | + LL| 1| if cond { + LL| 0| say("cond"); + LL| 1| } else if other { + LL| 1| say("other"); + LL| 1| } else { + LL| 0| say("neither"); + LL| 0| } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let cond = cfg_select!( + LL| | no => false, + LL| | yes => true, + LL| | ); + LL| | if_true(cond, !cond); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/if-tail-stmt.rs b/tests/coverage/if-tail-stmt.rs new file mode 100644 index 0000000000000..f350c4eba90b0 --- /dev/null +++ b/tests/coverage/if-tail-stmt.rs @@ -0,0 +1,45 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: no yes +//@[yes] ignore-coverage-map + +// A variety of simple `if` expressions, in which the then/else blocks end with +// a semicolon. Contrast with `if-tail-expr.rs`. + +fn if_true(cond: bool, other: bool) { + say("hello"); + + if cond { + say("true"); + } + + if cond { + say("true"); + } else { + say("false"); + } + + if cond { + say("cond"); + } else if other { + say("other"); + } else { + say("neither"); + } + + say("goodbye"); +} + +#[coverage(off)] +fn main() { + let cond = cfg_select!( + no => false, + yes => true, + ); + if_true(cond, !cond); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/if-tail-stmt.yes.coverage b/tests/coverage/if-tail-stmt.yes.coverage new file mode 100644 index 0000000000000..b4fa1884315e6 --- /dev/null +++ b/tests/coverage/if-tail-stmt.yes.coverage @@ -0,0 +1,48 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: no yes + LL| |//@[yes] ignore-coverage-map + LL| | + LL| |// A variety of simple `if` expressions, in which the then/else blocks end with + LL| |// a semicolon. Contrast with `if-tail-expr.rs`. + LL| | + LL| 1|fn if_true(cond: bool, other: bool) { + LL| 1| say("hello"); + LL| | + LL| 1| if cond { + LL| 1| say("true"); + LL| 1| } + ^0 + LL| | + LL| 1| if cond { + LL| 1| say("true"); + LL| 1| } else { + LL| 0| say("false"); + LL| 0| } + LL| | + LL| 1| if cond { + LL| 1| say("cond"); + LL| 1| } else if other { + ^0 + LL| 0| say("other"); + LL| 0| } else { + LL| 0| say("neither"); + LL| 0| } + LL| | + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let cond = cfg_select!( + LL| | no => false, + LL| | yes => true, + LL| | ); + LL| | if_true(cond, !cond); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/iffy/README.md b/tests/coverage/iffy/README.md new file mode 100644 index 0000000000000..0d8a866ed2685 --- /dev/null +++ b/tests/coverage/iffy/README.md @@ -0,0 +1,4 @@ +# `tests/coverage/iffy` + +Older tests that are of limited value for investigating specific problems, +but still have some worth in detecting regressions by adding variety to the test corpus. diff --git a/tests/coverage/abort.cov-map b/tests/coverage/iffy/abort.cov-map similarity index 100% rename from tests/coverage/abort.cov-map rename to tests/coverage/iffy/abort.cov-map diff --git a/tests/coverage/abort.coverage b/tests/coverage/iffy/abort.coverage similarity index 100% rename from tests/coverage/abort.coverage rename to tests/coverage/iffy/abort.coverage diff --git a/tests/coverage/abort.rs b/tests/coverage/iffy/abort.rs similarity index 100% rename from tests/coverage/abort.rs rename to tests/coverage/iffy/abort.rs diff --git a/tests/coverage/iffy/assert.cov-map b/tests/coverage/iffy/assert.cov-map new file mode 100644 index 0000000000000..543ab89628281 --- /dev/null +++ b/tests/coverage/iffy/assert.cov-map @@ -0,0 +1,42 @@ +Function name: assert::main +Raw bytes (76): 0x[01, 01, 06, 05, 01, 05, 17, 01, 09, 05, 13, 17, 0d, 01, 09, 0c, 01, 09, 01, 00, 1c, 01, 01, 09, 00, 16, 01, 00, 19, 00, 1b, 05, 01, 0b, 00, 18, 02, 01, 0c, 00, 1a, 09, 00, 1b, 02, 0a, 06, 02, 13, 00, 20, 0d, 00, 21, 02, 0a, 0e, 02, 09, 00, 0a, 02, 01, 09, 00, 17, 01, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/assert.rs +Number of expressions: 6 +- expression 0 operands: lhs = Counter(1), rhs = Counter(0) +- expression 1 operands: lhs = Counter(1), rhs = Expression(5, Add) +- expression 2 operands: lhs = Counter(0), rhs = Counter(2) +- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add) +- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(0), rhs = Counter(2) +Number of file 0 mappings: 12 +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 28) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 0, 25) to (start + 0, 27) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 24) +- Code(Expression(0, Sub)) at (prev + 1, 12) to (start + 0, 26) + = (c1 - c0) +- Code(Counter(2)) at (prev + 0, 27) to (start + 2, 10) +- Code(Expression(1, Sub)) at (prev + 2, 19) to (start + 0, 32) + = (c1 - (c0 + c2)) +- Code(Counter(3)) at (prev + 0, 33) to (start + 2, 10) +- Code(Expression(3, Sub)) at (prev + 2, 9) to (start + 0, 10) + = (c1 - ((c0 + c2) + c3)) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 23) + = (c1 - c0) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 11) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c3 + +Function name: assert::might_fail_assert +Raw bytes (24): 0x[01, 01, 00, 04, 01, 04, 01, 00, 28, 01, 01, 05, 00, 0d, 01, 01, 05, 00, 0f, 05, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/assert.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 40) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 + diff --git a/tests/coverage/iffy/assert.coverage b/tests/coverage/iffy/assert.coverage new file mode 100644 index 0000000000000..29a5b48c0566a --- /dev/null +++ b/tests/coverage/iffy/assert.coverage @@ -0,0 +1,33 @@ + LL| |#![allow(unused_assignments)] + LL| |//@ failure-status: 101 + LL| | + LL| 4|fn might_fail_assert(one_plus_one: u32) { + LL| 4| println!("does 1 + 1 = {}?", one_plus_one); + LL| 4| assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); + LL| 3|} + LL| | + LL| 1|fn main() -> Result<(), u8> { + LL| 1| let mut countdown = 10; + LL| 10| while countdown > 0 { + LL| 9| if countdown == 1 { + LL| 1| might_fail_assert(3); + LL| 8| } else if countdown < 5 { + LL| 3| might_fail_assert(2); + LL| 5| } + LL| 9| countdown -= 1; + LL| | } + LL| 1| Ok(()) + LL| 1|} + LL| | + LL| |// Notes: + LL| |// 1. Compare this program and its coverage results to those of the very similar test + LL| |// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. + LL| |// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or + LL| |// related `assert_*!()` macro. + LL| |// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce + LL| |// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to + LL| |// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). + LL| |// 4. `TerminatorKind::Assert` is, however, also present in the MIR generated for this test + LL| |// (and in many other coverage tests). The `Assert` terminator is typically generated by the + LL| |// Rust compiler to check for runtime failures, such as numeric overflows. + diff --git a/tests/coverage/iffy/assert.rs b/tests/coverage/iffy/assert.rs new file mode 100644 index 0000000000000..30d511f8f7a89 --- /dev/null +++ b/tests/coverage/iffy/assert.rs @@ -0,0 +1,32 @@ +#![allow(unused_assignments)] +//@ failure-status: 101 + +fn might_fail_assert(one_plus_one: u32) { + println!("does 1 + 1 = {}?", one_plus_one); + assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); +} + +fn main() -> Result<(), u8> { + let mut countdown = 10; + while countdown > 0 { + if countdown == 1 { + might_fail_assert(3); + } else if countdown < 5 { + might_fail_assert(2); + } + countdown -= 1; + } + Ok(()) +} + +// Notes: +// 1. Compare this program and its coverage results to those of the very similar test +// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. +// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or +// related `assert_*!()` macro. +// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce +// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to +// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). +// 4. `TerminatorKind::Assert` is, however, also present in the MIR generated for this test +// (and in many other coverage tests). The `Assert` terminator is typically generated by the +// Rust compiler to check for runtime failures, such as numeric overflows. diff --git a/tests/coverage/auxiliary/inline_always_with_dead_code.rs b/tests/coverage/iffy/auxiliary/inline_always_with_dead_code.rs similarity index 100% rename from tests/coverage/auxiliary/inline_always_with_dead_code.rs rename to tests/coverage/iffy/auxiliary/inline_always_with_dead_code.rs diff --git a/tests/coverage/auxiliary/used_crate.rs b/tests/coverage/iffy/auxiliary/used_crate.rs similarity index 100% rename from tests/coverage/auxiliary/used_crate.rs rename to tests/coverage/iffy/auxiliary/used_crate.rs diff --git a/tests/coverage/auxiliary/used_inline_crate.rs b/tests/coverage/iffy/auxiliary/used_inline_crate.rs similarity index 100% rename from tests/coverage/auxiliary/used_inline_crate.rs rename to tests/coverage/iffy/auxiliary/used_inline_crate.rs diff --git a/tests/coverage/closure.cov-map b/tests/coverage/iffy/closure.cov-map similarity index 100% rename from tests/coverage/closure.cov-map rename to tests/coverage/iffy/closure.cov-map diff --git a/tests/coverage/closure.coverage b/tests/coverage/iffy/closure.coverage similarity index 100% rename from tests/coverage/closure.coverage rename to tests/coverage/iffy/closure.coverage diff --git a/tests/coverage/closure.rs b/tests/coverage/iffy/closure.rs similarity index 100% rename from tests/coverage/closure.rs rename to tests/coverage/iffy/closure.rs diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/iffy/closure_macro.cov-map similarity index 100% rename from tests/coverage/closure_macro.cov-map rename to tests/coverage/iffy/closure_macro.cov-map diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/iffy/closure_macro.coverage similarity index 100% rename from tests/coverage/closure_macro.coverage rename to tests/coverage/iffy/closure_macro.coverage diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/iffy/closure_macro.rs similarity index 100% rename from tests/coverage/closure_macro.rs rename to tests/coverage/iffy/closure_macro.rs diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/iffy/conditions.cov-map similarity index 100% rename from tests/coverage/conditions.cov-map rename to tests/coverage/iffy/conditions.cov-map diff --git a/tests/coverage/conditions.coverage b/tests/coverage/iffy/conditions.coverage similarity index 100% rename from tests/coverage/conditions.coverage rename to tests/coverage/iffy/conditions.coverage diff --git a/tests/coverage/conditions.rs b/tests/coverage/iffy/conditions.rs similarity index 100% rename from tests/coverage/conditions.rs rename to tests/coverage/iffy/conditions.rs diff --git a/tests/coverage/continue.cov-map b/tests/coverage/iffy/continue.cov-map similarity index 100% rename from tests/coverage/continue.cov-map rename to tests/coverage/iffy/continue.cov-map diff --git a/tests/coverage/continue.coverage b/tests/coverage/iffy/continue.coverage similarity index 100% rename from tests/coverage/continue.coverage rename to tests/coverage/iffy/continue.coverage diff --git a/tests/coverage/continue.rs b/tests/coverage/iffy/continue.rs similarity index 100% rename from tests/coverage/continue.rs rename to tests/coverage/iffy/continue.rs diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/iffy/coroutine.cov-map similarity index 100% rename from tests/coverage/coroutine.cov-map rename to tests/coverage/iffy/coroutine.cov-map diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/iffy/coroutine.coverage similarity index 100% rename from tests/coverage/coroutine.coverage rename to tests/coverage/iffy/coroutine.coverage diff --git a/tests/coverage/coroutine.rs b/tests/coverage/iffy/coroutine.rs similarity index 100% rename from tests/coverage/coroutine.rs rename to tests/coverage/iffy/coroutine.rs diff --git a/tests/coverage/drop_trait.cov-map b/tests/coverage/iffy/drop_trait.cov-map similarity index 100% rename from tests/coverage/drop_trait.cov-map rename to tests/coverage/iffy/drop_trait.cov-map diff --git a/tests/coverage/drop_trait.coverage b/tests/coverage/iffy/drop_trait.coverage similarity index 100% rename from tests/coverage/drop_trait.coverage rename to tests/coverage/iffy/drop_trait.coverage diff --git a/tests/coverage/drop_trait.rs b/tests/coverage/iffy/drop_trait.rs similarity index 100% rename from tests/coverage/drop_trait.rs rename to tests/coverage/iffy/drop_trait.rs diff --git a/tests/coverage/generics.cov-map b/tests/coverage/iffy/generics.cov-map similarity index 100% rename from tests/coverage/generics.cov-map rename to tests/coverage/iffy/generics.cov-map diff --git a/tests/coverage/generics.coverage b/tests/coverage/iffy/generics.coverage similarity index 100% rename from tests/coverage/generics.coverage rename to tests/coverage/iffy/generics.coverage diff --git a/tests/coverage/generics.rs b/tests/coverage/iffy/generics.rs similarity index 100% rename from tests/coverage/generics.rs rename to tests/coverage/iffy/generics.rs diff --git a/tests/coverage/if.cov-map b/tests/coverage/iffy/if.cov-map similarity index 100% rename from tests/coverage/if.cov-map rename to tests/coverage/iffy/if.cov-map diff --git a/tests/coverage/if.coverage b/tests/coverage/iffy/if.coverage similarity index 100% rename from tests/coverage/if.coverage rename to tests/coverage/iffy/if.coverage diff --git a/tests/coverage/if.rs b/tests/coverage/iffy/if.rs similarity index 100% rename from tests/coverage/if.rs rename to tests/coverage/iffy/if.rs diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/iffy/if_else.cov-map similarity index 100% rename from tests/coverage/if_else.cov-map rename to tests/coverage/iffy/if_else.cov-map diff --git a/tests/coverage/if_else.coverage b/tests/coverage/iffy/if_else.coverage similarity index 100% rename from tests/coverage/if_else.coverage rename to tests/coverage/iffy/if_else.coverage diff --git a/tests/coverage/if_else.rs b/tests/coverage/iffy/if_else.rs similarity index 100% rename from tests/coverage/if_else.rs rename to tests/coverage/iffy/if_else.rs diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/iffy/inline-dead.cov-map similarity index 100% rename from tests/coverage/inline-dead.cov-map rename to tests/coverage/iffy/inline-dead.cov-map diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/iffy/inline-dead.coverage similarity index 100% rename from tests/coverage/inline-dead.coverage rename to tests/coverage/iffy/inline-dead.coverage diff --git a/tests/coverage/inline-dead.rs b/tests/coverage/iffy/inline-dead.rs similarity index 100% rename from tests/coverage/inline-dead.rs rename to tests/coverage/iffy/inline-dead.rs diff --git a/tests/coverage/inline.cov-map b/tests/coverage/iffy/inline.cov-map similarity index 100% rename from tests/coverage/inline.cov-map rename to tests/coverage/iffy/inline.cov-map diff --git a/tests/coverage/inline.coverage b/tests/coverage/iffy/inline.coverage similarity index 100% rename from tests/coverage/inline.coverage rename to tests/coverage/iffy/inline.coverage diff --git a/tests/coverage/inline.rs b/tests/coverage/iffy/inline.rs similarity index 100% rename from tests/coverage/inline.rs rename to tests/coverage/iffy/inline.rs diff --git a/tests/coverage/inner_items.cov-map b/tests/coverage/iffy/inner_items.cov-map similarity index 100% rename from tests/coverage/inner_items.cov-map rename to tests/coverage/iffy/inner_items.cov-map diff --git a/tests/coverage/inner_items.coverage b/tests/coverage/iffy/inner_items.coverage similarity index 100% rename from tests/coverage/inner_items.coverage rename to tests/coverage/iffy/inner_items.coverage diff --git a/tests/coverage/inner_items.rs b/tests/coverage/iffy/inner_items.rs similarity index 100% rename from tests/coverage/inner_items.rs rename to tests/coverage/iffy/inner_items.rs diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/iffy/issue-83601.cov-map similarity index 100% rename from tests/coverage/issue-83601.cov-map rename to tests/coverage/iffy/issue-83601.cov-map diff --git a/tests/coverage/issue-83601.coverage b/tests/coverage/iffy/issue-83601.coverage similarity index 100% rename from tests/coverage/issue-83601.coverage rename to tests/coverage/iffy/issue-83601.coverage diff --git a/tests/coverage/issue-83601.rs b/tests/coverage/iffy/issue-83601.rs similarity index 100% rename from tests/coverage/issue-83601.rs rename to tests/coverage/iffy/issue-83601.rs diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/iffy/issue-84561.cov-map similarity index 100% rename from tests/coverage/issue-84561.cov-map rename to tests/coverage/iffy/issue-84561.cov-map diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/iffy/issue-84561.coverage similarity index 100% rename from tests/coverage/issue-84561.coverage rename to tests/coverage/iffy/issue-84561.coverage diff --git a/tests/coverage/issue-84561.rs b/tests/coverage/iffy/issue-84561.rs similarity index 100% rename from tests/coverage/issue-84561.rs rename to tests/coverage/iffy/issue-84561.rs diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/iffy/issue-85461.cov-map similarity index 100% rename from tests/coverage/issue-85461.cov-map rename to tests/coverage/iffy/issue-85461.cov-map diff --git a/tests/coverage/issue-85461.coverage b/tests/coverage/iffy/issue-85461.coverage similarity index 100% rename from tests/coverage/issue-85461.coverage rename to tests/coverage/iffy/issue-85461.coverage diff --git a/tests/coverage/issue-85461.rs b/tests/coverage/iffy/issue-85461.rs similarity index 100% rename from tests/coverage/issue-85461.rs rename to tests/coverage/iffy/issue-85461.rs diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/iffy/issue-93054.cov-map similarity index 100% rename from tests/coverage/issue-93054.cov-map rename to tests/coverage/iffy/issue-93054.cov-map diff --git a/tests/coverage/issue-93054.coverage b/tests/coverage/iffy/issue-93054.coverage similarity index 100% rename from tests/coverage/issue-93054.coverage rename to tests/coverage/iffy/issue-93054.coverage diff --git a/tests/coverage/issue-93054.rs b/tests/coverage/iffy/issue-93054.rs similarity index 100% rename from tests/coverage/issue-93054.rs rename to tests/coverage/iffy/issue-93054.rs diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/iffy/lazy_boolean.cov-map similarity index 100% rename from tests/coverage/lazy_boolean.cov-map rename to tests/coverage/iffy/lazy_boolean.cov-map diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/iffy/lazy_boolean.coverage similarity index 100% rename from tests/coverage/lazy_boolean.coverage rename to tests/coverage/iffy/lazy_boolean.coverage diff --git a/tests/coverage/lazy_boolean.rs b/tests/coverage/iffy/lazy_boolean.rs similarity index 100% rename from tests/coverage/lazy_boolean.rs rename to tests/coverage/iffy/lazy_boolean.rs diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/iffy/loops_branches.cov-map similarity index 100% rename from tests/coverage/loops_branches.cov-map rename to tests/coverage/iffy/loops_branches.cov-map diff --git a/tests/coverage/loops_branches.coverage b/tests/coverage/iffy/loops_branches.coverage similarity index 100% rename from tests/coverage/loops_branches.coverage rename to tests/coverage/iffy/loops_branches.coverage diff --git a/tests/coverage/loops_branches.rs b/tests/coverage/iffy/loops_branches.rs similarity index 100% rename from tests/coverage/loops_branches.rs rename to tests/coverage/iffy/loops_branches.rs diff --git a/tests/coverage/match_or_pattern.cov-map b/tests/coverage/iffy/match_or_pattern.cov-map similarity index 100% rename from tests/coverage/match_or_pattern.cov-map rename to tests/coverage/iffy/match_or_pattern.cov-map diff --git a/tests/coverage/match_or_pattern.coverage b/tests/coverage/iffy/match_or_pattern.coverage similarity index 100% rename from tests/coverage/match_or_pattern.coverage rename to tests/coverage/iffy/match_or_pattern.coverage diff --git a/tests/coverage/match_or_pattern.rs b/tests/coverage/iffy/match_or_pattern.rs similarity index 100% rename from tests/coverage/match_or_pattern.rs rename to tests/coverage/iffy/match_or_pattern.rs diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/iffy/nested_loops.cov-map similarity index 100% rename from tests/coverage/nested_loops.cov-map rename to tests/coverage/iffy/nested_loops.cov-map diff --git a/tests/coverage/nested_loops.coverage b/tests/coverage/iffy/nested_loops.coverage similarity index 100% rename from tests/coverage/nested_loops.coverage rename to tests/coverage/iffy/nested_loops.coverage diff --git a/tests/coverage/nested_loops.rs b/tests/coverage/iffy/nested_loops.rs similarity index 100% rename from tests/coverage/nested_loops.rs rename to tests/coverage/iffy/nested_loops.rs diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/iffy/no_cov_crate.cov-map similarity index 100% rename from tests/coverage/no_cov_crate.cov-map rename to tests/coverage/iffy/no_cov_crate.cov-map diff --git a/tests/coverage/no_cov_crate.coverage b/tests/coverage/iffy/no_cov_crate.coverage similarity index 100% rename from tests/coverage/no_cov_crate.coverage rename to tests/coverage/iffy/no_cov_crate.coverage diff --git a/tests/coverage/no_cov_crate.rs b/tests/coverage/iffy/no_cov_crate.rs similarity index 100% rename from tests/coverage/no_cov_crate.rs rename to tests/coverage/iffy/no_cov_crate.rs diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/iffy/overflow.cov-map similarity index 100% rename from tests/coverage/overflow.cov-map rename to tests/coverage/iffy/overflow.cov-map diff --git a/tests/coverage/overflow.coverage b/tests/coverage/iffy/overflow.coverage similarity index 100% rename from tests/coverage/overflow.coverage rename to tests/coverage/iffy/overflow.coverage diff --git a/tests/coverage/overflow.rs b/tests/coverage/iffy/overflow.rs similarity index 100% rename from tests/coverage/overflow.rs rename to tests/coverage/iffy/overflow.rs diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/iffy/panic_unwind.cov-map similarity index 100% rename from tests/coverage/panic_unwind.cov-map rename to tests/coverage/iffy/panic_unwind.cov-map diff --git a/tests/coverage/panic_unwind.coverage b/tests/coverage/iffy/panic_unwind.coverage similarity index 100% rename from tests/coverage/panic_unwind.coverage rename to tests/coverage/iffy/panic_unwind.coverage diff --git a/tests/coverage/panic_unwind.rs b/tests/coverage/iffy/panic_unwind.rs similarity index 100% rename from tests/coverage/panic_unwind.rs rename to tests/coverage/iffy/panic_unwind.rs diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/iffy/partial_eq.cov-map similarity index 100% rename from tests/coverage/partial_eq.cov-map rename to tests/coverage/iffy/partial_eq.cov-map diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/iffy/partial_eq.coverage similarity index 100% rename from tests/coverage/partial_eq.coverage rename to tests/coverage/iffy/partial_eq.coverage diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/iffy/partial_eq.rs similarity index 100% rename from tests/coverage/partial_eq.rs rename to tests/coverage/iffy/partial_eq.rs diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/iffy/simple_loop.cov-map similarity index 100% rename from tests/coverage/simple_loop.cov-map rename to tests/coverage/iffy/simple_loop.cov-map diff --git a/tests/coverage/simple_loop.coverage b/tests/coverage/iffy/simple_loop.coverage similarity index 100% rename from tests/coverage/simple_loop.coverage rename to tests/coverage/iffy/simple_loop.coverage diff --git a/tests/coverage/simple_loop.rs b/tests/coverage/iffy/simple_loop.rs similarity index 100% rename from tests/coverage/simple_loop.rs rename to tests/coverage/iffy/simple_loop.rs diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/iffy/simple_match.cov-map similarity index 100% rename from tests/coverage/simple_match.cov-map rename to tests/coverage/iffy/simple_match.cov-map diff --git a/tests/coverage/simple_match.coverage b/tests/coverage/iffy/simple_match.coverage similarity index 100% rename from tests/coverage/simple_match.coverage rename to tests/coverage/iffy/simple_match.coverage diff --git a/tests/coverage/simple_match.rs b/tests/coverage/iffy/simple_match.rs similarity index 100% rename from tests/coverage/simple_match.rs rename to tests/coverage/iffy/simple_match.rs diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/iffy/try_error_result.cov-map similarity index 100% rename from tests/coverage/try_error_result.cov-map rename to tests/coverage/iffy/try_error_result.cov-map diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/iffy/try_error_result.coverage similarity index 100% rename from tests/coverage/try_error_result.coverage rename to tests/coverage/iffy/try_error_result.coverage diff --git a/tests/coverage/try_error_result.rs b/tests/coverage/iffy/try_error_result.rs similarity index 100% rename from tests/coverage/try_error_result.rs rename to tests/coverage/iffy/try_error_result.rs diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/iffy/uses_crate.cov-map similarity index 100% rename from tests/coverage/uses_crate.cov-map rename to tests/coverage/iffy/uses_crate.cov-map diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/iffy/uses_crate.coverage similarity index 100% rename from tests/coverage/uses_crate.coverage rename to tests/coverage/iffy/uses_crate.coverage diff --git a/tests/coverage/uses_crate.rs b/tests/coverage/iffy/uses_crate.rs similarity index 100% rename from tests/coverage/uses_crate.rs rename to tests/coverage/iffy/uses_crate.rs diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/iffy/uses_inline_crate.cov-map similarity index 100% rename from tests/coverage/uses_inline_crate.cov-map rename to tests/coverage/iffy/uses_inline_crate.cov-map diff --git a/tests/coverage/uses_inline_crate.coverage b/tests/coverage/iffy/uses_inline_crate.coverage similarity index 100% rename from tests/coverage/uses_inline_crate.coverage rename to tests/coverage/iffy/uses_inline_crate.coverage diff --git a/tests/coverage/uses_inline_crate.rs b/tests/coverage/iffy/uses_inline_crate.rs similarity index 100% rename from tests/coverage/uses_inline_crate.rs rename to tests/coverage/iffy/uses_inline_crate.rs diff --git a/tests/coverage/iffy/while.cov-map b/tests/coverage/iffy/while.cov-map new file mode 100644 index 0000000000000..c4183e18e021d --- /dev/null +++ b/tests/coverage/iffy/while.cov-map @@ -0,0 +1,14 @@ +Function name: while::main +Raw bytes (34): 0x[01, 01, 00, 06, 01, 01, 01, 00, 0a, 01, 01, 09, 00, 0c, 01, 00, 0f, 00, 10, 01, 01, 0b, 00, 14, 00, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/while.rs +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) +- Code(Counter(0)) at (prev + 1, 11) to (start + 0, 20) +- Code(Zero) at (prev + 0, 21) to (start + 2, 6) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/iffy/while.coverage b/tests/coverage/iffy/while.coverage new file mode 100644 index 0000000000000..90c16288d668c --- /dev/null +++ b/tests/coverage/iffy/while.coverage @@ -0,0 +1,7 @@ + LL| 1|fn main() { + LL| 1| let num = 9; + LL| 1| while num >= 10 { + LL| 0| // loop body + LL| 0| } + LL| 1|} + diff --git a/tests/coverage/iffy/while.rs b/tests/coverage/iffy/while.rs new file mode 100644 index 0000000000000..d60916a979818 --- /dev/null +++ b/tests/coverage/iffy/while.rs @@ -0,0 +1,6 @@ +fn main() { + let num = 9; + while num >= 10 { + // loop body + } +} diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/iffy/while_early_ret.cov-map similarity index 100% rename from tests/coverage/while_early_ret.cov-map rename to tests/coverage/iffy/while_early_ret.cov-map diff --git a/tests/coverage/while_early_ret.coverage b/tests/coverage/iffy/while_early_ret.coverage similarity index 100% rename from tests/coverage/while_early_ret.coverage rename to tests/coverage/iffy/while_early_ret.coverage diff --git a/tests/coverage/while_early_ret.rs b/tests/coverage/iffy/while_early_ret.rs similarity index 100% rename from tests/coverage/while_early_ret.rs rename to tests/coverage/iffy/while_early_ret.rs diff --git a/tests/coverage/yield.cov-map b/tests/coverage/iffy/yield.cov-map similarity index 100% rename from tests/coverage/yield.cov-map rename to tests/coverage/iffy/yield.cov-map diff --git a/tests/coverage/yield.coverage b/tests/coverage/iffy/yield.coverage similarity index 100% rename from tests/coverage/yield.coverage rename to tests/coverage/iffy/yield.coverage diff --git a/tests/coverage/yield.rs b/tests/coverage/iffy/yield.rs similarity index 100% rename from tests/coverage/yield.rs rename to tests/coverage/iffy/yield.rs diff --git a/tests/coverage/let-else.none.cov-map b/tests/coverage/let-else.none.cov-map new file mode 100644 index 0000000000000..af5b34cb36f79 --- /dev/null +++ b/tests/coverage/let-else.none.cov-map @@ -0,0 +1,38 @@ +Function name: let_else::let_else_no_semi +Raw bytes (41): 0x[01, 01, 01, 01, 05, 07, 01, 10, 01, 00, 2b, 02, 01, 0e, 00, 11, 01, 00, 15, 00, 1c, 05, 01, 09, 00, 0f, 02, 02, 05, 00, 08, 02, 00, 09, 00, 0c, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/let-else.rs +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 43) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 17) + = (c0 - c1) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 28) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 8) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 0, 9) to (start + 0, 12) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 + +Function name: let_else::let_else_semi +Raw bytes (41): 0x[01, 01, 01, 01, 05, 07, 01, 08, 01, 00, 28, 02, 01, 0e, 00, 11, 01, 00, 15, 00, 1c, 05, 01, 09, 00, 0f, 02, 02, 05, 00, 08, 02, 00, 09, 00, 0c, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/let-else.rs +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 40) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 17) + = (c0 - c1) +- Code(Counter(0)) at (prev + 0, 21) to (start + 0, 28) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 8) + = (c0 - c1) +- Code(Expression(0, Sub)) at (prev + 0, 9) to (start + 0, 12) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 + diff --git a/tests/coverage/let-else.none.coverage b/tests/coverage/let-else.none.coverage new file mode 100644 index 0000000000000..a24877eb90a03 --- /dev/null +++ b/tests/coverage/let-else.none.coverage @@ -0,0 +1,39 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: none some + LL| |//@[some] ignore-coverage-map + LL| | + LL| |// Basic test for let-else statements. + LL| | + LL| 1|fn let_else_semi(opt_msg: Option<&str>) { + LL| 1| let Some(msg) = opt_msg else { + ^0 + LL| 1| return; + LL| | }; + LL| 0| say(msg); + LL| 1|} + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn let_else_no_semi(opt_msg: Option<&str>) { + LL| 1| let Some(msg) = opt_msg else { + ^0 + LL| 1| return + LL| | }; + LL| 0| say(msg); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt_msg = cfg_select!( + LL| | some => Some("hello"), + LL| | none => None, + LL| | ); + LL| | let_else_semi(opt_msg); + LL| | let_else_no_semi(opt_msg); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/let-else.rs b/tests/coverage/let-else.rs new file mode 100644 index 0000000000000..0ebef52d649c7 --- /dev/null +++ b/tests/coverage/let-else.rs @@ -0,0 +1,36 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: none some +//@[some] ignore-coverage-map + +// Basic test for let-else statements. + +fn let_else_semi(opt_msg: Option<&str>) { + let Some(msg) = opt_msg else { + return; + }; + say(msg); +} + +#[rustfmt::skip] +fn let_else_no_semi(opt_msg: Option<&str>) { + let Some(msg) = opt_msg else { + return + }; + say(msg); +} + +#[coverage(off)] +fn main() { + let opt_msg = cfg_select!( + some => Some("hello"), + none => None, + ); + let_else_semi(opt_msg); + let_else_no_semi(opt_msg); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/let-else.some.coverage b/tests/coverage/let-else.some.coverage new file mode 100644 index 0000000000000..828731b199f95 --- /dev/null +++ b/tests/coverage/let-else.some.coverage @@ -0,0 +1,37 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: none some + LL| |//@[some] ignore-coverage-map + LL| | + LL| |// Basic test for let-else statements. + LL| | + LL| 1|fn let_else_semi(opt_msg: Option<&str>) { + LL| 1| let Some(msg) = opt_msg else { + LL| 0| return; + LL| | }; + LL| 1| say(msg); + LL| 1|} + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn let_else_no_semi(opt_msg: Option<&str>) { + LL| 1| let Some(msg) = opt_msg else { + LL| 0| return + LL| | }; + LL| 1| say(msg); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | let opt_msg = cfg_select!( + LL| | some => Some("hello"), + LL| | none => None, + LL| | ); + LL| | let_else_semi(opt_msg); + LL| | let_else_no_semi(opt_msg); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/match.cov-map b/tests/coverage/match.cov-map new file mode 100644 index 0000000000000..ac9433fda2dcb --- /dev/null +++ b/tests/coverage/match.cov-map @@ -0,0 +1,49 @@ +Function name: match::match_expr +Raw bytes (131): 0x[01, 01, 0b, 1d, 07, 0b, 19, 0f, 15, 05, 0d, 0d, 11, 0d, 11, 05, 09, 05, 09, 05, 09, 01, 1d, 01, 1d, 15, 01, 06, 01, 00, 2a, 0d, 01, 0b, 00, 0c, 02, 01, 14, 00, 17, 02, 00, 18, 00, 1e, 19, 03, 0d, 00, 10, 19, 00, 11, 00, 16, 15, 02, 14, 02, 0a, 11, 03, 17, 00, 18, 11, 00, 1c, 02, 0a, 16, 03, 14, 00, 17, 16, 00, 18, 00, 1f, 09, 01, 0e, 00, 13, 05, 00, 18, 00, 1d, 09, 00, 21, 00, 22, 09, 00, 26, 02, 0a, 22, 03, 0e, 00, 13, 22, 00, 18, 00, 1b, 22, 00, 1c, 00, 23, 2a, 01, 11, 00, 14, 2a, 00, 15, 00, 1b, 01, 02, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/match.rs +Number of expressions: 11 +- expression 0 operands: lhs = Counter(7), rhs = Expression(1, Add) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(6) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Counter(1), rhs = Counter(3) +- expression 4 operands: lhs = Counter(3), rhs = Counter(4) +- expression 5 operands: lhs = Counter(3), rhs = Counter(4) +- expression 6 operands: lhs = Counter(1), rhs = Counter(2) +- expression 7 operands: lhs = Counter(1), rhs = Counter(2) +- expression 8 operands: lhs = Counter(1), rhs = Counter(2) +- expression 9 operands: lhs = Counter(0), rhs = Counter(7) +- expression 10 operands: lhs = Counter(0), rhs = Counter(7) +Number of file 0 mappings: 21 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 42) +- Code(Counter(3)) at (prev + 1, 11) to (start + 0, 12) +- Code(Expression(0, Sub)) at (prev + 1, 20) to (start + 0, 23) + = (c7 - (((c1 + c3) + c5) + c6)) +- Code(Expression(0, Sub)) at (prev + 0, 24) to (start + 0, 30) + = (c7 - (((c1 + c3) + c5) + c6)) +- Code(Counter(6)) at (prev + 3, 13) to (start + 0, 16) +- Code(Counter(6)) at (prev + 0, 17) to (start + 0, 22) +- Code(Counter(5)) at (prev + 2, 20) to (start + 2, 10) +- Code(Counter(4)) at (prev + 3, 23) to (start + 0, 24) +- Code(Counter(4)) at (prev + 0, 28) to (start + 2, 10) +- Code(Expression(5, Sub)) at (prev + 3, 20) to (start + 0, 23) + = (c3 - c4) +- Code(Expression(5, Sub)) at (prev + 0, 24) to (start + 0, 31) + = (c3 - c4) +- Code(Counter(2)) at (prev + 1, 14) to (start + 0, 19) +- Code(Counter(1)) at (prev + 0, 24) to (start + 0, 29) +- Code(Counter(2)) at (prev + 0, 33) to (start + 0, 34) +- Code(Counter(2)) at (prev + 0, 38) to (start + 2, 10) +- Code(Expression(8, Sub)) at (prev + 3, 14) to (start + 0, 19) + = (c1 - c2) +- Code(Expression(8, Sub)) at (prev + 0, 24) to (start + 0, 27) + = (c1 - c2) +- Code(Expression(8, Sub)) at (prev + 0, 28) to (start + 0, 35) + = (c1 - c2) +- Code(Expression(10, Sub)) at (prev + 1, 17) to (start + 0, 20) + = (c0 - c7) +- Code(Expression(10, Sub)) at (prev + 0, 21) to (start + 0, 27) + = (c0 - c7) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c6 + diff --git a/tests/coverage/match.coverage b/tests/coverage/match.coverage new file mode 100644 index 0000000000000..a69a8652b3c75 --- /dev/null +++ b/tests/coverage/match.coverage @@ -0,0 +1,43 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| | + LL| |// Basic test for `match` expressions with various kinds of arms and guards. + LL| | + LL| 16|fn match_expr(x: Option, cond: bool) { + LL| 3| match x { + LL| 0| Some(0) => say("zero"), + LL| | Some(1) => { + LL| | // (block with a trailing expression) + LL| 1| say("one") + LL| | } + LL| 2| Some(2) => { + LL| 2| say("two"); + LL| 2| } + LL| 0| Some(3) if cond => { + LL| 0| say("three-cond"); + LL| 0| } + LL| 3| Some(3) => say("three"), + LL| 9| Some(other) if other == 4 => { + ^4 ^4 + LL| 4| say("four"); + LL| 4| } + LL| 5| Some(other) => say("other"), + LL| 1| None => say("none"), + LL| | } + LL| 16|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | for i in 0..=5 { + LL| | for _ in 0..i { + LL| | match_expr(Some(i), false); + LL| | } + LL| | } + LL| | match_expr(None, true); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} + diff --git a/tests/coverage/match.rs b/tests/coverage/match.rs new file mode 100644 index 0000000000000..c9d4fd75bdc18 --- /dev/null +++ b/tests/coverage/match.rs @@ -0,0 +1,41 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 + +// Basic test for `match` expressions with various kinds of arms and guards. + +fn match_expr(x: Option, cond: bool) { + match x { + Some(0) => say("zero"), + Some(1) => { + // (block with a trailing expression) + say("one") + } + Some(2) => { + say("two"); + } + Some(3) if cond => { + say("three-cond"); + } + Some(3) => say("three"), + Some(other) if other == 4 => { + say("four"); + } + Some(other) => say("other"), + None => say("none"), + } +} + +#[coverage(off)] +fn main() { + for i in 0..=5 { + for _ in 0..i { + match_expr(Some(i), false); + } + } + match_expr(None, true); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); +} diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index c4183e18e021d..52bef0a80dfb1 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -1,14 +1,42 @@ -Function name: while::main -Raw bytes (34): 0x[01, 01, 00, 06, 01, 01, 01, 00, 0a, 01, 01, 09, 00, 0c, 01, 00, 0f, 00, 10, 01, 01, 0b, 00, 14, 00, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Function name: while::while_with_tail_expr +Raw bytes (56): 0x[01, 01, 01, 05, 01, 0a, 01, 06, 01, 00, 1a, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 10, 02, 01, 09, 00, 0f, 02, 01, 09, 00, 0c, 02, 00, 0d, 00, 1a, 01, 02, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => $DIR/while.rs -Number of expressions: 0 -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 10) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 12) -- Code(Counter(0)) at (prev + 0, 15) to (start + 0, 16) -- Code(Counter(0)) at (prev + 1, 11) to (start + 0, 20) -- Code(Zero) at (prev + 0, 21) to (start + 2, 6) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) -Highest counter ID seen: c0 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Counter(0) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) + = (c1 - c0) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 12) + = (c1 - c0) +- Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 26) + = (c1 - c0) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 + +Function name: while::while_with_tail_stmt +Raw bytes (51): 0x[01, 01, 01, 05, 01, 09, 01, 0f, 01, 00, 1a, 01, 01, 09, 00, 0e, 01, 00, 11, 00, 12, 05, 01, 0b, 00, 10, 02, 00, 11, 03, 06, 02, 01, 09, 00, 0f, 01, 03, 05, 00, 08, 01, 00, 09, 00, 12, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/while.rs +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Counter(0) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 14) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 18) +- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 3, 6) + = (c1 - c0) +- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) + = (c1 - c0) +- Code(Counter(0)) at (prev + 3, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/while.coverage b/tests/coverage/while.coverage index 90c16288d668c..a83198bbc675e 100644 --- a/tests/coverage/while.coverage +++ b/tests/coverage/while.coverage @@ -1,7 +1,34 @@ - LL| 1|fn main() { - LL| 1| let num = 9; - LL| 1| while num >= 10 { - LL| 0| // loop body - LL| 0| } + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| | + LL| |// Basic test for `while` expressions. + LL| | + LL| 1|fn while_with_tail_expr() { + LL| 1| let mut x = 5; + LL| 6| while x > 0 { + LL| 5| x -= 1; + LL| 5| say("decreased x") + LL| | } + LL| 1| say("goodbye"); LL| 1|} + LL| | + LL| 1|fn while_with_tail_stmt() { + LL| 1| let mut x = 5; + LL| 6| while x > 0 { + LL| 5| x -= 1; + LL| 5| say("decreased x"); + LL| 5| } + LL| 1| say("goodbye"); + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | while_with_tail_expr(); + LL| | while_with_tail_stmt(); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(msg: &str) { + LL| | println!("{msg}"); + LL| |} diff --git a/tests/coverage/while.rs b/tests/coverage/while.rs index d60916a979818..77ef50d09a6ac 100644 --- a/tests/coverage/while.rs +++ b/tests/coverage/while.rs @@ -1,6 +1,33 @@ -fn main() { - let num = 9; - while num >= 10 { - // loop body +#![feature(coverage_attribute)] +//@ edition: 2024 + +// Basic test for `while` expressions. + +fn while_with_tail_expr() { + let mut x = 5; + while x > 0 { + x -= 1; + say("decreased x") + } + say("goodbye"); +} + +fn while_with_tail_stmt() { + let mut x = 5; + while x > 0 { + x -= 1; + say("decreased x"); } + say("goodbye"); +} + +#[coverage(off)] +fn main() { + while_with_tail_expr(); + while_with_tail_stmt(); +} + +#[coverage(off)] +fn say(msg: &str) { + println!("{msg}"); } diff --git a/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir index 0050151e89b1b..158a1ea103a63 100644 --- a/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir +++ b/tests/mir-opt/building/write_box_via_move.box_new.CleanupPostBorrowck.after.mir @@ -23,7 +23,7 @@ fn box_new(_1: T) -> Box<[T; 1024]> { _4 = move _2; StorageLive(_5); _5 = copy _1; - ((((*_4).1: std::mem::ManuallyDrop<[T; 1024]>).0: std::mem::MaybeDangling<[T; 1024]>).0: [T; 1024]) = [move _5; 1024]; + (((*_4).1: std::mem::ManuallyDrop<[T; 1024]>).0: [T; 1024]) = [move _5; 1024]; StorageDead(_5); _3 = move _4; drop(_4) -> [return: bb2, unwind: bb5]; diff --git a/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir index 2410e4d31b486..d2f67cd6932c2 100644 --- a/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir +++ b/tests/mir-opt/building/write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir @@ -12,7 +12,7 @@ fn vec_macro() -> Vec { } bb1: { - ((((*_2).1: std::mem::ManuallyDrop<[i32; 8]>).0: std::mem::MaybeDangling<[i32; 8]>).0: [i32; 8]) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32]; + (((*_2).1: std::mem::ManuallyDrop<[i32; 8]>).0: [i32; 8]) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32]; _1 = move _2; drop(_2) -> [return: bb2, unwind: bb4]; } diff --git a/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir index fc75f261ea01b..6b9927949ffe2 100644 --- a/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir +++ b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir @@ -91,7 +91,7 @@ yields () bb6: { StorageDead(_19); - ((((*_5).1: std::mem::ManuallyDrop<[std::string::String; 5]>).0: std::mem::MaybeDangling<[std::string::String; 5]>).0: [std::string::String; 5]) = [move _6, move _9, move _12, move _15, move _18]; + (((*_5).1: std::mem::ManuallyDrop<[std::string::String; 5]>).0: [std::string::String; 5]) = [move _6, move _9, move _12, move _15, move _18]; drop(_18) -> [return: bb7, unwind: bb25, drop: bb15]; } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir index afee76707e8a4..e8efb9b7c3483 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-abort.mir @@ -55,7 +55,7 @@ fn test() -> Option> { _11 = copy ((_5 as Continue).0: u32); _4 = copy _11; StorageDead(_11); - ((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4]; + (((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: [u32; 1]) = [move _4]; StorageDead(_4); _2 = move _3; goto -> bb7; diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir index d44db1eb1c8c6..4da1eed4484bb 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.after.panic-unwind.mir @@ -55,7 +55,7 @@ fn test() -> Option> { _11 = copy ((_5 as Continue).0: u32); _4 = copy _11; StorageDead(_11); - ((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4]; + (((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: [u32; 1]) = [move _4]; StorageDead(_4); _2 = move _3; goto -> bb7; diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir index a49688ae891de..cad38c437e3c3 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir @@ -3,327 +3,309 @@ fn vec_move(_1: Vec) -> () { debug v => _1; let mut _0: (); + let mut _21: std::vec::IntoIter; let mut _22: std::vec::IntoIter; - let mut _23: std::vec::IntoIter; - let mut _24: &mut std::vec::IntoIter; - let mut _25: std::option::Option; - let mut _26: isize; - let _28: (); + let mut _23: &mut std::vec::IntoIter; + let mut _24: std::option::Option; + let mut _25: isize; + let _27: (); scope 1 { - debug iter => _23; - let _27: impl Sized; + debug iter => _22; + let _26: impl Sized; scope 2 { - debug x => _27; + debug x => _26; } } scope 3 (inlined as IntoIterator>::into_iter) { debug self => _1; - let _3: std::mem::ManuallyDrop>; - let mut _4: *const std::alloc::Global; - let mut _8: usize; - let mut _10: *mut impl Sized; - let mut _11: *const impl Sized; - let mut _12: usize; - let _29: &std::vec::Vec; - let mut _30: &std::mem::ManuallyDrop>; - let mut _31: &alloc::raw_vec::RawVec; - let mut _32: &std::mem::ManuallyDrop>; - let _33: &std::vec::Vec; - let mut _34: &std::mem::ManuallyDrop>; - let _35: &std::vec::Vec; - let mut _36: &std::mem::ManuallyDrop>; - let mut _37: &alloc::raw_vec::RawVec; - let mut _38: &std::mem::ManuallyDrop>; + let _2: std::mem::ManuallyDrop>; + let mut _3: *const std::alloc::Global; + let mut _7: usize; + let mut _9: *mut impl Sized; + let mut _10: *const impl Sized; + let mut _11: usize; + let _28: &std::vec::Vec; + let mut _29: &std::mem::ManuallyDrop>; + let mut _30: &alloc::raw_vec::RawVec; + let mut _31: &std::mem::ManuallyDrop>; + let _32: &std::vec::Vec; + let mut _33: &std::mem::ManuallyDrop>; + let _34: &std::vec::Vec; + let mut _35: &std::mem::ManuallyDrop>; + let mut _36: &alloc::raw_vec::RawVec; + let mut _37: &std::mem::ManuallyDrop>; scope 4 { - debug me => _3; + debug me => _2; scope 5 { - debug alloc => const ManuallyDrop:: {{ value: MaybeDangling::(std::alloc::Global) }}; - let _6: std::ptr::NonNull; + debug alloc => const ManuallyDrop:: {{ value: std::alloc::Global }}; + let _5: std::ptr::NonNull; scope 6 { - debug buf => _6; - let _7: *mut impl Sized; + debug buf => _5; + let _6: *mut impl Sized; scope 7 { - debug begin => _7; + debug begin => _6; scope 8 { - debug end => _11; - let _20: usize; + debug end => _10; + let _19: usize; scope 9 { - debug cap => _20; + debug cap => _19; } - scope 45 (inlined > as Deref>::deref) { - debug self => _38; - scope 46 (inlined MaybeDangling::>::as_ref) { - } - } - scope 47 (inlined alloc::raw_vec::RawVec::::capacity) { + scope 39 (inlined > as Deref>::deref) { debug self => _37; - let mut _39: &alloc::raw_vec::RawVecInner; - scope 48 (inlined std::mem::size_of::) { + } + scope 40 (inlined alloc::raw_vec::RawVec::::capacity) { + debug self => _36; + let mut _38: &alloc::raw_vec::RawVecInner; + scope 41 (inlined std::mem::size_of::) { } - scope 49 (inlined alloc::raw_vec::RawVecInner::capacity) { - debug self => _39; + scope 42 (inlined alloc::raw_vec::RawVecInner::capacity) { + debug self => _38; debug elem_size => const ::SIZE; - let mut _21: core::num::niche_types::UsizeNoHighBit; - scope 50 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { - debug self => _21; + let mut _20: core::num::niche_types::UsizeNoHighBit; + scope 43 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { + debug self => _20; } } } } - scope 29 (inlined > as Deref>::deref) { - debug self => _34; - scope 30 (inlined MaybeDangling::>::as_ref) { - } - } - scope 31 (inlined Vec::::len) { + scope 25 (inlined > as Deref>::deref) { debug self => _33; - let mut _13: bool; - scope 32 { + } + scope 26 (inlined Vec::::len) { + debug self => _32; + let mut _12: bool; + scope 27 { } } - scope 33 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { - debug self => _7; - debug count => _12; - let mut _14: *mut u8; - let mut _18: *mut u8; - let mut _19: *const impl Sized; - scope 34 (inlined std::ptr::mut_ptr::::cast::) { - debug self => _7; + scope 28 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { + debug self => _6; + debug count => _11; + let mut _13: *mut u8; + let mut _17: *mut u8; + let mut _18: *const impl Sized; + scope 29 (inlined std::ptr::mut_ptr::::cast::) { + debug self => _6; } - scope 35 (inlined std::ptr::mut_ptr::::wrapping_add) { - debug self => _14; - debug count => _12; - let mut _15: isize; - scope 36 (inlined std::ptr::mut_ptr::::wrapping_offset) { - debug self => _14; - debug count => _15; + scope 30 (inlined std::ptr::mut_ptr::::wrapping_add) { + debug self => _13; + debug count => _11; + let mut _14: isize; + scope 31 (inlined std::ptr::mut_ptr::::wrapping_offset) { + debug self => _13; + debug count => _14; + let mut _15: *const u8; let mut _16: *const u8; - let mut _17: *const u8; } } - scope 37 (inlined std::ptr::mut_ptr::::with_metadata_of::) { - debug self => _18; - debug meta => _19; - scope 38 (inlined std::ptr::metadata::) { - debug ptr => _19; + scope 32 (inlined std::ptr::mut_ptr::::with_metadata_of::) { + debug self => _17; + debug meta => _18; + scope 33 (inlined std::ptr::metadata::) { + debug ptr => _18; } - scope 39 (inlined std::ptr::from_raw_parts_mut::) { + scope 34 (inlined std::ptr::from_raw_parts_mut::) { } } } - scope 40 (inlined > as Deref>::deref) { - debug self => _36; - scope 41 (inlined MaybeDangling::>::as_ref) { - } - } - scope 42 (inlined Vec::::len) { + scope 35 (inlined > as Deref>::deref) { debug self => _35; - let mut _9: bool; - scope 43 { + } + scope 36 (inlined Vec::::len) { + debug self => _34; + let mut _8: bool; + scope 37 { } } - scope 44 (inlined #[track_caller] std::ptr::mut_ptr::::add) { - debug self => _7; - debug count => _8; + scope 38 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + debug self => _6; + debug count => _7; } } - scope 28 (inlined NonNull::::as_ptr) { - debug self => _6; - } - } - scope 20 (inlined > as Deref>::deref) { - debug self => _32; - scope 21 (inlined MaybeDangling::>::as_ref) { + scope 24 (inlined NonNull::::as_ptr) { + debug self => _5; } } - scope 22 (inlined alloc::raw_vec::RawVec::::non_null) { + scope 17 (inlined > as Deref>::deref) { debug self => _31; - scope 23 (inlined alloc::raw_vec::RawVecInner::non_null::) { - let mut _5: std::ptr::NonNull; - scope 24 (inlined std::ptr::Unique::::cast::) { - scope 25 (inlined NonNull::::cast::) { - scope 26 (inlined NonNull::::as_ptr) { + } + scope 18 (inlined alloc::raw_vec::RawVec::::non_null) { + debug self => _30; + scope 19 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _4: std::ptr::NonNull; + scope 20 (inlined std::ptr::Unique::::cast::) { + scope 21 (inlined NonNull::::cast::) { + scope 22 (inlined NonNull::::as_ptr) { } } } - scope 27 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 23 (inlined std::ptr::Unique::::as_non_null_ptr) { } } } } - scope 12 (inlined > as Deref>::deref) { - debug self => _30; - scope 13 (inlined MaybeDangling::>::as_ref) { - } - } - scope 14 (inlined Vec::::allocator) { + scope 11 (inlined > as Deref>::deref) { debug self => _29; - scope 15 (inlined alloc::raw_vec::RawVec::::allocator) { - scope 16 (inlined alloc::raw_vec::RawVecInner::allocator) { + } + scope 12 (inlined Vec::::allocator) { + debug self => _28; + scope 13 (inlined alloc::raw_vec::RawVec::::allocator) { + scope 14 (inlined alloc::raw_vec::RawVecInner::allocator) { } } } - scope 17 (inlined #[track_caller] std::ptr::read::) { - debug src => _4; + scope 15 (inlined #[track_caller] std::ptr::read::) { + debug src => _3; } - scope 18 (inlined ManuallyDrop::::new) { + scope 16 (inlined ManuallyDrop::::new) { debug value => const std::alloc::Global; - scope 19 (inlined MaybeDangling::::new) { - } } } scope 10 (inlined ManuallyDrop::>::new) { debug value => _1; - let mut _2: std::mem::MaybeDangling>; - scope 11 (inlined MaybeDangling::>::new) { - } } } bb0: { - StorageLive(_22); - StorageLive(_11); - StorageLive(_20); - StorageLive(_5); - StorageLive(_17); - StorageLive(_3); - StorageLive(_2); - _2 = MaybeDangling::>(copy _1); - _3 = ManuallyDrop::> { value: move _2 }; - StorageDead(_2); + StorageLive(_21); + StorageLive(_10); + StorageLive(_19); StorageLive(_4); - // DBG: _30 = &_3; - // DBG: _29 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _4 = &raw const (((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global); - StorageDead(_4); + StorageLive(_16); + StorageLive(_2); + _2 = ManuallyDrop::> { value: copy _1 }; + StorageLive(_3); + // DBG: _29 = &_2; + // DBG: _28 = &(_2.0: std::vec::Vec); + _3 = &raw const ((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global); + StorageDead(_3); + StorageLive(_5); + // DBG: _31 = &_2; + // DBG: _30 = &((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec); + _4 = copy (((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = copy _4 as std::ptr::NonNull (Transmute); StorageLive(_6); - // DBG: _32 = &_3; - // DBG: _31 = &(((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec); - _5 = copy ((((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _6 = copy _5 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy _5 as *mut impl Sized (Transmute); + _6 = copy _4 as *mut impl Sized (Transmute); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); - StorageLive(_8); - // DBG: _36 = &_3; - // DBG: _35 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _8 = copy (((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).1: usize); StorageLive(_9); - _9 = Le(copy _8, const ::MAX_SLICE_LEN); - assume(move _9); - StorageDead(_9); - _10 = Offset(copy _7, copy _8); - _11 = copy _10 as *const impl Sized (PtrToPtr); + StorageLive(_7); + // DBG: _35 = &_2; + // DBG: _34 = &(_2.0: std::vec::Vec); + _7 = copy ((_2.0: std::vec::Vec).1: usize); + StorageLive(_8); + _8 = Le(copy _7, const ::MAX_SLICE_LEN); + assume(move _8); StorageDead(_8); - StorageDead(_10); + _9 = Offset(copy _6, copy _7); + _10 = copy _9 as *const impl Sized (PtrToPtr); + StorageDead(_7); + StorageDead(_9); goto -> bb4; } bb2: { + StorageLive(_11); + // DBG: _33 = &_2; + // DBG: _32 = &(_2.0: std::vec::Vec); + _11 = copy ((_2.0: std::vec::Vec).1: usize); StorageLive(_12); - // DBG: _34 = &_3; - // DBG: _33 = &((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec); - _12 = copy (((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).1: usize); + _12 = Le(copy _11, const ::MAX_SLICE_LEN); + assume(move _12); + StorageDead(_12); + StorageLive(_17); StorageLive(_13); - _13 = Le(copy _12, const ::MAX_SLICE_LEN); - assume(move _13); - StorageDead(_13); - StorageLive(_18); + _13 = copy _4 as *mut u8 (Transmute); StorageLive(_14); - _14 = copy _5 as *mut u8 (Transmute); + _14 = copy _11 as isize (IntToInt); StorageLive(_15); - _15 = copy _12 as isize (IntToInt); - StorageLive(_16); - _16 = copy _5 as *const u8 (Transmute); - _17 = arith_offset::(move _16, move _15) -> [return: bb3, unwind unreachable]; + _15 = copy _4 as *const u8 (Transmute); + _16 = arith_offset::(move _15, move _14) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_16); - _18 = copy _17 as *mut u8 (PtrToPtr); StorageDead(_15); + _17 = copy _16 as *mut u8 (PtrToPtr); StorageDead(_14); - StorageLive(_19); - _19 = copy _5 as *const impl Sized (Transmute); - StorageDead(_19); + StorageDead(_13); + StorageLive(_18); + _18 = copy _4 as *const impl Sized (Transmute); StorageDead(_18); - StorageDead(_12); - _11 = copy _17 as *const impl Sized (PtrToPtr); + StorageDead(_17); + StorageDead(_11); + _10 = copy _16 as *const impl Sized (PtrToPtr); goto -> bb4; } bb4: { - // DBG: _38 = &_3; - // DBG: _37 = &(((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec); - // DBG: _39 = &((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); + // DBG: _37 = &_2; + // DBG: _36 = &((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec); + // DBG: _38 = &(((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); switchInt(const ::SIZE) -> [0: bb5, otherwise: bb6]; } bb5: { - _20 = const usize::MAX; + _19 = const usize::MAX; goto -> bb7; } bb6: { - StorageLive(_21); - _21 = copy (((((_3.0: std::mem::MaybeDangling>).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).1: core::num::niche_types::UsizeNoHighBit); - _20 = copy _21 as usize (Transmute); - StorageDead(_21); + StorageLive(_20); + _20 = copy ((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).1: core::num::niche_types::UsizeNoHighBit); + _19 = copy _20 as usize (Transmute); + StorageDead(_20); goto -> bb7; } bb7: { - _22 = std::vec::IntoIter:: { buf: copy _6, phantom: const ZeroSized: PhantomData, cap: move _20, alloc: const ManuallyDrop:: {{ value: MaybeDangling::(std::alloc::Global) }}, ptr: copy _6, end: copy _11 }; - StorageDead(_7); + _21 = std::vec::IntoIter:: { buf: copy _5, phantom: const ZeroSized: PhantomData, cap: move _19, alloc: const ManuallyDrop:: {{ value: std::alloc::Global }}, ptr: copy _5, end: copy _10 }; StorageDead(_6); - StorageDead(_3); - StorageDead(_17); StorageDead(_5); - StorageDead(_20); - StorageDead(_11); - StorageLive(_23); - _23 = move _22; + StorageDead(_2); + StorageDead(_16); + StorageDead(_4); + StorageDead(_19); + StorageDead(_10); + StorageLive(_22); + _22 = move _21; goto -> bb8; } bb8: { - StorageLive(_25); StorageLive(_24); - _24 = &mut _23; - _25 = as Iterator>::next(move _24) -> [return: bb9, unwind: bb15]; + StorageLive(_23); + _23 = &mut _22; + _24 = as Iterator>::next(move _23) -> [return: bb9, unwind: bb15]; } bb9: { - _26 = discriminant(_25); - switchInt(move _26) -> [0: bb10, 1: bb12, otherwise: bb14]; + _25 = discriminant(_24); + switchInt(move _25) -> [0: bb10, 1: bb12, otherwise: bb14]; } bb10: { + StorageDead(_23); StorageDead(_24); - StorageDead(_25); - drop(_23) -> [return: bb11, unwind continue]; + drop(_22) -> [return: bb11, unwind continue]; } bb11: { - StorageDead(_23); StorageDead(_22); + StorageDead(_21); return; } bb12: { - StorageLive(_27); - _27 = move ((_25 as Some).0: impl Sized); - _28 = opaque::(move _27) -> [return: bb13, unwind: bb15]; + StorageLive(_26); + _26 = move ((_24 as Some).0: impl Sized); + _27 = opaque::(move _26) -> [return: bb13, unwind: bb15]; } bb13: { - StorageDead(_27); + StorageDead(_26); + StorageDead(_23); StorageDead(_24); - StorageDead(_25); goto -> bb8; } @@ -332,7 +314,7 @@ fn vec_move(_1: Vec) -> () { } bb15 (cleanup): { - drop(_23) -> [return: bb16, unwind terminate(cleanup)]; + drop(_22) -> [return: bb16, unwind terminate(cleanup)]; } bb16 (cleanup): { diff --git a/tests/rustdoc-html/doc-cfg/all-targets.rs b/tests/rustdoc-html/doc-cfg/all-targets.rs index d5a8be83bc1d3..aec251878781e 100644 --- a/tests/rustdoc-html/doc-cfg/all-targets.rs +++ b/tests/rustdoc-html/doc-cfg/all-targets.rs @@ -79,11 +79,11 @@ pub fn bar() {} // Emscripten and ESP-IDF and FreeBSD and Fuchsia and GNU/Hurd and Haiku \ // and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \ // and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \ -// and OpenBSD and Play Station 1 and Play Station Portable and Play Station Vita \ -// and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS and RTEMS OS and Solaris and \ -// SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS \ -// and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \ -// Virtual Machine only.' +// and OpenBSD and Play Station 1 and Play Station 3 and Play Station Portable \ +// and Play Station Vita and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS \ +// and RTEMS OS and Solaris and SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI \ +// and VEXos and visionOS and VxWorks and WASI and watchOS and Windows and Xous \ +// and zero knowledge Virtual Machine only.' #[doc(cfg(all( target_os = "aix", target_os = "amdhsa", @@ -114,6 +114,7 @@ pub fn bar() {} target_os = "qnx", target_os = "nuttx", target_os = "openbsd", + target_os = "ps3", target_os = "psp", target_os = "psx", target_os = "qurt", diff --git a/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs b/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs index 41bf42d2e7aad..343e66cfc9666 100644 --- a/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs +++ b/tests/rustdoc-html/inline_local/fully-stable-path-is-better.rs @@ -16,10 +16,10 @@ pub mod stb1 { #[unstable(feature = "uns", issue = "135003")] pub mod uns { #[stable(since = "1.0", feature = "stb1")] - #[rustc_allowed_through_unstable_modules = "use stable path instead"] + #[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stb1")] pub struct Inside1; #[stable(since = "1.0", feature = "stb2")] - #[rustc_allowed_through_unstable_modules = "use stable path instead"] + #[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stb2")] pub struct Inside2; } diff --git a/tests/rustdoc-html/stability.rs b/tests/rustdoc-html/stability.rs index 4870c68dfe5e6..8df66a59d3c15 100644 --- a/tests/rustdoc-html/stability.rs +++ b/tests/rustdoc-html/stability.rs @@ -85,7 +85,10 @@ pub mod stable_later { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "use stable path instead"] +#[rustc_allowed_through_unstable_modules( + message = "use stable path instead", + module = "stable_module", +)] pub mod stable_earlier1 { //@ has stability/stable_earlier1/struct.StableInUnstable.html \ // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 6d2ac90c0c975..e7cb6199ab45c 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -59,6 +59,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 6d2ac90c0c975..e7cb6199ab45c 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -59,6 +59,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index edea2d5772280..437ebd63ceba5 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:65:1 | diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 6242d93b09534..82c469e0f4f80 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 176c68ecd4c7b..b5c73d00564c6 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 176c68ecd4c7b..b5c73d00564c6 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -106,6 +106,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -187,6 +188,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -258,6 +260,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:40:1 | @@ -336,6 +339,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -402,6 +406,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:59:1 | @@ -481,6 +486,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -554,6 +560,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:62:1 | @@ -626,6 +633,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -692,6 +700,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -764,6 +773,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -830,6 +840,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:69:1 | @@ -924,6 +935,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:52:5 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr index 65818feab4297..df49fbfe3d272 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr @@ -69,6 +69,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -146,6 +147,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -223,6 +225,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -300,6 +303,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -377,6 +381,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -454,6 +459,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr index cbe389c42d40a..7ceb6a2092af2 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr @@ -69,6 +69,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -146,6 +147,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -223,6 +225,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -300,6 +303,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -377,6 +381,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -454,6 +459,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index efeec0d86982b..935ab97647321 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -83,6 +83,7 @@ error: fn_abi_of(extern_c) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:20:1 | @@ -174,6 +175,7 @@ error: fn_abi_of(extern_rust) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:27:1 | diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 82d3793c35328..f19480faec4fa 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/sysv64-zst.rs:8:1 | diff --git a/tests/ui/asm/aarch64/aarch64-sve.rs b/tests/ui/asm/aarch64/aarch64-sve.rs index a146d73345554..daa4ab98dee75 100644 --- a/tests/ui/asm/aarch64/aarch64-sve.rs +++ b/tests/ui/asm/aarch64/aarch64-sve.rs @@ -15,6 +15,7 @@ use minicore::*; fn f(x: f64) { unsafe { asm!("", out("p0") _); + asm!("", out("z0") _); asm!("", out("ffr") _); } } diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs index 39a3e386bb6e5..daaca4746cf37 100644 --- a/tests/ui/asm/aarch64/bad-reg.rs +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -1,5 +1,5 @@ //@ add-minicore -//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+neon +//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+neon,+sve //@ needs-llvm-components: aarch64 //@ ignore-backends: gcc #![crate_type = "lib"] @@ -38,15 +38,15 @@ fn main() { asm!("", in("x19") foo); //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm - asm!("", in("p0") foo); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("", in("ffr") foo); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output //~| ERROR type `i32` cannot be used with this register class - asm!("", out("p0") _); - asm!("{}", in(preg) foo); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("", out("ffr") _); + asm!("{}", in(ffr) foo); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output //~| ERROR type `i32` cannot be used with this register class - asm!("{}", out(preg) _); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("{}", out(ffr) _); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output // Explicit register conflicts // (except in/lateout which don't conflict) diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 9f3d54eb46660..8937509763dec 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -4,7 +4,7 @@ error: invalid register class `foo`: unknown register class LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ | - = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, and `preg` + = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg`, and `ffr` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:20:18 @@ -30,7 +30,7 @@ LL | asm!("{:r}", in(vreg) foo); | | | template modifier | - = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` error: invalid asm template modifier `r` for this register class --> $DIR/bad-reg.rs:26:15 @@ -40,7 +40,7 @@ LL | asm!("{:r}", in(vreg_low16) foo); | | | template modifier | - = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` error: asm template modifiers are not allowed for `const` arguments --> $DIR/bad-reg.rs:28:15 @@ -82,23 +82,23 @@ error: invalid register `x19`: x19 is used internally by LLVM and cannot be used LL | asm!("", in("x19") foo); | ^^^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:41:18 | -LL | asm!("", in("p0") foo); - | ^^^^^^^^^^^^ +LL | asm!("", in("ffr") foo); + | ^^^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:45:20 | -LL | asm!("{}", in(preg) foo); - | ^^^^^^^^^^^^ +LL | asm!("{}", in(ffr) foo); + | ^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:48:20 | -LL | asm!("{}", out(preg) _); - | ^^^^^^^^^^^ +LL | asm!("{}", out(ffr) _); + | ^^^^^^^^^^ error: register `w0` conflicts with register `x0` --> $DIR/bad-reg.rs:54:32 @@ -145,20 +145,20 @@ LL | asm!("", in("v0") foo, out("q0") bar); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:41:27 + --> $DIR/bad-reg.rs:41:28 | -LL | asm!("", in("p0") foo); - | ^^^ +LL | asm!("", in("ffr") foo); + | ^^^ | - = note: register class `preg` supports these types: + = note: register class `ffr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:29 + --> $DIR/bad-reg.rs:45:28 | -LL | asm!("{}", in(preg) foo); - | ^^^ +LL | asm!("{}", in(ffr) foo); + | ^^^ | - = note: register class `preg` supports these types: + = note: register class `ffr` supports these types: error: aborting due to 20 previous errors diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index 2cd767db0334a..325e2c43b3035 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -12,7 +12,7 @@ error: cannot use value of type `{closure@$DIR/type-check-2.rs:32:28: 32:36}` fo LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly --> $DIR/type-check-2.rs:34:28 @@ -20,7 +20,7 @@ error: cannot use value of type `Vec` for inline assembly LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `(i32, i32, i32)` for inline assembly --> $DIR/type-check-2.rs:36:28 @@ -28,7 +28,7 @@ error: cannot use value of type `(i32, i32, i32)` for inline assembly LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly --> $DIR/type-check-2.rs:38:28 @@ -36,7 +36,7 @@ error: cannot use value of type `[i32; 3]` for inline assembly LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly --> $DIR/type-check-2.rs:46:31 @@ -44,7 +44,7 @@ error: cannot use value of type `fn() {main}` for inline assembly LL | asm!("{}", inout(reg) f); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly --> $DIR/type-check-2.rs:49:31 @@ -52,7 +52,7 @@ error: cannot use value of type `&mut i32` for inline assembly LL | asm!("{}", inout(reg) r); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 7 previous errors diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 2f8439d0a0f9e..6c01a3380f169 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,9 +1,9 @@ //@ only-aarch64 -//@ compile-flags: -C target-feature=+neon +//@ compile-flags: -C target-feature=+neon,+sve -#![feature(repr_simd)] +#![feature(asm_experimental_reg, repr_simd, stdarch_aarch64_sve)] -use std::arch::aarch64::float64x2_t; +use std::arch::aarch64::{float64x2_t, svdup_n_f64, svdup_n_s16, svdup_n_s32, svptrue_b8}; use std::arch::{asm, global_asm}; #[repr(simd)] @@ -13,6 +13,10 @@ struct Simd256bit([f64; 4]); fn main() { let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; let f64x4 = Simd256bit([0.0, 0.0, 0.0, 0.0]); + let svi16 = unsafe { svdup_n_s16(0i16) }; + let svi32 = unsafe { svdup_n_s32(0i32) }; + let svf64 = unsafe { svdup_n_f64(0f64) }; + let svb8 = unsafe { svptrue_b8() }; unsafe { // Types must be listed in the register class. @@ -33,9 +37,12 @@ fn main() { asm!("{:d}", in(vreg) 0f64); asm!("{:q}", in(vreg) f64x2); asm!("{:v}", in(vreg) f64x2); + asm!("{:z}", in(vreg) svi32); + asm!("{}", in(preg) svb8); // Should be the same as vreg asm!("{:q}", in(vreg_low16) f64x2); + asm!("{:z}", in(vreg_low16) svi32); // Template modifiers of a different size to the argument are fine asm!("{:w}", in(reg) 0u64); @@ -62,6 +69,12 @@ fn main() { //~^ WARN formatting may not be suitable for sub-register argument asm!("{}", in(vreg_low16) 0f64); //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svi16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svi32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svf64); + //~^ WARN formatting may not be suitable for sub-register argument asm!("{0} {0}", in(reg) 0i16); //~^ WARN formatting may not be suitable for sub-register argument @@ -76,9 +89,16 @@ fn main() { //~^ ERROR type `float64x2_t` cannot be used with this register class asm!("{}", in(vreg) f64x4); //~^ ERROR type `Simd256bit` cannot be used with this register class + asm!("{}", in(reg) svi32); + //~^ ERROR type `svint32_t` cannot be used with this register class + asm!("{}", in(reg) svb8); + //~^ ERROR type `svbool_t` cannot be used with this register class + asm!("{}", in(vreg) svb8); + //~^ ERROR type `svbool_t` cannot be used with this register class + asm!("{}", in(preg) svi32); + //~^ ERROR type `svint32_t` cannot be used with this register class // Split inout operands must have compatible types - let mut val_i16: i16; let mut val_f32: f32; let mut val_u32: u32; diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr index 9d84d2666b33c..e407ed3a9d3ac 100644 --- a/tests/ui/asm/aarch64/type-check-3.stderr +++ b/tests/ui/asm/aarch64/type-check-3.stderr @@ -1,96 +1,123 @@ warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:48:15 + --> $DIR/type-check-3.rs:55:15 | LL | asm!("{}", in(reg) 0u8); | ^^ --- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:50:15 + --> $DIR/type-check-3.rs:57:15 | LL | asm!("{}", in(reg) 0u16); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:52:15 + --> $DIR/type-check-3.rs:59:15 | LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:54:15 + --> $DIR/type-check-3.rs:61:15 | LL | asm!("{}", in(reg) 0f32); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:57:15 + --> $DIR/type-check-3.rs:64:15 | LL | asm!("{}", in(vreg) 0i16); | ^^ ---- for this argument | - = help: use `{0:h}` to have the register formatted as `h0` (for 16-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:h}` to have the register formatted as `h0` (for 2-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:59:15 + --> $DIR/type-check-3.rs:66:15 | LL | asm!("{}", in(vreg) 0f32); | ^^ ---- for this argument | - = help: use `{0:s}` to have the register formatted as `s0` (for 32-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:s}` to have the register formatted as `s0` (for 4-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:61:15 + --> $DIR/type-check-3.rs:68:15 | LL | asm!("{}", in(vreg) 0f64); | ^^ ---- for this argument | - = help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:d}` to have the register formatted as `d0` (for 8-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:63:15 + --> $DIR/type-check-3.rs:70:15 | LL | asm!("{}", in(vreg_low16) 0f64); | ^^ ---- for this argument | - = help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:d}` to have the register formatted as `d0` (for 8-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:66:15 + --> $DIR/type-check-3.rs:72:15 + | +LL | asm!("{}", in(vreg) svi16); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:74:15 + | +LL | asm!("{}", in(vreg) svi32); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:76:15 + | +LL | asm!("{}", in(vreg) svf64); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:79:15 | LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:68:15 + --> $DIR/type-check-3.rs:81:15 | LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) error: type `i128` cannot be used with this register class - --> $DIR/type-check-3.rs:73:28 + --> $DIR/type-check-3.rs:86:28 | LL | asm!("{}", in(reg) 0i128); | ^^^^^ @@ -98,7 +125,7 @@ LL | asm!("{}", in(reg) 0i128); = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `float64x2_t` cannot be used with this register class - --> $DIR/type-check-3.rs:75:28 + --> $DIR/type-check-3.rs:88:28 | LL | asm!("{}", in(reg) f64x2); | ^^^^^ @@ -106,15 +133,47 @@ LL | asm!("{}", in(reg) f64x2); = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `Simd256bit` cannot be used with this register class - --> $DIR/type-check-3.rs:77:29 + --> $DIR/type-check-3.rs:90:29 | LL | asm!("{}", in(vreg) f64x4); | ^^^^^ | - = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2, svint8_t, svint16_t, svint32_t, svint64_t, svint128_t, svfloat26_t, svfloat32_t, svfloat64_t, svint128_t, svfloat128_t + +error: type `svint32_t` cannot be used with this register class + --> $DIR/type-check-3.rs:92:28 + | +LL | asm!("{}", in(reg) svi32); + | ^^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 + +error: type `svbool_t` cannot be used with this register class + --> $DIR/type-check-3.rs:94:28 + | +LL | asm!("{}", in(reg) svb8); + | ^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 + +error: type `svbool_t` cannot be used with this register class + --> $DIR/type-check-3.rs:96:29 + | +LL | asm!("{}", in(vreg) svb8); + | ^^^^ + | + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2, svint8_t, svint16_t, svint32_t, svint64_t, svint128_t, svfloat26_t, svfloat32_t, svfloat64_t, svint128_t, svfloat128_t + +error: type `svint32_t` cannot be used with this register class + --> $DIR/type-check-3.rs:98:29 + | +LL | asm!("{}", in(preg) svi32); + | ^^^^^ + | + = note: register class `preg` supports these types: svbool_t error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:88:33 + --> $DIR/type-check-3.rs:108:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_f32); | ^^^^ ^^^^^^^ type `f32` @@ -124,7 +183,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_f32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:90:33 + --> $DIR/type-check-3.rs:110:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); | ^^^^ ^^^^^^^ type `*mut u8` @@ -134,7 +193,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:92:33 + --> $DIR/type-check-3.rs:112:33 | LL | asm!("{:x}", inout(reg) main => val_u32); | ^^^^ ^^^^^^^ type `u32` @@ -143,5 +202,5 @@ LL | asm!("{:x}", inout(reg) main => val_u32); | = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size -error: aborting due to 6 previous errors; 10 warnings emitted +error: aborting due to 10 previous errors; 13 warnings emitted diff --git a/tests/ui/asm/bad-template.aarch64.stderr b/tests/ui/asm/bad-template.aarch64.stderr index 5f7ebb539107c..268fcceb14a50 100644 --- a/tests/ui/asm/bad-template.aarch64.stderr +++ b/tests/ui/asm/bad-template.aarch64.stderr @@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default error: aborting due to 21 previous errors; 1 warning emitted diff --git a/tests/ui/asm/bad-template.x86_64.stderr b/tests/ui/asm/bad-template.x86_64.stderr index 9947117621f1c..cc8626deeb5fa 100644 --- a/tests/ui/asm/bad-template.x86_64.stderr +++ b/tests/ui/asm/bad-template.x86_64.stderr @@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument | - = help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:e}` to have the register formatted as `eax` (for 4-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default error: aborting due to 21 previous errors; 1 warning emitted diff --git a/tests/ui/asm/issue-87802.stderr b/tests/ui/asm/issue-87802.stderr index 64e91662919b2..da3f6815cd7da 100644 --- a/tests/ui/asm/issue-87802.stderr +++ b/tests/ui/asm/issue-87802.stderr @@ -4,7 +4,7 @@ error: cannot use value of type `!` for inline assembly LL | asm!("/* {0} */", out(reg) x); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 1 previous error diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index aa9eed2fce65c..20e7017ee9ad5 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -43,7 +43,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", in(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly --> $DIR/type-check-1.rs:23:29 @@ -51,7 +51,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", out(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly --> $DIR/type-check-1.rs:26:31 @@ -59,7 +59,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", inout(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 8 previous errors diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index e5d39b2fbd053..5e54f5af4c6d8 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -12,7 +12,7 @@ error: cannot use value of type `{closure@$DIR/type-check-2.rs:48:28: 48:36}` fo LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly --> $DIR/type-check-2.rs:50:28 @@ -20,7 +20,7 @@ error: cannot use value of type `Vec` for inline assembly LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `(i32, i32, i32)` for inline assembly --> $DIR/type-check-2.rs:52:28 @@ -28,7 +28,7 @@ error: cannot use value of type `(i32, i32, i32)` for inline assembly LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly --> $DIR/type-check-2.rs:54:28 @@ -36,7 +36,7 @@ error: cannot use value of type `[i32; 3]` for inline assembly LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly --> $DIR/type-check-2.rs:62:31 @@ -44,7 +44,7 @@ error: cannot use value of type `fn() {main}` for inline assembly LL | asm!("{}", inout(reg) f); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly --> $DIR/type-check-2.rs:65:31 @@ -52,7 +52,7 @@ error: cannot use value of type `&mut i32` for inline assembly LL | asm!("{}", inout(reg) r); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2.rs:15:28 diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr index ea9a3955e7078..e3ad64495904b 100644 --- a/tests/ui/asm/x86_64/type-check-3.stderr +++ b/tests/ui/asm/x86_64/type-check-3.stderr @@ -44,8 +44,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:x}` to have the register formatted as `ax` (for 2-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default warning: formatting may not be suitable for sub-register argument @@ -54,8 +54,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:x}` to have the register formatted as `ax` (for 2-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) warning: formatting may not be suitable for sub-register argument --> $DIR/type-check-3.rs:36:15 @@ -63,8 +63,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument | - = help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:e}` to have the register formatted as `eax` (for 4-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) warning: formatting may not be suitable for sub-register argument --> $DIR/type-check-3.rs:39:15 @@ -72,8 +72,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{}", in(ymm_reg) 0i64); | ^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `xmm0` (for 128-bit values) - = help: or use `{0:y}` to keep the default formatting of `ymm0` (for 256-bit values) + = help: use `{0:x}` to have the register formatted as `xmm0` (for 16-byte values) + = help: or use `{0:y}` to keep the default formatting of `ymm0` (for 32-byte values) error: type `i8` cannot be used with this register class --> $DIR/type-check-3.rs:50:28 diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout index 90381a12bbd4b..775f683a8f926 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout @@ -7,8 +7,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size field `.value`: 3077 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes -print-type-size field `.0`: 3077 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3077 bytes print-type-size field `.uninit`: 0 bytes @@ -38,8 +36,6 @@ print-type-size variant `Panicked`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes -print-type-size field `.0`: 1025 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes @@ -93,10 +89,6 @@ print-type-size type: `std::mem::ManuallyDrop`: 1 bytes, alignment: 1 byte print-type-size field `.value`: 1 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeDangling`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes print-type-size type: `std::mem::MaybeUninit`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index f65c5c1a7cb78..b6051da95ca42 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -7,8 +7,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes -print-type-size field `.0`: 3075 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3075 bytes print-type-size field `.uninit`: 0 bytes @@ -26,8 +24,6 @@ print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes -print-type-size field `.0`: 2050 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 2050 bytes print-type-size field `.uninit`: 0 bytes @@ -45,8 +41,6 @@ print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes -print-type-size field `.0`: 1025 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index 45edd7bc0e0ee..c616e45a9ab8e 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr index d5da912a9b89a..638a0856b7b7f 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.win.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -66,6 +66,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index 1e203b93e66b3..776d0a72287f9 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -70,6 +70,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | @@ -150,6 +151,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:37:1 | @@ -230,6 +232,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { Win64, ), can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:44:1 | diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index 9bf3cef403159..d65562313cb42 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, and `solaris` and 15 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, and `rtems` and 16 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 395a739b0be72..98404cd495dcf 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -232,7 +232,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -305,7 +305,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 31 warnings emitted diff --git a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs new file mode 100644 index 0000000000000..8233d6034a40a --- /dev/null +++ b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.rs @@ -0,0 +1,73 @@ +fn req_fn(_: impl Fn(&'static str) -> String) {} +fn req_fn_mut(_: impl FnMut(&'static str) -> String) {} + +fn test_fn_mut_passed_as_mut_ref_to_fn() { + let mut v = Vec::new(); + let mut accumulate = |x| { + //~^ ERROR E0525 + v.push(x); + v.join("/") + }; + req_fn(&mut accumulate); +} + +fn test_fn_once_passed_as_mut_ref_to_fn() { + let s = String::new(); + let mut consume = move |_x| { + //~^ ERROR E0525 + drop(s); + String::new() + }; + req_fn(&mut consume); +} + +fn test_fn_once_passed_as_mut_ref_to_fn_mut() { + let s = String::new(); + let mut consume = move |_x| { + //~^ ERROR E0525 + drop(s); + String::new() + }; + req_fn_mut(&mut consume); +} + +fn test_double_ref_fn_mut_passed_to_fn() { + let mut v = Vec::new(); + let mut accumulate = |x| { + //~^ ERROR E0525 + v.push(x); + v.join("/") + }; + req_fn(&mut &mut accumulate); +} + +fn test_fn_passed_as_mut_ref_to_fn() { + let mut pure_closure = |x: &'static str| x.to_string(); + req_fn(&mut pure_closure); + //~^ ERROR E0277 +} + +fn test_nested_closure_conservative_fallback() { + let mut v = Vec::new(); + let s = String::new(); + let mut outer = |_x| { + v.push("a"); + let inner = || drop(s); + inner(); + v.join("/") + }; + req_fn(&mut outer); + //~^ ERROR E0277 +} + +fn test_unresolved_integer_fallback_copy() { + let x = 0; + let mut c = |_x| { + let _y = x; + String::new() + }; + req_fn(&mut c); + //~^ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr new file mode 100644 index 0000000000000..dfc657f6c3a00 --- /dev/null +++ b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr @@ -0,0 +1,145 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:6:26 + | +LL | let mut accumulate = |x| { + | ^^^ this closure implements `FnMut`, not `Fn` +LL | +LL | v.push(x); + | - closure is `FnMut` because it mutates the variable `v` here +... +LL | req_fn(&mut accumulate); + | ------ --------------- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:16:23 + | +LL | let mut consume = move |_x| { + | ^^^^^^^^^ this closure implements `FnOnce`, not `Fn` +LL | +LL | drop(s); + | - closure is `FnOnce` because it moves the variable `s` out of its environment +... +LL | req_fn(&mut consume); + | ------ ------------ the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:26:23 + | +LL | let mut consume = move |_x| { + | ^^^^^^^^^ this closure implements `FnOnce`, not `FnMut` +LL | +LL | drop(s); + | - closure is `FnOnce` because it moves the variable `s` out of its environment +... +LL | req_fn_mut(&mut consume); + | ---------- ------- the requirement to implement `FnMut` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:26:23: 26:32}` to implement `FnMut(&'static str)` +note: required by a bound in `req_fn_mut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:2:23 + | +LL | fn req_fn_mut(_: impl FnMut(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn_mut` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:36:26 + | +LL | let mut accumulate = |x| { + | ^^^ this closure implements `FnMut`, not `Fn` +LL | +LL | v.push(x); + | - closure is `FnMut` because it mutates the variable `v` here +... +LL | req_fn(&mut &mut accumulate); + | ------ -------------------- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:46:12 + | +LL | req_fn(&mut pure_closure); + | ------ ^^^^^^^^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut pure_closure); +LL + req_fn(pure_closure); + | + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:59:12 + | +LL | req_fn(&mut outer); + | ------ ^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut outer); +LL + req_fn(outer); + | + +error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:69:12 + | +LL | req_fn(&mut c); + | ------ ^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` +note: required by a bound in `req_fn` + --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:1:19 + | +LL | fn req_fn(_: impl Fn(&'static str) -> String) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` +help: consider removing the leading `&`-reference + | +LL - req_fn(&mut c); +LL + req_fn(c); + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0525. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/fnmut-shared-reference-requires-fn.rs b/tests/ui/closures/fnmut-shared-reference-requires-fn.rs new file mode 100644 index 0000000000000..1207bc4cf1d52 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-requires-fn.rs @@ -0,0 +1,11 @@ +//! Do not suggest a mutable reference when the root obligation genuinely requires `Fn`. + +fn requires_fn(_: F) {} + +fn main() { + let mut value = 0; + let mut func = || value += 1; + //~^ ERROR expected a closure that implements the `Fn` trait + + requires_fn(&func); +} diff --git a/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr b/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr new file mode 100644 index 0000000000000..6a62f4d1a74c1 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-requires-fn.stderr @@ -0,0 +1,23 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/fnmut-shared-reference-requires-fn.rs:7:20 + | +LL | let mut func = || value += 1; + | ^^ ----- closure is `FnMut` because it mutates the variable `value` here + | | + | this closure implements `FnMut`, not `Fn` +... +LL | requires_fn(&func); + | ----------- ---- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&{closure@$DIR/fnmut-shared-reference-requires-fn.rs:7:20: 7:22}` to implement `Fn()` +note: required by a bound in `requires_fn` + --> $DIR/fnmut-shared-reference-requires-fn.rs:3:19 + | +LL | fn requires_fn(_: F) {} + | ^^^^ required by this bound in `requires_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed new file mode 100644 index 0000000000000..1918d26ac2d90 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix + +//! Regression test for https://github.com/rust-lang/rust/issues/118843. +//! A shared reference to an `FnMut` closure should suggest a mutable reference. + +fn main() { + let mut value = 0; + let mut func = |increment: usize| value += increment; + //~^ ERROR expected a closure that implements the `Fn` trait + + (0..100).for_each(&mut func); + //~^ HELP consider changing this borrow's mutability +} diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs new file mode 100644 index 0000000000000..d7bd2fb60398a --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.rs @@ -0,0 +1,13 @@ +//@ run-rustfix + +//! Regression test for https://github.com/rust-lang/rust/issues/118843. +//! A shared reference to an `FnMut` closure should suggest a mutable reference. + +fn main() { + let mut value = 0; + let mut func = |increment: usize| value += increment; + //~^ ERROR expected a closure that implements the `Fn` trait + + (0..100).for_each(&func); + //~^ HELP consider changing this borrow's mutability +} diff --git a/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr new file mode 100644 index 0000000000000..817c073e92aa8 --- /dev/null +++ b/tests/ui/closures/fnmut-shared-reference-suggestion-issue-118843.stderr @@ -0,0 +1,24 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/fnmut-shared-reference-suggestion-issue-118843.rs:8:20 + | +LL | let mut func = |increment: usize| value += increment; + | ^^^^^^^^^^^^^^^^^^ ----- closure is `FnMut` because it mutates the variable `value` here + | | + | this closure implements `FnMut`, not `Fn` +... +LL | (0..100).for_each(&func); + | -------- ---- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | + = note: required for `&{closure@$DIR/fnmut-shared-reference-suggestion-issue-118843.rs:8:20: 8:38}` to implement `FnMut(usize)` +note: required by a bound in `for_each` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider changing this borrow's mutability + | +LL | (0..100).for_each(&mut func); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/consts/array-type-usize-suggestion.rs b/tests/ui/consts/array-type-usize-suggestion.rs new file mode 100644 index 0000000000000..a86613ba8d4df --- /dev/null +++ b/tests/ui/consts/array-type-usize-suggestion.rs @@ -0,0 +1,9 @@ +//@ check-fail + +fn main() { + let length = 3; + let values: [i32; length] = [0; length]; + //~^ ERROR attempt to use a non-constant value in a constant [E0435] + //~| ERROR attempt to use a non-constant value in a constant [E0435] + println!("{}", values.len()); +} diff --git a/tests/ui/consts/array-type-usize-suggestion.stderr b/tests/ui/consts/array-type-usize-suggestion.stderr new file mode 100644 index 0000000000000..aef1cbee06011 --- /dev/null +++ b/tests/ui/consts/array-type-usize-suggestion.stderr @@ -0,0 +1,27 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/array-type-usize-suggestion.rs:5:23 + | +LL | let values: [i32; length] = [0; length]; + | ^^^^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL - let length = 3; +LL + const length: usize = 3; + | + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/array-type-usize-suggestion.rs:5:37 + | +LL | let values: [i32; length] = [0; length]; + | ^^^^^^ non-constant value + | +help: consider using `const` instead of `let` + | +LL - let length = 3; +LL + const length: usize = 3; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/non-const-value-in-const.stderr b/tests/ui/consts/non-const-value-in-const.stderr index 201c310843b38..67478a4f84727 100644 --- a/tests/ui/consts/non-const-value-in-const.stderr +++ b/tests/ui/consts/non-const-value-in-const.stderr @@ -19,7 +19,7 @@ LL | let _ = [0; x]; help: consider using `const` instead of `let` | LL - let x = 5; -LL + const x: /* Type */ = 5; +LL + const x: usize = 5; | error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0789.rs b/tests/ui/error-codes/E0789.rs index 4a55e1743158d..3b83d88aa9eaf 100644 --- a/tests/ui/error-codes/E0789.rs +++ b/tests/ui/error-codes/E0789.rs @@ -4,7 +4,7 @@ #![feature(staged_api)] #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules = "use stable path instead"] +#[rustc_allowed_through_unstable_modules(message = "use stable path instead", module = "stable")] // #[stable(feature = "foo", since = "1.0")] struct Foo; //~^ ERROR `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr new file mode 100644 index 0000000000000..f19cb17a04a29 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr @@ -0,0 +1,53 @@ +error[E0658]: register class `preg` can only be used as a clobber in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:45:23 + | +LL | asm!("/* {0} */", in(preg) p); + | ^^^^^^^^^^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:33:32 + | +LL | asm!("/* {0} */", in(vreg) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:36:38 + | +LL | asm!("/* {0} */", in(vreg_low16) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:39:23 + | +LL | asm!("", in("z0") x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svbool_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:45:32 + | +LL | asm!("/* {0} */", in(preg) p); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` 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 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr similarity index 90% rename from tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr rename to tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr index fb54438ef589e..0f829dd65cb47 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr @@ -1,5 +1,5 @@ error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:41 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:41 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:54 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:54 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:51 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:51 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ @@ -29,7 +29,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:63 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:63 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs index 0d2c4fe2b67c3..c91036366a028 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -1,6 +1,9 @@ //@ add-minicore -//@ compile-flags: --target loongarch64-unknown-none -//@ needs-llvm-components: loongarch +//@ revisions: aarch64 loongarch +//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve +//@ [aarch64] needs-llvm-components: aarch64 +//@ [loongarch] compile-flags: --target loongarch64-unknown-none +//@ [loongarch] needs-llvm-components: loongarch //@ ignore-backends: gcc #![feature(no_core, lang_items, rustc_attrs, repr_simd)] @@ -11,17 +14,53 @@ extern crate minicore; use minicore::*; +#[cfg(aarch64)] +#[rustc_scalable_vector(4)] +pub struct svint32_t(i32); + +#[cfg(aarch64)] +impl Copy for svint32_t {} + +#[cfg(aarch64)] +#[rustc_scalable_vector(16)] +pub struct svbool_t(bool); + +#[cfg(aarch64)] +impl Copy for svbool_t {} + +#[cfg(aarch64)] +unsafe fn vector(x: svint32_t) { + asm!("/* {0} */", in(vreg) x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable + + asm!("/* {0} */", in(vreg_low16) x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable + + asm!("", in("z0") x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable +} + +#[cfg(aarch64)] +unsafe fn predicate(p: svbool_t) { + asm!("/* {0} */", in(preg) p); + //[aarch64]~^ ERROR register class `preg` can only be used as a clobber in stable + //[aarch64]~| ERROR type `svbool_t` cannot be used with this register class in stable +} + +#[cfg(loongarch)] #[repr(simd)] pub struct i8x16([i8; 16]); +#[cfg(loongarch)] impl Copy for i8x16 {} +#[cfg(loongarch)] unsafe fn main(x: i8x16) -> i8x16 { let y; asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); - //~^ ERROR register class `vreg` can only be used as a clobber in stable - //~| ERROR register class `vreg` can only be used as a clobber in stable - //~| ERROR type `i8x16` cannot be used with this register class in stable - //~| ERROR type `i8x16` cannot be used with this register class in stable + //[loongarch]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch]~| ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch]~| ERROR type `i8x16` cannot be used with this register class in stable + //[loongarch]~| ERROR type `i8x16` cannot be used with this register class in stable y } diff --git a/tests/ui/parser/recover/array-type-no-semi.stderr b/tests/ui/parser/recover/array-type-no-semi.stderr index 0af085140223e..01fcc3766f635 100644 --- a/tests/ui/parser/recover/array-type-no-semi.stderr +++ b/tests/ui/parser/recover/array-type-no-semi.stderr @@ -68,7 +68,7 @@ LL | let c: [i32, x]; help: consider using `const` instead of `let` | LL - let x = 5; -LL + const x: /* Type */ = 5; +LL + const x: usize = 5; | error[E0423]: cannot find value `i32` in this scope diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index c068818fdc9a5..0499531158844 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -12,8 +12,6 @@ print-type-size variant `Panicked`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes print-type-size field `.value`: 8192 bytes -print-type-size type: `std::mem::MaybeDangling<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes -print-type-size field `.0`: 8192 bytes print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 8192 bytes print-type-size field `.uninit`: 0 bytes @@ -53,8 +51,6 @@ print-type-size type: `std::ptr::NonNull>`: 8 bytes, alig print-type-size field `.pointer`: 8 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeDangling<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes -print-type-size field `.0`: 1 bytes print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout index b51beb514ba80..4ce1ce46f6e82 100644 --- a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout +++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout @@ -11,8 +11,6 @@ print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `std::mem::ManuallyDrop`: 4 bytes, alignment: 4 bytes print-type-size field `.value`: 4 bytes -print-type-size type: `std::mem::MaybeDangling`: 4 bytes, alignment: 4 bytes -print-type-size field `.0`: 4 bytes print-type-size type: `std::mem::MaybeUninit`: 4 bytes, alignment: 4 bytes print-type-size variant `MaybeUninit`: 4 bytes print-type-size field `.uninit`: 0 bytes diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr index e2cecf9973b8b..91d6a5d79d0ac 100644 --- a/tests/ui/repeat-expr/repeat_count.stderr +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -7,7 +7,7 @@ LL | let a = [0; n]; help: consider using `const` instead of `let` | LL - let n = 1; -LL + const n: /* Type */ = 1; +LL + const n: usize = 1; | error[E0308]: mismatched types diff --git a/tests/ui/splat/splat-invalid.rs b/tests/ui/splat/splat-invalid.rs index a9586b056d8e7..9a0101636a8b0 100644 --- a/tests/ui/splat/splat-invalid.rs +++ b/tests/ui/splat/splat-invalid.rs @@ -61,4 +61,27 @@ impl FooTrait for Foo { fn no_splat(#[rustc_splat] _: (u32, f64)) {} //~ ERROR method `no_splat` has an incompatible type for trait } -fn main() {} +#[rustfmt::skip] +fn main() { + let multisplat_fn_bad_: + fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat_fn_bad; + //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list + let multisplat_arg_bad_: fn( + #[rustc_splat] + #[rustc_splat] + (u32, i8), + ) = multisplat_arg_bad; + let multisplat_arg_fn_bad_: fn( + #[rustc_splat] + //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list + #[rustc_splat] + (u32, i8), + #[rustc_splat] (u32, i8), + ) = multisplat_arg_fn_bad; + + let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; + //~^ ERROR `...` and `#[rustc_splat]` are not allowed in the same function argument list + let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + //~^ ERROR `...` must be the last argument of a C-variadic function + //~| ERROR `...` and `#[rustc_splat]` are not allowed in the same function argument list +} diff --git a/tests/ui/splat/splat-invalid.stderr b/tests/ui/splat/splat-invalid.stderr index 771556d3e91a9..f1c492bd3e37e 100644 --- a/tests/ui/splat/splat-invalid.stderr +++ b/tests/ui/splat/splat-invalid.stderr @@ -87,6 +87,50 @@ LL | fn splat_variadic4(..., #[rustc_splat] (_a, _b): (u32, i8)) {} | = help: remove `#[rustc_splat]` or remove `...` +error: multiple `#[rustc_splat]`s are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:67:12 + | +LL | fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat_fn_bad; + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` from all but one argument + +error: multiple `#[rustc_splat]`s are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:75:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ +LL | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ +LL | (u32, i8), +LL | #[rustc_splat] (u32, i8), + | ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` from all but one argument + +error: `...` and `#[rustc_splat]` are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:82:47 + | +LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; + | ^^^^^^^^^^^^^^ ^^^ + | + = help: remove `#[rustc_splat]` or remove `...` + +error: `...` must be the last argument of a C-variadic function + --> $DIR/splat-invalid.rs:84:48 + | +LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + | ^^^ + +error: `...` and `#[rustc_splat]` are not allowed in the same function argument list + --> $DIR/splat-invalid.rs:84:48 + | +LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + | ^^^ ^^^^^^^^^^^^^^ + | + = help: remove `#[rustc_splat]` or remove `...` + error: multiple `rustc_splat` attributes --> $DIR/splat-invalid.rs:11:5 | @@ -139,6 +183,6 @@ LL | fn no_splat(_: (u32, f64)); = note: expected signature `fn((_, _))` found signature `fn(#[rustc_splat] (_, _))` -error: aborting due to 14 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/splat/splat-non-tuple.rs b/tests/ui/splat/splat-non-tuple.rs index e1b115432d788..a11d94a1fbb99 100644 --- a/tests/ui/splat/splat-non-tuple.rs +++ b/tests/ui/splat/splat-non-tuple.rs @@ -84,6 +84,11 @@ fn main() { primitive_arg(1u32); enum_arg(NotATuple::A(1u32)); + #[rustfmt::skip] + let primitive_arg_: fn(#[rustc_splat] u32) = primitive_arg; + primitive_arg_(1u32); + //~^ ERROR cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a u32 + let foo = Foo; struct_arg(foo); foo.tuple_2_self((1u32, 2i8)); diff --git a/tests/ui/splat/splat-non-tuple.stderr b/tests/ui/splat/splat-non-tuple.stderr index d51968eac80c0..b92c257b9b021 100644 --- a/tests/ui/splat/splat-non-tuple.stderr +++ b/tests/ui/splat/splat-non-tuple.stderr @@ -30,6 +30,12 @@ LL | fn enum_arg(#[rustc_splat] y: NotATuple) {} LL | enum_arg(NotATuple::A(1u32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a u32 (u32) + --> $DIR/splat-non-tuple.rs:89:5 + | +LL | primitive_arg_(1u32); + | ^^^^^^^^^^^^^^^^^^^^ + error[E0277]: cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a Foo (Foo) --> $DIR/splat-non-tuple.rs:25:33 | @@ -48,7 +54,7 @@ LL | fn tuple_struct_arg(#[rustc_splat] z: TupleStruct) {} LL | tuple_struct_arg(tuple_struct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0053, E0277. For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index 16e3676aa6503..b0b1f78cb28b2 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -7,13 +7,18 @@ LL | use core::unicode::UNICODE_VERSION; = help: add `#![feature(unicode_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: use of deprecated module `std::intrinsics`: import this function via `std::mem` instead - --> $DIR/accidental-stable-in-unstable.rs:10:23 +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidental-stable-in-unstable.rs:10:5 | LL | use core::intrinsics::transmute; // depended upon by rand_core - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default +help: import this function via the `mem` module instead + | +LL - use core::intrinsics::transmute; // depended upon by rand_core +LL + use core::mem::transmute; // depended upon by rand_core + | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed new file mode 100644 index 0000000000000..41917c65f5215 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed @@ -0,0 +1,39 @@ +//@ run-rustfix +#![crate_type = "lib"] +#![allow(unnecessary_transmutes, unused_imports)] +#![deny(deprecated)] + +extern crate core; + +use std::mem::transmute as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::ptr::copy as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use std::ptr::copy_nonoverlapping as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::ptr::write_bytes as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + +use core::ptr::{ + copy as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + copy_nonoverlapping as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + write_bytes as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +}; + +pub fn what() { + unsafe { + let value = 42_u8; + let mut dst = 0; + let _ = std::mem::transmute::(value); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::ptr::copy(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + std::ptr::write_bytes(&mut dst, value, 1) + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + } +} diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs new file mode 100644 index 0000000000000..189927e9e8989 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs @@ -0,0 +1,39 @@ +//@ run-rustfix +#![crate_type = "lib"] +#![allow(unnecessary_transmutes, unused_imports)] +#![deny(deprecated)] + +extern crate core; + +use std::intrinsics::transmute as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::intrinsics::copy as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use std::intrinsics::copy_nonoverlapping as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +use core::intrinsics::write_bytes as _; +//~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + +use core::intrinsics::{ + copy as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + copy_nonoverlapping as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + write_bytes as _, + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +}; + +pub fn what() { + unsafe { + let value = 42_u8; + let mut dst = 0; + let _ = std::intrinsics::transmute::(value); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::intrinsics::copy(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + std::intrinsics::write_bytes(&mut dst, value, 1) + //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + } +} diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr new file mode 100644 index 0000000000000..645437a306f74 --- /dev/null +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr @@ -0,0 +1,139 @@ +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:8:5 + | +LL | use std::intrinsics::transmute as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/accidentally-stable-intrinsics.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ +help: import this function via the `mem` module instead + | +LL - use std::intrinsics::transmute as _; +LL + use std::mem::transmute as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:10:5 + | +LL | use core::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::copy as _; +LL + use core::ptr::copy as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:12:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:14:5 + | +LL | use core::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::write_bytes as _; +LL + use core::ptr::write_bytes as _; + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:18:5 + | +LL | copy as _, + | ^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:20:5 + | +LL | copy_nonoverlapping as _, + | ^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:22:5 + | +LL | write_bytes as _, + | ^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:30:17 + | +LL | let _ = std::intrinsics::transmute::(value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `mem` module instead + | +LL - let _ = std::intrinsics::transmute::(value); +LL + let _ = std::mem::transmute::(value); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:32:9 + | +LL | core::intrinsics::copy(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy(&value, &mut dst, 1); +LL + core::ptr::copy(&value, &mut dst, 1); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:34:9 + | +LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); +LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + | + +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:36:9 + | +LL | std::intrinsics::write_bytes(&mut dst, value, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: import this function via the `ptr` module instead + | +LL - std::intrinsics::write_bytes(&mut dst, value, 1) +LL + std::ptr::write_bytes(&mut dst, value, 1) + | + +error: aborting due to 11 previous errors + diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index 5baa0fda94037..eaa3ad9b830b4 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -1,9 +1,9 @@ -// Test for new `#[rustc_allowed_through_unstable_modules]` attribute +// Test for `#[rustc_allowed_through_unstable_modules]` attribute // //@ aux-build:allowed-through-unstable-core.rs #![crate_type = "lib"] extern crate allowed_through_unstable_core; -use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead +use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated import through accidentally stabilized module `unstable_module` use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 3098f1c961f95..160dd4d4babff 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -1,10 +1,15 @@ -warning: use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead - --> $DIR/allowed-through-unstable.rs:8:53 +warning: use of deprecated import through accidentally stabilized module `unstable_module` + --> $DIR/allowed-through-unstable.rs:8:5 | LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default +help: use the new path instead + | +LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; +LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnstable; + | error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/allowed-through-unstable.rs:9:36 diff --git a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs index 23c722d6e8eba..5f7e344aece60 100644 --- a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs +++ b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs @@ -6,7 +6,10 @@ #[unstable(feature = "unstable_test_feature", issue = "1")] pub mod unstable_module { #[stable(feature = "stable_test_feature", since = "1.2.0")] - #[rustc_allowed_through_unstable_modules = "use the new path instead"] + #[rustc_allowed_through_unstable_modules( + message= "use the new path instead", + module = "stable", + )] pub trait OldStableTraitAllowedThoughUnstable {} #[stable(feature = "stable_test_feature", since = "1.2.0")]