@@ -132,11 +132,24 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
132
132
}
133
133
134
134
{
135
+ // `#[track_caller]` affects the ABI of a function (by adding a location argument),
136
+ // so a `track_caller` can only tail call other `track_caller` functions.
137
+ //
138
+ // The issue is however that we can't know if a function is `track_caller` or not at
139
+ // this point (THIR can be polymorphic, we may have an unresolved trait function).
140
+ // We could only allow functions that we *can* resolve and *are* `track_caller`,
141
+ // but that would turn changing `track_caller`-ness into a breaking change,
142
+ // which is probably undesirable.
143
+ //
144
+ // Also note that we don't check callee's `track_caller`-ness at all, mostly for the
145
+ // reasons above, but also because we can always tailcall the shim we'd generate for
146
+ // coercing the function to an `fn()` pointer. (although in that case the tailcall is
147
+ // basically useless -- the shim calls the actual function, so tailcalling the shim is
148
+ // equivalent to calling the function)
135
149
let caller_needs_location = self . needs_location ( self . caller_ty ) ;
136
- let callee_needs_location = self . needs_location ( ty) ;
137
150
138
- if caller_needs_location != callee_needs_location {
139
- self . report_track_caller_mismatch ( expr. span , caller_needs_location ) ;
151
+ if caller_needs_location {
152
+ self . report_track_caller_caller ( expr. span ) ;
140
153
}
141
154
}
142
155
@@ -150,7 +163,9 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
150
163
}
151
164
152
165
/// Returns true if function of type `ty` needs location argument
153
- /// (i.e. if a function is marked as `#[track_caller]`)
166
+ /// (i.e. if a function is marked as `#[track_caller]`).
167
+ ///
168
+ /// Panics if the function's instance can't be immediately resolved.
154
169
fn needs_location ( & self , ty : Ty < ' tcx > ) -> bool {
155
170
if let & ty:: FnDef ( did, substs) = ty. kind ( ) {
156
171
let instance =
@@ -293,25 +308,15 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
293
308
self . found_errors = Err ( err) ;
294
309
}
295
310
296
- fn report_track_caller_mismatch ( & mut self , sp : Span , caller_needs_location : bool ) {
297
- let err = match caller_needs_location {
298
- true => self
299
- . tcx
300
- . dcx ( )
301
- . struct_span_err (
302
- sp,
303
- "a function marked with `#[track_caller]` cannot tail-call one that is not" ,
304
- )
305
- . emit ( ) ,
306
- false => self
307
- . tcx
308
- . dcx ( )
309
- . struct_span_err (
310
- sp,
311
- "a function mot marked with `#[track_caller]` cannot tail-call one that is" ,
312
- )
313
- . emit ( ) ,
314
- } ;
311
+ fn report_track_caller_caller ( & mut self , sp : Span ) {
312
+ let err = self
313
+ . tcx
314
+ . dcx ( )
315
+ . struct_span_err (
316
+ sp,
317
+ "a function marked with `#[track_caller]` cannot perform a tail-call" ,
318
+ )
319
+ . emit ( ) ;
315
320
316
321
self . found_errors = Err ( err) ;
317
322
}
0 commit comments