mirror of
https://github.com/golang/go
synced 2024-11-23 06:40:05 -07:00
8e6dfe1b31
Deal with export/import of recursive generic types. This includes typeparams which have bounds that reference the typeparam. There are three main changes: - Change export/import of typeparams to have an implicit "declaration" (doDecl). We need to do a declaration of typeparams (via the typeparam's package and unique name), because it may be referenced within its bound during its own definition. - We delay most of the processing of the Instantiate call until we finish the creation of the top-most type (similar to the way we delay CheckSize). This is because we can't do the full instantiation properly until the base type is fully defined (with methods). The functions delayDoInst() and resumeDoInst() delay and resume the processing of the instantiations. - To do the full needed type substitutions for type instantiations during import, I had to separate out the type subster in stencil.go and move it to subr.go in the typecheck package. The subster in stencil.go now does node substitution and makes use of the type subster to do type substitutions. Notable other changes: - In types/builtins.go, put the newly defined typeparam for a union type (related to use of real/imag, etc.) in the current package, rather than the builtin package, so exports/imports work properly. - In types2, allowed NewTypeParam() to be called with a nil bound, and allow setting the bound later. (Needed to import a typeparam whose bound refers to the typeparam itself.) - During import of typeparams in types2 (importer/import.go), we need to keep an index of the typeparams by their package and unique name (with id). Use a new map typParamIndex[] for that. Again, this is needed to deal with typeparams whose bounds refer to the typeparam itself. - Added several new tests absdiffimp.go and orderedmapsimp.go. Some of the orderemapsimp tests are commented out for now, because there are some issues with closures inside instantiations (relating to unexported names of closure structs). - Renamed some typeparams in test value.go to make them all T (to make typeparam uniqueness is working fine). Change-Id: Ib47ed9471c19ee8e9fbb34e8506907dad3021e5a Reviewed-on: https://go-review.googlesource.com/c/go/+/323029 Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
98 lines
2.7 KiB
Go
98 lines
2.7 KiB
Go
// run -gcflags=-G=3
|
|
|
|
// 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 (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
type Numeric interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
|
~float32 | ~float64 |
|
|
~complex64 | ~complex128
|
|
}
|
|
|
|
// numericAbs matches numeric types with an Abs method.
|
|
type numericAbs[T any] interface {
|
|
Numeric
|
|
Abs() T
|
|
}
|
|
|
|
// AbsDifference computes the absolute value of the difference of
|
|
// a and b, where the absolute value is determined by the Abs method.
|
|
func absDifference[T numericAbs[T]](a, b T) T {
|
|
d := a - b
|
|
return d.Abs()
|
|
}
|
|
|
|
// orderedNumeric matches numeric types that support the < operator.
|
|
type orderedNumeric interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
|
~float32 | ~float64
|
|
}
|
|
|
|
// Complex matches the two complex types, which do not have a < operator.
|
|
type Complex interface {
|
|
~complex64 | ~complex128
|
|
}
|
|
|
|
// orderedAbs is a helper type that defines an Abs method for
|
|
// ordered numeric types.
|
|
type orderedAbs[T orderedNumeric] T
|
|
|
|
func (a orderedAbs[T]) Abs() orderedAbs[T] {
|
|
if a < 0 {
|
|
return -a
|
|
}
|
|
return a
|
|
}
|
|
|
|
// complexAbs is a helper type that defines an Abs method for
|
|
// complex types.
|
|
type complexAbs[T Complex] T
|
|
|
|
func (a complexAbs[T]) Abs() complexAbs[T] {
|
|
r := float64(real(a))
|
|
i := float64(imag(a))
|
|
d := math.Sqrt(r * r + i * i)
|
|
return complexAbs[T](complex(d, 0))
|
|
}
|
|
|
|
// OrderedAbsDifference returns the absolute value of the difference
|
|
// between a and b, where a and b are of an ordered type.
|
|
func orderedAbsDifference[T orderedNumeric](a, b T) T {
|
|
return T(absDifference(orderedAbs[T](a), orderedAbs[T](b)))
|
|
}
|
|
|
|
// ComplexAbsDifference returns the absolute value of the difference
|
|
// between a and b, where a and b are of a complex type.
|
|
func complexAbsDifference[T Complex](a, b T) T {
|
|
return T(absDifference(complexAbs[T](a), complexAbs[T](b)))
|
|
}
|
|
|
|
func main() {
|
|
if got, want := orderedAbsDifference(1.0, -2.0), 3.0; got != want {
|
|
panic(fmt.Sprintf("got = %v, want = %v", got, want))
|
|
}
|
|
if got, want := orderedAbsDifference(-1.0, 2.0), 3.0; got != want {
|
|
panic(fmt.Sprintf("got = %v, want = %v", got, want))
|
|
}
|
|
if got, want := orderedAbsDifference(-20, 15), 35; got != want {
|
|
panic(fmt.Sprintf("got = %v, want = %v", got, want))
|
|
}
|
|
|
|
if got, want := complexAbsDifference(5.0 + 2.0i, 2.0 - 2.0i), 5+0i; got != want {
|
|
panic(fmt.Sprintf("got = %v, want = %v", got, want))
|
|
}
|
|
if got, want := complexAbsDifference(2.0 - 2.0i, 5.0 + 2.0i), 5+0i; got != want {
|
|
panic(fmt.Sprintf("got = %v, want = %v", got, want))
|
|
}
|
|
}
|