@@ -67,7 +67,7 @@ pub use smol_str::{SmolStr, SmolStrBuilder, ToSmolStr, format_smolstr};
6767/// files.
6868#[ derive( Debug , PartialEq , Eq ) ]
6969pub struct Parse < T > {
70- green : GreenNode ,
70+ green : Option < GreenNode > ,
7171 errors : Option < Arc < [ SyntaxError ] > > ,
7272 _ty : PhantomData < fn ( ) -> T > ,
7373}
@@ -81,14 +81,14 @@ impl<T> Clone for Parse<T> {
8181impl < T > Parse < T > {
8282 fn new ( green : GreenNode , errors : Vec < SyntaxError > ) -> Parse < T > {
8383 Parse {
84- green,
84+ green : Some ( green ) ,
8585 errors : if errors. is_empty ( ) { None } else { Some ( errors. into ( ) ) } ,
8686 _ty : PhantomData ,
8787 }
8888 }
8989
9090 pub fn syntax_node ( & self ) -> SyntaxNode {
91- SyntaxNode :: new_root ( self . green . clone ( ) )
91+ SyntaxNode :: new_root ( self . green . as_ref ( ) . unwrap ( ) . clone ( ) )
9292 }
9393
9494 pub fn errors ( & self ) -> Vec < SyntaxError > {
@@ -100,8 +100,10 @@ impl<T> Parse<T> {
100100
101101impl < T : AstNode > Parse < T > {
102102 /// Converts this parse result into a parse result for an untyped syntax tree.
103- pub fn to_syntax ( self ) -> Parse < SyntaxNode > {
104- Parse { green : self . green , errors : self . errors , _ty : PhantomData }
103+ pub fn to_syntax ( mut self ) -> Parse < SyntaxNode > {
104+ let green = self . green . take ( ) ;
105+ let errors = self . errors . take ( ) ;
106+ Parse { green, errors, _ty : PhantomData }
105107 }
106108
107109 /// Gets the parsed syntax tree as a typed ast node.
@@ -124,9 +126,9 @@ impl<T: AstNode> Parse<T> {
124126}
125127
126128impl Parse < SyntaxNode > {
127- pub fn cast < N : AstNode > ( self ) -> Option < Parse < N > > {
129+ pub fn cast < N : AstNode > ( mut self ) -> Option < Parse < N > > {
128130 if N :: cast ( self . syntax_node ( ) ) . is_some ( ) {
129- Some ( Parse { green : self . green , errors : self . errors , _ty : PhantomData } )
131+ Some ( Parse { green : self . green . take ( ) , errors : self . errors . take ( ) , _ty : PhantomData } )
130132 } else {
131133 None
132134 }
@@ -162,7 +164,7 @@ impl Parse<SourceFile> {
162164 edition,
163165 )
164166 . map ( |( green_node, errors, _reparsed_range) | Parse {
165- green : green_node,
167+ green : Some ( green_node) ,
166168 errors : if errors. is_empty ( ) { None } else { Some ( errors. into ( ) ) } ,
167169 _ty : PhantomData ,
168170 } )
@@ -198,6 +200,27 @@ impl ast::Expr {
198200 }
199201}
200202
203+ impl < T > Drop for Parse < T > {
204+ fn drop ( & mut self ) {
205+ let Some ( green) = self . green . take ( ) else {
206+ return ;
207+ } ;
208+ static PARSE_DROP_THREAD : std:: sync:: OnceLock < std:: sync:: mpsc:: Sender < GreenNode > > =
209+ std:: sync:: OnceLock :: new ( ) ;
210+ PARSE_DROP_THREAD
211+ . get_or_init ( || {
212+ let ( sender, receiver) = std:: sync:: mpsc:: channel :: < GreenNode > ( ) ;
213+ std:: thread:: Builder :: new ( )
214+ . name ( "ParseNodeDropper" . to_owned ( ) )
215+ . spawn ( move || receiver. iter ( ) . for_each ( drop) )
216+ . unwrap ( ) ;
217+ sender
218+ } )
219+ . send ( green)
220+ . unwrap ( ) ;
221+ }
222+ }
223+
201224/// `SourceFile` represents a parse tree for a single Rust file.
202225pub use crate :: ast:: SourceFile ;
203226
0 commit comments