diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 6542cbf4ba2b3..3157b18b63515 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -110,6 +110,22 @@ pub enum DeprecatedSince { Err, } +#[derive( + Copy, + Debug, + Eq, + PartialEq, + Encodable, + Decodable, + Clone, + HashStable_Generic, + PrintAttribute +)] +pub enum CoverageStatus { + On, + Off, +} + impl Deprecation { /// Whether an item marked with #[deprecated(since = "X")] is currently /// deprecated (i.e., whether X is not greater than the current rustc @@ -274,6 +290,9 @@ pub enum AttributeKind { /// Represents `#[const_trait]`. ConstTrait(Span), + /// Represents `#[coverage]`. + Coverage(Span, CoverageStatus), + ///Represents `#[rustc_deny_explicit_impl]`. DenyExplicitImpl(Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 6b54827c473b8..8a3eb2ac845a3 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -28,6 +28,7 @@ impl AttributeKind { ConstStability { .. } => Yes, ConstStabilityIndirect => No, ConstTrait(..) => No, + Coverage(..) => No, DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotImplementViaObject(..) => No, diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 34d9b04834825..3e542771d58c9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy}; +use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy}; use rustc_feature::{AttributeTemplate, template}; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; @@ -52,6 +52,45 @@ impl NoArgsAttributeParser for ColdParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold; } +pub(crate) struct CoverageParser; + +impl SingleAttributeParser for CoverageParser { + const PATH: &[Symbol] = &[sym::coverage]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let Some(args) = args.list() else { + cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]); + return None; + }; + + let Some(arg) = args.single() else { + cx.expected_single_argument(args.span); + return None; + }; + + let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]); + + let Some(arg) = arg.meta_item() else { + fail_incorrect_argument(args.span); + return None; + }; + + let status = match arg.path().word_sym() { + Some(sym::off) => CoverageStatus::Off, + Some(sym::on) => CoverageStatus::On, + None | Some(_) => { + fail_incorrect_argument(arg.span()); + return None; + } + }; + + Some(AttributeKind::Coverage(cx.attr_span, status)) + } +} + pub(crate) struct ExportNameParser; impl SingleAttributeParser for ExportNameParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 1449680e35b81..4d692d9562c1e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -17,8 +17,9 @@ use crate::attributes::allow_unstable::{ AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, }; use crate::attributes::codegen_attrs::{ - ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser, - OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser, + ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, + OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, + UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -139,6 +140,7 @@ attribute_parsers!( // tidy-alphabetical-end // tidy-alphabetical-start + Single, Single, Single, Single, @@ -452,6 +454,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, + list: false, + }, + }) + } + + pub(crate) fn expected_specific_argument_and_list( + &self, + span: Span, + possibilities: Vec<&'static str>, + ) -> ErrorGuaranteed { + self.emit_err(AttributeParseError { + span, + attr_span: self.attr_span, + template: self.template.clone(), + attribute: self.attr_path.clone(), + reason: AttributeParseErrorReason::ExpectedSpecificArgument { + possibilities, + strings: false, + list: true, }, }) } @@ -469,6 +490,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: true, + list: false, }, }) } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 5b0bf0e6662f0..9a400e0fe1042 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -533,7 +533,9 @@ pub(crate) struct LinkOrdinalOutOfRange { pub(crate) enum AttributeParseErrorReason { ExpectedNoArgs, - ExpectedStringLiteral { byte_string: Option }, + ExpectedStringLiteral { + byte_string: Option, + }, ExpectedIntegerLiteral, ExpectedAtLeastOneArgument, ExpectedSingleArgument, @@ -541,7 +543,12 @@ pub(crate) enum AttributeParseErrorReason { UnexpectedLiteral, ExpectedNameValue(Option), DuplicateKey(Symbol), - ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool }, + ExpectedSpecificArgument { + possibilities: Vec<&'static str>, + strings: bool, + /// Should we tell the user to write a list when they didn't? + list: bool, + }, } pub(crate) struct AttributeParseError { @@ -615,7 +622,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { format!("expected this to be of the form `{name} = \"...\"`"), ); } - AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => { + AttributeParseErrorReason::ExpectedSpecificArgument { + possibilities, + strings, + list: false, + } => { let quote = if strings { '"' } else { '`' }; match possibilities.as_slice() { &[] => {} @@ -641,6 +652,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { } } } + AttributeParseErrorReason::ExpectedSpecificArgument { + possibilities, + strings, + list: true, + } => { + let quote = if strings { '"' } else { '`' }; + match possibilities.as_slice() { + &[] => {} + &[x] => { + diag.span_label( + self.span, + format!( + "this attribute is only valid with {quote}{x}{quote} as an argument" + ), + ); + } + [first, second] => { + diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); + } + [first @ .., second_to_last, last] => { + let mut res = String::new(); + for i in first { + res.push_str(&format!("{quote}{i}{quote}, ")); + } + res.push_str(&format!( + "{quote}{second_to_last}{quote} or {quote}{last}{quote}" + )); + + diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}")); + } + } + } } let suggestions = self.template.suggestions(false, &name); diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index a98e9c6d1c7fc..dd8f0e46a0e03 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy( methods: Vec::new(), associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push); @@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty( methods: Vec::new(), associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push); @@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty( methods: Vec::new(), associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push); @@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty( methods: Vec::new(), associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 69f8c273797e4..3c78f53c5cb0a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand_ext(cx, mitem, item, push, is_simple) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index eca79e4dc4897..29d531219a69c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand_ext(cx, mitem, item, push, true) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 1ed44c20bc61e..0e1ecf3118ac3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index b1d950b8d89de..990835fa27739 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq( methods: Vec::new(), associated_types: Vec::new(), is_const: false, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; structural_trait_def.expand(cx, mitem, item, push); @@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq( methods, associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 0a076dd670b34..f5d262ece36e3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord( methods: vec![partial_cmp_def], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 8ab21986e68a0..1d63ce7d5fd27 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 1fe567e23f455..b4e2d27fed333 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c55a9e73e3822..b24e55637613a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -181,9 +181,11 @@ use std::{iter, vec}; pub(crate) use StaticFields::*; pub(crate) use SubstructureFields::*; use rustc_ast::ptr::P; +use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind}; +use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ - self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, - Generics, Mutability, PatKind, VariantData, + self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, + GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData, }; use rustc_attr_data_structures::{AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; @@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> { pub associated_types: Vec<(Ident, Ty)>, pub is_const: bool, + + pub is_staged_api_crate: bool, } pub(crate) struct MethodDef<'a> { @@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let path = cx.path_all(self.span, false, vec![type_ident], self_params); let self_type = cx.ty_path(path); + let rustc_const_unstable = + cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); + + let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),]; + + // Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd, + // Other crates don't need stability attributes, so adding them is not useful, but libcore needs them + // on all const trait impls. + if self.is_const && self.is_staged_api_crate { + attrs.push( + cx.attr_nested( + rustc_ast::AttrItem { + unsafety: Safety::Default, + path: rustc_const_unstable, + args: AttrArgs::Delimited(DelimArgs { + dspan: DelimSpan::from_single(self.span), + delim: rustc_ast::token::Delimiter::Parenthesis, + tokens: [ + TokenKind::Ident(sym::feature, IdentIsRaw::No), + TokenKind::Eq, + TokenKind::lit(LitKind::Str, sym::derive_const, None), + TokenKind::Comma, + TokenKind::Ident(sym::issue, IdentIsRaw::No), + TokenKind::Eq, + TokenKind::lit(LitKind::Str, sym::derive_const_issue, None), + ] + .into_iter() + .map(|kind| { + TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone) + }) + .collect(), + }), + tokens: None, + }, + self.span, + ), + ) + } - let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),]; let opt_trait_ref = Some(trait_ref); cx.item( diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 6e6dbe19e4d1a..78534449895c2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash( }], associated_types: Vec::new(), is_const, + is_staged_api_crate: cx.ecfg.features.staged_api(), }; hash_trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs index ad46e18c11c0d..b7491b7e522f3 100644 --- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs +++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs @@ -11,6 +11,12 @@ #[derive(Copy, Clone, PartialEq, Debug)] struct f32x4(pub [f32; 4]); +impl f32x4 { + fn into_array(self) -> [f32; 4] { + unsafe { std::mem::transmute(self) } + } +} + use std::intrinsics::simd::*; fn main() { @@ -29,22 +35,22 @@ fn main() { unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); - assert_eq!(min0, min1); + assert_eq!(min0.into_array(), min1.into_array()); let e = f32x4([1.0, 1.0, 3.0, 3.0]); - assert_eq!(min0, e); + assert_eq!(min0.into_array(), e.into_array()); let minn = simd_fmin(x, n); - assert_eq!(minn, x); + assert_eq!(minn.into_array(), x.into_array()); let minn = simd_fmin(y, n); - assert_eq!(minn, y); + assert_eq!(minn.into_array(), y.into_array()); let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); - assert_eq!(max0, max1); + assert_eq!(max0.into_array(), max1.into_array()); let e = f32x4([2.0, 2.0, 4.0, 4.0]); - assert_eq!(max0, e); + assert_eq!(max0.into_array(), e.into_array()); let maxn = simd_fmax(x, n); - assert_eq!(maxn, x); + assert_eq!(maxn.into_array(), x.into_array()); let maxn = simd_fmax(y, n); - assert_eq!(maxn, y); + assert_eq!(maxn.into_array(), y.into_array()); } } diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 246bd3104ec41..86602c6b2a3fd 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -348,7 +348,8 @@ fn main() { struct V([f64; 2]); let f = V([0.0, 1.0]); - let _a = f.0[0]; + let fp = (&raw const f) as *const [f64; 2]; + let _a = (unsafe { &*fp })[0]; stack_val_align(); } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index b0d191528a891..13e3aa88f271a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -329,20 +329,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let offset = self.layout.fields.offset(i); if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) { - if let BackendRepr::SimdVector { count, .. } = self.layout.backend_repr - && let BackendRepr::Memory { sized: true } = field.backend_repr - && count.is_power_of_two() - { - assert_eq!(field.size, self.layout.size); - // This is being deprecated, but for now stdarch still needs it for - // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]); - let place = PlaceRef::alloca(bx, field); - self.val.store(bx, place.val.with_type(self.layout)); - return bx.load_operand(place); - } else { - // Part of https://github.com/rust-lang/compiler-team/issues/838 - bug!("Non-ref type {self:?} cannot project to ref field type {field:?}"); - } + // Part of https://github.com/rust-lang/compiler-team/issues/838 + span_bug!( + fx.mir.span, + "Non-ref type {self:?} cannot project to ref field type {field:?}", + ); } let val = if field.is_zst() { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1849038545556..f3ed604210565 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1237,9 +1237,55 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option bool { + let s1 = s1.replace('-', "_"); + let s2 = s2.replace('-', "_"); + s1 == s2 + } + + if let Some(name) = matches.opt_str("o") + && let Some(suspect) = args.iter().find(|arg| arg.starts_with("-o") && *arg != "-o") + { + let filename = suspect.strip_prefix("-").unwrap_or(suspect); + let optgroups = config::rustc_optgroups(); + let fake_args = ["optimize", "o0", "o1", "o2", "o3", "ofast", "og", "os", "oz"]; + + // Check if provided filename might be confusing in conjunction with `-o` flag, + // i.e. consider `-o{filename}` such as `-optimize` with `filename` being `ptimize`. + // There are high-value confusables, for example: + // - Long name of flags, e.g. `--out-dir` vs `-out-dir` + // - C compiler flag, e.g. `optimize`, `o0`, `o1`, `o2`, `o3`, `ofast`. + // - Codegen flags, e.g. `pt-level` of `-opt-level`. + if optgroups.iter().any(|option| eq_ignore_separators(option.long_name(), filename)) + || config::CG_OPTIONS.iter().any(|option| eq_ignore_separators(option.name(), filename)) + || fake_args.iter().any(|arg| eq_ignore_separators(arg, filename)) + { + early_dcx.early_warn( + "option `-o` has no space between flag name and value, which can be confusing", + ); + early_dcx.early_note(format!( + "output filename `-o {name}` is applied instead of a flag named `o{name}`" + )); + early_dcx.early_help(format!( + "insert a space between `-o` and `{name}` if this is intentional: `-o {name}`" + )); + } + } +} + fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { Input::File(file) => new_parser_from_file(&sess.psess, file, None), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 85683c1a03ff2..51d6e43ab6720 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -3,8 +3,8 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::literal; use rustc_ast::{ - self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp, - attr, token, tokenstream, + self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, + UnOp, attr, token, tokenstream, }; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; @@ -766,4 +766,10 @@ impl<'a> ExtCtxt<'a> { span, ) } + + // Builds an attribute fully manually. + pub fn attr_nested(&self, inner: AttrItem, span: Span) -> ast::Attribute { + let g = &self.sess.psess.attr_id_generator; + attr::mk_attr_from_item(g, inner, None, ast::AttrStyle::Outer, span) + } } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a20becbe7e843..e38ca9e80cea9 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -158,7 +158,7 @@ hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be imp hir_analysis_drop_impl_negative = negative `Drop` impls are not supported hir_analysis_drop_impl_on_wrong_item = - the `Drop` trait may only be implemented for local structs, enums, and unions + the `{$trait_}` trait may only be implemented for local structs, enums, and unions .label = must be a struct, enum, or union in the current crate hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 8356a0af63c35..27948f50a4ad5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -37,6 +37,7 @@ pub(super) fn check_trait<'tcx>( let lang_items = tcx.lang_items(); let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header }; checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?; + checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?; checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?; checker.check(lang_items.const_param_ty_trait(), |checker| { visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy) @@ -83,7 +84,10 @@ fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaran let impl_ = tcx.hir_expect_item(impl_did).expect_impl(); - Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span })) + Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { + span: impl_.self_ty.span, + trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id), + })) } fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index eb65050c17c78..fbd21f8b10003 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -205,6 +205,7 @@ pub(crate) struct DropImplOnWrongItem { #[primary_span] #[label] pub span: Span, + pub trait_: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index ccf76dc710874..986c001de5e80 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,3 +1,4 @@ +use rustc_attr_data_structures::{AttributeKind, CoverageStatus, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind}; @@ -5,7 +6,6 @@ use rustc_middle::mir::{Body, Statement, StatementKind}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; use rustc_span::def_id::LocalDefId; -use rustc_span::sym; use tracing::trace; use crate::coverage::counters::node_flow::make_node_counters; @@ -58,26 +58,20 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// Query implementation for `coverage_attr_on`. fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // Check for annotations directly on this def. - if let Some(attr) = tcx.get_attr(def_id, sym::coverage) { - match attr.meta_item_list().as_deref() { - Some([item]) if item.has_name(sym::off) => return false, - Some([item]) if item.has_name(sym::on) => return true, - Some(_) | None => { - // Other possibilities should have been rejected by `rustc_parse::validate_attr`. - // Use `span_delayed_bug` to avoid an ICE in failing builds (#127880). - tcx.dcx().span_delayed_bug(attr.span(), "unexpected value of coverage attribute"); - } + if let Some(coverage_status) = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Coverage(_, status) => status) + { + *coverage_status == CoverageStatus::On + } else { + match tcx.opt_local_parent(def_id) { + // Check the parent def (and so on recursively) until we find an + // enclosing attribute or reach the crate root. + Some(parent) => tcx.coverage_attr_on(parent), + // We reached the crate root without seeing a coverage attribute, so + // allow coverage instrumentation by default. + None => true, } } - - match tcx.opt_local_parent(def_id) { - // Check the parent def (and so on recursively) until we find an - // enclosing attribute or reach the crate root. - Some(parent) => tcx.coverage_attr_on(parent), - // We reached the crate root without seeing a coverage attribute, so - // allow coverage instrumentation by default. - None => true, - } } /// Query implementation for `coverage_ids_info`. diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6b11706d2b55f..07717b7c06948 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -105,7 +105,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; -use rustc_span::def_id::DefId; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; @@ -130,7 +129,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { - let opaque = state.new_opaque(); + let opaque = state.new_opaque(body.local_decls[local].ty); state.assign(local, opaque); } @@ -155,22 +154,6 @@ newtype_index! { struct VnIndex {} } -/// Computing the aggregate's type can be quite slow, so we only keep the minimal amount of -/// information to reconstruct it when needed. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -enum AggregateTy<'tcx> { - /// Invariant: this must not be used for an empty array. - Array, - Tuple, - Def(DefId, ty::GenericArgsRef<'tcx>), - RawPtr { - /// Needed for cast propagation. - data_pointer_ty: Ty<'tcx>, - /// The data pointer can be anything thin, so doesn't determine the output. - output_pointer_ty: Ty<'tcx>, - }, -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] enum AddressKind { Ref(BorrowKind), @@ -193,7 +176,14 @@ enum Value<'tcx> { }, /// An aggregate value, either tuple/closure/struct/enum. /// This does not contain unions, as we cannot reason with the value. - Aggregate(AggregateTy<'tcx>, VariantIdx, Vec), + Aggregate(VariantIdx, Vec), + /// A raw pointer aggregate built from a thin pointer and metadata. + RawPtr { + /// Thin pointer component. This is field 0 in MIR. + pointer: VnIndex, + /// Metadata component. This is field 1 in MIR. + metadata: VnIndex, + }, /// This corresponds to a `[value; count]` expression. Repeat(VnIndex, ty::Const<'tcx>), /// The address of a place. @@ -206,7 +196,7 @@ enum Value<'tcx> { // Extractions. /// This is the *value* obtained by projecting another value. - Projection(VnIndex, ProjectionElem>), + Projection(VnIndex, ProjectionElem), /// Discriminant of the given value. Discriminant(VnIndex), /// Length of an array or slice. @@ -219,8 +209,6 @@ enum Value<'tcx> { Cast { kind: CastKind, value: VnIndex, - from: Ty<'tcx>, - to: Ty<'tcx>, }, } @@ -228,12 +216,13 @@ struct VnState<'body, 'tcx> { tcx: TyCtxt<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, local_decls: &'body LocalDecls<'tcx>, + is_coroutine: bool, /// Value stored in each local. locals: IndexVec>, /// Locals that are assigned that value. // This vector does not hold all the values of `VnIndex` that we create. rev_locals: IndexVec>, - values: FxIndexSet>, + values: FxIndexSet<(Value<'tcx>, Ty<'tcx>)>, /// Values evaluated as constants if possible. evaluated: IndexVec>>, /// Counter to generate different values. @@ -265,6 +254,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { tcx, ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), local_decls, + is_coroutine: body.coroutine.is_some(), locals: IndexVec::from_elem(None, local_decls), rev_locals: IndexVec::with_capacity(num_values), values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), @@ -282,8 +272,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } #[instrument(level = "trace", skip(self), ret)] - fn insert(&mut self, value: Value<'tcx>) -> VnIndex { - let (index, new) = self.values.insert_full(value); + fn insert(&mut self, ty: Ty<'tcx>, value: Value<'tcx>) -> VnIndex { + let (index, new) = self.values.insert_full((value, ty)); let index = VnIndex::from_usize(index); if new { // Grow `evaluated` and `rev_locals` here to amortize the allocations. @@ -305,20 +295,33 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { /// Create a new `Value` for which we have no information at all, except that it is distinct /// from all the others. #[instrument(level = "trace", skip(self), ret)] - fn new_opaque(&mut self) -> VnIndex { + fn new_opaque(&mut self, ty: Ty<'tcx>) -> VnIndex { let value = Value::Opaque(self.next_opaque()); - self.insert(value) + self.insert(ty, value) } /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> VnIndex { + let pty = place.ty(self.local_decls, self.tcx).ty; + let ty = match kind { + AddressKind::Ref(bk) => { + Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, pty, bk.to_mutbl_lossy()) + } + AddressKind::Address(mutbl) => Ty::new_ptr(self.tcx, pty, mutbl.to_mutbl_lossy()), + }; let value = Value::Address { place, kind, provenance: self.next_opaque() }; - self.insert(value) + self.insert(ty, value) } + #[inline] fn get(&self, index: VnIndex) -> &Value<'tcx> { - self.values.get_index(index.as_usize()).unwrap() + &self.values.get_index(index.as_usize()).unwrap().0 + } + + #[inline] + fn ty(&self, index: VnIndex) -> Ty<'tcx> { + self.values.get_index(index.as_usize()).unwrap().1 } /// Record that `local` is assigned `value`. `local` must be SSA. @@ -341,29 +344,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { debug_assert_ne!(disambiguator, 0); disambiguator }; - self.insert(Value::Constant { value, disambiguator }) + self.insert(value.ty(), Value::Constant { value, disambiguator }) } fn insert_bool(&mut self, flag: bool) -> VnIndex { // Booleans are deterministic. let value = Const::from_bool(self.tcx, flag); debug_assert!(value.is_deterministic()); - self.insert(Value::Constant { value, disambiguator: 0 }) + self.insert(self.tcx.types.bool, Value::Constant { value, disambiguator: 0 }) } - fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex { + fn insert_scalar(&mut self, ty: Ty<'tcx>, scalar: Scalar) -> VnIndex { // Scalars are deterministic. let value = Const::from_scalar(self.tcx, scalar, ty); debug_assert!(value.is_deterministic()); - self.insert(Value::Constant { value, disambiguator: 0 }) + self.insert(ty, Value::Constant { value, disambiguator: 0 }) } - fn insert_tuple(&mut self, values: Vec) -> VnIndex { - self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values)) + fn insert_tuple(&mut self, ty: Ty<'tcx>, values: Vec) -> VnIndex { + self.insert(ty, Value::Aggregate(VariantIdx::ZERO, values)) } - fn insert_deref(&mut self, value: VnIndex) -> VnIndex { - let value = self.insert(Value::Projection(value, ProjectionElem::Deref)); + fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { + let value = self.insert(ty, Value::Projection(value, ProjectionElem::Deref)); self.derefs.push(value); value } @@ -371,14 +374,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn invalidate_derefs(&mut self) { for deref in std::mem::take(&mut self.derefs) { let opaque = self.next_opaque(); - *self.values.get_index_mut2(deref.index()).unwrap() = Value::Opaque(opaque); + self.values.get_index_mut2(deref.index()).unwrap().0 = Value::Opaque(opaque); } } #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { use Value::*; + let ty = self.ty(value); + // Avoid computing layouts inside a coroutine, as that can cause cycles. + let ty = if !self.is_coroutine || ty.is_scalar() { + self.ecx.layout_of(ty).ok()? + } else { + return None; + }; let op = match *self.get(value) { + _ if ty.is_zst() => ImmTy::uninit(ty).into(), + Opaque(_) => return None, // Do not bother evaluating repeat expressions. This would uselessly consume memory. Repeat(..) => return None, @@ -386,42 +398,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Constant { ref value, disambiguator: _ } => { self.ecx.eval_mir_constant(value, DUMMY_SP, None).discard_err()? } - Aggregate(kind, variant, ref fields) => { + Aggregate(variant, ref fields) => { let fields = fields .iter() .map(|&f| self.evaluated[f].as_ref()) .collect::>>()?; - let ty = match kind { - AggregateTy::Array => { - assert!(fields.len() > 0); - Ty::new_array(self.tcx, fields[0].layout.ty, fields.len() as u64) - } - AggregateTy::Tuple => { - Ty::new_tup_from_iter(self.tcx, fields.iter().map(|f| f.layout.ty)) - } - AggregateTy::Def(def_id, args) => { - self.tcx.type_of(def_id).instantiate(self.tcx, args) - } - AggregateTy::RawPtr { output_pointer_ty, .. } => output_pointer_ty, - }; - let variant = if ty.is_enum() { Some(variant) } else { None }; - let ty = self.ecx.layout_of(ty).ok()?; - if ty.is_zst() { - ImmTy::uninit(ty).into() - } else if matches!(kind, AggregateTy::RawPtr { .. }) { - // Pointers don't have fields, so don't `project_field` them. - let data = self.ecx.read_pointer(fields[0]).discard_err()?; - let meta = if fields[1].layout.is_zst() { - MemPlaceMeta::None - } else { - MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).discard_err()?) - }; - let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx); - ImmTy::from_immediate(ptr_imm, ty).into() - } else if matches!( - ty.backend_repr, - BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..) - ) { + let variant = if ty.ty.is_enum() { Some(variant) } else { None }; + if matches!(ty.backend_repr, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) + { let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?; let variant_dest = if let Some(variant) = variant { self.ecx.project_downcast(&dest, variant).discard_err()? @@ -446,32 +430,46 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return None; } } + RawPtr { pointer, metadata } => { + let pointer = self.evaluated[pointer].as_ref()?; + let metadata = self.evaluated[metadata].as_ref()?; + + // Pointers don't have fields, so don't `project_field` them. + let data = self.ecx.read_pointer(pointer).discard_err()?; + let meta = if metadata.layout.is_zst() { + MemPlaceMeta::None + } else { + MemPlaceMeta::Meta(self.ecx.read_scalar(metadata).discard_err()?) + }; + let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx); + ImmTy::from_immediate(ptr_imm, ty).into() + } Projection(base, elem) => { - let value = self.evaluated[base].as_ref()?; + let base = self.evaluated[base].as_ref()?; let elem = match elem { ProjectionElem::Deref => ProjectionElem::Deref, ProjectionElem::Downcast(name, read_variant) => { ProjectionElem::Downcast(name, read_variant) } - ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty), + ProjectionElem::Field(f, ()) => ProjectionElem::Field(f, ty.ty), ProjectionElem::ConstantIndex { offset, min_length, from_end } => { ProjectionElem::ConstantIndex { offset, min_length, from_end } } ProjectionElem::Subslice { from, to, from_end } => { ProjectionElem::Subslice { from, to, from_end } } - ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty), - ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty), - ProjectionElem::UnwrapUnsafeBinder(ty) => { - ProjectionElem::UnwrapUnsafeBinder(ty) + ProjectionElem::OpaqueCast(()) => ProjectionElem::OpaqueCast(ty.ty), + ProjectionElem::Subtype(()) => ProjectionElem::Subtype(ty.ty), + ProjectionElem::UnwrapUnsafeBinder(()) => { + ProjectionElem::UnwrapUnsafeBinder(ty.ty) } // This should have been replaced by a `ConstantIndex` earlier. ProjectionElem::Index(_) => return None, }; - self.ecx.project(value, elem).discard_err()? + self.ecx.project(base, elem).discard_err()? } - Address { place, kind, provenance: _ } => { + Address { place, kind: _, provenance: _ } => { if !place.is_indirect_first_projection() { return None; } @@ -487,19 +485,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { mplace = self.ecx.project(&mplace, proj).discard_err()?; } let pointer = mplace.to_ref(&self.ecx); - let ty = match kind { - AddressKind::Ref(bk) => Ty::new_ref( - self.tcx, - self.tcx.lifetimes.re_erased, - mplace.layout.ty, - bk.to_mutbl_lossy(), - ), - AddressKind::Address(mutbl) => { - Ty::new_ptr(self.tcx, mplace.layout.ty, mutbl.to_mutbl_lossy()) - } - }; - let layout = self.ecx.layout_of(ty).ok()?; - ImmTy::from_immediate(pointer, layout).into() + ImmTy::from_immediate(pointer, ty).into() } Discriminant(base) => { @@ -511,32 +497,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } Len(slice) => { let slice = self.evaluated[slice].as_ref()?; - let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let len = slice.len(&self.ecx).discard_err()?; - let imm = ImmTy::from_uint(len, usize_layout); - imm.into() + ImmTy::from_uint(len, ty).into() } - NullaryOp(null_op, ty) => { - let layout = self.ecx.layout_of(ty).ok()?; + NullaryOp(null_op, arg_ty) => { + let arg_layout = self.ecx.layout_of(arg_ty).ok()?; if let NullOp::SizeOf | NullOp::AlignOf = null_op - && layout.is_unsized() + && arg_layout.is_unsized() { return None; } let val = match null_op { - NullOp::SizeOf => layout.size.bytes(), - NullOp::AlignOf => layout.align.abi.bytes(), + NullOp::SizeOf => arg_layout.size.bytes(), + NullOp::AlignOf => arg_layout.align.abi.bytes(), NullOp::OffsetOf(fields) => self .ecx .tcx - .offset_of_subfield(self.typing_env(), layout, fields.iter()) + .offset_of_subfield(self.typing_env(), arg_layout, fields.iter()) .bytes(), NullOp::UbChecks => return None, NullOp::ContractChecks => return None, }; - let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); - let imm = ImmTy::from_uint(val, usize_layout); - imm.into() + ImmTy::from_uint(val, ty).into() } UnaryOp(un_op, operand) => { let operand = self.evaluated[operand].as_ref()?; @@ -552,30 +534,27 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let val = self.ecx.binary_op(bin_op, &lhs, &rhs).discard_err()?; val.into() } - Cast { kind, value, from: _, to } => match kind { + Cast { kind, value } => match kind { CastKind::IntToInt | CastKind::IntToFloat => { let value = self.evaluated[value].as_ref()?; let value = self.ecx.read_immediate(value).discard_err()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.int_to_int_or_float(&value, to).discard_err()?; + let res = self.ecx.int_to_int_or_float(&value, ty).discard_err()?; res.into() } CastKind::FloatToFloat | CastKind::FloatToInt => { let value = self.evaluated[value].as_ref()?; let value = self.ecx.read_immediate(value).discard_err()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.float_to_float_or_int(&value, to).discard_err()?; + let res = self.ecx.float_to_float_or_int(&value, ty).discard_err()?; res.into() } CastKind::Transmute => { let value = self.evaluated[value].as_ref()?; - let to = self.ecx.layout_of(to).ok()?; // `offset` for immediates generally only supports projections that match the // type of the immediate. However, as a HACK, we exploit that it can also do // limited transmutes: it only works between types with the same layout, and // cannot transmute pointers to integers. if value.as_mplace_or_imm().is_right() { - let can_transmute = match (value.layout.backend_repr, to.backend_repr) { + let can_transmute = match (value.layout.backend_repr, ty.backend_repr) { (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => { s1.size(&self.ecx) == s2.size(&self.ecx) && !matches!(s1.primitive(), Primitive::Pointer(..)) @@ -595,13 +574,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return None; } } - value.offset(Size::ZERO, to, &self.ecx).discard_err()? + value.offset(Size::ZERO, ty, &self.ecx).discard_err()? } CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => { let src = self.evaluated[value].as_ref()?; - let to = self.ecx.layout_of(to).ok()?; - let dest = self.ecx.allocate(to, MemoryKind::Stack).discard_err()?; - self.ecx.unsize_into(src, to, &dest.clone().into()).discard_err()?; + let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?; + self.ecx.unsize_into(src, ty, &dest.clone().into()).discard_err()?; self.ecx .alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()) .discard_err()?; @@ -610,15 +588,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { CastKind::FnPtrToPtr | CastKind::PtrToPtr => { let src = self.evaluated[value].as_ref()?; let src = self.ecx.read_immediate(src).discard_err()?; - let to = self.ecx.layout_of(to).ok()?; - let ret = self.ecx.ptr_to_ptr(&src, to).discard_err()?; + let ret = self.ecx.ptr_to_ptr(&src, ty).discard_err()?; ret.into() } CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer, _) => { let src = self.evaluated[value].as_ref()?; let src = self.ecx.read_immediate(src).discard_err()?; - let to = self.ecx.layout_of(to).ok()?; - ImmTy::from_immediate(*src, to).into() + ImmTy::from_immediate(*src, ty).into() } _ => return None, }, @@ -628,31 +604,30 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn project( &mut self, - place: PlaceRef<'tcx>, + place_ty: PlaceTy<'tcx>, value: VnIndex, proj: PlaceElem<'tcx>, from_non_ssa_index: &mut bool, - ) -> Option { + ) -> Option<(PlaceTy<'tcx>, VnIndex)> { + let projection_ty = place_ty.projection_ty(self.tcx, proj); let proj = match proj { ProjectionElem::Deref => { - let ty = place.ty(self.local_decls, self.tcx).ty; - if let Some(Mutability::Not) = ty.ref_mutability() - && let Some(pointee_ty) = ty.builtin_deref(true) - && pointee_ty.is_freeze(self.tcx, self.typing_env()) + if let Some(Mutability::Not) = place_ty.ty.ref_mutability() + && projection_ty.ty.is_freeze(self.tcx, self.typing_env()) { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - return Some(self.insert_deref(value)); + return Some((projection_ty, self.insert_deref(projection_ty.ty, value))); } else { return None; } } ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index), - ProjectionElem::Field(f, ty) => { - if let Value::Aggregate(_, _, fields) = self.get(value) { - return Some(fields[f.as_usize()]); + ProjectionElem::Field(f, _) => { + if let Value::Aggregate(_, fields) = self.get(value) { + return Some((projection_ty, fields[f.as_usize()])); } else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value) - && let Value::Aggregate(_, written_variant, fields) = self.get(*outer_value) + && let Value::Aggregate(written_variant, fields) = self.get(*outer_value) // This pass is not aware of control-flow, so we do not know whether the // replacement we are doing is actually reachable. We could be in any arm of // ``` @@ -670,14 +645,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // a downcast to an inactive variant. && written_variant == read_variant { - return Some(fields[f.as_usize()]); + return Some((projection_ty, fields[f.as_usize()])); } - ProjectionElem::Field(f, ty) + ProjectionElem::Field(f, ()) } ProjectionElem::Index(idx) => { if let Value::Repeat(inner, _) = self.get(value) { *from_non_ssa_index |= self.locals[idx].is_none(); - return Some(*inner); + return Some((projection_ty, *inner)); } let idx = self.locals[idx]?; ProjectionElem::Index(idx) @@ -685,15 +660,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ProjectionElem::ConstantIndex { offset, min_length, from_end } => { match self.get(value) { Value::Repeat(inner, _) => { - return Some(*inner); + return Some((projection_ty, *inner)); } - Value::Aggregate(AggregateTy::Array, _, operands) => { + Value::Aggregate(_, operands) => { let offset = if from_end { operands.len() - offset as usize } else { offset as usize }; - return operands.get(offset).copied(); + let value = operands.get(offset).copied()?; + return Some((projection_ty, value)); } _ => {} }; @@ -702,12 +678,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ProjectionElem::Subslice { from, to, from_end } => { ProjectionElem::Subslice { from, to, from_end } } - ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty), - ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty), - ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(ty), + ProjectionElem::OpaqueCast(_) => ProjectionElem::OpaqueCast(()), + ProjectionElem::Subtype(_) => ProjectionElem::Subtype(()), + ProjectionElem::UnwrapUnsafeBinder(_) => ProjectionElem::UnwrapUnsafeBinder(()), }; - Some(self.insert(Value::Projection(value, proj))) + let value = self.insert(projection_ty.ty, Value::Projection(value, proj)); + Some((projection_ty, value)) } /// Simplify the projection chain if we know better. @@ -769,6 +746,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Invariant: `value` holds the value up-to the `index`th projection excluded. let mut value = self.locals[place.local]?; + // Invariant: `value` has type `place_ty`, with optional downcast variant if needed. + let mut place_ty = PlaceTy::from_ty(self.local_decls[place.local].ty); let mut from_non_ssa_index = false; for (index, proj) in place.projection.iter().enumerate() { if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) @@ -786,8 +765,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { place_ref = PlaceRef { local, projection: &place.projection[index..] }; } - let base = PlaceRef { local: place.local, projection: &place.projection[..index] }; - value = self.project(base, value, proj, &mut from_non_ssa_index)?; + (place_ty, value) = self.project(place_ty, value, proj, &mut from_non_ssa_index)?; } if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) @@ -864,14 +842,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.simplify_place_projection(place, location); return Some(self.new_pointer(*place, AddressKind::Address(mutbl))); } - Rvalue::WrapUnsafeBinder(ref mut op, ty) => { + Rvalue::WrapUnsafeBinder(ref mut op, _) => { let value = self.simplify_operand(op, location)?; - Value::Cast { - kind: CastKind::Transmute, - value, - from: op.ty(self.local_decls, self.tcx), - to: ty, - } + Value::Cast { kind: CastKind::Transmute, value } } // Operations. @@ -896,18 +869,17 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Unsupported values. Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None, }; - debug!(?value); - Some(self.insert(value)) + let ty = rvalue.ty(self.local_decls, self.tcx); + Some(self.insert(ty, value)) } fn simplify_discriminant(&mut self, place: VnIndex) -> Option { - if let Value::Aggregate(enum_ty, variant, _) = *self.get(place) - && let AggregateTy::Def(enum_did, enum_args) = enum_ty - && let DefKind::Enum = self.tcx.def_kind(enum_did) + let enum_ty = self.ty(place); + if enum_ty.is_enum() + && let Value::Aggregate(variant, _) = *self.get(place) { - let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_args); let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_err()?; - return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty)); + return Some(self.insert_scalar(discr.layout.ty, discr.to_scalar())); } None @@ -915,12 +887,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn try_as_place_elem( &mut self, - proj: ProjectionElem>, + ty: Ty<'tcx>, + proj: ProjectionElem, loc: Location, ) -> Option> { Some(match proj { ProjectionElem::Deref => ProjectionElem::Deref, - ProjectionElem::Field(idx, ty) => ProjectionElem::Field(idx, ty), + ProjectionElem::Field(idx, ()) => ProjectionElem::Field(idx, ty), ProjectionElem::Index(idx) => { let Some(local) = self.try_as_local(idx, loc) else { return None; @@ -935,9 +908,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ProjectionElem::Subslice { from, to, from_end } } ProjectionElem::Downcast(symbol, idx) => ProjectionElem::Downcast(symbol, idx), - ProjectionElem::OpaqueCast(idx) => ProjectionElem::OpaqueCast(idx), - ProjectionElem::Subtype(idx) => ProjectionElem::Subtype(idx), - ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(ty), + ProjectionElem::OpaqueCast(()) => ProjectionElem::OpaqueCast(ty), + ProjectionElem::Subtype(()) => ProjectionElem::Subtype(ty), + ProjectionElem::UnwrapUnsafeBinder(()) => ProjectionElem::UnwrapUnsafeBinder(ty), }) } @@ -983,8 +956,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Allow introducing places with non-constant offsets, as those are still better than // reconstructing an aggregate. - if let Some(place) = self.try_as_place(copy_from_local_value, location, true) - && rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty + if self.ty(copy_from_local_value) == rvalue.ty(self.local_decls, self.tcx) + && let Some(place) = self.try_as_place(copy_from_local_value, location, true) { // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments. // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections. @@ -1004,9 +977,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { rvalue: &mut Rvalue<'tcx>, location: Location, ) -> Option { + let tcx = self.tcx; + let ty = rvalue.ty(self.local_decls, tcx); + let Rvalue::Aggregate(box ref kind, ref mut field_ops) = *rvalue else { bug!() }; - let tcx = self.tcx; if field_ops.is_empty() { let is_zst = match *kind { AggregateKind::Array(..) @@ -1021,87 +996,72 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { }; if is_zst { - let ty = rvalue.ty(self.local_decls, tcx); return Some(self.insert_constant(Const::zero_sized(ty))); } } - let (mut ty, variant_index) = match *kind { - AggregateKind::Array(..) => { - assert!(!field_ops.is_empty()); - (AggregateTy::Array, FIRST_VARIANT) - } - AggregateKind::Tuple => { + let fields: Vec<_> = field_ops + .iter_mut() + .map(|op| { + self.simplify_operand(op, location) + .unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx))) + }) + .collect(); + + let variant_index = match *kind { + AggregateKind::Array(..) | AggregateKind::Tuple => { assert!(!field_ops.is_empty()); - (AggregateTy::Tuple, FIRST_VARIANT) - } - AggregateKind::Closure(did, args) - | AggregateKind::CoroutineClosure(did, args) - | AggregateKind::Coroutine(did, args) => (AggregateTy::Def(did, args), FIRST_VARIANT), - AggregateKind::Adt(did, variant_index, args, _, None) => { - (AggregateTy::Def(did, args), variant_index) + FIRST_VARIANT } + AggregateKind::Closure(..) + | AggregateKind::CoroutineClosure(..) + | AggregateKind::Coroutine(..) => FIRST_VARIANT, + AggregateKind::Adt(_, variant_index, _, _, None) => variant_index, // Do not track unions. AggregateKind::Adt(_, _, _, _, Some(_)) => return None, - AggregateKind::RawPtr(pointee_ty, mtbl) => { + AggregateKind::RawPtr(..) => { assert_eq!(field_ops.len(), 2); - let data_pointer_ty = field_ops[FieldIdx::ZERO].ty(self.local_decls, self.tcx); - let output_pointer_ty = Ty::new_ptr(self.tcx, pointee_ty, mtbl); - (AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty }, FIRST_VARIANT) - } - }; - - let mut fields: Vec<_> = field_ops - .iter_mut() - .map(|op| self.simplify_operand(op, location).unwrap_or_else(|| self.new_opaque())) - .collect(); - - if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty { - let mut was_updated = false; + let [mut pointer, metadata] = fields.try_into().unwrap(); + + // Any thin pointer of matching mutability is fine as the data pointer. + let mut was_updated = false; + while let Value::Cast { kind: CastKind::PtrToPtr, value: cast_value } = + self.get(pointer) + && let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(*cast_value).kind() + && let ty::RawPtr(_, output_mtbl) = ty.kind() + && from_mtbl == output_mtbl + && from_pointee_ty.is_sized(self.tcx, self.typing_env()) + { + pointer = *cast_value; + was_updated = true; + } - // Any thin pointer of matching mutability is fine as the data pointer. - while let Value::Cast { - kind: CastKind::PtrToPtr, - value: cast_value, - from: cast_from, - to: _, - } = self.get(fields[0]) - && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind() - && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind() - && from_mtbl == output_mtbl - && from_pointee_ty.is_sized(self.tcx, self.typing_env()) - { - fields[0] = *cast_value; - *data_pointer_ty = *cast_from; - was_updated = true; - } + if was_updated && let Some(op) = self.try_as_operand(pointer, location) { + field_ops[FieldIdx::ZERO] = op; + } - if was_updated && let Some(op) = self.try_as_operand(fields[0], location) { - field_ops[FieldIdx::ZERO] = op; + return Some(self.insert(ty, Value::RawPtr { pointer, metadata })); } - } + }; - if let AggregateTy::Array = ty - && fields.len() > 4 - { + if ty.is_array() && fields.len() > 4 { let first = fields[0]; if fields.iter().all(|&v| v == first) { let len = ty::Const::from_target_usize(self.tcx, fields.len().try_into().unwrap()); if let Some(op) = self.try_as_operand(first, location) { *rvalue = Rvalue::Repeat(op, len); } - return Some(self.insert(Value::Repeat(first, len))); + return Some(self.insert(ty, Value::Repeat(first, len))); } } - if let AggregateTy::Def(_, _) = ty - && let Some(value) = - self.simplify_aggregate_to_copy(lhs, rvalue, location, &fields, variant_index) + if let Some(value) = + self.simplify_aggregate_to_copy(lhs, rvalue, location, &fields, variant_index) { return Some(value); } - Some(self.insert(Value::Aggregate(ty, variant_index, fields))) + Some(self.insert(ty, Value::Aggregate(variant_index, fields))) } #[instrument(level = "trace", skip(self), ret)] @@ -1112,6 +1072,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { location: Location, ) -> Option { let mut arg_index = self.simplify_operand(arg_op, location)?; + let arg_ty = self.ty(arg_index); + let ret_ty = op.ty(self.tcx, arg_ty); // PtrMetadata doesn't care about *const vs *mut vs & vs &mut, // so start by removing those distinctions so we can update the `Operand` @@ -1127,8 +1089,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // we can't always know exactly what the metadata are. // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`, // it's fine to get a projection as the type. - Value::Cast { kind: CastKind::PtrToPtr, value: inner, from, to } - if self.pointers_have_same_metadata(*from, *to) => + Value::Cast { kind: CastKind::PtrToPtr, value: inner } + if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) => { arg_index = *inner; was_updated = true; @@ -1165,26 +1127,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => { Value::BinaryOp(BinOp::Eq, *lhs, *rhs) } - (UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => { - return Some(fields[1]); - } + (UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(*metadata), // We have an unsizing cast, which assigns the length to wide pointer metadata. ( UnOp::PtrMetadata, Value::Cast { kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _), - from, - to, - .. + value: inner, }, - ) if let ty::Slice(..) = to.builtin_deref(true).unwrap().kind() - && let ty::Array(_, len) = from.builtin_deref(true).unwrap().kind() => + ) if let ty::Slice(..) = arg_ty.builtin_deref(true).unwrap().kind() + && let ty::Array(_, len) = self.ty(*inner).builtin_deref(true).unwrap().kind() => { return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } _ => Value::UnaryOp(op, arg_index), }; - Some(self.insert(value)) + Some(self.insert(ret_ty, value)) } #[instrument(level = "trace", skip(self), ret)] @@ -1197,25 +1155,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ) -> Option { let lhs = self.simplify_operand(lhs_operand, location); let rhs = self.simplify_operand(rhs_operand, location); + // Only short-circuit options after we called `simplify_operand` // on both operands for side effect. let mut lhs = lhs?; let mut rhs = rhs?; - let lhs_ty = lhs_operand.ty(self.local_decls, self.tcx); + let lhs_ty = self.ty(lhs); // If we're comparing pointers, remove `PtrToPtr` casts if the from // types of both casts and the metadata all match. if let BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge = op && lhs_ty.is_any_ptr() - && let Value::Cast { - kind: CastKind::PtrToPtr, value: lhs_value, from: lhs_from, .. - } = self.get(lhs) - && let Value::Cast { - kind: CastKind::PtrToPtr, value: rhs_value, from: rhs_from, .. - } = self.get(rhs) - && lhs_from == rhs_from - && self.pointers_have_same_metadata(*lhs_from, lhs_ty) + && let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value } = self.get(lhs) + && let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value } = self.get(rhs) + && let lhs_from = self.ty(*lhs_value) + && lhs_from == self.ty(*rhs_value) + && self.pointers_have_same_metadata(lhs_from, lhs_ty) { lhs = *lhs_value; rhs = *rhs_value; @@ -1230,8 +1186,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if let Some(value) = self.simplify_binary_inner(op, lhs_ty, lhs, rhs) { return Some(value); } + let ty = op.ty(self.tcx, lhs_ty, self.ty(rhs)); let value = Value::BinaryOp(op, lhs, rhs); - Some(self.insert(value)) + Some(self.insert(ty, value)) } fn simplify_binary_inner( @@ -1323,19 +1280,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { | BinOp::Shr, Left(0), _, - ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), + ) => self.insert_scalar(lhs_ty, Scalar::from_uint(0u128, layout.size)), // Attempt to simplify `x | ALL_ONES` to `ALL_ONES`. (BinOp::BitOr, _, Left(ones)) | (BinOp::BitOr, Left(ones), _) if ones == layout.size.truncate(u128::MAX) || (layout.ty.is_bool() && ones == 1) => { - self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty) + self.insert_scalar(lhs_ty, Scalar::from_uint(ones, layout.size)) } // Sub/Xor with itself. (BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b) if a == b => { - self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty) + self.insert_scalar(lhs_ty, Scalar::from_uint(0u128, layout.size)) } // Comparison: // - if both operands can be computed as bits, just compare the bits; @@ -1349,8 +1306,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { }; if op.is_overflowing() { + let ty = Ty::new_tup(self.tcx, &[self.ty(result), self.tcx.types.bool]); let false_val = self.insert_bool(false); - Some(self.insert_tuple(vec![result, false_val])) + Some(self.insert_tuple(ty, vec![result, false_val])) } else { Some(result) } @@ -1366,9 +1324,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { use CastKind::*; use rustc_middle::ty::adjustment::PointerCoercion::*; - let mut from = initial_operand.ty(self.local_decls, self.tcx); let mut kind = *initial_kind; let mut value = self.simplify_operand(initial_operand, location)?; + let mut from = self.ty(value); if from == to { return Some(value); } @@ -1376,7 +1334,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_), _) = kind { // Each reification of a generic fn may get a different pointer. // Do not try to merge them. - return Some(self.new_opaque()); + return Some(self.new_opaque(to)); } let mut was_ever_updated = false; @@ -1399,23 +1357,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // If a cast just casts away the metadata again, then we can get it by // casting the original thin pointer passed to `from_raw_parts` if let PtrToPtr = kind - && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) = - self.get(value) + && let Value::RawPtr { pointer, .. } = self.get(value) && let ty::RawPtr(to_pointee, _) = to.kind() && to_pointee.is_sized(self.tcx, self.typing_env()) { - from = *data_pointer_ty; - value = fields[0]; + from = self.ty(*pointer); + value = *pointer; was_updated_this_iteration = true; - if *data_pointer_ty == to { - return Some(fields[0]); + if from == to { + return Some(*pointer); } } // Aggregate-then-Transmute can just transmute the original field value, // so long as the bytes of a value from only from a single field. if let Transmute = kind - && let Value::Aggregate(_aggregate_ty, variant_idx, field_values) = self.get(value) + && let Value::Aggregate(variant_idx, field_values) = self.get(value) && let Some((field_idx, field_ty)) = self.value_is_all_in_one_field(from, *variant_idx) { @@ -1428,13 +1385,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } // Various cast-then-cast cases can be simplified. - if let Value::Cast { - kind: inner_kind, - value: inner_value, - from: inner_from, - to: inner_to, - } = *self.get(value) - { + if let Value::Cast { kind: inner_kind, value: inner_value } = *self.get(value) { + let inner_from = self.ty(inner_value); let new_kind = match (inner_kind, kind) { // Even if there's a narrowing cast in here that's fine, because // things like `*mut [i32] -> *mut i32 -> *const i32` and @@ -1443,9 +1395,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // PtrToPtr-then-Transmute is fine so long as the pointer cast is identity: // `*const T -> *mut T -> NonNull` is fine, but we need to check for narrowing // to skip things like `*const [i32] -> *const i32 -> NonNull`. - (PtrToPtr, Transmute) - if self.pointers_have_same_metadata(inner_from, inner_to) => - { + (PtrToPtr, Transmute) if self.pointers_have_same_metadata(inner_from, from) => { Some(Transmute) } // Similarly, for Transmute-then-PtrToPtr. Note that we need to check different @@ -1456,7 +1406,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // If would be legal to always do this, but we don't want to hide information // from the backend that it'd otherwise be able to use for optimizations. (Transmute, Transmute) - if !self.type_may_have_niche_of_interest_to_backend(inner_to) => + if !self.type_may_have_niche_of_interest_to_backend(from) => { Some(Transmute) } @@ -1485,7 +1435,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { *initial_kind = kind; } - Some(self.insert(Value::Cast { kind, value, from, to })) + Some(self.insert(to, Value::Cast { kind, value })) } fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option { @@ -1507,18 +1457,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } // We have an unsizing cast, which assigns the length to wide pointer metadata. - if let Value::Cast { kind, from, to, .. } = self.get(inner) + if let Value::Cast { kind, value: from } = self.get(inner) && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind - && let Some(from) = from.builtin_deref(true) + && let Some(from) = self.ty(*from).builtin_deref(true) && let ty::Array(_, len) = from.kind() - && let Some(to) = to.builtin_deref(true) + && let Some(to) = self.ty(inner).builtin_deref(true) && let ty::Slice(..) = to.kind() { return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } // Fallback: a symbolic `Len`. - Some(self.insert(Value::Len(inner))) + Some(self.insert(self.tcx.types.usize, Value::Len(inner))) } fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool { @@ -1727,7 +1677,7 @@ impl<'tcx> VnState<'_, 'tcx> { return Some(place); } else if let Value::Projection(pointer, proj) = *self.get(index) && (allow_complex_projection || proj.is_stable_offset()) - && let Some(proj) = self.try_as_place_elem(proj, loc) + && let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc) { projection.push(proj); index = pointer; @@ -1755,7 +1705,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); - if context.is_mutating_use() && !place.projection.is_empty() { + if context.is_mutating_use() && place.is_indirect() { // Non-local mutation maybe invalidate deref. self.invalidate_derefs(); } @@ -1767,36 +1717,42 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.super_operand(operand, location); } - fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { - if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind { - self.simplify_place_projection(lhs, location); - - let value = self.simplify_rvalue(lhs, rvalue, location); - let value = if let Some(local) = lhs.as_local() - && self.ssa.is_ssa(local) - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark - // `local` as reusable if we have an exact type match. - && self.local_decls[local].ty == rvalue.ty(self.local_decls, self.tcx) + fn visit_assign( + &mut self, + lhs: &mut Place<'tcx>, + rvalue: &mut Rvalue<'tcx>, + location: Location, + ) { + self.simplify_place_projection(lhs, location); + + let value = self.simplify_rvalue(lhs, rvalue, location); + if let Some(value) = value { + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + } else if let Some(place) = self.try_as_place(value, location, false) + && *rvalue != Rvalue::Use(Operand::Move(place)) + && *rvalue != Rvalue::Use(Operand::Copy(place)) { - let value = value.unwrap_or_else(|| self.new_opaque()); - self.assign(local, value); - Some(value) - } else { - value - }; - if let Some(value) = value { - if let Some(const_) = self.try_as_constant(value) { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(place) = self.try_as_place(value, location, false) - && *rvalue != Rvalue::Use(Operand::Move(place)) - && *rvalue != Rvalue::Use(Operand::Copy(place)) - { - *rvalue = Rvalue::Use(Operand::Copy(place)); - self.reused_locals.insert(place.local); - } + *rvalue = Rvalue::Use(Operand::Copy(place)); + self.reused_locals.insert(place.local); } } - self.super_statement(stmt, location); + + if lhs.is_indirect() { + // Non-local mutation maybe invalidate deref. + self.invalidate_derefs(); + } + + if let Some(local) = lhs.as_local() + && self.ssa.is_ssa(local) + && let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. + && self.local_decls[local].ty == rvalue_ty + { + let value = value.unwrap_or_else(|| self.new_opaque(rvalue_ty)); + self.assign(local, value); + } } fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { @@ -1804,7 +1760,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { if let Some(local) = destination.as_local() && self.ssa.is_ssa(local) { - let opaque = self.new_opaque(); + let ty = self.local_decls[local].ty; + let opaque = self.new_opaque(ty); self.assign(local, opaque); } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index cbb9bbfd12f9f..13e256a8affd1 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -719,6 +719,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } + if adt_def.repr().simd() { + self.fail( + location, + format!( + "Projecting into SIMD type {adt_def:?} is banned by MCP#838" + ), + ); + } + let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT); let Some(field) = adt_def.variant(var).fields.get(f) else { fail_out_of_bounds(self, location); diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 783d79d978ab6..a476f0db37e0d 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -318,6 +318,7 @@ pub fn check_builtin_meta_item( | sym::rustc_layout_scalar_valid_range_end | sym::no_implicit_prelude | sym::automatically_derived + | sym::coverage ) { return; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d8ffcedeb88a4..2766b14bb8d01 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -288,6 +288,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => { self.check_rustc_std_internal_symbol(attr_span, span, target) } + &Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => { + self.check_coverage(attr_span, span, target) + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -297,7 +300,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target) } - [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::no_sanitize, ..] => { self.check_no_sanitize(attr, span, target) } @@ -588,7 +590,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that `#[coverage(..)]` is applied to a function/closure/method, /// or to an impl block or module. - fn check_coverage(&self, attr: &Attribute, target_span: Span, target: Target) { + fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) { let mut not_fn_impl_mod = None; let mut no_body = None; @@ -611,7 +613,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } self.dcx().emit_err(errors::CoverageAttributeNotAllowed { - attr_span: attr.span(), + attr_span, not_fn_impl_mod, no_body, help: (), diff --git a/compiler/rustc_public/src/rustc_internal/mod.rs b/compiler/rustc_public/src/rustc_internal/mod.rs index 5d7c8256d5bf0..01354fc7bd422 100644 --- a/compiler/rustc_public/src/rustc_internal/mod.rs +++ b/compiler/rustc_public/src/rustc_internal/mod.rs @@ -144,10 +144,10 @@ where #[macro_export] macro_rules! run { ($args:expr, $callback_fn:ident) => { - run_driver!($args, || $callback_fn()) + $crate::run_driver!($args, || $callback_fn()) }; ($args:expr, $callback:expr) => { - run_driver!($args, $callback) + $crate::run_driver!($args, $callback) }; } @@ -158,10 +158,10 @@ macro_rules! run { #[macro_export] macro_rules! run_with_tcx { ($args:expr, $callback_fn:ident) => { - run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) + $crate::run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) }; ($args:expr, $callback:expr) => { - run_driver!($args, $callback, with_tcx) + $crate::run_driver!($args, $callback, with_tcx) }; } @@ -191,11 +191,11 @@ macro_rules! run_driver { use rustc_public::CompilerError; use std::ops::ControlFlow; - pub struct StableMir ControlFlow> + pub struct StableMir ControlFlow> where B: Send, C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, + F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { callback: Option, result: Option>, @@ -205,7 +205,7 @@ macro_rules! run_driver { where B: Send, C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, + F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Creates a new `StableMir` instance, with given test_function and arguments. pub fn new(callback: F) -> Self { @@ -240,7 +240,7 @@ macro_rules! run_driver { where B: Send, C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, + F: FnOnce($($crate::optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) @@ -251,7 +251,7 @@ macro_rules! run_driver { ) -> Compilation { if let Some(callback) = self.callback.take() { rustc_internal::run(tcx, || { - self.result = Some(callback($(optional!($with_tcx tcx))?)); + self.result = Some(callback($($crate::optional!($with_tcx tcx))?)); }) .unwrap(); if self.result.as_ref().is_some_and(|val| val.is_continue()) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 753b9365cd877..93cec8daa5a4a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2899,9 +2899,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } if param.ident.name == kw::UnderscoreLifetime { + // To avoid emitting two similar errors, + // we need to check if the span is a raw underscore lifetime, see issue #143152 + let is_raw_underscore_lifetime = self + .r + .tcx + .sess + .psess + .raw_identifier_spans + .iter() + .any(|span| span == param.span()); + self.r .dcx() - .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }); + .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) + .emit_unless(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); continue; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a91e2140fd44e..d6215e1de043a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1708,6 +1708,11 @@ impl RustcOptGroup { OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc), }; } + + /// This is for diagnostics-only. + pub fn long_name(&self) -> &str { + self.long_name + } } pub fn make_opt( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7147f37efc102..d28a73bc13978 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -840,6 +840,7 @@ symbols! { derive, derive_coerce_pointee, derive_const, + derive_const_issue: "118304", derive_default_enum, derive_smart_pointer, destruct, diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 30f42050ac8ac..d0ba9c398864f 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -348,13 +348,13 @@ //! format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' //! argument := integer | identifier //! -//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] //! fill := character //! align := '<' | '^' | '>' //! sign := '+' | '-' //! width := count //! precision := count | '*' -//! type := '' | '?' | 'x?' | 'X?' | identifier +//! type := '?' | 'x?' | 'X?' | identifier //! count := parameter | integer //! parameter := argument '$' //! ``` diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 03b120fbf0c34..6419ae9911359 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -381,7 +381,8 @@ pub struct AssertParamIsEq { /// /// assert_eq!(2.cmp(&1), Ordering::Greater); /// ``` -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord, Debug, Hash)] +#[derive_const(PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] // This is a lang item only so that `BinOp::Cmp` in MIR can return it. // It has no special behavior, but does require that the three variants diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs index a06a5227fe285..7d61c9345ecf8 100644 --- a/library/core/src/cmp/bytewise.rs +++ b/library/core/src/cmp/bytewise.rs @@ -17,11 +17,15 @@ use crate::num::NonZero; /// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct. /// - `>::{eq,ne}` are equivalent to comparing the bytes. #[rustc_specialization_trait] -pub(crate) unsafe trait BytewiseEq: PartialEq + Sized {} +#[const_trait] +pub(crate) unsafe trait BytewiseEq: + ~const PartialEq + Sized +{ +} macro_rules! is_bytewise_comparable { ($($t:ty),+ $(,)?) => {$( - unsafe impl BytewiseEq for $t {} + unsafe impl const BytewiseEq for $t {} )+}; } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index fa27acac21721..f90e6851d1f5f 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2208,6 +2208,7 @@ pub const unsafe fn raw_eq(a: &T, b: &T) -> bool; /// [valid]: crate::ptr#safety #[rustc_nounwind] #[rustc_intrinsic] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] pub const unsafe fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32; /// See documentation of [`std::hint::black_box`] for details. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e08edde3b38bb..729de5ffc8f6e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -103,6 +103,7 @@ #![feature(cfg_select)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(const_carrying_mul_add)] +#![feature(const_cmp)] #![feature(const_destruct)] #![feature(const_eval_select)] #![feature(core_intrinsics)] @@ -146,6 +147,7 @@ #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] +#![feature(derive_const)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 1b6dbc2f428f7..8ac6ce2242d4e 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1615,7 +1615,7 @@ pub(crate) mod builtin { /// See [the reference] for more info. /// /// [the reference]: ../../../reference/attributes/derive.html - #[unstable(feature = "derive_const", issue = "none")] + #[unstable(feature = "derive_const", issue = "118304")] #[rustc_builtin_macro] pub macro derive_const($item:item) { /* compiler built-in */ diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 11d50e0f89f30..b8900c4113ad3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -200,9 +200,10 @@ impl UseCloned for NonZero where T: ZeroablePrimitive {} impl Copy for NonZero where T: ZeroablePrimitive {} #[stable(feature = "nonzero", since = "1.28.0")] -impl PartialEq for NonZero +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for NonZero where - T: ZeroablePrimitive + PartialEq, + T: ZeroablePrimitive + ~const PartialEq, { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 9f432758a66f6..da6e311ff5e1b 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2243,7 +2243,8 @@ impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { #[stable(feature = "rust1", since = "1.0.0")] impl crate::marker::StructuralPartialEq for Option {} #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Option { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for Option { #[inline] fn eq(&self, other: &Self) -> bool { // Spelling out the cases explicitly optimizes better than diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 7b9e04920d51d..a4be66b90cab3 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -80,7 +80,7 @@ pub use crate::macros::builtin::{ alloc_error_handler, bench, derive, global_allocator, test, test_case, }; -#[unstable(feature = "derive_const", issue = "none")] +#[unstable(feature = "derive_const", issue = "118304")] pub use crate::macros::builtin::derive_const; #[unstable( diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 5ce72b46eee36..1eda8bc1bec40 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -8,9 +8,10 @@ use crate::num::NonZero; use crate::ops::ControlFlow; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U]> for [T] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U]> for [T] where - T: PartialEq, + T: ~const PartialEq, { fn eq(&self, other: &[U]) -> bool { SlicePartialEq::equal(self, other) @@ -94,6 +95,8 @@ impl PartialOrd for [T] { #[doc(hidden)] // intermediate trait for specialization of slice's PartialEq +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] trait SlicePartialEq { fn equal(&self, other: &[B]) -> bool; @@ -103,9 +106,10 @@ trait SlicePartialEq { } // Generic slice equality -impl SlicePartialEq for [A] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SlicePartialEq for [A] where - A: PartialEq, + A: ~const PartialEq, { default fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { @@ -115,11 +119,14 @@ where // Implemented as explicit indexing rather // than zipped iterators for performance reasons. // See PR https://github.com/rust-lang/rust/pull/116846 - for idx in 0..self.len() { + // FIXME(const_hack): make this a `for idx in 0..self.len()` loop. + let mut idx = 0; + while idx < self.len() { // bound checks are optimized away if self[idx] != other[idx] { return false; } + idx += 1; } true @@ -128,9 +135,10 @@ where // When each element can be compared byte-wise, we can compare all the bytes // from the whole size in one call to the intrinsics. -impl SlicePartialEq for [A] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SlicePartialEq for [A] where - A: BytewiseEq, + A: ~const BytewiseEq, { fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 42ffc591b5bbf..d0f2b9226bf6d 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -23,7 +23,8 @@ impl Ord for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for str { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for str { #[inline] fn eq(&self, other: &str) -> bool { self.as_bytes() == other.as_bytes() diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 69f0335315356..70c1113155656 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -67,7 +67,7 @@ pub use core::prelude::v1::{ alloc_error_handler, bench, derive, global_allocator, test, test_case, }; -#[unstable(feature = "derive_const", issue = "none")] +#[unstable(feature = "derive_const", issue = "118304")] pub use core::prelude::v1::derive_const; // Do not `doc(no_inline)` either. diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index 726d4c01cc3f3..e2cd08733af1c 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -349,12 +349,15 @@ fn simd_mask() { // Non-power-of-2 multi-byte mask. #[repr(simd, packed)] #[allow(non_camel_case_types)] - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone)] struct i32x10([i32; 10]); impl i32x10 { fn splat(x: i32) -> Self { Self([x; 10]) } + fn into_array(self) -> [i32; 10] { + unsafe { std::mem::transmute(self) } + } } unsafe { let mask = i32x10([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]); @@ -377,19 +380,22 @@ fn simd_mask() { i32x10::splat(!0), // yes i32x10::splat(0), // no ); - assert_eq!(selected1, mask); - assert_eq!(selected2, mask); + assert_eq!(selected1.into_array(), mask.into_array()); + assert_eq!(selected2.into_array(), mask.into_array()); } // Test for a mask where the next multiple of 8 is not a power of two. #[repr(simd, packed)] #[allow(non_camel_case_types)] - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone)] struct i32x20([i32; 20]); impl i32x20 { fn splat(x: i32) -> Self { Self([x; 20]) } + fn into_array(self) -> [i32; 20] { + unsafe { std::mem::transmute(self) } + } } unsafe { let mask = i32x20([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0, 0, 0, 0, !0, !0, !0, !0, !0, !0, !0]); @@ -419,8 +425,8 @@ fn simd_mask() { i32x20::splat(!0), // yes i32x20::splat(0), // no ); - assert_eq!(selected1, mask); - assert_eq!(selected2, mask); + assert_eq!(selected1.into_array(), mask.into_array()); + assert_eq!(selected2.into_array(), mask.into_array()); } } @@ -708,12 +714,12 @@ fn simd_ops_non_pow2() { let x = SimdPacked([1u32; 3]); let y = SimdPacked([2u32; 3]); let z = unsafe { intrinsics::simd_add(x, y) }; - assert_eq!({ z.0 }, [3u32; 3]); + assert_eq!(unsafe { *(&raw const z).cast::<[u32; 3]>() }, [3u32; 3]); let x = SimdPadded([1u32; 3]); let y = SimdPadded([2u32; 3]); let z = unsafe { intrinsics::simd_add(x, y) }; - assert_eq!(z.0, [3u32; 3]); + assert_eq!(unsafe { *(&raw const z).cast::<[u32; 3]>() }, [3u32; 3]); } fn main() { diff --git a/tests/auxiliary/minisimd.rs b/tests/auxiliary/minisimd.rs new file mode 100644 index 0000000000000..ff0c996de1c87 --- /dev/null +++ b/tests/auxiliary/minisimd.rs @@ -0,0 +1,160 @@ +//! Auxiliary crate for tests that need SIMD types. +//! +//! Historically the tests just made their own, but projections into simd types +//! was banned by , which +//! breaks `derive(Clone)`, so this exists to give easily-usable types that can +//! be used without copy-pasting the definitions of the helpers everywhere. +//! +//! This makes no attempt to guard against ICEs. Using it with proper types +//! and such is your responsibility in the tests you write. + +#![allow(unused)] +#![allow(non_camel_case_types)] + +// The field is currently left `pub` for convenience in porting tests, many of +// which attempt to just construct it directly. That still works; it's just the +// `.0` projection that doesn't. +#[repr(simd)] +#[derive(Copy, Eq)] +pub struct Simd(pub [T; N]); + +impl Clone for Simd { + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for Simd { + fn eq(&self, other: &Self) -> bool { + self.as_array() == other.as_array() + } +} + +impl core::fmt::Debug for Simd { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + <[T; N] as core::fmt::Debug>::fmt(self.as_array(), f) + } +} + +impl core::ops::Index for Simd { + type Output = T; + fn index(&self, i: usize) -> &T { + &self.as_array()[i] + } +} + +impl Simd { + pub const fn from_array(a: [T; N]) -> Self { + Simd(a) + } + pub fn as_array(&self) -> &[T; N] { + let p: *const Self = self; + unsafe { &*p.cast::<[T; N]>() } + } + pub fn into_array(self) -> [T; N] + where + T: Copy, + { + *self.as_array() + } +} + +pub type u8x2 = Simd; +pub type u8x4 = Simd; +pub type u8x8 = Simd; +pub type u8x16 = Simd; +pub type u8x32 = Simd; +pub type u8x64 = Simd; + +pub type u16x2 = Simd; +pub type u16x4 = Simd; +pub type u16x8 = Simd; +pub type u16x16 = Simd; +pub type u16x32 = Simd; + +pub type u32x2 = Simd; +pub type u32x4 = Simd; +pub type u32x8 = Simd; +pub type u32x16 = Simd; + +pub type u64x2 = Simd; +pub type u64x4 = Simd; +pub type u64x8 = Simd; + +pub type u128x2 = Simd; +pub type u128x4 = Simd; + +pub type i8x2 = Simd; +pub type i8x4 = Simd; +pub type i8x8 = Simd; +pub type i8x16 = Simd; +pub type i8x32 = Simd; +pub type i8x64 = Simd; + +pub type i16x2 = Simd; +pub type i16x4 = Simd; +pub type i16x8 = Simd; +pub type i16x16 = Simd; +pub type i16x32 = Simd; + +pub type i32x2 = Simd; +pub type i32x4 = Simd; +pub type i32x8 = Simd; +pub type i32x16 = Simd; + +pub type i64x2 = Simd; +pub type i64x4 = Simd; +pub type i64x8 = Simd; + +pub type i128x2 = Simd; +pub type i128x4 = Simd; + +pub type f32x2 = Simd; +pub type f32x4 = Simd; +pub type f32x8 = Simd; +pub type f32x16 = Simd; + +pub type f64x2 = Simd; +pub type f64x4 = Simd; +pub type f64x8 = Simd; + +// The field is currently left `pub` for convenience in porting tests, many of +// which attempt to just construct it directly. That still works; it's just the +// `.0` projection that doesn't. +#[repr(simd, packed)] +#[derive(Copy)] +pub struct PackedSimd(pub [T; N]); + +impl Clone for PackedSimd { + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for PackedSimd { + fn eq(&self, other: &Self) -> bool { + self.as_array() == other.as_array() + } +} + +impl core::fmt::Debug for PackedSimd { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + <[T; N] as core::fmt::Debug>::fmt(self.as_array(), f) + } +} + +impl PackedSimd { + pub const fn from_array(a: [T; N]) -> Self { + PackedSimd(a) + } + pub fn as_array(&self) -> &[T; N] { + let p: *const Self = self; + unsafe { &*p.cast::<[T; N]>() } + } + pub fn into_array(self) -> [T; N] + where + T: Copy, + { + *self.as_array() + } +} diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs index 42921442e039f..a2249f4fff7bf 100644 --- a/tests/codegen/const-vector.rs +++ b/tests/codegen/const-vector.rs @@ -16,18 +16,9 @@ #![feature(mips_target_feature)] #![allow(non_camel_case_types)] -// Setting up structs that can be used as const vectors -#[repr(simd)] -#[derive(Clone)] -pub struct i8x2([i8; 2]); - -#[repr(simd)] -#[derive(Clone)] -pub struct f32x2([f32; 2]); - -#[repr(simd, packed)] -#[derive(Copy, Clone)] -pub struct Simd([T; N]); +#[path = "../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::{PackedSimd as Simd, f32x2, i8x2}; // The following functions are required for the tests to ensure // that they are called with a const vector @@ -45,7 +36,7 @@ extern "unadjusted" { // Ensure the packed variant of the simd struct does not become a const vector // if the size is not a power of 2 -// CHECK: %"Simd" = type { [3 x i32] } +// CHECK: %"minisimd::PackedSimd" = type { [3 x i32] } #[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))] #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] @@ -54,27 +45,34 @@ extern "unadjusted" { pub fn do_call() { unsafe { // CHECK: call void @test_i8x2(<2 x i8> - test_i8x2(const { i8x2([32, 64]) }); + test_i8x2(const { i8x2::from_array([32, 64]) }); // CHECK: call void @test_i8x2_two_args(<2 x i8> , <2 x i8> - test_i8x2_two_args(const { i8x2([32, 64]) }, const { i8x2([8, 16]) }); + test_i8x2_two_args( + const { i8x2::from_array([32, 64]) }, + const { i8x2::from_array([8, 16]) }, + ); // CHECK: call void @test_i8x2_mixed_args(<2 x i8> , i32 43, <2 x i8> - test_i8x2_mixed_args(const { i8x2([32, 64]) }, 43, const { i8x2([8, 16]) }); + test_i8x2_mixed_args( + const { i8x2::from_array([32, 64]) }, + 43, + const { i8x2::from_array([8, 16]) }, + ); // CHECK: call void @test_i8x2_arr(<2 x i8> - test_i8x2_arr(const { i8x2([32, 64]) }); + test_i8x2_arr(const { i8x2::from_array([32, 64]) }); // CHECK: call void @test_f32x2(<2 x float> - test_f32x2(const { f32x2([0.32, 0.64]) }); + test_f32x2(const { f32x2::from_array([0.32, 0.64]) }); // CHECK: void @test_f32x2_arr(<2 x float> - test_f32x2_arr(const { f32x2([0.32, 0.64]) }); + test_f32x2_arr(const { f32x2::from_array([0.32, 0.64]) }); // CHECK: call void @test_simd(<4 x i32> test_simd(const { Simd::([2, 4, 6, 8]) }); - // CHECK: call void @test_simd_unaligned(%"Simd" %1 + // CHECK: call void @test_simd_unaligned(%"minisimd::PackedSimd" %1 test_simd_unaligned(const { Simd::([2, 4, 6]) }); } } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs index 485ba92272dd2..baf445d0a1b31 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fabs; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fabs; // CHECK-LABEL: @fabs_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 { simd_fabs(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @fabs_64x4 #[no_mangle] pub unsafe fn fabs_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs index e8bda7c29c4be..096de56927428 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_ceil; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_ceil; // CHECK-LABEL: @ceil_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 { simd_ceil(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @ceil_64x4 #[no_mangle] pub unsafe fn ceil_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs index 8dc967bc3adc8..5b2197924bc77 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fcos; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fcos; // CHECK-LABEL: @fcos_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 { simd_fcos(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @fcos_64x4 #[no_mangle] pub unsafe fn fcos_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs index 00caca2f2949d..d4eadb36c65f5 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fexp; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fexp; // CHECK-LABEL: @exp_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn exp_32x16(a: f32x16) -> f32x16 { simd_fexp(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @exp_64x4 #[no_mangle] pub unsafe fn exp_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs index eda4053189cbb..d32015b799017 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fexp2; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fexp2; // CHECK-LABEL: @exp2_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 { simd_fexp2(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @exp2_64x4 #[no_mangle] pub unsafe fn exp2_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs index ad69d4cdd88cb..1e1c8ce0c3529 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_floor; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_floor; // CHECK-LABEL: @floor_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn floor_32x16(a: f32x16) -> f32x16 { simd_floor(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @floor_64x4 #[no_mangle] pub unsafe fn floor_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs index cbeefdc31c0df..982077d81f9ab 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fma; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fma; // CHECK-LABEL: @fma_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 { simd_fma(a, b, c) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @fma_64x4 #[no_mangle] pub unsafe fn fma_64x4(a: f64x4, b: f64x4, c: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs index 618daa4b44d09..e20a591f573b7 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fsqrt; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fsqrt; // CHECK-LABEL: @fsqrt_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 { simd_fsqrt(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @fsqrt_64x4 #[no_mangle] pub unsafe fn fsqrt_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs index 98a481e4004ee..bf1ffc7633092 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_flog; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_flog; // CHECK-LABEL: @log_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn log_32x16(a: f32x16) -> f32x16 { simd_flog(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @log_64x4 #[no_mangle] pub unsafe fn log_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs index 9108cd963f027..ccf484e0e4158 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_flog10; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_flog10; // CHECK-LABEL: @log10_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn log10_32x16(a: f32x16) -> f32x16 { simd_flog10(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @log10_64x4 #[no_mangle] pub unsafe fn log10_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs index 2b20850dbd9a1..677d8b01e8481 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_flog2; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_flog2; // CHECK-LABEL: @log2_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn log2_32x16(a: f32x16) -> f32x16 { simd_flog2(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @log2_64x4 #[no_mangle] pub unsafe fn log2_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs index ce07b212e846d..8dd464a1bffb6 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -4,11 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::{simd_fmax, simd_fmin}; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); +use std::intrinsics::simd::{simd_fmax, simd_fmin}; // CHECK-LABEL: @fmin #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs index 7de26b415bbbb..48becc72c0be7 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -4,23 +4,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_fsin; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub [f32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub [f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub [f32; 16]); +use std::intrinsics::simd::simd_fsin; // CHECK-LABEL: @fsin_32x2 #[no_mangle] @@ -50,18 +38,6 @@ pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 { simd_fsin(a) } -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub [f64; 2]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub [f64; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub [f64; 8]); - // CHECK-LABEL: @fsin_64x4 #[no_mangle] pub unsafe fn fsin_64x4(a: f64x4) -> f64x4 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index ecf5eb24ee5b2..06d4688971526 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -5,66 +5,11 @@ #![allow(non_camel_case_types)] #![deny(unused)] -use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub}; - -#[rustfmt::skip] -mod types { - // signed integer types - - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2([i8; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4([i8; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8([i8; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16([i8; 16]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32([i8; 32]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64([i8; 64]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2([i16; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4([i16; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8([i16; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16([i16; 16]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32([i16; 32]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2([i32; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4([i32; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8([i32; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16([i32; 16]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2([i64; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4([i64; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8([i64; 8]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2([i128; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4([i128; 4]); - - // unsigned integer types +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2([u8; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4([u8; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8([u8; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16([u8; 16]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32([u8; 32]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64([u8; 64]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2([u16; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4([u16; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8([u16; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16([u16; 16]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32([u16; 32]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2([u32; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4([u32; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8([u32; 8]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16([u32; 16]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2([u64; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4([u64; 4]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8([u64; 8]); - - #[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2([u128; 2]); - #[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4([u128; 4]); -} - -use types::*; +use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub}; // NOTE(eddyb) `%{{x|0}}` is used because on some targets (e.g. WASM) // SIMD vectors are passed directly, resulting in `%x` being a vector, diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index a2c40aa91b51f..294262d81526f 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -5,19 +5,11 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_bitmask; - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct u32x2([u32; 2]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct i32x2([i32; 2]); - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct i8x16([i8; 16]); +use std::intrinsics::simd::simd_bitmask; // NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM) // SIMD vectors are passed directly, resulting in `%x` being a vector, diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index c06b36d68b904..690bfb432f9b0 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -6,15 +6,14 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_gather; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub [T; 2]); +use std::intrinsics::simd::simd_gather; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub [T; 4]); +pub type Vec2 = Simd; +pub type Vec4 = Simd; // CHECK-LABEL: @gather_f32x2 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs index 21578e67cffc6..fda315dc66ca2 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -4,15 +4,14 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_masked_load; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub [T; 2]); +use std::intrinsics::simd::simd_masked_load; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub [T; 4]); +pub type Vec2 = Simd; +pub type Vec4 = Simd; // CHECK-LABEL: @load_f32x2 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs index 22a8f7e54bd3f..6ca7388d464b9 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -4,15 +4,14 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_masked_store; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub [T; 2]); +use std::intrinsics::simd::simd_masked_store; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub [T; 4]); +pub type Vec2 = Simd; +pub type Vec4 = Simd; // CHECK-LABEL: @store_f32x2 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index 0cc9e6ae59adb..743652966e164 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -6,15 +6,14 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_scatter; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub [T; 2]); +use std::intrinsics::simd::simd_scatter; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub [T; 4]); +pub type Vec2 = Simd; +pub type Vec4 = Simd; // CHECK-LABEL: @scatter_f32x2 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs index f6531c1b23aeb..2c0bad21f44b3 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -4,27 +4,13 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::{simd_select, simd_select_bitmask}; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub [f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8([f32; 8]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct b8x4(pub [i8; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct i32x4([i32; 4]); +use std::intrinsics::simd::{simd_select, simd_select_bitmask}; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct u32x4([u32; 4]); +pub type b8x4 = i8x4; // CHECK-LABEL: @select_m8 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs index 269fe41225efa..79f00a6ed6032 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs @@ -4,15 +4,14 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::{simd_reduce_all, simd_reduce_any}; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct mask32x2([i32; 2]); +use std::intrinsics::simd::{simd_reduce_all, simd_reduce_any}; -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct mask8x16([i8; 16]); +pub type mask32x2 = Simd; +pub type mask8x16 = Simd; // NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM) // SIMD vectors are passed directly, resulting in `%x` being a vector, diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 301f06c2d74ae..05c2f7e1bdfc1 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -8,13 +8,12 @@ #![allow(non_camel_case_types)] #![feature(repr_simd, core_intrinsics)] -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct S([f32; N]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct T([f32; 4]); +pub type S = Simd; +pub type T = Simd; // CHECK-LABEL: @array_align( #[no_mangle] @@ -34,7 +33,7 @@ pub fn vector_align() -> usize { #[no_mangle] pub fn build_array_s(x: [f32; 4]) -> S<4> { // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) - S::<4>(x) + Simd(x) } // CHECK-LABEL: @build_array_transmute_s @@ -48,7 +47,7 @@ pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> { #[no_mangle] pub fn build_array_t(x: [f32; 4]) -> T { // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) - T(x) + Simd(x) } // CHECK-LABEL: @build_array_transmute_t diff --git a/tests/codegen/simd/aggregate-simd.rs b/tests/codegen/simd/aggregate-simd.rs index 065e429a4c782..57a301d634c81 100644 --- a/tests/codegen/simd/aggregate-simd.rs +++ b/tests/codegen/simd/aggregate-simd.rs @@ -5,15 +5,11 @@ #![no_std] #![crate_type = "lib"] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; use core::intrinsics::simd::{simd_add, simd_extract}; -#[repr(simd)] -#[derive(Clone, Copy)] -pub struct Simd([T; N]); - -#[repr(simd, packed)] -#[derive(Clone, Copy)] -pub struct PackedSimd([T; N]); +use minisimd::*; #[repr(transparent)] pub struct Transparent(T); diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs index 73e0d29d7d67c..70c03fcc95574 100644 --- a/tests/codegen/simd/packed-simd.rs +++ b/tests/codegen/simd/packed-simd.rs @@ -9,18 +9,14 @@ use core::intrinsics::simd as intrinsics; use core::{mem, ptr}; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::{PackedSimd, Simd as FullSimd}; + // Test codegen for not only "packed" but also "fully aligned" SIMD types, and conversion between // them. A repr(packed,simd) type with 3 elements can't exceed its element alignment, whereas the // same type as repr(simd) will instead have padding. -#[repr(simd, packed)] -#[derive(Copy, Clone)] -pub struct PackedSimd([T; N]); - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct FullSimd([T; N]); - // non-powers-of-two have padding and need to be expanded to full vectors fn load(v: PackedSimd) -> FullSimd { unsafe { diff --git a/tests/codegen/simd/project-to-simd-array-field.rs b/tests/codegen/simd/project-to-simd-array-field.rs deleted file mode 100644 index 29fab64063363..0000000000000 --- a/tests/codegen/simd/project-to-simd-array-field.rs +++ /dev/null @@ -1,31 +0,0 @@ -//@compile-flags: -Copt-level=3 - -#![crate_type = "lib"] -#![feature(repr_simd, core_intrinsics)] - -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(simd)] -struct i32x4([i32; 4]); - -#[inline(always)] -fn to_array4(a: i32x4) -> [i32; 4] { - a.0 -} - -// CHECK-LABEL: simd_add_self_then_return_array( -// CHECK-SAME: ptr{{.+}}sret{{.+}}%[[RET:.+]], -// CHECK-SAME: ptr{{.+}}%a) -#[no_mangle] -pub fn simd_add_self_then_return_array(a: &i32x4) -> [i32; 4] { - // It would be nice to just ban `.0` into simd types, - // but until we do this has to keep working. - // See also - - // CHECK: %[[T1:.+]] = load <4 x i32>, ptr %a - // CHECK: %[[T2:.+]] = shl <4 x i32> %[[T1]], {{splat \(i32 1\)|}} - // CHECK: store <4 x i32> %[[T2]], ptr %[[RET]] - let a = *a; - let b = unsafe { core::intrinsics::simd::simd_add(a, a) }; - to_array4(b) -} diff --git a/tests/codegen/simd/simd_arith_offset.rs b/tests/codegen/simd/simd_arith_offset.rs index b8af6fce33267..210b4e9bb50e1 100644 --- a/tests/codegen/simd/simd_arith_offset.rs +++ b/tests/codegen/simd/simd_arith_offset.rs @@ -5,16 +5,14 @@ #![crate_type = "lib"] #![feature(repr_simd, core_intrinsics)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; use std::intrinsics::simd::simd_arith_offset; -/// A vector of *const T. -#[derive(Debug, Copy, Clone)] -#[repr(simd)] -pub struct SimdConstPtr([*const T; LANES]); +use minisimd::*; -#[derive(Debug, Copy, Clone)] -#[repr(simd)] -pub struct Simd([T; LANES]); +/// A vector of *const T. +pub type SimdConstPtr = Simd<*const T, LANES>; // CHECK-LABEL: smoke #[no_mangle] diff --git a/tests/mir-opt/const_prop/transmute.rs b/tests/mir-opt/const_prop/transmute.rs index 892b91a5414c3..33cbefbf053f5 100644 --- a/tests/mir-opt/const_prop/transmute.rs +++ b/tests/mir-opt/const_prop/transmute.rs @@ -56,7 +56,7 @@ pub unsafe fn undef_union_as_integer() -> u32 { pub unsafe fn unreachable_direct() -> ! { // CHECK-LABEL: fn unreachable_direct( // CHECK: = const (); - // CHECK: = const () as Never (Transmute); + // CHECK: = const ZeroSized: Never; let x: Never = unsafe { transmute(()) }; match x {} } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff index 3364782022dc7..5aeb55a5a6a53 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff @@ -15,7 +15,7 @@ - _2 = (); - _1 = move _2 as Never (Transmute); + _2 = const (); -+ _1 = const () as Never (Transmute); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff index 3364782022dc7..5aeb55a5a6a53 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff @@ -15,7 +15,7 @@ - _2 = (); - _1 = move _2 as Never (Transmute); + _2 = const (); -+ _1 = const () as Never (Transmute); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff index 770c673077533..ffe4a0272b4b1 100644 --- a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff @@ -18,7 +18,8 @@ bb0: { _4 = copy _1 as *const T (PtrToPtr); - _5 = PtrMetadata(copy _4); +- _5 = PtrMetadata(copy _4); ++ _5 = const (); _6 = copy _1 as *const (&A, [T]) (PtrToPtr); - _7 = PtrMetadata(copy _6); + _7 = PtrMetadata(copy _1); diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff index 770c673077533..ffe4a0272b4b1 100644 --- a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff @@ -18,7 +18,8 @@ bb0: { _4 = copy _1 as *const T (PtrToPtr); - _5 = PtrMetadata(copy _4); +- _5 = PtrMetadata(copy _4); ++ _5 = const (); _6 = copy _1 as *const (&A, [T]) (PtrToPtr); - _7 = PtrMetadata(copy _6); + _7 = PtrMetadata(copy _1); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 6ef320c90de12..5d348bc3c1e40 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -869,7 +869,7 @@ fn generic_cast_metadata(ps: *const [T], pa: *const A, // Metadata usize -> (), do not optimize. // CHECK: [[T:_.+]] = copy _1 as - // CHECK-NEXT: PtrMetadata(copy [[T]]) + // CHECK-NEXT: const (); let t1 = CastPtrToPtr::<_, *const T>(ps); let m1 = PtrMetadata(t1); diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 3b58f1d61f4bb..8c5fbda63921f 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -109,7 +109,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb4: { - StorageLive(_15); _14 = &mut _13; _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; } @@ -120,7 +119,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb6: { - StorageDead(_15); StorageDead(_13); drop(_2) -> [return: bb7, unwind continue]; } @@ -135,14 +133,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_19); _19 = &_2; StorageLive(_20); - _20 = (copy _17, copy _18); + _20 = copy ((_15 as Some).0: (usize, &T)); _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } bb9: { StorageDead(_20); StorageDead(_19); - StorageDead(_15); goto -> bb4; } diff --git a/tests/run-make/mte-ffi/bar.h b/tests/run-make/mte-ffi/bar.h index 9b030c618d184..a2292ae02a308 100644 --- a/tests/run-make/mte-ffi/bar.h +++ b/tests/run-make/mte-ffi/bar.h @@ -1,5 +1,3 @@ -// FIXME(#141600) the mte-ffi test doesn't fail in aarch64-gnu - #ifndef __BAR_H #define __BAR_H diff --git a/tests/run-make/mte-ffi/bar_float.c b/tests/run-make/mte-ffi/bar_float.c index acc2f5d9266d0..a1590f62765a6 100644 --- a/tests/run-make/mte-ffi/bar_float.c +++ b/tests/run-make/mte-ffi/bar_float.c @@ -3,9 +3,9 @@ #include #include "bar.h" -extern void foo(float*); +extern void foo(char*); -void bar(float *ptr) { +void bar(char *ptr) { if (((uintptr_t)ptr >> 56) != 0x1f) { fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); exit(1); diff --git a/tests/run-make/mte-ffi/bar_int.c b/tests/run-make/mte-ffi/bar_int.c index c92e765302c1e..d1c79e95dc9cb 100644 --- a/tests/run-make/mte-ffi/bar_int.c +++ b/tests/run-make/mte-ffi/bar_int.c @@ -5,7 +5,7 @@ extern void foo(unsigned int *); -void bar(unsigned int *ptr) { +void bar(char *ptr) { if (((uintptr_t)ptr >> 56) != 0x1f) { fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n"); exit(1); diff --git a/tests/run-make/mte-ffi/bar_string.c b/tests/run-make/mte-ffi/bar_string.c index 8e1202f6fd159..5669ffd6695e7 100644 --- a/tests/run-make/mte-ffi/bar_string.c +++ b/tests/run-make/mte-ffi/bar_string.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "bar.h" extern void foo(char*); @@ -33,7 +32,7 @@ int main(void) // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be), // and a different value in the ignored top 4 bits. - ptr = (char *)((uintptr_t)ptr | 0x1fl << 56); + ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56); if (mte_enabled()) { set_tag(ptr); diff --git a/tests/run-make/mte-ffi/rmake.rs b/tests/run-make/mte-ffi/rmake.rs index a8da0dc0ee039..71d8318d9465c 100644 --- a/tests/run-make/mte-ffi/rmake.rs +++ b/tests/run-make/mte-ffi/rmake.rs @@ -2,6 +2,13 @@ //! FFI boundaries (C <-> Rust). This test does not require MTE: whilst the test will use MTE if //! available, if it is not, arbitrary tag bits are set using TBI. +//@ ignore-test (FIXME #141600) +// +// FIXME(#141600): this test is broken in two ways: +// 1. This test triggers `-Wincompatible-pointer-types` on GCC 14. +// 2. This test requires ARMv8.5+ w/ MTE extensions enabled, but GHA CI runner hardware do not have +// this enabled. + //@ only-aarch64-unknown-linux-gnu // Reason: this test is only valid for AArch64 with `gcc`. The linker must be explicitly specified // when cross-compiling, so it is limited to `aarch64-unknown-linux-gnu`. diff --git a/tests/run-make/option-output-no-space/main.rs b/tests/run-make/option-output-no-space/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/option-output-no-space/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs new file mode 100644 index 0000000000000..2c42f15aa89a6 --- /dev/null +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -0,0 +1,95 @@ +// This test is to check if the warning is emitted when no space +// between `-o` and arg is applied, see issue #142812 + +//@ ignore-cross-compile +use run_make_support::rustc; + +fn main() { + // test fake args + rustc() + .input("main.rs") + .arg("-optimize") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o ptimize` is applied instead of a flag named `optimize`", + ); + rustc() + .input("main.rs") + .arg("-o0") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o 0` is applied instead of a flag named `o0`", + ); + rustc().input("main.rs").arg("-o1").run(); + // test real args by iter optgroups + rustc() + .input("main.rs") + .arg("-out-dir") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o ut-dir` is applied instead of a flag named `out-dir`", + ) + .assert_stderr_contains( + "help: insert a space between `-o` and `ut-dir` if this is intentional: `-o ut-dir`", + ); + // test real args by iter CG_OPTIONS + rustc() + .input("main.rs") + .arg("-opt_level") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o pt_level` is applied instead of a flag named `opt_level`", + ) + .assert_stderr_contains( + "help: insert a space between `-o` and `pt_level` if this is intentional: `-o pt_level`" + ); + // separater in-sensitive + rustc() + .input("main.rs") + .arg("-opt-level") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o pt-level` is applied instead of a flag named `opt-level`", + ) + .assert_stderr_contains( + "help: insert a space between `-o` and `pt-level` if this is intentional: `-o pt-level`" + ); + rustc() + .input("main.rs") + .arg("-overflow-checks") + .run() + .assert_stderr_contains( + "warning: option `-o` has no space between flag name and value, which can be confusing", + ) + .assert_stderr_contains( + "note: output filename `-o verflow-checks` \ + is applied instead of a flag named `overflow-checks`", + ) + .assert_stderr_contains( + "help: insert a space between `-o` and `verflow-checks` \ + if this is intentional: `-o verflow-checks`", + ); + + // No warning for Z_OPTIONS + rustc().input("main.rs").arg("-oom").run().assert_stderr_equals(""); + + // test no warning when there is space between `-o` and arg + rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals(""); + rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals(""); + rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals(""); +} diff --git a/tests/ui/async-await/async-drop/foreign-fundamental.rs b/tests/ui/async-await/async-drop/foreign-fundamental.rs new file mode 100644 index 0000000000000..1c192fccd9f0c --- /dev/null +++ b/tests/ui/async-await/async-drop/foreign-fundamental.rs @@ -0,0 +1,21 @@ +//@ edition: 2018 + +#![feature(async_drop)] +//~^ WARN the feature `async_drop` is incomplete + +use std::future::AsyncDrop; +use std::pin::Pin; + +struct Foo; + +impl AsyncDrop for &Foo { + //~^ ERROR the `AsyncDrop` trait may only be implemented for + async fn drop(self: Pin<&mut Self>) {} +} + +impl AsyncDrop for Pin { + //~^ ERROR the `AsyncDrop` trait may only be implemented for + async fn drop(self: Pin<&mut Self>) {} +} + +fn main() {} diff --git a/tests/ui/async-await/async-drop/foreign-fundamental.stderr b/tests/ui/async-await/async-drop/foreign-fundamental.stderr new file mode 100644 index 0000000000000..7b52329ac99d1 --- /dev/null +++ b/tests/ui/async-await/async-drop/foreign-fundamental.stderr @@ -0,0 +1,24 @@ +warning: the feature `async_drop` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/foreign-fundamental.rs:3:12 + | +LL | #![feature(async_drop)] + | ^^^^^^^^^^ + | + = note: see issue #126482 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0120]: the `AsyncDrop` trait may only be implemented for local structs, enums, and unions + --> $DIR/foreign-fundamental.rs:11:20 + | +LL | impl AsyncDrop for &Foo { + | ^^^^ must be a struct, enum, or union in the current crate + +error[E0120]: the `AsyncDrop` trait may only be implemented for local structs, enums, and unions + --> $DIR/foreign-fundamental.rs:16:20 + | +LL | impl AsyncDrop for Pin { + | ^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0120`. diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 56f2be353e768..0d0c338d30269 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -37,19 +37,6 @@ error: malformed `crate_name` attribute input LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` -error: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:90:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL | #[coverage(off)] - | +++++ -LL | #[coverage(on)] - | ++++ - error: malformed `no_sanitize` attribute input --> $DIR/malformed-attrs.rs:92:1 | @@ -460,6 +447,19 @@ error[E0539]: malformed `link_section` attribute input LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` +error[E0539]: malformed `coverage` attribute input + --> $DIR/malformed-attrs.rs:90:1 + | +LL | #[coverage] + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[coverage(off)] + | +++++ +LL | #[coverage(on)] + | ++++ + error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:97:1 | diff --git a/tests/ui/consts/const-compare-bytes-ub.rs b/tests/ui/consts/const-compare-bytes-ub.rs index 0bc8585a4eed1..7e3df92a2bf5a 100644 --- a/tests/ui/consts/const-compare-bytes-ub.rs +++ b/tests/ui/consts/const-compare-bytes-ub.rs @@ -1,6 +1,6 @@ //@ check-fail -#![feature(core_intrinsics)] +#![feature(core_intrinsics, const_cmp)] use std::intrinsics::compare_bytes; use std::mem::MaybeUninit; diff --git a/tests/ui/consts/const-compare-bytes.rs b/tests/ui/consts/const-compare-bytes.rs index cd5cdfd0400ec..9563375555cfd 100644 --- a/tests/ui/consts/const-compare-bytes.rs +++ b/tests/ui/consts/const-compare-bytes.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(core_intrinsics)] +#![feature(core_intrinsics, const_cmp)] use std::intrinsics::compare_bytes; fn main() { diff --git a/tests/ui/consts/const-eval/auxiliary/stability.rs b/tests/ui/consts/const-eval/auxiliary/stability.rs index e615955186020..48ced3bc51e62 100644 --- a/tests/ui/consts/const-eval/auxiliary/stability.rs +++ b/tests/ui/consts/const-eval/auxiliary/stability.rs @@ -1,10 +1,11 @@ // Crate that exports a const fn. Used for testing cross-crate. -#![crate_type="rlib"] +#![crate_type = "rlib"] #![stable(feature = "rust1", since = "1.0.0")] - #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature="foo", issue = "none")] -pub const fn foo() -> u32 { 42 } +#[rustc_const_unstable(feature = "foo", issue = "none")] +pub const fn foo() -> u32 { + 42 +} diff --git a/tests/ui/coverage-attr/bad-attr-ice.feat.stderr b/tests/ui/coverage-attr/bad-attr-ice.feat.stderr index dc84394fe3c0c..5a003af42da57 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.feat.stderr +++ b/tests/ui/coverage-attr/bad-attr-ice.feat.stderr @@ -1,10 +1,10 @@ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/bad-attr-ice.rs:11:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ @@ -13,3 +13,4 @@ LL | #[coverage(on)] error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr b/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr index 49b8974bfdfb8..4501e5e9dc821 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr +++ b/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr @@ -1,26 +1,27 @@ -error: malformed `coverage` attribute input +error[E0658]: the `#[coverage]` attribute is an experimental feature --> $DIR/bad-attr-ice.rs:11:1 | LL | #[coverage] | ^^^^^^^^^^^ | -help: the following are the possible correct uses - | -LL | #[coverage(off)] - | +++++ -LL | #[coverage(on)] - | ++++ + = note: see issue #84605 for more information + = help: add `#![feature(coverage_attribute)]` 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]: the `#[coverage]` attribute is an experimental feature +error[E0539]: malformed `coverage` attribute input --> $DIR/bad-attr-ice.rs:11:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | - = note: see issue #84605 for more information - = help: add `#![feature(coverage_attribute)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: try changing it to one of the following valid forms of the attribute + | +LL | #[coverage(off)] + | +++++ +LL | #[coverage(on)] + | ++++ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0539, E0658. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/bad-syntax.stderr b/tests/ui/coverage-attr/bad-syntax.stderr index fa500b542097d..927f61da08db8 100644 --- a/tests/ui/coverage-attr/bad-syntax.stderr +++ b/tests/ui/coverage-attr/bad-syntax.stderr @@ -1,23 +1,59 @@ -error: malformed `coverage` attribute input +error: expected identifier, found `,` + --> $DIR/bad-syntax.rs:44:12 + | +LL | #[coverage(,off)] + | ^ expected identifier + | +help: remove this comma + | +LL - #[coverage(,off)] +LL + #[coverage(off)] + | + +error: multiple `coverage` attributes + --> $DIR/bad-syntax.rs:9:1 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/bad-syntax.rs:10:1 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ + +error: multiple `coverage` attributes + --> $DIR/bad-syntax.rs:13:1 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/bad-syntax.rs:14:1 + | +LL | #[coverage(on)] + | ^^^^^^^^^^^^^^^ + +error[E0539]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:17:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:20:1 | LL | #[coverage = true] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = true] LL + #[coverage(off)] @@ -26,26 +62,30 @@ LL - #[coverage = true] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0805]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:23:1 | LL | #[coverage()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^--^ + | | + | expected a single argument here | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++ LL | #[coverage(on)] | ++ -error: malformed `coverage` attribute input +error[E0805]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:26:1 | LL | #[coverage(off, off)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^----------^ + | | + | expected a single argument here | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(off, off)] LL + #[coverage(off)] @@ -54,13 +94,15 @@ LL - #[coverage(off, off)] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0805]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:29:1 | LL | #[coverage(off, on)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^---------^ + | | + | expected a single argument here | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(off, on)] LL + #[coverage(off)] @@ -69,13 +111,15 @@ LL - #[coverage(off, on)] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:32:1 | LL | #[coverage(bogus)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^-----^^ + | | + | valid arguments are `on` or `off` | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(bogus)] LL + #[coverage(off)] @@ -84,13 +128,15 @@ LL - #[coverage(bogus)] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0805]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:35:1 | LL | #[coverage(bogus, off)] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^------------^ + | | + | expected a single argument here | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(bogus, off)] LL + #[coverage(off)] @@ -99,13 +145,15 @@ LL - #[coverage(bogus, off)] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0805]: malformed `coverage` attribute input --> $DIR/bad-syntax.rs:38:1 | LL | #[coverage(off, bogus)] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^------------^ + | | + | expected a single argument here | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(off, bogus)] LL + #[coverage(off)] @@ -114,41 +162,7 @@ LL - #[coverage(off, bogus)] LL + #[coverage(on)] | -error: expected identifier, found `,` - --> $DIR/bad-syntax.rs:44:12 - | -LL | #[coverage(,off)] - | ^ expected identifier - | -help: remove this comma - | -LL - #[coverage(,off)] -LL + #[coverage(off)] - | - -error: multiple `coverage` attributes - --> $DIR/bad-syntax.rs:9:1 - | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/bad-syntax.rs:10:1 - | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ - -error: multiple `coverage` attributes - --> $DIR/bad-syntax.rs:13:1 - | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/bad-syntax.rs:14:1 - | -LL | #[coverage(on)] - | ^^^^^^^^^^^^^^^ - error: aborting due to 11 previous errors +Some errors have detailed explanations: E0539, E0805. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs index ffd9afe2ce186..8171dbbf69278 100644 --- a/tests/ui/coverage-attr/name-value.rs +++ b/tests/ui/coverage-attr/name-value.rs @@ -20,7 +20,6 @@ mod my_mod_inner { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR [E0788] struct MyStruct; #[coverage = "off"] @@ -28,22 +27,18 @@ struct MyStruct; impl MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32 = 7; } #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR [E0788] trait MyTrait { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] type T; } @@ -52,12 +47,10 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32 = 8; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] type T = (); } diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index f24db78415e39..a838ec5df8ead 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -1,10 +1,10 @@ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/name-value.rs:12:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -13,28 +13,28 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/name-value.rs:17:5 | LL | #![coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #![coverage = "off"] -LL + #![coverage(off)] +LL + #[coverage(off)] | LL - #![coverage = "off"] -LL + #![coverage(on)] +LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/name-value.rs:21:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -43,13 +43,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:26:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:25:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -58,13 +58,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:29:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:28:5 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -73,13 +73,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:35:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:33:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -88,13 +88,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:39:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:36:5 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -103,13 +103,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:44:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:40:5 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -118,13 +118,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:50:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:45:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -133,13 +133,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:53:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:48:5 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -148,13 +148,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:58:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:52:5 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -163,13 +163,13 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: malformed `coverage` attribute input - --> $DIR/name-value.rs:64:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/name-value.rs:57:1 | LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage = "off"] LL + #[coverage(off)] @@ -178,87 +178,6 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:21:1 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | struct MyStruct; - | ---------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:35:1 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | / trait MyTrait { -LL | | #[coverage = "off"] -... | -LL | | type T; -LL | | } - | |_- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:39:5 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | const X: u32; - | ------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:44:5 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | type T; - | ------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:29:5 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | const X: u32 = 7; - | ----------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:53:5 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | const X: u32 = 8; - | ----------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/name-value.rs:58:5 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | type T = (); - | ------------ not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error: aborting due to 19 previous errors +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0788`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/subword.stderr b/tests/ui/coverage-attr/subword.stderr index a5d1a492181be..32a09a10c8492 100644 --- a/tests/ui/coverage-attr/subword.stderr +++ b/tests/ui/coverage-attr/subword.stderr @@ -1,10 +1,12 @@ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/subword.rs:8:1 | LL | #[coverage(yes(milord))] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^-----------^^ + | | + | valid arguments are `on` or `off` | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(yes(milord))] LL + #[coverage(off)] @@ -13,13 +15,15 @@ LL - #[coverage(yes(milord))] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/subword.rs:11:1 | LL | #[coverage(no(milord))] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^----------^^ + | | + | valid arguments are `on` or `off` | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(no(milord))] LL + #[coverage(off)] @@ -28,13 +32,15 @@ LL - #[coverage(no(milord))] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/subword.rs:14:1 | LL | #[coverage(yes = "milord")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^--------------^^ + | | + | valid arguments are `on` or `off` | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(yes = "milord")] LL + #[coverage(off)] @@ -43,13 +49,15 @@ LL - #[coverage(yes = "milord")] LL + #[coverage(on)] | -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/subword.rs:17:1 | LL | #[coverage(no = "milord")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^-------------^^ + | | + | valid arguments are `on` or `off` | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL - #[coverage(no = "milord")] LL + #[coverage(off)] @@ -60,3 +68,4 @@ LL + #[coverage(on)] error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs index d0f743938f3af..81bd558b8b002 100644 --- a/tests/ui/coverage-attr/word-only.rs +++ b/tests/ui/coverage-attr/word-only.rs @@ -20,7 +20,6 @@ mod my_mod_inner { #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR [E0788] struct MyStruct; #[coverage] @@ -28,22 +27,18 @@ struct MyStruct; impl MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32 = 7; } #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR [E0788] trait MyTrait { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32; #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] type T; } @@ -52,12 +47,10 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] const X: u32 = 8; #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR [E0788] type T = (); } diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index 2773db9c85786..dd161360a5c4b 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -1,240 +1,161 @@ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/word-only.rs:12:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/word-only.rs:17:5 | LL | #![coverage] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute + | +LL - #![coverage] +LL + #[coverage(off)] + | +LL - #![coverage] +LL + #[coverage(on)] | -LL | #![coverage(off)] - | +++++ -LL | #![coverage(on)] - | ++++ -error: malformed `coverage` attribute input +error[E0539]: malformed `coverage` attribute input --> $DIR/word-only.rs:21:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:26:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:25:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:29:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:28:5 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:35:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:33:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:39:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:36:5 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:44:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:40:5 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:50:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:45:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:53:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:48:5 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:58:5 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:52:5 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error: malformed `coverage` attribute input - --> $DIR/word-only.rs:64:1 +error[E0539]: malformed `coverage` attribute input + --> $DIR/word-only.rs:57:1 | LL | #[coverage] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | LL | #[coverage(off)] | +++++ LL | #[coverage(on)] | ++++ -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:21:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | struct MyStruct; - | ---------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:35:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | / trait MyTrait { -LL | | #[coverage] -... | -LL | | type T; -LL | | } - | |_- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:39:5 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | const X: u32; - | ------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:44:5 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | type T; - | ------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:29:5 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | const X: u32 = 7; - | ----------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:53:5 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | const X: u32 = 8; - | ----------------- not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error[E0788]: coverage attribute not allowed here - --> $DIR/word-only.rs:58:5 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | type T = (); - | ------------ not a function, impl block, or module - | - = help: coverage attribute can be applied to a function (with body), impl block, or module - -error: aborting due to 19 previous errors +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0788`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/deduplicate-diagnostics.deduplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr similarity index 80% rename from tests/ui/deduplicate-diagnostics.deduplicate.stderr rename to tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr index 5df2c687bddc2..c0d568eb5384e 100644 --- a/tests/ui/deduplicate-diagnostics.deduplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr @@ -1,11 +1,11 @@ error[E0452]: malformed lint attribute input - --> $DIR/deduplicate-diagnostics.rs:8:8 + --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument error: cannot find derive macro `Unresolved` in this scope - --> $DIR/deduplicate-diagnostics.rs:4:10 + --> $DIR/deduplicate-diagnostics.rs:6:10 | LL | #[derive(Unresolved)] | ^^^^^^^^^^ diff --git a/tests/ui/deduplicate-diagnostics.duplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr similarity index 81% rename from tests/ui/deduplicate-diagnostics.duplicate.stderr rename to tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr index 48e2ba7b86aa4..74d7066293f30 100644 --- a/tests/ui/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr @@ -1,17 +1,17 @@ error[E0452]: malformed lint attribute input - --> $DIR/deduplicate-diagnostics.rs:8:8 + --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument error: cannot find derive macro `Unresolved` in this scope - --> $DIR/deduplicate-diagnostics.rs:4:10 + --> $DIR/deduplicate-diagnostics.rs:6:10 | LL | #[derive(Unresolved)] | ^^^^^^^^^^ error: cannot find derive macro `Unresolved` in this scope - --> $DIR/deduplicate-diagnostics.rs:4:10 + --> $DIR/deduplicate-diagnostics.rs:6:10 | LL | #[derive(Unresolved)] | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | #[derive(Unresolved)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input - --> $DIR/deduplicate-diagnostics.rs:8:8 + --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument @@ -27,7 +27,7 @@ LL | #[deny("literal")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0452]: malformed lint attribute input - --> $DIR/deduplicate-diagnostics.rs:8:8 + --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] | ^^^^^^^^^ bad attribute argument diff --git a/tests/ui/deduplicate-diagnostics.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs similarity index 84% rename from tests/ui/deduplicate-diagnostics.rs rename to tests/ui/diagnostic-flags/deduplicate-diagnostics.rs index 299c1f5f46108..48705266e3584 100644 --- a/tests/ui/deduplicate-diagnostics.rs +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs @@ -1,3 +1,5 @@ +//! Test that `-Z deduplicate-diagnostics` flag properly deduplicates diagnostic messages. + //@ revisions: duplicate deduplicate //@[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes diff --git a/tests/ui/error-codes/E0120.rs b/tests/ui/error-codes/E0120.rs index 35f544fddfbfc..4e5cc7d6833b1 100644 --- a/tests/ui/error-codes/E0120.rs +++ b/tests/ui/error-codes/E0120.rs @@ -1,4 +1,4 @@ -trait MyTrait { fn foo() {} } +trait MyTrait { fn foo(&self) {} } impl Drop for dyn MyTrait { //~^ ERROR E0120 diff --git a/tests/ui/expr/syntax-edge-cases-lint-clean.rs b/tests/ui/expr/weird-exprs.rs similarity index 100% rename from tests/ui/expr/syntax-edge-cases-lint-clean.rs rename to tests/ui/expr/weird-exprs.rs diff --git a/tests/ui/log-poly.rs b/tests/ui/fmt/println-debug-different-types.rs similarity index 72% rename from tests/ui/log-poly.rs rename to tests/ui/fmt/println-debug-different-types.rs index 64994a558174c..9e21be1f03fca 100644 --- a/tests/ui/log-poly.rs +++ b/tests/ui/fmt/println-debug-different-types.rs @@ -1,8 +1,10 @@ +//! Smoke test for println!() with debug format specifiers. + //@ run-pass #[derive(Debug)] enum Numbers { - Three + Three, } pub fn main() { diff --git a/tests/ui/darwin-ld64.rs b/tests/ui/linking/ld64-cross-compilation.rs similarity index 71% rename from tests/ui/darwin-ld64.rs rename to tests/ui/linking/ld64-cross-compilation.rs index 75acc07a002c4..d6c6d1ff91def 100644 --- a/tests/ui/darwin-ld64.rs +++ b/tests/ui/linking/ld64-cross-compilation.rs @@ -1,11 +1,11 @@ +//! This is a regression test for https://github.com/rust-lang/rust/issues/140686. +//! Although this is a ld64(ld-classic) bug, we still need to support it +//! due to cross-compilation and support for older Xcode. + //@ compile-flags: -Copt-level=3 -Ccodegen-units=256 -Clink-arg=-ld_classic //@ run-pass //@ only-x86_64-apple-darwin -// This is a regression test for https://github.com/rust-lang/rust/issues/140686. -// Although this is a ld64(ld-classic) bug, we still need to support it -// due to cross-compilation and support for older Xcode. - fn main() { let dst: Vec = Vec::new(); let len = broken_func(std::hint::black_box(2), dst); diff --git a/tests/crashes/128094.rs b/tests/ui/mir/gvn-nonsensical-coroutine-layout.rs similarity index 53% rename from tests/crashes/128094.rs rename to tests/ui/mir/gvn-nonsensical-coroutine-layout.rs index 56d09d78bed91..f0d174cd01b0a 100644 --- a/tests/crashes/128094.rs +++ b/tests/ui/mir/gvn-nonsensical-coroutine-layout.rs @@ -1,15 +1,19 @@ -//@ known-bug: rust-lang/rust#128094 +//! Verify that we do not ICE when a coroutine body is malformed. //@ compile-flags: -Zmir-enable-passes=+GVN //@ edition: 2018 pub enum Request { TestSome(T), + //~^ ERROR cannot find type `T` in this scope [E0412] } pub async fn handle_event(event: Request) { async move { static instance: Request = Request { bar: 17 }; + //~^ ERROR expected struct, variant or union type, found enum `Request` [E0574] &instance } .await; } + +fn main() {} diff --git a/tests/ui/mir/gvn-nonsensical-coroutine-layout.stderr b/tests/ui/mir/gvn-nonsensical-coroutine-layout.stderr new file mode 100644 index 0000000000000..abc7b16ca7415 --- /dev/null +++ b/tests/ui/mir/gvn-nonsensical-coroutine-layout.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/gvn-nonsensical-coroutine-layout.rs:6:14 + | +LL | TestSome(T), + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | pub enum Request { + | +++ + +error[E0574]: expected struct, variant or union type, found enum `Request` + --> $DIR/gvn-nonsensical-coroutine-layout.rs:12:36 + | +LL | static instance: Request = Request { bar: 17 }; + | ^^^^^^^ not a struct, variant or union type + | +help: consider importing this struct instead + | +LL + use std::error::Request; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0574. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/crashes/135128.rs b/tests/ui/mir/gvn-nonsensical-sized-str.rs similarity index 51% rename from tests/crashes/135128.rs rename to tests/ui/mir/gvn-nonsensical-sized-str.rs index c718b758dc69b..29a82f8ce2a16 100644 --- a/tests/crashes/135128.rs +++ b/tests/ui/mir/gvn-nonsensical-sized-str.rs @@ -1,13 +1,16 @@ -//@ known-bug: #135128 +//! Verify that we do not ICE when optimizing bodies with nonsensical bounds. //@ compile-flags: -Copt-level=1 //@ edition: 2021 +//@ build-pass #![feature(trivial_bounds)] async fn return_str() -> str where str: Sized, + //~^ WARN trait bound str: Sized does not depend on any type or lifetime parameters { *"Sized".to_string().into_boxed_str() } + fn main() {} diff --git a/tests/ui/mir/gvn-nonsensical-sized-str.stderr b/tests/ui/mir/gvn-nonsensical-sized-str.stderr new file mode 100644 index 0000000000000..08f0193e9f61c --- /dev/null +++ b/tests/ui/mir/gvn-nonsensical-sized-str.stderr @@ -0,0 +1,10 @@ +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/gvn-nonsensical-sized-str.rs:10:10 + | +LL | str: Sized, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lexical-scopes.rs b/tests/ui/shadowed/shadowing-generic-item.rs similarity index 76% rename from tests/ui/lexical-scopes.rs rename to tests/ui/shadowed/shadowing-generic-item.rs index 46cfdf1efa8f0..c3a0ced04e7f0 100644 --- a/tests/ui/lexical-scopes.rs +++ b/tests/ui/shadowed/shadowing-generic-item.rs @@ -1,3 +1,5 @@ +//! Test that generic parameters shadow structs and modules with the same name. + struct T { i: i32 } fn f() { let t = T { i: 0 }; //~ ERROR expected struct, variant or union type, found type parameter `T` diff --git a/tests/ui/lexical-scopes.stderr b/tests/ui/shadowed/shadowing-generic-item.stderr similarity index 89% rename from tests/ui/lexical-scopes.stderr rename to tests/ui/shadowed/shadowing-generic-item.stderr index f0eaa1a5c64c4..55a0bb36ea80b 100644 --- a/tests/ui/lexical-scopes.stderr +++ b/tests/ui/shadowed/shadowing-generic-item.stderr @@ -1,5 +1,5 @@ error[E0574]: expected struct, variant or union type, found type parameter `T` - --> $DIR/lexical-scopes.rs:3:13 + --> $DIR/shadowing-generic-item.rs:5:13 | LL | struct T { i: i32 } | - you might have meant to refer to this struct @@ -9,7 +9,7 @@ LL | let t = T { i: 0 }; | ^ not a struct, variant or union type error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope - --> $DIR/lexical-scopes.rs:10:10 + --> $DIR/shadowing-generic-item.rs:12:10 | LL | fn g() { | --- function or associated item `f` not found for this type parameter diff --git a/tests/ui/simd/generics.rs b/tests/ui/simd/generics.rs index 1ae08fef7cdf7..54e76f7bc5d8c 100644 --- a/tests/ui/simd/generics.rs +++ b/tests/ui/simd/generics.rs @@ -2,24 +2,18 @@ #![allow(non_camel_case_types)] #![feature(repr_simd, core_intrinsics)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_add; use std::ops; -#[repr(simd)] -#[derive(Copy, Clone)] -struct f32x4([f32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct A([f32; N]); +type A = Simd; -#[repr(simd)] -#[derive(Copy, Clone)] -struct B([T; 4]); +type B = Simd; -#[repr(simd)] -#[derive(Copy, Clone)] -struct C([T; N]); +type C = Simd; fn add>(lhs: T, rhs: T) -> T { lhs + rhs @@ -33,48 +27,24 @@ impl ops::Add for f32x4 { } } -impl ops::Add for A<4> { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - unsafe { simd_add(self, rhs) } - } -} - -impl ops::Add for B { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - unsafe { simd_add(self, rhs) } - } -} - -impl ops::Add for C { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - unsafe { simd_add(self, rhs) } - } -} - pub fn main() { let x = [1.0f32, 2.0f32, 3.0f32, 4.0f32]; let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32]; // lame-o - let a = f32x4([1.0f32, 2.0f32, 3.0f32, 4.0f32]); - let f32x4([a0, a1, a2, a3]) = add(a, a); + let a = f32x4::from_array([1.0f32, 2.0f32, 3.0f32, 4.0f32]); + let [a0, a1, a2, a3] = add(a, a).into_array(); assert_eq!(a0, 2.0f32); assert_eq!(a1, 4.0f32); assert_eq!(a2, 6.0f32); assert_eq!(a3, 8.0f32); - let a = A(x); - assert_eq!(add(a, a).0, y); + let a = A::from_array(x); + assert_eq!(add(a, a).into_array(), y); - let b = B(x); - assert_eq!(add(b, b).0, y); + let b = B::from_array(x); + assert_eq!(add(b, b).into_array(), y); - let c = C(x); - assert_eq!(add(c, c).0, y); + let c = C::from_array(x); + assert_eq!(add(c, c).into_array(), y); } diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index 01fed8537d0b9..743aae8d1c319 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -11,9 +11,9 @@ #![feature(repr_simd, intrinsics, core_intrinsics)] #![allow(non_camel_case_types)] -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub [f32; 4]); +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; use std::intrinsics::simd::*; @@ -27,19 +27,19 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => {{ let a = $a; let b = $b; - assert_approx_eq_f32!(a.0[0], b.0[0]); - assert_approx_eq_f32!(a.0[1], b.0[1]); - assert_approx_eq_f32!(a.0[2], b.0[2]); - assert_approx_eq_f32!(a.0[3], b.0[3]); + assert_approx_eq_f32!(a[0], b[0]); + assert_approx_eq_f32!(a[1], b[1]); + assert_approx_eq_f32!(a[2], b[2]); + assert_approx_eq_f32!(a[3], b[3]); }}; } fn main() { - let x = f32x4([1.0, 1.0, 1.0, 1.0]); - let y = f32x4([-1.0, -1.0, -1.0, -1.0]); - let z = f32x4([0.0, 0.0, 0.0, 0.0]); + let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]); + let y = f32x4::from_array([-1.0, -1.0, -1.0, -1.0]); + let z = f32x4::from_array([0.0, 0.0, 0.0, 0.0]); - let h = f32x4([0.5, 0.5, 0.5, 0.5]); + let h = f32x4::from_array([0.5, 0.5, 0.5, 0.5]); unsafe { let r = simd_fabs(y); diff --git a/tests/ui/simd/intrinsic/float-minmax-pass.rs b/tests/ui/simd/intrinsic/float-minmax-pass.rs index 00c0d8cea3fa5..12210ba0ad120 100644 --- a/tests/ui/simd/intrinsic/float-minmax-pass.rs +++ b/tests/ui/simd/intrinsic/float-minmax-pass.rs @@ -6,15 +6,15 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub [f32; 4]); +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; use std::intrinsics::simd::*; fn main() { - let x = f32x4([1.0, 2.0, 3.0, 4.0]); - let y = f32x4([2.0, 1.0, 4.0, 3.0]); + let x = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); + let y = f32x4::from_array([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -23,13 +23,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4([nan, nan, nan, nan]); + let n = f32x4::from_array([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4([1.0, 1.0, 3.0, 3.0]); + let e = f32x4::from_array([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -39,7 +39,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4([2.0, 2.0, 4.0, 4.0]); + let e = f32x4::from_array([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs index 4c97fb2141d09..bf38a8b17202f 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs @@ -2,80 +2,77 @@ #![allow(non_camel_case_types)] #![feature(repr_simd, core_intrinsics)] -#[repr(simd)] -#[derive(Copy, Clone)] -struct i32x4(pub [i32; 4]); +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -struct U32([u32; N]); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct f32x4(pub [f32; 4]); +type U32 = Simd; macro_rules! all_eq { - ($a: expr, $b: expr) => {{ + ($a: expr, $b: expr $(,)?) => {{ let a = $a; let b = $b; - assert!(a.0 == b.0); + assert!(a == b); }}; } use std::intrinsics::simd::*; fn main() { - let x1 = i32x4([1, 2, 3, 4]); - let y1 = U32::<4>([1, 2, 3, 4]); - let z1 = f32x4([1.0, 2.0, 3.0, 4.0]); - let x2 = i32x4([2, 3, 4, 5]); - let y2 = U32::<4>([2, 3, 4, 5]); - let z2 = f32x4([2.0, 3.0, 4.0, 5.0]); - let x3 = i32x4([0, i32::MAX, i32::MIN, -1_i32]); - let y3 = U32::<4>([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]); + let x1 = i32x4::from_array([1, 2, 3, 4]); + let y1 = U32::<4>::from_array([1, 2, 3, 4]); + let z1 = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); + let x2 = i32x4::from_array([2, 3, 4, 5]); + let y2 = U32::<4>::from_array([2, 3, 4, 5]); + let z2 = f32x4::from_array([2.0, 3.0, 4.0, 5.0]); + let x3 = i32x4::from_array([0, i32::MAX, i32::MIN, -1_i32]); + let y3 = U32::<4>::from_array([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]); unsafe { - all_eq!(simd_add(x1, x2), i32x4([3, 5, 7, 9])); - all_eq!(simd_add(x2, x1), i32x4([3, 5, 7, 9])); - all_eq!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); - all_eq!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); - all_eq!(simd_add(z1, z2), f32x4([3.0, 5.0, 7.0, 9.0])); - all_eq!(simd_add(z2, z1), f32x4([3.0, 5.0, 7.0, 9.0])); - - all_eq!(simd_mul(x1, x2), i32x4([2, 6, 12, 20])); - all_eq!(simd_mul(x2, x1), i32x4([2, 6, 12, 20])); - all_eq!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); - all_eq!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); - all_eq!(simd_mul(z1, z2), f32x4([2.0, 6.0, 12.0, 20.0])); - all_eq!(simd_mul(z2, z1), f32x4([2.0, 6.0, 12.0, 20.0])); - - all_eq!(simd_sub(x2, x1), i32x4([1, 1, 1, 1])); - all_eq!(simd_sub(x1, x2), i32x4([-1, -1, -1, -1])); - all_eq!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); - all_eq!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); - all_eq!(simd_sub(z2, z1), f32x4([1.0, 1.0, 1.0, 1.0])); - all_eq!(simd_sub(z1, z2), f32x4([-1.0, -1.0, -1.0, -1.0])); - - all_eq!(simd_div(x1, x1), i32x4([1, 1, 1, 1])); - all_eq!(simd_div(i32x4([2, 4, 6, 8]), i32x4([2, 2, 2, 2])), x1); - all_eq!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); - all_eq!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); - all_eq!(simd_div(z1, z1), f32x4([1.0, 1.0, 1.0, 1.0])); - all_eq!(simd_div(z1, z2), f32x4([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0])); - all_eq!(simd_div(z2, z1), f32x4([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0])); - - all_eq!(simd_rem(x1, x1), i32x4([0, 0, 0, 0])); - all_eq!(simd_rem(x2, x1), i32x4([0, 1, 1, 1])); - all_eq!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); - all_eq!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); - all_eq!(simd_rem(z1, z1), f32x4([0.0, 0.0, 0.0, 0.0])); + all_eq!(simd_add(x1, x2), i32x4::from_array([3, 5, 7, 9])); + all_eq!(simd_add(x2, x1), i32x4::from_array([3, 5, 7, 9])); + all_eq!(simd_add(y1, y2), U32::<4>::from_array([3, 5, 7, 9])); + all_eq!(simd_add(y2, y1), U32::<4>::from_array([3, 5, 7, 9])); + all_eq!(simd_add(z1, z2), f32x4::from_array([3.0, 5.0, 7.0, 9.0])); + all_eq!(simd_add(z2, z1), f32x4::from_array([3.0, 5.0, 7.0, 9.0])); + + all_eq!(simd_mul(x1, x2), i32x4::from_array([2, 6, 12, 20])); + all_eq!(simd_mul(x2, x1), i32x4::from_array([2, 6, 12, 20])); + all_eq!(simd_mul(y1, y2), U32::<4>::from_array([2, 6, 12, 20])); + all_eq!(simd_mul(y2, y1), U32::<4>::from_array([2, 6, 12, 20])); + all_eq!(simd_mul(z1, z2), f32x4::from_array([2.0, 6.0, 12.0, 20.0])); + all_eq!(simd_mul(z2, z1), f32x4::from_array([2.0, 6.0, 12.0, 20.0])); + + all_eq!(simd_sub(x2, x1), i32x4::from_array([1, 1, 1, 1])); + all_eq!(simd_sub(x1, x2), i32x4::from_array([-1, -1, -1, -1])); + all_eq!(simd_sub(y2, y1), U32::<4>::from_array([1, 1, 1, 1])); + all_eq!(simd_sub(y1, y2), U32::<4>::from_array([!0, !0, !0, !0])); + all_eq!(simd_sub(z2, z1), f32x4::from_array([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_sub(z1, z2), f32x4::from_array([-1.0, -1.0, -1.0, -1.0])); + + all_eq!(simd_div(x1, x1), i32x4::from_array([1, 1, 1, 1])); + all_eq!(simd_div(i32x4::from_array([2, 4, 6, 8]), i32x4::from_array([2, 2, 2, 2])), x1); + all_eq!(simd_div(y1, y1), U32::<4>::from_array([1, 1, 1, 1])); + all_eq!( + simd_div(U32::<4>::from_array([2, 4, 6, 8]), U32::<4>::from_array([2, 2, 2, 2])), + y1, + ); + all_eq!(simd_div(z1, z1), f32x4::from_array([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_div(z1, z2), f32x4::from_array([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0])); + all_eq!(simd_div(z2, z1), f32x4::from_array([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0])); + + all_eq!(simd_rem(x1, x1), i32x4::from_array([0, 0, 0, 0])); + all_eq!(simd_rem(x2, x1), i32x4::from_array([0, 1, 1, 1])); + all_eq!(simd_rem(y1, y1), U32::<4>::from_array([0, 0, 0, 0])); + all_eq!(simd_rem(y2, y1), U32::<4>::from_array([0, 1, 1, 1])); + all_eq!(simd_rem(z1, z1), f32x4::from_array([0.0, 0.0, 0.0, 0.0])); all_eq!(simd_rem(z1, z2), z1); - all_eq!(simd_rem(z2, z1), f32x4([0.0, 1.0, 1.0, 1.0])); + all_eq!(simd_rem(z2, z1), f32x4::from_array([0.0, 1.0, 1.0, 1.0])); - all_eq!(simd_shl(x1, x2), i32x4([1 << 2, 2 << 3, 3 << 4, 4 << 5])); - all_eq!(simd_shl(x2, x1), i32x4([2 << 1, 3 << 2, 4 << 3, 5 << 4])); - all_eq!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); - all_eq!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(x1, x2), i32x4::from_array([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(x2, x1), i32x4::from_array([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(y1, y2), U32::<4>::from_array([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(y2, y1), U32::<4>::from_array([2 << 1, 3 << 2, 4 << 3, 5 << 4])); // test right-shift by assuming left-shift is correct all_eq!(simd_shr(simd_shl(x1, x2), x2), x1); @@ -85,7 +82,7 @@ fn main() { all_eq!( simd_funnel_shl(x1, x2, x1), - i32x4([ + i32x4::from_array([ (1 << 1) | (2 >> 31), (2 << 2) | (3 >> 30), (3 << 3) | (4 >> 29), @@ -94,7 +91,7 @@ fn main() { ); all_eq!( simd_funnel_shl(x2, x1, x1), - i32x4([ + i32x4::from_array([ (2 << 1) | (1 >> 31), (3 << 2) | (2 >> 30), (4 << 3) | (3 >> 29), @@ -103,7 +100,7 @@ fn main() { ); all_eq!( simd_funnel_shl(y1, y2, y1), - U32::<4>([ + U32::<4>::from_array([ (1 << 1) | (2 >> 31), (2 << 2) | (3 >> 30), (3 << 3) | (4 >> 29), @@ -112,7 +109,7 @@ fn main() { ); all_eq!( simd_funnel_shl(y2, y1, y1), - U32::<4>([ + U32::<4>::from_array([ (2 << 1) | (1 >> 31), (3 << 2) | (2 >> 30), (4 << 3) | (3 >> 29), @@ -122,7 +119,7 @@ fn main() { all_eq!( simd_funnel_shr(x1, x2, x1), - i32x4([ + i32x4::from_array([ (1 << 31) | (2 >> 1), (2 << 30) | (3 >> 2), (3 << 29) | (4 >> 3), @@ -131,7 +128,7 @@ fn main() { ); all_eq!( simd_funnel_shr(x2, x1, x1), - i32x4([ + i32x4::from_array([ (2 << 31) | (1 >> 1), (3 << 30) | (2 >> 2), (4 << 29) | (3 >> 3), @@ -140,7 +137,7 @@ fn main() { ); all_eq!( simd_funnel_shr(y1, y2, y1), - U32::<4>([ + U32::<4>::from_array([ (1 << 31) | (2 >> 1), (2 << 30) | (3 >> 2), (3 << 29) | (4 >> 3), @@ -149,7 +146,7 @@ fn main() { ); all_eq!( simd_funnel_shr(y2, y1, y1), - U32::<4>([ + U32::<4>::from_array([ (2 << 31) | (1 >> 1), (3 << 30) | (2 >> 2), (4 << 29) | (3 >> 3), @@ -159,52 +156,69 @@ fn main() { // ensure we get logical vs. arithmetic shifts correct let (a, b, c, d) = (-12, -123, -1234, -12345); - all_eq!(simd_shr(i32x4([a, b, c, d]), x1), i32x4([a >> 1, b >> 2, c >> 3, d >> 4])); all_eq!( - simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), - U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4]) + simd_shr(i32x4::from_array([a, b, c, d]), x1), + i32x4::from_array([a >> 1, b >> 2, c >> 3, d >> 4]), + ); + all_eq!( + simd_shr(U32::<4>::from_array([a as u32, b as u32, c as u32, d as u32]), y1), + U32::<4>::from_array([ + (a as u32) >> 1, + (b as u32) >> 2, + (c as u32) >> 3, + (d as u32) >> 4, + ]), ); - all_eq!(simd_and(x1, x2), i32x4([0, 2, 0, 4])); - all_eq!(simd_and(x2, x1), i32x4([0, 2, 0, 4])); - all_eq!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); - all_eq!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); + all_eq!(simd_and(x1, x2), i32x4::from_array([0, 2, 0, 4])); + all_eq!(simd_and(x2, x1), i32x4::from_array([0, 2, 0, 4])); + all_eq!(simd_and(y1, y2), U32::<4>::from_array([0, 2, 0, 4])); + all_eq!(simd_and(y2, y1), U32::<4>::from_array([0, 2, 0, 4])); - all_eq!(simd_or(x1, x2), i32x4([3, 3, 7, 5])); - all_eq!(simd_or(x2, x1), i32x4([3, 3, 7, 5])); - all_eq!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); - all_eq!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); + all_eq!(simd_or(x1, x2), i32x4::from_array([3, 3, 7, 5])); + all_eq!(simd_or(x2, x1), i32x4::from_array([3, 3, 7, 5])); + all_eq!(simd_or(y1, y2), U32::<4>::from_array([3, 3, 7, 5])); + all_eq!(simd_or(y2, y1), U32::<4>::from_array([3, 3, 7, 5])); - all_eq!(simd_xor(x1, x2), i32x4([3, 1, 7, 1])); - all_eq!(simd_xor(x2, x1), i32x4([3, 1, 7, 1])); - all_eq!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); - all_eq!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_xor(x1, x2), i32x4::from_array([3, 1, 7, 1])); + all_eq!(simd_xor(x2, x1), i32x4::from_array([3, 1, 7, 1])); + all_eq!(simd_xor(y1, y2), U32::<4>::from_array([3, 1, 7, 1])); + all_eq!(simd_xor(y2, y1), U32::<4>::from_array([3, 1, 7, 1])); - all_eq!(simd_neg(x1), i32x4([-1, -2, -3, -4])); - all_eq!(simd_neg(x2), i32x4([-2, -3, -4, -5])); - all_eq!(simd_neg(z1), f32x4([-1.0, -2.0, -3.0, -4.0])); - all_eq!(simd_neg(z2), f32x4([-2.0, -3.0, -4.0, -5.0])); + all_eq!(simd_neg(x1), i32x4::from_array([-1, -2, -3, -4])); + all_eq!(simd_neg(x2), i32x4::from_array([-2, -3, -4, -5])); + all_eq!(simd_neg(z1), f32x4::from_array([-1.0, -2.0, -3.0, -4.0])); + all_eq!(simd_neg(z2), f32x4::from_array([-2.0, -3.0, -4.0, -5.0])); - all_eq!(simd_bswap(x1), i32x4([0x01000000, 0x02000000, 0x03000000, 0x04000000])); - all_eq!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000])); + all_eq!( + simd_bswap(x1), + i32x4::from_array([0x01000000, 0x02000000, 0x03000000, 0x04000000]), + ); + all_eq!( + simd_bswap(y1), + U32::<4>::from_array([0x01000000, 0x02000000, 0x03000000, 0x04000000]), + ); all_eq!( simd_bitreverse(x1), - i32x4([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000]) + i32x4::from_array([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000]) + ); + all_eq!( + simd_bitreverse(y1), + U32::<4>::from_array([0x80000000, 0x40000000, 0xc0000000, 0x20000000]), ); - all_eq!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000])); - all_eq!(simd_ctlz(x1), i32x4([31, 30, 30, 29])); - all_eq!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29])); + all_eq!(simd_ctlz(x1), i32x4::from_array([31, 30, 30, 29])); + all_eq!(simd_ctlz(y1), U32::<4>::from_array([31, 30, 30, 29])); - all_eq!(simd_ctpop(x1), i32x4([1, 1, 2, 1])); - all_eq!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1])); - all_eq!(simd_ctpop(x2), i32x4([1, 2, 1, 2])); - all_eq!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2])); - all_eq!(simd_ctpop(x3), i32x4([0, 31, 1, 32])); - all_eq!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32])); + all_eq!(simd_ctpop(x1), i32x4::from_array([1, 1, 2, 1])); + all_eq!(simd_ctpop(y1), U32::<4>::from_array([1, 1, 2, 1])); + all_eq!(simd_ctpop(x2), i32x4::from_array([1, 2, 1, 2])); + all_eq!(simd_ctpop(y2), U32::<4>::from_array([1, 2, 1, 2])); + all_eq!(simd_ctpop(x3), i32x4::from_array([0, 31, 1, 32])); + all_eq!(simd_ctpop(y3), U32::<4>::from_array([0, 31, 1, 32])); - all_eq!(simd_cttz(x1), i32x4([0, 1, 0, 2])); - all_eq!(simd_cttz(y1), U32::<4>([0, 1, 0, 2])); + all_eq!(simd_cttz(x1), i32x4::from_array([0, 1, 0, 2])); + all_eq!(simd_cttz(y1), U32::<4>::from_array([0, 1, 0, 2])); } } diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs index 4d12a312331a7..a997f12370347 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs @@ -4,26 +4,24 @@ #![allow(non_camel_case_types)] #![feature(repr_simd, core_intrinsics)] -use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub}; +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub [u32; 4]); +use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub}; -#[repr(simd)] -#[derive(Copy, Clone)] -struct I32([i32; N]); +type I32 = Simd; fn main() { // unsigned { const M: u32 = u32::MAX; - let a = u32x4([1, 2, 3, 4]); - let b = u32x4([2, 4, 6, 8]); - let m = u32x4([M, M, M, M]); - let m1 = u32x4([M - 1, M - 1, M - 1, M - 1]); - let z = u32x4([0, 0, 0, 0]); + let a = u32x4::from_array([1, 2, 3, 4]); + let b = u32x4::from_array([2, 4, 6, 8]); + let m = u32x4::from_array([M, M, M, M]); + let m1 = u32x4::from_array([M - 1, M - 1, M - 1, M - 1]); + let z = u32x4::from_array([0, 0, 0, 0]); unsafe { assert_eq!(simd_saturating_add(z, z), z); @@ -48,41 +46,41 @@ fn main() { const MIN: i32 = i32::MIN; const MAX: i32 = i32::MAX; - let a = I32::<4>([1, 2, 3, 4]); - let b = I32::<4>([2, 4, 6, 8]); - let c = I32::<4>([-1, -2, -3, -4]); - let d = I32::<4>([-2, -4, -6, -8]); + let a = I32::<4>::from_array([1, 2, 3, 4]); + let b = I32::<4>::from_array([2, 4, 6, 8]); + let c = I32::<4>::from_array([-1, -2, -3, -4]); + let d = I32::<4>::from_array([-2, -4, -6, -8]); - let max = I32::<4>([MAX, MAX, MAX, MAX]); - let max1 = I32::<4>([MAX - 1, MAX - 1, MAX - 1, MAX - 1]); - let min = I32::<4>([MIN, MIN, MIN, MIN]); - let min1 = I32::<4>([MIN + 1, MIN + 1, MIN + 1, MIN + 1]); + let max = I32::<4>::from_array([MAX, MAX, MAX, MAX]); + let max1 = I32::<4>::from_array([MAX - 1, MAX - 1, MAX - 1, MAX - 1]); + let min = I32::<4>::from_array([MIN, MIN, MIN, MIN]); + let min1 = I32::<4>::from_array([MIN + 1, MIN + 1, MIN + 1, MIN + 1]); - let z = I32::<4>([0, 0, 0, 0]); + let z = I32::<4>::from_array([0, 0, 0, 0]); unsafe { - assert_eq!(simd_saturating_add(z, z).0, z.0); - assert_eq!(simd_saturating_add(z, a).0, a.0); - assert_eq!(simd_saturating_add(b, z).0, b.0); - assert_eq!(simd_saturating_add(a, a).0, b.0); - assert_eq!(simd_saturating_add(a, max).0, max.0); - assert_eq!(simd_saturating_add(max, b).0, max.0); - assert_eq!(simd_saturating_add(max1, a).0, max.0); - assert_eq!(simd_saturating_add(min1, z).0, min1.0); - assert_eq!(simd_saturating_add(min, z).0, min.0); - assert_eq!(simd_saturating_add(min1, c).0, min.0); - assert_eq!(simd_saturating_add(min, c).0, min.0); - assert_eq!(simd_saturating_add(min1, d).0, min.0); - assert_eq!(simd_saturating_add(min, d).0, min.0); + assert_eq!(simd_saturating_add(z, z), z); + assert_eq!(simd_saturating_add(z, a), a); + assert_eq!(simd_saturating_add(b, z), b); + assert_eq!(simd_saturating_add(a, a), b); + assert_eq!(simd_saturating_add(a, max), max); + assert_eq!(simd_saturating_add(max, b), max); + assert_eq!(simd_saturating_add(max1, a), max); + assert_eq!(simd_saturating_add(min1, z), min1); + assert_eq!(simd_saturating_add(min, z), min); + assert_eq!(simd_saturating_add(min1, c), min); + assert_eq!(simd_saturating_add(min, c), min); + assert_eq!(simd_saturating_add(min1, d), min); + assert_eq!(simd_saturating_add(min, d), min); - assert_eq!(simd_saturating_sub(b, z).0, b.0); - assert_eq!(simd_saturating_sub(b, a).0, a.0); - assert_eq!(simd_saturating_sub(a, a).0, z.0); - assert_eq!(simd_saturating_sub(a, b).0, c.0); - assert_eq!(simd_saturating_sub(z, max).0, min1.0); - assert_eq!(simd_saturating_sub(min1, z).0, min1.0); - assert_eq!(simd_saturating_sub(min1, a).0, min.0); - assert_eq!(simd_saturating_sub(min1, b).0, min.0); + assert_eq!(simd_saturating_sub(b, z), b); + assert_eq!(simd_saturating_sub(b, a), a); + assert_eq!(simd_saturating_sub(a, a), z); + assert_eq!(simd_saturating_sub(a, b), c); + assert_eq!(simd_saturating_sub(z, max), min1); + assert_eq!(simd_saturating_sub(min1, z), min1); + assert_eq!(simd_saturating_sub(min1, a), min); + assert_eq!(simd_saturating_sub(min1, b), min); } } } diff --git a/tests/ui/simd/intrinsic/generic-as.rs b/tests/ui/simd/intrinsic/generic-as.rs index da53211cbc743..f9ed416b6ff54 100644 --- a/tests/ui/simd/intrinsic/generic-as.rs +++ b/tests/ui/simd/intrinsic/generic-as.rs @@ -2,45 +2,47 @@ #![feature(repr_simd, core_intrinsics)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_as; -#[derive(Copy, Clone)] -#[repr(simd)] -struct V([T; 2]); +type V = Simd; fn main() { unsafe { - let u = V::([u32::MIN, u32::MAX]); + let u: V:: = Simd([u32::MIN, u32::MAX]); let i: V = simd_as(u); - assert_eq!(i.0[0], u.0[0] as i16); - assert_eq!(i.0[1], u.0[1] as i16); + assert_eq!(i[0], u[0] as i16); + assert_eq!(i[1], u[1] as i16); } unsafe { - let f = V::([f32::MIN, f32::MAX]); + let f: V:: = Simd([f32::MIN, f32::MAX]); let i: V = simd_as(f); - assert_eq!(i.0[0], f.0[0] as i16); - assert_eq!(i.0[1], f.0[1] as i16); + assert_eq!(i[0], f[0] as i16); + assert_eq!(i[1], f[1] as i16); } unsafe { - let f = V::([f32::MIN, f32::MAX]); + let f: V:: = Simd([f32::MIN, f32::MAX]); let u: V = simd_as(f); - assert_eq!(u.0[0], f.0[0] as u8); - assert_eq!(u.0[1], f.0[1] as u8); + assert_eq!(u[0], f[0] as u8); + assert_eq!(u[1], f[1] as u8); } unsafe { - let f = V::([f64::MIN, f64::MAX]); + let f: V:: = Simd([f64::MIN, f64::MAX]); let i: V = simd_as(f); - assert_eq!(i.0[0], f.0[0] as isize); - assert_eq!(i.0[1], f.0[1] as isize); + assert_eq!(i[0], f[0] as isize); + assert_eq!(i[1], f[1] as isize); } unsafe { - let f = V::([f64::MIN, f64::MAX]); + let f: V:: = Simd([f64::MIN, f64::MAX]); let u: V = simd_as(f); - assert_eq!(u.0[0], f.0[0] as usize); - assert_eq!(u.0[1], f.0[1] as usize); + assert_eq!(u[0], f[0] as usize); + assert_eq!(u[1], f[1] as usize); } } diff --git a/tests/ui/simd/intrinsic/generic-bswap-byte.rs b/tests/ui/simd/intrinsic/generic-bswap-byte.rs index 903a07656a705..d30a560b1c2ed 100644 --- a/tests/ui/simd/intrinsic/generic-bswap-byte.rs +++ b/tests/ui/simd/intrinsic/generic-bswap-byte.rs @@ -2,19 +2,15 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_bswap; - -#[repr(simd)] -#[derive(Copy, Clone)] -struct i8x4([i8; 4]); +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -struct u8x4([u8; 4]); +use std::intrinsics::simd::simd_bswap; fn main() { unsafe { - assert_eq!(simd_bswap(i8x4([0, 1, 2, 3])).0, [0, 1, 2, 3]); - assert_eq!(simd_bswap(u8x4([0, 1, 2, 3])).0, [0, 1, 2, 3]); + assert_eq!(simd_bswap(i8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]); + assert_eq!(simd_bswap(u8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]); } } diff --git a/tests/ui/simd/intrinsic/generic-cast-pass.rs b/tests/ui/simd/intrinsic/generic-cast-pass.rs index 7a4663bcad2b1..0c3b00d65bf5c 100644 --- a/tests/ui/simd/intrinsic/generic-cast-pass.rs +++ b/tests/ui/simd/intrinsic/generic-cast-pass.rs @@ -2,55 +2,57 @@ #![feature(repr_simd, core_intrinsics)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_cast; use std::cmp::{max, min}; -#[derive(Copy, Clone)] -#[repr(simd)] -struct V([T; 2]); +type V = Simd; fn main() { unsafe { - let u = V::([i16::MIN as u32, i16::MAX as u32]); + let u: V:: = Simd([i16::MIN as u32, i16::MAX as u32]); let i: V = simd_cast(u); - assert_eq!(i.0[0], u.0[0] as i16); - assert_eq!(i.0[1], u.0[1] as i16); + assert_eq!(i[0], u[0] as i16); + assert_eq!(i[1], u[1] as i16); } unsafe { - let f = V::([i16::MIN as f32, i16::MAX as f32]); + let f: V:: = Simd([i16::MIN as f32, i16::MAX as f32]); let i: V = simd_cast(f); - assert_eq!(i.0[0], f.0[0] as i16); - assert_eq!(i.0[1], f.0[1] as i16); + assert_eq!(i[0], f[0] as i16); + assert_eq!(i[1], f[1] as i16); } unsafe { - let f = V::([u8::MIN as f32, u8::MAX as f32]); + let f: V:: = Simd([u8::MIN as f32, u8::MAX as f32]); let u: V = simd_cast(f); - assert_eq!(u.0[0], f.0[0] as u8); - assert_eq!(u.0[1], f.0[1] as u8); + assert_eq!(u[0], f[0] as u8); + assert_eq!(u[1], f[1] as u8); } unsafe { // We would like to do isize::MIN..=isize::MAX, but those values are not representable in // an f64, so we clamp to the range of an i32 to prevent running into UB. - let f = V::([ + let f: V:: = Simd([ max(isize::MIN, i32::MIN as isize) as f64, min(isize::MAX, i32::MAX as isize) as f64, ]); let i: V = simd_cast(f); - assert_eq!(i.0[0], f.0[0] as isize); - assert_eq!(i.0[1], f.0[1] as isize); + assert_eq!(i[0], f[0] as isize); + assert_eq!(i[1], f[1] as isize); } unsafe { - let f = V::([ + let f: V:: = Simd([ max(usize::MIN, u32::MIN as usize) as f64, min(usize::MAX, u32::MAX as usize) as f64, ]); let u: V = simd_cast(f); - assert_eq!(u.0[0], f.0[0] as usize); - assert_eq!(u.0[1], f.0[1] as usize); + assert_eq!(u[0], f[0] as usize); + assert_eq!(u[1], f[1] as usize); } } diff --git a/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs index ea34e9ffeb8ec..594d1d25d165c 100644 --- a/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs +++ b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs @@ -1,18 +1,24 @@ //@ run-pass #![feature(repr_simd, core_intrinsics)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_cast; -#[derive(Copy, Clone)] -#[repr(simd)] -struct V([T; 4]); +type V = Simd; fn main() { - let u = V::([0, 1, 2, 3]); + let u: V:: = Simd([0, 1, 2, 3]); let uu32: V = unsafe { simd_cast(u) }; let ui64: V = unsafe { simd_cast(u) }; - for (u, (uu32, ui64)) in u.0.iter().zip(uu32.0.iter().zip(ui64.0.iter())) { + for (u, (uu32, ui64)) in u + .as_array() + .iter() + .zip(uu32.as_array().iter().zip(ui64.as_array().iter())) + { assert_eq!(*u as u32, *uu32); assert_eq!(*u as i64, *ui64); } diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs index 50a05eecb03b3..ae70050b662ca 100644 --- a/tests/ui/simd/intrinsic/generic-comparison-pass.rs +++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs @@ -3,17 +3,11 @@ #![feature(repr_simd, core_intrinsics, macro_metavar_expr_concat)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::{simd_eq, simd_ge, simd_gt, simd_le, simd_lt, simd_ne}; +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone)] -struct i32x4([i32; 4]); -#[repr(simd)] -#[derive(Copy, Clone)] -struct u32x4(pub [u32; 4]); -#[repr(simd)] -#[derive(Copy, Clone)] -struct f32x4(pub [f32; 4]); +use std::intrinsics::simd::{simd_eq, simd_ge, simd_gt, simd_le, simd_lt, simd_ne}; macro_rules! cmp { ($method: ident($lhs: expr, $rhs: expr)) => {{ @@ -21,10 +15,11 @@ macro_rules! cmp { let rhs = $rhs; let e: u32x4 = ${concat(simd_, $method)}($lhs, $rhs); // assume the scalar version is correct/the behaviour we want. - assert!((e.0[0] != 0) == lhs.0[0].$method(&rhs.0[0])); - assert!((e.0[1] != 0) == lhs.0[1].$method(&rhs.0[1])); - assert!((e.0[2] != 0) == lhs.0[2].$method(&rhs.0[2])); - assert!((e.0[3] != 0) == lhs.0[3].$method(&rhs.0[3])); + let (lhs, rhs, e) = (lhs.as_array(), rhs.as_array(), e.as_array()); + assert!((e[0] != 0) == lhs[0].$method(&rhs[0])); + assert!((e[1] != 0) == lhs[1].$method(&rhs[1])); + assert!((e[2] != 0) == lhs[2].$method(&rhs[2])); + assert!((e[3] != 0) == lhs[3].$method(&rhs[3])); }}; } macro_rules! tests { @@ -53,17 +48,17 @@ macro_rules! tests { fn main() { // 13 vs. -100 tests that we get signed vs. unsigned comparisons // correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13); - let i1 = i32x4([10, -11, 12, 13]); - let i2 = i32x4([5, -5, 20, -100]); - let i3 = i32x4([10, -11, 20, -100]); + let i1 = i32x4::from_array([10, -11, 12, 13]); + let i2 = i32x4::from_array([5, -5, 20, -100]); + let i3 = i32x4::from_array([10, -11, 20, -100]); - let u1 = u32x4([10, !11 + 1, 12, 13]); - let u2 = u32x4([5, !5 + 1, 20, !100 + 1]); - let u3 = u32x4([10, !11 + 1, 20, !100 + 1]); + let u1 = u32x4::from_array([10, !11 + 1, 12, 13]); + let u2 = u32x4::from_array([5, !5 + 1, 20, !100 + 1]); + let u3 = u32x4::from_array([10, !11 + 1, 20, !100 + 1]); - let f1 = f32x4([10.0, -11.0, 12.0, 13.0]); - let f2 = f32x4([5.0, -5.0, 20.0, -100.0]); - let f3 = f32x4([10.0, -11.0, 20.0, -100.0]); + let f1 = f32x4::from_array([10.0, -11.0, 12.0, 13.0]); + let f2 = f32x4::from_array([5.0, -5.0, 20.0, -100.0]); + let f3 = f32x4::from_array([10.0, -11.0, 20.0, -100.0]); unsafe { tests! { @@ -84,7 +79,7 @@ fn main() { // NAN comparisons are special: // -11 (*) 13 // -5 -100 (*) - let f4 = f32x4([f32::NAN, f1.0[1], f32::NAN, f2.0[3]]); + let f4 = f32x4::from_array([f32::NAN, f1.0[1], f32::NAN, f2.0[3]]); unsafe { tests! { diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index e4d47cdb38184..f441d992e11b7 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -2,23 +2,14 @@ #![feature(repr_simd, intrinsics, core_intrinsics)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::{ simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn, simd_shuffle, }; -#[repr(simd)] -#[derive(Copy, Clone, Debug, PartialEq)] -#[allow(non_camel_case_types)] -struct i32x2([i32; 2]); -#[repr(simd)] -#[derive(Copy, Clone, Debug, PartialEq)] -#[allow(non_camel_case_types)] -struct i32x4([i32; 4]); -#[repr(simd)] -#[derive(Copy, Clone, Debug, PartialEq)] -#[allow(non_camel_case_types)] -struct i32x8([i32; 8]); - #[repr(simd)] struct SimdShuffleIdx([u32; LEN]); @@ -34,26 +25,26 @@ macro_rules! all_eq { } fn main() { - let x2 = i32x2([20, 21]); - let x4 = i32x4([40, 41, 42, 43]); - let x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]); + let x2 = i32x2::from_array([20, 21]); + let x4 = i32x4::from_array([40, 41, 42, 43]); + let x8 = i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 87]); unsafe { - all_eq!(simd_insert(x2, 0, 100), i32x2([100, 21])); - all_eq!(simd_insert(x2, 1, 100), i32x2([20, 100])); - - all_eq!(simd_insert(x4, 0, 100), i32x4([100, 41, 42, 43])); - all_eq!(simd_insert(x4, 1, 100), i32x4([40, 100, 42, 43])); - all_eq!(simd_insert(x4, 2, 100), i32x4([40, 41, 100, 43])); - all_eq!(simd_insert(x4, 3, 100), i32x4([40, 41, 42, 100])); - - all_eq!(simd_insert(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); - all_eq!(simd_insert(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); - all_eq!(simd_insert(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); - all_eq!(simd_insert(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); - all_eq!(simd_insert(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); - all_eq!(simd_insert(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); - all_eq!(simd_insert(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); - all_eq!(simd_insert(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); + all_eq!(simd_insert(x2, 0, 100), i32x2::from_array([100, 21])); + all_eq!(simd_insert(x2, 1, 100), i32x2::from_array([20, 100])); + + all_eq!(simd_insert(x4, 0, 100), i32x4::from_array([100, 41, 42, 43])); + all_eq!(simd_insert(x4, 1, 100), i32x4::from_array([40, 100, 42, 43])); + all_eq!(simd_insert(x4, 2, 100), i32x4::from_array([40, 41, 100, 43])); + all_eq!(simd_insert(x4, 3, 100), i32x4::from_array([40, 41, 42, 100])); + + all_eq!(simd_insert(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100])); all_eq!(simd_extract(x2, 0), 20); all_eq!(simd_extract(x2, 1), 21); @@ -73,22 +64,22 @@ fn main() { all_eq!(simd_extract(x8, 7), 87); } unsafe { - all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21])); - all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100])); - - all_eq!(simd_insert_dyn(x4, 0, 100), i32x4([100, 41, 42, 43])); - all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43])); - all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43])); - all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 100])); - - all_eq!(simd_insert_dyn(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); - all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); - all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); - all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); - all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); - all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); - all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); - all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); + all_eq!(simd_insert_dyn(x2, 0, 100), i32x2::from_array([100, 21])); + all_eq!(simd_insert_dyn(x2, 1, 100), i32x2::from_array([20, 100])); + + all_eq!(simd_insert_dyn(x4, 0, 100), i32x4::from_array([100, 41, 42, 43])); + all_eq!(simd_insert_dyn(x4, 1, 100), i32x4::from_array([40, 100, 42, 43])); + all_eq!(simd_insert_dyn(x4, 2, 100), i32x4::from_array([40, 41, 100, 43])); + all_eq!(simd_insert_dyn(x4, 3, 100), i32x4::from_array([40, 41, 42, 100])); + + all_eq!(simd_insert_dyn(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert_dyn(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert_dyn(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100])); all_eq!(simd_extract_dyn(x2, 0), 20); all_eq!(simd_extract_dyn(x2, 1), 21); @@ -108,38 +99,47 @@ fn main() { all_eq!(simd_extract_dyn(x8, 7), 87); } - let y2 = i32x2([120, 121]); - let y4 = i32x4([140, 141, 142, 143]); - let y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); + let y2 = i32x2::from_array([120, 121]); + let y4 = i32x4::from_array([140, 141, 142, 143]); + let y8 = i32x8::from_array([180, 181, 182, 183, 184, 185, 186, 187]); unsafe { - all_eq!(simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0]) }), i32x2([121, 20])); + all_eq!( + simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0]) }), + i32x2::from_array([121, 20]) + ); all_eq!( simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2]) }), - i32x4([121, 20, 21, 120]) + i32x4::from_array([121, 20, 21, 120]) ); all_eq!( simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2, 1, 2, 3, 0]) }), - i32x8([121, 20, 21, 120, 21, 120, 121, 20]) + i32x8::from_array([121, 20, 21, 120, 21, 120, 121, 20]) ); - all_eq!(simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }), i32x2([143, 42])); + all_eq!( + simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }), + i32x2::from_array([143, 42]) + ); all_eq!( simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0]) }), - i32x4([143, 42, 141, 40]) + i32x4::from_array([143, 42, 141, 40]) ); all_eq!( simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0, 3, 6, 4, 1]) }), - i32x8([143, 42, 141, 40, 43, 142, 140, 41]) + i32x8::from_array([143, 42, 141, 40, 43, 142, 140, 41]) ); - all_eq!(simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }), i32x2([183, 85])); + all_eq!( + simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }), + i32x2::from_array([183, 85]) + ); all_eq!( simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0]) }), - i32x4([183, 85, 187, 80]) + i32x4::from_array([183, 85, 187, 80]) ); all_eq!( simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0, 3, 8, 12, 1]) }), - i32x8([183, 85, 187, 80, 83, 180, 184, 81]) + i32x8::from_array([183, 85, 187, 80, 83, 180, 184, 81]) ); } } diff --git a/tests/ui/simd/intrinsic/generic-gather-scatter-pass.rs b/tests/ui/simd/intrinsic/generic-gather-scatter-pass.rs index b98d4d6575bb7..c2418c019edaf 100644 --- a/tests/ui/simd/intrinsic/generic-gather-scatter-pass.rs +++ b/tests/ui/simd/intrinsic/generic-gather-scatter-pass.rs @@ -6,24 +6,26 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::{simd_gather, simd_scatter}; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub [T; 4]); +type x4 = Simd; fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; - let default = x4([-3_f32, -3., -3., -3.]); - let s_strided = x4([0_f32, 2., -3., 6.]); - let mask = x4([-1_i32, -1, 0, -1]); + let default = x4::from_array([-3_f32, -3., -3., -3.]); + let s_strided = x4::from_array([0_f32, 2., -3., 6.]); + let mask = x4::from_array([-1_i32, -1, 0, -1]); // reading from *const unsafe { let pointer = x.as_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); let r_strided = simd_gather(default, pointers, mask); @@ -34,7 +36,7 @@ fn main() { unsafe { let pointer = x.as_mut_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); let r_strided = simd_gather(default, pointers, mask); @@ -45,9 +47,9 @@ fn main() { unsafe { let pointer = x.as_mut_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); - let values = x4([42_f32, 43_f32, 44_f32, 45_f32]); + let values = x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]); simd_scatter(values, pointers, mask); assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); @@ -65,14 +67,14 @@ fn main() { &x[7] as *const f32, ]; - let default = x4([y[0], y[0], y[0], y[0]]); - let s_strided = x4([y[0], y[2], y[0], y[6]]); + let default = x4::from_array([y[0], y[0], y[0], y[0]]); + let s_strided = x4::from_array([y[0], y[2], y[0], y[6]]); // reading from *const unsafe { let pointer = y.as_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); let r_strided = simd_gather(default, pointers, mask); @@ -83,7 +85,7 @@ fn main() { unsafe { let pointer = y.as_mut_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); let r_strided = simd_gather(default, pointers, mask); @@ -94,9 +96,9 @@ fn main() { unsafe { let pointer = y.as_mut_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i * 2))); - let values = x4([y[7], y[6], y[5], y[1]]); + let values = x4::from_array([y[7], y[6], y[5], y[1]]); simd_scatter(values, pointers, mask); let s = [ diff --git a/tests/ui/simd/intrinsic/generic-select-pass.rs b/tests/ui/simd/intrinsic/generic-select-pass.rs index 0e5f7c4902f3a..ff2d70d6a9782 100644 --- a/tests/ui/simd/intrinsic/generic-select-pass.rs +++ b/tests/ui/simd/intrinsic/generic-select-pass.rs @@ -6,38 +6,24 @@ // Test that the simd_select intrinsics produces correct results. #![feature(repr_simd, core_intrinsics)] -use std::intrinsics::simd::{simd_select, simd_select_bitmask}; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct i32x4(pub [i32; 4]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub [u32; 4]); +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct u32x8([u32; 8]); - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub [f32; 4]); +use std::intrinsics::simd::{simd_select, simd_select_bitmask}; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct b8x4(pub [i8; 4]); +type b8x4 = i8x4; fn main() { - let m0 = b8x4([!0, !0, !0, !0]); - let m1 = b8x4([0, 0, 0, 0]); - let m2 = b8x4([!0, !0, 0, 0]); - let m3 = b8x4([0, 0, !0, !0]); - let m4 = b8x4([!0, 0, !0, 0]); + let m0 = b8x4::from_array([!0, !0, !0, !0]); + let m1 = b8x4::from_array([0, 0, 0, 0]); + let m2 = b8x4::from_array([!0, !0, 0, 0]); + let m3 = b8x4::from_array([0, 0, !0, !0]); + let m4 = b8x4::from_array([!0, 0, !0, 0]); unsafe { - let a = i32x4([1, -2, 3, 4]); - let b = i32x4([5, 6, -7, 8]); + let a = i32x4::from_array([1, -2, 3, 4]); + let b = i32x4::from_array([5, 6, -7, 8]); let r: i32x4 = simd_select(m0, a, b); let e = a; @@ -48,21 +34,21 @@ fn main() { assert_eq!(r, e); let r: i32x4 = simd_select(m2, a, b); - let e = i32x4([1, -2, -7, 8]); + let e = i32x4::from_array([1, -2, -7, 8]); assert_eq!(r, e); let r: i32x4 = simd_select(m3, a, b); - let e = i32x4([5, 6, 3, 4]); + let e = i32x4::from_array([5, 6, 3, 4]); assert_eq!(r, e); let r: i32x4 = simd_select(m4, a, b); - let e = i32x4([1, 6, 3, 8]); + let e = i32x4::from_array([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = u32x4([1, 2, 3, 4]); - let b = u32x4([5, 6, 7, 8]); + let a = u32x4::from_array([1, 2, 3, 4]); + let b = u32x4::from_array([5, 6, 7, 8]); let r: u32x4 = simd_select(m0, a, b); let e = a; @@ -73,21 +59,21 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select(m2, a, b); - let e = u32x4([1, 2, 7, 8]); + let e = u32x4::from_array([1, 2, 7, 8]); assert_eq!(r, e); let r: u32x4 = simd_select(m3, a, b); - let e = u32x4([5, 6, 3, 4]); + let e = u32x4::from_array([5, 6, 3, 4]); assert_eq!(r, e); let r: u32x4 = simd_select(m4, a, b); - let e = u32x4([1, 6, 3, 8]); + let e = u32x4::from_array([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = f32x4([1., 2., 3., 4.]); - let b = f32x4([5., 6., 7., 8.]); + let a = f32x4::from_array([1., 2., 3., 4.]); + let b = f32x4::from_array([5., 6., 7., 8.]); let r: f32x4 = simd_select(m0, a, b); let e = a; @@ -98,23 +84,23 @@ fn main() { assert_eq!(r, e); let r: f32x4 = simd_select(m2, a, b); - let e = f32x4([1., 2., 7., 8.]); + let e = f32x4::from_array([1., 2., 7., 8.]); assert_eq!(r, e); let r: f32x4 = simd_select(m3, a, b); - let e = f32x4([5., 6., 3., 4.]); + let e = f32x4::from_array([5., 6., 3., 4.]); assert_eq!(r, e); let r: f32x4 = simd_select(m4, a, b); - let e = f32x4([1., 6., 3., 8.]); + let e = f32x4::from_array([1., 6., 3., 8.]); assert_eq!(r, e); } unsafe { let t = !0 as i8; let f = 0 as i8; - let a = b8x4([t, f, t, f]); - let b = b8x4([f, f, f, t]); + let a = b8x4::from_array([t, f, t, f]); + let b = b8x4::from_array([f, f, f, t]); let r: b8x4 = simd_select(m0, a, b); let e = a; @@ -125,21 +111,21 @@ fn main() { assert_eq!(r, e); let r: b8x4 = simd_select(m2, a, b); - let e = b8x4([t, f, f, t]); + let e = b8x4::from_array([t, f, f, t]); assert_eq!(r, e); let r: b8x4 = simd_select(m3, a, b); - let e = b8x4([f, f, t, f]); + let e = b8x4::from_array([f, f, t, f]); assert_eq!(r, e); let r: b8x4 = simd_select(m4, a, b); - let e = b8x4([t, f, t, t]); + let e = b8x4::from_array([t, f, t, t]); assert_eq!(r, e); } unsafe { - let a = u32x8([0, 1, 2, 3, 4, 5, 6, 7]); - let b = u32x8([8, 9, 10, 11, 12, 13, 14, 15]); + let a = u32x8::from_array([0, 1, 2, 3, 4, 5, 6, 7]); + let b = u32x8::from_array([8, 9, 10, 11, 12, 13, 14, 15]); let r: u32x8 = simd_select_bitmask(0u8, a, b); let e = b; @@ -150,21 +136,21 @@ fn main() { assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b); - let e = u32x8([0, 9, 2, 11, 4, 13, 6, 15]); + let e = u32x8::from_array([0, 9, 2, 11, 4, 13, 6, 15]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b); - let e = u32x8([8, 1, 10, 3, 12, 5, 14, 7]); + let e = u32x8::from_array([8, 1, 10, 3, 12, 5, 14, 7]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b); - let e = u32x8([8, 9, 10, 11, 4, 5, 6, 7]); + let e = u32x8::from_array([8, 9, 10, 11, 4, 5, 6, 7]); assert_eq!(r, e); } unsafe { - let a = u32x4([0, 1, 2, 3]); - let b = u32x4([4, 5, 6, 7]); + let a = u32x4::from_array([0, 1, 2, 3]); + let b = u32x4::from_array([4, 5, 6, 7]); let r: u32x4 = simd_select_bitmask(0u8, a, b); let e = b; @@ -175,15 +161,15 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b0101u8, a, b); - let e = u32x4([0, 5, 2, 7]); + let e = u32x4::from_array([0, 5, 2, 7]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1010u8, a, b); - let e = u32x4([4, 1, 6, 3]); + let e = u32x4::from_array([4, 1, 6, 3]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1100u8, a, b); - let e = u32x4([4, 5, 2, 3]); + let e = u32x4::from_array([4, 5, 2, 3]); assert_eq!(r, e); } } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index 13e7266b2a561..14f180425d8a9 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -5,11 +5,13 @@ //@ compile-flags: -Zmir-opt-level=4 #![feature(core_intrinsics, repr_simd)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_shuffle; -#[repr(simd)] -#[derive(Debug, PartialEq)] -struct Simd2([u8; 2]); +type Simd2 = u8x2; #[repr(simd)] struct SimdShuffleIdx([u32; LEN]); @@ -17,7 +19,11 @@ struct SimdShuffleIdx([u32; LEN]); fn main() { unsafe { const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 1]); - let p_res: Simd2 = simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX); + let p_res: Simd2 = simd_shuffle( + Simd2::from_array([10, 11]), + Simd2::from_array([12, 13]), + IDX, + ); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -27,16 +33,16 @@ fn main() { #[inline(never)] fn assert_10_11(x: Simd2) { - assert_eq!(x, Simd2([10, 11])); + assert_eq!(x.into_array(), [10, 11]); } #[inline(never)] fn assert_10_13(x: Simd2) { - assert_eq!(x, Simd2([10, 13])); + assert_eq!(x.into_array(), [10, 13]); } #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 3]); - simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) + simd_shuffle(Simd2::from_array([10, 11]), Simd2::from_array([12, 13]), IDX) } diff --git a/tests/ui/simd/intrinsic/ptr-cast.rs b/tests/ui/simd/intrinsic/ptr-cast.rs index 3a73c0273e1a7..63b65d83f7674 100644 --- a/tests/ui/simd/intrinsic/ptr-cast.rs +++ b/tests/ui/simd/intrinsic/ptr-cast.rs @@ -2,18 +2,20 @@ #![feature(repr_simd, core_intrinsics)] +#[path = "../../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::{simd_cast_ptr, simd_expose_provenance, simd_with_exposed_provenance}; -#[derive(Copy, Clone)] -#[repr(simd)] -struct V([T; 2]); +type V = Simd; fn main() { unsafe { let mut foo = 4i8; let ptr = &mut foo as *mut i8; - let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]); + let ptrs: V::<*mut i8> = Simd([ptr, core::ptr::null_mut()]); // change constness and type let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs); @@ -22,8 +24,8 @@ fn main() { let with_exposed_provenance: V<*mut i8> = simd_with_exposed_provenance(exposed_addr); - assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]); - assert!(exposed_addr.0 == [ptr as usize, 0]); - assert!(with_exposed_provenance.0 == ptrs.0); + assert!(const_ptrs.into_array() == [ptr as *const u8, core::ptr::null()]); + assert!(exposed_addr.into_array() == [ptr as usize, 0]); + assert!(with_exposed_provenance.into_array() == ptrs.into_array()); } } diff --git a/tests/ui/simd/issue-105439.rs b/tests/ui/simd/issue-105439.rs index 0a44f36fb2ec9..1d57eff341c01 100644 --- a/tests/ui/simd/issue-105439.rs +++ b/tests/ui/simd/issue-105439.rs @@ -10,7 +10,9 @@ struct i32x4([i32; 4]); #[inline(always)] fn to_array(a: i32x4) -> [i32; 4] { - a.0 + // This was originally just `a.0`, but that ended up being annoying enough + // that it was banned by + unsafe { std::mem::transmute(a) } } fn main() { diff --git a/tests/ui/simd/issue-39720.rs b/tests/ui/simd/issue-39720.rs index db441e5516793..09d6142c92019 100644 --- a/tests/ui/simd/issue-39720.rs +++ b/tests/ui/simd/issue-39720.rs @@ -2,16 +2,16 @@ #![feature(repr_simd, core_intrinsics)] -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -pub struct Char3(pub [i8; 3]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -pub struct Short3(pub [i16; 3]); +pub type Char3 = Simd; + +pub type Short3 = Simd; fn main() { - let cast: Short3 = unsafe { std::intrinsics::simd::simd_cast(Char3([10, -3, -9])) }; + let cast: Short3 = unsafe { std::intrinsics::simd::simd_cast(Char3::from_array([10, -3, -9])) }; println!("{:?}", cast); } diff --git a/tests/ui/simd/issue-85915-simd-ptrs.rs b/tests/ui/simd/issue-85915-simd-ptrs.rs index 4e2379d052510..a74c36fabc1b8 100644 --- a/tests/ui/simd/issue-85915-simd-ptrs.rs +++ b/tests/ui/simd/issue-85915-simd-ptrs.rs @@ -6,35 +6,27 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::{simd_gather, simd_scatter}; - -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct cptrx4([*const T; 4]); +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct mptrx4([*mut T; 4]); +use std::intrinsics::simd::{simd_gather, simd_scatter}; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4([f32; 4]); +type cptrx4 = Simd<*const T, 4>; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct i32x4([i32; 4]); +type mptrx4 = Simd<*mut T, 4>; fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; - let default = f32x4([-3_f32, -3., -3., -3.]); - let s_strided = f32x4([0_f32, 2., -3., 6.]); - let mask = i32x4([-1_i32, -1, 0, -1]); + let default = f32x4::from_array([-3_f32, -3., -3., -3.]); + let s_strided = f32x4::from_array([0_f32, 2., -3., 6.]); + let mask = i32x4::from_array([-1_i32, -1, 0, -1]); // reading from *const unsafe { let pointer = &x as *const f32; - let pointers = cptrx4([ + let pointers = cptrx4::from_array([ pointer.offset(0) as *const f32, pointer.offset(2), pointer.offset(4), @@ -49,14 +41,14 @@ fn main() { // writing to *mut unsafe { let pointer = &mut x as *mut f32; - let pointers = mptrx4([ + let pointers = mptrx4::from_array([ pointer.offset(0) as *mut f32, pointer.offset(2), pointer.offset(4), pointer.offset(6), ]); - let values = f32x4([42_f32, 43_f32, 44_f32, 45_f32]); + let values = f32x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]); simd_scatter(values, pointers, mask); assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs index a6c3017572a19..da4cd45658935 100644 --- a/tests/ui/simd/issue-89193.rs +++ b/tests/ui/simd/issue-89193.rs @@ -6,36 +6,38 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::simd_gather; -#[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub [T; 4]); +type x4 = Simd; fn main() { let x: [usize; 4] = [10, 11, 12, 13]; - let default = x4([0_usize, 1, 2, 3]); + let default = x4::from_array([0_usize, 1, 2, 3]); let all_set = u8::MAX as i8; // aka -1 - let mask = x4([all_set, all_set, all_set, all_set]); - let expected = x4([10_usize, 11, 12, 13]); + let mask = x4::from_array([all_set, all_set, all_set, all_set]); + let expected = x4::from_array([10_usize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i))); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } // and again for isize let x: [isize; 4] = [10, 11, 12, 13]; - let default = x4([0_isize, 1, 2, 3]); - let expected = x4([10_isize, 11, 12, 13]); + let default = x4::from_array([0_isize, 1, 2, 3]); + let expected = x4::from_array([10_isize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); let pointers = - x4([pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3)]); + x4::from_array(std::array::from_fn(|i| pointer.add(i))); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } diff --git a/tests/ui/simd/masked-load-store.rs b/tests/ui/simd/masked-load-store.rs index 69ea76581ee69..da32ba611c485 100644 --- a/tests/ui/simd/masked-load-store.rs +++ b/tests/ui/simd/masked-load-store.rs @@ -1,11 +1,11 @@ //@ run-pass #![feature(repr_simd, core_intrinsics)] -use std::intrinsics::simd::{simd_masked_load, simd_masked_store}; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[derive(Copy, Clone)] -#[repr(simd)] -struct Simd([T; N]); +use std::intrinsics::simd::{simd_masked_load, simd_masked_store}; fn main() { unsafe { @@ -15,7 +15,7 @@ fn main() { let b: Simd = simd_masked_load(Simd::([-1, 0, -1, -1]), b_src.as_ptr(), b_default); - assert_eq!(&b.0, &[4, 9, 6, 7]); + assert_eq!(b.as_array(), &[4, 9, 6, 7]); let mut output = [u8::MAX; 5]; diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index a56f2ea14520c..1490f8e2319f0 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -11,6 +11,10 @@ )] #![allow(incomplete_features)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + #[cfg(old)] use std::intrinsics::simd::simd_shuffle; @@ -18,10 +22,6 @@ use std::intrinsics::simd::simd_shuffle; #[rustc_intrinsic] unsafe fn simd_shuffle_const_generic(a: T, b: T) -> U; -#[derive(Copy, Clone)] -#[repr(simd)] -struct Simd([T; N]); - trait Shuffle { const I: Simd; const J: &'static [u32] = &Self::I.0; @@ -57,9 +57,9 @@ fn main() { let b = Simd::([4, 5, 6, 7]); unsafe { let x: Simd = I1.shuffle(a, b); - assert_eq!(x.0, [0, 2, 4, 6]); + assert_eq!(x.into_array(), [0, 2, 4, 6]); let y: Simd = I2.shuffle(a, b); - assert_eq!(y.0, [1, 5]); + assert_eq!(y.into_array(), [1, 5]); } } diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs index cc54477ae7134..f0c6de7c402f1 100644 --- a/tests/ui/simd/repr_packed.rs +++ b/tests/ui/simd/repr_packed.rs @@ -3,15 +3,16 @@ #![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] -use std::intrinsics::simd::simd_add; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[repr(simd, packed)] -struct Simd([T; N]); +use std::intrinsics::simd::simd_add; fn check_size_align() { use std::mem; - assert_eq!(mem::size_of::>(), mem::size_of::<[T; N]>()); - assert_eq!(mem::size_of::>() % mem::align_of::>(), 0); + assert_eq!(mem::size_of::>(), mem::size_of::<[T; N]>()); + assert_eq!(mem::size_of::>() % mem::align_of::>(), 0); } fn check_ty() { @@ -35,14 +36,21 @@ fn main() { unsafe { // powers-of-two have no padding and have the same layout as #[repr(simd)] - let x: Simd = - simd_add(Simd::([0., 1., 2., 3.]), Simd::([2., 2., 2., 2.])); - assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]); + let x: PackedSimd = + simd_add( + PackedSimd::([0., 1., 2., 3.]), + PackedSimd::([2., 2., 2., 2.]), + ); + assert_eq!(x.into_array(), [2., 3., 4., 5.]); // non-powers-of-two should have padding (which is removed by #[repr(packed)]), // but the intrinsic handles it - let x: Simd = simd_add(Simd::([0., 1., 2.]), Simd::([2., 2., 2.])); - let arr: [f64; 3] = x.0; + let x: PackedSimd = + simd_add( + PackedSimd::([0., 1., 2.]), + PackedSimd::([2., 2., 2.]), + ); + let arr: [f64; 3] = x.into_array(); assert_eq!(arr, [2., 3., 4.]); } } diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index cd270edcf00ca..061571a47867f 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -10,10 +10,16 @@ use std::marker::ConstParamTy; use std::intrinsics::simd::simd_shuffle; +// not using `minisimd` because of the `ConstParamTy` #[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)] #[repr(simd)] struct Simd([T; N]); +fn into_array(v: Simd) -> [T; N] { + const { assert!(size_of::>() == size_of::<[T; N]>()) } + unsafe { std::intrinsics::transmute_unchecked(v) } +} + unsafe fn __shuffle_vector16, T, U>(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } @@ -25,10 +31,10 @@ fn main() { let b = Simd::([4, 5, 6, 7]); unsafe { let x: Simd = simd_shuffle(a, b, I1); - assert_eq!(x.0, [0, 2, 4, 6]); + assert_eq!(into_array(x), [0, 2, 4, 6]); let y: Simd = simd_shuffle(a, b, I2); - assert_eq!(y.0, [1, 5]); + assert_eq!(into_array(y), [1, 5]); } // Test that an indirection (via an unnamed constant) diff --git a/tests/ui/simd/simd-bitmask-notpow2.rs b/tests/ui/simd/simd-bitmask-notpow2.rs index 4935097065ea7..b9af591d1b94a 100644 --- a/tests/ui/simd/simd-bitmask-notpow2.rs +++ b/tests/ui/simd/simd-bitmask-notpow2.rs @@ -4,21 +4,23 @@ //@ ignore-endian-big #![feature(repr_simd, core_intrinsics)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; + use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask}; fn main() { // Non-power-of-2 multi-byte mask. - #[repr(simd, packed)] #[allow(non_camel_case_types)] - #[derive(Copy, Clone, Debug, PartialEq)] - struct i32x10([i32; 10]); + type i32x10 = PackedSimd; impl i32x10 { fn splat(x: i32) -> Self { Self([x; 10]) } } unsafe { - let mask = i32x10([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]); + let mask = i32x10::from_array([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]); let mask_bits = if cfg!(target_endian = "little") { 0b0101001011 } else { 0b1101001010 }; let mask_bytes = if cfg!(target_endian = "little") { [0b01001011, 0b01] } else { [0b11, 0b01001010] }; @@ -43,17 +45,20 @@ fn main() { } // Test for a mask where the next multiple of 8 is not a power of two. - #[repr(simd, packed)] #[allow(non_camel_case_types)] - #[derive(Copy, Clone, Debug, PartialEq)] - struct i32x20([i32; 20]); + type i32x20 = PackedSimd; impl i32x20 { fn splat(x: i32) -> Self { Self([x; 20]) } } unsafe { - let mask = i32x20([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0, 0, 0, 0, !0, !0, !0, !0, !0, !0, !0]); + let mask = i32x20::from_array([ + !0, !0, 0, !0, 0, + 0, !0, 0, !0, 0, + 0, 0, 0, !0, !0, + !0, !0, !0, !0, !0, + ]); let mask_bits = if cfg!(target_endian = "little") { 0b11111110000101001011 } else { diff --git a/tests/ui/simd/simd-bitmask.rs b/tests/ui/simd/simd-bitmask.rs index 6fcceeaa24bb3..609dae3647b24 100644 --- a/tests/ui/simd/simd-bitmask.rs +++ b/tests/ui/simd/simd-bitmask.rs @@ -1,11 +1,11 @@ //@run-pass #![feature(repr_simd, core_intrinsics)] -use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask}; +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +use minisimd::*; -#[derive(Copy, Clone)] -#[repr(simd)] -struct Simd([T; N]); +use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask}; fn main() { unsafe { @@ -41,11 +41,11 @@ fn main() { let mask = if cfg!(target_endian = "little") { 0b0101u8 } else { 0b1010u8 }; let r = simd_select_bitmask(mask, a, b); - assert_eq!(r.0, e); + assert_eq!(r.into_array(), e); let mask = if cfg!(target_endian = "little") { [0b0101u8] } else { [0b1010u8] }; let r = simd_select_bitmask(mask, a, b); - assert_eq!(r.0, e); + assert_eq!(r.into_array(), e); let a = Simd::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); let b = Simd::([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); @@ -57,7 +57,7 @@ fn main() { 0b0011000000001010u16 }; let r = simd_select_bitmask(mask, a, b); - assert_eq!(r.0, e); + assert_eq!(r.into_array(), e); let mask = if cfg!(target_endian = "little") { [0b00001100u8, 0b01010000u8] @@ -65,6 +65,6 @@ fn main() { [0b00110000u8, 0b00001010u8] }; let r = simd_select_bitmask(mask, a, b); - assert_eq!(r.0, e); + assert_eq!(r.into_array(), e); } } diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs index 77f1861524870..82902891b97f2 100644 --- a/tests/ui/simd/target-feature-mixup.rs +++ b/tests/ui/simd/target-feature-mixup.rs @@ -8,6 +8,11 @@ #![feature(repr_simd, target_feature, cfg_target_feature)] +#[path = "../../auxiliary/minisimd.rs"] +mod minisimd; +#[allow(unused)] +use minisimd::*; + use std::process::{Command, ExitStatus}; use std::env; @@ -50,19 +55,13 @@ fn is_sigill(status: ExitStatus) -> bool { #[allow(nonstandard_style)] mod test { // An SSE type - #[repr(simd)] - #[derive(PartialEq, Debug, Clone, Copy)] - struct __m128i([u64; 2]); + type __m128i = super::u64x2; // An AVX type - #[repr(simd)] - #[derive(PartialEq, Debug, Clone, Copy)] - struct __m256i([u64; 4]); + type __m256i = super::u64x4; // An AVX-512 type - #[repr(simd)] - #[derive(PartialEq, Debug, Clone, Copy)] - struct __m512i([u64; 8]); + type __m512i = super::u64x8; pub fn main(level: &str) { unsafe { @@ -88,9 +87,9 @@ mod test { )*) => ($( $(#[$attr])* unsafe fn $main(level: &str) { - let m128 = __m128i([1, 2]); - let m256 = __m256i([3, 4, 5, 6]); - let m512 = __m512i([7, 8, 9, 10, 11, 12, 13, 14]); + let m128 = __m128i::from_array([1, 2]); + let m256 = __m256i::from_array([3, 4, 5, 6]); + let m512 = __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14]); assert_eq!(id_sse_128(m128), m128); assert_eq!(id_sse_256(m256), m256); assert_eq!(id_sse_512(m512), m512); @@ -125,55 +124,55 @@ mod test { #[target_feature(enable = "sse2")] unsafe fn id_sse_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i([1, 2])); + assert_eq!(a, __m128i::from_array([1, 2])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i([3, 4, 5, 6])); + assert_eq!(a, __m256i::from_array([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); + assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i([1, 2])); + assert_eq!(a, __m128i::from_array([1, 2])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i([3, 4, 5, 6])); + assert_eq!(a, __m256i::from_array([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); + assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i([1, 2])); + assert_eq!(a, __m128i::from_array([1, 2])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i([3, 4, 5, 6])); + assert_eq!(a, __m256i::from_array([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); + assert_eq!(a, __m512i::from_array([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } } diff --git a/tests/ui/structs/default-field-values/const-trait-default-field-value.rs b/tests/ui/structs/default-field-values/const-trait-default-field-value.rs new file mode 100644 index 0000000000000..60c22efabc4de --- /dev/null +++ b/tests/ui/structs/default-field-values/const-trait-default-field-value.rs @@ -0,0 +1,37 @@ +//@ check-pass + +// Ensure that `default_field_values` and `const_default` interact properly. + +#![feature(const_default)] +#![feature(const_trait_impl)] +#![feature(default_field_values)] +#![feature(derive_const)] + +#[derive(PartialEq, Eq, Debug)] +#[derive_const(Default)] +struct S { + r: Option = as Default>::default(), + s: String = String::default(), + o: Option = Option::::default(), + p: std::marker::PhantomData<()> = std::marker::PhantomData::default(), + q: Option = as Default>::default(), + t: Option = Option::default(), + v: Option = const { Option::default() }, +} + +const _: S = S { .. }; +const _: S = const { S { .. } }; +const _: S = S::default(); +const _: S = const { S::default() }; + +fn main() { + let s = S { .. }; + assert_eq!(s.r, None); + assert_eq!(&s.s, ""); + assert_eq!(s.o, None); + assert_eq!(s.p, std::marker::PhantomData); + assert_eq!(s.q, None); + assert_eq!(s.t, None); + assert_eq!(s.v, None); + assert_eq!(s, S::default()); +} diff --git a/tests/ui/struct-ctor-mangling.rs b/tests/ui/symbol-names/struct-constructor-mangling.rs similarity index 54% rename from tests/ui/struct-ctor-mangling.rs rename to tests/ui/symbol-names/struct-constructor-mangling.rs index f32cbb7aaae99..ec8791e215491 100644 --- a/tests/ui/struct-ctor-mangling.rs +++ b/tests/ui/symbol-names/struct-constructor-mangling.rs @@ -1,3 +1,5 @@ +//! Test that the symbol mangling of Foo-the-constructor-function versus Foo-the-type do not collide + //@ run-pass fn size_of_val(_: &T) -> usize { @@ -6,8 +8,6 @@ fn size_of_val(_: &T) -> usize { struct Foo(#[allow(dead_code)] i64); -// Test that the (symbol) mangling of `Foo` (the `struct` type) and that of -// `typeof Foo` (the function type of the `struct` constructor) don't collide. fn main() { size_of_val(&Foo(0)); size_of_val(&Foo); diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs index dc960422a4a41..da28d9a47c31e 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-trait.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver //@ known-bug: #110395 -// Broken until we have `const PartialEq` impl in stdlib +// Broken until `(): const PartialEq` #![allow(incomplete_features)] #![feature(const_trait_impl, const_cmp, const_destruct)] diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr index 5ed12b3705290..cbc62d602a473 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr @@ -4,6 +4,7 @@ error[E0658]: use of unstable library feature `derive_const` LL | #[derive_const(Debug)] | ^^^^^^^^^^^^ | + = note: see issue #118304 for more information = help: add `#![feature(derive_const)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr deleted file mode 100644 index 89e59e5db6ed3..0000000000000 --- a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0015]: cannot match on `str` in constant functions - --> $DIR/match-non-const-eq.rs:7:9 - | -LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts - | ^^^ - | - = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/match-non-const-eq.rs b/tests/ui/traits/const-traits/match-non-const-eq.rs index 73f8af86bd050..03adb8dc5a4e5 100644 --- a/tests/ui/traits/const-traits/match-non-const-eq.rs +++ b/tests/ui/traits/const-traits/match-non-const-eq.rs @@ -1,11 +1,12 @@ -//@ known-bug: #110395 //@ revisions: stock gated -#![cfg_attr(gated, feature(const_trait_impl))] +#![cfg_attr(gated, feature(const_trait_impl, const_cmp))] +//@[gated] check-pass const fn foo(input: &'static str) { match input { - "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts - //FIXME ~^ ERROR cannot match on `str` in constant functions + "a" => (), + //[stock]~^ ERROR cannot match on `str` in constant functions + //[stock]~| ERROR `PartialEq` is not yet stable as a const trait _ => (), } } diff --git a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr index 89e59e5db6ed3..5b662447bde18 100644 --- a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr +++ b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr @@ -1,12 +1,26 @@ -error[E0015]: cannot match on `str` in constant functions +error[E0658]: cannot match on `str` in constant functions --> $DIR/match-non-const-eq.rs:7:9 | -LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts +LL | "a" => (), | ^^^ | = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: `PartialEq` is not yet stable as a const trait + --> $DIR/match-non-const-eq.rs:7:9 + | +LL | "a" => (), + | ^^^ + | +help: add `#![feature(const_cmp)]` to the crate attributes to enable + | +LL + #![feature(const_cmp)] + | + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs b/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs new file mode 100644 index 0000000000000..874b3d2c48dbb --- /dev/null +++ b/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs @@ -0,0 +1,9 @@ +// This test is to ensure that the raw underscore lifetime won't emit two duplicate errors. +// See issue #143152 + +//@ edition: 2021 + +fn f<'r#_>(){} +//~^ ERROR `_` cannot be a raw lifetime + +fn main() {} diff --git a/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr b/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr new file mode 100644 index 0000000000000..bdb357a47f4b7 --- /dev/null +++ b/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr @@ -0,0 +1,8 @@ +error: `_` cannot be a raw lifetime + --> $DIR/raw-underscore-lifetime.rs:6:6 + | +LL | fn f<'r#_>(){} + | ^^^^ + +error: aborting due to 1 previous error +