Fixes #69576.
Change-Id: I8fc077970276977dd89fc2dd3867f2765d52e54e
Reviewed-on: https://go-review.googlesource.com/c/go/+/615275
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
// verify instantiation lazily (was go.dev/issue/50450)
check.later(func() {
tparams := typ.TypeParams().list()
+ // check type constraints
if i, err := check.verify(pos, tparams, targs, check.context()); err != nil {
// best position for error reporting
pos := pos
return nil
}
-// update de-duplicates n against previously seen types with the hash h. If an
-// identical type is found with the type hash h, the previously seen type is
-// returned. Otherwise, n is returned, and recorded in the Context for the hash
-// h.
+// update de-duplicates inst against previously seen types with the hash h.
+// If an identical type is found with the type hash h, the previously seen
+// type is returned. Otherwise, inst is returned, and recorded in the Context
+// for the hash h.
func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type {
assert(inst != nil)
return orig // nothing to do (minor optimization)
}
- return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
+ res = check.newAliasInstance(pos, orig, targs, expanding, ctxt)
case *Signature:
assert(expanding == nil) // function instances cannot be reached from Named types
}()
var cause string
- gtyp := check.genericType(x, &cause)
+ typ := check.genericType(x, &cause)
if cause != "" {
check.errorf(x, NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, cause)
}
- if !isValid(gtyp) {
- return gtyp // error already reported
+ if !isValid(typ) {
+ return typ // error already reported
}
+ // typ must be a generic Alias or Named type (but not a *Signature)
+ if _, ok := typ.(*Signature); ok {
+ panic("unexpected generic signature")
+ }
+ gtyp := typ.(genericType)
// evaluate arguments
targs := check.typeList(xlist)
return Typ[Invalid]
}
- if orig, _ := gtyp.(*Alias); orig != nil {
- return check.instance(x.Pos(), orig, targs, nil, check.context())
- }
-
- orig := asNamed(gtyp)
- if orig == nil {
- panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp))
- }
-
- // create the instance
- inst := asNamed(check.instance(x.Pos(), orig, targs, nil, check.context()))
+ // create instance
+ // The instance is not generic anymore as it has type arguments, but it still
+ // satisfies the genericType interface because it has type parameters, too.
+ inst := check.instance(x.Pos(), gtyp, targs, nil, check.context()).(genericType)
- // orig.tparams may not be set up, so we need to do expansion later.
+ // For Named types, orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {
// This is an instance from the source, not from recursive substitution,
// and so it must be resolved during type-checking so that we can report
// errors.
- check.recordInstance(x, inst.TypeArgs().list(), inst)
+ check.recordInstance(x, targs, inst)
- if check.validateTArgLen(x.Pos(), inst.obj.name, inst.TypeParams().Len(), inst.TypeArgs().Len()) {
- if i, err := check.verify(x.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), check.context()); err != nil {
+ name := inst.(interface{ Obj() *TypeName }).Obj().name
+ tparams := inst.TypeParams().list()
+ if check.validateTArgLen(x.Pos(), name, len(tparams), len(targs)) {
+ // check type constraints
+ if i, err := check.verify(x.Pos(), inst.TypeParams().list(), targs, check.context()); err != nil {
// best position for error reporting
pos := x.Pos()
if i < len(xlist) {
}
check.softErrorf(pos, InvalidTypeArg, "%s", err)
} else {
- check.mono.recordInstance(check.pkg, x.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), xlist)
+ check.mono.recordInstance(check.pkg, x.Pos(), tparams, targs, xlist)
}
}
-
- // TODO(rfindley): remove this call: we don't need to call validType here,
- // as cycles can only occur for types used inside a Named type declaration,
- // and so it suffices to call validType from declared types.
- check.validType(inst)
- }).describef(x, "resolve instance %s", inst)
+ }).describef(x, "verify instantiation %s", inst)
return inst
}
// verify instantiation lazily (was go.dev/issue/50450)
check.later(func() {
tparams := typ.TypeParams().list()
+ // check type constraints
if i, err := check.verify(pos, tparams, targs, check.context()); err != nil {
// best position for error reporting
pos := pos
return nil
}
-// update de-duplicates n against previously seen types with the hash h. If an
-// identical type is found with the type hash h, the previously seen type is
-// returned. Otherwise, n is returned, and recorded in the Context for the hash
-// h.
+// update de-duplicates inst against previously seen types with the hash h.
+// If an identical type is found with the type hash h, the previously seen
+// type is returned. Otherwise, inst is returned, and recorded in the Context
+// for the hash h.
func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type {
assert(inst != nil)
return orig // nothing to do (minor optimization)
}
- return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
+ res = check.newAliasInstance(pos, orig, targs, expanding, ctxt)
case *Signature:
assert(expanding == nil) // function instances cannot be reached from Named types
}()
var cause string
- gtyp := check.genericType(ix.X, &cause)
+ typ := check.genericType(ix.X, &cause)
if cause != "" {
check.errorf(ix.Orig, NotAGenericType, invalidOp+"%s (%s)", ix.Orig, cause)
}
- if !isValid(gtyp) {
- return gtyp // error already reported
+ if !isValid(typ) {
+ return typ // error already reported
}
+ // typ must be a generic Alias or Named type (but not a *Signature)
+ if _, ok := typ.(*Signature); ok {
+ panic("unexpected generic signature")
+ }
+ gtyp := typ.(genericType)
// evaluate arguments
targs := check.typeList(ix.Indices)
return Typ[Invalid]
}
- if orig, _ := gtyp.(*Alias); orig != nil {
- return check.instance(ix.Pos(), orig, targs, nil, check.context())
- }
-
- orig := asNamed(gtyp)
- if orig == nil {
- panic(fmt.Sprintf("%v: cannot instantiate %v", ix.Pos(), gtyp))
- }
-
- // create the instance
- inst := asNamed(check.instance(ix.Pos(), orig, targs, nil, check.context()))
+ // create instance
+ // The instance is not generic anymore as it has type arguments, but it still
+ // satisfies the genericType interface because it has type parameters, too.
+ inst := check.instance(ix.Pos(), gtyp, targs, nil, check.context()).(genericType)
- // orig.tparams may not be set up, so we need to do expansion later.
+ // For Named types, orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {
// This is an instance from the source, not from recursive substitution,
// and so it must be resolved during type-checking so that we can report
// errors.
- check.recordInstance(ix.Orig, inst.TypeArgs().list(), inst)
+ check.recordInstance(ix.Orig, targs, inst)
- if check.validateTArgLen(ix.Pos(), inst.obj.name, inst.TypeParams().Len(), inst.TypeArgs().Len()) {
- if i, err := check.verify(ix.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), check.context()); err != nil {
+ name := inst.(interface{ Obj() *TypeName }).Obj().name
+ tparams := inst.TypeParams().list()
+ if check.validateTArgLen(ix.Pos(), name, len(tparams), len(targs)) {
+ // check type constraints
+ if i, err := check.verify(ix.Pos(), inst.TypeParams().list(), targs, check.context()); err != nil {
// best position for error reporting
pos := ix.Pos()
if i < len(ix.Indices) {
}
check.softErrorf(atPos(pos), InvalidTypeArg, "%v", err)
} else {
- check.mono.recordInstance(check.pkg, ix.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), ix.Indices)
+ check.mono.recordInstance(check.pkg, ix.Pos(), tparams, targs, ix.Indices)
}
}
-
- // TODO(rfindley): remove this call: we don't need to call validType here,
- // as cycles can only occur for types used inside a Named type declaration,
- // and so it suffices to call validType from declared types.
- check.validType(inst)
- }).describef(ix, "resolve instance %s", inst)
+ }).describef(ix, "verify instantiation %s", inst)
return inst
}
--- /dev/null
+// -goexperiment=aliastypeparams -gotypesalias=1
+
+// Copyright 2024 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 p
+
+type A[P int] = struct{}
+
+var _ A[string /* ERROR "string does not satisfy int (string missing in int)" */]