3
3
// This source code is licensed under the GNU license found in the
4
4
// LICENSE file in the root directory of this source tree.
5
5
6
+ //! This module provides essential functions for resolving call targets.
7
+
6
8
use rustc_hir:: def_id:: DefId ;
7
9
use rustc_middle:: ty:: { GenericArgsRef , TyCtxt , TyKind } ;
8
10
9
11
use crate :: util;
10
12
11
- /// Try to resolve the given FnDef, devirtualize the callee function if possible.
13
+ /// Try to resolve the function with `def_id` and `gen_args`.
14
+ ///
15
+ /// If the function is not a trait method, (`def_id`, `gen_args`) is returned
16
+ /// directly. Otherwise, the function is devirtualized to a specific implementation.
12
17
pub fn resolve_fn_def < ' tcx > (
13
18
tcx : TyCtxt < ' tcx > ,
14
- callee_def_id : DefId ,
19
+ def_id : DefId ,
15
20
gen_args : GenericArgsRef < ' tcx > ,
16
21
) -> ( DefId , GenericArgsRef < ' tcx > ) {
17
- if tcx. is_mir_available ( callee_def_id ) && !util:: is_trait_method ( tcx, callee_def_id ) {
18
- ( callee_def_id , gen_args)
19
- } else if let Some ( ( callee_def_id , callee_substs ) ) =
20
- try_to_devirtualize ( tcx, callee_def_id , gen_args)
22
+ if tcx. is_mir_available ( def_id ) && !util:: is_trait_method ( tcx, def_id ) {
23
+ ( def_id , gen_args)
24
+ } else if let Some ( ( resolved_def_id , resolved_substs ) ) =
25
+ try_to_devirtualize ( tcx, def_id , gen_args)
21
26
{
22
- ( callee_def_id , callee_substs )
27
+ ( resolved_def_id , resolved_substs )
23
28
} else {
24
- // if the mir is unavailable or the callee cannot be resolved, return the callee_def_id directly
25
- ( callee_def_id, gen_args)
29
+ // if the function cannot be resolved,
30
+ // return the original (def_id, gen_args) pair directly.
31
+ ( def_id, gen_args)
26
32
}
27
33
}
28
34
35
+ /// Try to devirtualize a trait method with `def_id` and `gen_args`.
36
+ ///
37
+ /// Returns `None` if the given `def_id` does not correspond to a trait method or
38
+ /// we cannot resolve the trait method to a specific instance. For example, the
39
+ /// first gen_arg is a dynamic type.
29
40
pub fn try_to_devirtualize < ' tcx > (
30
41
tcx : TyCtxt < ' tcx > ,
31
- callee_def_id : DefId ,
42
+ def_id : DefId ,
32
43
gen_args : GenericArgsRef < ' tcx > ,
33
44
) -> Option < ( DefId , GenericArgsRef < ' tcx > ) > {
34
- if !util:: is_trait_method ( tcx, callee_def_id ) {
45
+ if !util:: is_trait_method ( tcx, def_id ) {
35
46
return None ;
36
47
}
37
48
49
+ // A trait method cannot be devirtualized when the first gen_arg corresponds
50
+ // to a dynamic type.
38
51
let arg0_ty = gen_args
39
52
. types ( )
40
53
. next ( )
@@ -45,20 +58,20 @@ pub fn try_to_devirtualize<'tcx>(
45
58
46
59
let param_env = rustc_middle:: ty:: ParamEnv :: reveal_all ( ) ;
47
60
let abi = tcx
48
- . type_of ( callee_def_id )
61
+ . type_of ( def_id )
49
62
. skip_binder ( )
50
63
. fn_sig ( tcx)
51
64
. abi ( ) ;
52
65
let resolved_instance = if abi == rustc_target:: spec:: abi:: Abi :: Rust {
53
66
// Instance::resolve panics if try_normalize_erasing_regions returns an error.
54
- // It is hard to figure out exactly when this will be the case .
67
+ // It is difficult to determine exactly when this error will occur .
55
68
if tcx. try_normalize_erasing_regions ( param_env, gen_args) . is_err ( ) {
56
69
None
57
70
} else {
58
71
Some ( rustc_middle:: ty:: Instance :: resolve (
59
72
tcx,
60
73
param_env,
61
- callee_def_id ,
74
+ def_id ,
62
75
gen_args,
63
76
) )
64
77
}
@@ -67,10 +80,6 @@ pub fn try_to_devirtualize<'tcx>(
67
80
} ;
68
81
if let Some ( Ok ( Some ( instance) ) ) = resolved_instance {
69
82
let resolved_def_id = instance. def . def_id ( ) ;
70
- let has_mir = tcx. is_mir_available ( resolved_def_id) ;
71
- if !has_mir {
72
- return None ;
73
- }
74
83
return Some ( ( resolved_def_id, instance. args ) ) ;
75
84
}
76
85
None
0 commit comments