Skip to main content

rune/query/
mod.rs

1//! Lazy query system, used to compile and build items on demand and keep track
2//! of what's being used and not.
3
4mod query;
5
6use core::fmt;
7use core::mem::take;
8
9use rust_alloc::rc::Rc;
10
11pub(crate) use self::query::{Query, QueryInner, QuerySource};
12
13use crate::alloc::prelude::*;
14use crate::ast::{self, OptionSpanned, Span};
15use crate::compile::{Doc, Error, ItemId, ItemMeta, Location, ModId, Result};
16use crate::grammar::{Ignore, Node, NodeAt, NodeId, Tree};
17use crate::hash::Hash;
18use crate::hir;
19use crate::indexing;
20use crate::parse::NonZeroId;
21use crate::runtime::Call;
22use crate::{self as rune, SourceId};
23
24/// Indication whether a value is being evaluated because it's being used or not.
25#[derive(Default, Debug, TryClone, Clone, Copy)]
26#[try_clone(copy)]
27pub(crate) enum Used {
28    /// The value is not being used.
29    Unused,
30    /// The value is being used.
31    #[default]
32    Used,
33}
34
35impl Used {
36    /// Test if this used indicates unuse.
37    pub(crate) fn is_unused(self) -> bool {
38        matches!(self, Self::Unused)
39    }
40}
41
42pub(crate) enum Named2Kind {
43    /// A full path.
44    Full,
45    /// An identifier.
46    Ident(ast::Ident),
47    /// Self value.
48    SelfValue(#[allow(unused)] ast::SelfValue),
49}
50
51/// The result of calling [Query::convert_path2].
52pub(crate) struct Named2<'a> {
53    /// Module named item belongs to.
54    pub(crate) module: ModId,
55    /// The kind of named item.
56    pub(crate) kind: Named2Kind,
57    /// The path resolved to the given item.
58    pub(crate) item: ItemId,
59    /// Trailing parameters.
60    pub(crate) trailing: usize,
61    /// Type parameters if any.
62    pub(crate) parameters: [Option<Node<'a>>; 2],
63}
64
65impl fmt::Display for Named2<'_> {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        fmt::Display::fmt(&self.item, f)
68    }
69}
70
71pub(crate) enum BuiltInMacro2 {
72    File(ast::LitStr),
73    Line(usize),
74    Template(Rc<Tree>, BuiltInLiteral),
75    Format(Rc<Tree>),
76}
77
78#[derive(Debug, TryClone)]
79pub(crate) struct Closure<'hir> {
80    /// Ast for closure.
81    pub(crate) hir: &'hir hir::ExprClosure<'hir>,
82    /// Calling convention used for closure.
83    pub(crate) call: Call,
84}
85
86#[derive(Debug, TryClone)]
87pub(crate) struct AsyncBlock<'hir> {
88    /// Ast for block.
89    pub(crate) hir: &'hir hir::AsyncBlock<'hir>,
90    /// Calling convention used for async block.
91    pub(crate) call: Call,
92}
93
94/// An entry in the build queue.
95#[derive(Debug, TryClone)]
96pub(crate) enum SecondaryBuild<'hir> {
97    Closure(Closure<'hir>),
98    AsyncBlock(AsyncBlock<'hir>),
99}
100
101/// An entry in the build queue.
102#[derive(Debug, TryClone)]
103pub(crate) struct SecondaryBuildEntry<'hir> {
104    /// The item of the build entry.
105    pub(crate) item_meta: ItemMeta,
106    /// The build entry.
107    pub(crate) build: SecondaryBuild<'hir>,
108}
109
110/// An entry in the build queue.
111#[derive(Debug, TryClone)]
112pub(crate) enum Build {
113    Function(indexing::Function),
114    Unused,
115    Import(indexing::Import),
116    /// A public re-export.
117    ReExport,
118    /// A build which simply queries for the item.
119    Query,
120}
121
122/// An entry in the build queue.
123#[derive(Debug, TryClone)]
124pub(crate) struct BuildEntry {
125    /// The item of the build entry.
126    pub(crate) item_meta: ItemMeta,
127    /// The build entry.
128    pub(crate) build: Build,
129}
130
131/// The kind of item being implemented.
132pub(crate) enum ImplItemKind {
133    Node {
134        /// The path being implemented.
135        path: NodeAt,
136        /// Functions being added.
137        functions: Vec<(NodeId, Attrs)>,
138    },
139}
140
141#[must_use = "must be consumed"]
142#[derive(Default, Debug)]
143pub(crate) struct Attrs {
144    pub(crate) test: Option<Span>,
145    pub(crate) bench: Option<Span>,
146    pub(crate) docs: Vec<Doc>,
147    pub(crate) builtin: Option<(Span, BuiltInLiteral)>,
148}
149
150impl Attrs {
151    pub(crate) fn deny_non_docs(self, cx: &mut dyn Ignore<'_>) -> Result<()> {
152        if let Some(span) = self.test {
153            cx.error(Error::msg(span, "unsupported #[test] attribute"))?;
154        }
155
156        if let Some(span) = self.bench {
157            cx.error(Error::msg(span, "unsupported #[bench] attribute"))?;
158        }
159
160        if let Some((span, _)) = self.builtin {
161            cx.error(Error::msg(span, "unsupported #[builtin] attribute"))?;
162        }
163
164        Ok(())
165    }
166
167    pub(crate) fn deny_any(self, cx: &mut dyn Ignore<'_>) -> Result<()> {
168        if let Some(span) = self.docs.option_span() {
169            cx.error(Error::msg(span, "unsupported documentation"))?;
170        }
171
172        self.deny_non_docs(cx)?;
173        Ok(())
174    }
175}
176
177/// The implementation item.
178pub(crate) struct ImplItem {
179    /// The kind of item being implemented.
180    pub(crate) kind: ImplItemKind,
181    /// Location where the item impl is defined and is being expanded.
182    pub(crate) location: Location,
183    ///See [Indexer][crate::indexing::Indexer].
184    pub(crate) root: Option<SourceId>,
185    ///See [Indexer][crate::indexing::Indexer].
186    pub(crate) nested_item: Option<Span>,
187    /// See [Indexer][crate::indexing::Indexer].
188    pub(crate) macro_depth: usize,
189}
190
191/// Expand the given macro.
192#[must_use = "Must be used to report errors"]
193pub(crate) struct ExpandMacroBuiltin {
194    /// The identifier of the macro being expanded.
195    pub(crate) id: NonZeroId,
196    /// The macro being expanded.
197    pub(crate) node: NodeAt,
198    /// Location where the item impl is defined and is being expanded.
199    pub(crate) location: Location,
200    /// See [Indexer][crate::indexing::Indexer].
201    pub(crate) root: Option<SourceId>,
202    /// See [Indexer][crate::indexing::Indexer].
203    pub(crate) macro_depth: usize,
204    /// Indexing item at macro expansion position.
205    pub(crate) item: indexing::IndexItem,
206    /// The literal option.
207    pub(crate) literal: BuiltInLiteral,
208}
209
210impl ExpandMacroBuiltin {
211    /// Deny any unused options.
212    pub(crate) fn finish(self) -> Result<NonZeroId> {
213        if let BuiltInLiteral::Yes(span) = self.literal {
214            return Err(Error::msg(
215                span,
216                "#[builtin(literal)] option is not allowed",
217            ));
218        }
219
220        Ok(self.id)
221    }
222}
223
224/// Whether the literal option is set.
225#[derive(Default, Debug)]
226pub(crate) enum BuiltInLiteral {
227    Yes(Span),
228    #[default]
229    No,
230}
231
232impl BuiltInLiteral {
233    /// Take the literal option.
234    pub(crate) fn take(&mut self) -> Self {
235        take(self)
236    }
237
238    /// Test if the literal option is set.
239    pub(crate) fn is_yes(&self) -> bool {
240        matches!(self, Self::Yes(_))
241    }
242}
243
244/// Expand an item which has at least one attribute which might be an attribute
245/// macro.
246pub(crate) struct ExpandAttributeMacro {
247    /// The item node being expanded, including its attributes.
248    pub(crate) node: NodeAt,
249    /// Location of the item being expanded.
250    pub(crate) location: Location,
251    /// See [Indexer][crate::indexing::Indexer].
252    pub(crate) root: Option<SourceId>,
253    /// See [Indexer][crate::indexing::Indexer].
254    pub(crate) nested_item: Option<Span>,
255    /// See [Indexer][crate::indexing::Indexer].
256    pub(crate) macro_depth: usize,
257    /// Indexing item at macro expansion position.
258    pub(crate) item: indexing::IndexItem,
259}
260
261/// A deferred build entry.
262pub(crate) enum DeferEntry {
263    ImplItem(ImplItem),
264    ExpandMacroBuiltin(ExpandMacroBuiltin),
265    ExpandMacroCall(ExpandMacroBuiltin),
266    ExpandAttributeMacro(ExpandAttributeMacro),
267}
268
269/// A compiled constant function.
270pub(crate) struct ConstFn<'hir> {
271    /// The item of the const fn.
272    pub(crate) item_meta: ItemMeta,
273    /// HIR function associated with this constant function.
274    pub(crate) hir: hir::ItemFn<'hir>,
275    /// Expressions referred to by `hir`.
276    ///
277    /// The HIR refers to its children by identifier, so it is only meaningful
278    /// alongside the store they were lowered into.
279    pub(crate) exprs: hir::Exprs<'hir>,
280}
281
282/// The data of a macro call.
283pub(crate) enum ExpandedMacro {
284    /// A built-in expanded macro.
285    Builtin(BuiltInMacro2),
286    /// The expanded body of a macro.
287    Tree(Rc<Tree>),
288}
289
290/// Generic parameters.
291#[derive(Default)]
292pub(crate) struct GenericsParameters {
293    pub(crate) trailing: usize,
294    pub(crate) parameters: [Option<Hash>; 2],
295}
296
297impl GenericsParameters {
298    pub(crate) fn is_empty(&self) -> bool {
299        self.parameters.iter().all(|p| p.is_none())
300    }
301}
302
303impl fmt::Debug for GenericsParameters {
304    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305        let mut f = f.debug_list();
306
307        for p in &self.parameters[2 - self.trailing..] {
308            f.entry(p);
309        }
310
311        f.finish()
312    }
313}
314
315impl AsRef<GenericsParameters> for GenericsParameters {
316    #[inline]
317    fn as_ref(&self) -> &GenericsParameters {
318        self
319    }
320}