mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] cmd/compile: get type aliases working with generic types
Generic types can the source type of a type alias, so modify g.typ0() to be able to deal with base generic types. Added test aliasimp.go that tests aliasing of local generic types and imported generic types. Change-Id: I1c398193819d47a36b014cc1f9bb55107e9a565b Reviewed-on: https://go-review.googlesource.com/c/go/+/322194 Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
95748d1b74
commit
b7f7d1cd7b
|
@ -91,50 +91,49 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
|
||||||
case *types2.Basic:
|
case *types2.Basic:
|
||||||
return g.basic(typ)
|
return g.basic(typ)
|
||||||
case *types2.Named:
|
case *types2.Named:
|
||||||
if typ.TParams() != nil {
|
// If tparams is set, but targs is not, typ is a base generic
|
||||||
|
// type. typ is appearing as part of the source type of an alias,
|
||||||
|
// since that is the only use of a generic type that doesn't
|
||||||
|
// involve instantiation. We just translate the named type in the
|
||||||
|
// normal way below using g.obj().
|
||||||
|
if typ.TParams() != nil && typ.TArgs() != nil {
|
||||||
// typ is an instantiation of a defined (named) generic type.
|
// typ is an instantiation of a defined (named) generic type.
|
||||||
// This instantiation should also be a defined (named) type.
|
// This instantiation should also be a defined (named) type.
|
||||||
// types2 gives us the substituted type in t.Underlying()
|
// types2 gives us the substituted type in t.Underlying()
|
||||||
// The substituted type may or may not still have type
|
// The substituted type may or may not still have type
|
||||||
// params. We might, for example, be substituting one type
|
// params. We might, for example, be substituting one type
|
||||||
// param for another type param.
|
// param for another type param.
|
||||||
|
//
|
||||||
if typ.TArgs() == nil {
|
// When converted to types.Type, typ has a unique name,
|
||||||
base.Fatalf("In typ0, Targs should be set if TParams is set")
|
// based on the names of the type arguments.
|
||||||
}
|
|
||||||
|
|
||||||
// When converted to types.Type, typ must have a name,
|
|
||||||
// based on the names of the type arguments. We need a
|
|
||||||
// name to deal with recursive generic types (and it also
|
|
||||||
// looks better when printing types).
|
|
||||||
instName := instTypeName2(typ.Obj().Name(), typ.TArgs())
|
instName := instTypeName2(typ.Obj().Name(), typ.TArgs())
|
||||||
s := g.pkg(typ.Obj().Pkg()).Lookup(instName)
|
s := g.pkg(typ.Obj().Pkg()).Lookup(instName)
|
||||||
if s.Def != nil {
|
if s.Def != nil {
|
||||||
// We have already encountered this instantiation,
|
// We have already encountered this instantiation.
|
||||||
// so use the type we previously created, since there
|
// Use the type we previously created, since there
|
||||||
// must be exactly one instance of a defined type.
|
// must be exactly one instance of a defined type.
|
||||||
return s.Def.Type()
|
return s.Def.Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a forwarding type first and put it in the g.typs
|
// Create a forwarding type first and put it in the g.typs
|
||||||
// map, in order to deal with recursive generic types.
|
// map, in order to deal with recursive generic types
|
||||||
// Fully set up the extra ntyp information (Def, RParams,
|
// (including via method signatures).. Set up the extra
|
||||||
// which may set HasTParam) before translating the
|
// ntyp information (Def, RParams, which may set
|
||||||
// underlying type itself, so we handle recursion
|
// HasTParam) before translating the underlying type
|
||||||
// correctly, including via method signatures.
|
// itself, so we handle recursion correctly.
|
||||||
ntyp := typecheck.NewIncompleteNamedType(g.pos(typ.Obj().Pos()), s)
|
ntyp := typecheck.NewIncompleteNamedType(g.pos(typ.Obj().Pos()), s)
|
||||||
g.typs[typ] = ntyp
|
g.typs[typ] = ntyp
|
||||||
|
|
||||||
// If ntyp still has type params, then we must be
|
// If ntyp still has type params, then we must be
|
||||||
// referencing something like 'value[T2]', as when
|
// referencing something like 'value[T2]', as when
|
||||||
// specifying the generic receiver of a method,
|
// specifying the generic receiver of a method, where
|
||||||
// where value was defined as "type value[T any]
|
// value was defined as "type value[T any] ...". Save the
|
||||||
// ...". Save the type args, which will now be the
|
// type args, which will now be the new typeparams of the
|
||||||
// new type of the current type.
|
// current type.
|
||||||
//
|
//
|
||||||
// If ntyp does not have type params, we are saving the
|
// If ntyp does not have type params, we are saving the
|
||||||
// concrete types used to instantiate this type. We'll use
|
// non-generic types used to instantiate this type. We'll
|
||||||
// these when instantiating the methods of the
|
// use these when instantiating the methods of the
|
||||||
// instantiated type.
|
// instantiated type.
|
||||||
rparams := make([]*types.Type, len(typ.TArgs()))
|
rparams := make([]*types.Type, len(typ.TArgs()))
|
||||||
for i, targ := range typ.TArgs() {
|
for i, targ := range typ.TArgs() {
|
||||||
|
|
9
test/typeparam/aliasimp.dir/a.go
Normal file
9
test/typeparam/aliasimp.dir/a.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2020 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 a
|
||||||
|
|
||||||
|
type Rimp[T any] struct {
|
||||||
|
F T
|
||||||
|
}
|
38
test/typeparam/aliasimp.dir/main.go
Normal file
38
test/typeparam/aliasimp.dir/main.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2020 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
|
||||||
|
|
||||||
|
import "a"
|
||||||
|
|
||||||
|
type R[T any] struct {
|
||||||
|
F T
|
||||||
|
}
|
||||||
|
|
||||||
|
type S = R
|
||||||
|
|
||||||
|
type Sint = R[int]
|
||||||
|
|
||||||
|
type Simp = a.Rimp
|
||||||
|
|
||||||
|
type SimpString Simp[string]
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var s S[int]
|
||||||
|
if s.F != 0 {
|
||||||
|
panic(s.F)
|
||||||
|
}
|
||||||
|
var s2 Sint
|
||||||
|
if s2.F != 0 {
|
||||||
|
panic(s2.F)
|
||||||
|
}
|
||||||
|
var s3 Simp[string]
|
||||||
|
if s3.F != "" {
|
||||||
|
panic(s3.F)
|
||||||
|
}
|
||||||
|
var s4 SimpString
|
||||||
|
if s4.F != "" {
|
||||||
|
panic(s4.F)
|
||||||
|
}
|
||||||
|
}
|
7
test/typeparam/aliasimp.go
Normal file
7
test/typeparam/aliasimp.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// rundir -G=3
|
||||||
|
|
||||||
|
// 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 ignored
|
Loading…
Reference in a new issue