Skip to content

Commit 09ada1a

Browse files
griesemergopherbot
authored andcommitted
cmd/compile/internal/syntax: parser to accept ~x as unary expression
Accept ~x as ordinary unary expression in the parser but recognize such expressions as invalid in the type checker. This change opens the door to recognizing complex type constraint literals such as `*E|~int` in `[P *E|~int]` and parse them correctly instead of reporting a parse error because `P*E|~int` syntactically looks like an incorrect array length expression (binary expression where the RHS of | is an invalid unary expression ~int). As a result, the parser is more forgiving with expressions but the type checker will reject invalid uses as before. We could pass extra information into the binary/unary expression parse functions to prevent the use of ~ in invalid situations but it doesn't seem worth the trouble. In fact it may be advantageous to allow a more liberal expression syntax especially in the presence of errors (better parser synchronization after an error). Preparation for fixing #49482. Change-Id: I119e8bd9445dfa6460fcd7e0658e3554a34b2769 Reviewed-on: https://go-review.googlesource.com/c/go/+/402255 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]>
1 parent e845750 commit 09ada1a

File tree

6 files changed

+24
-9
lines changed

6 files changed

+24
-9
lines changed

src/cmd/compile/internal/syntax/parser.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ func (p *parser) unaryExpr() Expr {
827827
switch p.tok {
828828
case _Operator, _Star:
829829
switch p.op {
830-
case Mul, Add, Sub, Not, Xor:
830+
case Mul, Add, Sub, Not, Xor, Tilde:
831831
x := new(Operation)
832832
x.pos = p.pos()
833833
x.Op = p.op

src/cmd/compile/internal/syntax/testdata/typeset.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,17 @@ func _[_ t[t] | t[t]]() {}
6565

6666
// Single-expression type parameter lists and those that don't start
6767
// with a (type parameter) name are considered array sizes.
68-
// The term must be a valid expression (it could be a type - and then
69-
// a type-checker will complain - but we don't allow ~ in the expr).
68+
// The term must be a valid expression (it could be a type incl. a
69+
// tilde term) but the type-checker will complain.
7070
type (
7171
_[t] t
72-
_[/* ERROR unexpected ~ */ ~t] t
7372
_[t|t] t
74-
_[/* ERROR unexpected ~ */ ~t|t] t
75-
_[t| /* ERROR unexpected ~ */ ~t] t
76-
_[/* ERROR unexpected ~ */ ~t|~t] t
73+
74+
// These are invalid and the type-checker will complain.
75+
_[~t] t
76+
_[~t|t] t
77+
_[t|~t] t
78+
_[~t|~t] t
7779
)
7880

7981
type (

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

+6
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) {
208208
x.typ = ch.elem
209209
check.hasCallOrRecv = true
210210
return
211+
212+
case syntax.Tilde:
213+
// Provide a better error position and message than what check.op below could do.
214+
check.error(e, "cannot use ~ outside of interface or type constraint")
215+
x.mode = invalid
216+
return
211217
}
212218

213219
if !check.op(unaryOpPredicates, x, e.Op) {

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

+7
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,10 @@ func _() {
178178
_ = -g /* ERROR 2-valued g */ ()
179179
_ = <-g /* ERROR 2-valued g */ ()
180180
}
181+
182+
// ~ is accepted as unary operator only permitted in interface type elements
183+
var (
184+
_ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ 0
185+
_ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ "foo"
186+
_ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ i0
187+
)

src/cmd/compile/internal/types2/testdata/fixedbugs/issue49482.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ type _[P /* ERROR non-function P */ (*int)] int
2222
type _[P *struct /* ERROR "not an expression" */ {}| int /* ERROR "not an expression" */ ] struct{}
2323

2424
// The following fails to parse, due to the '~'
25-
type _[P *struct /* ERROR "not an expression" */ {}|~ /* ERROR "unexpected ~" */ int] struct{}
25+
type _[P *struct /* ERROR "not an expression" */ {}|~int /* ERROR "not an expression" */ ] struct{}

test/fixedbugs/issue23587.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
package p
88

99
func _(x int) {
10-
_ = ~x // ERROR "unexpected ~"
10+
_ = ~x // unary ~ permitted but the type-checker will complain
1111
}
1212

1313
func _(x int) {

0 commit comments

Comments
 (0)