Repository: goadesign/goa (go)

Issue:
Invalid View Mapper Generated For Anonymous Child Attributes
go version: 1.14.3
goa version: v3.1.3 (I checked my go.sum file, and it is actually pulling this version in to my project as well)

I am trying to define some anonymous child attribute types to avoid making a few one-off type definitions, and I think I uncovered a bug. If instead of using an anonymous inner type in the attribute definition, and just use a type I define with `Type("something", func() { etc }` then it works as expected and doesn't generate errors (which is the way I'll go with it for now).

First, here's my simple repro scenario:

Service definition:
```
package goa

import (
	. "goa.design/goa/v3/dsl"
)

var _ = Service("repro", func() {
	Method("DoIt", func() {
		Result(result)
		HTTP(func() {
			POST("/repro")
			Response(StatusOK)
		})
	})
})

var result = ResultType("application/vnd.config.reproResult", func() {
	TypeName("ReproResult")

	Attribute("parent", func() {
		Attribute("child", String)
		Required("child")
	})
})
```

API definition:
```
package goa

import (
	. "goa.design/goa/v3/dsl"
)

var _ = API("ReproAPI", func(){
	Version("1.0.0")

	Server("Repro Server", func() {
		Services("repro")
		Host("localhost", func() { URI("http://localhost/")})
	})
})
```

When I run `goa gen` then `go vet ./...` then I get the following error:
```
# pathstuffhere/pkg/gen/repro
pkg/gen/repro/service.go:73:15: cannot use &struct { Child string } literal (type *struct { Child string }) as type *struct { Child *string } in assignment
pkg/gen/repro/service.go:76:4: cannot use &res.Parent.Child (type *string) as type string in field value
```

The generated code, indeed, seems not to be assigning to the anonymous struct type correctly in `gen/repro/service.go`:
```
// newReproResultView projects result type ReproResult to projected type
// ReproResultView using the "default" view.
func newReproResultView(res *ReproResult) *reproviews.ReproResultView {
	vres := &reproviews.ReproResultView{}
	if res.Parent != nil {
		vres.Parent = &struct {
			Child string
		}{
			Child: &res.Parent.Child,
		}
	}
	return vres
}
```

Note, if I remove the `Required` directive from the inner-most `child` attribute, then re-generation and running `go vet` yields a new problem with the generated code:
```
# somepath/pkg/gen/http/repro/server
vet: pkg/gen/http/repro/server/types.go:29:17: cannot use &(struct{Child *string} literal) (value of type *struct{Child *string}) as *struct{Child *string "form:\"child,omitempty\" json:\"child,omitempty\" xml:\"child,omitempty\""} value in assignment
# somepath/pkg/gen/http/cli/repro_server
vet: pkg/gen/http/cli/repro_server/cli.go:264:9: undeclared name: attributec
```

The generated code in this case in gen/repro/server/types.go:
```
// NewDoItResponseBody builds the HTTP response body from the result of the
// "DoIt" endpoint of the "repro" service.
func NewDoItResponseBody(res *reproviews.ReproResultView) *DoItResponseBody {
	body := &DoItResponseBody{}
	if res.Parent != nil {
		body.Parent = &struct {
			Child *string
		}{
			Child: res.Parent.Child,
		}
	}
	return body
}
```

Explicitly adding a default view to the result type also results in some problems:
```
	View("default", func() {
		Attribute("parent")
	})
```

generated output causes `go vet` errors:
```
pkg/gen/repro/service.go:73:15: cannot use &struct { Child string } literal (type *struct { Child string }) as type *struct { Child *string } in assignment
pkg/gen/repro/service.go:76:4: cannot use &res.Parent.Child (type *string) as type string in field value
```

Pull request:
Properly handle inline object results
Fix #2592

Patch:
diff --git a/codegen/go_transform.go b/codegen/go_transform.go
index a82652c6..a603ee7b 100644
--- a/codegen/go_transform.go
+++ b/codegen/go_transform.go
@@ -176,7 +176,8 @@ func transformObject(source, target *expr.AttributeExpr, sourceVar, targetVar st
 	if newVar {
 		assign = ":="
 	}
-	buffer.WriteString(fmt.Sprintf("%s %s %s%s{%s}\n", targetVar, assign, deref, ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg), initCode))
+	name := ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
+	buffer.WriteString(fmt.Sprintf("%s %s %s%s{%s}\n", targetVar, assign, deref, name, initCode))
 	buffer.WriteString(postInitCode)
 
 	// iterate through attributes to initialize rest of the struct fields and
