go/types: implement conversions to generic types

Change-Id: Ifa878fddea3548a27579b3196921c6816f2d9363
This commit is contained in:
Robert Griesemer 2019-12-15 20:18:18 -08:00
parent 75897ab270
commit 29f795f511
3 changed files with 37 additions and 6 deletions

View File

@ -1,6 +1,6 @@
TODO
- allow recursive type parameterization without need to repeat type parameters
- if type parameters are repeated in recursive instantiation, they must be the same order
- if type parameters are repeated in recursive instantiation, they must be the same order (not yet checked)
- implement contract embedding
- interface embedding doesn't take care of literal type constraints yet
(need an allTypes list, like we have an allMethods list?)
@ -8,7 +8,6 @@ TODO
OPEN ISSUES
- using a contract and enumerating type arguments currently leads to an error (e.g. func f(type T C(T)) (x T) ... )
git add - contracts slip through in places where only types are permitted
- conversions against parameterized types are not implemented
- parameterized interface methods (of type bounds) need to be customized (subst) for context
DESIGN DECISIONS

View File

@ -510,6 +510,39 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
return
}
// In case of a type parameter, conversion must succeed against
// all types enumerated by the the type parameter bound.
if t, _ := target.Underlying().(*TypeParam); t != nil {
types := t.Interface().types
if len(types) == 0 {
goto Error
}
for _, t := range t.Interface().types {
check.convertUntypedInternal(x, t)
if x.mode == invalid {
goto Error
}
}
x.typ = target
check.updateExprType(x.expr, target, true) // UntypedNils are final
return
}
check.convertUntypedInternal(x, target)
return
Error:
// TODO(gri) better error message (explain cause)
check.errorf(x.pos(), "cannot convert %s to %s", x, target)
x.mode = invalid
}
// convertUntypedInternal should only be called by convertUntyped.
func (check *Checker) convertUntypedInternal(x *operand, target Type) {
assert(isTyped(target))
// typed target
switch t := target.Underlying().(type) {
case *Basic:

View File

@ -62,10 +62,9 @@ contract Complex(T) {
type OrderedAbs(type T OrderedNumeric) T
func (a OrderedAbs(T)) Abs() T {
// TODO(gri) implement conversions against parameterized types
// if a < 0 {
// return -a
// }
if a < 0 {
return -a
}
return a
}