go/ast: add Unparen(Expr) helper

Fixes #60061

Change-Id: If1bc03f9367620c9ea8702bfd4648020d5ab52ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/495315
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Alan Donovan 2023-05-16 13:33:15 -04:00
parent af0609b080
commit e201ff2b98
6 changed files with 18 additions and 31 deletions

1
api/next/60061.txt Normal file
View file

@ -0,0 +1 @@
pkg go/ast, func Unparen(Expr) Expr #60061

View file

@ -1110,3 +1110,14 @@ func generator(file *File) (string, bool) {
}
return "", false
}
// Unparen returns the expression with any enclosing parentheses removed.
func Unparen(e Expr) Expr {
for {
paren, ok := e.(*ParenExpr)
if !ok {
return e
}
e = paren.X
}
}

View file

@ -1654,14 +1654,6 @@ func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
return &ast.CompositeLit{Type: typ, Lbrace: lbrace, Elts: elts, Rbrace: rbrace}
}
// If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
func unparen(x ast.Expr) ast.Expr {
if p, isParen := x.(*ast.ParenExpr); isParen {
x = unparen(p.X)
}
return x
}
func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr {
if p.trace {
defer un(trace(p, "PrimaryExpr"))
@ -1706,7 +1698,7 @@ func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr {
case token.LBRACE:
// operand may have returned a parenthesized complit
// type; accept it but complain if we have a complit
t := unparen(x)
t := ast.Unparen(x)
// determine if '{' belongs to a composite literal or a block statement
switch t.(type) {
case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr:
@ -1949,7 +1941,7 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
func (p *parser) parseCallExpr(callType string) *ast.CallExpr {
x := p.parseRhs() // could be a conversion: (some type)(x)
if t := unparen(x); t != x {
if t := ast.Unparen(x); t != x {
p.error(x.Pos(), fmt.Sprintf("expression in %s must not be parenthesized", callType))
x = t
}

View file

@ -234,7 +234,7 @@ func (r *resolver) walkExprs(list []ast.Expr) {
func (r *resolver) walkLHS(list []ast.Expr) {
for _, expr := range list {
expr := unparen(expr)
expr := ast.Unparen(expr)
if _, ok := expr.(*ast.Ident); !ok && expr != nil {
ast.Walk(r, expr)
}

View file

@ -1127,7 +1127,7 @@ func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
// checkExpr checks that x is an expression (and not a type).
func (p *parser) checkExpr(x ast.Expr) ast.Expr {
switch t := unparen(x).(type) {
switch t := ast.Unparen(x).(type) {
case *ast.BadExpr:
case *ast.Ident:
case *ast.BasicLit:
@ -1200,18 +1200,10 @@ func deref(x ast.Expr) ast.Expr {
return x
}
// If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
func unparen(x ast.Expr) ast.Expr {
if p, isParen := x.(*ast.ParenExpr); isParen {
x = unparen(p.X)
}
return x
}
// checkExprOrType checks that x is an expression or a type
// (and not a raw type such as [...]T).
func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
switch t := unparen(x).(type) {
switch t := ast.Unparen(x).(type) {
case *ast.ParenExpr:
panic("unreachable")
case *ast.UnaryExpr:

View file

@ -1029,13 +1029,4 @@ func arrayPtrDeref(typ Type) Type {
return typ
}
// unparen returns e with any enclosing parentheses stripped.
func unparen(e ast.Expr) ast.Expr {
for {
p, ok := e.(*ast.ParenExpr)
if !ok {
return e
}
e = p.X
}
}
func unparen(e ast.Expr) ast.Expr { return ast.Unparen(e) }