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 return packagePrefix(obj.Pkg(), check.qualifier) + obj.Name()
259 }
260
261
262 obj := cycle[start]
263 tname, _ := obj.(*TypeName)
264 if tname != nil {
265 if a, ok := tname.Type().(*Alias); ok {
266 a.fromRHS = Typ[Invalid]
267 }
268 }
269
270
271 if len(cycle) == 1 {
272 if tname != nil {
273 check.errorf(obj, InvalidDeclCycle, "invalid recursive type: %s refers to itself", name(obj))
274 } else {
275 check.errorf(obj, InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", name(obj))
276 }
277 return
278 }
279
280 err := check.newError(InvalidDeclCycle)
281 if tname != nil {
282 err.addf(obj, "invalid recursive type %s", name(obj))
283 } else {
284 err.addf(obj, "invalid cycle in declaration of %s", name(obj))
285 }
286
287 for i := range cycle {
288 next := cycle[(start+i+1)%len(cycle)]
289 err.addf(obj, "%s refers to %s", name(obj), name(next))
290 obj = next
291 }
292 err.report()
293 }
294
295
296
297 func firstInSrc(path []Object) int {
298 fst, pos := 0, path[0].Pos()
299 for i, t := range path[1:] {
300 if cmpPos(t.Pos(), pos) < 0 {
301 fst, pos = i+1, t.Pos()
302 }
303 }
304 return fst
305 }
306
307 func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited bool) {
308 assert(obj.typ == nil)
309
310
311 defer func(iota constant.Value, errpos syntax.Pos) {
312 check.iota = iota
313 check.errpos = errpos
314 }(check.iota, check.errpos)
315 check.iota = obj.val
316 check.errpos = nopos
317
318
319 obj.val = constant.MakeUnknown()
320
321
322 if typ != nil {
323 t := check.typ(typ)
324 if !isConstType(t) {
325
326
327 if isValid(t.Underlying()) {
328 check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
329 }
330 obj.typ = Typ[Invalid]
331 return
332 }
333 obj.typ = t
334 }
335
336
337 var x operand
338 if init != nil {
339 if inherited {
340
341
342
343
344
345
346 check.errpos = obj.pos
347 }
348 check.expr(nil, &x, init)
349 }
350 check.initConst(obj, &x)
351 }
352
353 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) {
354 assert(obj.typ == nil)
355
356
357 if typ != nil {
358 obj.typ = check.varType(typ)
359
360
361
362
363
364
365
366
367 }
368
369
370 if init == nil {
371 if typ == nil {
372
373 obj.typ = Typ[Invalid]
374 }
375 return
376 }
377
378 if lhs == nil || len(lhs) == 1 {
379 assert(lhs == nil || lhs[0] == obj)
380 var x operand
381 check.expr(newTarget(obj.typ, obj.name), &x, init)
382 check.initVar(obj, &x, "variable declaration")
383 return
384 }
385
386 if debug {
387
388 if !slices.Contains(lhs, obj) {
389 panic("inconsistent lhs")
390 }
391 }
392
393
394
395
396
397 if typ != nil {
398 for _, lhs := range lhs {
399 lhs.typ = obj.typ
400 }
401 }
402
403 check.initVars(lhs, []syntax.Expr{init}, nil)
404 }
405
406
407 func (check *Checker) isImportedConstraint(typ Type) bool {
408 named := asNamed(typ)
409 if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil {
410 return false
411 }
412 u, _ := named.Underlying().(*Interface)
413 return u != nil && !u.IsMethodSet()
414 }
415
416 func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl) {
417 assert(obj.typ == nil)
418
419
420 versionErr := false
421
422 var rhs Type
423 check.later(func() {
424 if t := asNamed(obj.typ); t != nil {
425 check.validType(t)
426 }
427
428 _ = !versionErr && check.isImportedConstraint(rhs) && check.verifyVersionf(tdecl.Type, go1_18, "using type constraint %s", rhs)
429 }).describef(obj, "validType(%s)", obj.Name())
430
431
432 var tparam0 *syntax.Field
433 if len(tdecl.TParamList) > 0 {
434 tparam0 = tdecl.TParamList[0]
435 }
436
437
438 if tdecl.Alias {
439
440
441 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_23, "generic type alias") {
442 versionErr = true
443 }
444 if !versionErr && !check.verifyVersionf(tdecl, go1_9, "type alias") {
445 versionErr = true
446 }
447
448 alias := check.newAlias(obj, nil)
449
450
451
452 defer func() {
453 if alias.fromRHS == nil {
454 alias.fromRHS = Typ[Invalid]
455 unalias(alias)
456 }
457 }()
458
459
460 if tparam0 != nil {
461 check.openScope(tdecl, "type parameters")
462 defer check.closeScope()
463 check.collectTypeParams(&alias.tparams, tdecl.TParamList)
464 }
465
466 rhs = check.declaredType(tdecl.Type, obj)
467 assert(rhs != nil)
468 alias.fromRHS = rhs
469
470
471
472 if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 {
473 check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS")
474 alias.fromRHS = Typ[Invalid]
475 }
476
477 return
478 }
479
480
481 if !versionErr && tparam0 != nil && !check.verifyVersionf(tparam0, go1_18, "type parameter") {
482 versionErr = true
483 }
484
485 named := check.newNamed(obj, nil, nil)
486 if tdecl.TParamList != nil {
487 check.openScope(tdecl, "type parameters")
488 defer check.closeScope()
489 check.collectTypeParams(&named.tparams, tdecl.TParamList)
490 }
491
492 rhs = check.declaredType(tdecl.Type, obj)
493 assert(rhs != nil)
494 named.fromRHS = rhs
495
496
497
498 if isTypeParam(rhs) {
499 check.error(tdecl.Type, MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
500 named.fromRHS = Typ[Invalid]
501 }
502 }
503
504 func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Field) {
505 tparams := make([]*TypeParam, len(list))
506
507
508
509
510 if len(list) > 0 {
511 scopePos := list[0].Pos()
512 for i, f := range list {
513 tparams[i] = check.declareTypeParam(f.Name, scopePos)
514 }
515 }
516
517
518
519
520 *dst = bindTParams(tparams)
521
522
523
524
525
526
527
528
529 assert(!check.inTParamList)
530 check.inTParamList = true
531 defer func() {
532 check.inTParamList = false
533 }()
534
535
536 var bound Type
537 for i, f := range list {
538
539
540
541 if i == 0 || f.Type != list[i-1].Type {
542 bound = check.bound(f.Type)
543 if isTypeParam(bound) {
544
545
546
547
548 check.error(f.Type, MisplacedTypeParam, "cannot use a type parameter as constraint")
549 bound = Typ[Invalid]
550 }
551 }
552 tparams[i].bound = bound
553 }
554 }
555
556 func (check *Checker) bound(x syntax.Expr) Type {
557
558
559
560 if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) {
561 t := check.typ(&syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}})
562
563 if t, _ := t.(*Interface); t != nil {
564 t.implicit = true
565 }
566 return t
567 }
568 return check.typ(x)
569 }
570
571 func (check *Checker) declareTypeParam(name *syntax.Name, scopePos syntax.Pos) *TypeParam {
572
573
574
575
576
577
578 tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil)
579 tpar := check.newTypeParam(tname, Typ[Invalid])
580 check.declare(check.scope, name, tname, scopePos)
581 return tpar
582 }
583
584 func (check *Checker) collectMethods(obj *TypeName) {
585
586
587
588
589 methods := check.methods[obj]
590 if methods == nil {
591 return
592 }
593 delete(check.methods, obj)
594 assert(!check.objMap[obj].tdecl.Alias)
595
596
597 var mset objset
598
599
600
601 base := asNamed(obj.typ)
602 if base != nil {
603 assert(base.TypeArgs().Len() == 0)
604
605
606
607 check.later(func() {
608 check.checkFieldUniqueness(base)
609 }).describef(obj, "verifying field uniqueness for %v", base)
610
611
612
613
614 for i := 0; i < base.NumMethods(); i++ {
615 m := base.Method(i)
616 assert(m.name != "_")
617 assert(mset.insert(m) == nil)
618 }
619 }
620
621
622 for _, m := range methods {
623
624
625 assert(m.name != "_")
626 if alt := mset.insert(m); alt != nil {
627 if alt.Pos().IsKnown() {
628 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared at %v", obj.Name(), m.name, alt.Pos())
629 } else {
630 check.errorf(m.pos, DuplicateMethod, "method %s.%s already declared", obj.Name(), m.name)
631 }
632 continue
633 }
634
635 if base != nil {
636 base.AddMethod(m)
637 }
638 }
639 }
640
641 func (check *Checker) checkFieldUniqueness(base *Named) {
642 if t, _ := base.Underlying().(*Struct); t != nil {
643 var mset objset
644 for i := 0; i < base.NumMethods(); i++ {
645 m := base.Method(i)
646 assert(m.name != "_")
647 assert(mset.insert(m) == nil)
648 }
649
650
651
652 for _, fld := range t.fields {
653 if fld.name != "_" {
654 if alt := mset.insert(fld); alt != nil {
655
656
657 _ = alt.(*Func)
658
659
660
661 err := check.newError(DuplicateFieldAndMethod)
662 err.addf(alt, "field and method with the same name %s", fld.name)
663 err.addAltDecl(fld)
664 err.report()
665 }
666 }
667 }
668 }
669 }
670
671 func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
672 assert(obj.typ == nil)
673
674
675 assert(check.iota == nil)
676
677 sig := new(Signature)
678 obj.typ = sig
679
680 fdecl := decl.fdecl
681 check.funcType(sig, fdecl.Recv, fdecl.TParamList, fdecl.Type)
682
683
684
685 sig.scope.pos = fdecl.Pos()
686 sig.scope.end = syntax.EndPos(fdecl)
687
688 if len(fdecl.TParamList) > 0 && fdecl.Body == nil {
689 check.softErrorf(fdecl, BadDecl, "generic function is missing function body")
690 }
691
692
693
694 if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
695 check.later(func() {
696 check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
697 }).describef(obj, "func %s", obj.name)
698 }
699 }
700
701 func (check *Checker) declStmt(list []syntax.Decl) {
702 pkg := check.pkg
703
704 first := -1
705 var last *syntax.ConstDecl
706 for index, decl := range list {
707 if _, ok := decl.(*syntax.ConstDecl); !ok {
708 first = -1
709 }
710
711 switch s := decl.(type) {
712 case *syntax.ConstDecl:
713 top := len(check.delayed)
714
715
716 if first < 0 || s.Group == nil || list[index-1].(*syntax.ConstDecl).Group != s.Group {
717 first = index
718 last = nil
719 }
720 iota := constant.MakeInt64(int64(index - first))
721
722
723 inherited := true
724 switch {
725 case s.Type != nil || s.Values != nil:
726 last = s
727 inherited = false
728 case last == nil:
729 last = new(syntax.ConstDecl)
730 inherited = false
731 }
732
733
734 lhs := make([]*Const, len(s.NameList))
735 values := syntax.UnpackListExpr(last.Values)
736 for i, name := range s.NameList {
737 obj := NewConst(name.Pos(), pkg, name.Value, nil, iota)
738 lhs[i] = obj
739
740 var init syntax.Expr
741 if i < len(values) {
742 init = values[i]
743 }
744
745 check.constDecl(obj, last.Type, init, inherited)
746 }
747
748
749 check.arity(s.Pos(), s.NameList, values, true, inherited)
750
751
752 check.processDelayed(top)
753
754
755
756
757
758 scopePos := syntax.EndPos(s)
759 for i, name := range s.NameList {
760 check.declare(check.scope, name, lhs[i], scopePos)
761 }
762
763 case *syntax.VarDecl:
764 top := len(check.delayed)
765
766 lhs0 := make([]*Var, len(s.NameList))
767 for i, name := range s.NameList {
768 lhs0[i] = newVar(LocalVar, name.Pos(), pkg, name.Value, nil)
769 }
770
771
772 values := syntax.UnpackListExpr(s.Values)
773 for i, obj := range lhs0 {
774 var lhs []*Var
775 var init syntax.Expr
776 switch len(values) {
777 case len(s.NameList):
778
779 init = values[i]
780 case 1:
781
782 lhs = lhs0
783 init = values[0]
784 default:
785 if i < len(values) {
786 init = values[i]
787 }
788 }
789 check.varDecl(obj, lhs, s.Type, init)
790 if len(values) == 1 {
791
792
793
794
795
796 if debug {
797 for _, obj := range lhs0 {
798 assert(obj.typ != nil)
799 }
800 }
801 break
802 }
803 }
804
805
806 if s.Type == nil || values != nil {
807 check.arity(s.Pos(), s.NameList, values, false, false)
808 }
809
810
811 check.processDelayed(top)
812
813
814
815 scopePos := syntax.EndPos(s)
816 for i, name := range s.NameList {
817
818 check.declare(check.scope, name, lhs0[i], scopePos)
819 }
820
821 case *syntax.TypeDecl:
822 obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
823
824
825
826 scopePos := s.Name.Pos()
827 check.declare(check.scope, s.Name, obj, scopePos)
828 check.push(obj)
829 check.typeDecl(obj, s)
830 check.pop()
831
832 default:
833 check.errorf(s, InvalidSyntaxTree, "unknown syntax.Decl node %T", s)
834 }
835 }
836 }
837
View as plain text