mirror of
https://github.com/golang/go
synced 2024-11-21 23:34:42 -07:00
types2, go/types: fix instantiation of named type with generic alias
The typechecker is assuming that alias instances cannot be reached from a named type. However, when type parameters on aliases are permited, it can happen. This CL changes the typechecker to propagate the correct named instance is being expanded. Updates #46477 Fixes #68580 Change-Id: Id0879021f4640c0fefe277701d5096c649413811 Reviewed-on: https://go-review.googlesource.com/c/go/+/601115 Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
d8c7230c97
commit
9b4b4ae585
@ -134,10 +134,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
|
|||||||
// newAliasInstance creates a new alias instance for the given origin and type
|
// newAliasInstance creates a new alias instance for the given origin and type
|
||||||
// arguments, recording pos as the position of its synthetic object (for error
|
// arguments, recording pos as the position of its synthetic object (for error
|
||||||
// reporting).
|
// reporting).
|
||||||
func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
|
func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
|
||||||
assert(len(targs) > 0)
|
assert(len(targs) > 0)
|
||||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
||||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
|
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
|
||||||
res := check.newAlias(obj, rhs)
|
res := check.newAlias(obj, rhs)
|
||||||
res.orig = orig
|
res.orig = orig
|
||||||
res.tparams = orig.tparams
|
res.tparams = orig.tparams
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"internal/buildcfg"
|
||||||
. "internal/types/errors"
|
. "internal/types/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,8 +127,9 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
|
|||||||
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||||
|
|
||||||
case *Alias:
|
case *Alias:
|
||||||
// TODO(gri) is this correct?
|
if !buildcfg.Experiment.AliasTypeParams {
|
||||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||||
|
}
|
||||||
|
|
||||||
tparams := orig.TypeParams()
|
tparams := orig.TypeParams()
|
||||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
||||||
@ -138,7 +140,7 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
|
|||||||
return orig // nothing to do (minor optimization)
|
return orig // nothing to do (minor optimization)
|
||||||
}
|
}
|
||||||
|
|
||||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||||
|
|
||||||
case *Signature:
|
case *Signature:
|
||||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
assert(expanding == nil) // function instances cannot be reached from Named types
|
||||||
|
@ -115,7 +115,7 @@ func (subst *subster) typ(typ Type) Type {
|
|||||||
// that has a type argument for it.
|
// that has a type argument for it.
|
||||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||||
if updated {
|
if updated {
|
||||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
|
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *Array:
|
case *Array:
|
||||||
|
@ -137,10 +137,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
|
|||||||
// newAliasInstance creates a new alias instance for the given origin and type
|
// newAliasInstance creates a new alias instance for the given origin and type
|
||||||
// arguments, recording pos as the position of its synthetic object (for error
|
// arguments, recording pos as the position of its synthetic object (for error
|
||||||
// reporting).
|
// reporting).
|
||||||
func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
|
func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
|
||||||
assert(len(targs) > 0)
|
assert(len(targs) > 0)
|
||||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
||||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
|
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
|
||||||
res := check.newAlias(obj, rhs)
|
res := check.newAlias(obj, rhs)
|
||||||
res.orig = orig
|
res.orig = orig
|
||||||
res.tparams = orig.tparams
|
res.tparams = orig.tparams
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"internal/buildcfg"
|
||||||
. "internal/types/errors"
|
. "internal/types/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,8 +130,9 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
|
|||||||
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||||
|
|
||||||
case *Alias:
|
case *Alias:
|
||||||
// TODO(gri) is this correct?
|
if !buildcfg.Experiment.AliasTypeParams {
|
||||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||||
|
}
|
||||||
|
|
||||||
tparams := orig.TypeParams()
|
tparams := orig.TypeParams()
|
||||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
||||||
@ -141,7 +143,7 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
|
|||||||
return orig // nothing to do (minor optimization)
|
return orig // nothing to do (minor optimization)
|
||||||
}
|
}
|
||||||
|
|
||||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||||
|
|
||||||
case *Signature:
|
case *Signature:
|
||||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
assert(expanding == nil) // function instances cannot be reached from Named types
|
||||||
|
@ -118,7 +118,7 @@ func (subst *subster) typ(typ Type) Type {
|
|||||||
// that has a type argument for it.
|
// that has a type argument for it.
|
||||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||||
if updated {
|
if updated {
|
||||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
|
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *Array:
|
case *Array:
|
||||||
|
15
test/fixedbugs/issue68580.go
Normal file
15
test/fixedbugs/issue68580.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// compile -goexperiment aliastypeparams
|
||||||
|
|
||||||
|
// 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 main
|
||||||
|
|
||||||
|
type A[P any] = struct{ _ P }
|
||||||
|
|
||||||
|
type N[P any] A[P]
|
||||||
|
|
||||||
|
func f[P any](N[P]) {}
|
||||||
|
|
||||||
|
var _ = f[int]
|
Loading…
Reference in New Issue
Block a user