Skip to content

Commit fe8ebb1

Browse files
committed
Allow ensure queries to return Result<(), ErrorGuaranteed>
1 parent eb99a89 commit fe8ebb1

File tree

5 files changed

+75
-9
lines changed

5 files changed

+75
-9
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1899,10 +1899,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
18991899

19001900
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
19011901
let items = tcx.hir_module_items(module);
1902-
let mut res = items.par_items(|item| tcx.check_well_formed(item.owner_id));
1903-
res = res.and(items.par_impl_items(|item| tcx.check_well_formed(item.owner_id)));
1904-
res = res.and(items.par_trait_items(|item| tcx.check_well_formed(item.owner_id)));
1905-
res.and(items.par_foreign_items(|item| tcx.check_well_formed(item.owner_id)))
1902+
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
1903+
res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1904+
res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1905+
res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)))
19061906
}
19071907

19081908
fn error_392(

compiler/rustc_hir_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
206206
}
207207

208208
tcx.sess.time("wf_checking", || {
209-
tcx.hir().try_par_for_each_module(|module| tcx.check_mod_type_wf(module))
209+
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
210210
})?;
211211

212212
// NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.

compiler/rustc_macros/src/query.rs

+10
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ struct QueryModifiers {
114114

115115
/// Generate a `feed` method to set the query's value from another query.
116116
feedable: Option<Ident>,
117+
118+
/// Forward the result on ensure if the query gets recomputed, and
119+
/// return `Ok(())` otherwise. Only applicable to queries returning
120+
/// `Result<(), ErrorGuaranteed>`
121+
ensure_forwards_result_if_red: Option<Ident>,
117122
}
118123

119124
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
@@ -128,6 +133,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
128133
let mut depth_limit = None;
129134
let mut separate_provide_extern = None;
130135
let mut feedable = None;
136+
let mut ensure_forwards_result_if_red = None;
131137

132138
while !input.is_empty() {
133139
let modifier: Ident = input.parse()?;
@@ -187,6 +193,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
187193
try_insert!(separate_provide_extern = modifier);
188194
} else if modifier == "feedable" {
189195
try_insert!(feedable = modifier);
196+
} else if modifier == "ensure_forwards_result_if_red" {
197+
try_insert!(ensure_forwards_result_if_red = modifier);
190198
} else {
191199
return Err(Error::new(modifier.span(), "unknown query modifier"));
192200
}
@@ -206,6 +214,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
206214
depth_limit,
207215
separate_provide_extern,
208216
feedable,
217+
ensure_forwards_result_if_red,
209218
})
210219
}
211220

@@ -325,6 +334,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
325334
eval_always,
326335
depth_limit,
327336
separate_provide_extern,
337+
ensure_forwards_result_if_red,
328338
);
329339

330340
if modifiers.cache.is_some() {

compiler/rustc_middle/src/query/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use crate::mir::interpret::{
2525
use crate::mir::interpret::{LitToConstError, LitToConstInput};
2626
use crate::mir::mono::CodegenUnit;
2727
use crate::query::erase::{erase, restore, Erase};
28-
use crate::query::plumbing::{query_ensure, query_get_at, CyclePlaceholder, DynamicQuery};
28+
use crate::query::plumbing::{
29+
query_ensure, query_ensure_error_guaranteed, query_get_at, CyclePlaceholder, DynamicQuery,
30+
};
2931
use crate::thir;
3032
use crate::traits::query::{
3133
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -967,6 +969,7 @@ rustc_queries! {
967969

968970
query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
969971
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
972+
ensure_forwards_result_if_red
970973
}
971974

972975
query collect_mod_item_types(key: LocalModDefId) -> () {
@@ -1501,6 +1504,7 @@ rustc_queries! {
15011504

15021505
query check_well_formed(key: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
15031506
desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) }
1507+
ensure_forwards_result_if_red
15041508
}
15051509

15061510
// The `DefId`s of all non-generic functions and statics in the given crate

compiler/rustc_middle/src/query/plumbing.rs

+55-3
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,45 @@ pub fn query_ensure<'tcx, Cache>(
173173
}
174174
}
175175

176+
#[inline]
177+
pub fn query_ensure_error_guaranteed<'tcx, Cache>(
178+
tcx: TyCtxt<'tcx>,
179+
execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
180+
query_cache: &Cache,
181+
key: Cache::Key,
182+
check_cache: bool,
183+
) -> Result<(), ErrorGuaranteed>
184+
where
185+
Cache: QueryCache<Value = super::erase::Erase<Result<(), ErrorGuaranteed>>>,
186+
{
187+
let key = key.into_query_param();
188+
if let Some(res) = try_get_cached(tcx, query_cache, &key) {
189+
super::erase::restore(res)
190+
} else {
191+
execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
192+
.map(super::erase::restore)
193+
// Either we actually executed the query, which means we got a full `Result`,
194+
// or we can just assume the query succeeded, because it was green in the
195+
// incremental cache. If it is green, that means that the previous compilation
196+
// that wrote to the incremental cache compiles successfully. That is only
197+
// possible if the cache entry was `Ok(())`, so we emit that here, without
198+
// actually encoding the `Result` in the cache or loading it from there.
199+
.unwrap_or(Ok(()))
200+
}
201+
}
202+
203+
macro_rules! query_ensure {
204+
([]$($args:tt)*) => {
205+
query_ensure($($args)*)
206+
};
207+
([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => {
208+
query_ensure_error_guaranteed($($args)*)
209+
};
210+
([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
211+
query_ensure!([$($modifiers)*]$($args)*)
212+
};
213+
}
214+
176215
macro_rules! query_helper_param_ty {
177216
(DefId) => { impl IntoQueryParam<DefId> };
178217
(LocalDefId) => { impl IntoQueryParam<LocalDefId> };
@@ -220,6 +259,18 @@ macro_rules! separate_provide_extern_decl {
220259
};
221260
}
222261

262+
macro_rules! ensure_result {
263+
([][$ty:ty]) => {
264+
()
265+
};
266+
([(ensure_forwards_result_if_red) $($rest:tt)*][$ty:ty]) => {
267+
Result<(), ErrorGuaranteed>
268+
};
269+
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
270+
ensure_result!([$($modifiers)*][$($args)*])
271+
};
272+
}
273+
223274
macro_rules! separate_provide_extern_default {
224275
([][$name:ident]) => {
225276
()
@@ -343,14 +394,15 @@ macro_rules! define_callbacks {
343394
impl<'tcx> TyCtxtEnsure<'tcx> {
344395
$($(#[$attr])*
345396
#[inline(always)]
346-
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
347-
query_ensure(
397+
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> ensure_result!([$($modifiers)*][$V]) {
398+
query_ensure!(
399+
[$($modifiers)*]
348400
self.tcx,
349401
self.tcx.query_system.fns.engine.$name,
350402
&self.tcx.query_system.caches.$name,
351403
key.into_query_param(),
352404
false,
353-
);
405+
)
354406
})*
355407
}
356408

0 commit comments

Comments
 (0)