3
3
4
4
use crate :: errors:: {
5
5
SimdShuffleMissingLength , UnrecognizedAtomicOperation , UnrecognizedIntrinsicFunction ,
6
- WrongNumberOfTypeArgumentsToInstrinsic ,
6
+ WrongNumberOfGenericArgumentsToInstrinsic ,
7
7
} ;
8
8
use crate :: require_same_types;
9
9
10
- use rustc_errors:: struct_span_err;
10
+ use rustc_errors:: { pluralize , struct_span_err} ;
11
11
use rustc_hir as hir;
12
12
use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
13
13
use rustc_middle:: ty:: subst:: Subst ;
@@ -21,36 +21,68 @@ fn equate_intrinsic_type<'tcx>(
21
21
tcx : TyCtxt < ' tcx > ,
22
22
it : & hir:: ForeignItem < ' _ > ,
23
23
n_tps : usize ,
24
+ n_lts : usize ,
24
25
sig : ty:: PolyFnSig < ' tcx > ,
25
26
) {
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
+ }
28
49
_ => {
29
50
struct_span_err ! ( tcx. sess, it. span, E0622 , "intrinsic must be a function" )
30
51
. span_label ( it. span , "expected a function" )
31
52
. emit ( ) ;
32
53
return ;
33
54
}
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
+ } ;
42
56
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 {
44
67
span,
45
- found : i_n_tps ,
68
+ found : gen_tys ,
46
69
expected : n_tps,
70
+ expected_pluralize : pluralize ! ( n_tps) ,
71
+ descr : "type" ,
47
72
} ) ;
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) ;
49
85
}
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) ;
54
86
}
55
87
56
88
/// 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<'_>) {
121
153
} )
122
154
} ;
123
155
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_" ) {
125
157
let split: Vec < & str > = name_str. split ( '_' ) . collect ( ) ;
126
158
assert ! ( split. len( ) >= 2 , "Atomic intrinsic in an incorrect format" ) ;
127
159
@@ -143,7 +175,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
143
175
return ;
144
176
}
145
177
} ;
146
- ( n_tps, inputs, output, hir:: Unsafety :: Unsafe )
178
+ ( n_tps, 0 , inputs, output, hir:: Unsafety :: Unsafe )
147
179
} else {
148
180
let unsafety = intrinsic_operation_unsafety ( intrinsic_name) ;
149
181
let ( n_tps, inputs, output) = match intrinsic_name {
@@ -372,11 +404,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
372
404
return ;
373
405
}
374
406
} ;
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
+ )
376
414
} ;
377
415
let sig = tcx. mk_fn_sig ( inputs. into_iter ( ) , output, false , unsafety, Abi :: RustIntrinsic ) ;
378
416
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)
380
418
}
381
419
382
420
/// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -472,5 +510,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
472
510
Abi :: PlatformIntrinsic ,
473
511
) ;
474
512
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)
476
514
}
0 commit comments