@@ -24,7 +24,7 @@ use rustc_hir::def_id::DefId;
2424use rustc_hir:: { CRATE_HIR_ID , HirId } ;
2525use rustc_middle:: mir:: visit:: Visitor as _;
2626use rustc_middle:: mir:: {
27- self , Body , CastKind , ClearCrossCrate , Location , Rvalue , SourceInfo , Terminator , TerminatorKind ,
27+ self , Body , CastKind , Location , Rvalue , SourceScope , Terminator , TerminatorKind ,
2828} ;
2929use rustc_middle:: mono:: MonoItem ;
3030use rustc_middle:: span_bug;
@@ -126,15 +126,17 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for LintPostMono<'a, 'tcx> {
126126 if let Some ( ( callee_instance, pre_mono_call) ) = self . get_call_def_mir ( terminator, location)
127127 {
128128 let use_ = self . use_ ( UseKind :: Called ( callee_instance) , terminator. source_info . span ) ;
129- self . on_edge ( use_, & terminator. source_info , pre_mono_call) ;
129+ self . on_edge ( use_, terminator. source_info . scope , pre_mono_call) ;
130130 }
131+ self . super_terminator ( terminator, location) ;
131132 }
132133
133134 fn visit_rvalue ( & mut self , rval : & Rvalue < ' tcx > , location : Location ) {
134135 let Some ( ( call_span, use_kind) ) = self . find_dynamic_cast ( rval) else { return } ;
135136 let source_info = self . body . source_info ( location) ;
136137 let use_ = self . use_ ( use_kind, call_span) ;
137- self . on_edge ( use_, source_info, use_. def_id ( ) ) ;
138+ self . on_edge ( use_, source_info. scope , use_. def_id ( ) ) ;
139+ self . super_rvalue ( rval, location) ;
138140 }
139141}
140142
@@ -190,16 +192,14 @@ impl<'a, 'tcx> LintPostMono<'a, 'tcx> {
190192 Use { kind, span, from_instantiation : self . from_instantiation }
191193 }
192194
193- fn on_edge ( & mut self , use_ : Use < ' tcx > , source_info : & SourceInfo , pre_mono_callee : DefId ) {
195+ fn lint ( & mut self , use_ : Use < ' tcx > , scope : SourceScope ) -> HirId {
194196 // Try to update the lint node if possible, but use the lint node of the caller if the
195197 // callee is cross-crate.
196198 // FIXME: we have enough info here to show a backtrace of how the function was instantiated,
197199 // maybe pass that in so we can show it?
198- let lint_node = match self . body . source_scopes [ source_info. scope ] . local_data . as_ref ( ) {
199- ClearCrossCrate :: Set ( data) => data. lint_root ,
200- // We assume that all roots come from the current crate.
201- // This is checked earlier in `lint_validated_roots`.
202- ClearCrossCrate :: Clear => match self . from_instantiation . as_ref ( ) {
200+ let lint_node = match scope. lint_root ( & self . body . source_scopes ) {
201+ Some ( node) => node,
202+ None => match self . from_instantiation . as_ref ( ) {
203203 // This is a bit odd - we use the HIR id of the caller function,
204204 // not the callee that actually caused the error.
205205 // The callee is in another crate so we don't have any choice here.
@@ -213,6 +213,12 @@ impl<'a, 'tcx> LintPostMono<'a, 'tcx> {
213213 // Lint this use.
214214 self . linter . check_use ( lint_node, use_) ;
215215
216+ lint_node
217+ }
218+
219+ fn on_edge ( & mut self , use_ : Use < ' tcx > , scope : SourceScope , pre_mono_callee : DefId ) {
220+ let lint_node = self . lint ( use_, scope) ;
221+
216222 // Recurse into the instantiated call.
217223 let callee_instance = match use_. kind {
218224 UseKind :: TraitObjectCast (
@@ -333,10 +339,27 @@ impl<'a, 'tcx> LintPostMono<'a, 'tcx> {
333339 }
334340
335341 let body = tcx. instance_mir ( instance. def ) ;
342+ trace ! ( body = ?body, "visiting body" ) ;
336343 let mut this = LintPostMono { linter, visited, roots, instance, body, from_instantiation } ;
337- for ( bb, data) in mir:: traversal:: reachable ( body) {
344+ for ( bb, data) in mir:: traversal:: preorder ( body) {
338345 this. visit_basic_block_data ( bb, data) ;
339346 }
347+
348+ // If the MIR inliner ran, we may not see all original function calls.
349+ // Usually these are preserved in the source scopes for each statement, but if the
350+ // inliner has completely deleted every statement in the body we can't rely on that.
351+ // Iterate through every source scope we know about just in case.
352+ for ( scope, scope_data) in body. source_scopes . iter_enumerated ( ) {
353+ trace ! ( "saw scope {scope_data:?}" ) ;
354+ if let Some ( ( instance, span) ) = scope_data. inlined {
355+ debug ! ( "saw inlined instance {instance:?}" ) ;
356+ let use_ = this. use_ ( UseKind :: Called ( instance) , span) ;
357+ // NOTE: we can't use `on_edge` here because it won't properly substitute generic
358+ // parameters when it recurses. That's ok: since we're visiting every source scope in
359+ // this body, we'll catch all the other inlined calls when we see their `scope_data`.
360+ this. lint ( use_, scope) ;
361+ }
362+ }
340363 }
341364
342365 fn get_call_def_mir (
0 commit comments