}
switch p.tok {
- case token.ADD, token.SUB, token.NOT, token.XOR, token.AND:
+ case token.ADD, token.SUB, token.NOT, token.XOR, token.AND, token.TILDE:
pos, op := p.pos, p.tok
p.next()
x := p.parseUnaryExpr()
// Single-expression type parameter lists and those that don't start
// with a (type parameter) name are considered array sizes.
-// The term must be a valid expression (it could be a type - and then
-// a type-checker will complain - but we don't allow ~ in the expr).
-// TODO(rfindley): Improve error recover here. In these cases go/parser error
-// recovery is worse than cmd/compile/internal/syntax, and unnecessary type
-// declarations had to be inserted to force synchronization.
-type _[t] t
-type _[~ /* ERROR "expected operand" */ t] t
-type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser
-type _[t|t] t
-type _[~ /* ERROR "expected operand" */ t|t] t
-type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser
-type _[t| ~ /* ERROR "expected operand" */ t] t
-type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser
-type _[~ /* ERROR "expected operand" */ t|~t] t
-type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser
+// The term must be a valid expression (it could be a type incl. a
+// tilde term) but the type-checker will complain.
+type (
+ _[t] t
+ _[t|t] t
+
+ // These are invalid and the type-checker will complain.
+ _[~t] t
+ _[~t|t] t
+ _[t|~t] t
+ _[~t|~t] t
+)
type _[_ t, t /* ERROR "type parameters must be named" */ ] t
type _[_ ~t, t /* ERROR "type parameters must be named" */ ] t
x.typ = ch.elem
check.hasCallOrRecv = true
return
+
+ case token.TILDE:
+ // Provide a better error position and message than what check.op below could do.
+ check.error(e, _UndefinedOp, "cannot use ~ outside of interface or type constraint")
+ x.mode = invalid
+ return
}
if !check.op(unaryOpPredicates, x, e.Op) {
_ = -g /* ERROR 2-valued g */ ()
_ = <-g /* ERROR 2-valued g */ ()
}
+
+// ~ is accepted as unary operator only permitted in interface type elements
+var (
+ _ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ 0
+ _ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ "foo"
+ _ = ~ /* ERROR cannot use ~ outside of interface or type constraint */ i0
+)
type _[P *struct /* ERROR "expected expression" */ {}| int /* ERROR "not an expression" */ ] struct{}
// The following fails to parse, due to the '~'
-type _[P *struct /* ERROR "expected expression" */ {}|~ /* ERROR "expected operand" */ int] struct{}
-
-// This is fragile: 'var' synchronizes the parser, and we absorb the rest of the errors.
-var /* ERROR "expected ']'" */ _ /* ERROR "value or type" */
+type _[P *struct /* ERROR "expected expression" */ {}|~int /* ERROR "not an expression" */ ] struct{}