From 3935b33b310f364aced53ef492df28245b10f986 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 9 Mar 2020 21:45:21 -0700 Subject: [PATCH] go/types: avoid follow-on panic after assertion failure in subst Also: Updated NOTES. Change-Id: Iabc45e46aa76bacf5c6984dab6f4bcab74392562 --- src/go/types/NOTES | 3 ++- src/go/types/contracts.go | 3 +++ src/go/types/subst.go | 7 ++++++- src/go/types/testdata/tmp.go2 | 17 +++++++++++++---- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/go/types/NOTES b/src/go/types/NOTES index 335eb58c5a..ecb80d62e5 100644 --- a/src/go/types/NOTES +++ b/src/go/types/NOTES @@ -4,7 +4,7 @@ so we have a better track record. I only switched to this file in Nov 2019, henc ---------------------------------------------------------------------------------------------------- TODO -- use Underlying() to return a type parameter's bound? investigate! +- review embedding of contracts with multiple and different numbers of arguments - likely incorrect - debug (and error msg) printing of generic instantiated types needs some work - improve error messages! - use []*TypeParam for tparams in subst? (unclear) @@ -14,6 +14,7 @@ TODO ---------------------------------------------------------------------------------------------------- KNOWN ISSUES +- 'comparable' predeclared contract is not implemented yet - iteration over generic variables doesn't report certain channel errors (see TODOs in code) - cannot handle mutually recursive parameterized interfaces using themselves as type bounds - contract instantiation requires the type arguments to be type parameters from the type of function diff --git a/src/go/types/contracts.go b/src/go/types/contracts.go index 817368efb7..818ca05484 100644 --- a/src/go/types/contracts.go +++ b/src/go/types/contracts.go @@ -137,6 +137,9 @@ func (check *Checker) contractDecl(obj *Contract, cdecl *ast.ContractSpec) { // add the instantiated bounds as embedded interfaces to the respective // embedding (outer) contract bound + // TODO(gri) This seems incorrect. We must accomodate the situation where + // the embedded interfaces have different type parameters than + // the embedding interfaces. for i, ebound := range eobj.Bounds { index := targs[i].(*TypeParam).index iface := bounds[index].underlying.(*Interface) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 2326795e86..7f6427df76 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -73,6 +73,11 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist case *Signature: tparams = t.tparams defer func() { + // If we had an unexpected failure somewhere don't + // panic below when asserting res.(*Signature). + if res == nil { + return + } // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). @@ -80,7 +85,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist copy := *t res = © } - // After instantiating a generic signure, it is not generic + // After instantiating a generic signature, it is not generic // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index 7255712b55..261cf2cb52 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -2,9 +2,18 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package p +package main -type T(type a, b, c) struct {} +contract anInt(T) { + T int +} -//func (_ T(_, T(_, _, _), _)) m() {} -func (_ T(_, int, _)) m() {} +contract twoInt(K, _) { + anInt(K) +} + +func f(type K, V twoInt)() + +func _ () { + // f(int, int)() // this fails at the moment +} \ No newline at end of file