From 287db04636ffefa3fdaa39fe0fdcc3cf75b60444 Mon Sep 17 00:00:00 2001 From: Catherine Date: Mon, 24 Jul 2023 04:55:47 +0000 Subject: [PATCH 01/10] Specify macro is invalid in certain contexts --- compiler/rustc_parse/messages.ftl | 6 +++ compiler/rustc_parse/src/errors.rs | 6 +++ .../rustc_parse/src/parser/diagnostics.rs | 37 +++++++++++-------- compiler/rustc_parse/src/parser/item.rs | 26 +++++++++---- compiler/rustc_parse/src/parser/pat.rs | 12 +++++- .../parser/macro/macro-expand-to-field-2.rs | 16 ++++++++ .../macro/macro-expand-to-field-2.stderr | 18 +++++++++ .../parser/macro/macro-expand-to-field-3.rs | 15 ++++++++ .../macro/macro-expand-to-field-3.stderr | 19 ++++++++++ .../ui/parser/macro/macro-expand-to-field.rs | 26 +++++++++++++ .../parser/macro/macro-expand-to-field.stderr | 29 +++++++++++++++ .../parser/macro/macro-expand-to-match-arm.rs | 15 ++++++++ .../macro/macro-expand-to-match-arm.stderr | 10 +++++ 13 files changed, 209 insertions(+), 26 deletions(-) create mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.rs create mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.stderr create mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.rs create mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.stderr create mode 100644 tests/ui/parser/macro/macro-expand-to-field.rs create mode 100644 tests/ui/parser/macro/macro-expand-to-field.stderr create mode 100644 tests/ui/parser/macro/macro-expand-to-match-arm.rs create mode 100644 tests/ui/parser/macro/macro-expand-to-match-arm.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 9787d98c1a49a..7d71449122f70 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -457,6 +457,12 @@ parse_loop_else = `{$loop_kind}...else` loops are not supported .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run .loop_keyword = `else` is attached to this loop +parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields + +parse_macro_expands_to_enum_variant = macros cannot expand to enum variants + +parse_macro_expands_to_match_arm = macros cannot expand to match arms + parse_macro_invocation_visibility = can't qualify macro invocation with `pub` .suggestion = remove the visibility .help = try adjusting the macro to put `{$vis}` inside the invocation diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 96e1c0e3c6d9e..7f209c63f4290 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1800,6 +1800,12 @@ pub struct UnknownPrefix<'a> { pub sugg: Option, } +#[derive(Subdiagnostic)] +#[note(parse_macro_expands_to_adt_field)] +pub struct MacroExpandsToAdtField<'a> { + pub adt_ty: &'a str, +} + #[derive(Subdiagnostic)] pub enum UnknownPrefixSugg { #[suggestion( diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c3cf6437afa07..3eed3ed9e1b50 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2591,6 +2591,7 @@ impl<'a> Parser<'a> { pub(crate) fn maybe_recover_unexpected_comma( &mut self, lo: Span, + is_mac_invoc: bool, rt: CommaRecoveryMode, ) -> PResult<'a, ()> { if self.token != token::Comma { @@ -2611,24 +2612,28 @@ impl<'a> Parser<'a> { let seq_span = lo.to(self.prev_token.span); let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - err.multipart_suggestion( - format!( - "try adding parentheses to match on a tuple{}", - if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, - ), - vec![ - (seq_span.shrink_to_lo(), "(".to_string()), - (seq_span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - if let CommaRecoveryMode::EitherTupleOrPipe = rt { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(',', " |"), + if is_mac_invoc { + err.note(fluent::parse_macro_expands_to_match_arm); + } else { + err.multipart_suggestion( + format!( + "try adding parentheses to match on a tuple{}", + if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, + ), + vec![ + (seq_span.shrink_to_lo(), "(".to_string()), + (seq_span.shrink_to_hi(), ")".to_string()), + ], Applicability::MachineApplicable, ); + if let CommaRecoveryMode::EitherTupleOrPipe = rt { + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), + Applicability::MachineApplicable, + ); + } } } Err(err) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 1470180dea714..6ec3a1ff1a572 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,8 +1,8 @@ -use crate::errors; - use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; +use crate::errors::{self, MacroExpandsToAdtField}; +use crate::fluent_generated as fluent; use ast::StaticItem; use rustc_ast::ast::*; use rustc_ast::ptr::P; @@ -1342,6 +1342,13 @@ impl<'a> Parser<'a> { } let ident = this.parse_field_ident("enum", vlo)?; + if this.token == token::Not { + return this.unexpected().map_err(|mut err| { + err.note(fluent::parse_macro_expands_to_enum_variant); + err + }); + } + let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { // Parse a struct variant. let (fields, recovered) = @@ -1369,7 +1376,7 @@ impl<'a> Parser<'a> { Ok((Some(vr), TrailingToken::MaybeComma)) }, - ).map_err(|mut err|{ + ).map_err(|mut err| { err.help("enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`"); err }) @@ -1691,9 +1698,10 @@ impl<'a> Parser<'a> { Ok(a_var) } - fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { + fn expect_field_ty_separator(&mut self, adt_ty: &str) -> PResult<'a, ()> { if let Err(mut err) = self.expect(&token::Colon) { let sm = self.sess.source_map(); + let mac_invoc = self.token.kind == token::Not; let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi && self.look_ahead(1, |t| { @@ -1705,7 +1713,9 @@ impl<'a> Parser<'a> { _ => true, } }); - if eq_typo || semi_typo { + if mac_invoc { + err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); + } else if eq_typo || semi_typo { self.bump(); // Gracefully handle small typos. err.span_suggestion_short( @@ -1713,8 +1723,8 @@ impl<'a> Parser<'a> { "field names and their types are separated with `:`", ":", Applicability::MachineApplicable, - ); - err.emit(); + ) + .emit(); } else { return Err(err); } @@ -1731,7 +1741,7 @@ impl<'a> Parser<'a> { attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - self.expect_field_ty_separator()?; + self.expect_field_ty_separator(adt_ty)?; let ty = self.parse_ty()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 14891c45d81a2..b477453615d79 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -135,7 +135,11 @@ impl<'a> Parser<'a> { // Parse the first pattern (`p_0`). let mut first_pat = self.parse_pat_no_top_alt(expected)?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma(first_pat.span, rt)?; + self.maybe_recover_unexpected_comma( + first_pat.span, + matches!(first_pat.kind, PatKind::MacCall(_)), + rt, + )?; } // If the next token is not a `|`, @@ -177,7 +181,11 @@ impl<'a> Parser<'a> { err })?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma(pat.span, rt)?; + self.maybe_recover_unexpected_comma( + pat.span, + matches!(pat.kind, PatKind::MacCall(_)), + rt, + )?; } pats.push(pat); } diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.rs b/tests/ui/parser/macro/macro-expand-to-field-2.rs new file mode 100644 index 0000000000000..2f806bcea845d --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field-2.rs @@ -0,0 +1,16 @@ +#![no_main] + +macro_rules! field { + ($name:ident:$type:ty) => { + $name:$type + }; +} + +enum EnumVariantField { + Named { //~ NOTE while parsing this struct + field!(oopsies:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR expected `:`, found `!` + //~^^ ERROR expected `,`, or `}`, found `(` + //~^^^ NOTE expected `:` + }, +} diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.stderr b/tests/ui/parser/macro/macro-expand-to-field-2.stderr new file mode 100644 index 0000000000000..8c3758173fee4 --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field-2.stderr @@ -0,0 +1,18 @@ +error: expected `:`, found `!` + --> $DIR/macro-expand-to-field-2.rs:11:14 + | +LL | field!(oopsies:()), + | ^ expected `:` + | + = note: macros cannot expand to struct fields + +error: expected `,`, or `}`, found `(` + --> $DIR/macro-expand-to-field-2.rs:11:15 + | +LL | Named { + | ----- while parsing this struct +LL | field!(oopsies:()), + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.rs b/tests/ui/parser/macro/macro-expand-to-field-3.rs new file mode 100644 index 0000000000000..0a8b655e0dc03 --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field-3.rs @@ -0,0 +1,15 @@ +#![no_main] + +macro_rules! field { + ($name:ident:$type:ty) => { + $name:$type + }; +} + +union EnumVariantField { //~ NOTE while parsing this union + A: u32, + field!(oopsies:()), //~ NOTE macros cannot expand to union fields + //~^ ERROR expected `:`, found `!` + //~^^ ERROR expected `,`, or `}`, found `(` + //~^^^ NOTE expected `:` +} diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.stderr b/tests/ui/parser/macro/macro-expand-to-field-3.stderr new file mode 100644 index 0000000000000..360b2bf793ba0 --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field-3.stderr @@ -0,0 +1,19 @@ +error: expected `:`, found `!` + --> $DIR/macro-expand-to-field-3.rs:11:10 + | +LL | field!(oopsies:()), + | ^ expected `:` + | + = note: macros cannot expand to union fields + +error: expected `,`, or `}`, found `(` + --> $DIR/macro-expand-to-field-3.rs:11:11 + | +LL | union EnumVariantField { + | ---------------- while parsing this union +LL | A: u32, +LL | field!(oopsies:()), + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs new file mode 100644 index 0000000000000..38055a3bbb2dd --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -0,0 +1,26 @@ +#![no_main] + +macro_rules! field { + ($name:ident:$type:ty) => { + $name:$type + }; +} + +macro_rules! variant { + ($name:ident) => { + $name + } +} + +struct Struct { //~ NOTE while parsing this struct + field!(bar:u128), //~ NOTE macros cannot expand to struct fields + //~^ ERROR expected `:`, found `!` + //~^^ NOTE expected `:` + //~^^^ ERROR expected `,`, or `}`, found `(` +} + +enum EnumVariant { //~ NOTE while parsing this enum + variant!(whoops), //~ NOTE macros cannot expand to enum variants + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this +} diff --git a/tests/ui/parser/macro/macro-expand-to-field.stderr b/tests/ui/parser/macro/macro-expand-to-field.stderr new file mode 100644 index 0000000000000..3f7fad334ecd2 --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-field.stderr @@ -0,0 +1,29 @@ +error: expected `:`, found `!` + --> $DIR/macro-expand-to-field.rs:16:10 + | +LL | field!(bar:u128), + | ^ expected `:` + | + = note: macros cannot expand to struct fields + +error: expected `,`, or `}`, found `(` + --> $DIR/macro-expand-to-field.rs:16:11 + | +LL | struct Struct { + | ------ while parsing this struct +LL | field!(bar:u128), + | ^ + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:23:12 + | +LL | enum EnumVariant { + | ----------- while parsing this enum +LL | variant!(whoops), + | ^ unexpected token after this + | + = note: macros cannot expand to enum variants + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs new file mode 100644 index 0000000000000..043bf371902c4 --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -0,0 +1,15 @@ +macro_rules! arm { + ($pattern:pat => $block:block) => { + $pattern => $block + }; +} + +fn main() { + let x = Some(1); + match x { + Some(1) => {}, + arm!(None => {}), //~ NOTE macros cannot expand to match arms + //~^ ERROR unexpected `,` in pattern + _ => {}, + }; +} diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr new file mode 100644 index 0000000000000..1a5f4696858cf --- /dev/null +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr @@ -0,0 +1,10 @@ +error: unexpected `,` in pattern + --> $DIR/macro-expand-to-match-arm.rs:11:25 + | +LL | arm!(None => {}), + | ^ + | + = note: macros cannot expand to match arms + +error: aborting due to previous error + From dece622ee48d9744d6e64891a734e8fd25eac903 Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Mon, 24 Jul 2023 17:05:10 +0000 Subject: [PATCH 02/10] Recover from some macros --- compiler/rustc_parse/src/parser/item.rs | 46 ++++++++++---- compiler/rustc_parse/src/parser/pat.rs | 6 +- .../parser/macro/macro-expand-to-field-2.rs | 16 ----- .../macro/macro-expand-to-field-2.stderr | 18 ------ .../parser/macro/macro-expand-to-field-3.rs | 15 ----- .../macro/macro-expand-to-field-3.stderr | 19 ------ .../ui/parser/macro/macro-expand-to-field.rs | 41 ++++++++++-- .../parser/macro/macro-expand-to-field.stderr | 63 +++++++++++++++---- .../parser/macro/macro-expand-to-match-arm.rs | 2 + 9 files changed, 124 insertions(+), 102 deletions(-) delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.rs delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.stderr delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.rs delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6ec3a1ff1a572..7b479067ecdce 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1343,10 +1343,14 @@ impl<'a> Parser<'a> { let ident = this.parse_field_ident("enum", vlo)?; if this.token == token::Not { - return this.unexpected().map_err(|mut err| { - err.note(fluent::parse_macro_expands_to_enum_variant); - err - }); + if let Err(mut err) = this.unexpected::<()>() { + err.note(fluent::parse_macro_expands_to_enum_variant).emit(); + } + + this.bump(); + this.parse_delim_args()?; + + return Ok((None, TrailingToken::MaybeComma)); } let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { @@ -1586,7 +1590,8 @@ impl<'a> Parser<'a> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; - Ok((this.parse_single_struct_field(adt_ty, lo, vis, attrs)?, TrailingToken::None)) + this.parse_single_struct_field(adt_ty, lo, vis, attrs) + .map(|field| (field, TrailingToken::None)) }) } @@ -1698,10 +1703,9 @@ impl<'a> Parser<'a> { Ok(a_var) } - fn expect_field_ty_separator(&mut self, adt_ty: &str) -> PResult<'a, ()> { + fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { if let Err(mut err) = self.expect(&token::Colon) { let sm = self.sess.source_map(); - let mac_invoc = self.token.kind == token::Not; let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi && self.look_ahead(1, |t| { @@ -1713,9 +1717,7 @@ impl<'a> Parser<'a> { _ => true, } }); - if mac_invoc { - err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); - } else if eq_typo || semi_typo { + if eq_typo || semi_typo { self.bump(); // Gracefully handle small typos. err.span_suggestion_short( @@ -1741,7 +1743,29 @@ impl<'a> Parser<'a> { attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - self.expect_field_ty_separator(adt_ty)?; + // Parse the macro invocation and recover + if self.token.kind == token::Not { + if let Err(mut err) = self.unexpected::() { + err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); + self.bump(); + self.parse_delim_args()?; + return Ok(FieldDef { + span: DUMMY_SP, + ident: None, + vis, + id: DUMMY_NODE_ID, + ty: P(Ty { + id: DUMMY_NODE_ID, + kind: TyKind::Err, + span: DUMMY_SP, + tokens: None, + }), + attrs, + is_placeholder: false, + }); + } + } + self.expect_field_ty_separator()?; let ty = self.parse_ty()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b477453615d79..58c00ebdea0dd 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -181,11 +181,7 @@ impl<'a> Parser<'a> { err })?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma( - pat.span, - matches!(pat.kind, PatKind::MacCall(_)), - rt, - )?; + self.maybe_recover_unexpected_comma(pat.span, false, rt)?; } pats.push(pat); } diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.rs b/tests/ui/parser/macro/macro-expand-to-field-2.rs deleted file mode 100644 index 2f806bcea845d..0000000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![no_main] - -macro_rules! field { - ($name:ident:$type:ty) => { - $name:$type - }; -} - -enum EnumVariantField { - Named { //~ NOTE while parsing this struct - field!(oopsies:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR expected `:`, found `!` - //~^^ ERROR expected `,`, or `}`, found `(` - //~^^^ NOTE expected `:` - }, -} diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.stderr b/tests/ui/parser/macro/macro-expand-to-field-2.stderr deleted file mode 100644 index 8c3758173fee4..0000000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-2.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: expected `:`, found `!` - --> $DIR/macro-expand-to-field-2.rs:11:14 - | -LL | field!(oopsies:()), - | ^ expected `:` - | - = note: macros cannot expand to struct fields - -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field-2.rs:11:15 - | -LL | Named { - | ----- while parsing this struct -LL | field!(oopsies:()), - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.rs b/tests/ui/parser/macro/macro-expand-to-field-3.rs deleted file mode 100644 index 0a8b655e0dc03..0000000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_main] - -macro_rules! field { - ($name:ident:$type:ty) => { - $name:$type - }; -} - -union EnumVariantField { //~ NOTE while parsing this union - A: u32, - field!(oopsies:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR expected `:`, found `!` - //~^^ ERROR expected `,`, or `}`, found `(` - //~^^^ NOTE expected `:` -} diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.stderr b/tests/ui/parser/macro/macro-expand-to-field-3.stderr deleted file mode 100644 index 360b2bf793ba0..0000000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-3.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: expected `:`, found `!` - --> $DIR/macro-expand-to-field-3.rs:11:10 - | -LL | field!(oopsies:()), - | ^ expected `:` - | - = note: macros cannot expand to union fields - -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field-3.rs:11:11 - | -LL | union EnumVariantField { - | ---------------- while parsing this union -LL | A: u32, -LL | field!(oopsies:()), - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs index 38055a3bbb2dd..fd1d408e7265b 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.rs +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -12,15 +12,46 @@ macro_rules! variant { } } -struct Struct { //~ NOTE while parsing this struct +struct Struct { field!(bar:u128), //~ NOTE macros cannot expand to struct fields - //~^ ERROR expected `:`, found `!` - //~^^ NOTE expected `:` - //~^^^ ERROR expected `,`, or `}`, found `(` + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this + a: u32, + b: u32, + field!(recovers:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this } -enum EnumVariant { //~ NOTE while parsing this enum +enum EnumVariant { variant!(whoops), //~ NOTE macros cannot expand to enum variants //~^ ERROR unexpected token: `!` //~^^ NOTE unexpected token after this + U32, + F64, + variant!(recovers), //~ NOTE macros cannot expand to enum variants + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this +} + +enum EnumVariantField { + Named { + field!(oopsies:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + field!(oopsies2:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + }, +} + +union Union { + A: u32, + field!(oopsies:()), //~ NOTE macros cannot expand to union fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + B: u32, + field!(recovers:()), //~ NOTE macros cannot expand to union fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this } diff --git a/tests/ui/parser/macro/macro-expand-to-field.stderr b/tests/ui/parser/macro/macro-expand-to-field.stderr index 3f7fad334ecd2..108b68b481f05 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.stderr +++ b/tests/ui/parser/macro/macro-expand-to-field.stderr @@ -1,29 +1,66 @@ -error: expected `:`, found `!` +error: unexpected token: `!` --> $DIR/macro-expand-to-field.rs:16:10 | LL | field!(bar:u128), - | ^ expected `:` + | ^ unexpected token after this | = note: macros cannot expand to struct fields -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field.rs:16:11 +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:21:10 | -LL | struct Struct { - | ------ while parsing this struct -LL | field!(bar:u128), - | ^ +LL | field!(recovers:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:23:12 + --> $DIR/macro-expand-to-field.rs:27:12 | -LL | enum EnumVariant { - | ----------- while parsing this enum LL | variant!(whoops), | ^ unexpected token after this | = note: macros cannot expand to enum variants - = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` -error: aborting due to 3 previous errors +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:32:12 + | +LL | variant!(recovers), + | ^ unexpected token after this + | + = note: macros cannot expand to enum variants + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:39:14 + | +LL | field!(oopsies:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:42:14 + | +LL | field!(oopsies2:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:50:10 + | +LL | field!(oopsies:()), + | ^ unexpected token after this + | + = note: macros cannot expand to union fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:54:10 + | +LL | field!(recovers:()), + | ^ unexpected token after this + | + = note: macros cannot expand to union fields + +error: aborting due to 8 previous errors diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index 043bf371902c4..c176e8bbd9dc5 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -10,6 +10,8 @@ fn main() { Some(1) => {}, arm!(None => {}), //~ NOTE macros cannot expand to match arms //~^ ERROR unexpected `,` in pattern + // doesn't recover + Some(2) => {}, _ => {}, }; } From c7db0f47514aa122641e30fb5b3d1a6d76a6b4d8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 2 Aug 2023 00:44:41 +0200 Subject: [PATCH 03/10] Migrate GUI colors test to original CSS color format --- tests/rustdoc-gui/pocket-menu.goml | 73 ++++++++++++------------------ 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml index 4bdf31ecb1997..404e574030591 100644 --- a/tests/rustdoc-gui/pocket-menu.goml +++ b/tests/rustdoc-gui/pocket-menu.goml @@ -29,52 +29,39 @@ click: "#help-button" assert-css: ("#help-button .popover", {"display": "none"}) assert-css: ("#settings-menu .popover", {"display": "none"}) -// We check the borders color now: - -// Ayu theme -set-local-storage: { - "rustdoc-theme": "ayu", - "rustdoc-use-system-theme": "false", -} -reload: - -click: "#help-button" -assert-css: ( - "#help-button .popover", - {"display": "block", "border-color": "rgb(92, 103, 115)"}, -) -compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) -compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) - -// Dark theme -set-local-storage: { - "rustdoc-theme": "dark", - "rustdoc-use-system-theme": "false", -} -reload: +define-function: ( + "check-popover-colors", + (theme, border_color), + block { + set-local-storage: { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + } + reload: -click: "#help-button" -assert-css: ( - "#help-button .popover", - {"display": "block", "border-color": "rgb(224, 224, 224)"}, + click: "#help-button" + assert-css: ( + "#help-button .popover", + {"display": "block", "border-color": |border_color|}, + ) + compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) + compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) + } ) -compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) -compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) - -// Light theme -set-local-storage: { - "rustdoc-theme": "light", - "rustdoc-use-system-theme": "false", -} -reload: -click: "#help-button" -assert-css: ( - "#help-button .popover", - {"display": "block", "border-color": "rgb(224, 224, 224)"}, -) -compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) -compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) +// We check the borders color now: +call-function: ("check-popover-colors", { + "theme": "ayu", + "border_color": "#5c6773", +}) +call-function: ("check-popover-colors", { + "theme": "dark", + "border_color": "#e0e0e0", +}) +call-function: ("check-popover-colors", { + "theme": "light", + "border_color": "#e0e0e0", +}) // Opening the mobile sidebar should close the settings popover. set-window-size: (650, 600) From bbd69e4a4c27f2407326a71a4eb37de694a72b87 Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Wed, 2 Aug 2023 23:59:30 +0000 Subject: [PATCH 04/10] Add test for enum with fields --- compiler/rustc_parse/src/parser/item.rs | 7 +-- .../ui/parser/macro/macro-expand-to-field.rs | 57 ++++++++++++------- .../parser/macro/macro-expand-to-field.stderr | 22 ++++--- .../parser/macro/macro-expand-to-match-arm.rs | 5 +- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 7b479067ecdce..2f1d377585d78 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1754,12 +1754,7 @@ impl<'a> Parser<'a> { ident: None, vis, id: DUMMY_NODE_ID, - ty: P(Ty { - id: DUMMY_NODE_ID, - kind: TyKind::Err, - span: DUMMY_SP, - tokens: None, - }), + ty: self.mk_ty(DUMMY_SP, TyKind::Err), attrs, is_placeholder: false, }); diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs index fd1d408e7265b..155872f7a5d79 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.rs +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -1,4 +1,4 @@ -#![no_main] +// compile-flags: --crate-type=lib macro_rules! field { ($name:ident:$type:ty) => { @@ -13,9 +13,10 @@ macro_rules! variant { } struct Struct { - field!(bar:u128), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + field!(bar:u128), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this a: u32, b: u32, field!(recovers:()), //~ NOTE macros cannot expand to struct fields @@ -24,34 +25,46 @@ struct Struct { } enum EnumVariant { - variant!(whoops), //~ NOTE macros cannot expand to enum variants - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + variant!(whoops), + //~^ NOTE macros cannot expand to enum variants + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this U32, F64, - variant!(recovers), //~ NOTE macros cannot expand to enum variants - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + variant!(recovers), + //~^ NOTE macros cannot expand to enum variants + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this + Data { + field!(x:u32), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this + } } enum EnumVariantField { Named { - field!(oopsies:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this - field!(oopsies2:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(oopsies:()), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this + field!(oopsies2:()), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this }, } union Union { A: u32, - field!(oopsies:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(oopsies:()), + //~^ NOTE macros cannot expand to union fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this B: u32, - field!(recovers:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(recovers:()), + //~^ NOTE macros cannot expand to union fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this } diff --git a/tests/ui/parser/macro/macro-expand-to-field.stderr b/tests/ui/parser/macro/macro-expand-to-field.stderr index 108b68b481f05..adcd032f5c0df 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.stderr +++ b/tests/ui/parser/macro/macro-expand-to-field.stderr @@ -7,7 +7,7 @@ LL | field!(bar:u128), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:21:10 + --> $DIR/macro-expand-to-field.rs:22:10 | LL | field!(recovers:()), | ^ unexpected token after this @@ -15,7 +15,7 @@ LL | field!(recovers:()), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:27:12 + --> $DIR/macro-expand-to-field.rs:28:12 | LL | variant!(whoops), | ^ unexpected token after this @@ -23,7 +23,7 @@ LL | variant!(whoops), = note: macros cannot expand to enum variants error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:32:12 + --> $DIR/macro-expand-to-field.rs:34:12 | LL | variant!(recovers), | ^ unexpected token after this @@ -33,13 +33,21 @@ LL | variant!(recovers), error: unexpected token: `!` --> $DIR/macro-expand-to-field.rs:39:14 | +LL | field!(x:u32), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:48:14 + | LL | field!(oopsies:()), | ^ unexpected token after this | = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:42:14 + --> $DIR/macro-expand-to-field.rs:52:14 | LL | field!(oopsies2:()), | ^ unexpected token after this @@ -47,7 +55,7 @@ LL | field!(oopsies2:()), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:50:10 + --> $DIR/macro-expand-to-field.rs:61:10 | LL | field!(oopsies:()), | ^ unexpected token after this @@ -55,12 +63,12 @@ LL | field!(oopsies:()), = note: macros cannot expand to union fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:54:10 + --> $DIR/macro-expand-to-field.rs:66:10 | LL | field!(recovers:()), | ^ unexpected token after this | = note: macros cannot expand to union fields -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index c176e8bbd9dc5..39d1d065ed986 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -8,8 +8,9 @@ fn main() { let x = Some(1); match x { Some(1) => {}, - arm!(None => {}), //~ NOTE macros cannot expand to match arms - //~^ ERROR unexpected `,` in pattern + arm!(None => {}), + //~^ NOTE macros cannot expand to match arms + //~| ERROR unexpected `,` in pattern // doesn't recover Some(2) => {}, _ => {}, From d0ed4edfc65645cd7377ad501f1a2c5c8b5385b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Aug 2023 11:25:25 +0200 Subject: [PATCH 05/10] Migrate GUI colors test to original CSS color format --- tests/rustdoc-gui/sidebar-source-code-display.goml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/sidebar-source-code-display.goml b/tests/rustdoc-gui/sidebar-source-code-display.goml index 33210c9fdc9c1..88546ed254925 100644 --- a/tests/rustdoc-gui/sidebar-source-code-display.goml +++ b/tests/rustdoc-gui/sidebar-source-code-display.goml @@ -141,7 +141,7 @@ call-function: ("check-colors", { "theme": "ayu", "color": "#c5c5c5", "color_hover": "#ffb44c", - "background": "rgb(20, 25, 31)", + "background": "#14191f", "background_hover": "#14191f", "background_toggle": "rgba(0, 0, 0, 0)", "background_toggle_hover": "rgba(70, 70, 70, 0.33)", From 4457ef2c6db2aa65aeaba084d2d85f3355595f5a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 10 Jul 2023 13:03:48 +0000 Subject: [PATCH 06/10] Forbid old-style `simd_shuffleN` intrinsics --- .../src/intrinsics/simd.rs | 54 +-- .../rustc_codegen_gcc/src/intrinsic/simd.rs | 445 ++++++++++-------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 34 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 +- .../src/error_codes/E0439.md | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 14 - .../src/lower_intrinsics.rs | 2 +- tests/incremental/issue-61530.rs | 6 +- .../simd/intrinsic/generic-elements-pass.rs | 22 +- tests/ui/simd/intrinsic/generic-elements.rs | 22 +- .../ui/simd/intrinsic/generic-elements.stderr | 74 +-- .../simd/intrinsic/inlining-issue67557-ice.rs | 4 +- .../ui/simd/intrinsic/inlining-issue67557.rs | 6 +- tests/ui/simd/shuffle-not-out-of-bounds.rs | 31 +- .../ui/simd/shuffle-not-out-of-bounds.stderr | 50 +- tests/ui/simd/shuffle.rs | 3 +- 16 files changed, 393 insertions(+), 380 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index d1c29f24ab96d..9863e40b5b7a1 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -117,8 +117,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - // simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U - _ if intrinsic.as_str().starts_with("simd_shuffle") => { + // simd_shuffle(x: T, y: T, idx: I) -> U + sym::simd_shuffle => { let (x, y, idx) = match args { [x, y, idx] => (x, y, idx), _ => { @@ -133,36 +133,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; } - // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. - // If there is no suffix, use the index array length. - let n: u16 = if intrinsic == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); - match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len - .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) - .unwrap_or_else(|| { - span_bug!(span, "could not evaluate shuffle index array length") - }) - .try_into() - .unwrap(), - _ => { - fx.tcx.sess.span_err( - span, - format!( - "simd_shuffle index must be an array of `u32`, got `{}`", - idx_ty, - ), - ); - // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - return; - } + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + let n: u16 = match idx_ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len + .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) + .unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }) + .try_into() + .unwrap(), + _ => { + fx.tcx.sess.span_err( + span, + format!("simd_shuffle index must be an array of `u32`, got `{}`", idx_ty), + ); + // Prevent verifier error + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; } - } else { - // FIXME remove this case - intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() }; assert_eq!(x.layout(), y.layout()); @@ -179,7 +169,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; let idx_const = crate::constant::mir_operand_get_const_val(fx, idx) - .expect("simd_shuffle* idx not const"); + .expect("simd_shuffle idx not const"); let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index f27de867d367b..85d3e7234a0e6 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -1,11 +1,11 @@ -#[cfg(feature="master")] -use gccjit::{ComparisonOp, UnaryOp}; use gccjit::ToRValue; use gccjit::{BinaryOp, RValue, Type}; +#[cfg(feature = "master")] +use gccjit::{ComparisonOp, UnaryOp}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -#[cfg(feature="master")] +#[cfg(feature = "master")] use rustc_codegen_ssa::errors::ExpectedPointerMutability; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; @@ -19,7 +19,7 @@ use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::Align; use crate::builder::Builder; -#[cfg(feature="master")] +#[cfg(feature = "master")] use crate::context::CodegenCx; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( @@ -57,7 +57,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -95,7 +98,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // NOTE: since the arguments can be vectors of floats, make sure the mask is a vector of // integer. let mask_element_type = bx.type_ix(arg1_element_type.get_size() as u64 * 8); - let vector_mask_type = bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); + let vector_mask_type = + bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); let mut elements = vec![]; let one = bx.context.new_rvalue_one(mask.get_type()); @@ -149,38 +153,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // compare them as equal, so bitcast. // FIXME(antoyo): allow comparing vector types as equal in libgccjit. let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type()); - return Ok(compare_simd_types( - bx, - arg1, - arg2, - in_elem, - llret_ty, - cmp_op, - )); + return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op)); } - if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { - let n: u64 = if stripped.is_empty() { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + if name == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let n: u64 = match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( + || span_bug!(span, "could not evaluate shuffle index array length"), + ) } - } else { - stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }) + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), }; - require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); @@ -202,7 +192,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -228,7 +224,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, @@ -241,7 +240,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); @@ -267,19 +266,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Unsupported, } - let in_style = - match in_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let in_style = match in_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; - let out_style = - match out_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let out_style = match out_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; match (in_style, out_style) { (Style::Unsupported, Style::Unsupported) => { @@ -294,7 +291,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( out_elem } ); - }, + } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } } @@ -342,10 +339,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mut shift = 0; for i in 0..in_len { - let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); + let elem = + bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); let shifted = elem >> sign_shift; let masked = shifted & one; - result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift)); + result = result + | (bx.context.new_cast(None, masked, result_type) + << bx.context.new_rvalue_from_int(result_type, shift)); shift += 1; } @@ -394,46 +394,50 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Err(()); }}; } - let (elem_ty_str, elem_ty) = - if let ty::Float(f) = in_elem.kind() { - let elem_ty = bx.cx.type_float_from_ty(*f); - match f.bit_width() { - 32 => ("f", elem_ty), - 64 => ("", elem_ty), - _ => { - return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty }); - } + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { + let elem_ty = bx.cx.type_float_from_ty(*f); + match f.bit_width() { + 32 => ("f", elem_ty), + 64 => ("", elem_ty), + _ => { + return_error!(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty + }); } } - else { - return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); - }; + } else { + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); - let intr_name = - match name { - sym::simd_ceil => "ceil", - sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 - sym::simd_fcos => "cos", - sym::simd_fexp2 => "exp2", - sym::simd_fexp => "exp", - sym::simd_flog10 => "log10", - sym::simd_flog2 => "log2", - sym::simd_flog => "log", - sym::simd_floor => "floor", - sym::simd_fma => "fma", - sym::simd_fpowi => "__builtin_powi", - sym::simd_fpow => "pow", - sym::simd_fsin => "sin", - sym::simd_fsqrt => "sqrt", - sym::simd_round => "round", - sym::simd_trunc => "trunc", - _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }) - }; + let intr_name = match name { + sym::simd_ceil => "ceil", + sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 + sym::simd_fcos => "cos", + sym::simd_fexp2 => "exp2", + sym::simd_fexp => "exp", + sym::simd_flog10 => "log10", + sym::simd_flog2 => "log2", + sym::simd_flog => "log", + sym::simd_floor => "floor", + sym::simd_fma => "fma", + sym::simd_fpowi => "__builtin_powi", + sym::simd_fpow => "pow", + sym::simd_fsin => "sin", + sym::simd_fsqrt => "sqrt", + sym::simd_round => "round", + sym::simd_trunc => "trunc", + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), + }; let builtin_name = format!("{}{}", intr_name, elem_ty_str); let funcs = bx.cx.functions.borrow(); - let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); + let function = funcs + .get(&builtin_name) + .unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); // TODO(antoyo): add platform-specific behavior here for architectures that have these // intrinsics as instructions (for instance, gpus) @@ -479,8 +483,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } - #[cfg(feature="master")] - fn vector_ty<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, elem_ty: Ty<'tcx>, vec_len: u64) -> Type<'gcc> { + #[cfg(feature = "master")] + fn vector_ty<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + elem_ty: Ty<'tcx>, + vec_len: u64, + ) -> Type<'gcc> { // FIXME: use cx.layout_of(ty).llvm_type() ? let elem_ty = match *elem_ty.kind() { ty::Int(v) => cx.type_int_from_ty(v), @@ -491,15 +499,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( cx.type_vector(elem_ty, vec_len) } - #[cfg(feature="master")] - fn gather<'a, 'gcc, 'tcx>(default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, underlying_ty: Ty<'tcx>, invert: bool) -> RValue<'gcc> { - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + #[cfg(feature = "master")] + fn gather<'a, 'gcc, 'tcx>( + default: RValue<'gcc>, + pointers: RValue<'gcc>, + mask: RValue<'gcc>, + pointer_count: usize, + bx: &mut Builder<'a, 'gcc, 'tcx>, + in_len: u64, + underlying_ty: Ty<'tcx>, + invert: bool, + ) -> RValue<'gcc> { + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); let mut values = vec![]; @@ -530,13 +545,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if invert { bx.shuffle_vector(vector, default, mask) - } - else { + } else { bx.shuffle_vector(default, vector, mask) } } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_gather { // simd_gather(values: , pointers: , // mask: ) -> @@ -546,8 +560,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: @@ -641,10 +661,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - return Ok(gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, false)); + return Ok(gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + false, + )); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_scatter { // simd_scatter(values: , pointers: , // mask: ) -> () @@ -654,8 +683,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -744,17 +779,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - let result = gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, true); + let result = gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + true, + ); let pointers = args[1].immediate(); - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); for i in 0..in_len { @@ -809,11 +851,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let rhs = args[1].immediate(); let is_add = name == sym::simd_saturating_add; let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; - let (signed, elem_width, elem_ty) = - match *in_elem.kind() { - ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), - ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), - _ => { + let (signed, elem_width, elem_ty) = match *in_elem.kind() { + ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), + ty::Uint(i) => { + (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)) + } + _ => { return_error!(InvalidMonomorphization::ExpectedVectorElementType { span, name, @@ -823,77 +866,82 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } }; - let result = - match (signed, is_add) { - (false, true) => { - let res = lhs + rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); - res | cmp - }, - (true, true) => { - // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition - // TODO(antoyo): improve using conditional operators if possible. - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; - - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; - - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; - - and1 + and2 - }, - (false, false) => { - let res = lhs - rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); - res & cmp - }, - (true, false) => { - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): this uses the same algorithm from saturating add, but add the - // negative of the right operand. Find a proper subtraction algorithm. - let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; - - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; - - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; - - and1 + and2 - } - }; + let result = match (signed, is_add) { + (false, true) => { + let res = lhs + rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); + res | cmp + } + (true, true) => { + // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition + // TODO(antoyo): improve using conditional operators if possible. + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; + + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; + + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; + + and1 + and2 + } + (false, false) => { + let res = lhs - rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); + res & cmp + } + (true, false) => { + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): this uses the same algorithm from saturating add, but add the + // negative of the right operand. Find a proper subtraction algorithm. + let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); + + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; + + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; + + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; + + and1 + and2 + } + }; return Ok(result); } @@ -968,7 +1016,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( 1.0 ); - macro_rules! minmax_red { ($name:ident: $int_red:ident, $float_red:ident) => { if name == sym::$name { @@ -979,13 +1026,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { - span, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, name, symbol: sym::$name, in_ty, - in_elem, - ret_ty + in_elem, + ret_ty }), }; } @@ -1025,7 +1072,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(input, $op); - Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) + Ok(if !$boolean { + r + } else { + bx.icmp( + IntPredicate::IntNE, + r, + bx.context.new_rvalue_zero(r.get_type()), + ) + }) } _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 86c39ab5e943f..6f1e4c5178aae 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1020,28 +1020,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>( )); } - if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { - // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. - // If there is no suffix, use the index array length. - let n: u64 = if stripped.is_empty() { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + if name == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let n: u64 = match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( + || span_bug!(span, "could not evaluate shuffle index array length"), + ) } - } else { - stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }) + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), }; require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f13dfd96b8ee9..4f26383ed05f0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -862,11 +862,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .iter() .enumerate() .map(|(i, arg)| { - // The indices passed to simd_shuffle* in the + // The indices passed to simd_shuffle in the // third argument must be constant. This is // checked by const-qualification, which also // promotes any complex rvalues to constants. - if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") { + if i == 2 && intrinsic == sym::simd_shuffle { if let mir::Operand::Constant(constant) = arg { let (llval, ty) = self.simd_shuffle_indices(&bx, constant); return OperandRef { diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md index 24268aef2222a..369226c383ec5 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0439.md +++ b/compiler/rustc_error_codes/src/error_codes/E0439.md @@ -16,7 +16,7 @@ extern "platform-intrinsic" { The `simd_shuffle` function needs the length of the array passed as last parameter in its name. Example: -``` +```ignore (no longer compiles) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 064021b1ea429..970efaf312c54 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -567,20 +567,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_min_nanless | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), - name if name.as_str().starts_with("simd_shuffle") => { - match name.as_str()["simd_shuffle".len()..].parse() { - Ok(n) => { - let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)]; - (2, params, param(1)) - } - Err(_) => { - let msg = - format!("unrecognized platform-specific intrinsic function: `{name}`"); - tcx.sess.struct_span_err(it.span, msg).emit(); - return; - } - } - } _ => { let msg = format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, msg).emit(); diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index d1ecfe9f8512d..fc36c6e4124a6 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -305,7 +305,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Unreachable; } } - _ if intrinsic_name.as_str().starts_with("simd_shuffle") => { + sym::simd_shuffle => { validate_simd_shuffle(tcx, args, terminator.source_info.span); } _ => {} diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs index edb3d60ba3f89..1dcb41ddedae2 100644 --- a/tests/incremental/issue-61530.rs +++ b/tests/incremental/issue-61530.rs @@ -6,13 +6,13 @@ struct I32x2(i32, i32); extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } fn main() { unsafe { const IDX: [u32; 2] = [0, 0]; - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX); - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); } } diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 3c913c0adfa60..905c3b8d3cca1 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -22,9 +22,7 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } macro_rules! all_eq { @@ -83,19 +81,19 @@ fn main() { let y4 = i32x4(140, 141, 142, 143); let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); unsafe { - all_eq!(simd_shuffle2(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); - all_eq!(simd_shuffle4(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); - all_eq!(simd_shuffle8(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), i32x8(121, 20, 21, 120, 21, 120, 121, 20)); - all_eq!(simd_shuffle2(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); - all_eq!(simd_shuffle4(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); - all_eq!(simd_shuffle8(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), i32x8(143, 42, 141, 40, 43, 142, 140, 41)); - all_eq!(simd_shuffle2(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); - all_eq!(simd_shuffle4(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); - all_eq!(simd_shuffle8(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), i32x8(183, 85, 187, 80, 83, 180, 184, 81)); } diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index abde69163bd4e..0ff2203ec722e 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -34,9 +34,7 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } fn main() { @@ -51,27 +49,27 @@ fn main() { //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` const IDX2: [u32; 2] = [0; 2]; - simd_shuffle2::(0, 0, IDX2); + simd_shuffle::(0, 0, IDX2); //~^ ERROR expected SIMD input type, found non-SIMD `i32` const IDX4: [u32; 4] = [0; 4]; - simd_shuffle4::(0, 0, IDX4); + simd_shuffle::(0, 0, IDX4); //~^ ERROR expected SIMD input type, found non-SIMD `i32` const IDX8: [u32; 8] = [0; 8]; - simd_shuffle8::(0, 0, IDX8); + simd_shuffle::(0, 0, IDX8); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - simd_shuffle2::<_, f32x2>(x, x, IDX2); + simd_shuffle::<_, _, f32x2>(x, x, IDX2); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - simd_shuffle4::<_, f32x4>(x, x, IDX4); + simd_shuffle::<_, _, f32x4>(x, x, IDX4); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - simd_shuffle8::<_, f32x8>(x, x, IDX8); + simd_shuffle::<_, _, f32x8>(x, x, IDX8); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - simd_shuffle2::<_, i32x8>(x, x, IDX2); + simd_shuffle::<_, _, i32x8>(x, x, IDX2); //~^ ERROR expected return type of length 2, found `i32x8` with length 8 - simd_shuffle4::<_, i32x8>(x, x, IDX4); + simd_shuffle::<_, _, i32x8>(x, x, IDX4); //~^ ERROR expected return type of length 4, found `i32x8` with length 8 - simd_shuffle8::<_, i32x2>(x, x, IDX8); + simd_shuffle::<_, _, i32x2>(x, x, IDX8); //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } } diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index 5b423f7040f90..115d9d4b3f3ac 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,74 +1,74 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:44:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:46:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:50:9 + --> $DIR/generic-elements.rs:48:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:54:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:52:9 | -LL | simd_shuffle2::(0, 0, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:57:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:55:9 | -LL | simd_shuffle4::(0, 0, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:60:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:58:9 | -LL | simd_shuffle8::(0, 0, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + --> $DIR/generic-elements.rs:61:9 + | +LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` --> $DIR/generic-elements.rs:63:9 | -LL | simd_shuffle2::<_, f32x2>(x, x, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` --> $DIR/generic-elements.rs:65:9 | -LL | simd_shuffle4::<_, f32x4>(x, x, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:67:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:68:9 | -LL | simd_shuffle8::<_, f32x8>(x, x, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 --> $DIR/generic-elements.rs:70:9 | -LL | simd_shuffle2::<_, i32x8>(x, x, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 --> $DIR/generic-elements.rs:72:9 | -LL | simd_shuffle4::<_, i32x8>(x, x, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:74:9 - | -LL | simd_shuffle8::<_, i32x2>(x, x, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index 7221b3ab769db..5ca684a9d7831 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -6,7 +6,7 @@ #![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } #[repr(simd)] @@ -22,5 +22,5 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index 0d15427095a74..5633ad70cd318 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -6,7 +6,7 @@ #![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } #[repr(simd)] @@ -16,7 +16,7 @@ struct Simd2(u8, u8); fn main() { unsafe { const IDX: [u32; 2] = [0, 1]; - let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX); + let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -38,5 +38,5 @@ fn assert_10_13(x: Simd2) { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.rs b/tests/ui/simd/shuffle-not-out-of-bounds.rs index 0dee3a0e869d7..18939bcc5b4b2 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.rs +++ b/tests/ui/simd/shuffle-not-out-of-bounds.rs @@ -29,12 +29,7 @@ struct u8x32([u8; 32]); struct u8x64([u8; 64]); extern "platform-intrinsic" { - pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; - pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; - pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U; - pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U; + pub fn simd_shuffle(x: T, y: T, idx: I) -> U; } // Test vectors by lane size. Since LLVM does not distinguish between a shuffle @@ -58,22 +53,22 @@ macro_rules! test_shuffle_lanes { } } } -//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic +//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic // Because the test is mostly embedded in a macro, all the errors have the same origin point. // And unfortunately, standard comments, as in the UI test harness, disappear in macros! fn main() { - test_shuffle_lanes!(2, u8x2, simd_shuffle2); - test_shuffle_lanes!(4, u8x4, simd_shuffle4); - test_shuffle_lanes!(8, u8x8, simd_shuffle8); - test_shuffle_lanes!(16, u8x16, simd_shuffle16); - test_shuffle_lanes!(32, u8x32, simd_shuffle32); - test_shuffle_lanes!(64, u8x64, simd_shuffle64); + test_shuffle_lanes!(2, u8x2, simd_shuffle); + test_shuffle_lanes!(4, u8x4, simd_shuffle); + test_shuffle_lanes!(8, u8x8, simd_shuffle); + test_shuffle_lanes!(16, u8x16, simd_shuffle); + test_shuffle_lanes!(32, u8x32, simd_shuffle); + test_shuffle_lanes!(64, u8x64, simd_shuffle); extern "platform-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.stderr b/tests/ui/simd/shuffle-not-out-of-bounds.stderr index 415f04d933f25..59e5ab858664a 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/tests/ui/simd/shuffle-not-out-of-bounds.stderr @@ -1,71 +1,71 @@ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 8) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 16) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 32) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 64) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 128) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:84:23 + --> $DIR/shuffle-not-out-of-bounds.rs:79:23 | LL | let _: u8x2 = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 461243d489283..838e31f8e4154 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -8,7 +8,6 @@ extern "platform-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; - fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; } #[derive(Copy, Clone)] @@ -16,7 +15,7 @@ extern "platform-intrinsic" { struct Simd([T; N]); pub unsafe fn __shuffle_vector16(x: T, y: T) -> U { - simd_shuffle16(x, y, IDX) + simd_shuffle(x, y, IDX) } fn main() { From 5992e9b2fe64600158448f65890324f9ecfe63d5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 3 Aug 2023 14:07:37 +0200 Subject: [PATCH 07/10] builtin impl confirmation wuhu --- .../src/traits/select/confirmation.rs | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index bf09681c66d1a..cf9d2bda17ef8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -987,9 +987,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let target = self.infcx.shallow_resolve(target); debug!(?source, ?target, "confirm_builtin_unsize_candidate"); - let mut nested = vec![]; - let src; - match (source.kind(), target.kind()) { + Ok(match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping). (&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b)) if dyn_a == dyn_b => @@ -1016,16 +1014,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. - let InferOk { obligations, .. } = self + let InferOk { mut obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) .sup(DefineOpaqueTypes::No, target, source_trait) .map_err(|_| Unimplemented)?; - nested.extend(obligations); // Register one obligation for 'a: 'b. let outlives = ty::OutlivesPredicate(r_a, r_b); - nested.push(Obligation::with_depth( + obligations.push(Obligation::with_depth( tcx, obligation.cause.clone(), obligation.recursion_depth + 1, @@ -1033,7 +1030,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.rebind(outlives), )); - src = BuiltinImplSource::Misc; + ImplSource::Builtin(BuiltinImplSource::Misc, obligations) } // `T` -> `Trait` @@ -1059,11 +1056,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // words, if the object type is `Foo + Send`, this would create an obligation for // the `Send` check.) // - Projection predicates - nested.extend( - data.iter().map(|predicate| { - predicate_to_obligation(predicate.with_self_ty(tcx, source)) - }), - ); + let mut nested: Vec<_> = data + .iter() + .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source))) + .collect(); // We can only make objects from sized types. let tr = ty::TraitRef::from_lang_item( @@ -1081,7 +1077,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx), )); - src = BuiltinImplSource::Misc; + ImplSource::Builtin(BuiltinImplSource::Misc, nested) } // `[T; n]` -> `[T]` @@ -1091,9 +1087,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, b, a) .map_err(|_| Unimplemented)?; - nested.extend(obligations); - src = BuiltinImplSource::Misc; + ImplSource::Builtin(BuiltinImplSource::Misc, obligations) } // `Struct` -> `Struct` @@ -1106,6 +1101,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tail_field = def.non_enum_variant().tail(); let tail_field_ty = tcx.type_of(tail_field.did); + let mut nested = vec![]; + // Extract `TailField` and `TailField` from `Struct` and `Struct`, // normalizing in the process, since `type_of` returns something directly from // astconv (which means it's un-normalized). @@ -1151,7 +1148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); nested.push(tail_unsize_obligation); - src = BuiltinImplSource::Misc; + ImplSource::Builtin(BuiltinImplSource::Misc, nested) } // `(.., T)` -> `(.., U)` @@ -1166,27 +1163,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // last element is equal to the target. let new_tuple = Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last))); - let InferOk { obligations, .. } = self + let InferOk { mut obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, target, new_tuple) .map_err(|_| Unimplemented)?; - nested.extend(obligations); // Add a nested `T: Unsize` predicate. let last_unsize_obligation = obligation.with( tcx, ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]), ); - nested.push(last_unsize_obligation); + obligations.push(last_unsize_obligation); - src = BuiltinImplSource::TupleUnsizing; + ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations) } _ => bug!("source: {source}, target: {target}"), - }; - - Ok(ImplSource::Builtin(src, nested)) + }) } fn confirm_const_destruct_candidate( From f15832f44433685faab7364b0b325baa33188d39 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 3 Aug 2023 20:43:28 +0200 Subject: [PATCH 08/10] compiletest: Handle non-utf8 paths (fix FIXME) --- src/tools/compiletest/src/runtest.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 45582ddcbafc6..640efa78796e3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1933,7 +1933,8 @@ impl<'test> TestCx<'test> { let mut test_client = Command::new(self.config.remote_test_client.as_ref().unwrap()); test_client - .args(&["run", &support_libs.len().to_string(), &prog]) + .args(&["run", &support_libs.len().to_string()]) + .arg(&prog) .args(support_libs) .args(args); @@ -2516,7 +2517,7 @@ impl<'test> TestCx<'test> { // If this is emscripten, then run tests under nodejs if self.config.target.contains("emscripten") { if let Some(ref p) = self.config.nodejs { - args.push(p.clone()); + args.push(p.into()); } else { self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)"); } @@ -2524,7 +2525,7 @@ impl<'test> TestCx<'test> { // shim } else if self.config.target.contains("wasm32") { if let Some(ref p) = self.config.nodejs { - args.push(p.clone()); + args.push(p.into()); } else { self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)"); } @@ -2536,13 +2537,12 @@ impl<'test> TestCx<'test> { .unwrap() // chop off `ui` .parent() .unwrap(); // chop off `tests` - args.push(src.join("src/etc/wasm32-shim.js").display().to_string()); + args.push(src.join("src/etc/wasm32-shim.js").into_os_string()); } let exe_file = self.make_exe_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - args.push(exe_file.to_str().unwrap().to_owned()); + args.push(exe_file.into_os_string()); // Add the arguments in the run_flags directive args.extend(self.split_maybe_args(&self.props.run_flags)); @@ -2551,12 +2551,16 @@ impl<'test> TestCx<'test> { ProcArgs { prog, args } } - fn split_maybe_args(&self, argstr: &Option) -> Vec { + fn split_maybe_args(&self, argstr: &Option) -> Vec { match *argstr { Some(ref s) => s .split(' ') .filter_map(|s| { - if s.chars().all(|c| c.is_whitespace()) { None } else { Some(s.to_owned()) } + if s.chars().all(|c| c.is_whitespace()) { + None + } else { + Some(OsString::from(s)) + } }) .collect(), None => Vec::new(), @@ -4363,8 +4367,8 @@ impl<'test> TestCx<'test> { } struct ProcArgs { - prog: String, - args: Vec, + prog: OsString, + args: Vec, } pub struct ProcRes { From 40729bcb6914c8d239c70ad9ac4c532a0d12e495 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 3 Aug 2023 12:48:55 -0700 Subject: [PATCH 09/10] Enable tests on rustc_codegen_ssa --- compiler/rustc_codegen_ssa/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 6582fd62387ca..8f383f68bcd3e 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -3,9 +3,6 @@ name = "rustc_codegen_ssa" version = "0.0.0" edition = "2021" -[lib] -test = false - [dependencies] ar_archive_writer = "0.1.3" bitflags = "1.2.1" From 2232fe8da3dcd4796e6db060ba61ba9c70a2a3f5 Mon Sep 17 00:00:00 2001 From: xstaticxgpx Date: Wed, 2 Aug 2023 09:58:30 -0400 Subject: [PATCH 10/10] unix/kernel_copy.rs: copy_file_range_candidate allows empty output files This is for https://github.com/rust-lang/rust/issues/114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Further, `NoneObtained` is not relevant in this context, so remove it. Simply, determine what is input or output given the passed enum Unit. --- library/std/src/sys/unix/kernel_copy.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 7d49bbdcbe063..4d17a1b000229 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -89,6 +89,12 @@ enum FdMeta { NoneObtained, } +#[derive(PartialEq)] +enum FdHandle { + Input, + Output, +} + impl FdMeta { fn maybe_fifo(&self) -> bool { match self { @@ -114,12 +120,14 @@ impl FdMeta { } } - fn copy_file_range_candidate(&self) -> bool { + fn copy_file_range_candidate(&self, f: FdHandle) -> bool { match self { // copy_file_range will fail on empty procfs files. `read` can determine whether EOF has been reached // without extra cost and skip the write, thus there is no benefit in attempting copy_file_range - FdMeta::Metadata(meta) if meta.is_file() && meta.len() > 0 => true, - FdMeta::NoneObtained => true, + FdMeta::Metadata(meta) if f == FdHandle::Input && meta.is_file() && meta.len() > 0 => { + true + } + FdMeta::Metadata(meta) if f == FdHandle::Output && meta.is_file() => true, _ => false, } } @@ -197,7 +205,9 @@ impl SpecCopy for Copier<'_, '_, R, W> { written += flush()?; let max_write = reader.min_limit(); - if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() { + if input_meta.copy_file_range_candidate(FdHandle::Input) + && output_meta.copy_file_range_candidate(FdHandle::Output) + { let result = copy_regular_files(readfd, writefd, max_write); result.update_take(reader);