diff options
| -rw-r--r-- | compiler/rustc_macros/src/query.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/plumbing.rs | 10 |
3 files changed, 34 insertions, 22 deletions
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 88ea6e07d6e..62bf34ad5ad 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -118,11 +118,17 @@ struct QueryModifiers { /// Generate a `feed` method to set the query's value from another query. feedable: Option<Ident>, - /// Forward the result on ensure if the query gets recomputed, and - /// return `Ok(())` otherwise. Only applicable to queries returning - /// `Result<T, ErrorGuaranteed>`. The `T` is not returned from `ensure` - /// invocations. - ensure_forwards_result_if_red: Option<Ident>, + /// When this query is called via `tcx.ensure_ok()`, it returns + /// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to + /// be executed, and that execution returns an error, the error result is + /// returned to the caller. + /// + /// If execution is skipped, a synthetic `Ok(())` is returned, on the + /// assumption that a query with all-green inputs must have succeeded. + /// + /// Can only be applied to queries with a return value of + /// `Result<_, ErrorGuaranteed>`. + return_result_from_ensure_ok: Option<Ident>, } fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { @@ -138,7 +144,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { let mut depth_limit = None; let mut separate_provide_extern = None; let mut feedable = None; - let mut ensure_forwards_result_if_red = None; + let mut return_result_from_ensure_ok = None; while !input.is_empty() { let modifier: Ident = input.parse()?; @@ -200,8 +206,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { try_insert!(separate_provide_extern = modifier); } else if modifier == "feedable" { try_insert!(feedable = modifier); - } else if modifier == "ensure_forwards_result_if_red" { - try_insert!(ensure_forwards_result_if_red = modifier); + } else if modifier == "return_result_from_ensure_ok" { + try_insert!(return_result_from_ensure_ok = modifier); } else { return Err(Error::new(modifier.span(), "unknown query modifier")); } @@ -222,7 +228,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { depth_limit, separate_provide_extern, feedable, - ensure_forwards_result_if_red, + return_result_from_ensure_ok, }) } @@ -354,7 +360,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { eval_always, depth_limit, separate_provide_extern, - ensure_forwards_result_if_red, + return_result_from_ensure_ok, ); if modifiers.cache.is_some() { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 934593dfb79..6c442fc1047 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1087,7 +1087,7 @@ rustc_queries! { query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Caches `CoerceUnsized` kinds for impls on custom types. @@ -1095,7 +1095,7 @@ rustc_queries! { desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern - ensure_forwards_result_if_red + return_result_from_ensure_ok } query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { @@ -1110,7 +1110,7 @@ rustc_queries! { query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Borrow-checks the function body. If this is a closure, returns @@ -1140,7 +1140,7 @@ rustc_queries! { /// </div> query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for inherent impls that should not be defined in crate" } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. @@ -1152,7 +1152,7 @@ rustc_queries! { /// </div> query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Checks whether all impls in the crate pass the overlap check, returning @@ -1162,7 +1162,7 @@ rustc_queries! { "checking whether impl `{}` follows the orphan rules", tcx.def_path_str(key), } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Check whether the function has any recursion that could cause the inliner to trigger @@ -1479,7 +1479,7 @@ rustc_queries! { query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } cache_on_disk_if { true } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } @@ -1715,12 +1715,12 @@ rustc_queries! { query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } // The `DefId`s of all non-generic functions and statics in the given crate @@ -2442,7 +2442,7 @@ rustc_queries! { /// Any other def id will ICE. query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6648e3d9d53..6c1ef046a60 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -118,6 +118,12 @@ impl<'tcx> TyCtxt<'tcx> { /// /// Therefore, this call mode is not appropriate for callers that want to /// ensure that the query is _never_ executed in the future. + /// + /// ## `return_result_from_ensure_ok` + /// If a query has the `return_result_from_ensure_ok` modifier, calls via + /// `ensure_ok` will instead return `Result<(), ErrorGuaranteed>`. If the + /// query needs to be executed, and execution returns an error, that error + /// is returned to the caller. #[inline(always)] pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> { TyCtxtEnsureOk { tcx: self } @@ -223,7 +229,7 @@ macro_rules! query_ensure { ([]$($args:tt)*) => { query_ensure($($args)*) }; - ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => { + ([(return_result_from_ensure_ok) $($rest:tt)*]$($args:tt)*) => { query_ensure_error_guaranteed($($args)*).map(|_| ()) }; ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { @@ -282,7 +288,7 @@ macro_rules! ensure_ok_result { ( [] ) => { () }; - ( [(ensure_forwards_result_if_red) $($rest:tt)*] ) => { + ( [(return_result_from_ensure_ok) $($rest:tt)*] ) => { Result<(), ErrorGuaranteed> }; ( [$other:tt $($modifiers:tt)*] ) => { |
