cue icon indicating copy to clipboard operation
cue copied to clipboard

Multi-package evaluation doesn't become concrete with v3 evaluator

Open rd-niklas-gergs opened this issue 3 weeks ago • 3 comments

What version of CUE are you using (cue version)?

Reproduced (but likely not limited) with 0.15.1 and 0.14.2:

cue version (devel)

CUE language version v0.15.1

Go version go1.25.4
      -buildmode exe
       -compiler gc
       -trimpath true
  DefaultGODEBUG containermaxprocs=0,decoratemappings=0,tlssha1=1,updatemaxprocs=0,x509sha256skid=0
     CGO_ENABLED 1
          GOARCH arm64
            GOOS darwin
         GOARM64 v8.0
cue version v0.14.2

go version go1.24.8
      -buildmode exe
       -compiler gc
       -trimpath true
     CGO_ENABLED 0
          GOARCH arm64
            GOOS darwin
         GOARM64 v8.0
cue.lang.version v0.14.2

Does this issue reproduce with the latest stable release?

Yes

What did you do?

To reproduce this a cue module with multi packages is needed. Let's call the module test.test with a schema and one root package. The content of the schema package is:

package schema

#Key: {
        key: string
}

#Value: {
        value: string
}

close({dict: close({[string]: #Key | #Value})})

And in the main.cue package we try to use it:

import "test.test/schema"

result: schema

result: dict: hello: {
        key: "world"
}

What did you expect to see?

I expect cue export main.cue to output:

{
    "result": {
        "dict": {
            "hello": {
                "key": "world"
            }
        }
    }
}

What did you see instead?

result.dict.hello: incomplete value {key:"world"} | {key:"world",value:string}

V3 evaluator

The expected behavior can be observed with v0.14.2 by setting CUE_EXPERIMENT = "evalv3=0".

rd-niklas-gergs avatar Nov 27 '25 09:11 rd-niklas-gergs

Reduced as follows:

env CUE_EXPERIMENT=evalv3=0
exec cue-v0.14.2 export

env CUE_EXPERIMENT=
exec cue export

-- cue.mod/module.cue --
module: "foo.test/main"
language: version: "v0.14.0"

-- input.cue --
package main

import "foo.test/main/imported"

out: imported
out: either: foo: "world"

-- imported/imported.cue --
package imported

#Foo: foo: _
#Bar: bar: _

{either: #Foo | #Bar}

As of d2bed8db0c1e0f51d71a778568d0d10839d14441:

> env CUE_EXPERIMENT=evalv3=0
> exec cue-v0.14.2 export
[stdout]
{
    "out": {
        "either": {
            "foo": "world"
        }
    }
}
> env CUE_EXPERIMENT=
> exec cue export
[stderr]
out.either: incomplete value {foo:"world"} | {foo:"world",bar:_}
[exit status 1]

I have failed to reduce this to a single file so far.

mvdan avatar Nov 27 '25 15:11 mvdan

I can say that, for now, you can avoid this by not using the top-level package value, so e.g. using schema.#Schema rather than schema.

mvdan avatar Nov 27 '25 15:11 mvdan

Bisected the evalv3 regression to 6746a8260338954609b4efaaf771810c75a06547.

mvdan avatar Nov 27 '25 15:11 mvdan