@@ -131,11 +131,24 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
131131 }
132132
133133 {
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 polymorphic, 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)
134148 let caller_needs_location = self . needs_location ( self . caller_ty ) ;
135- let callee_needs_location = self . needs_location ( ty) ;
136149
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 ) ;
139152 }
140153 }
141154
@@ -149,7 +162,9 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
149162 }
150163
151164 /// 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.
153168 fn needs_location ( & self , ty : Ty < ' tcx > ) -> bool {
154169 if let & ty:: FnDef ( did, substs) = ty. kind ( ) {
155170 let instance =
@@ -292,25 +307,15 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
292307 self . found_errors = Err ( err) ;
293308 }
294309
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 ( ) ;
314319
315320 self . found_errors = Err ( err) ;
316321 }
0 commit comments