From 7b2befc27b2e65e0ffdd9e8280951e7349317e39 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Tue, 8 Jun 2021 20:38:43 +0200 Subject: [PATCH 1/2] Check the number of generic lifetime and const parameters of intrinsics --- .../src/error_codes/E0094.md | 3 +- compiler/rustc_typeck/src/check/intrinsic.rs | 86 +++++++++++++------ compiler/rustc_typeck/src/errors.rs | 8 +- src/test/ui/simd-intrinsic/issue-85855.rs | 20 +++++ src/test/ui/simd-intrinsic/issue-85855.stderr | 27 ++++++ 5 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/simd-intrinsic/issue-85855.rs create mode 100644 src/test/ui/simd-intrinsic/issue-85855.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42baa65bf9faf..42cd2aa185315 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,4 +1,5 @@ -An invalid number of type parameters was given to an intrinsic function. +An invalid number of generic type, lifetime, or const parameters was +given to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 5741b6824b5d7..7a7ecb06132b9 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,11 +3,11 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfTypeArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToInstrinsic, }; use crate::require_same_types; -use rustc_errors::struct_span_err; +use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; @@ -21,36 +21,68 @@ fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, n_tps: usize, + n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - match it.kind { - hir::ForeignItemKind::Fn(..) => {} + let (gen_lts, gen_tys, gen_cns, span) = match &it.kind { + hir::ForeignItemKind::Fn(.., generics) => { + let mut gen_lts = 0; + let mut gen_tys = 0; + let mut gen_cns = 0; + + for param in generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { + gen_lts += 1; + } + hir::GenericParamKind::Type { .. } => { + gen_tys += 1; + } + hir::GenericParamKind::Const { .. } => { + gen_cns += 1; + } + } + } + + (gen_lts, gen_tys, gen_cns, generics.span) + } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") .span_label(it.span, "expected a function") .emit(); return; } - } - - let i_n_tps = tcx.generics_of(it.def_id).own_counts().types; - if i_n_tps != n_tps { - let span = match it.kind { - hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span, - _ => bug!(), - }; + }; - tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic { + if gen_lts != n_lts { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { + span, + found: gen_lts, + expected: n_lts, + expected_pluralize: pluralize!(n_lts), + descr: "lifetime", + }); + } else if gen_tys != n_tps { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { span, - found: i_n_tps, + found: gen_tys, expected: n_tps, + expected_pluralize: pluralize!(n_tps), + descr: "type", }); - return; + } else if gen_cns != 0 { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { + span, + found: gen_cns, + expected: 0, + expected_pluralize: pluralize!(0), + descr: "const", + }); + } else { + let fty = tcx.mk_fn_ptr(sig); + let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } - - let fty = tcx.mk_fn_ptr(sig); - let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); - require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } /// Returns `true` if the given intrinsic is unsafe to call or not. @@ -121,7 +153,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") { let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -143,7 +175,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, hir::Unsafety::Unsafe) + (n_tps, 0, inputs, output, hir::Unsafety::Unsafe) } else { let unsafety = intrinsic_operation_unsafety(intrinsic_name); let (n_tps, inputs, output) = match intrinsic_name { @@ -372,11 +404,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, unsafety) + ( + n_tps, + if matches!(intrinsic_name, sym::va_copy) { 1 } else { 0 }, + inputs, + output, + unsafety, + ) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -472,5 +510,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) Abi::PlatformIntrinsic, ); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, sig) } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 5068242692ae8..bc686a025a650 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfTypeArgumentsToInstrinsic { - #[message = "intrinsic has wrong number of type \ +pub struct WrongNumberOfGenericArgumentsToInstrinsic<'a> { + #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] - #[label = "expected {expected} type parameter"] + #[label = "expected {expected} {descr} parameter{expected_pluralize}"] pub span: Span, pub found: usize, pub expected: usize, + pub expected_pluralize: &'a str, + pub descr: &'a str, } #[derive(SessionDiagnostic)] diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs new file mode 100644 index 0000000000000..61aa15be47f63 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -0,0 +1,20 @@ +// Check that appropriate errors are reported if an intrinsic is defined +// with the wrong number of generic lifetime/type/const parameters, and +// that no ICE occurs in these cases. + +#![feature(platform_intrinsics)] +#![crate_type="lib"] + +extern "platform-intrinsic" { + fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_add<'a, T>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_sub(x: T, y: U); + //~^ ERROR: intrinsic has wrong number of type parameters + + fn simd_mul(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of const parameters +} diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr new file mode 100644 index 0000000000000..7dfdecb9520a7 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -0,0 +1,27 @@ +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:9:27 + | +LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:12:16 + | +LL | fn simd_add<'a, T>(x: T, y: T); + | ^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/issue-85855.rs:15:16 + | +LL | fn simd_sub(x: T, y: U); + | ^^^^^^ expected 1 type parameter + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:18:16 + | +LL | fn simd_mul(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0094`. From fe9334910998308f797207f05ed98beb37242973 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Thu, 1 Jul 2021 13:52:44 +0200 Subject: [PATCH 2/2] Minor adjustments and refactoring --- .../src/error_codes/E0094.md | 3 +- compiler/rustc_typeck/src/check/intrinsic.rs | 77 ++++++------------- compiler/rustc_typeck/src/errors.rs | 2 +- src/test/ui/simd-intrinsic/issue-85855.rs | 3 +- src/test/ui/simd-intrinsic/issue-85855.stderr | 12 +-- 5 files changed, 30 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42cd2aa185315..ec86ec44ece8e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,5 +1,4 @@ -An invalid number of generic type, lifetime, or const parameters was -given to an intrinsic function. +An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 7a7ecb06132b9..38ace42618bfc 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,7 +3,7 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfGenericArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; @@ -24,27 +24,10 @@ fn equate_intrinsic_type<'tcx>( n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - let (gen_lts, gen_tys, gen_cns, span) = match &it.kind { + let (own_counts, span) = match &it.kind { hir::ForeignItemKind::Fn(.., generics) => { - let mut gen_lts = 0; - let mut gen_tys = 0; - let mut gen_cns = 0; - - for param in generics.params { - match param.kind { - hir::GenericParamKind::Lifetime { .. } => { - gen_lts += 1; - } - hir::GenericParamKind::Type { .. } => { - gen_tys += 1; - } - hir::GenericParamKind::Const { .. } => { - gen_cns += 1; - } - } - } - - (gen_lts, gen_tys, gen_cns, generics.span) + let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts(); + (own_counts, generics.span) } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") @@ -54,31 +37,25 @@ fn equate_intrinsic_type<'tcx>( } }; - if gen_lts != n_lts { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_lts, - expected: n_lts, - expected_pluralize: pluralize!(n_lts), - descr: "lifetime", - }); - } else if gen_tys != n_tps { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_tys, - expected: n_tps, - expected_pluralize: pluralize!(n_tps), - descr: "type", - }); - } else if gen_cns != 0 { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_cns, - expected: 0, - expected_pluralize: pluralize!(0), - descr: "const", - }); - } else { + let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool { + if found != expected { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToIntrinsic { + span, + found, + expected, + expected_pluralize: pluralize!(expected), + descr, + }); + false + } else { + true + } + }; + + if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") + && gen_count_ok(own_counts.types, n_tps, "type") + && gen_count_ok(own_counts.consts, 0, "const") + { let fty = tcx.mk_fn_ptr(sig); let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); @@ -404,13 +381,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - ( - n_tps, - if matches!(intrinsic_name, sym::va_copy) { 1 } else { 0 }, - inputs, - output, - unsafety, - ) + (n_tps, 0, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index bc686a025a650..184a827a4f902 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,7 +24,7 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfGenericArgumentsToInstrinsic<'a> { +pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] #[label = "expected {expected} {descr} parameter{expected_pluralize}"] diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs index 61aa15be47f63..f276fbd669470 100644 --- a/src/test/ui/simd-intrinsic/issue-85855.rs +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -9,8 +9,7 @@ extern "platform-intrinsic" { fn simd_saturating_add<'a, T: 'a>(x: T, y: T); //~^ ERROR: intrinsic has wrong number of lifetime parameters - fn simd_add<'a, T>(x: T, y: T); - //~^ ERROR: intrinsic has wrong number of lifetime parameters + fn simd_add<'a, T>(x: T, y: T) -> T; fn simd_sub(x: T, y: U); //~^ ERROR: intrinsic has wrong number of type parameters diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr index 7dfdecb9520a7..fb2f1fbc5b1cc 100644 --- a/src/test/ui/simd-intrinsic/issue-85855.stderr +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -4,24 +4,18 @@ error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expect LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); | ^^^^^^^^^^^ expected 0 lifetime parameters -error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:12:16 - | -LL | fn simd_add<'a, T>(x: T, y: T); - | ^^^^^^^ expected 0 lifetime parameters - error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 - --> $DIR/issue-85855.rs:15:16 + --> $DIR/issue-85855.rs:14:16 | LL | fn simd_sub(x: T, y: U); | ^^^^^^ expected 1 type parameter error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:18:16 + --> $DIR/issue-85855.rs:17:16 | LL | fn simd_mul(x: T, y: T); | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0094`.