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