mirror of
https://github.com/golang/go
synced 2024-11-22 21:00:04 -07:00
[dev.typeparams] go/types: factor out constraint satisfaction check
This is a port of CL 322070 to go/types, adjusted for the different error reporting API. Change-Id: I75eafe015b5b00554116527ea021e7a5f9e0343b Reviewed-on: https://go-review.googlesource.com/c/go/+/324759 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
7497e57a39
commit
7c8a5be2d6
@ -121,20 +121,30 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist
|
||||
|
||||
// check bounds
|
||||
for i, tname := range tparams {
|
||||
tpar := tname.typ.(*_TypeParam)
|
||||
iface := tpar.Bound()
|
||||
if iface.Empty() {
|
||||
continue // no type bound
|
||||
}
|
||||
|
||||
targ := targs[i]
|
||||
|
||||
// best position for error reporting
|
||||
pos := pos
|
||||
if i < len(poslist) {
|
||||
pos = poslist[i]
|
||||
}
|
||||
|
||||
// stop checking bounds after the first failure
|
||||
if !check.satisfies(pos, targs[i], tname.typ.(*_TypeParam), smap) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return check.subst(pos, typ, smap)
|
||||
}
|
||||
|
||||
// satisfies reports whether the type argument targ satisfies the constraint of type parameter
|
||||
// parameter tpar (after any of its type parameters have been substituted through smap).
|
||||
// A suitable error is reported if the result is false.
|
||||
func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap *substMap) bool {
|
||||
iface := tpar.Bound()
|
||||
if iface.Empty() {
|
||||
return true // no type bound
|
||||
}
|
||||
|
||||
// The type parameter bound is parameterized with the same type parameters
|
||||
// as the instantiated type; before we can use it for bounds checking we
|
||||
// need to instantiate it with the type arguments with which we instantiate
|
||||
@ -150,7 +160,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist
|
||||
// TODO(gri) is this what we want? (spec question)
|
||||
if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
|
||||
check.errorf(atPos(pos), 0, "%s has no methods", targ)
|
||||
break
|
||||
return false
|
||||
}
|
||||
if m, wrong := check.missingMethod(targ, iface, true); m != nil {
|
||||
// TODO(gri) needs to print updated name to avoid major confusion in error message!
|
||||
@ -171,13 +181,13 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist
|
||||
} else {
|
||||
check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name)
|
||||
}
|
||||
break
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// targ's underlying type must also be one of the interface types listed, if any
|
||||
if iface.allTypes == nil {
|
||||
continue // nothing to do
|
||||
return true // nothing to do
|
||||
}
|
||||
|
||||
// If targ is itself a type parameter, each of its possible types, but at least one, must be in the
|
||||
@ -186,26 +196,25 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist
|
||||
targBound := targ.Bound()
|
||||
if targBound.allTypes == nil {
|
||||
check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
|
||||
break
|
||||
return false
|
||||
}
|
||||
for _, t := range unpackType(targBound.allTypes) {
|
||||
if !iface.isSatisfiedBy(t) {
|
||||
// TODO(gri) match this error message with the one below (or vice versa)
|
||||
check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes)
|
||||
break
|
||||
return false
|
||||
}
|
||||
}
|
||||
break
|
||||
return false
|
||||
}
|
||||
|
||||
// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
|
||||
if !iface.isSatisfiedBy(targ) {
|
||||
check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes)
|
||||
break
|
||||
}
|
||||
check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes)
|
||||
return false
|
||||
}
|
||||
|
||||
return check.subst(pos, typ, smap)
|
||||
return true
|
||||
}
|
||||
|
||||
// subst returns the type typ with its type parameters tpars replaced by
|
||||
|
Loading…
Reference in New Issue
Block a user