Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/lib.rs')
-rw-r--r--crates/syntax/src/lib.rs40
1 files changed, 32 insertions, 8 deletions
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index a3c19f71fb..7346b93192 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -67,7 +67,7 @@ pub use smol_str::{SmolStr, SmolStrBuilder, ToSmolStr, format_smolstr};
/// files.
#[derive(Debug, PartialEq, Eq)]
pub struct Parse<T> {
- green: GreenNode,
+ green: Option<GreenNode>,
errors: Option<Arc<[SyntaxError]>>,
_ty: PhantomData<fn() -> T>,
}
@@ -81,14 +81,14 @@ impl<T> Clone for Parse<T> {
impl<T> Parse<T> {
fn new(green: GreenNode, errors: Vec<SyntaxError>) -> Parse<T> {
Parse {
- green,
+ green: Some(green),
errors: if errors.is_empty() { None } else { Some(errors.into()) },
_ty: PhantomData,
}
}
pub fn syntax_node(&self) -> SyntaxNode {
- SyntaxNode::new_root(self.green.clone())
+ SyntaxNode::new_root(self.green.as_ref().unwrap().clone())
}
pub fn errors(&self) -> Vec<SyntaxError> {
@@ -100,8 +100,10 @@ impl<T> Parse<T> {
impl<T: AstNode> Parse<T> {
/// Converts this parse result into a parse result for an untyped syntax tree.
- pub fn to_syntax(self) -> Parse<SyntaxNode> {
- Parse { green: self.green, errors: self.errors, _ty: PhantomData }
+ pub fn to_syntax(mut self) -> Parse<SyntaxNode> {
+ let green = self.green.take();
+ let errors = self.errors.take();
+ Parse { green, errors, _ty: PhantomData }
}
/// Gets the parsed syntax tree as a typed ast node.
@@ -124,9 +126,9 @@ impl<T: AstNode> Parse<T> {
}
impl Parse<SyntaxNode> {
- pub fn cast<N: AstNode>(self) -> Option<Parse<N>> {
+ pub fn cast<N: AstNode>(mut self) -> Option<Parse<N>> {
if N::cast(self.syntax_node()).is_some() {
- Some(Parse { green: self.green, errors: self.errors, _ty: PhantomData })
+ Some(Parse { green: self.green.take(), errors: self.errors.take(), _ty: PhantomData })
} else {
None
}
@@ -162,7 +164,7 @@ impl Parse<SourceFile> {
edition,
)
.map(|(green_node, errors, _reparsed_range)| Parse {
- green: green_node,
+ green: Some(green_node),
errors: if errors.is_empty() { None } else { Some(errors.into()) },
_ty: PhantomData,
})
@@ -198,6 +200,28 @@ impl ast::Expr {
}
}
+#[cfg(not(no_salsa_async_drops))]
+impl<T> Drop for Parse<T> {
+ fn drop(&mut self) {
+ let Some(green) = self.green.take() else {
+ return;
+ };
+ static PARSE_DROP_THREAD: std::sync::OnceLock<std::sync::mpsc::Sender<GreenNode>> =
+ std::sync::OnceLock::new();
+ PARSE_DROP_THREAD
+ .get_or_init(|| {
+ let (sender, receiver) = std::sync::mpsc::channel::<GreenNode>();
+ std::thread::Builder::new()
+ .name("ParseNodeDropper".to_owned())
+ .spawn(move || receiver.iter().for_each(drop))
+ .unwrap();
+ sender
+ })
+ .send(green)
+ .unwrap();
+ }
+}
+
/// `SourceFile` represents a parse tree for a single Rust file.
pub use crate::ast::SourceFile;