1// Copyright 2021 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 5package types2 6 7import ( 8 "testing" 9) 10 11func TestContextHashCollisions(t *testing.T) { 12 if debug { 13 t.Skip("hash collisions are expected, and would fail debug assertions") 14 } 15 // Unit test the de-duplication fall-back logic in Context. 16 // 17 // We can't test this via Instantiate because this is only a fall-back in 18 // case our hash is imperfect. 19 // 20 // These lookups and updates use reasonable looking types in an attempt to 21 // make them robust to internal type assertions, but could equally well use 22 // arbitrary types. 23 24 // Create some distinct origin types. nullaryP and nullaryQ have no 25 // parameters and are identical (but have different type parameter names). 26 // unaryP has a parameter. 27 var nullaryP, nullaryQ, unaryP Type 28 { 29 // type nullaryP = func[P any]() 30 tparam := NewTypeParam(NewTypeName(nopos, nil, "P", nil), &emptyInterface) 31 nullaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) 32 } 33 { 34 // type nullaryQ = func[Q any]() 35 tparam := NewTypeParam(NewTypeName(nopos, nil, "Q", nil), &emptyInterface) 36 nullaryQ = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) 37 } 38 { 39 // type unaryP = func[P any](_ P) 40 tparam := NewTypeParam(NewTypeName(nopos, nil, "P", nil), &emptyInterface) 41 params := NewTuple(NewVar(nopos, nil, "_", tparam)) 42 unaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, params, nil, false) 43 } 44 45 ctxt := NewContext() 46 47 // Update the context with an instantiation of nullaryP. 48 inst := NewSignatureType(nil, nil, nil, nil, nil, false) 49 if got := ctxt.update("", nullaryP, []Type{Typ[Int]}, inst); got != inst { 50 t.Error("bad") 51 } 52 53 // unaryP is not identical to nullaryP, so we should not get inst when 54 // instantiated with identical type arguments. 55 if got := ctxt.lookup("", unaryP, []Type{Typ[Int]}); got != nil { 56 t.Error("bad") 57 } 58 59 // nullaryQ is identical to nullaryP, so we *should* get inst when 60 // instantiated with identical type arguments. 61 if got := ctxt.lookup("", nullaryQ, []Type{Typ[Int]}); got != inst { 62 t.Error("bad") 63 } 64 65 // ...but verify we don't get inst with different type arguments. 66 if got := ctxt.lookup("", nullaryQ, []Type{Typ[String]}); got != nil { 67 t.Error("bad") 68 } 69} 70