diff --git a/internal/core/adt/closed.go b/internal/core/adt/closed.go index b11fedbbb58..20b7db14618 100644 --- a/internal/core/adt/closed.go +++ b/internal/core/adt/closed.go @@ -180,6 +180,7 @@ func (c CloseInfo) SpawnEmbed(x Node) CloseInfo { mode: closeEmbed, root: EmbeddingSpan, span: c.span() | EmbeddingSpan, + decl: c.closeInfo.Decl(), } return c } @@ -193,6 +194,7 @@ func (c CloseInfo) SpawnGroup(x Expr) CloseInfo { parent: c.closeInfo, location: x, span: c.span(), + decl: c.closeInfo.Decl(), } return c } @@ -206,6 +208,7 @@ func (c CloseInfo) SpawnSpan(x Node, t SpanType) CloseInfo { location: x, root: t, span: c.span() | t, + decl: c.closeInfo.Decl(), } return c } @@ -228,6 +231,7 @@ func (c CloseInfo) SpawnRef(arc *Vertex, isDef bool, x Expr) CloseInfo { parent: c.closeInfo, location: x, span: span, + decl: c.closeInfo.Decl(), } } if isDef { @@ -294,6 +298,21 @@ type closeInfo struct { root SpanType span SpanType + + // decl is the parent declaration which contains the conjuct which + // gave rise to this closeInfo. + decl Decl +} + +// Returns the first non-nil Decl from c, or c's parents, if possible. +func (c *closeInfo) Decl() Decl { + for c != nil && c.decl == nil { + c = c.parent + } + if c == nil { + return nil + } + return c.decl } // closeStats holds the administrative fields for a closeInfo value. Each diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go index 9514091aa2b..e9b6bf8a8c3 100644 --- a/internal/core/adt/composite.go +++ b/internal/core/adt/composite.go @@ -1399,6 +1399,8 @@ func (v *Vertex) AddStruct(s *StructLit, env *Environment, ci CloseInfo) *Struct } if cc := ci.cc; cc != nil && cc.decl != nil { info.Decl = cc.decl + } else if decl := ci.closeInfo.Decl(); decl != nil { + info.Decl = decl } for _, t := range v.Structs { if *t == info { // TODO: check for different identity. diff --git a/internal/core/adt/comprehension.go b/internal/core/adt/comprehension.go index 2a64b274023..86759d8467a 100644 --- a/internal/core/adt/comprehension.go +++ b/internal/core/adt/comprehension.go @@ -160,6 +160,7 @@ func (n *nodeContext) insertComprehension( if !n.ctx.isDevVersion() { ci = ci.SpawnEmbed(c) ci.closeInfo.span |= ComprehensionSpan + ci.decl = c } var decls []Decl diff --git a/internal/core/adt/eval.go b/internal/core/adt/eval.go index 84f06c898bc..37879f93c18 100644 --- a/internal/core/adt/eval.go +++ b/internal/core/adt/eval.go @@ -2153,6 +2153,7 @@ func (n *nodeContext) addStruct( // TODO(perf): only do this if addExprConjunct below will result in // a fieldSet. Otherwise the entry will just be removed next. id := closeInfo.SpawnEmbed(x) + id.decl = x c := MakeConjunct(childEnv, x, id) n.addExprConjunct(c, partial)