internal/core/compile: fix alias resolution bug
Fixes #495
Change-Id: Ia8a4b0972e036cd970f921046d5a436f7a8e413e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7267
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/basicrewrite/aliases/aliases.txtar b/cue/testdata/basicrewrite/aliases/aliases.txtar
new file mode 100644
index 0000000..fb1d760
--- /dev/null
+++ b/cue/testdata/basicrewrite/aliases/aliases.txtar
@@ -0,0 +1,34 @@
+-- in.cue --
+t0: {
+ a=_a: _
+ let _b = a
+ _out: _b
+}
+t1: {
+ _a: b
+ let b = c
+ c=d: 3
+}
+-- out/compile --
+--- in.cue
+{
+ t0: {
+ _a: _
+ _out: ă0;let _bă
+ }
+ t1: {
+ _a: ă0;let bă
+ d: 3
+ }
+}
+-- out/eval --
+(struct){
+ t0: (struct){
+ _a: (_){ _ }
+ _out: (_){ _ }
+ }
+ t1: (struct){
+ _a: (int){ 3 }
+ d: (int){ 3 }
+ }
+}
diff --git a/internal/core/compile/compile.go b/internal/core/compile/compile.go
index 2e7d406..e261193 100644
--- a/internal/core/compile/compile.go
+++ b/internal/core/compile/compile.go
@@ -166,6 +166,15 @@
return nil
}
+func (c *compiler) updateAlias(id *ast.Ident, expr adt.Expr) {
+ k := len(c.stack) - 1
+ m := c.stack[k].aliases
+
+ x := m[id.Name]
+ x.expr = expr
+ m[id.Name] = x
+}
+
// lookupAlias looks up an alias with the given name at the k'th stack position.
func (c compiler) lookupAlias(k int, id *ast.Ident) aliasEntry {
m := c.stack[k].aliases
@@ -441,6 +450,9 @@
func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) {
for _, d := range a {
+ c.markAlias(d)
+ }
+ for _, d := range a {
c.addLetDecl(d)
}
for _, d := range a {
@@ -450,6 +462,30 @@
}
}
+func (c *compiler) markAlias(d ast.Decl) {
+ switch x := d.(type) {
+ case *ast.Field:
+ lab := x.Label
+ if a, ok := lab.(*ast.Alias); ok {
+ if _, ok = a.Expr.(ast.Label); !ok {
+ c.errf(a, "alias expression is not a valid label")
+ }
+
+ e := aliasEntry{source: a}
+
+ c.insertAlias(a.Ident, e)
+ }
+
+ case *ast.LetClause:
+ a := aliasEntry{source: x}
+ c.insertAlias(x.Ident, a)
+
+ case *ast.Alias:
+ a := aliasEntry{source: x}
+ c.insertAlias(x.Ident, a)
+ }
+}
+
func (c *compiler) decl(d ast.Decl) adt.Decl {
switch x := d.(type) {
case *ast.BadDecl:
@@ -462,18 +498,12 @@
return c.errf(a, "alias expression is not a valid label")
}
- e := aliasEntry{source: a}
-
switch lab.(type) {
case *ast.Ident, *ast.BasicLit, *ast.ListLit:
// Even though we won't need the alias, we still register it
// for duplicate and failed reference detection.
default:
- e.expr = c.expr(a.Expr)
- }
-
- if err := c.insertAlias(a.Ident, e); err != nil {
- return err
+ c.updateAlias(a.Ident, c.expr(a.Expr))
}
}
@@ -576,19 +606,13 @@
// blowup in x2: x1+x1, x3: x2+x2, ... patterns.
expr := c.labeledExpr(nil, (*letScope)(x), x.Expr)
-
- a := aliasEntry{source: x, expr: expr}
-
- c.insertAlias(x.Ident, a)
+ c.updateAlias(x.Ident, expr)
case *ast.Alias:
+ // TODO(legacy): deprecated, remove this use of Alias
expr := c.labeledExpr(nil, (*deprecatedAliasScope)(x), x.Expr)
-
- // TODO(legacy): deprecated, remove this use of Alias
- a := aliasEntry{source: x, expr: expr}
-
- c.insertAlias(x.Ident, a)
+ c.updateAlias(x.Ident, expr)
}
}