1
2
3
4
5 package types2
6
7 import (
8 "cmd/compile/internal/syntax"
9 "fmt"
10 "go/constant"
11 . "internal/types/errors"
12 "slices"
13 )
14
15 func (check *Checker) declare(scope *Scope, id *syntax.Name, obj Object, pos syntax.Pos) {
16
17
18
19
20 if obj.Name() != "_" {
21 if alt := scope.Insert(obj); alt != nil {
22 err := check.newError(DuplicateDecl)
23 err.addf(obj, "%s redeclared in this block", obj.Name())
24 err.addAltDecl(alt)
25 err.report()
26 return
27 }
28 obj.setScopePos(pos)
29 }
30 if id != nil {
31 check.recordDef(id, obj)
32 }
33 }
34
35
36 func pathString(path []Object) string {
37 var s string
38 for i, p := range path {
39 if i > 0 {
40 s += "->"
41 }
42 s += p.Name()
43 }
44 return s
45 }
46
47
48 func (check *Checker) objDecl(obj Object) {
49 if tracePos {
50 check.pushPos(obj.Pos())
51 defer func() {
52
53 if p := recover(); p != nil {
54 panic(p)
55 }
56 check.popPos()
57 }()
58 }
59
60 if check.conf.Trace && obj.Type() == nil {
61 if check.indent == 0 {
62 fmt.Println()
63 }
64 check.trace(obj.Pos(), "-- checking %s (objPath = %s)", obj, pathString(check.objPath))
65 check.indent++
66 defer func() {
67 check.indent--
68 check.trace(obj.Pos(), "=> %s", obj)
69 }()
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 if _, ok := check.objPathIdx[obj]; ok {
102 switch obj := obj.(type) {
103 case *Const, *Var:
104 if !check.validCycle(obj) || obj.Type() == nil {
105 obj.setType(Typ[Invalid])
106 }
107 case *TypeName:
108 if !check.validCycle(obj) {
109 obj.setType(Typ[Invalid])
110 }
111 case *Func:
112 if !check.validCycle(obj) {
113
114
115
116
117 }
118 default:
119 panic("unreachable")
120 }
121
122 assert(obj.Type() != nil)
123 return
124 }
125
126 if obj.Type() != nil {
127 return
128 }
129
130
131
132 check.push(obj)
133 defer check.pop()
134
135 d, ok := check.objMap[obj]
136 assert(ok)
137
138
139 defer func(env environment) {
140 check.environment = env
141 }(check.environment)
142 check.environment = environment{scope: d.file, version: d.version}
143
144
145
146
147
148
149 switch obj := obj.(type) {
150 case *Const:
151 check.decl = d
152 check.constDecl(obj, d.vtyp, d.init, d.inherited)
153 case *Var:
154 check.decl = d
155 check.varDecl(obj, d.lhs, d.vtyp, d.init)
156 case *TypeName:
157
158 check.typeDecl(obj, d.tdecl)
159 check.collectMethods(obj)
160 case *Func:
161
162 check.funcDecl(obj, d)
163 default:
164 panic("unreachable")
165 }
166 }
167
168
169
170 func (check *Checker) validCycle(obj Object) (valid bool) {
171
172 if debug {
173 info := check.objMap[obj]
174 inObjMap := info != nil && (info.fdecl == nil || info.fdecl.Recv == nil)
175 isPkgObj := obj.Parent() == check.pkg.scope
176 if isPkgObj != inObjMap {
177 check.dump("%v: inconsistent object map for %s (isPkgObj = %v, inObjMap = %v)", obj.Pos(), obj, isPkgObj, inObjMap)
178 panic("unreachable")
179 }
180 }
181
182
183 start, found := check.objPathIdx[obj]
184 assert(found)
185 cycle := check.objPath[start:]
186 tparCycle := false
187 nval := 0
188 ndef := 0
189 loop:
190 for _, obj := range cycle {
191 switch obj := obj.(type) {
192 case *Const, *Var:
193 nval++
194 case *TypeName:
195
196
197
198 if check.inTParamList && isGeneric(obj.typ) {
199 tparCycle = true
200 break loop
201 }
202 if !obj.IsAlias() {
203 ndef++
204 }
205 case *Func:
206
207 default:
208 panic("unreachable")
209 }
210 }
211
212 if check.conf.Trace {
213 check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle))
214 if tparCycle {
215 check.trace(obj.Pos(), "## cycle contains: generic type in a type parameter list")
216 } else {
217 check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef)
218 }
219 defer func() {
220 if valid {
221 check.trace(obj.Pos(), "=> cycle is valid")
222 } else {
223 check.trace(obj.Pos(), "=> error: cycle is invalid")
224 }
225 }()
226 }
227
228
229 if tparCycle {
230 return true
231 }
232
233
234
235
236 if nval == len(cycle) {
237 return true
238 }
239
240
241
242
243 if nval == 0 && ndef > 0 {
244 return true
245 }
246
247 check.cycleError(cycle, firstInSrc(cycle))
248 return false
249 }
250
251
252 func (check *Checker) cycleError(cycle []Object, start int) {
253
254
255
256
257 name := func(obj Object) string {
258
259 if n := asNamed(obj.Type()); n != nil && n.inst != nil {
260 return TypeString(n, check.qualifier)
261 }
262 return packagePrefix(obj.Pkg(), check.qualifier) + obj.Name()
263 }
264
265
266 obj := cycle[start]
267 tname, _ := obj.(*TypeName)
268 if tname != nil {
269 if a, ok := tname.Type().(*Alias); ok {
270 a.fromRHS = Typ[Invalid]
271 }
272 }
273
274
275 if len(cycle) == 1 {
276 if tname != nil {
277 check.errorf(obj, InvalidDeclCycle, "invalid recursive type: %s refers to itself", name(obj))
278 } else {
279 check.errorf(obj, InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", name(obj))
280 }
281 return
282 }
283
284 err := check.newError(InvalidDeclCycle)
285 if tname != nil {
286 err.addf(obj, "invalid recursive type %s", name(obj))
287 } else {
288 err.addf(obj, "invalid cycle in declaration of %s", name(obj))
289 }
290
291 for i := range cycle {
292 next := cycle[(start+i+1)%len(cycle)]
293 err.addf(obj, "%s refers to %s", name(obj), name(next))
294 obj = next
295 }
296 err.report()
297 }
298
299
300
301 func firstInSrc(path []Object) int {
302 fst, pos := 0, path[0].Pos()
303 for i, t := range path[1:] {
304 if cmpPos(t.Pos(), pos) < 0 {
305 fst, pos = i+1, t.Pos()
306 }
307 }
308 return fst
309 }
310
311 func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited bool) {
312 assert(obj.typ == nil)
313
314
315 defer func(iota constant.Value, errpos syntax.Pos) {
316 check.iota = iota
317 check.errpos = errpos
318 }(check.iota, check.errpos)
319 check.iota = obj.val
320 check.errpos = nopos
321
322
323 obj.val = constant.MakeUnknown()
324
325
326 if typ != nil {
327 t := check.typ(typ)
328 if !isConstType(t) {
329
330
331 if isValid(t.Underlying()) {
332 check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
333 }
334 obj.typ = Typ[Invalid]
335 return
336 }
337 obj.typ = t
338 }
339
340
341 var x operand
342 if init != nil {
343 if inherited {
344
345
346
347
348
349
350 check.errpos = obj.pos
351 }
352 check.expr(nil, &x, init)
353 }
354 check.initConst(obj, &x)
355 }
356
357 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) {
358 assert(obj.typ == nil)
359
360
361 if typ != nil {
362 obj.typ = check.varType(typ)
363
364
365
366
367
368
369
370
371 }
372
373
374 if init == nil {
375 if typ == nil {
376
377 obj.typ = Typ[Invalid]
378 }
379 return
380 }
381
382 if lhs == nil || len(lhs) == 1 {
383 assert(lhs == nil || lhs[0] == obj)
384 var x operand
385 check.expr(newTarget(obj.typ, obj.name), &x, init)
386 check.initVar(obj, &x, "variable declaration")
387 return
388 }
389
390 if debug {
391
392 if !slices.Contains(lhs, obj) {
393 panic("inconsistent lhs")
394 }
395 }
396
397
398
399
400
401 if typ != nil {
402 for _, lhs := range lhs {
403 lhs.typ = obj.typ
404 }
405 }
406
407 check.initVars(lhs, []syntax.Expr{init}, nil)
408 }
409
410
411 func (check *Checker) isImportedConstraint(typ Type) bool {
412 named := asNamed(typ)
413 if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil {
414 return false
415 }
416 u, _ := named.Underlying().(*Interface)
417 return u != nil && !u.IsMethodSet()
418 }
419
420 func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl) {
421 assert(obj.typ == nil)
422
423
424 versionErr := false
425
426 var rhs Type
427 check.later(func() {
428 if t := asNamed(obj.typ); t != nil {
429 check.validType(t)
430 }
431
432 _ = !versionErr && check.isImportedConstraint(rhs) && check.verifyVersionf(tdecl.Type, go1_18, "using type constraint %s", rhs)
433 }).describef(obj, "validType(%s)", obj.Name())
434
435
436 var tparam0 *syntax.Field
437 if len(tdecl.TParamList) > 0 {
438 tparam0 = tdecl.TParamList[0]
439 }
440
441
442 if tdecl.Alias {
443
444
445 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_23, "generic type alias") {
446 versionErr = true
447 }
448 if !versionErr && !check.verifyVersionf(tdecl, go1_9, "type alias") {
449 versionErr = true
450 }
451
452 alias := check.newAlias(obj, nil)
453
454
455
456 defer func() {
457 if alias.fromRHS == nil {
458 alias.fromRHS = Typ[Invalid]
459 unalias(alias)
460 }
461 }()
462
463
464 if tparam0 != nil {
465 check.openScope(tdecl, "type parameters")
466 defer check.closeScope()
467 check.collectTypeParams(&alias.tparams, tdecl.TParamList)
468 }
469
470 rhs = check.declaredType(tdecl.Type, obj)
471 assert(rhs != nil)
472 alias.fromRHS = rhs
473
474
475
476 if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 {
477 check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS")
478 alias.fromRHS = Typ[Invalid]
479 }
480
481 return
482 }
483
484
485 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_18, "type parameter") {
486 versionErr = true
487 }
488
489 named := check.newNamed(obj, nil, nil)
490 if tdecl.TParamList != nil {
491 check.openScope(tdecl, "type parameters")
492 defer check.closeScope()
493 check.collectTypeParams(&named.tparams, tdecl.TParamList)
494 }
495
496 rhs = check.declaredType(tdecl.Type, obj)
497 assert(rhs != nil)
498 named.fromRHS = rhs
499
500
501
502 if isTypeParam(rhs) {
503 check.error(tdecl.Type, MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
504 named.fromRHS = Typ[Invalid]
505 }
506 }
507
508 func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Field) {
509 tparams := make([]*TypeParam, len(list))
510
511
512
513
514 if len(list) > 0 {
515 scopePos := list[0].Pos()
516 for i, f := range list {
517 tparams[i] = check.declareTypeParam(f.Name, scopePos)
518 }
519 }
520
521
522
523
524 *dst = bindTParams(tparams)
525
526
527
528
529
530
531
532
533 assert(!check.inTParamList)
534 check.inTParamList = true
535 defer func() {
536 check.inTParamList = false
537 }()
538
539
540 var bound Type
541 for i, f := range list {
542
543
544
545 if i == 0 || f.Type != list[i-1].Type {
546 bound = check.bound(f.Type)
547 if isTypeParam(bound) {
548
549
550
551
552 check.error(f.Type, MisplacedTypeParam, "cannot use a type parameter as constraint")
553 bound = Typ[Invalid]
554 }
555 }
556 tparams[i].bound = bound
557 }
558 }
559
560 func (check *Checker) bound(x syntax.Expr) Type {
561
562
563
564 if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) {
565 t := check.typ(&syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}})
566
567 if t, _ := t.(*Interface); t != nil {
568 t.implicit = true
569 }
570 return t
571 }
572 return check.typ(x)
573 }
574
575 func (check *Checker) declareTypeParam(name *syntax.Name, scopePos syntax.Pos) *TypeParam {
576
577
578
579
580
581
582 tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil)
583 tpar := check.newTypeParam(tname, Typ[Invalid])
584 check.declare(check.scope, name, tname, scopePos)
585 return tpar
586 }
587
588 func (check *Checker) collectMethods(obj *TypeName) {
589
590
591
592
593 methods := check.methods[obj]
594 if methods == nil {
595 return
596 }
597 delete(check.methods, obj)
598 assert(!check.objMap[obj].tdecl.Alias)
599
600
601 var mset objset
602
603
604
605 base := asNamed(obj.typ)
606 if base != nil {
607 assert(base.TypeArgs().Len() == 0)
608
609
610
611 check.later(func() {
612 check.checkFieldUniqueness(base)
613 }).describef(obj, "verifying field uniqueness for %v", base)
614
615
616
617
618 for i := 0; i < base.NumMethods(); i++ {
619 m := base.Method(i)
620 assert(m.name != "_")
621 assert(mset.insert(m) == nil)
622 }
623 }
624
625
626 for _, m := range methods {
627
628
629 assert(m.name != "_")
630 if alt := mset.insert(m); alt != nil {
631 if alt.Pos().IsKnown() {
632 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared at %v", obj.Name(), m.name, alt.Pos())
633 } else {
634 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared", obj.Name(), m.name)
635 }
636 continue
637 }
638
639 if base != nil {
640 base.AddMethod(m)
641 }
642 }
643 }
644
645 func (check *Checker) checkFieldUniqueness(base *Named) {
646 if t, _ := base.Underlying().(*Struct); t != nil {
647 var mset objset
648 for i := 0; i < base.NumMethods(); i++ {
649 m := base.Method(i)
650 assert(m.name != "_")
651 assert(mset.insert(m) == nil)
652 }
653
654
655
656 for _, fld := range t.fields {
657 if fld.name != "_" {
658 if alt := mset.insert(fld); alt != nil {
659
660
661 _ = alt.(*Func)
662
663
664
665 err := check.newError(DuplicateFieldAndMethod)
666 err.addf(alt, "field and method with the same name %s", fld.name)
667 err.addAltDecl(fld)
668 err.report()
669 }
670 }
671 }
672 }
673 }
674
675 func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
676 assert(obj.typ == nil)
677
678
679 assert(check.iota == nil)
680
681 sig := new(Signature)
682 obj.typ = sig
683
684 fdecl := decl.fdecl
685 check.funcType(sig, fdecl.Recv, fdecl.TParamList, fdecl.Type)
686
687 if fdecl.Pragma != nil {
688 if p, ok := fdecl.Pragma.(interface{ Nointerface() bool }); ok && p.Nointerface() {
689 obj.nointerface = true
690 }
691 }
692
693
694
695 sig.scope.pos = fdecl.Pos()
696 sig.scope.end = syntax.EndPos(fdecl)
697
698 if len(fdecl.TParamList) > 0 && fdecl.Body == nil {
699 check.softErrorf(fdecl, BadDecl, "generic function is missing function body")
700 }
701
702
703
704 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
705 check.later(func() {
706 check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
707 }).describef(obj, "func %s", obj.name)
708 }
709 }
710
711 func (check *Checker) declStmt(list []syntax.Decl) {
712 pkg := check.pkg
713
714 first := -1
715 var last *syntax.ConstDecl
716 for index, decl := range list {
717 if _, ok := decl.(*syntax.ConstDecl); !ok {
718 first = -1
719 }
720
721 switch s := decl.(type) {
722 case *syntax.ConstDecl:
723 top := len(check.delayed)
724
725
726 if first < 0 || s.Group == nil || list[index-1].(*syntax.ConstDecl).Group != s.Group {
727 first = index
728 last = nil
729 }
730 iota := constant.MakeInt64(int64(index - first))
731
732
733 inherited := true
734 switch {
735 case s.Type != nil || s.Values != nil:
736 last = s
737 inherited = false
738 case last == nil:
739 last = new(syntax.ConstDecl)
740 inherited = false
741 }
742
743
744 lhs := make([]*Const, len(s.NameList))
745 values := syntax.UnpackListExpr(last.Values)
746 for i, name := range s.NameList {
747 obj := NewConst(name.Pos(), pkg, name.Value, nil, iota)
748 lhs[i] = obj
749
750 var init syntax.Expr
751 if i < len(values) {
752 init = values[i]
753 }
754
755 check.constDecl(obj, last.Type, init, inherited)
756 }
757
758
759 check.arity(s.Pos(), s.NameList, values, true, inherited)
760
761
762 check.processDelayed(top)
763
764
765
766
767
768 scopePos := syntax.EndPos(s)
769 for i, name := range s.NameList {
770 check.declare(check.scope, name, lhs[i], scopePos)
771 }
772
773 case *syntax.VarDecl:
774 top := len(check.delayed)
775
776 lhs0 := make([]*Var, len(s.NameList))
777 for i, name := range s.NameList {
778 lhs0[i] = newVar(LocalVar, name.Pos(), pkg, name.Value, nil)
779 }
780
781
782 values := syntax.UnpackListExpr(s.Values)
783 for i, obj := range lhs0 {
784 var lhs []*Var
785 var init syntax.Expr
786 switch len(values) {
787 case len(s.NameList):
788
789 init = values[i]
790 case 1:
791
792 lhs = lhs0
793 init = values[0]
794 default:
795 if i < len(values) {
796 init = values[i]
797 }
798 }
799 check.varDecl(obj, lhs, s.Type, init)
800 if len(values) == 1 {
801
802
803
804
805
806 if debug {
807 for _, obj := range lhs0 {
808 assert(obj.typ != nil)
809 }
810 }
811 break
812 }
813 }
814
815
816 if s.Type == nil || values != nil {
817 check.arity(s.Pos(), s.NameList, values, false, false)
818 }
819
820
821 check.processDelayed(top)
822
823
824
825 scopePos := syntax.EndPos(s)
826 for i, name := range s.NameList {
827
828 check.declare(check.scope, name, lhs0[i], scopePos)
829 }
830
831 case *syntax.TypeDecl:
832 obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
833
834
835
836 scopePos := s.Name.Pos()
837 check.declare(check.scope, s.Name, obj, scopePos)
838 check.push(obj)
839 check.typeDecl(obj, s)
840 check.pop()
841
842 default:
843 check.errorf(s, InvalidSyntaxTree, "unknown syntax.Decl node %T", s)
844 }
845 }
846 }
847
View as plain text