github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/go/types/decl.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package types 6 7 import ( 8 "go/ast" 9 "go/exact" 10 "go/token" 11 ) 12 13 func (check *Checker) reportAltDecl(obj Object) { 14 if pos := obj.Pos(); pos.IsValid() { 15 // We use "other" rather than "previous" here because 16 // the first declaration seen may not be textually 17 // earlier in the source. 18 check.errorf(pos, "\tother declaration of %s", obj.Name()) // secondary error, \t indented 19 } 20 } 21 22 func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object) { 23 // spec: "The blank identifier, represented by the underscore 24 // character _, may be used in a declaration like any other 25 // identifier but the declaration does not introduce a new 26 // binding." 27 if obj.Name() != "_" { 28 if alt := scope.Insert(obj); alt != nil { 29 check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name()) 30 check.reportAltDecl(alt) 31 return 32 } 33 } 34 if id != nil { 35 check.recordDef(id, obj) 36 } 37 } 38 39 // objDecl type-checks the declaration of obj in its respective (file) context. 40 // See check.typ for the details on def and path. 41 func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) { 42 if obj.Type() != nil { 43 return // already checked - nothing to do 44 } 45 46 if trace { 47 check.trace(obj.Pos(), "-- declaring %s", obj.Name()) 48 check.indent++ 49 defer func() { 50 check.indent-- 51 check.trace(obj.Pos(), "=> %s", obj) 52 }() 53 } 54 55 d := check.objMap[obj] 56 if d == nil { 57 check.dump("%s: %s should have been declared", obj.Pos(), obj.Name()) 58 unreachable() 59 } 60 61 // save/restore current context and setup object context 62 defer func(ctxt context) { 63 check.context = ctxt 64 }(check.context) 65 check.context = context{ 66 scope: d.file, 67 } 68 69 // Const and var declarations must not have initialization 70 // cycles. We track them by remembering the current declaration 71 // in check.decl. Initialization expressions depending on other 72 // consts, vars, or functions, add dependencies to the current 73 // check.decl. 74 switch obj := obj.(type) { 75 case *Const: 76 check.decl = d // new package-level const decl 77 check.constDecl(obj, d.typ, d.init) 78 case *Var: 79 check.decl = d // new package-level var decl 80 check.varDecl(obj, d.lhs, d.typ, d.init) 81 case *TypeName: 82 // invalid recursive types are detected via path 83 check.typeDecl(obj, d.typ, def, path) 84 case *Func: 85 // functions may be recursive - no need to track dependencies 86 check.funcDecl(obj, d) 87 default: 88 unreachable() 89 } 90 } 91 92 func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { 93 assert(obj.typ == nil) 94 95 if obj.visited { 96 obj.typ = Typ[Invalid] 97 return 98 } 99 obj.visited = true 100 101 // use the correct value of iota 102 assert(check.iota == nil) 103 check.iota = obj.val 104 defer func() { check.iota = nil }() 105 106 // provide valid constant value under all circumstances 107 obj.val = exact.MakeUnknown() 108 109 // determine type, if any 110 if typ != nil { 111 t := check.typ(typ) 112 if !isConstType(t) { 113 check.errorf(typ.Pos(), "invalid constant type %s", t) 114 obj.typ = Typ[Invalid] 115 return 116 } 117 obj.typ = t 118 } 119 120 // check initialization 121 var x operand 122 if init != nil { 123 check.expr(&x, init) 124 } 125 check.initConst(obj, &x) 126 } 127 128 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { 129 assert(obj.typ == nil) 130 131 if obj.visited { 132 obj.typ = Typ[Invalid] 133 return 134 } 135 obj.visited = true 136 137 // var declarations cannot use iota 138 assert(check.iota == nil) 139 140 // determine type, if any 141 if typ != nil { 142 obj.typ = check.typ(typ) 143 } 144 145 // check initialization 146 if init == nil { 147 if typ == nil { 148 // error reported before by arityMatch 149 obj.typ = Typ[Invalid] 150 } 151 return 152 } 153 154 if lhs == nil || len(lhs) == 1 { 155 assert(lhs == nil || lhs[0] == obj) 156 var x operand 157 check.expr(&x, init) 158 check.initVar(obj, &x, false) 159 return 160 } 161 162 if debug { 163 // obj must be one of lhs 164 found := false 165 for _, lhs := range lhs { 166 if obj == lhs { 167 found = true 168 break 169 } 170 } 171 if !found { 172 panic("inconsistent lhs") 173 } 174 } 175 check.initVars(lhs, []ast.Expr{init}, token.NoPos) 176 } 177 178 // underlying returns the underlying type of typ; possibly by following 179 // forward chains of named types. Such chains only exist while named types 180 // are incomplete. 181 func underlying(typ Type) Type { 182 for { 183 n, _ := typ.(*Named) 184 if n == nil { 185 break 186 } 187 typ = n.underlying 188 } 189 return typ 190 } 191 192 func (n *Named) setUnderlying(typ Type) { 193 if n != nil { 194 n.underlying = typ 195 } 196 } 197 198 func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName) { 199 assert(obj.typ == nil) 200 201 // type declarations cannot use iota 202 assert(check.iota == nil) 203 204 named := &Named{obj: obj} 205 def.setUnderlying(named) 206 obj.typ = named // make sure recursive type declarations terminate 207 208 // determine underlying type of named 209 check.typExpr(typ, named, append(path, obj)) 210 211 // The underlying type of named may be itself a named type that is 212 // incomplete: 213 // 214 // type ( 215 // A B 216 // B *C 217 // C A 218 // ) 219 // 220 // The type of C is the (named) type of A which is incomplete, 221 // and which has as its underlying type the named type B. 222 // Determine the (final, unnamed) underlying type by resolving 223 // any forward chain (they always end in an unnamed type). 224 named.underlying = underlying(named.underlying) 225 226 // check and add associated methods 227 // TODO(gri) It's easy to create pathological cases where the 228 // current approach is incorrect: In general we need to know 229 // and add all methods _before_ type-checking the type. 230 // See http://play.golang.org/p/WMpE0q2wK8 231 check.addMethodDecls(obj) 232 } 233 234 func (check *Checker) addMethodDecls(obj *TypeName) { 235 // get associated methods 236 methods := check.methods[obj.name] 237 if len(methods) == 0 { 238 return // no methods 239 } 240 delete(check.methods, obj.name) 241 242 // use an objset to check for name conflicts 243 var mset objset 244 245 // spec: "If the base type is a struct type, the non-blank method 246 // and field names must be distinct." 247 base := obj.typ.(*Named) 248 if t, _ := base.underlying.(*Struct); t != nil { 249 for _, fld := range t.fields { 250 if fld.name != "_" { 251 assert(mset.insert(fld) == nil) 252 } 253 } 254 } 255 256 // Checker.Files may be called multiple times; additional package files 257 // may add methods to already type-checked types. Add pre-existing methods 258 // so that we can detect redeclarations. 259 for _, m := range base.methods { 260 assert(m.name != "_") 261 assert(mset.insert(m) == nil) 262 } 263 264 // type-check methods 265 for _, m := range methods { 266 // spec: "For a base type, the non-blank names of methods bound 267 // to it must be unique." 268 if m.name != "_" { 269 if alt := mset.insert(m); alt != nil { 270 switch alt.(type) { 271 case *Var: 272 check.errorf(m.pos, "field and method with the same name %s", m.name) 273 case *Func: 274 check.errorf(m.pos, "method %s already declared for %s", m.name, base) 275 default: 276 unreachable() 277 } 278 check.reportAltDecl(alt) 279 continue 280 } 281 } 282 check.objDecl(m, nil, nil) 283 // methods with blank _ names cannot be found - don't keep them 284 if m.name != "_" { 285 base.methods = append(base.methods, m) 286 } 287 } 288 } 289 290 func (check *Checker) funcDecl(obj *Func, decl *declInfo) { 291 assert(obj.typ == nil) 292 293 // func declarations cannot use iota 294 assert(check.iota == nil) 295 296 sig := new(Signature) 297 obj.typ = sig // guard against cycles 298 fdecl := decl.fdecl 299 check.funcType(sig, fdecl.Recv, fdecl.Type) 300 if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) { 301 check.errorf(fdecl.Pos(), "func init must have no arguments and no return values") 302 // ok to continue 303 } 304 305 // function body must be type-checked after global declarations 306 // (functions implemented elsewhere have no body) 307 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil { 308 check.later(obj.name, decl, sig, fdecl.Body) 309 } 310 } 311 312 func (check *Checker) declStmt(decl ast.Decl) { 313 pkg := check.pkg 314 315 switch d := decl.(type) { 316 case *ast.BadDecl: 317 // ignore 318 319 case *ast.GenDecl: 320 var last *ast.ValueSpec // last ValueSpec with type or init exprs seen 321 for iota, spec := range d.Specs { 322 switch s := spec.(type) { 323 case *ast.ValueSpec: 324 switch d.Tok { 325 case token.CONST: 326 // determine which init exprs to use 327 switch { 328 case s.Type != nil || len(s.Values) > 0: 329 last = s 330 case last == nil: 331 last = new(ast.ValueSpec) // make sure last exists 332 } 333 334 // declare all constants 335 lhs := make([]*Const, len(s.Names)) 336 for i, name := range s.Names { 337 obj := NewConst(name.Pos(), pkg, name.Name, nil, exact.MakeInt64(int64(iota))) 338 lhs[i] = obj 339 340 var init ast.Expr 341 if i < len(last.Values) { 342 init = last.Values[i] 343 } 344 345 check.constDecl(obj, last.Type, init) 346 } 347 348 check.arityMatch(s, last) 349 350 for i, name := range s.Names { 351 check.declare(check.scope, name, lhs[i]) 352 } 353 354 case token.VAR: 355 lhs0 := make([]*Var, len(s.Names)) 356 for i, name := range s.Names { 357 lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil) 358 } 359 360 // initialize all variables 361 for i, obj := range lhs0 { 362 var lhs []*Var 363 var init ast.Expr 364 switch len(s.Values) { 365 case len(s.Names): 366 // lhs and rhs match 367 init = s.Values[i] 368 case 1: 369 // rhs is expected to be a multi-valued expression 370 lhs = lhs0 371 init = s.Values[0] 372 default: 373 if i < len(s.Values) { 374 init = s.Values[i] 375 } 376 } 377 check.varDecl(obj, lhs, s.Type, init) 378 if len(s.Values) == 1 { 379 // If we have a single lhs variable we are done either way. 380 // If we have a single rhs expression, it must be a multi- 381 // valued expression, in which case handling the first lhs 382 // variable will cause all lhs variables to have a type 383 // assigned, and we are done as well. 384 if debug { 385 for _, obj := range lhs0 { 386 assert(obj.typ != nil) 387 } 388 } 389 break 390 } 391 } 392 393 check.arityMatch(s, nil) 394 395 // declare all variables 396 // (only at this point are the variable scopes (parents) set) 397 for i, name := range s.Names { 398 check.declare(check.scope, name, lhs0[i]) 399 } 400 401 default: 402 check.invalidAST(s.Pos(), "invalid token %s", d.Tok) 403 } 404 405 case *ast.TypeSpec: 406 obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil) 407 check.declare(check.scope, s.Name, obj) 408 check.typeDecl(obj, s.Type, nil, nil) 409 410 default: 411 check.invalidAST(s.Pos(), "const, type, or var declaration expected") 412 } 413 } 414 415 default: 416 check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d) 417 } 418 }