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>(
453453 instance. def = ty:: InstanceKind :: Virtual ( call, 0 ) ;
454454 instance. args = abstract_args;
455455 }
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+ }
456485 }
457486
458487 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