Closed verdverm closed 3 years ago
at https://github.com/cuelang/cue/blob/master/internal/core/adt/context.go#L660
adding the following to the empty switch case resolves the issue and does not seem to break my usage / output. Not sure if that is correct or if node should really never be nil at this point...
if node == nil {
return emptyNode
}
I'm not entirely clear what you did to produce this panic.
I cue eval
'd one of my mega configs at that commit. https://github.com/hofstadter-io/hofmod-server or _saas repo repro. Haven't found a minimal example yet...
Could you try it with tip again? There have been some significant changes in the code so the stack trace won't say much anymore and the problem may have been fixed.
Thanks!
Sure, was just reading some of them on Gerrit that seem to be the ones your merged. I think I'm actually following those CL's a bit!
I somehow think these won't fix it though. There is something fishy. The marker should only be obtainable from node
, which then cannot be nil. So if that is the case, it must have been returned by getDefault
, which should never happen. So I must be missing something. (Or evalState
, which is even worse.)
So would be good where this StructMarker is coming from, assuming it is not node.Value
. That is the issue.
Also, are you using it through the API or is this produced by the cue tool?
produced by both, repro'd with cue exclusively
Interesting. Looked at the code but will be hard to figure it out unless I know where the StructMarker is coming from. So if you can trace that back that would be great. Basically, a StructMarker should never be returned by any function.
Something like the check here for the StructMarker case? Is that the condition we want to find the source of? ( I am seeing them both print many times, always together )
(also happy to run through delve and the input with a screen schare, ping me on slack)
func (c *OpContext) node(x Expr, scalar bool) *Vertex {
v := c.evalState(x, EvaluatingArcs)
v, ok := c.getDefault(v, scalar)
if !ok {
// Error already generated by getDefault.
return emptyNode
}
node, ok := v.(*Vertex)
if ok {
v = node.Value
}
switch nv := v.(type) {
case nil:
c.addErrf(IncompleteError, pos(x), "incomplete value %s", c.Str(x))
return emptyNode
case *Bottom:
c.AddBottom(nv)
return emptyNode
case *ListMarker:
// fmt.Println("case: *ListMarker")
case *StructMarker:
if !ok {
fmt.Println("case: *StructMarker", )
if node == nil {
fmt.Println("nil StructMarker", )
return emptyNode
}
}
default:
if v.Kind()&StructKind != 0 {
c.addErrf(IncompleteError, pos(x),
"incomplete feed source value %s (type %s)",
x.Source(), v.Kind())
return emptyNode
} else if !ok {
c.addErrf(0, pos(x), // TODO(error): better message.
"invalid operand %s (found %s, want list or struct)",
x.Source(), v.Kind())
return emptyNode
}
}
return node.Default()
}
adding a case to getDefault
...
func (c *OpContext) getDefault(v Value, scalar bool) (result Value, ok bool) {
var d *Disjunction
switch x := v.(type) {
default:
return v, true
// This always prints with the two prints in the last comment
case *StructMarker:
fmt.Println("STRUCT")
return v, true
case *Vertex:
// TODO: return vertex if not disjunction.
switch t := x.Value.(type) {
case *Disjunction:
d = t
case *StructMarker, *ListMarker:
return v, true
case *Vertex:
return c.getDefault(t, scalar)
default:
if !scalar {
return v, true
}
return t, true
}
case *Disjunction:
d = x
}
if d.NumDefaults != 1 {
c.addErrf(IncompleteError, c.pos(),
"unresolved disjunction %s (type %s)", c.Str(d), d.Kind())
return nil, false
}
return c.getDefault(d.Values[0], scalar)
}
This is always printing as well
func (c *OpContext) node(x Expr, scalar bool) *Vertex {
v := c.evalState(x, EvaluatingArcs)
switch v.(type) {
case *StructMarker:
fmt.Println("evalState return StructMarker")
}
v, ok := c.getDefault(v, scalar)
if !ok {
// Error already generated by getDefault.
return emptyNode
}
....
Good to know. So evalState
is returning a StructMarker when it shouldn't. Will take a look.
I will have a solution: I'm making the markers different types so that the compiler will enforce correctness.
See these three CLs: remote: https://cue-review.googlesource.com/c/cue/+/7764 internal/core/adt: add methods for concreteness [NEW] remote: https://cue-review.googlesource.com/c/cue/+/7765 internal/core/adt: introduce base value type [NEW] remote: https://cue-review.googlesource.com/c/cue/+/7766 internal/core/adt: automatic renaming
These make ListMarker and StructMarker a separate type, to the point that functions that return or pass them to the adt.Expr or adt.Value types. There are some casts left, but these are much more localized.
I ran into some funky stuff. Didn't seem too critical, but I can imagine it could have led to your issue. So hopefully it is gone now.
This issue has been migrated to https://github.com/cue-lang/cue/issues/598.
For more details about CUE's migration to a new home, please see https://github.com/cue-lang/cue/issues/1078.
What version of CUE are you using (
cue version
)?master @ 6c49cf0
the previous commit(s) do not have this panic
fmt.Printf("nil node: %# v\n", v)