From e658c42ba460b91d5b6934829ddffa802d4ca524 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 11 Nov 2021 20:15:02 -0500 Subject: [PATCH] go/types: add a test for Context deduplication of hash collisions Add a test that exercises the fall-back logic in Context to handle hash collisions by de-duplicating using Identical. This has to be a somewhat invasive test because we don't know any actual cases of hash collisions. Change-Id: Idf00f7a6ab8c7517ed0f91fdc42d54f5e736b1b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/363517 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/context_test.go | 70 ++++++++++++++++++++++++++++++++++++ src/go/types/types_test.go | 8 ----- 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 src/go/types/context_test.go delete mode 100644 src/go/types/types_test.go diff --git a/src/go/types/context_test.go b/src/go/types/context_test.go new file mode 100644 index 0000000000..ec30050202 --- /dev/null +++ b/src/go/types/context_test.go @@ -0,0 +1,70 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/token" + "testing" +) + +func TestContextHashCollisions(t *testing.T) { + if debug { + t.Skip("hash collisions are expected, and would fail debug assertions") + } + // Unit test the de-duplication fall-back logic in Context. + // + // We can't test this via Instantiate because this is only a fall-back in + // case our hash is imperfect. + // + // These lookups and updates use reasonable looking types in an attempt to + // make them robust to internal type assertions, but could equally well use + // arbitrary types. + + // Create some distinct origin types. nullaryP and nullaryQ have no + // parameters and are identical (but have different type parameter names). + // unaryP has a parameter. + var nullaryP, nullaryQ, unaryP Type + { + // type nullaryP = func[P any]() + tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "P", nil), &emptyInterface) + nullaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) + } + { + // type nullaryQ = func[Q any]() + tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "Q", nil), &emptyInterface) + nullaryQ = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) + } + { + // type unaryP = func[P any](_ P) + tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "P", nil), &emptyInterface) + params := NewTuple(NewVar(token.NoPos, nil, "_", tparam)) + unaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, params, nil, false) + } + + ctxt := NewContext() + + // Update the context with an instantiation of nullaryP. + inst := NewSignatureType(nil, nil, nil, nil, nil, false) + if got := ctxt.update("", nullaryP, []Type{Typ[Int]}, inst); got != inst { + t.Error("bad") + } + + // unaryP is not identical to nullaryP, so we should not get inst when + // instantiated with identical type arguments. + if got := ctxt.lookup("", unaryP, []Type{Typ[Int]}); got != nil { + t.Error("bad") + } + + // nullaryQ is identical to nullaryP, so we *should* get inst when + // instantiated with identical type arguments. + if got := ctxt.lookup("", nullaryQ, []Type{Typ[Int]}); got != inst { + t.Error("bad") + } + + // ...but verify we don't get inst with different type arguments. + if got := ctxt.lookup("", nullaryQ, []Type{Typ[String]}); got != nil { + t.Error("bad") + } +} diff --git a/src/go/types/types_test.go b/src/go/types/types_test.go deleted file mode 100644 index f2358c6e19..0000000000 --- a/src/go/types/types_test.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types - -// Debug is set if go/types is built with debug mode enabled. -const Debug = debug -- 2.48.1