From 22e1778ec0e7fc77ae465bd0f69ead91447be742 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 May 2021 14:04:34 +0200 Subject: [PATCH 1/5] rustc_args_required_const is no longer a promotion site --- .../rustc_mir/src/transform/promote_consts.rs | 189 +++--------------- src/test/ui/consts/const_arg_local.rs | 11 - src/test/ui/consts/const_arg_local.stderr | 8 - src/test/ui/consts/const_arg_promotable.rs | 10 - .../ui/consts/const_arg_promotable.stderr | 8 - src/test/ui/consts/const_arg_promotable2.rs | 18 -- .../ui/consts/const_arg_promotable2.stderr | 8 - src/test/ui/consts/const_arg_wrapper.rs | 10 - src/test/ui/consts/const_arg_wrapper.stderr | 8 - .../ui/consts/rustc-args-required-const.rs | 27 --- .../consts/rustc-args-required-const.stderr | 14 -- 11 files changed, 28 insertions(+), 283 deletions(-) delete mode 100644 src/test/ui/consts/const_arg_local.rs delete mode 100644 src/test/ui/consts/const_arg_local.stderr delete mode 100644 src/test/ui/consts/const_arg_promotable.rs delete mode 100644 src/test/ui/consts/const_arg_promotable.stderr delete mode 100644 src/test/ui/consts/const_arg_promotable2.rs delete mode 100644 src/test/ui/consts/const_arg_promotable2.stderr delete mode 100644 src/test/ui/consts/const_arg_wrapper.rs delete mode 100644 src/test/ui/consts/const_arg_wrapper.stderr delete mode 100644 src/test/ui/consts/rustc-args-required-const.rs delete mode 100644 src/test/ui/consts/rustc-args-required-const.stderr diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 1bbaf833c4fd9..f786f327ba2f5 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -12,20 +12,16 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. -use rustc_ast::LitKind; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_middle::mir::traversal::ReversePostorder; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable}; -use rustc_span::symbol::sym; use rustc_span::Span; use rustc_index::vec::{Idx, IndexVec}; -use rustc_target::spec::abi::Abi; use std::cell::Cell; use std::{cmp, iter, mem}; @@ -101,47 +97,16 @@ impl TempState { pub enum Candidate { /// Borrow of a constant temporary, candidate for lifetime extension. Ref(Location), - - /// Currently applied to function calls where the callee has the unstable - /// `#[rustc_args_required_const]` attribute as well as the SIMD shuffle - /// intrinsic. The intrinsic requires the arguments are indeed constant and - /// the attribute currently provides the semantic requirement that arguments - /// must be constant. - Argument { bb: BasicBlock, index: usize }, } impl Candidate { - /// Returns `true` if we should use the "explicit" rules for promotability for this `Candidate`. - fn forces_explicit_promotion(&self) -> bool { - match self { - Candidate::Ref(_) => false, - Candidate::Argument { .. } => true, - } - } - fn source_info(&self, body: &Body<'_>) -> SourceInfo { match self { Candidate::Ref(location) => *body.source_info(*location), - Candidate::Argument { bb, .. } => *body.source_info(body.terminator_loc(*bb)), } } } -fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { - let attrs = tcx.get_attrs(def_id); - let attr = attrs.iter().find(|a| tcx.sess.check_name(a, sym::rustc_args_required_const))?; - let mut ret = vec![]; - for meta in attr.meta_item_list()? { - match meta.literal()?.kind { - LitKind::Int(a, _) => { - ret.push(a as usize); - } - _ => bug!("invalid arg index"), - } - } - Some(ret) -} - struct Collector<'a, 'tcx> { ccx: &'a ConstCx<'a, 'tcx>, temps: IndexVec, @@ -208,31 +173,6 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { _ => {} } } - - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - self.super_terminator(terminator, location); - - if let TerminatorKind::Call { ref func, .. } = terminator.kind { - if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() { - let fn_sig = self.ccx.tcx.fn_sig(def_id); - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { - let name = self.ccx.tcx.item_name(def_id); - // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. - if name.as_str().starts_with("simd_shuffle") { - self.candidates.push(Candidate::Argument { bb: location.block, index: 2 }); - - return; // Don't double count `simd_shuffle` candidates - } - } - - if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) { - for index in constant_args { - self.candidates.push(Candidate::Argument { bb: location.block, index }); - } - } - } - } - } } pub fn collect_temps_and_candidates( @@ -256,14 +196,6 @@ pub fn collect_temps_and_candidates( struct Validator<'a, 'tcx> { ccx: &'a ConstCx<'a, 'tcx>, temps: &'a IndexVec, - - /// Explicit promotion happens e.g. for constant arguments declared via - /// `rustc_args_required_const`. - /// Implicit promotion has almost the same rules, except that disallows `const fn` - /// except for those marked `#[rustc_promotable]`. This is to avoid changing - /// a legitimate run-time operation into a failing compile-time operation - /// e.g. due to addresses being compared inside the function. - explicit: bool, } impl std::ops::Deref for Validator<'a, 'tcx> { @@ -280,8 +212,6 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> { match candidate { Candidate::Ref(loc) => { - assert!(!self.explicit); - let statement = &self.body[loc.block].statements[loc.statement_index]; match &statement.kind { StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => { @@ -310,15 +240,6 @@ impl<'tcx> Validator<'_, 'tcx> { _ => bug!(), } } - Candidate::Argument { bb, index } => { - assert!(self.explicit); - - let terminator = self.body[bb].terminator(); - match &terminator.kind { - TerminatorKind::Call { args, .. } => self.validate_operand(&args[index]), - _ => bug!(), - } - } } } @@ -448,12 +369,10 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {} ProjectionElem::Index(local) => { - if !self.explicit { - let mut promotable = false; - // Only accept if we can predict the index and are indexing an array. - let val = if let TempState::Defined { location: loc, .. } = - self.temps[local] - { + let mut promotable = false; + // Only accept if we can predict the index and are indexing an array. + let val = + if let TempState::Defined { location: loc, .. } = self.temps[local] { let block = &self.body[loc.block]; if loc.statement_index < block.statements.len() { let statement = &block.statements[loc.statement_index]; @@ -470,28 +389,27 @@ impl<'tcx> Validator<'_, 'tcx> { } else { None }; - if let Some(idx) = val { - // Determine the type of the thing we are indexing. - let ty = place_base.ty(self.body, self.tcx).ty; - match ty.kind() { - ty::Array(_, len) => { - // It's an array; determine its length. - if let Some(len) = - len.try_eval_usize(self.tcx, self.param_env) - { - // If the index is in-bounds, go ahead. - if idx < len { - promotable = true; - } + if let Some(idx) = val { + // Determine the type of the thing we are indexing. + let ty = place_base.ty(self.body, self.tcx).ty; + match ty.kind() { + ty::Array(_, len) => { + // It's an array; determine its length. + if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) + { + // If the index is in-bounds, go ahead. + if idx < len { + promotable = true; } } - _ => {} } + _ => {} } - if !promotable { - return Err(Unpromotable); - } } + if !promotable { + return Err(Unpromotable); + } + self.validate_local(local)?; } @@ -636,7 +554,7 @@ impl<'tcx> Validator<'_, 'tcx> { match op { BinOp::Div | BinOp::Rem => { - if !self.explicit && lhs_ty.is_integral() { + if lhs_ty.is_integral() { // Integer division: the RHS must be a non-zero const. let const_val = match rhs { Operand::Constant(c) => { @@ -721,13 +639,12 @@ impl<'tcx> Validator<'_, 'tcx> { ) -> Result<(), Unpromotable> { let fn_ty = callee.ty(self.body, self.tcx); - // When doing explicit promotion and inside const/static items, we promote all (eligible) function calls. + // Inside const/static items, we promote all (eligible) function calls. // Everywhere else, we require `#[rustc_promotable]` on the callee. - let promote_all_const_fn = self.explicit - || matches!( - self.const_kind, - Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) - ); + let promote_all_const_fn = matches!( + self.const_kind, + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) + ); if !promote_all_const_fn { if let ty::FnDef(def_id, _) = *fn_ty.kind() { // Never promote runtime `const fn` calls of @@ -765,41 +682,12 @@ pub fn validate_candidates( temps: &IndexVec, candidates: &[Candidate], ) -> Vec { - let mut validator = Validator { ccx, temps, explicit: false }; + let validator = Validator { ccx, temps }; candidates .iter() .copied() - .filter(|&candidate| { - validator.explicit = candidate.forces_explicit_promotion(); - - // FIXME(eddyb) also emit the errors for shuffle indices - // and `#[rustc_args_required_const]` arguments here. - - let is_promotable = validator.validate_candidate(candidate).is_ok(); - - // If we use explicit validation, we carry the risk of turning a legitimate run-time - // operation into a failing compile-time operation. Make sure that does not happen - // by asserting that there is no possible run-time behavior here in case promotion - // fails. - if validator.explicit && !is_promotable { - ccx.tcx.sess.delay_span_bug( - ccx.body.span, - "Explicit promotion requested, but failed to promote", - ); - } - - match candidate { - Candidate::Argument { bb, index } if !is_promotable => { - let span = ccx.body[bb].terminator().source_info.span; - let msg = format!("argument {} is required to be a constant", index + 1); - ccx.tcx.sess.span_err(span, &msg); - } - _ => (), - } - - is_promotable - }) + .filter(|&candidate| validator.validate_candidate(candidate).is_ok()) .collect() } @@ -1039,26 +927,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { _ => bug!(), } } - Candidate::Argument { bb, index } => { - let terminator = blocks[bb].terminator_mut(); - match terminator.kind { - TerminatorKind::Call { ref mut args, .. } => { - let ty = args[index].ty(local_decls, self.tcx); - let span = terminator.source_info.span; - - Rvalue::Use(mem::replace(&mut args[index], promoted_operand(ty, span))) - } - // We expected a `TerminatorKind::Call` for which we'd like to promote an - // argument. `qualify_consts` saw a `TerminatorKind::Call` here, but - // we are seeing a `Goto`. That means that the `promote_temps` method - // already promoted this call away entirely. This case occurs when calling - // a function requiring a constant argument and as that constant value - // providing a value whose computation contains another call to a function - // requiring a constant argument. - TerminatorKind::Goto { .. } => return None, - _ => bug!(), - } - } } }; @@ -1113,7 +981,6 @@ pub fn promote_candidates<'tcx>( } } } - Candidate::Argument { .. } => {} } // Declare return place local so that `mir::Body::new` doesn't complain. diff --git a/src/test/ui/consts/const_arg_local.rs b/src/test/ui/consts/const_arg_local.rs deleted file mode 100644 index 9add1f8d5a359..0000000000000 --- a/src/test/ui/consts/const_arg_local.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -fn foo(_imm8: i32) {} - -fn bar() { - let imm8 = 3; - foo(imm8) //~ ERROR argument 1 is required to be a constant -} - -fn main() {} diff --git a/src/test/ui/consts/const_arg_local.stderr b/src/test/ui/consts/const_arg_local.stderr deleted file mode 100644 index bad85471a6b37..0000000000000 --- a/src/test/ui/consts/const_arg_local.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: argument 1 is required to be a constant - --> $DIR/const_arg_local.rs:8:5 - | -LL | foo(imm8) - | ^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const_arg_promotable.rs b/src/test/ui/consts/const_arg_promotable.rs deleted file mode 100644 index cea3817550eb2..0000000000000 --- a/src/test/ui/consts/const_arg_promotable.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -fn foo(_imm8: i32) {} - -fn bar() { - foo(*&mut 42) //~ ERROR argument 1 is required to be a constant -} - -fn main() {} diff --git a/src/test/ui/consts/const_arg_promotable.stderr b/src/test/ui/consts/const_arg_promotable.stderr deleted file mode 100644 index b24b245b3ce0c..0000000000000 --- a/src/test/ui/consts/const_arg_promotable.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: argument 1 is required to be a constant - --> $DIR/const_arg_promotable.rs:7:5 - | -LL | foo(*&mut 42) - | ^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const_arg_promotable2.rs b/src/test/ui/consts/const_arg_promotable2.rs deleted file mode 100644 index 3399e51ed4edb..0000000000000 --- a/src/test/ui/consts/const_arg_promotable2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// This test is a regression test for a bug where we only checked function calls in no-const -// functions for `rustc_args_required_const` arguments. This meant that even though `bar` needs its -// argument to be const, inside a const fn (callable at runtime), the value for it may come from a -// non-constant (namely an argument to the const fn). - -#![feature(rustc_attrs)] -const fn foo(a: i32) { - bar(a); //~ ERROR argument 1 is required to be a constant -} - -#[rustc_args_required_const(0)] -const fn bar(_: i32) {} - -fn main() { - // this function call will pass a runtime-value (number of program arguments) to `foo`, which - // will in turn forward it to `bar`, which expects a compile-time argument - foo(std::env::args().count() as i32); -} diff --git a/src/test/ui/consts/const_arg_promotable2.stderr b/src/test/ui/consts/const_arg_promotable2.stderr deleted file mode 100644 index 149d1ce89408d..0000000000000 --- a/src/test/ui/consts/const_arg_promotable2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: argument 1 is required to be a constant - --> $DIR/const_arg_promotable2.rs:8:5 - | -LL | bar(a); - | ^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const_arg_wrapper.rs b/src/test/ui/consts/const_arg_wrapper.rs deleted file mode 100644 index 3dd3a2ffaf3cb..0000000000000 --- a/src/test/ui/consts/const_arg_wrapper.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -fn foo(_imm8: i32) {} - -fn bar(imm8: i32) { - foo(imm8) //~ ERROR argument 1 is required to be a constant -} - -fn main() {} diff --git a/src/test/ui/consts/const_arg_wrapper.stderr b/src/test/ui/consts/const_arg_wrapper.stderr deleted file mode 100644 index 9cd95a2020fcd..0000000000000 --- a/src/test/ui/consts/const_arg_wrapper.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: argument 1 is required to be a constant - --> $DIR/const_arg_wrapper.rs:7:5 - | -LL | foo(imm8) - | ^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/consts/rustc-args-required-const.rs b/src/test/ui/consts/rustc-args-required-const.rs deleted file mode 100644 index 0723b66879c38..0000000000000 --- a/src/test/ui/consts/rustc-args-required-const.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -fn foo(_a: i32) { -} - -#[rustc_args_required_const(1)] -fn bar(_a: i32, _b: i32) { -} - -const A: i32 = 3; - -const fn baz() -> i32 { - 3 -} - -fn main() { - foo(2); - foo(2 + 3); - const BAZ: i32 = baz(); - foo(BAZ); - let a = 4; - foo(A); - foo(a); //~ ERROR: argument 1 is required to be a constant - bar(a, 3); - bar(a, a); //~ ERROR: argument 2 is required to be a constant -} diff --git a/src/test/ui/consts/rustc-args-required-const.stderr b/src/test/ui/consts/rustc-args-required-const.stderr deleted file mode 100644 index 8b302692053a2..0000000000000 --- a/src/test/ui/consts/rustc-args-required-const.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: argument 1 is required to be a constant - --> $DIR/rustc-args-required-const.rs:24:5 - | -LL | foo(a); - | ^^^^^^ - -error: argument 2 is required to be a constant - --> $DIR/rustc-args-required-const.rs:26:5 - | -LL | bar(a, a); - | ^^^^^^^^^ - -error: aborting due to 2 previous errors - From 44a8e8d7455cd8f8ec3b3f2d5d4ef80693608f63 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 May 2021 14:21:33 +0200 Subject: [PATCH 2/5] entirely remove rustc_args_required_const attribute --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 - compiler/rustc_feature/src/builtin_attrs.rs | 1 - compiler/rustc_mir/src/interpret/cast.rs | 8 -- compiler/rustc_mir/src/interpret/intern.rs | 1 - .../rustc_mir/src/transform/promote_consts.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 80 +------------------ compiler/rustc_span/src/symbol.rs | 1 - .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 - .../rustc_typeck/src/check/fn_ctxt/checks.rs | 30 +------ .../ui/consts/const-eval/double_promotion.rs | 17 ---- ...lid-rustc_args_required_const-arguments.rs | 32 -------- ...rustc_args_required_const-arguments.stderr | 60 -------------- src/test/ui/rustc-args-required-const2.rs | 10 --- src/test/ui/rustc-args-required-const2.stderr | 8 -- 14 files changed, 4 insertions(+), 254 deletions(-) delete mode 100644 src/test/ui/consts/const-eval/double_promotion.rs delete mode 100644 src/test/ui/invalid/invalid-rustc_args_required_const-arguments.rs delete mode 100644 src/test/ui/invalid/invalid-rustc_args_required_const-arguments.stderr delete mode 100644 src/test/ui/rustc-args-required-const2.rs delete mode 100644 src/test/ui/rustc-args-required-const2.stderr diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 9917c23f12150..530de3de9e870 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -14,7 +14,6 @@ use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; -use rustc_span::symbol::sym; use rustc_target::abi::{Abi, Int, LayoutOf, Variants}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -187,9 +186,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => { match *operand.layout.ty.kind() { ty::FnDef(def_id, substs) => { - if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) { - bug!("reifying a fn ptr that requires const arguments"); - } let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), ty::ParamEnv::reveal_all(), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a8719be84c2a4..24b53bcf82af8 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -469,7 +469,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), // ========================================================================== diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs index 2d9e6df0ab860..848b44d13aadf 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_mir/src/interpret/cast.rs @@ -7,7 +7,6 @@ use rustc_middle::mir::CastKind; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut}; -use rustc_span::symbol::sym; use rustc_target::abi::{Integer, LayoutOf, Variants}; use super::{ @@ -49,13 +48,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // All reifications must be monomorphic, bail out otherwise. ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; - if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { - span_bug!( - self.cur_span(), - "reifying a fn ptr that requires const arguments" - ); - } - let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, self.param_env, diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs index 95464da145cfd..23c0fe97c5f69 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_mir/src/interpret/intern.rs @@ -305,7 +305,6 @@ where let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), // `Constant` includes array lengths. - // `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments. InternKind::Constant | InternKind::Promoted => InternMode::Const, }; diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index f786f327ba2f5..f6b1323e10797 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -32,8 +32,8 @@ use crate::transform::MirPass; /// A `MirPass` for promotion. /// -/// Promotion is the extraction of promotable temps into separate MIR bodies. This pass also emits -/// errors when promotion of `#[rustc_args_required_const]` arguments fails. +/// Promotion is the extraction of promotable temps into separate MIR bodies so they can have +/// `'static` lifetime. /// /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each /// newly created `Constant`. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cb06cbfcc7be0..bf574bbfbb5ae 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -13,9 +13,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{ - self, FnSig, ForeignItem, ForeignItemKind, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, -}; +use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID}; use rustc_hir::{MethodKind, Target}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES, @@ -81,9 +79,6 @@ impl CheckAttrVisitor<'tcx> { sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline), sym::no_link => self.check_no_link(hir_id, &attr, span, target), sym::export_name => self.check_export_name(hir_id, &attr, span, target), - sym::rustc_args_required_const => { - self.check_rustc_args_required_const(&attr, span, target, item) - } sym::rustc_layout_scalar_valid_range_start | sym::rustc_layout_scalar_valid_range_end => { self.check_rustc_layout_scalar_valid_range(&attr, span, target) @@ -948,79 +943,6 @@ impl CheckAttrVisitor<'tcx> { } } - /// Checks if `#[rustc_args_required_const]` is applied to a function and has a valid argument. - fn check_rustc_args_required_const( - &self, - attr: &Attribute, - span: &Span, - target: Target, - item: Option>, - ) -> bool { - let is_function = matches!(target, Target::Fn | Target::Method(..) | Target::ForeignFn); - if !is_function { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a function") - .span_label(*span, "not a function") - .emit(); - return false; - } - - let list = match attr.meta_item_list() { - // The attribute form is validated on AST. - None => return false, - Some(it) => it, - }; - - let mut invalid_args = vec![]; - for meta in list { - if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { - if let Some(ItemLike::Item(Item { - kind: ItemKind::Fn(FnSig { decl, .. }, ..), - .. - })) - | Some(ItemLike::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(decl, ..), - .. - })) = item - { - let arg_count = decl.inputs.len() as u128; - if *val >= arg_count { - let span = meta.span(); - self.tcx - .sess - .struct_span_err(span, "index exceeds number of arguments") - .span_label( - span, - format!( - "there {} only {} argument{}", - if arg_count != 1 { "are" } else { "is" }, - arg_count, - pluralize!(arg_count) - ), - ) - .emit(); - return false; - } - } else { - bug!("should be a function item"); - } - } else { - invalid_args.push(meta.span()); - } - } - - if !invalid_args.is_empty() { - self.tcx - .sess - .struct_span_err(invalid_args, "arguments should be non-negative integers") - .emit(); - false - } else { - true - } - } - fn check_rustc_layout_scalar_valid_range( &self, attr: &Attribute, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4c80b84e3d275..a65c66f8ee7a8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -992,7 +992,6 @@ symbols! { rustc_allocator, rustc_allocator_nounwind, rustc_allow_const_fn_unstable, - rustc_args_required_const, rustc_attrs, rustc_builtin_macro, rustc_capture_analysis, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 4d6caf07236e2..4de8216884a68 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1537,8 +1537,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - self.check_rustc_args_require_const(def_id, hir_id, span); - debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_substituted); self.write_substs(hir_id, substs); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 3417bc0197253..49aea19c8d099 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty}; use rustc_session::Session; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{self, MultiSpan, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; @@ -720,34 +720,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - pub(in super::super) fn check_rustc_args_require_const( - &self, - def_id: DefId, - hir_id: hir::HirId, - span: Span, - ) { - // We're only interested in functions tagged with - // #[rustc_args_required_const], so ignore anything that's not. - if !self.tcx.has_attr(def_id, sym::rustc_args_required_const) { - return; - } - - // If our calling expression is indeed the function itself, we're good! - // If not, generate an error that this can only be called directly. - if let Node::Expr(expr) = self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id)) { - if let ExprKind::Call(ref callee, ..) = expr.kind { - if callee.hir_id == hir_id { - return; - } - } - } - - self.tcx.sess.span_err( - span, - "this function can only be invoked directly, not through a function pointer", - ); - } - /// A common error is to add an extra semicolon: /// /// ``` diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs deleted file mode 100644 index 9ee2777a647e0..0000000000000 --- a/src/test/ui/consts/const-eval/double_promotion.rs +++ /dev/null @@ -1,17 +0,0 @@ -// check-pass - -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -pub const fn a(value: u8) -> u8 { - value -} - -#[rustc_args_required_const(0)] -pub fn b(_: u8) { - unimplemented!() -} - -fn main() { - let _ = b(a(0)); -} diff --git a/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.rs b/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.rs deleted file mode 100644 index 99508baeb0070..0000000000000 --- a/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] //~ ERROR index exceeds number of arguments -fn foo1() {} - -#[rustc_args_required_const(1)] //~ ERROR index exceeds number of arguments -fn foo2(_: u8) {} - -#[rustc_args_required_const(a)] //~ ERROR arguments should be non-negative integers -fn foo4() {} - -#[rustc_args_required_const(1, a, 2, b)] //~ ERROR arguments should be non-negative integers -fn foo5(_: u8, _: u8, _: u8) {} - -#[rustc_args_required_const(0)] //~ ERROR attribute should be applied to a function -struct S; - -#[rustc_args_required_const(0usize)] //~ ERROR suffixed literals are not allowed in attributes -fn foo6(_: u8) {} - -extern { - #[rustc_args_required_const(1)] //~ ERROR index exceeds number of arguments - fn foo7(_: u8); -} - -#[rustc_args_required_const] //~ ERROR malformed `rustc_args_required_const` attribute -fn bar1() {} - -#[rustc_args_required_const = 1] //~ ERROR malformed `rustc_args_required_const` attribute -fn bar2() {} - -fn main() {} diff --git a/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.stderr b/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.stderr deleted file mode 100644 index 932344f0a33c5..0000000000000 --- a/src/test/ui/invalid/invalid-rustc_args_required_const-arguments.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: suffixed literals are not allowed in attributes - --> $DIR/invalid-rustc_args_required_const-arguments.rs:18:29 - | -LL | #[rustc_args_required_const(0usize)] - | ^^^^^^ - | - = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - -error: malformed `rustc_args_required_const` attribute input - --> $DIR/invalid-rustc_args_required_const-arguments.rs:26:1 - | -LL | #[rustc_args_required_const] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_args_required_const(N)]` - -error: malformed `rustc_args_required_const` attribute input - --> $DIR/invalid-rustc_args_required_const-arguments.rs:29:1 - | -LL | #[rustc_args_required_const = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_args_required_const(N)]` - -error: index exceeds number of arguments - --> $DIR/invalid-rustc_args_required_const-arguments.rs:3:29 - | -LL | #[rustc_args_required_const(0)] - | ^ there are only 0 arguments - -error: index exceeds number of arguments - --> $DIR/invalid-rustc_args_required_const-arguments.rs:6:29 - | -LL | #[rustc_args_required_const(1)] - | ^ there is only 1 argument - -error: arguments should be non-negative integers - --> $DIR/invalid-rustc_args_required_const-arguments.rs:9:29 - | -LL | #[rustc_args_required_const(a)] - | ^ - -error: arguments should be non-negative integers - --> $DIR/invalid-rustc_args_required_const-arguments.rs:12:32 - | -LL | #[rustc_args_required_const(1, a, 2, b)] - | ^ ^ - -error: attribute should be applied to a function - --> $DIR/invalid-rustc_args_required_const-arguments.rs:15:1 - | -LL | #[rustc_args_required_const(0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | struct S; - | --------- not a function - -error: index exceeds number of arguments - --> $DIR/invalid-rustc_args_required_const-arguments.rs:22:33 - | -LL | #[rustc_args_required_const(1)] - | ^ there is only 1 argument - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/rustc-args-required-const2.rs b/src/test/ui/rustc-args-required-const2.rs deleted file mode 100644 index 06457bc5ca65a..0000000000000 --- a/src/test/ui/rustc-args-required-const2.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_args_required_const(0)] -fn foo(_a: i32) { -} - -fn main() { - let a = foo; //~ ERROR: this function can only be invoked directly - a(2); -} diff --git a/src/test/ui/rustc-args-required-const2.stderr b/src/test/ui/rustc-args-required-const2.stderr deleted file mode 100644 index a8906ad3bc551..0000000000000 --- a/src/test/ui/rustc-args-required-const2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: this function can only be invoked directly, not through a function pointer - --> $DIR/rustc-args-required-const2.rs:8:13 - | -LL | let a = foo; - | ^^^ - -error: aborting due to previous error - From 2e8e91ce25a95f11b09ef59386174edca338cc3a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 May 2021 10:17:25 +0200 Subject: [PATCH 3/5] add check that simd_shuffle arguments are constants --- .../rustc_mir/src/transform/lower_intrinsics.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir/src/transform/lower_intrinsics.rs index e6ee474285ec1..6d7e4cdb1c6ef 100644 --- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs +++ b/compiler/rustc_mir/src/transform/lower_intrinsics.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; pub struct LowerIntrinsics; @@ -119,6 +120,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } } + _ if intrinsic_name.as_str().starts_with("simd_shuffle") => { + validate_simd_shuffle(tcx, args, terminator.source_info.span); + } _ => {} } } @@ -132,9 +136,19 @@ fn resolve_rust_intrinsic( ) -> Option<(Symbol, SubstsRef<'tcx>)> { if let ty::FnDef(def_id, substs) = *func_ty.kind() { let fn_sig = func_ty.fn_sig(tcx); - if fn_sig.abi() == Abi::RustIntrinsic { + if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { return Some((tcx.item_name(def_id), substs)); } } None } + +fn validate_simd_shuffle(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { + match &args[2] { + Operand::Constant(_) => {} // all good + _ => { + let msg = format!("last argument of `simd_shuffle` is required to be a `const` item"); + tcx.sess.span_err(span, &msg); + } + } +} From 2a245e0226c387c39d35723f0091cbaa7b49386e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 May 2021 16:22:27 +0200 Subject: [PATCH 4/5] update stdarch --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index 6c4f4e1990b76..c14e98417feb4 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 6c4f4e1990b76be8a07bde1956d2e3452fd55ee4 +Subproject commit c14e98417feb406df66e821ccd81e1293b4baa6f From c61e8face090e2b8a0a8eca535e8b58feee25625 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 May 2021 17:08:45 +0200 Subject: [PATCH 5/5] fix test suite --- src/test/incremental/issue-61530.rs | 5 +- src/test/ui/issues/issue-38074.rs | 20 ------- .../simd-intrinsic-generic-elements.rs | 21 ++++---- .../simd-intrinsic-generic-elements.stderr | 54 +++++++++---------- .../simd-intrinsic-inlining-issue67557-ice.rs | 3 +- .../simd-intrinsic-inlining-issue67557.rs | 6 ++- .../simd/simd-intrinsic-generic-elements.rs | 20 +++---- 7 files changed, 59 insertions(+), 70 deletions(-) delete mode 100644 src/test/ui/issues/issue-38074.rs diff --git a/src/test/incremental/issue-61530.rs b/src/test/incremental/issue-61530.rs index 06b2957ac62c9..edb3d60ba3f89 100644 --- a/src/test/incremental/issue-61530.rs +++ b/src/test/incremental/issue-61530.rs @@ -11,7 +11,8 @@ extern "platform-intrinsic" { fn main() { unsafe { - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), [0, 0]); - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), [0, 0]); + 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); } } diff --git a/src/test/ui/issues/issue-38074.rs b/src/test/ui/issues/issue-38074.rs deleted file mode 100644 index 214d6752cef1d..0000000000000 --- a/src/test/ui/issues/issue-38074.rs +++ /dev/null @@ -1,20 +0,0 @@ -// run-pass -// ignore-emscripten FIXME(#45351) - -#![feature(platform_intrinsics, repr_simd)] - -extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; -} - -#[repr(simd)] -#[derive(Clone, Copy)] -#[allow(non_camel_case_types)] -struct u64x2(u64, u64); - -fn main() { - let a = u64x2(1, 2); - let r: u64x2 = unsafe { simd_shuffle2(a, a, [0-0, 0-0]) }; - assert_eq!(r.0, 1); - assert_eq!(r.1, 1); -} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs index 493cd7a477c7a..abde69163bd4e 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs @@ -50,25 +50,28 @@ fn main() { simd_extract::<_, f32>(x, 0); //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` - simd_shuffle2::(0, 0, [0; 2]); + const IDX2: [u32; 2] = [0; 2]; + simd_shuffle2::(0, 0, IDX2); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - simd_shuffle4::(0, 0, [0; 4]); + const IDX4: [u32; 4] = [0; 4]; + simd_shuffle4::(0, 0, IDX4); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - simd_shuffle8::(0, 0, [0; 8]); + const IDX8: [u32; 8] = [0; 8]; + simd_shuffle8::(0, 0, IDX8); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - simd_shuffle2::<_, f32x2>(x, x, [0; 2]); + simd_shuffle2::<_, f32x2>(x, x, IDX2); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - simd_shuffle4::<_, f32x4>(x, x, [0; 4]); + simd_shuffle4::<_, f32x4>(x, x, IDX4); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - simd_shuffle8::<_, f32x8>(x, x, [0; 8]); + simd_shuffle8::<_, f32x8>(x, x, IDX8); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - simd_shuffle2::<_, i32x8>(x, x, [0; 2]); + simd_shuffle2::<_, i32x8>(x, x, IDX2); //~^ ERROR expected return type of length 2, found `i32x8` with length 8 - simd_shuffle4::<_, i32x8>(x, x, [0; 4]); + simd_shuffle4::<_, i32x8>(x, x, IDX4); //~^ ERROR expected return type of length 4, found `i32x8` with length 8 - simd_shuffle8::<_, i32x2>(x, x, [0; 8]); + simd_shuffle8::<_, i32x2>(x, x, IDX8); //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr index 703e64d1ddcc8..4220411114efd 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr @@ -17,58 +17,58 @@ LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:53:9 + --> $DIR/simd-intrinsic-generic-elements.rs:54:9 | -LL | simd_shuffle2::(0, 0, [0; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle2::(0, 0, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:55:9 + --> $DIR/simd-intrinsic-generic-elements.rs:57:9 | -LL | simd_shuffle4::(0, 0, [0; 4]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle4::(0, 0, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:57:9 + --> $DIR/simd-intrinsic-generic-elements.rs:60:9 | -LL | simd_shuffle8::(0, 0, [0; 8]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle8::(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` - --> $DIR/simd-intrinsic-generic-elements.rs:60:9 + --> $DIR/simd-intrinsic-generic-elements.rs:63:9 | -LL | simd_shuffle2::<_, f32x2>(x, x, [0; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle2::<_, f32x2>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:62:9 + --> $DIR/simd-intrinsic-generic-elements.rs:65:9 | -LL | simd_shuffle4::<_, f32x4>(x, x, [0; 4]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle4::<_, f32x4>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:64:9 + --> $DIR/simd-intrinsic-generic-elements.rs:67:9 | -LL | simd_shuffle8::<_, f32x8>(x, x, [0; 8]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle8::<_, f32x8>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:67:9 + --> $DIR/simd-intrinsic-generic-elements.rs:70:9 | -LL | simd_shuffle2::<_, i32x8>(x, x, [0; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle2::<_, i32x8>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:69:9 + --> $DIR/simd-intrinsic-generic-elements.rs:72:9 | -LL | simd_shuffle4::<_, i32x8>(x, x, [0; 4]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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/simd-intrinsic-generic-elements.rs:71:9 + --> $DIR/simd-intrinsic-generic-elements.rs:74:9 | -LL | simd_shuffle8::<_, i32x2>(x, x, [0; 8]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle8::<_, i32x2>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs index 4be6818305010..7221b3ab769db 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs @@ -21,5 +21,6 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), [0, 3]) + const IDX: [u32; 2] = [0, 3]; + simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs index 67556829815b3..0d15427095a74 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs @@ -15,7 +15,8 @@ struct Simd2(u8, u8); fn main() { unsafe { - let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), [0, 1]); + const IDX: [u32; 2] = [0, 1]; + let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -36,5 +37,6 @@ fn assert_10_13(x: Simd2) { #[inline(always)] unsafe fn inline_me() -> Simd2 { - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), [0, 3]) + const IDX: [u32; 2] = [0, 3]; + simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/src/test/ui/simd/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/simd-intrinsic-generic-elements.rs index a85ec7c58235b..08544bce45db9 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-elements.rs @@ -2,6 +2,8 @@ // ignore-emscripten FIXME(#45351) hits an LLVM assert #![feature(repr_simd, platform_intrinsics)] +#![allow(incomplete_features)] +#![feature(inline_const)] #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] @@ -82,19 +84,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, [3, 0]), i32x2(121, 20)); - all_eq!(simd_shuffle4(x2, y2, [3, 0, 1, 2]), i32x4(121, 20, 21, 120)); - all_eq!(simd_shuffle8(x2, y2, [3, 0, 1, 2, 1, 2, 3, 0]), + 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] }), i32x8(121, 20, 21, 120, 21, 120, 121, 20)); - all_eq!(simd_shuffle2(x4, y4, [7, 2]), i32x2(143, 42)); - all_eq!(simd_shuffle4(x4, y4, [7, 2, 5, 0]), i32x4(143, 42, 141, 40)); - all_eq!(simd_shuffle8(x4, y4, [7, 2, 5, 0, 3, 6, 4, 1]), + 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] }), i32x8(143, 42, 141, 40, 43, 142, 140, 41)); - all_eq!(simd_shuffle2(x8, y8, [11, 5]), i32x2(183, 85)); - all_eq!(simd_shuffle4(x8, y8, [11, 5, 15, 0]), i32x4(183, 85, 187, 80)); - all_eq!(simd_shuffle8(x8, y8, [11, 5, 15, 0, 3, 8, 12, 1]), + 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] }), i32x8(183, 85, 187, 80, 83, 180, 184, 81)); }