33
44use crate :: errors:: {
55 SimdShuffleMissingLength , UnrecognizedAtomicOperation , UnrecognizedIntrinsicFunction ,
6- WrongNumberOfTypeArgumentsToInstrinsic ,
6+ WrongNumberOfGenericArgumentsToIntrinsic ,
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,45 @@ 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 ( own_counts, span) = match & it. kind {
28+ hir:: ForeignItemKind :: Fn ( .., generics) => {
29+ let own_counts = tcx. generics_of ( it. def_id . to_def_id ( ) ) . own_counts ( ) ;
30+ ( own_counts, generics. span )
31+ }
2832 _ => {
2933 struct_span_err ! ( tcx. sess, it. span, E0622 , "intrinsic must be a function" )
3034 . span_label ( it. span , "expected a function" )
3135 . emit ( ) ;
3236 return ;
3337 }
34- }
38+ } ;
3539
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- } ;
40+ let gen_count_ok = |found : usize , expected : usize , descr : & str | -> bool {
41+ if found != expected {
42+ tcx. sess . emit_err ( WrongNumberOfGenericArgumentsToIntrinsic {
43+ span,
44+ found,
45+ expected,
46+ expected_pluralize : pluralize ! ( expected) ,
47+ descr,
48+ } ) ;
49+ false
50+ } else {
51+ true
52+ }
53+ } ;
4254
43- tcx. sess . emit_err ( WrongNumberOfTypeArgumentsToInstrinsic {
44- span,
45- found : i_n_tps,
46- expected : n_tps,
47- } ) ;
48- return ;
55+ if gen_count_ok ( own_counts. lifetimes , n_lts, "lifetime" )
56+ && gen_count_ok ( own_counts. types , n_tps, "type" )
57+ && gen_count_ok ( own_counts. consts , 0 , "const" )
58+ {
59+ let fty = tcx. mk_fn_ptr ( sig) ;
60+ let cause = ObligationCause :: new ( it. span , it. hir_id ( ) , ObligationCauseCode :: IntrinsicType ) ;
61+ require_same_types ( tcx, & cause, tcx. mk_fn_ptr ( tcx. fn_sig ( it. def_id ) ) , fty) ;
4962 }
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) ;
5463}
5564
5665/// Returns the unsafety of the given intrinsic.
@@ -121,7 +130,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
121130 } )
122131 } ;
123132
124- let ( n_tps, inputs, output, unsafety) = if name_str. starts_with ( "atomic_" ) {
133+ let ( n_tps, n_lts , inputs, output, unsafety) = if name_str. starts_with ( "atomic_" ) {
125134 let split: Vec < & str > = name_str. split ( '_' ) . collect ( ) ;
126135 assert ! ( split. len( ) >= 2 , "Atomic intrinsic in an incorrect format" ) ;
127136
@@ -143,7 +152,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
143152 return ;
144153 }
145154 } ;
146- ( n_tps, inputs, output, hir:: Unsafety :: Unsafe )
155+ ( n_tps, 0 , inputs, output, hir:: Unsafety :: Unsafe )
147156 } else {
148157 let unsafety = intrinsic_operation_unsafety ( intrinsic_name) ;
149158 let ( n_tps, inputs, output) = match intrinsic_name {
@@ -372,11 +381,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
372381 return ;
373382 }
374383 } ;
375- ( n_tps, inputs, output, unsafety)
384+ ( n_tps, 0 , inputs, output, unsafety)
376385 } ;
377386 let sig = tcx. mk_fn_sig ( inputs. into_iter ( ) , output, false , unsafety, Abi :: RustIntrinsic ) ;
378387 let sig = ty:: Binder :: bind_with_vars ( sig, bound_vars) ;
379- equate_intrinsic_type ( tcx, it, n_tps, sig)
388+ equate_intrinsic_type ( tcx, it, n_tps, n_lts , sig)
380389}
381390
382391/// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -472,5 +481,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
472481 Abi :: PlatformIntrinsic ,
473482 ) ;
474483 let sig = ty:: Binder :: dummy ( sig) ;
475- equate_intrinsic_type ( tcx, it, n_tps, sig)
484+ equate_intrinsic_type ( tcx, it, n_tps, 0 , sig)
476485}
0 commit comments