33
44use crate :: errors:: {
55 SimdShuffleMissingLength , UnrecognizedAtomicOperation , UnrecognizedIntrinsicFunction ,
6- WrongNumberOfTypeArgumentsToInstrinsic ,
6+ WrongNumberOfGenericArgumentsToInstrinsic ,
77} ;
88use crate :: require_same_types;
99
10- use rustc_errors:: struct_span_err;
10+ use rustc_errors:: { pluralize , struct_span_err} ;
1111use rustc_hir as hir;
1212use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
1313use 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}
0 commit comments