@@ -132,11 +132,24 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
132132 }
133133
134134 {
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)
135149 let caller_needs_location = self . needs_location ( self . caller_ty ) ;
136- let callee_needs_location = self . needs_location ( ty) ;
137150
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 ) ;
140153 }
141154 }
142155
@@ -150,7 +163,9 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
150163 }
151164
152165 /// 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.
154169 fn needs_location ( & self , ty : Ty < ' tcx > ) -> bool {
155170 if let & ty:: FnDef ( did, substs) = ty. kind ( ) {
156171 let instance =
@@ -293,25 +308,15 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
293308 self . found_errors = Err ( err) ;
294309 }
295310
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 ( ) ;
315320
316321 self . found_errors = Err ( err) ;
317322 }
0 commit comments