From 42ecf39e85a6960f4e0c2272bf9aff491eda3b66 Mon Sep 17 00:00:00 2001 From: ChrisALiles Date: Mon, 26 Feb 2018 15:35:48 +1100 Subject: [PATCH] cmd/compile: improve compiler error on embedded structs Fixes #23609 Change-Id: I751aae3d849de7fce1306324fcb1a4c3842d873e Reviewed-on: https://go-review.googlesource.com/97076 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/typecheck.go | 13 +++++++++++- test/fixedbugs/issue23609.go | 27 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue23609.go diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index a1653d0e7f2..47a8a429442 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3114,7 +3114,18 @@ func typecheckcomplit(n *Node) *Node { if ci := lookdot1(nil, l.Sym, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup. yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym) } else { - yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t) + p, _ := dotpath(l.Sym, t, nil, true) + if p == nil { + yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t) + continue + } + // dotpath returns the parent embedded types in reverse order. + var ep []string + for ei := len(p) - 1; ei >= 0; ei-- { + ep = append(ep, p[ei].field.Type.Sym.Name) + } + ep = append(ep, l.Sym.Name) + yyerror("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), t) } continue } diff --git a/test/fixedbugs/issue23609.go b/test/fixedbugs/issue23609.go new file mode 100644 index 00000000000..7c17a98d32d --- /dev/null +++ b/test/fixedbugs/issue23609.go @@ -0,0 +1,27 @@ +// errorcheck + +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type t1 struct { + t1f1 int + t1f2 int +} +type t2 struct { + t2f1 int + t2f2 int + t1 +} +type t3 struct { + t3f1 int + t2 +} + +var ( + _ = t2{t1f1: 600} // ERROR "cannot use promoted field t1.t1f1 in struct literal of type t2" + _ = t3{t1f2: 800} // ERROR "cannot use promoted field t2.t1.t1f2 in struct literal of type t3" + _ = t3{t2f1: 900} // ERROR "cannot use promoted field t2.t2f1 in struct literal of type t3" +)