fix(tvix/eval): inherit scope poisoning data in nested contexts
Scope poisoning must be inherited across lambda context boundaries, e.g. if an outer scope has a poisoned `null`, any lambdas defined on the same level must reference that poisoned identifier correctly. Change-Id: I1aac64e1c048a6f3bacadb6d78ed295fa439e8b4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6410 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									0a13d267f0
								
							
						
					
					
						commit
						5ee89bcf5c
					
				
					 4 changed files with 36 additions and 4 deletions
				
			
		|  | @ -53,6 +53,13 @@ impl LambdaCtx { | |||
|             scope: Default::default(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn inherit(&self) -> Self { | ||||
|         LambdaCtx { | ||||
|             lambda: Lambda::new_anonymous(), | ||||
|             scope: self.scope.inherit(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Alias for the map of globally available functions that should
 | ||||
|  | @ -836,9 +843,7 @@ impl Compiler<'_> { | |||
|     } | ||||
| 
 | ||||
|     fn compile_lambda(&mut self, slot: Option<LocalIdx>, node: ast::Lambda) { | ||||
|         // Open new lambda context in compiler, which has its own
 | ||||
|         // scope etc.
 | ||||
|         self.contexts.push(LambdaCtx::new()); | ||||
|         self.new_context(); | ||||
|         self.begin_scope(); | ||||
| 
 | ||||
|         // Compile the function itself
 | ||||
|  | @ -912,7 +917,7 @@ impl Compiler<'_> { | |||
|         N: AstNode + Clone, | ||||
|         F: FnOnce(&mut Compiler, &N, Option<LocalIdx>), | ||||
|     { | ||||
|         self.contexts.push(LambdaCtx::new()); | ||||
|         self.new_context(); | ||||
|         self.begin_scope(); | ||||
|         content(self, node, slot); | ||||
|         self.end_scope(node); | ||||
|  | @ -1011,10 +1016,14 @@ impl Compiler<'_> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Increase the scope depth of the current function (e.g. within
 | ||||
|     /// a new bindings block, or `with`-scope).
 | ||||
|     fn begin_scope(&mut self) { | ||||
|         self.scope_mut().scope_depth += 1; | ||||
|     } | ||||
| 
 | ||||
|     /// Decrease scope depth of the current function and emit
 | ||||
|     /// instructions to clean up the stack at runtime.
 | ||||
|     fn end_scope<N: AstNode>(&mut self, node: &N) { | ||||
|         debug_assert!(self.scope().scope_depth != 0, "can not end top scope"); | ||||
| 
 | ||||
|  | @ -1055,6 +1064,15 @@ impl Compiler<'_> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Open a new lambda context within which to compile a function,
 | ||||
|     /// closure or thunk.
 | ||||
|     fn new_context(&mut self) { | ||||
|         // This must inherit the scope-poisoning status of the parent
 | ||||
|         // in order for upvalue resolution to work correctly with
 | ||||
|         // poisoned identifiers.
 | ||||
|         self.contexts.push(self.context().inherit()); | ||||
|     } | ||||
| 
 | ||||
|     /// Declare a local variable known in the scope that is being
 | ||||
|     /// compiled by pushing it to the locals. This is used to
 | ||||
|     /// determine the stack offset of variables.
 | ||||
|  |  | |||
|  | @ -152,6 +152,15 @@ impl Scope { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Inherit scope details from a parent scope (required for
 | ||||
|     /// correctly nesting scopes in lambdas and thunks when special
 | ||||
|     /// scope features like poisoning are present).
 | ||||
|     pub fn inherit(&self) -> Self { | ||||
|         let mut scope = Self::default(); | ||||
|         scope.poisoned_tokens = self.poisoned_tokens.clone(); | ||||
|         scope | ||||
|     } | ||||
| 
 | ||||
|     /// Check whether a given token is poisoned.
 | ||||
|     pub fn is_poisoned(&self, name: &str) -> bool { | ||||
|         self.poisoned_tokens.contains_key(name) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue