@@ -402,126 +402,189 @@ func TestTypesInfo(t *testing.T) {
402
402
}
403
403
}
404
404
405
- func TestInferredInfo (t * testing.T ) {
405
+ func TestInstanceInfo (t * testing.T ) {
406
406
var tests = []struct {
407
407
src string
408
- fun string
408
+ name string
409
409
targs []string
410
- sig string
410
+ typ string
411
411
}{
412
- {genericPkg + ` p0; func f[T any](T) {}; func _() { f(42) }` ,
412
+ {`package p0; func f[T any](T) {}; func _() { f(42) }` ,
413
413
`f` ,
414
414
[]string {`int` },
415
415
`func(int)` ,
416
416
},
417
- {genericPkg + ` p1; func f[T any](T) T { panic(0) }; func _() { f('@') }` ,
417
+ {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }` ,
418
418
`f` ,
419
419
[]string {`rune` },
420
420
`func(rune) rune` ,
421
421
},
422
- {genericPkg + ` p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }` ,
422
+ {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }` ,
423
423
`f` ,
424
424
[]string {`complex128` },
425
425
`func(...complex128) complex128` ,
426
426
},
427
- {genericPkg + ` p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }` ,
427
+ {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }` ,
428
428
`f` ,
429
429
[]string {`float64` , `string` , `byte` },
430
430
`func(float64, *string, []byte)` ,
431
431
},
432
- {genericPkg + ` p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }` ,
432
+ {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }` ,
433
433
`f` ,
434
434
[]string {`float64` , `byte` },
435
435
`func(float64, *byte, ...[]byte)` ,
436
436
},
437
437
438
- {genericPkg + ` s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }` ,
438
+ {`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }` ,
439
439
`f` ,
440
440
[]string {`string` , `*string` },
441
441
`func(x string)` ,
442
442
},
443
- {genericPkg + ` s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }` ,
443
+ {`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }` ,
444
444
`f` ,
445
445
[]string {`int` , `*int` },
446
446
`func(x []int)` ,
447
447
},
448
- {genericPkg + ` s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }` ,
448
+ {`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }` ,
449
449
`f` ,
450
450
[]string {`int` , `chan<- int` },
451
451
`func(x []int)` ,
452
452
},
453
- {genericPkg + ` s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }` ,
453
+ {`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }` ,
454
454
`f` ,
455
455
[]string {`int` , `chan<- int` , `chan<- []*chan<- int` },
456
456
`func(x []int)` ,
457
457
},
458
458
459
- {genericPkg + ` t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }` ,
459
+ {`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }` ,
460
460
`f` ,
461
461
[]string {`string` , `*string` },
462
462
`func() string` ,
463
463
},
464
- {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }` ,
464
+ {`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }` ,
465
+ `f` ,
466
+ []string {`string` , `*string` },
467
+ `func() string` ,
468
+ },
469
+ {`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }` ,
465
470
`f` ,
466
471
[]string {`int` , `chan<- int` },
467
472
`func() []int` ,
468
473
},
469
- {genericPkg + `t3 ; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }` ,
474
+ {`package t4 ; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }` ,
470
475
`f` ,
471
476
[]string {`int` , `chan<- int` , `chan<- []*chan<- int` },
472
477
`func() []int` ,
473
478
},
479
+ {`package i0; import "lib"; func _() { lib.F(42) }` ,
480
+ `F` ,
481
+ []string {`int` },
482
+ `func(int)` ,
483
+ },
484
+ {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]` ,
485
+ `T` ,
486
+ []string {`int` },
487
+ `struct{x int}` ,
488
+ },
489
+ {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])` ,
490
+ `T` ,
491
+ []string {`int` },
492
+ `struct{x int}` ,
493
+ },
494
+ {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]` ,
495
+ `T` ,
496
+ []string {`int` },
497
+ `struct{x int}` ,
498
+ },
499
+ {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]` ,
500
+ `T` ,
501
+ []string {`[]int` , `int` },
502
+ `struct{x []int; y int}` ,
503
+ },
504
+ {`package type4; import "lib"; var _ lib.T[int]` ,
505
+ `T` ,
506
+ []string {`int` },
507
+ `[]int` ,
508
+ },
474
509
}
475
510
476
511
for _ , test := range tests {
477
- info := Info {}
478
- info .Inferred = make (map [ast.Expr ]Inferred )
479
- name , err := mayTypecheck (t , "InferredInfo" , test .src , & info )
480
- if err != nil {
481
- t .Errorf ("package %s: %v" , name , err )
482
- continue
483
- }
512
+ const lib = `package lib
484
513
485
- // look for inferred type arguments and signature
486
- var targs * TypeList
487
- var sig * Signature
488
- for call , inf := range info .Inferred {
489
- var fun ast.Expr
490
- switch x := call .(type ) {
491
- case * ast.CallExpr :
492
- fun = x .Fun
493
- case * ast.IndexExpr :
494
- fun = x .X
495
- default :
496
- panic (fmt .Sprintf ("unexpected call expression type %T" , call ))
514
+ func F[P any](P) {}
515
+
516
+ type T[P any] []P
517
+ `
518
+
519
+ imports := make (testImporter )
520
+ conf := Config {Importer : imports }
521
+ instances := make (map [* ast.Ident ]Instance )
522
+ uses := make (map [* ast.Ident ]Object )
523
+ makePkg := func (src string ) * Package {
524
+ f , err := parser .ParseFile (fset , "p.go" , src , 0 )
525
+ if err != nil {
526
+ t .Fatal (err )
527
+ }
528
+ pkg , err := conf .Check ("" , fset , []* ast.File {f }, & Info {Instances : instances , Uses : uses })
529
+ if err != nil {
530
+ t .Fatal (err )
497
531
}
498
- if ExprString (fun ) == test .fun {
499
- targs = inf .TArgs
500
- sig = inf .Sig
532
+ imports [pkg .Name ()] = pkg
533
+ return pkg
534
+ }
535
+ makePkg (lib )
536
+ pkg := makePkg (test .src )
537
+
538
+ // look for instance information
539
+ var targs []Type
540
+ var typ Type
541
+ for ident , inst := range instances {
542
+ if ExprString (ident ) == test .name {
543
+ for i := 0 ; i < inst .TypeArgs .Len (); i ++ {
544
+ targs = append (targs , inst .TypeArgs .At (i ))
545
+ }
546
+ typ = inst .Type
547
+
548
+ // Check that we can find the corresponding parameterized type.
549
+ ptype := uses [ident ].Type ()
550
+ lister , _ := ptype .(interface { TypeParams () * TypeParamList })
551
+ if lister == nil || lister .TypeParams ().Len () == 0 {
552
+ t .Errorf ("package %s: info.Types[%v] = %v, want parameterized type" , pkg .Name (), ident , ptype )
553
+ continue
554
+ }
555
+
556
+ // Verify the invariant that re-instantiating the generic type with
557
+ // TypeArgs results in an equivalent type.
558
+ inst2 , err := Instantiate (nil , ptype , targs , true )
559
+ if err != nil {
560
+ t .Errorf ("Instantiate(%v, %v) failed: %v" , ptype , targs , err )
561
+ }
562
+ if ! Identical (inst .Type , inst2 ) {
563
+ t .Errorf ("%v and %v are not identical" , inst .Type , inst2 )
564
+ }
501
565
break
502
566
}
503
567
}
504
568
if targs == nil {
505
- t .Errorf ("package %s: no inferred information found for %s" , name , test .fun )
569
+ t .Errorf ("package %s: no instance information found for %s" , pkg . Name () , test .name )
506
570
continue
507
571
}
508
572
509
573
// check that type arguments are correct
510
- if targs . Len ( ) != len (test .targs ) {
511
- t .Errorf ("package %s: got %d type arguments; want %d" , name , targs . Len ( ), len (test .targs ))
574
+ if len ( targs ) != len (test .targs ) {
575
+ t .Errorf ("package %s: got %d type arguments; want %d" , pkg . Name (), len ( targs ), len (test .targs ))
512
576
continue
513
577
}
514
- for i := 0 ; i < targs .Len (); i ++ {
515
- targ := targs .At (i )
578
+ for i , targ := range targs {
516
579
if got := targ .String (); got != test .targs [i ] {
517
- t .Errorf ("package %s, %d. type argument: got %s; want %s" , name , i , got , test .targs [i ])
580
+ t .Errorf ("package %s, %d. type argument: got %s; want %s" , pkg . Name () , i , got , test .targs [i ])
518
581
continue
519
582
}
520
583
}
521
584
522
- // check that signature is correct
523
- if got := sig . String (); got != test .sig {
524
- t .Errorf ("package %s: got %s; want %s" , name , got , test .sig )
585
+ // check that the types match
586
+ if got := typ . Underlying (). String (); got != test .typ {
587
+ t .Errorf ("package %s: got %s; want %s" , pkg . Name () , got , test .typ )
525
588
}
526
589
}
527
590
}
0 commit comments