File tree 2 files changed +16
-2
lines changed
2 files changed +16
-2
lines changed Original file line number Diff line number Diff line change @@ -35,6 +35,9 @@ type Z17 interface {
35
35
}
36
36
func F17(type T Z17)(T)
37
37
38
+ // crash 18
39
+ type o18(type T) []func(_ o18([]_ /* ERROR cannot use _ */ ))
40
+
38
41
// crash 19
39
42
type Z19 [][[]Z19{}[0][0]]c19 /* ERROR undeclared */
40
43
Original file line number Diff line number Diff line change @@ -240,19 +240,20 @@ type subster struct {
240
240
func (subst * subster ) typ (typ Type ) Type {
241
241
switch t := typ .(type ) {
242
242
case nil :
243
+ // Call typOrNil if it's possible that typ is nil.
243
244
panic ("nil typ" )
244
245
245
246
case * Basic , * bottom , * top :
246
247
// nothing to do
247
248
248
249
case * Array :
249
- elem := subst .typ (t .elem )
250
+ elem := subst .typOrNil (t .elem )
250
251
if elem != t .elem {
251
252
return & Array {len : t .len , elem : elem }
252
253
}
253
254
254
255
case * Slice :
255
- elem := subst .typ (t .elem )
256
+ elem := subst .typOrNil (t .elem )
256
257
if elem != t .elem {
257
258
return & Slice {elem : elem }
258
259
}
@@ -448,6 +449,16 @@ func typeListString(list []Type) string {
448
449
return buf .String ()
449
450
}
450
451
452
+ // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid].
453
+ // A nil type may appear in pathological cases such as type T(type P) []func(_ T([]_))
454
+ // where an array/slice element is accessed before it is set up.
455
+ func (subst * subster ) typOrNil (typ Type ) Type {
456
+ if typ == nil {
457
+ return Typ [Invalid ]
458
+ }
459
+ return subst .typ (typ )
460
+ }
461
+
451
462
func (subst * subster ) var_ (v * Var ) * Var {
452
463
if v != nil {
453
464
if typ := subst .typ (v .typ ); typ != v .typ {
You can’t perform that action at this time.
0 commit comments