@@ -443,8 +444,8 @@ func transformHelperName(source, target *expr.AttributeExpr, ta *TransformAttrs)
 		prefix string
 	)
 	{
-		sname = Goify(ta.SourceCtx.Scope.Name(source, ta.SourceCtx.Pkg), true)
-		tname = Goify(ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg), true)
+		sname = Goify(ta.SourceCtx.Scope.Name(source, ta.SourceCtx.Pkg, ta.SourceCtx.Pointer, ta.SourceCtx.UseDefault), true)
+		tname = Goify(ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault), true)
 		prefix = ta.Prefix
 		if prefix == "" {
 			prefix = "transform"
diff --git a/codegen/service/service.go b/codegen/service/service.go
index 461aa606..b61a92b7 100644
--- a/codegen/service/service.go
+++ b/codegen/service/service.go
@@ -173,7 +173,7 @@ func errorName(et *UserTypeData) string {
 	if obj != nil {
 		for _, att := range *obj {
 			if _, ok := att.Attribute.Meta["struct:error:name"]; ok {
-				return fmt.Sprintf("e.%s", codegen.Goify(att.Name, true))
+				return fmt.Sprintf("e.%s", codegen.GoifyAtt(att.Attribute, att.Name, true))
 			}
 		}
 	}
diff --git a/codegen/service/service_data.go b/codegen/service/service_data.go
index def040f5..82edc82c 100644
--- a/codegen/service/service_data.go
+++ b/codegen/service/service_data.go
@@ -1510,12 +1510,12 @@ func buildConstructorCode(src, tgt *expr.AttributeExpr, sourceVar, targetVar str
 		"ArgVar":       sourceVar,
 		"ReturnVar":    targetVar,
 		"IsCollection": arr != nil,
-		"TargetType":   targetCtx.Scope.Name(tgt, targetCtx.Pkg),
+		"TargetType":   targetCtx.Scope.Name(tgt, targetCtx.Pkg, targetCtx.Pointer, targetCtx.UseDefault),
 	}
 
 	if arr != nil {
 		// result type collection
-		init := "new" + targetCtx.Scope.Name(arr.ElemType, "")
+		init := "new" + targetCtx.Scope.Name(arr.ElemType, "", targetCtx.Pointer, targetCtx.UseDefault)
 		if view != "" && view != expr.DefaultView {
 			init += codegen.Goify(view, true)
 		}
@@ -1552,13 +1552,13 @@ func buildConstructorCode(src, tgt *expr.AttributeExpr, sourceVar, targetVar str
 	data["Code"] = code
 
 	if view != "" {
-		data["InitName"] = targetCtx.Scope.Name(src, "")
+		data["InitName"] = targetCtx.Scope.Name(src, "", targetCtx.Pointer, targetCtx.UseDefault)
 	}
 	fields := make([]map[string]interface{}, 0, len(*targetRTs))
 	// iterate through the result types found in the target and add the
 	// code to initialize them
 	for _, nat := range *targetRTs {
-		finit := "new" + targetCtx.Scope.Name(nat.Attribute, "")
+		finit := "new" + targetCtx.Scope.Name(nat.Attribute, "", targetCtx.Pointer, targetCtx.UseDefault)
 		if view != "" {
 			v := ""
 			if vatt := rt.View(view).AttributeExpr.Find(nat.Name); vatt != nil {
diff --git a/codegen/transformer.go b/codegen/transformer.go
index a388b561..a7483fb4 100644
--- a/codegen/transformer.go
+++ b/codegen/transformer.go
@@ -11,13 +11,14 @@ type (
 	// generation.
 	Attributor interface {
 		Scoper
-		// Name generates a valid name for the given attribute type.
-		Name(att *expr.AttributeExpr, pkg string) string
+		// Name generates a valid name for the given attribute type. ptr and
+		// useDefault are used to generate inline struct type definitions.
+		Name(att *expr.AttributeExpr, pkg string, ptr, useDefault bool) string
 		// Ref generates a valid reference to the given attribute type.
 		Ref(att *expr.AttributeExpr, pkg string) string
 		// Field generates a valid data structure field identifier for the given
-		// attribute and field name. If firstUpper is true the field name's first
-		// letter is capitalized.
+		// attribute and field name. If firstUpper is true then the field name
+		// first letter is capitalized.
 		Field(att *expr.AttributeExpr, name string, firstUpper bool) string
 	}
 
@@ -229,7 +230,14 @@ func (a *AttributeContext) Dup() *AttributeContext {
 }
 
 // Name returns the type name for the given attribute.
-func (a *AttributeScope) Name(att *expr.AttributeExpr, pkg string) string {
+func (a *AttributeScope) Name(att *expr.AttributeExpr, pkg string, ptr, useDefault bool) string {
+	if _, ok := att.Type.(expr.UserType); !ok && expr.IsObject(att.Type) {
+		// In the special case of anonymous / inline struct types the "name" is
+		// in fact the struct typedef. In this case we need to force the
+		// generation of the fields as pointers if needed as the default
+		// GoTransform algorithm does not allow for an override.
+		return a.scope.GoTypeDef(att, ptr, useDefault)
+	}
 	return a.scope.GoFullTypeName(att, pkg)
 }
 
diff --git a/codegen/validation.go b/codegen/validation.go
index 749540ab..ad6dff88 100644
--- a/codegen/validation.go
+++ b/codegen/validation.go
@@ -198,7 +198,8 @@ func recurseValidationCode(att *expr.AttributeExpr, attCtx *AttributeContext, re
 				return recurseValidationCode(ut.Attribute(), ctx, true, tgt, context+suf, seen).String()
 			} else if hasValidations(attCtx, ut) {
 				var buf bytes.Buffer
-				data := map[string]interface{}{"name": Goify(attCtx.Scope.Name(att, ctx.Pkg), true), "target": tgt}
+				name := attCtx.Scope.Name(att, ctx.Pkg, ctx.Pointer, ctx.UseDefault)
+				data := map[string]interface{}{"name": Goify(name, true), "target": tgt}
 				if err := userValT.Execute(&buf, data); err != nil {
 					panic(err) // bug
 				}
@@ -317,7 +318,8 @@ func recurseAttribute(att *expr.AttributeExpr, attCtx *AttributeContext, nat *ex
 			if expr.IsPrimitive(nat.Attribute.Type) {
 				buf.Write(recurseValidationCode(ut.Attribute(), attCtx, att.IsRequired(nat.Name), tgt, context, seen).Bytes())
 			} else {
-				if err := userValT.Execute(&buf, map[string]interface{}{"name": Goify(attCtx.Scope.Name(nat.Attribute, attCtx.Pkg), true), "target": tgt}); err != nil {
+				name := attCtx.Scope.Name(nat.Attribute, attCtx.Pkg, attCtx.Pointer, attCtx.UseDefault)
+				if err := userValT.Execute(&buf, map[string]interface{}{"name": Goify(name, true), "target": tgt}); err != nil {
 					panic(err) // bug
 				}
 			}
diff --git a/expr/attribute.go b/expr/attribute.go
index b18dfad9..e445d040 100644
--- a/expr/attribute.go
+++ b/expr/attribute.go
@@ -533,6 +533,11 @@ func (a *AttributeExpr) debug(prefix string, seen map[*AttributeExpr]int, indent
 	if v := a.Validation; v != nil {
 		v.Debug(indent + 1)
 	}
+	if t, ok := a.Type.(UserType); ok {
+		if v := t.Attribute().Validation; v != nil {
+			v.Debug(indent + 1)
+		}
+	}
 }
 
 // validateEnumDefault makes sure that the attribute default value is one of the
diff --git a/expr/method.go b/expr/method.go
index fc41b1af..b2b3f0f3 100644
--- a/expr/method.go
+++ b/expr/method.go
@@ -305,7 +305,6 @@ func (m *MethodExpr) Finalize() {
 	} else if len(m.Requirements) == 0 && len(m.Service.Requirements) > 0 {
 		m.Requirements = copyReqs(m.Service.Requirements)
 	}
-
 }
 
 // IsStreaming determines whether the method streams payload or result.
diff --git a/grpc/codegen/protobuf.go b/grpc/codegen/protobuf.go
index 20b03e15..e026c826 100644
--- a/grpc/codegen/protobuf.go
+++ b/grpc/codegen/protobuf.go
@@ -18,7 +18,7 @@ type (
 )
 
 // Name returns the protocol buffer type name.
-func (p *protoBufScope) Name(att *expr.AttributeExpr, pkg string) string {
+func (p *protoBufScope) Name(att *expr.AttributeExpr, pkg string, ptr, useDefault bool) string {
 	return protoBufGoFullTypeName(att, pkg, p.scope)
 }
 
diff --git a/grpc/codegen/protobuf_transform.go b/grpc/codegen/protobuf_transform.go
index b6b8ba5c..6ae88429 100644
--- a/grpc/codegen/protobuf_transform.go
+++ b/grpc/codegen/protobuf_transform.go
@@ -101,7 +101,8 @@ func transformAttribute(source, target *expr.AttributeExpr, sourceVar, targetVar
 
 	if err := codegen.IsCompatible(source.Type, target.Type, sourceVar, targetVar); err != nil {
 		if ta.proto {
-			initCode += fmt.Sprintf("%s := &%s{}\n", targetVar, ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg))
+			name := ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
+			initCode += fmt.Sprintf("%s := &%s{}\n", targetVar, name)
 			targetVar += ".Field"
 			newVar = false
 			target = unwrapAttr(expr.DupAtt(target))
@@ -208,7 +209,7 @@ func transformObject(source, target *expr.AttributeExpr, sourceVar, targetVar st
 	if newVar {
 		assign = ":="
 	}
-	tname := ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg)
+	tname := ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
 	buffer.WriteString(fmt.Sprintf("%s %s %s%s{%s}\n", targetVar, assign, deref, tname, initCode))
 	buffer.WriteString(postInitCode)
 
@@ -227,7 +228,7 @@ func transformObject(source, target *expr.AttributeExpr, sourceVar, targetVar st
 		{
 			if err = codegen.IsCompatible(srcc.Type, tgtc.Type, "", ""); err != nil {
 				if ta.proto {
-					ta.targetInit = ta.TargetCtx.Scope.Name(tgtc, ta.TargetCtx.Pkg)
+					ta.targetInit = ta.TargetCtx.Scope.Name(tgtc, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
 					tgtc = unwrapAttr(tgtc)
 				} else {
 					srcc = unwrapAttr(srcc)
@@ -344,7 +345,7 @@ func transformArray(source, target *expr.Array, sourceVar, targetVar string, new
 	tgt := target.ElemType
 	if err = codegen.IsCompatible(src.Type, tgt.Type, "[0]", "[0]"); err != nil {
 		if ta.proto {
-			ta.targetInit = ta.TargetCtx.Scope.Name(tgt, ta.TargetCtx.Pkg)
+			ta.targetInit = ta.TargetCtx.Scope.Name(tgt, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
 			tgt = unwrapAttr(expr.DupAtt(tgt))
 		} else {
 			src = unwrapAttr(expr.DupAtt(src))
@@ -414,7 +415,7 @@ func transformMap(source, target *expr.Map, sourceVar, targetVar string, newVar
 	tgt := target.ElemType
 	if err = codegen.IsCompatible(src.Type, tgt.Type, "[*]", "[*]"); err != nil {
 		if ta.proto {
-			ta.targetInit = ta.TargetCtx.Scope.Name(tgt, ta.TargetCtx.Pkg)
+			ta.targetInit = ta.TargetCtx.Scope.Name(tgt, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault)
 			tgt = unwrapAttr(expr.DupAtt(tgt))
 		} else {
 			src = unwrapAttr(expr.DupAtt(src))
@@ -680,8 +681,8 @@ func transformHelperName(source, target *expr.AttributeExpr, ta *transformAttrs)
 		prefix string
 	)
 	{
-		sname = codegen.Goify(ta.SourceCtx.Scope.Name(source, ta.SourceCtx.Pkg), true)
-		tname = codegen.Goify(ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg), true)
+		sname = codegen.Goify(ta.SourceCtx.Scope.Name(source, ta.SourceCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault), true)
+		tname = codegen.Goify(ta.TargetCtx.Scope.Name(target, ta.TargetCtx.Pkg, ta.TargetCtx.Pointer, ta.TargetCtx.UseDefault), true)
 		prefix = ta.Prefix
 	}
 	return codegen.Goify(prefix+sname+"To"+tname, false)
diff --git a/grpc/codegen/service_data.go b/grpc/codegen/service_data.go
index bf3b5d35..9df7673c 100644
--- a/grpc/codegen/service_data.go
+++ b/grpc/codegen/service_data.go
@@ -874,7 +874,7 @@ func buildResponseConvertData(response, result *expr.AttributeExpr, svcCtx *code
 			data.Description = fmt.Sprintf("%s builds the gRPC response type from the result of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name)
 		}
 		return &ConvertData{
-			SrcName: svcCtx.Scope.Name(result, svcCtx.Pkg),
+			SrcName: svcCtx.Scope.Name(result, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 			SrcRef:  svcCtx.Scope.Ref(result, svcCtx.Pkg),
 			TgtName: protoBufGoFullTypeName(response, sd.PkgName, sd.Scope),
 			TgtRef:  protoBufGoFullTypeRef(response, sd.PkgName, sd.Scope),
@@ -925,7 +925,7 @@ func buildResponseConvertData(response, result *expr.AttributeExpr, svcCtx *code
 	return &ConvertData{
 		SrcName:    protoBufGoFullTypeName(response, sd.PkgName, sd.Scope),
 		SrcRef:     protoBufGoFullTypeRef(response, sd.PkgName, sd.Scope),
-		TgtName:    svcCtx.Scope.Name(result, svcCtx.Pkg),
+		TgtName:    svcCtx.Scope.Name(result, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 		TgtRef:     svcCtx.Scope.Ref(result, svcCtx.Pkg),
 		Init:       data,
 		Validation: addValidation(response, sd, false),
@@ -985,7 +985,7 @@ func buildInitData(source, target *expr.AttributeExpr, sourceVar, targetVar stri
 				&InitArgData{
 					Name:     sourceVar,
 					Ref:      sourceVar,
-					TypeName: srcCtx.Scope.Name(source, srcCtx.Pkg),
+					TypeName: srcCtx.Scope.Name(source, srcCtx.Pkg, srcCtx.Pointer, srcCtx.UseDefault),
 					TypeRef:  srcCtx.Scope.Ref(source, srcCtx.Pkg),
 					Example:  source.Example(expr.Root.API.Random()),
 				},
@@ -1053,7 +1053,7 @@ func buildErrorConvertData(ge *expr.GRPCErrorExpr, e *expr.GRPCEndpointExpr, sd
 			data.Description = fmt.Sprintf("%s builds the gRPC error response type from the error of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name)
 		}
 		return &ConvertData{
-			SrcName: svcCtx.Scope.Name(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg),
+			SrcName: svcCtx.Scope.Name(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 			SrcRef:  svcCtx.Scope.Ref(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg),
 			TgtName: protoBufGoFullTypeName(ge.Response.Message, sd.PkgName, sd.Scope),
 			TgtRef:  protoBufGoFullTypeRef(ge.Response.Message, sd.PkgName, sd.Scope),
@@ -1072,7 +1072,7 @@ func buildErrorConvertData(ge *expr.GRPCErrorExpr, e *expr.GRPCEndpointExpr, sd
 	return &ConvertData{
 		SrcName:    protoBufGoFullTypeName(ge.Response.Message, sd.PkgName, sd.Scope),
 		SrcRef:     protoBufGoFullTypeRef(ge.Response.Message, sd.PkgName, sd.Scope),
-		TgtName:    svcCtx.Scope.Name(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg),
+		TgtName:    svcCtx.Scope.Name(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 		TgtRef:     svcCtx.Scope.Ref(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg),
 		Init:       data,
 		Validation: addValidation(ge.Response.Message, sd, false),
@@ -1118,7 +1118,7 @@ func buildStreamData(e *expr.GRPCEndpointExpr, sd *ServiceData, svr bool) *Strea
 				sendName = md.ServerStream.SendName
 				sendRef = ed.ResultRef
 				sendType = &ConvertData{
-					SrcName: resCtx.Scope.Name(result, resCtx.Pkg),
+					SrcName: resCtx.Scope.Name(result, resCtx.Pkg, resCtx.Pointer, resCtx.UseDefault),
 					SrcRef:  resCtx.Scope.Ref(result, resCtx.Pkg),
 					TgtName: protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope),
 					TgtRef:  protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope),
@@ -1131,7 +1131,7 @@ func buildStreamData(e *expr.GRPCEndpointExpr, sd *ServiceData, svr bool) *Strea
 				recvType = &ConvertData{
 					SrcName:    protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope),
 					SrcRef:     protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope),
-					TgtName:    svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg),
+					TgtName:    svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 					TgtRef:     recvRef,
 					Init:       buildInitData(e.StreamingRequest, e.MethodExpr.StreamingPayload, "v", "spayload", svcCtx, false, sd),
 					Validation: addValidation(e.StreamingRequest, sd, true),
@@ -1147,7 +1147,7 @@ func buildStreamData(e *expr.GRPCEndpointExpr, sd *ServiceData, svr bool) *Strea
 				sendName = md.ClientStream.SendName
 				sendRef = svcCtx.Scope.Ref(e.MethodExpr.StreamingPayload, svcCtx.Pkg)
 				sendType = &ConvertData{
-					SrcName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg),
+					SrcName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg, svcCtx.Pointer, svcCtx.UseDefault),
 					SrcRef:  sendRef,
 					TgtName: protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope),
 					TgtRef:  protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope),
@@ -1160,7 +1160,7 @@ func buildStreamData(e *expr.GRPCEndpointExpr, sd *ServiceData, svr bool) *Strea
 				recvType = &ConvertData{
 					SrcName:    protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope),
 					SrcRef:     protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope),
-					TgtName:    resCtx.Scope.Name(result, resCtx.Pkg),
+					TgtName:    resCtx.Scope.Name(result, resCtx.Pkg, resCtx.Pointer, resCtx.UseDefault),
 					TgtRef:     resCtx.Scope.Ref(result, resCtx.Pkg),
 					Init:       buildInitData(e.Response.Message, result, "v", resVar, resCtx, false, sd),
 					Validation: addValidation(e.Response.Message, sd, false),
diff --git a/http/codegen/server.go b/http/codegen/server.go
index 93b8d334..a728ec9b 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -833,7 +833,7 @@ const requestElementsT = `{{- define "request_elements" }}
 {{- end }}
 
 {{- range .Cookies }}
-	c, err = r.Cookie("{{ .Name }}")
+	c, {{ if not .Required }}_{{ else }}err{{ end }} = r.Cookie("{{ .Name }}")
 	{{- if and (or (eq .Type.Name "string") (eq .Type.Name "any")) .Required }}
 		if err == http.ErrNoCookie {
 			err = goa.MergeErrors(err, goa.MissingFieldError("{{ .Name }}", "cookie"))
diff --git a/http/codegen/service_data.go b/http/codegen/service_data.go
index 3c482cb9..ab4e1889 100644
--- a/http/codegen/service_data.go
+++ b/http/codegen/service_data.go
@@ -990,7 +990,12 @@ func buildPayloadData(e *expr.HTTPEndpointExpr, sd *ServiceData) *PayloadData {
 				sd.ServerTypeNames[serverBodyData.Name] = false
 				sd.ClientTypeNames[serverBodyData.Name] = false
 			}
-			mustValidate = len(cookiesData) > 0
+			for _, p := range cookiesData {
+				if p.Required || p.Validate != "" || needConversion(p.Type) {
+					mustValidate = true
+					break
+				}
+			}
 			if !mustValidate {
 				for _, p := range paramsData {
 					if p.Validate != "" || needConversion(p.Type) {
@@ -1556,9 +1561,10 @@ func buildResponses(e *expr.HTTPEndpointExpr, result *expr.AttributeExpr, viewed
 							//   validation logic can be applied.
 							// * user type - we unmarshal the client response body to the
 							//   corresponding type in the service package after validating the
-							//   response body. Here, the transformation code must rely that the
-							//   required attributes are set in the response body (otherwise
-							//   validation would fail).
+							//   response body. Here, the transformation code must
+							//   rely on the fact that the required attributes are
+							//   set in the response body (otherwise validation
+							//   would fail).
 							code, helpers, err = unmarshal(resp.Body, resAttr, "body", "v", httpclictx, svcctx)
 							if err == nil {
 								sd.ClientTransformHelpers = codegen.AppendHelpers(sd.ClientTransformHelpers, helpers)
@@ -1908,6 +1914,9 @@ func buildRequestBodyType(body, att *expr.AttributeExpr, e *expr.HTTPEndpointExp
 	{
 		name = body.Type.Name()
 		ref = sd.Scope.GoTypeRef(body)
+
+		AddMarshalTags(body, make(map[string]struct{}))
+
 		if ut, ok := body.Type.(expr.UserType); ok {
 			varname = codegen.Goify(ut.Name(), true)
 			def = goTypeDef(sd.Scope, ut.Attribute(), svr, !svr)
@@ -2047,6 +2056,8 @@ func buildResponseBodyType(body, att *expr.AttributeExpr, e *expr.HTTPEndpointEx
 		ref = sd.Scope.GoTypeRef(body)
 		mustInit = att.Type != expr.Empty && needInit(body.Type)
 
+		AddMarshalTags(body, make(map[string]struct{}))
+
 		if ut, ok := body.Type.(expr.UserType); ok {
 			// response body is a user type.
 			varname = codegen.Goify(ut.Name(), true)
@@ -2591,6 +2602,33 @@ func needConversion(dt expr.DataType) bool {
 	}
 }
 
+// AddMarshalTags adds JSON, XML and Form tags to all inline object attributes recursively.
+func AddMarshalTags(att *expr.AttributeExpr, seen map[string]struct{}) {
+	if !expr.IsObject(att.Type) {
+		return
+	}
+	if ut, ok := att.Type.(expr.UserType); ok {
+		if _, ok := seen[ut.Hash()]; ok {
+			return // avoid infinite recursions
+		}
+		seen[ut.Hash()] = struct{}{}
+		for _, att := range *(expr.AsObject(att.Type)) {
+			AddMarshalTags(att.Attribute, seen)
+		}
+		return
+	}
+	// inline object
+	for _, natt := range *(expr.AsObject(att.Type)) {
+		if natt.Attribute.Meta == nil {
+			natt.Attribute.Meta = expr.MetaExpr{}
+		}
+		ns := []string{natt.Name}
+		natt.Attribute.Meta["struct:tag:form"] = ns
+		natt.Attribute.Meta["struct:tag:json"] = ns
+		natt.Attribute.Meta["struct:tag:xml"] = ns
+	}
+}
+
 // needInit returns true if and only if the given type is or makes use of user
 // types.
 func needInit(dt expr.DataType) bool {


Test patch:
diff --git a/codegen/service/service_test.go b/codegen/service/service_test.go
index 7bb94380..a591dc78 100644
--- a/codegen/service/service_test.go
+++ b/codegen/service/service_test.go
@@ -30,6 +30,7 @@ func TestService(t *testing.T) {
 		{"result-with-result-collection", testdata.ResultWithResultCollectionMethodDSL, testdata.ResultWithResultCollectionMethod},
 		{"service-level-error", testdata.ServiceErrorDSL, testdata.ServiceError},
 		{"custom-errors", testdata.CustomErrorsDSL, testdata.CustomErrors},
+		{"custom-errors-custom-field", testdata.CustomErrorsCustomFieldDSL, testdata.CustomErrorsCustomField},
 		{"force-generate-type", testdata.ForceGenerateTypeDSL, testdata.ForceGenerateType},
 		{"force-generate-type-explicit", testdata.ForceGenerateTypeExplicitDSL, testdata.ForceGenerateTypeExplicit},
 		{"streaming-result", testdata.StreamingResultMethodDSL, testdata.StreamingResultMethod},
diff --git a/codegen/service/testdata/service_code.go b/codegen/service/testdata/service_code.go
index 39f84649..7c9090cd 100644
--- a/codegen/service/testdata/service_code.go
+++ b/codegen/service/testdata/service_code.go
@@ -362,6 +362,38 @@ func (e *Result) ErrorName() string {
 }
 `
 
+const CustomErrorsCustomField = `
+// Service is the CustomErrorsCustomFields service interface.
+type Service interface {
+	// A implements A.
+	A(context.Context) (err error)
+}
+
+// ServiceName is the name of the service as defined in the design. This is the
+// same value that is set in the endpoint request contexts under the ServiceKey
+// key.
+const ServiceName = "CustomErrorsCustomFields"
+
+// MethodNames lists the service method names as defined in the design. These
+// are the same values that are set in the endpoint request contexts under the
+// MethodKey key.
+var MethodNames = [1]string{"A"}
+
+type GoaError struct {
+	ErrorCode string
+}
+
+// Error returns an error description.
+func (e *GoaError) Error() string {
+	return ""
+}
+
+// ErrorName returns "GoaError".
+func (e *GoaError) ErrorName() string {
+	return e.ErrorCode
+}
+`
+
 const MultipleMethodsResultMultipleViews = `
 // Service is the MultipleMethodsResultMultipleViews service interface.
 type Service interface {
diff --git a/codegen/service/testdata/service_dsls.go b/codegen/service/testdata/service_dsls.go
index 70af7e6f..5a856106 100644
--- a/codegen/service/testdata/service_dsls.go
+++ b/codegen/service/testdata/service_dsls.go
@@ -149,6 +149,21 @@ var CustomErrorsDSL = func() {
 	})
 }
 
+var CustomErrorsCustomFieldDSL = func() {
+	var Result = ResultType("application/vnd.goa.error", func() {
+		Attribute("error", String, func() {
+			Meta("struct:error:name")
+			Meta("struct:field:name", "ErrorCode")
+		})
+		Required("error")
+	})
+	Service("CustomErrorsCustomFields", func() {
+		Method("A", func() {
+			Error("struct_error_name", Result, "struct error name description")
+		})
+	})
+}
+
 var MultipleMethodsResultMultipleViewsDSL = func() {
 	var RTWithViews = ResultType("application/vnd.result.multiple.views", func() {
 		TypeName("MultipleViews")
diff --git a/http/codegen/client_body_types_test.go b/http/codegen/client_body_types_test.go
index 8149035f..f2b9a2aa 100644
--- a/http/codegen/client_body_types_test.go
+++ b/http/codegen/client_body_types_test.go
@@ -45,6 +45,7 @@ func TestBodyTypeInit(t *testing.T) {
 		{"body-path-user-validate", testdata.PayloadBodyPathUserValidateDSL, 2, BodyPathUserValidateInitCode},
 		{"body-primitive-array-user-validate", testdata.PayloadBodyPrimitiveArrayUserValidateDSL, 2, BodyPrimitiveArrayUserValidateInitCode},
 		{"result-body-user", testdata.ResultBodyObjectHeaderDSL, 2, ResultBodyObjectHeaderInitCode},
+		{"result-body-inline-object", testdata.ResultBodyInlineObjectDSL, 2, ResultBodyInlineObjectInitCode},
 		{"result-explicit-body-primitive", testdata.ExplicitBodyPrimitiveResultMultipleViewsDSL, 1, ExplicitBodyPrimitiveResultMultipleViewsInitCode},
 		{"result-explicit-body-user-type", testdata.ExplicitBodyUserResultMultipleViewsDSL, 3, ExplicitBodyUserResultMultipleViewsInitCode},
 		{"result-explicit-body-object", testdata.ExplicitBodyUserResultObjectDSL, 3, ExplicitBodyObjectInitCode},
@@ -185,6 +186,23 @@ func NewMethodBodyObjectHeaderResultOK(body *MethodBodyObjectHeaderResponseBody,
 }
 `
 
+const ResultBodyInlineObjectInitCode = `// NewMethodBodyInlineObjectResultTypeNoContent builds a
+// "ServiceBodyInlineObject" service "MethodBodyInlineObject" endpoint result
+// from a HTTP "NoContent" response.
+func NewMethodBodyInlineObjectResultTypeNoContent(body *MethodBodyInlineObjectResponseBody) *servicebodyinlineobject.ResultType {
+	v := &servicebodyinlineobject.ResultType{}
+	if body.Parent != nil {
+		v.Parent = &struct {
+			Child *string
+		}{
+			Child: body.Parent.Child,
+		}
+	}
+
+	return v
+}
+`
+
 const ExplicitBodyPrimitiveResultMultipleViewsInitCode = `// NewMethodExplicitBodyPrimitiveResultMultipleViewResulttypemultipleviewsOK
 // builds a "ServiceExplicitBodyPrimitiveResultMultipleView" service
 // "MethodExplicitBodyPrimitiveResultMultipleView" endpoint result from a HTTP
diff --git a/http/codegen/server_encode_test.go b/http/codegen/server_encode_test.go
index 2fdfea71..f994543b 100644
--- a/http/codegen/server_encode_test.go
+++ b/http/codegen/server_encode_test.go
@@ -62,6 +62,7 @@ func TestEncode(t *testing.T) {
 		{"body-primitive-array-string", testdata.ResultBodyPrimitiveArrayStringDSL, testdata.ResultBodyPrimitiveArrayStringEncodeCode},
 		{"body-primitive-array-bool", testdata.ResultBodyPrimitiveArrayBoolDSL, testdata.ResultBodyPrimitiveArrayBoolEncodeCode},
 		{"body-primitive-array-user", testdata.ResultBodyPrimitiveArrayUserDSL, testdata.ResultBodyPrimitiveArrayUserEncodeCode},
+		{"body-inline-object", testdata.ResultBodyInlineObjectDSL, testdata.ResultBodyInlineObjectEncodeCode},
 
 		{"body-header-object", testdata.ResultBodyHeaderObjectDSL, testdata.ResultBodyHeaderObjectEncodeCode},
 		{"body-header-user", testdata.ResultBodyHeaderUserDSL, testdata.ResultBodyHeaderUserEncodeCode},
diff --git a/http/codegen/testdata/payload_decode_functions.go b/http/codegen/testdata/payload_decode_functions.go
index 0bd80a94..dbc13d12 100644
--- a/http/codegen/testdata/payload_decode_functions.go
+++ b/http/codegen/testdata/payload_decode_functions.go
@@ -3416,11 +3416,10 @@ var PayloadCookieStringDecodeCode = `// DecodeMethodCookieStringRequest returns
 func DecodeMethodCookieStringRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
 	return func(r *http.Request) (interface{}, error) {
 		var (
-			c2  *string
-			err error
-			c   *http.Cookie
+			c2 *string
+			c  *http.Cookie
 		)
-		c, err = r.Cookie("c")
+		c, _ = r.Cookie("c")
 		var c2Raw string
 		if c != nil {
 			c2Raw = c.Value
@@ -3428,9 +3427,6 @@ func DecodeMethodCookieStringRequest(mux goahttp.Muxer, decoder func(*http.Reque
 		if c2Raw != "" {
 			c2 = &c2Raw
 		}
-		if err != nil {
-			return nil, err
-		}
 		payload := NewMethodCookieStringPayload(c2)
 
 		return payload, nil
@@ -3447,7 +3443,7 @@ func DecodeMethodCookieStringValidateRequest(mux goahttp.Muxer, decoder func(*ht
 			err error
 			c   *http.Cookie
 		)
-		c, err = r.Cookie("c")
+		c, _ = r.Cookie("c")
 		var c2Raw string
 		if c != nil {
 			c2Raw = c.Value
@@ -3540,11 +3536,10 @@ var PayloadCookieStringDefaultDecodeCode = `// DecodeMethodCookieStringDefaultRe
 func DecodeMethodCookieStringDefaultRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
 	return func(r *http.Request) (interface{}, error) {
 		var (
-			c2  string
-			err error
-			c   *http.Cookie
+			c2 string
+			c  *http.Cookie
 		)
-		c, err = r.Cookie("c")
+		c, _ = r.Cookie("c")
 		var c2Raw string
 		if c != nil {
 			c2Raw = c.Value
@@ -3554,9 +3549,6 @@ func DecodeMethodCookieStringDefaultRequest(mux goahttp.Muxer, decoder func(*htt
 		} else {
 			c2 = "def"
 		}
-		if err != nil {
-			return nil, err
-		}
 		payload := NewMethodCookieStringDefaultPayload(c2)
 
 		return payload, nil
@@ -3574,7 +3566,7 @@ func DecodeMethodCookieStringDefaultValidateRequest(mux goahttp.Muxer, decoder f
 			err error
 			c   *http.Cookie
 		)
-		c, err = r.Cookie("c")
+		c, _ = r.Cookie("c")
 		var c2Raw string
 		if c != nil {
 			c2Raw = c.Value
diff --git a/http/codegen/testdata/result_dsls.go b/http/codegen/testdata/result_dsls.go
index 35694cd2..19b1bbd2 100644
--- a/http/codegen/testdata/result_dsls.go
+++ b/http/codegen/testdata/result_dsls.go
@@ -1039,6 +1039,22 @@ var ResultBodyPrimitiveArrayUserDSL = func() {
 	})
 }
 
+var ResultBodyInlineObjectDSL = func() {
+	var ResultType = Type("ResultType", func() {
+		Attribute("parent", func() {
+			Attribute("child")
+		})
+	})
+	Service("ServiceBodyInlineObject", func() {
+		Method("MethodBodyInlineObject", func() {
+			Result(ResultType)
+			HTTP(func() {
+				POST("/")
+			})
+		})
+	})
+}
+
 var ResultBodyHeaderObjectDSL = func() {
 	Service("ServiceBodyHeaderObject", func() {
 		Method("MethodBodyHeaderObject", func() {
diff --git a/http/codegen/testdata/result_encode_functions.go b/http/codegen/testdata/result_encode_functions.go
index ae251708..9502fb12 100644
--- a/http/codegen/testdata/result_encode_functions.go
+++ b/http/codegen/testdata/result_encode_functions.go
@@ -866,6 +866,19 @@ func EncodeMethodBodyPrimitiveArrayUserResponse(encoder func(context.Context, ht
 }
 `
 
+var ResultBodyInlineObjectEncodeCode = `// EncodeMethodBodyInlineObjectResponse returns an encoder for responses
+// returned by the ServiceBodyInlineObject MethodBodyInlineObject endpoint.
+func EncodeMethodBodyInlineObjectResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
+	return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
+		res := v.(*servicebodyinlineobject.ResultType)
+		enc := encoder(ctx, w)
+		body := NewMethodBodyInlineObjectResponseBody(res)
+		w.WriteHeader(http.StatusNoContent)
+		return enc.Encode(body)
+	}
+}
+`
+
 var ResultBodyHeaderObjectEncodeCode = `// EncodeMethodBodyHeaderObjectResponse returns an encoder for responses
 // returned by the ServiceBodyHeaderObject MethodBodyHeaderObject endpoint.
 func EncodeMethodBodyHeaderObjectResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {