@@ -26,12 +26,12 @@ import (
26
26
// instantiated.
27
27
func (check * Checker ) Instantiate (pos syntax.Pos , typ Type , targs []Type , posList []syntax.Pos , verify bool ) (res Type ) {
28
28
// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
29
- var tparams [] * TypeName
29
+ var inst Type
30
30
switch t := typ .(type ) {
31
31
case * Named :
32
- return check .instantiateLazy (pos , t , targs , posList , verify )
32
+ inst = check .instantiateLazy (pos , t , targs )
33
33
case * Signature :
34
- tparams = t .TParams ().list ()
34
+ tparams : = t .TParams ().list ()
35
35
defer func () {
36
36
// If we had an unexpected failure somewhere don't panic below when
37
37
// asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
@@ -50,18 +50,35 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis
50
50
// anymore; we need to set tparams to nil.
51
51
res .(* Signature ).tparams = nil
52
52
}()
53
+ inst = check .instantiate (pos , typ , tparams , targs , nil )
53
54
default :
54
55
// only types and functions can be generic
55
56
panic (fmt .Sprintf ("%v: cannot instantiate %v" , pos , typ ))
56
57
}
57
- inst := check .instantiate (pos , typ , tparams , targs , nil )
58
58
59
59
if verify {
60
- assert (len (posList ) <= len (targs ))
61
- if len (tparams ) == len (targs ) {
62
- check .verify (pos , tparams , targs , posList )
60
+ if check == nil {
61
+ panic ("cannot have nil Checker if verifying constraints" )
63
62
}
63
+ assert (len (posList ) <= len (targs ))
64
+ check .later (func () {
65
+ // Collect tparams again because lazily loaded *Named types may not have
66
+ // had tparams set up above.
67
+ var tparams []* TypeName
68
+ switch t := typ .(type ) {
69
+ case * Named :
70
+ tparams = t .TParams ().list ()
71
+ case * Signature :
72
+ tparams = t .TParams ().list ()
73
+ }
74
+ // Avoid duplicate errors; instantiate will have complained if tparams
75
+ // and targs do not have the same length.
76
+ if len (tparams ) == len (targs ) {
77
+ check .verify (pos , tparams , targs , posList )
78
+ }
79
+ })
64
80
}
81
+
65
82
return inst
66
83
}
67
84
@@ -101,20 +118,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName,
101
118
102
119
// instantiateLazy avoids actually instantiating the type until needed. typ
103
120
// must be a *Named type.
104
- func (check * Checker ) instantiateLazy (pos syntax.Pos , orig * Named , targs []Type , posList []syntax.Pos , verify bool ) Type {
105
- if verify {
106
- if check == nil {
107
- // Provide a more useful panic instead of panicking at check.later below.
108
- panic ("cannot have nil Checker if verifying constraints" )
109
- }
110
- assert (len (posList ) <= len (targs ))
111
- if orig .TParams ().Len () == len (targs ) {
112
- check .later (func () {
113
- check .verify (pos , orig .tparams .list (), targs , posList )
114
- })
115
- }
116
- }
117
-
121
+ func (check * Checker ) instantiateLazy (pos syntax.Pos , orig * Named , targs []Type ) Type {
118
122
h := instantiatedHash (orig , targs )
119
123
if check != nil {
120
124
// typ may already have been instantiated with identical type arguments. In
@@ -136,9 +140,6 @@ func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type,
136
140
}
137
141
138
142
func (check * Checker ) verify (pos syntax.Pos , tparams []* TypeName , targs []Type , posList []syntax.Pos ) {
139
- if check == nil {
140
- panic ("cannot have nil Checker if verifying constraints" )
141
- }
142
143
smap := makeSubstMap (tparams , targs )
143
144
for i , tname := range tparams {
144
145
// best position for error reporting
0 commit comments