Skip to content

Commit 85cc4b2

Browse files
Rollup merge of #152958 - nnethercote:rustc_queries-fixes, r=oli-obk
`rustc_queries` simplifications Queries have two ways of specifying code snippets, in `desc` and `cache_on_disk_if` blocks. An example: ```rust query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> { arena_cache desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } } ``` If you need to use `tcx` in the snippet, you can use an explicit binding. But there are multiple problems with this. - The syntax used is different in the two snippets: `|tcx|` within the block vs. `(tcx)` outside the block. (!!) - Bug 1: In `desc` snippets you can leave out the `|tcx|` and still use `tcx`. Several existing queries do this. - Bug 2: In `desc` snippets you can always use `key` in the snippet to refer to the key, even if that's not the identifier used in the query head. - Finally, you can bind `tcx` and not use it, without a warning. Several existing queries do this. I think explicit `tcx` binding is silly. Many queries need `tcx` and this macro is already super-magical, so just making `tcx` implicitly available seems fine, rather than making the query writer jump through a little syntactic hoop. This makes both the query definitions and the proc macro simpler. r? @petrochenkov
2 parents 143ca0b + ecb778f commit 85cc4b2

2 files changed

Lines changed: 186 additions & 203 deletions

File tree

compiler/rustc_macros/src/query.rs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,11 @@ impl<T: Parse> Parse for List<T> {
103103

104104
struct Desc {
105105
modifier: Ident,
106-
tcx_binding: Option<Ident>,
107106
expr_list: Punctuated<Expr, Token![,]>,
108107
}
109108

110109
struct CacheOnDiskIf {
111110
modifier: Ident,
112-
tcx_binding: Option<Pat>,
113111
block: Block,
114112
}
115113

@@ -192,35 +190,16 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
192190

193191
if modifier == "desc" {
194192
// Parse a description modifier like:
195-
// `desc { |tcx| "foo {}", tcx.item_path(key) }`
193+
// `desc { "foo {}", tcx.item_path(key) }`
196194
let attr_content;
197195
braced!(attr_content in input);
198-
let tcx_binding = if attr_content.peek(Token![|]) {
199-
attr_content.parse::<Token![|]>()?;
200-
let tcx = attr_content.parse()?;
201-
attr_content.parse::<Token![|]>()?;
202-
Some(tcx)
203-
} else {
204-
None
205-
};
206196
let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;
207-
try_insert!(desc = Desc { modifier, tcx_binding, expr_list });
197+
try_insert!(desc = Desc { modifier, expr_list });
208198
} else if modifier == "cache_on_disk_if" {
209199
// Parse a cache-on-disk modifier like:
210-
//
211-
// `cache_on_disk_if { true }`
212-
// `cache_on_disk_if { key.is_local() }`
213-
// `cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }`
214-
let tcx_binding = if input.peek(token::Paren) {
215-
let args;
216-
parenthesized!(args in input);
217-
let tcx = Pat::parse_single(&args)?;
218-
Some(tcx)
219-
} else {
220-
None
221-
};
200+
// `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }`
222201
let block = input.parse()?;
223-
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, tcx_binding, block });
202+
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
224203
} else if modifier == "arena_cache" {
225204
try_insert!(arena_cache = modifier);
226205
} else if modifier == "cycle_fatal" {
@@ -313,24 +292,24 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
313292
erased_name.set_span(Span::call_site());
314293

315294
// Generate a function to check whether we should cache the query to disk, for some key.
316-
if let Some(CacheOnDiskIf { tcx_binding, block, .. }) = modifiers.cache_on_disk_if.as_ref() {
317-
let tcx = tcx_binding.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
318-
// we're taking `key` by reference, but some rustc types usually prefer being passed by value
295+
if let Some(CacheOnDiskIf { block, .. }) = modifiers.cache_on_disk_if.as_ref() {
296+
// `pass_by_value`: some keys are marked with `rustc_pass_by_value`, but we take keys by
297+
// reference here.
298+
// FIXME: `pass_by_value` is badly named; `allow(rustc::pass_by_value)` actually means
299+
// "allow pass by reference of `rustc_pass_by_value` types".
319300
streams.cache_on_disk_if_fns_stream.extend(quote! {
320301
#[allow(unused_variables, rustc::pass_by_value)]
321302
#[inline]
322-
pub fn #erased_name<'tcx>(#tcx: TyCtxt<'tcx>, #key_pat: &crate::queries::#name::Key<'tcx>) -> bool
303+
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, #key_pat: &#key_ty) -> bool
323304
#block
324305
});
325306
}
326307

327-
let Desc { tcx_binding, expr_list, .. } = &modifiers.desc;
328-
let tcx = tcx_binding.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t });
308+
let Desc { expr_list, .. } = &modifiers.desc;
329309

330310
let desc = quote! {
331311
#[allow(unused_variables)]
332-
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, key: #key_ty) -> String {
333-
let (#tcx, #key_pat) = (tcx, key);
312+
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, #key_pat: #key_ty) -> String {
334313
format!(#expr_list)
335314
}
336315
};

0 commit comments

Comments
 (0)