Source file src/cmd/compile/internal/types/structuraltype_test.go

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Test that StructuralType() calculates the correct value of structural type for
     6  // unusual cases.
     7  
     8  package types
     9  
    10  import (
    11  	"cmd/internal/src"
    12  	"testing"
    13  )
    14  
    15  type test struct {
    16  	typ            *Type
    17  	structuralType *Type
    18  }
    19  
    20  func TestStructuralType(t *testing.T) {
    21  	// These are the few constants that need to be initialized in order to use
    22  	// the types package without using the typecheck package by calling
    23  	// typecheck.InitUniverse() (the normal way to initialize the types package).
    24  	PtrSize = 8
    25  	RegSize = 8
    26  	MaxWidth = 1 << 50
    27  
    28  	// type intType = int
    29  	intType := newType(TINT)
    30  	// type structf = struct { f int }
    31  	structf := NewStruct(nil, []*Field{
    32  		NewField(src.NoXPos, LocalPkg.Lookup("f"), intType),
    33  	})
    34  
    35  	// type Sf structf
    36  	Sf := newType(TFORW)
    37  	Sf.sym = LocalPkg.Lookup("Sf")
    38  	Sf.SetUnderlying(structf)
    39  
    40  	// type A int
    41  	A := newType(TFORW)
    42  	A.sym = LocalPkg.Lookup("A")
    43  	A.SetUnderlying(intType)
    44  
    45  	// type B int
    46  	B := newType(TFORW)
    47  	B.sym = LocalPkg.Lookup("B")
    48  	B.SetUnderlying(intType)
    49  
    50  	emptyInterface := NewInterface(BuiltinPkg, []*Field{}, false)
    51  	any := newType(TFORW)
    52  	any.sym = LocalPkg.Lookup("any")
    53  	any.SetUnderlying(emptyInterface)
    54  
    55  	// The tests marked NONE have no structural type; all the others have a
    56  	// structural type of structf - "struct { f int }"
    57  	tests := []*test{
    58  		{
    59  			// interface { struct { f int } }
    60  			embed(structf),
    61  			structf,
    62  		},
    63  		{
    64  			// interface { struct { f int }; any }
    65  			embed(structf, any),
    66  			structf,
    67  		},
    68  		{
    69  			// interface { Sf }
    70  			embed(Sf),
    71  			structf,
    72  		},
    73  		{
    74  			// interface { any | Sf }
    75  			embed(any, Sf),
    76  			structf,
    77  		},
    78  		{
    79  			// interface { struct { f int }; Sf } - NONE
    80  			embed(structf, Sf),
    81  			nil,
    82  		},
    83  		{
    84  			// interface { struct { f int } | ~struct { f int } }
    85  			embed(NewUnion([]*Type{structf, structf}, []bool{false, true})),
    86  			structf,
    87  		},
    88  		{
    89  			// interface { ~struct { f int } ; Sf }
    90  			embed(NewUnion([]*Type{structf}, []bool{true}), Sf),
    91  			structf,
    92  		},
    93  		{
    94  			// interface { struct { f int } ; Sf } - NONE
    95  			embed(NewUnion([]*Type{structf}, []bool{false}), Sf),
    96  			nil,
    97  		},
    98  		{
    99  			// interface { Sf | A; B | Sf}
   100  			embed(NewUnion([]*Type{Sf, A}, []bool{false, false}),
   101  				NewUnion([]*Type{B, Sf}, []bool{false, false})),
   102  			structf,
   103  		},
   104  		{
   105  			// interface { Sf | A; A | Sf } - NONE
   106  			embed(NewUnion([]*Type{Sf, A}, []bool{false, false}),
   107  				NewUnion([]*Type{A, Sf}, []bool{false, false})),
   108  			nil,
   109  		},
   110  		{
   111  			// interface { Sf | any } - NONE
   112  			embed(NewUnion([]*Type{Sf, any}, []bool{false, false})),
   113  			nil,
   114  		},
   115  		{
   116  			// interface { Sf | any; Sf }
   117  			embed(NewUnion([]*Type{Sf, any}, []bool{false, false}), Sf),
   118  			structf,
   119  		},
   120  	}
   121  	for _, tst := range tests {
   122  		if got, want := tst.typ.StructuralType(), tst.structuralType; got != want {
   123  			t.Errorf("StructuralType(%v) = %v, wanted %v",
   124  				tst.typ, got, want)
   125  		}
   126  	}
   127  }
   128  
   129  func embed(types ...*Type) *Type {
   130  	fields := make([]*Field, len(types))
   131  	for i, t := range types {
   132  		fields[i] = NewField(src.NoXPos, nil, t)
   133  	}
   134  	return NewInterface(LocalPkg, fields, false)
   135  }
   136  

View as plain text