mirror of
https://github.com/golang/go
synced 2024-11-11 20:50:23 -07:00
[dev.regabi] go/types: type alias decl requires go1.9
This is a port of CL 289570 to go/types. It has some notable differences with that CL: + A new _BadDecl error code is added, to indicate declarations with bad syntax. + declInfo is updated hold not an 'alias' bool, but an aliasPos token.Pos to identify the location of the type aliasing '=' token. This allows for error messages to be accurately placed on the '=' For #31793 Change-Id: Ib15969f9cd5be30228b7a4c6406f978d6fc58018 Reviewed-on: https://go-review.googlesource.com/c/go/+/291318 Trust: Robert Findley <rfindley@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
c2358a1ae7
commit
7696c94334
@ -189,7 +189,7 @@ func (check *Checker) objDecl(obj Object, def *Named) {
|
||||
check.varDecl(obj, d.lhs, d.typ, d.init)
|
||||
case *TypeName:
|
||||
// invalid recursive types are detected via path
|
||||
check.typeDecl(obj, d.typ, def, d.alias)
|
||||
check.typeDecl(obj, d.typ, def, d.aliasPos)
|
||||
case *Func:
|
||||
// functions may be recursive - no need to track dependencies
|
||||
check.funcDecl(obj, d)
|
||||
@ -234,7 +234,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) {
|
||||
// this information explicitly in the object.
|
||||
var alias bool
|
||||
if d := check.objMap[obj]; d != nil {
|
||||
alias = d.alias // package-level object
|
||||
alias = d.aliasPos.IsValid() // package-level object
|
||||
} else {
|
||||
alias = obj.IsAlias() // function local object
|
||||
}
|
||||
@ -640,14 +640,17 @@ func (n *Named) setUnderlying(typ Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) {
|
||||
func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, aliasPos token.Pos) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
check.later(func() {
|
||||
check.validType(obj.typ, nil)
|
||||
})
|
||||
|
||||
if alias {
|
||||
if aliasPos.IsValid() {
|
||||
if !check.allowVersion(obj.pkg, 1, 9) {
|
||||
check.errorf(atPos(aliasPos), _BadDecl, "type aliases requires go1.9 or later")
|
||||
}
|
||||
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.typ = check.typ(typ)
|
||||
@ -678,9 +681,12 @@ func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bo
|
||||
|
||||
}
|
||||
|
||||
// TODO(rFindley): move to the callsite, as this is only needed for top-level
|
||||
// decls.
|
||||
check.addMethodDecls(obj)
|
||||
}
|
||||
|
||||
// TODO(rFindley): rename to collectMethods, to be consistent with types2.
|
||||
func (check *Checker) addMethodDecls(obj *TypeName) {
|
||||
// get associated methods
|
||||
// (Checker.collectObjects only collects methods with non-blank names;
|
||||
@ -691,7 +697,7 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
|
||||
return
|
||||
}
|
||||
delete(check.methods, obj)
|
||||
assert(!check.objMap[obj].alias) // don't use TypeName.IsAlias (requires fully set up object)
|
||||
assert(!check.objMap[obj].aliasPos.IsValid()) // don't use TypeName.IsAlias (requires fully set up object)
|
||||
|
||||
// use an objset to check for name conflicts
|
||||
var mset objset
|
||||
@ -864,7 +870,7 @@ func (check *Checker) declStmt(d ast.Decl) {
|
||||
check.declare(check.scope, d.spec.Name, obj, scopePos)
|
||||
// mark and unmark type before calling typeDecl; its type is still nil (see Checker.objDecl)
|
||||
obj.setColor(grey + color(check.push(obj)))
|
||||
check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign.IsValid())
|
||||
check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign)
|
||||
check.pop().setColor(black)
|
||||
default:
|
||||
check.invalidAST(d.node(), "unknown ast.Decl node %T", d.node())
|
||||
|
@ -1366,4 +1366,7 @@ const (
|
||||
// return i
|
||||
// }
|
||||
_InvalidGo
|
||||
|
||||
// _BadDecl occurs when a declaration has invalid syntax.
|
||||
_BadDecl
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ type declInfo struct {
|
||||
init ast.Expr // init/orig expression, or nil
|
||||
inherited bool // if set, the init expression is inherited from a previous constant declaration
|
||||
fdecl *ast.FuncDecl // func declaration, or nil
|
||||
alias bool // type alias declaration
|
||||
aliasPos token.Pos // If valid, the decl is a type alias and aliasPos is the position of '='.
|
||||
|
||||
// The deps field tracks initialization expression dependencies.
|
||||
deps map[Object]bool // lazily initialized
|
||||
@ -366,7 +366,7 @@ func (check *Checker) collectObjects() {
|
||||
}
|
||||
case typeDecl:
|
||||
obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil)
|
||||
check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, typ: d.spec.Type, alias: d.spec.Assign.IsValid()})
|
||||
check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, typ: d.spec.Type, aliasPos: d.spec.Assign})
|
||||
case funcDecl:
|
||||
info := &declInfo{file: fileScope, fdecl: d.decl}
|
||||
name := d.decl.Name.Name
|
||||
@ -493,7 +493,7 @@ func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeNam
|
||||
// we're done if tdecl defined tname as a new type
|
||||
// (rather than an alias)
|
||||
tdecl := check.objMap[tname] // must exist for objects in package scope
|
||||
if !tdecl.alias {
|
||||
if !tdecl.aliasPos.IsValid() {
|
||||
return ptr, tname
|
||||
}
|
||||
|
||||
@ -534,7 +534,7 @@ func (check *Checker) packageObjects() {
|
||||
// phase 1
|
||||
for _, obj := range objList {
|
||||
// If we have a type alias, collect it for the 2nd phase.
|
||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].alias {
|
||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].aliasPos.IsValid() {
|
||||
aliasList = append(aliasList, tname)
|
||||
continue
|
||||
}
|
||||
|
11
src/go/types/testdata/go1_8.src
vendored
Normal file
11
src/go/types/testdata/go1_8.src
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
// Check Go language version-specific errors.
|
||||
|
||||
package go1_8 // go1.8
|
||||
|
||||
// type alias declarations
|
||||
type any = /* ERROR type aliases requires go1.9 or later */ interface{}
|
||||
|
Loading…
Reference in New Issue
Block a user