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.rs | 40 |
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; |