File tree Expand file tree Collapse file tree 3 files changed +89
-0
lines changed
compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi Expand file tree Collapse file tree 3 files changed +89
-0
lines changed Original file line number Diff line number Diff line change @@ -453,6 +453,35 @@ pub(crate) fn transform_instance<'tcx>(
453
453
instance. def = ty:: InstanceKind :: Virtual ( call, 0 ) ;
454
454
instance. args = abstract_args;
455
455
}
456
+ let fn_traits = [
457
+ ( LangItem :: Fn , sym:: call) ,
458
+ ( LangItem :: FnMut , sym:: call_mut) ,
459
+ ( LangItem :: FnOnce , sym:: call_once) ,
460
+ ] ;
461
+ for ( lang_item, method_sym) in fn_traits {
462
+ if let Some ( trait_id) = tcx. lang_items ( ) . get ( lang_item) {
463
+ let items = tcx. associated_items ( trait_id) ;
464
+ if let Some ( call_method) =
465
+ items. in_definition_order ( ) . find ( |item| item. name ( ) == method_sym)
466
+ {
467
+ if instance. def_id ( ) == call_method. def_id {
468
+ // This is a call to a method of Fn, FnMut, or FnOnce. Transform self into a
469
+ // trait object of the trait that defines the method.
470
+ let self_ty = trait_object_ty (
471
+ tcx,
472
+ ty:: Binder :: dummy ( ty:: TraitRef :: from_method (
473
+ tcx,
474
+ trait_id,
475
+ instance. args ,
476
+ ) ) ,
477
+ ) ;
478
+ instance. args =
479
+ tcx. mk_args_trait ( self_ty, instance. args . into_iter ( ) . skip ( 1 ) ) ;
480
+ break ;
481
+ }
482
+ }
483
+ }
484
+ }
456
485
}
457
486
458
487
instance
Original file line number Diff line number Diff line change
1
+ // Verifies that types that implement the Fn, FnMut, or FnOnce traits can be
2
+ // called through their trait methods.
3
+ //
4
+ //@ needs-sanitizer-cfi
5
+ //@ compile-flags: -Ctarget-feature=-crt-static -Ccodegen-units=1 -Clto -Cprefer-dynamic=off -Copt-level=0 -Zsanitizer=cfi --test
6
+ //@ run-pass
7
+
8
+ #![ feature( fn_traits) ]
9
+ #![ feature( unboxed_closures) ]
10
+
11
+ fn foo ( _a : u32 ) { }
12
+
13
+ #[ test]
14
+ fn test_fn_trait ( ) {
15
+ let f: Box < dyn Fn ( u32 ) > = Box :: new ( foo) ;
16
+ Fn :: call ( & f, ( 0 , ) ) ;
17
+ }
18
+
19
+ #[ test]
20
+ fn test_fnmut_trait ( ) {
21
+ let mut a = 0 ;
22
+ let mut f: Box < dyn FnMut ( u32 ) > = Box :: new ( |x| a += x) ;
23
+ FnMut :: call_mut ( & mut f, ( 1 , ) ) ;
24
+ }
25
+
26
+ #[ test]
27
+ fn test_fnonce_trait ( ) {
28
+ let f: Box < dyn FnOnce ( u32 ) > = Box :: new ( foo) ;
29
+ FnOnce :: call_once ( f, ( 2 , ) ) ;
30
+ }
Original file line number Diff line number Diff line change
1
+ // Verifies that types that implement the Fn, FnMut, or FnOnce traits can be
2
+ // called through their trait methods.
3
+ //
4
+ //@ needs-sanitizer-cfi
5
+ //@ compile-flags: -Ctarget-feature=-crt-static -Zpanic_abort_tests -Cpanic=abort -Cprefer-dynamic=off -Copt-level=0 -Zsanitizer=kcfi --test
6
+ //@ run-pass
7
+
8
+ #![ feature( fn_traits) ]
9
+ #![ feature( unboxed_closures) ]
10
+
11
+ fn foo ( _a : u32 ) { }
12
+
13
+ #[ test]
14
+ fn test_fn_trait ( ) {
15
+ let f: Box < dyn Fn ( u32 ) > = Box :: new ( foo) ;
16
+ Fn :: call ( & f, ( 0 , ) ) ;
17
+ }
18
+
19
+ #[ test]
20
+ fn test_fnmut_trait ( ) {
21
+ let mut a = 0 ;
22
+ let mut f: Box < dyn FnMut ( u32 ) > = Box :: new ( |x| a += x) ;
23
+ FnMut :: call_mut ( & mut f, ( 1 , ) ) ;
24
+ }
25
+
26
+ #[ test]
27
+ fn test_fnonce_trait ( ) {
28
+ let f: Box < dyn FnOnce ( u32 ) > = Box :: new ( foo) ;
29
+ FnOnce :: call_once ( f, ( 2 , ) ) ;
30
+ }
You can’t perform that action at this time.
0 commit comments