fix(tvix/eval): consider let ... inherit ...
in dynamic scopes
In conditions where no dynamic identifiers exist in a scope, inheriting is usually a no-op - *unless* the identifier is not statically known and the scope has a non-empty `with`-stack. Change-Id: Iff4138d9cd4c56e844bc574203708dacc11c3f73 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6264 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
parent
c3b13416b0
commit
2023b8e33f
3 changed files with 40 additions and 3 deletions
|
@ -667,13 +667,34 @@ impl Compiler {
|
|||
for inherit in node.inherits() {
|
||||
match inherit.from() {
|
||||
// Within a `let` binding, inheriting from the outer
|
||||
// scope is practically a no-op.
|
||||
None => {
|
||||
// scope is a no-op *if* the identifier can be
|
||||
// statically resolved.
|
||||
None if self.scope().with_stack.is_empty() => {
|
||||
self.emit_warning(inherit.syntax().clone(), WarningKind::UselessInherit);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
None => {
|
||||
for ident in inherit.idents() {
|
||||
// If the identifier resolves statically, it
|
||||
// has precedence over dynamic bindings, and
|
||||
// the inherit is useless.
|
||||
if self
|
||||
.resolve_local(ident.ident_token().unwrap().text())
|
||||
.is_some()
|
||||
{
|
||||
self.emit_warning(ident.syntax().clone(), WarningKind::UselessInherit);
|
||||
continue;
|
||||
}
|
||||
|
||||
self.compile_ident(ident.clone());
|
||||
self.declare_local(
|
||||
ident.syntax().clone(),
|
||||
ident.ident_token().unwrap().text(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Some(from) => {
|
||||
for ident in inherit.idents() {
|
||||
self.compile(from.expr().unwrap());
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,15 @@
|
|||
# Normally using an `inherit` without a source attribute set within a
|
||||
# `let` is a no-op, *unless* there is a with in-scope that might
|
||||
# provide the value.
|
||||
|
||||
# Provide a dynamic `x` identifier in the scope.
|
||||
with ({ x = 1;});
|
||||
|
||||
# inherit this `x` as a static identifier
|
||||
let inherit x;
|
||||
|
||||
# Provide another dynamic `x` identifier
|
||||
in with ({ x = 3; });
|
||||
|
||||
# Inherited static identifier should have precedence
|
||||
x
|
Loading…
Reference in a new issue