@@ -300,7 +300,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
300300
301301 // Delegate to another function to actually execute the query job.
302302 let ( value, dep_node_index) = if INCR {
303- execute_job_incr ( query, tcx, key, dep_node, id)
303+ execute_job_incr ( query, tcx, key, dep_node. unwrap ( ) , id)
304304 } else {
305305 execute_job_non_incr ( query, tcx, key, id)
306306 } ;
@@ -416,27 +416,23 @@ fn execute_job_incr<'tcx, C: QueryCache>(
416416 query : & ' tcx QueryVTable < ' tcx , C > ,
417417 tcx : TyCtxt < ' tcx > ,
418418 key : C :: Key ,
419- mut dep_node_opt : Option < DepNode > ,
419+ dep_node : DepNode ,
420420 job_id : QueryJobId ,
421421) -> ( C :: Value , DepNodeIndex ) {
422422 let dep_graph_data =
423423 tcx. dep_graph . data ( ) . expect ( "should always be present in incremental mode" ) ;
424424
425425 if !query. anon && !query. eval_always {
426- // `to_dep_node` is expensive for some `DepKind`s.
427- let dep_node =
428- dep_node_opt. get_or_insert_with ( || DepNode :: construct ( tcx, query. dep_kind , & key) ) ;
429-
430426 // The diagnostics for this query will be promoted to the current session during
431427 // `try_mark_green()`, so we can ignore them here.
432428 if let Some ( ret) = start_query ( job_id, false , || try {
433- let ( prev_index, dep_node_index) = dep_graph_data. try_mark_green ( tcx, dep_node) ?;
429+ let ( prev_index, dep_node_index) = dep_graph_data. try_mark_green ( tcx, & dep_node) ?;
434430 let value = load_from_disk_or_invoke_provider_green (
435431 tcx,
436432 dep_graph_data,
437433 query,
438434 key,
439- dep_node,
435+ & dep_node,
440436 prev_index,
441437 dep_node_index,
442438 ) ;
@@ -456,10 +452,6 @@ fn execute_job_incr<'tcx, C: QueryCache>(
456452 } ) ;
457453 }
458454
459- // `to_dep_node` is expensive for some `DepKind`s.
460- let dep_node =
461- dep_node_opt. unwrap_or_else ( || DepNode :: construct ( tcx, query. dep_kind , & key) ) ;
462-
463455 // Call the query provider.
464456 dep_graph_data. with_task (
465457 dep_node,
@@ -571,69 +563,56 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
571563 value
572564}
573565
574- /// Return value struct for [`check_if_ensure_can_skip_execution`].
575- struct EnsureCanSkip {
576- /// If true, the current `tcx.ensure_ok()` or `tcx.ensure_done()` query
577- /// can return early without actually trying to execute.
578- skip_execution : bool ,
579- /// A dep node that was prepared while checking whether execution can be
580- /// skipped, to be reused by execution itself if _not_ skipped.
581- dep_node : Option < DepNode > ,
582- }
583-
584566/// Checks whether a `tcx.ensure_ok()` or `tcx.ensure_done()` query call can
585567/// return early without actually trying to execute.
586568///
587569/// This only makes sense during incremental compilation, because it relies
588570/// on having the dependency graph (and in some cases a disk-cached value)
589571/// from the previous incr-comp session.
590572#[ inline( never) ]
591- fn check_if_ensure_can_skip_execution < ' tcx , C : QueryCache > (
573+ fn ensure_can_skip_execution < ' tcx , C : QueryCache > (
592574 query : & ' tcx QueryVTable < ' tcx , C > ,
593575 tcx : TyCtxt < ' tcx > ,
594576 key : C :: Key ,
577+ dep_node : DepNode ,
595578 ensure_mode : EnsureMode ,
596- ) -> EnsureCanSkip {
579+ ) -> bool {
597580 // Queries with `eval_always` should never skip execution.
598581 if query. eval_always {
599- return EnsureCanSkip { skip_execution : false , dep_node : None } ;
582+ return false ;
600583 }
601584
602585 // Ensuring an anonymous query makes no sense
603586 assert ! ( !query. anon) ;
604587
605- let dep_node = DepNode :: construct ( tcx, query. dep_kind , & key) ;
606-
607- let serialized_dep_node_index = match tcx. dep_graph . try_mark_green ( tcx, & dep_node) {
588+ match tcx. dep_graph . try_mark_green ( tcx, & dep_node) {
608589 None => {
609590 // A None return from `try_mark_green` means that this is either
610591 // a new dep node or that the dep node has already been marked red.
611592 // Either way, we can't call `dep_graph.read()` as we don't have the
612593 // DepNodeIndex. We must invoke the query itself. The performance cost
613594 // this introduces should be negligible as we'll immediately hit the
614595 // in-memory cache, or another query down the line will.
615- return EnsureCanSkip { skip_execution : false , dep_node : Some ( dep_node ) } ;
596+ false
616597 }
617598 Some ( ( serialized_dep_node_index, dep_node_index) ) => {
618599 tcx. dep_graph . read_index ( dep_node_index) ;
619600 tcx. prof . query_cache_hit ( dep_node_index. into ( ) ) ;
620- serialized_dep_node_index
621- }
622- } ;
623-
624- match ensure_mode {
625- EnsureMode :: Ok => {
626- // In ensure-ok mode, we can skip execution for this key if the node
627- // is green. It must have succeeded in the previous session, and
628- // therefore would succeed in the current session if executed.
629- EnsureCanSkip { skip_execution : true , dep_node : None }
630- }
631- EnsureMode :: Done => {
632- // In ensure-done mode, we can only skip execution for this key if
633- // there's a disk-cached value available to load later if needed,
634- // which guarantees the query provider will never run for this key.
635- let is_loadable = ( query. is_loadable_from_disk_fn ) ( tcx, key, serialized_dep_node_index) ;
636- EnsureCanSkip { skip_execution : is_loadable, dep_node : Some ( dep_node) }
601+ match ensure_mode {
602+ // In ensure-ok mode, we can skip execution for this key if the
603+ // node is green. It must have succeeded in the previous
604+ // session, and therefore would succeed in the current session
605+ // if executed.
606+ EnsureMode :: Ok => true ,
607+
608+ // In ensure-done mode, we can only skip execution for this key
609+ // if there's a disk-cached value available to load later if
610+ // needed, which guarantees the query provider will never run
611+ // for this key.
612+ EnsureMode :: Done => {
613+ ( query. is_loadable_from_disk_fn ) ( tcx, key, serialized_dep_node_index)
614+ }
615+ }
637616 }
638617 }
639618}
@@ -660,24 +639,20 @@ pub(super) fn execute_query_incr_inner<'tcx, C: QueryCache>(
660639 key : C :: Key ,
661640 mode : QueryMode ,
662641) -> Option < C :: Value > {
642+ // There are scenarios where this `dep_node` is never used (e.g. for `anon` queries) but they
643+ // are rare enough that the wasted effort doesn't materially hurt performance.
644+ let dep_node = DepNode :: construct ( tcx, query. dep_kind , & key) ;
645+
663646 // Check if query execution can be skipped, for `ensure_ok` or `ensure_done`.
664- // This might have the side-effect of creating a suitable DepNode, which
665- // we should reuse for execution instead of creating a new one.
666- let dep_node: Option < DepNode > = match mode {
667- QueryMode :: Ensure { ensure_mode } => {
668- let EnsureCanSkip { skip_execution, dep_node } =
669- check_if_ensure_can_skip_execution ( query, tcx, key, ensure_mode) ;
670- if skip_execution {
671- // Return early to skip execution.
672- return None ;
673- }
674- dep_node
675- }
676- QueryMode :: Get => None ,
677- } ;
647+ if let QueryMode :: Ensure { ensure_mode } = mode
648+ && ensure_can_skip_execution ( query, tcx, key, dep_node, ensure_mode)
649+ {
650+ return None ;
651+ }
678652
679- let ( result, dep_node_index) =
680- ensure_sufficient_stack ( || try_execute_query :: < C , true > ( query, tcx, span, key, dep_node) ) ;
653+ let ( result, dep_node_index) = ensure_sufficient_stack ( || {
654+ try_execute_query :: < C , true > ( query, tcx, span, key, Some ( dep_node) )
655+ } ) ;
681656 if let Some ( dep_node_index) = dep_node_index {
682657 tcx. dep_graph . read_index ( dep_node_index)
683658 }
0 commit comments