Skip to content

Commit 7b2befc

Browse files
committed
Check the number of generic lifetime and const parameters of intrinsics
1 parent a50d721 commit 7b2befc

File tree

5 files changed

+116
-28
lines changed

5 files changed

+116
-28
lines changed

compiler/rustc_error_codes/src/error_codes/E0094.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
An invalid number of type parameters was given to an intrinsic function.
1+
An invalid number of generic type, lifetime, or const parameters was
2+
given to an intrinsic function.
23

34
Erroneous code example:
45

compiler/rustc_typeck/src/check/intrinsic.rs

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
44
use crate::errors::{
55
SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
6-
WrongNumberOfTypeArgumentsToInstrinsic,
6+
WrongNumberOfGenericArgumentsToInstrinsic,
77
};
88
use crate::require_same_types;
99

10-
use rustc_errors::struct_span_err;
10+
use rustc_errors::{pluralize, struct_span_err};
1111
use rustc_hir as hir;
1212
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
1313
use rustc_middle::ty::subst::Subst;
@@ -21,36 +21,68 @@ fn equate_intrinsic_type<'tcx>(
2121
tcx: TyCtxt<'tcx>,
2222
it: &hir::ForeignItem<'_>,
2323
n_tps: usize,
24+
n_lts: usize,
2425
sig: ty::PolyFnSig<'tcx>,
2526
) {
26-
match it.kind {
27-
hir::ForeignItemKind::Fn(..) => {}
27+
let (gen_lts, gen_tys, gen_cns, span) = match &it.kind {
28+
hir::ForeignItemKind::Fn(.., generics) => {
29+
let mut gen_lts = 0;
30+
let mut gen_tys = 0;
31+
let mut gen_cns = 0;
32+
33+
for param in generics.params {
34+
match param.kind {
35+
hir::GenericParamKind::Lifetime { .. } => {
36+
gen_lts += 1;
37+
}
38+
hir::GenericParamKind::Type { .. } => {
39+
gen_tys += 1;
40+
}
41+
hir::GenericParamKind::Const { .. } => {
42+
gen_cns += 1;
43+
}
44+
}
45+
}
46+
47+
(gen_lts, gen_tys, gen_cns, generics.span)
48+
}
2849
_ => {
2950
struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function")
3051
.span_label(it.span, "expected a function")
3152
.emit();
3253
return;
3354
}
34-
}
35-
36-
let i_n_tps = tcx.generics_of(it.def_id).own_counts().types;
37-
if i_n_tps != n_tps {
38-
let span = match it.kind {
39-
hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span,
40-
_ => bug!(),
41-
};
55+
};
4256

43-
tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic {
57+
if gen_lts != n_lts {
58+
tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic {
59+
span,
60+
found: gen_lts,
61+
expected: n_lts,
62+
expected_pluralize: pluralize!(n_lts),
63+
descr: "lifetime",
64+
});
65+
} else if gen_tys != n_tps {
66+
tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic {
4467
span,
45-
found: i_n_tps,
68+
found: gen_tys,
4669
expected: n_tps,
70+
expected_pluralize: pluralize!(n_tps),
71+
descr: "type",
4772
});
48-
return;
73+
} else if gen_cns != 0 {
74+
tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic {
75+
span,
76+
found: gen_cns,
77+
expected: 0,
78+
expected_pluralize: pluralize!(0),
79+
descr: "const",
80+
});
81+
} else {
82+
let fty = tcx.mk_fn_ptr(sig);
83+
let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
84+
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
4985
}
50-
51-
let fty = tcx.mk_fn_ptr(sig);
52-
let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
53-
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
5486
}
5587

5688
/// 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<'_>) {
121153
})
122154
};
123155

124-
let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
156+
let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
125157
let split: Vec<&str> = name_str.split('_').collect();
126158
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
127159

@@ -143,7 +175,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
143175
return;
144176
}
145177
};
146-
(n_tps, inputs, output, hir::Unsafety::Unsafe)
178+
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
147179
} else {
148180
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
149181
let (n_tps, inputs, output) = match intrinsic_name {
@@ -372,11 +404,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
372404
return;
373405
}
374406
};
375-
(n_tps, inputs, output, unsafety)
407+
(
408+
n_tps,
409+
if matches!(intrinsic_name, sym::va_copy) { 1 } else { 0 },
410+
inputs,
411+
output,
412+
unsafety,
413+
)
376414
};
377415
let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
378416
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
379-
equate_intrinsic_type(tcx, it, n_tps, sig)
417+
equate_intrinsic_type(tcx, it, n_tps, n_lts, sig)
380418
}
381419

382420
/// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -472,5 +510,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
472510
Abi::PlatformIntrinsic,
473511
);
474512
let sig = ty::Binder::dummy(sig);
475-
equate_intrinsic_type(tcx, it, n_tps, sig)
513+
equate_intrinsic_type(tcx, it, n_tps, 0, sig)
476514
}

compiler/rustc_typeck/src/errors.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> {
2424

2525
#[derive(SessionDiagnostic)]
2626
#[error = "E0094"]
27-
pub struct WrongNumberOfTypeArgumentsToInstrinsic {
28-
#[message = "intrinsic has wrong number of type \
27+
pub struct WrongNumberOfGenericArgumentsToInstrinsic<'a> {
28+
#[message = "intrinsic has wrong number of {descr} \
2929
parameters: found {found}, expected {expected}"]
30-
#[label = "expected {expected} type parameter"]
30+
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
3131
pub span: Span,
3232
pub found: usize,
3333
pub expected: usize,
34+
pub expected_pluralize: &'a str,
35+
pub descr: &'a str,
3436
}
3537

3638
#[derive(SessionDiagnostic)]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Check that appropriate errors are reported if an intrinsic is defined
2+
// with the wrong number of generic lifetime/type/const parameters, and
3+
// that no ICE occurs in these cases.
4+
5+
#![feature(platform_intrinsics)]
6+
#![crate_type="lib"]
7+
8+
extern "platform-intrinsic" {
9+
fn simd_saturating_add<'a, T: 'a>(x: T, y: T);
10+
//~^ ERROR: intrinsic has wrong number of lifetime parameters
11+
12+
fn simd_add<'a, T>(x: T, y: T);
13+
//~^ ERROR: intrinsic has wrong number of lifetime parameters
14+
15+
fn simd_sub<T, U>(x: T, y: U);
16+
//~^ ERROR: intrinsic has wrong number of type parameters
17+
18+
fn simd_mul<T, const N: usize>(x: T, y: T);
19+
//~^ ERROR: intrinsic has wrong number of const parameters
20+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0
2+
--> $DIR/issue-85855.rs:9:27
3+
|
4+
LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T);
5+
| ^^^^^^^^^^^ expected 0 lifetime parameters
6+
7+
error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0
8+
--> $DIR/issue-85855.rs:12:16
9+
|
10+
LL | fn simd_add<'a, T>(x: T, y: T);
11+
| ^^^^^^^ expected 0 lifetime parameters
12+
13+
error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
14+
--> $DIR/issue-85855.rs:15:16
15+
|
16+
LL | fn simd_sub<T, U>(x: T, y: U);
17+
| ^^^^^^ expected 1 type parameter
18+
19+
error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0
20+
--> $DIR/issue-85855.rs:18:16
21+
|
22+
LL | fn simd_mul<T, const N: usize>(x: T, y: T);
23+
| ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters
24+
25+
error: aborting due to 4 previous errors
26+
27+
For more information about this error, try `rustc --explain E0094`.

0 commit comments

Comments
 (0)