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)
// 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
}
}
}
-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)
}
+ // 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;
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
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())
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
}
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
// 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
}
// 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
}