Skip to content

Commit cd15a48

Browse files
committed
[dev.typeparams] cmd/compile/internal/types2: correct error position for inherited const init expression
Enabled fixedbugs/issue8183.go for run.go with new typechecker now that issue is fixed. Fixes #42992. Updates #42991. Change-Id: I23451999983b740d5f37ce3fa75ee756daf1a44f Reviewed-on: https://go-review.googlesource.com/c/go/+/275517 Trust: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 02820d6 commit cd15a48

File tree

7 files changed

+72
-16
lines changed

7 files changed

+72
-16
lines changed

src/cmd/compile/internal/types2/check.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type context struct {
5151
scope *Scope // top-most scope for lookups
5252
pos syntax.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
5353
iota constant.Value // value of iota in a constant declaration; nil otherwise
54+
errpos syntax.Pos // if valid, identifier position of a constant with inherited initializer
5455
sig *Signature // function signature if inside a function; nil otherwise
5556
isPanic map[*syntax.CallExpr]bool // set of panic call expressions (used for termination check)
5657
hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions

src/cmd/compile/internal/types2/decl.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func (check *Checker) objDecl(obj Object, def *Named) {
187187
switch obj := obj.(type) {
188188
case *Const:
189189
check.decl = d // new package-level const decl
190-
check.constDecl(obj, d.vtyp, d.init)
190+
check.constDecl(obj, d.vtyp, d.init, d.inherited)
191191
case *Var:
192192
check.decl = d // new package-level var decl
193193
check.varDecl(obj, d.lhs, d.vtyp, d.init)
@@ -421,12 +421,16 @@ func firstInSrc(path []Object) int {
421421
return fst
422422
}
423423

424-
func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr) {
424+
func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited bool) {
425425
assert(obj.typ == nil)
426426

427-
// use the correct value of iota
428-
defer func(iota constant.Value) { check.iota = iota }(check.iota)
427+
// use the correct value of iota and errpos
428+
defer func(iota constant.Value, errpos syntax.Pos) {
429+
check.iota = iota
430+
check.errpos = errpos
431+
}(check.iota, check.errpos)
429432
check.iota = obj.val
433+
check.errpos = nopos
430434

431435
// provide valid constant value under all circumstances
432436
obj.val = constant.MakeUnknown()
@@ -449,6 +453,15 @@ func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr) {
449453
// check initialization
450454
var x operand
451455
if init != nil {
456+
if inherited {
457+
// The initialization expression is inherited from a previous
458+
// constant declaration, and (error) positions refer to that
459+
// expression and not the current constant declaration. Use
460+
// the constant identifier position for any errors during
461+
// init expression evaluation since that is all we have
462+
// (see issues #42991, #42992).
463+
check.errpos = obj.pos
464+
}
452465
check.expr(&x, init)
453466
}
454467
check.initConst(obj, &x)
@@ -898,7 +911,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
898911
init = values[i]
899912
}
900913

901-
check.constDecl(obj, last.Type, init)
914+
check.constDecl(obj, last.Type, init, inherited)
902915
}
903916

904917
// Constants must always have init values.

src/cmd/compile/internal/types2/errors.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ func (check *Checker) err(pos syntax.Pos, msg string, soft bool) {
8787
return
8888
}
8989

90+
// If we are encountering an error while evaluating an inherited
91+
// constant initialization expression, pos is the position of in
92+
// the original expression, and not of the currently declared
93+
// constant identifier. Use the provided errpos instead.
94+
// TODO(gri) We may also want to augment the error message and
95+
// refer to the position (pos) in the original expression.
96+
if check.errpos.IsKnown() {
97+
assert(check.iota != nil)
98+
pos = check.errpos
99+
}
100+
90101
err := Error{pos, stripAnnotations(msg), msg, soft}
91102
if check.firstErr == nil {
92103
check.firstErr = err

src/cmd/compile/internal/types2/resolver.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ import (
1717

1818
// A declInfo describes a package-level const, type, var, or func declaration.
1919
type declInfo struct {
20-
file *Scope // scope of file containing this declaration
21-
lhs []*Var // lhs of n:1 variable declarations, or nil
22-
vtyp syntax.Expr // type, or nil (for const and var declarations only)
23-
init syntax.Expr // init/orig expression, or nil (for const and var declarations only)
24-
tdecl *syntax.TypeDecl // type declaration, or nil
25-
fdecl *syntax.FuncDecl // func declaration, or nil
20+
file *Scope // scope of file containing this declaration
21+
lhs []*Var // lhs of n:1 variable declarations, or nil
22+
vtyp syntax.Expr // type, or nil (for const and var declarations only)
23+
init syntax.Expr // init/orig expression, or nil (for const and var declarations only)
24+
inherited bool // if set, the init expression is inherited from a previous constant declaration
25+
tdecl *syntax.TypeDecl // type declaration, or nil
26+
fdecl *syntax.FuncDecl // func declaration, or nil
2627

2728
// The deps field tracks initialization expression dependencies.
2829
deps map[Object]bool // lazily initialized
@@ -338,7 +339,7 @@ func (check *Checker) collectObjects() {
338339
init = values[i]
339340
}
340341

341-
d := &declInfo{file: fileScope, vtyp: last.Type, init: init}
342+
d := &declInfo{file: fileScope, vtyp: last.Type, init: init, inherited: inherited}
342343
check.declarePkgObj(name, obj, d)
343344
}
344345

src/cmd/compile/internal/types2/testdata/constdecl.src

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,35 @@ func _() {
104104
const x, y, z = 0, 1, unsafe.Sizeof(func() { _ = x /* ERROR "undeclared name" */ + y /* ERROR "undeclared name" */ + z /* ERROR "undeclared name" */ })
105105
}
106106

107+
// Test cases for errors in inherited constant initialization expressions.
108+
// Errors related to inherited initialization expressions must appear at
109+
// the constant identifier being declared, not at the original expression
110+
// (issues #42991, #42992).
111+
const (
112+
_ byte = 255 + iota
113+
/* some gap */
114+
_ // ERROR overflows byte
115+
/* some gap */
116+
/* some gap */ _ /* ERROR overflows byte */; _ /* ERROR overflows byte */
117+
/* some gap */
118+
_ = 255 + iota
119+
_ = byte /* ERROR overflows byte */ (255) + iota
120+
_ /* ERROR overflows byte */
121+
)
122+
123+
// Test cases from issue.
124+
const (
125+
ok = byte(iota + 253)
126+
bad
127+
barn
128+
bard // ERROR cannot convert
129+
)
130+
131+
const (
132+
c = len([1 - iota]int{})
133+
d
134+
e // ERROR invalid array length
135+
f // ERROR invalid array length
136+
)
137+
107138
// TODO(gri) move extra tests from testdata/const0.src into here

test/fixedbugs/issue8183.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ const (
1212
ok = byte(iota + 253)
1313
bad
1414
barn
15-
bard // ERROR "constant 256 overflows byte"
15+
bard // ERROR "constant 256 overflows byte|cannot convert"
1616
)
1717

1818
const (
1919
c = len([1 - iota]int{})
2020
d
21-
e // ERROR "array bound must be non-negative"
22-
f // ERROR "array bound must be non-negative"
21+
e // ERROR "array bound must be non-negative|invalid array length"
22+
f // ERROR "array bound must be non-negative|invalid array length"
2323
)

test/run.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2132,5 +2132,4 @@ var excluded = map[string]bool{
21322132
"fixedbugs/issue7746.go": true, // type-checking doesn't terminate
21332133
"fixedbugs/issue8501.go": true, // crashes
21342134
"fixedbugs/issue8507.go": true, // crashes
2135-
"fixedbugs/issue8183.go": true, // issue #42992
21362135
}

0 commit comments

Comments
 (0)