@@ -64,6 +64,7 @@ fn check_fn_for_unconditional_recursion<'tcx>(
64
64
| TerminatorKind :: Abort
65
65
| TerminatorKind :: Return
66
66
| TerminatorKind :: Unreachable => {
67
+ // We propagate backwards, so these should never be encountered here.
67
68
unreachable ! ( "unexpected terminator {:?}" , terminator. kind)
68
69
}
69
70
} ;
@@ -118,13 +119,15 @@ fn find_blocks_calling_self<'tcx>(
118
119
def_id : DefId ,
119
120
) -> BitSet < BasicBlock > {
120
121
let param_env = tcx. param_env ( def_id) ;
122
+
123
+ // If this is trait/impl method, extract the trait's substs.
121
124
let trait_substs_count = match tcx. opt_associated_item ( def_id) {
122
125
Some ( AssocItem { container : AssocItemContainer :: TraitContainer ( trait_def_id) , .. } ) => {
123
126
tcx. generics_of ( trait_def_id) . count ( )
124
127
}
125
128
_ => 0 ,
126
129
} ;
127
- let caller_substs = & InternalSubsts :: identity_for_item ( tcx, def_id) [ ..trait_substs_count] ;
130
+ let trait_substs = & InternalSubsts :: identity_for_item ( tcx, def_id) [ ..trait_substs_count] ;
128
131
129
132
let mut self_calls = BitSet :: new_empty ( body. basic_blocks ( ) . len ( ) ) ;
130
133
@@ -142,8 +145,12 @@ fn find_blocks_calling_self<'tcx>(
142
145
143
146
// FIXME(#57965): Make this work across function boundaries
144
147
148
+ // If this is a trait fn, the substs on the trait have to match, or we might be
149
+ // calling into an entirely different method (for example, a call from the default
150
+ // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are
151
+ // specific types).
145
152
let is_self_call =
146
- call_fn_id == def_id && & call_substs[ ..caller_substs . len ( ) ] == caller_substs ;
153
+ call_fn_id == def_id && & call_substs[ ..trait_substs . len ( ) ] == trait_substs ;
147
154
148
155
if is_self_call {
149
156
self_calls. insert ( bb) ;
0 commit comments