cue: don't extract embedded values

Only non-value expressions are extracted.

Change-Id: Iecbcc66036cea68acf0679ef1a6d9a647bba4672
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9861
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cue/types.go b/cue/types.go
index 3502e4a..32af926 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -2392,6 +2392,10 @@
 		ctx := v.ctx()
 		for _, d := range x.Decls {
 			switch x := d.(type) {
+			default:
+				fields = append(fields, d)
+			case adt.Value:
+				fields = append(fields, d)
 			case adt.Expr:
 				// embedding
 				n := &adt.Vertex{Label: v.v.Label}
@@ -2400,9 +2404,6 @@
 				n.Finalize(ctx)
 				n.Parent = v.v.Parent
 				a = append(a, makeValue(v.idx, n, v.parent_))
-
-			default:
-				fields = append(fields, d)
 			}
 		}
 		if len(a) == 0 {
@@ -2414,9 +2415,16 @@
 			n := &adt.Vertex{
 				Label: v.v.Label,
 			}
-			c := adt.MakeRootConjunct(env, &adt.StructLit{
-				Decls: fields,
-			})
+			s := &adt.StructLit{}
+			if k := v.v.Kind(); k != adt.StructKind && k != BottomKind {
+				// TODO: we should also add such a declaration for embeddings
+				// of structs with definitions. However, this is currently
+				// also not supported at the CUE level. If we do, it may be
+				// best handled with a special mode of unification.
+				s.Decls = append(s.Decls, &adt.BasicType{K: k})
+			}
+			s.Decls = append(s.Decls, fields...)
+			c := adt.MakeRootConjunct(env, s)
 			n.AddConjunct(c)
 			n.Finalize(ctx)
 			n.Parent = v.v.Parent
diff --git a/cue/types_test.go b/cue/types_test.go
index c792e27..ba1494d 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -3331,9 +3331,19 @@
 		input: `v: "Hello, \(x)! Welcome to \(place)", place: string, x: string`,
 		want:  `\()("Hello, " .(〈〉 "x") "! Welcome to " .(〈〉 "place") "")`,
 	}, {
+		// Split out the reference, but ensure the split-off outer struct
+		// remains valid.
+		input: `v: { a, #b: 1 }, a: 2`,
+		want:  `&(.(〈〉 "a") {int,#b:1})`,
+	}, {
+		// Result is an error, no need to split off.
 		input: `v: { a, b: 1 }, a: 2`,
 		want:  `&(.(〈〉 "a") {b:1})`,
 	}, {
+		// Don't split of concrete values.
+		input: `v: { "foo", #def: 1 }`,
+		want:  `{"foo",#def:1}`,
+	}, {
 		input: `v: { {c: a}, b: a }, a: int`,
 		want:  `&({c:a} {b:a})`,
 	}, {