mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
![Dan Scales](/assets/img/avatar_default.png)
Since we use existing instantiations from the symbol table when possible (to make sure each instantiation is unique), we need to pop instantiations of local types when leaving the containing scope. g.stmts() now pushes and pops scope, and we do a Pushdcl() in g.typ0() when creating an instantiation of a local type. Non-instantiated local types (generic or not) are translated directly from types2, so they don't need to be pushed/popped. We don't export function bodies with local types, so there is no issue during import. We still don't support local types in generic functions/methods. Fixes #50177 Change-Id: If2d2fe71aec003d13f0338565c7a0da2c9580a14 Reviewed-on: https://go-review.googlesource.com/c/go/+/372654 Reviewed-by: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
102 lines
2 KiB
Go
102 lines
2 KiB
Go
// compile -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 main
|
|
|
|
import "fmt"
|
|
|
|
type Fn[T any] func(T)
|
|
type FnErr[T any] func(T) error
|
|
|
|
// Test that local generic types across functions don't conflict, and they also don't
|
|
// conflict with local non-generic types and local variables.
|
|
func caller0() {
|
|
type X[T any] struct {
|
|
fn Fn[int]
|
|
}
|
|
|
|
x := X[int]{func(v int) { fmt.Println(v) }}
|
|
x.fn(0)
|
|
}
|
|
|
|
func caller1(val int) {
|
|
type X[T any] struct {
|
|
fn FnErr[int]
|
|
}
|
|
|
|
x := X[int]{func(v int) error { fmt.Println(v); return nil }}
|
|
x.fn(0)
|
|
}
|
|
|
|
func caller1a(val int) {
|
|
type X struct {
|
|
fn func(float64) error
|
|
}
|
|
|
|
x := X{func(v float64) error { fmt.Println(v); return nil }}
|
|
x.fn(float64(3.2))
|
|
}
|
|
|
|
func caller1b(val int) {
|
|
type Y struct {
|
|
fn func(float64) error
|
|
}
|
|
|
|
X := Y{func(v float64) error { fmt.Println(v); return nil }}
|
|
X.fn(float64(3.2))
|
|
}
|
|
|
|
// Test that local generic types within different if clauses don't conflict.
|
|
func caller2(val int) {
|
|
if val > 2 {
|
|
type X[T any] struct {
|
|
fn func(v int) float64
|
|
}
|
|
|
|
x := X[int]{func(v int) float64 { fmt.Println(v); return 1.5 }}
|
|
x.fn(0)
|
|
} else {
|
|
type X[T any] struct {
|
|
fn func(v int) int
|
|
}
|
|
x := X[int]{func(v int) int { fmt.Println(v); return 5 }}
|
|
x.fn(0)
|
|
}
|
|
}
|
|
|
|
// Test that local generic types within different cases don't conflict with each
|
|
// other or with local non-generic types or local variables.
|
|
func caller3(val int) {
|
|
switch val {
|
|
case 0:
|
|
type X[T any] struct {
|
|
fn func(v int) float64
|
|
}
|
|
|
|
x := X[int]{func(v int) float64 { fmt.Println(v); return 1.5 }}
|
|
x.fn(0)
|
|
case 1:
|
|
type X[T any] struct {
|
|
fn func(v int) int
|
|
}
|
|
x := X[int]{func(v int) int { fmt.Println(v); return 5 }}
|
|
x.fn(0)
|
|
case 2:
|
|
type X struct {
|
|
fn func(v int) bool
|
|
}
|
|
x := X{func(v int) bool { fmt.Println(v); return false }}
|
|
x.fn(0)
|
|
case 3:
|
|
type Y struct {
|
|
fn func(v int) bool
|
|
}
|
|
X := Y{func(v int) bool { fmt.Println(v); return false }}
|
|
X.fn(0)
|
|
|
|
}
|
|
}
|