Skip to content

Commit b730a84

Browse files
committed
Extract some modifier-parsing code to rustc_macros::query::modifiers
1 parent ec818fd commit b730a84

2 files changed

Lines changed: 126 additions & 152 deletions

File tree

compiler/rustc_macros/src/query.rs

Lines changed: 9 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ use syn::parse::{Parse, ParseStream, Result};
55
use syn::punctuated::Punctuated;
66
use syn::spanned::Spanned;
77
use syn::{
8-
AttrStyle, Attribute, Block, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced,
9-
parenthesized, parse_macro_input, token,
8+
AttrStyle, Attribute, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, parenthesized,
9+
parse_macro_input, token,
1010
};
1111

12+
mod modifiers;
13+
1214
mod kw {
1315
syn::custom_keyword!(non_query);
1416
syn::custom_keyword!(query);
@@ -52,7 +54,7 @@ struct Query {
5254
key_ty: Type,
5355
return_ty: ReturnType,
5456

55-
modifiers: QueryModifiers,
57+
modifiers: modifiers::QueryModifiers,
5658
}
5759

5860
/// Declaration of a non-query dep kind.
@@ -102,7 +104,7 @@ impl Parse for QueryEntry {
102104
// Parse the query modifiers
103105
let braces_content;
104106
braced!(braces_content in input);
105-
let modifiers = parse_query_modifiers(&braces_content)?;
107+
let modifiers = modifiers::parse_query_modifiers(&braces_content)?;
106108

107109
// If there are no doc-comments, give at least some idea of what
108110
// it does by showing the query description.
@@ -127,151 +129,6 @@ impl<T: Parse> Parse for List<T> {
127129
}
128130
}
129131

130-
struct Desc {
131-
modifier: Ident,
132-
expr_list: Punctuated<Expr, Token![,]>,
133-
}
134-
135-
struct CacheOnDiskIf {
136-
modifier: Ident,
137-
block: Block,
138-
}
139-
140-
struct QueryModifiers {
141-
/// The description of the query.
142-
desc: Desc,
143-
144-
/// Use this type for the in-memory cache.
145-
arena_cache: Option<Ident>,
146-
147-
/// Cache the query to disk if the `Block` returns true.
148-
cache_on_disk_if: Option<CacheOnDiskIf>,
149-
150-
/// A cycle error for this query aborting the compilation with a fatal error.
151-
cycle_fatal: Option<Ident>,
152-
153-
/// A cycle error results in a delay_bug call
154-
cycle_delay_bug: Option<Ident>,
155-
156-
/// A cycle error results in a stashed cycle error that can be unstashed and canceled later
157-
cycle_stash: Option<Ident>,
158-
159-
/// Don't hash the result, instead just mark a query red if it runs
160-
no_hash: Option<Ident>,
161-
162-
/// Generate a dep node based on the dependencies of the query
163-
anon: Option<Ident>,
164-
165-
/// Always evaluate the query, ignoring its dependencies
166-
eval_always: Option<Ident>,
167-
168-
/// Whether the query has a call depth limit
169-
depth_limit: Option<Ident>,
170-
171-
/// Use a separate query provider for local and extern crates
172-
separate_provide_extern: Option<Ident>,
173-
174-
/// Generate a `feed` method to set the query's value from another query.
175-
feedable: Option<Ident>,
176-
177-
/// When this query is called via `tcx.ensure_ok()`, it returns
178-
/// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to
179-
/// be executed, and that execution returns an error, the error result is
180-
/// returned to the caller.
181-
///
182-
/// If execution is skipped, a synthetic `Ok(())` is returned, on the
183-
/// assumption that a query with all-green inputs must have succeeded.
184-
///
185-
/// Can only be applied to queries with a return value of
186-
/// `Result<_, ErrorGuaranteed>`.
187-
return_result_from_ensure_ok: Option<Ident>,
188-
}
189-
190-
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
191-
let mut arena_cache = None;
192-
let mut cache_on_disk_if = None;
193-
let mut desc = None;
194-
let mut cycle_fatal = None;
195-
let mut cycle_delay_bug = None;
196-
let mut cycle_stash = None;
197-
let mut no_hash = None;
198-
let mut anon = None;
199-
let mut eval_always = None;
200-
let mut depth_limit = None;
201-
let mut separate_provide_extern = None;
202-
let mut feedable = None;
203-
let mut return_result_from_ensure_ok = None;
204-
205-
while !input.is_empty() {
206-
let modifier: Ident = input.parse()?;
207-
208-
macro_rules! try_insert {
209-
($name:ident = $expr:expr) => {
210-
if $name.is_some() {
211-
return Err(Error::new(modifier.span(), "duplicate modifier"));
212-
}
213-
$name = Some($expr);
214-
};
215-
}
216-
217-
if modifier == "desc" {
218-
// Parse a description modifier like:
219-
// `desc { "foo {}", tcx.item_path(key) }`
220-
let attr_content;
221-
braced!(attr_content in input);
222-
let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;
223-
try_insert!(desc = Desc { modifier, expr_list });
224-
} else if modifier == "cache_on_disk_if" {
225-
// Parse a cache-on-disk modifier like:
226-
// `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }`
227-
let block = input.parse()?;
228-
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
229-
} else if modifier == "arena_cache" {
230-
try_insert!(arena_cache = modifier);
231-
} else if modifier == "cycle_fatal" {
232-
try_insert!(cycle_fatal = modifier);
233-
} else if modifier == "cycle_delay_bug" {
234-
try_insert!(cycle_delay_bug = modifier);
235-
} else if modifier == "cycle_stash" {
236-
try_insert!(cycle_stash = modifier);
237-
} else if modifier == "no_hash" {
238-
try_insert!(no_hash = modifier);
239-
} else if modifier == "anon" {
240-
try_insert!(anon = modifier);
241-
} else if modifier == "eval_always" {
242-
try_insert!(eval_always = modifier);
243-
} else if modifier == "depth_limit" {
244-
try_insert!(depth_limit = modifier);
245-
} else if modifier == "separate_provide_extern" {
246-
try_insert!(separate_provide_extern = modifier);
247-
} else if modifier == "feedable" {
248-
try_insert!(feedable = modifier);
249-
} else if modifier == "return_result_from_ensure_ok" {
250-
try_insert!(return_result_from_ensure_ok = modifier);
251-
} else {
252-
return Err(Error::new(modifier.span(), "unknown query modifier"));
253-
}
254-
}
255-
let Some(desc) = desc else {
256-
return Err(input.error("no description provided"));
257-
};
258-
Ok(QueryModifiers {
259-
arena_cache,
260-
cache_on_disk_if,
261-
desc,
262-
cycle_fatal,
263-
cycle_delay_bug,
264-
cycle_stash,
265-
no_hash,
266-
anon,
267-
eval_always,
268-
depth_limit,
269-
separate_provide_extern,
270-
feedable,
271-
return_result_from_ensure_ok,
272-
})
273-
}
274-
275132
fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attribute> {
276133
use ::syn::*;
277134
let mut iter = list.iter();
@@ -318,7 +175,7 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
318175
erased_name.set_span(Span::call_site());
319176

320177
// Generate a function to check whether we should cache the query to disk, for some key.
321-
if let Some(CacheOnDiskIf { block, .. }) = modifiers.cache_on_disk_if.as_ref() {
178+
if let Some(modifiers::CacheOnDiskIf { block, .. }) = modifiers.cache_on_disk_if.as_ref() {
322179
// `disallowed_pass_by_ref` is needed because some keys are `rustc_pass_by_value`.
323180
streams.cache_on_disk_if_fns_stream.extend(quote! {
324181
#[cfg_attr(not(bootstrap), allow(unused_variables, rustc::disallowed_pass_by_ref))]
@@ -329,7 +186,7 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
329186
});
330187
}
331188

332-
let Desc { expr_list, .. } = &modifiers.desc;
189+
let modifiers::Desc { expr_list, .. } = &modifiers.desc;
333190

334191
let desc = quote! {
335192
#[allow(unused_variables)]
@@ -356,7 +213,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
356213
crate::query::modifiers::#name;
357214
});
358215

359-
if let Some(CacheOnDiskIf { modifier, .. }) = &modifiers.cache_on_disk_if {
216+
if let Some(modifiers::CacheOnDiskIf { modifier, .. }) = &modifiers.cache_on_disk_if {
360217
modifiers_stream.extend(quote! {
361218
crate::query::modifiers::#modifier;
362219
});
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use syn::parse::{Parse, ParseStream, Result};
2+
use syn::punctuated::Punctuated;
3+
use syn::{Block, Error, Expr, Ident, Token, braced};
4+
5+
pub(crate) struct Desc {
6+
pub(crate) modifier: Ident,
7+
pub(crate) expr_list: Punctuated<Expr, Token![,]>,
8+
}
9+
10+
pub(crate) struct CacheOnDiskIf {
11+
pub(crate) modifier: Ident,
12+
pub(crate) block: Block,
13+
}
14+
15+
/// See [`rustc_middle::query::modifiers`] for documentation of each query modifier.
16+
pub(crate) struct QueryModifiers {
17+
// tidy-alphabetical-start
18+
pub(crate) anon: Option<Ident>,
19+
pub(crate) arena_cache: Option<Ident>,
20+
pub(crate) cache_on_disk_if: Option<CacheOnDiskIf>,
21+
pub(crate) cycle_delay_bug: Option<Ident>,
22+
pub(crate) cycle_fatal: Option<Ident>,
23+
pub(crate) cycle_stash: Option<Ident>,
24+
pub(crate) depth_limit: Option<Ident>,
25+
pub(crate) desc: Desc,
26+
pub(crate) eval_always: Option<Ident>,
27+
pub(crate) feedable: Option<Ident>,
28+
pub(crate) no_hash: Option<Ident>,
29+
pub(crate) return_result_from_ensure_ok: Option<Ident>,
30+
pub(crate) separate_provide_extern: Option<Ident>,
31+
// tidy-alphabetical-end
32+
}
33+
34+
pub(crate) fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
35+
let mut arena_cache = None;
36+
let mut cache_on_disk_if = None;
37+
let mut desc = None;
38+
let mut cycle_fatal = None;
39+
let mut cycle_delay_bug = None;
40+
let mut cycle_stash = None;
41+
let mut no_hash = None;
42+
let mut anon = None;
43+
let mut eval_always = None;
44+
let mut depth_limit = None;
45+
let mut separate_provide_extern = None;
46+
let mut feedable = None;
47+
let mut return_result_from_ensure_ok = None;
48+
49+
while !input.is_empty() {
50+
let modifier: Ident = input.parse()?;
51+
52+
macro_rules! try_insert {
53+
($name:ident = $expr:expr) => {
54+
if $name.is_some() {
55+
return Err(Error::new(modifier.span(), "duplicate modifier"));
56+
}
57+
$name = Some($expr);
58+
};
59+
}
60+
61+
if modifier == "desc" {
62+
// Parse a description modifier like:
63+
// `desc { "foo {}", tcx.item_path(key) }`
64+
let attr_content;
65+
braced!(attr_content in input);
66+
let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;
67+
try_insert!(desc = Desc { modifier, expr_list });
68+
} else if modifier == "cache_on_disk_if" {
69+
// Parse a cache-on-disk modifier like:
70+
// `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }`
71+
let block = input.parse()?;
72+
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
73+
} else if modifier == "arena_cache" {
74+
try_insert!(arena_cache = modifier);
75+
} else if modifier == "cycle_fatal" {
76+
try_insert!(cycle_fatal = modifier);
77+
} else if modifier == "cycle_delay_bug" {
78+
try_insert!(cycle_delay_bug = modifier);
79+
} else if modifier == "cycle_stash" {
80+
try_insert!(cycle_stash = modifier);
81+
} else if modifier == "no_hash" {
82+
try_insert!(no_hash = modifier);
83+
} else if modifier == "anon" {
84+
try_insert!(anon = modifier);
85+
} else if modifier == "eval_always" {
86+
try_insert!(eval_always = modifier);
87+
} else if modifier == "depth_limit" {
88+
try_insert!(depth_limit = modifier);
89+
} else if modifier == "separate_provide_extern" {
90+
try_insert!(separate_provide_extern = modifier);
91+
} else if modifier == "feedable" {
92+
try_insert!(feedable = modifier);
93+
} else if modifier == "return_result_from_ensure_ok" {
94+
try_insert!(return_result_from_ensure_ok = modifier);
95+
} else {
96+
return Err(Error::new(modifier.span(), "unknown query modifier"));
97+
}
98+
}
99+
let Some(desc) = desc else {
100+
return Err(input.error("no description provided"));
101+
};
102+
Ok(QueryModifiers {
103+
arena_cache,
104+
cache_on_disk_if,
105+
desc,
106+
cycle_fatal,
107+
cycle_delay_bug,
108+
cycle_stash,
109+
no_hash,
110+
anon,
111+
eval_always,
112+
depth_limit,
113+
separate_provide_extern,
114+
feedable,
115+
return_result_from_ensure_ok,
116+
})
117+
}

0 commit comments

Comments
 (0)