From 22e926546732e4ea1fb20551be4b91f51f3b6e65 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 13:02:24 -0700 Subject: [dev.typeparams] cmd/compile/internal/types2: replace types2.Instantiate with Checker.Instantiate Allow Checker.Instantiate to work with a nil *Checker receiver (for now). This opens the door to passing in a *Checker at all times. Also, added a verify flag to Instantiate, InstantiateLazy, and instance, to be able to control if constraint satisfaction should be checked or not. Removed types2.Instantiate. For #47103. Change-Id: Ie00ce41b3e50a0fc4341e013922e5f874276d282 Reviewed-on: https://go-review.googlesource.com/c/go/+/333569 Trust: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/subst.go | 55 +++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'src/cmd/compile/internal/types2/subst.go') diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 6e4e778b20..32cf527372 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -53,8 +53,24 @@ func (m *substMap) lookup(tpar *TypeParam) Type { return tpar } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslist []syntax.Pos) (res Type) { - if check.conf.Trace { +// Instantiate instantiates the type typ with the given type arguments +// targs. To check type constraint satisfaction, verify must be set. +// pos and posList correspond to the instantiation and type argument +// positions respectively; posList may be nil or shorter than the number +// of type arguments provided. +// typ must be a *Named or a *Signature type, and its number of type +// parameters must match the number of provided type arguments. +// The receiver (check) may be nil if and only if verify is not set. +// The result is a new, instantiated (not generic) type of the same kind +// (either a *Named or a *Signature). +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && check.conf.Trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) check.indent++ defer func() { @@ -70,7 +86,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis }() } - assert(len(poslist) <= len(targs)) + assert(len(posList) <= len(targs)) // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? var tparams []*TypeName @@ -97,18 +113,19 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() - default: - check.dump("%v: cannot instantiate %v", pos, typ) - unreachable() // only defined types and (defined) functions can be generic - + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message - check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] + if check != nil { + check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } if len(tparams) == 0 { @@ -118,15 +135,17 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis smap := makeSubstMap(tparams, targs) // check bounds - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(poslist) { - pos = poslist[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break + if verify { + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } } } -- cgit v1.2.3-54-g00ecf