]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: introduce `isValid` predicate and use throughout
authorRobert Griesemer <gri@golang.org>
Fri, 15 Sep 2023 01:02:41 +0000 (18:02 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 15 Sep 2023 16:16:58 +0000 (16:16 +0000)
Preparation for Alias type nodes. Using a predicate will ensure
that alias indirection can be taken care of when needed, eventually.

Change-Id: I689fab6052060eb6bcb2eeac28ba09fdb73f6868
Reviewed-on: https://go-review.googlesource.com/c/go/+/528695
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>

40 files changed:
src/cmd/compile/internal/types2/api.go
src/cmd/compile/internal/types2/assignments.go
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/check.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/index.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/interface.go
src/cmd/compile/internal/types2/operand.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/signature.go
src/cmd/compile/internal/types2/stmt.go
src/cmd/compile/internal/types2/struct.go
src/cmd/compile/internal/types2/typeparam.go
src/cmd/compile/internal/types2/typeset.go
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/union.go
src/cmd/compile/internal/types2/validtype.go
src/go/types/api.go
src/go/types/assignments.go
src/go/types/builtins.go
src/go/types/call.go
src/go/types/check.go
src/go/types/decl.go
src/go/types/expr.go
src/go/types/index.go
src/go/types/instantiate.go
src/go/types/interface.go
src/go/types/operand.go
src/go/types/predicates.go
src/go/types/signature.go
src/go/types/stmt.go
src/go/types/struct.go
src/go/types/typeparam.go
src/go/types/typeset.go
src/go/types/typexpr.go
src/go/types/union.go
src/go/types/validtype.go

index 48cafe03e7645efeb537d2f97dec9793e407fd73..9f2daa7f70769d814b50e0923dfa93be0afd8a06 100644 (file)
@@ -458,7 +458,7 @@ func (conf *Config) Check(path string, files []*syntax.File, info *Info) (*Packa
 func AssertableTo(V *Interface, T Type) bool {
        // Checker.newAssertableTo suppresses errors for invalid types, so we need special
        // handling here.
-       if T.Underlying() == Typ[Invalid] {
+       if !isValid(T.Underlying()) {
                return false
        }
        return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
@@ -496,7 +496,7 @@ func Implements(V Type, T *Interface) bool {
        }
        // Checker.implements suppresses errors for invalid types, so we need special
        // handling here.
-       if V.Underlying() == Typ[Invalid] {
+       if !isValid(V.Underlying()) {
                return false
        }
        return (*Checker)(nil).implements(nopos, V, T, false, nil)
index 28ceb6cd75d1814b13a4a6c7ec6d1bacb12ba31b..079802b0b056682fc6f2aa8a282aa156888dfaaa 100644 (file)
@@ -102,7 +102,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
 }
 
 func (check *Checker) initConst(lhs *Const, x *operand) {
-       if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
                if lhs.typ == nil {
                        lhs.typ = Typ[Invalid]
                }
@@ -137,7 +137,7 @@ func (check *Checker) initConst(lhs *Const, x *operand) {
 // or Typ[Invalid] in case of an error.
 // If the initialization check fails, x.mode is set to invalid.
 func (check *Checker) initVar(lhs *Var, x *operand, context string) {
-       if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
                if lhs.typ == nil {
                        lhs.typ = Typ[Invalid]
                }
@@ -202,7 +202,7 @@ func (check *Checker) lhsVar(lhs syntax.Expr) Type {
                v.used = v_used // restore v.used
        }
 
-       if x.mode == invalid || x.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) {
                return Typ[Invalid]
        }
 
@@ -234,7 +234,7 @@ func (check *Checker) lhsVar(lhs syntax.Expr) Type {
 // If the assignment check fails and x != nil, x.mode is set to invalid.
 func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand) {
        T := check.lhsVar(lhs) // nil if lhs is _
-       if T == Typ[Invalid] {
+       if !isValid(T) {
                if x != nil {
                        x.mode = invalid
                } else {
@@ -282,7 +282,7 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string {
                switch {
                case t == nil:
                        fallthrough // should not happen but be cautious
-               case t == Typ[Invalid]:
+               case !isValid(t):
                        s = "unknown type"
                case isUntyped(t):
                        if isNumeric(t) {
index 41e60f118de3c5e33441b889890f785159268b5f..01b8e46304cfcac949c5aa138c437c09e54b0214 100644 (file)
@@ -206,7 +206,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
                if mode == invalid {
                        // avoid error if underlying type is invalid
-                       if under(x.typ) != Typ[Invalid] {
+                       if isValid(under(x.typ)) {
                                code := InvalidCap
                                if id == _Len {
                                        code = InvalidLen
@@ -490,7 +490,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // (no argument evaluated yet)
                arg0 := argList[0]
                T := check.varType(arg0)
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        return
                }
 
@@ -600,7 +600,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // new(T)
                // (no argument evaluated yet)
                T := check.varType(argList[0])
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        return
                }
 
index 643242db57c889ae1e3e07edb975ec3c39d851c0..718c54913d36bbe4c411376157e14ccde2661856 100644 (file)
@@ -792,7 +792,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, w
        obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
        if obj == nil {
                // Don't report another error if the underlying type was invalid (go.dev/issue/49541).
-               if under(x.typ) == Typ[Invalid] {
+               if !isValid(under(x.typ)) {
                        goto Error
                }
 
index 0a24eb2dabfe9269e26d807f545596de1042549a..f21704f1083fca72f6991cd40cf75b7ba20e38c9 100644 (file)
@@ -170,7 +170,7 @@ func (check *Checker) validAlias(alias *TypeName, typ Type) {
 
 // isBrokenAlias reports whether alias doesn't have a determined type yet.
 func (check *Checker) isBrokenAlias(alias *TypeName) bool {
-       return alias.typ == Typ[Invalid] && check.brokenAliases[alias]
+       return !isValid(alias.typ) && check.brokenAliases[alias]
 }
 
 func (check *Checker) rememberUntyped(e syntax.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
@@ -503,7 +503,7 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty
                assert(val != nil)
                // We check allBasic(typ, IsConstType) here as constant expressions may be
                // recorded as type parameters.
-               assert(typ == Typ[Invalid] || allBasic(typ, IsConstType))
+               assert(!isValid(typ) || allBasic(typ, IsConstType))
        }
        if m := check.Types; m != nil {
                m[x] = TypeAndValue{mode, typ, val}
index 8c6fb45ac0c01331f006be593bfb70f6df5392cd..ccdfb19722843958378dbe7fa95fb7604a384949 100644 (file)
@@ -387,7 +387,7 @@ func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited boo
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (go.dev/issue/22090)
-                       if under(t) != Typ[Invalid] {
+                       if isValid(under(t)) {
                                check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
                        }
                        obj.typ = Typ[Invalid]
index f28fbae12314e43380933769922268009f066cd6..321b0c47623aa4685b2647c17f4c74fde782c319 100644 (file)
@@ -392,7 +392,7 @@ func (check *Checker) updateExprVal(x syntax.Expr, val constant.Value) {
 // If x is a constant operand, the returned constant.Value will be the
 // representation of x in this context.
 func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, Code) {
-       if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
+       if x.mode == invalid || isTyped(x.typ) || !isValid(target) {
                return x.typ, nil, 0
        }
        // x is untyped
@@ -474,7 +474,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 // If switchCase is true, the operator op is ignored.
 func (check *Checker) comparison(x, y *operand, op syntax.Operator, switchCase bool) {
        // Avoid spurious errors if any of the operands has an invalid type (go.dev/issue/54405).
-       if x.typ == Typ[Invalid] || y.typ == Typ[Invalid] {
+       if !isValid(x.typ) || !isValid(y.typ) {
                x.mode = invalid
                return
        }
@@ -828,7 +828,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
        if !Identical(x.typ, y.typ) {
                // only report an error if we have valid types
                // (otherwise we had an error reported elsewhere already)
-               if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
+               if isValid(x.typ) && isValid(y.typ) {
                        if e != nil {
                                check.errorf(x, MismatchedTypes, invalidOp+"%s (mismatched types %s and %s)", e, x.typ, y.typ)
                        } else {
@@ -1308,7 +1308,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e syntax.Expr, hint Type)
                                check.use(e)
                        }
                        // if utyp is invalid, an error was reported before
-                       if utyp != Typ[Invalid] {
+                       if isValid(utyp) {
                                check.errorf(e, InvalidLit, "invalid composite literal type %s", typ)
                                goto Error
                        }
@@ -1363,7 +1363,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e syntax.Expr, hint Type)
                        goto Error
                }
                T := check.varType(e.Type)
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        goto Error
                }
                check.typeAssertion(e, x, T, false)
index 3ebe85135507a8378b8e00125779e45482a9b42c..4db2213086444e4cd974f4a3e12f9ae2fa83a684 100644 (file)
@@ -29,7 +29,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
                x.mode = invalid
                // TODO(gri) here we re-evaluate e.X - try to avoid this
                x.typ = check.varType(e)
-               if x.typ != Typ[Invalid] {
+               if isValid(x.typ) {
                        x.mode = typexpr
                }
                return false
@@ -428,7 +428,7 @@ func (check *Checker) indexedElts(elts []syntax.Expr, typ Type, length int64) in
                validIndex := false
                eval := e
                if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
-                       if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
+                       if typ, i := check.index(kv.Key, length); isValid(typ) {
                                if i >= 0 {
                                        index = i
                                        validIndex = true
index 6024035a38bdfb8886f140050732d87c7e7ef340..0c6b202ff9f8e26f8e5d431b17bda3d966181def 100644 (file)
@@ -192,10 +192,10 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
 func (check *Checker) implements(pos syntax.Pos, V, T Type, constraint bool, cause *string) bool {
        Vu := under(V)
        Tu := under(T)
-       if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
+       if !isValid(Vu) || !isValid(Tu) {
                return true // avoid follow-on errors
        }
-       if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
+       if p, _ := Vu.(*Pointer); p != nil && !isValid(under(p.base)) {
                return true // avoid follow-on errors (see go.dev/issue/49541 for an example)
        }
 
index 6623ff557533b6e5bde58adb3cbb773a55b8461b..3866975a91acb3982e644b40255cff77484285ae 100644 (file)
@@ -143,7 +143,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
                typ := check.typ(f.Type)
                sig, _ := typ.(*Signature)
                if sig == nil {
-                       if typ != Typ[Invalid] {
+                       if isValid(typ) {
                                check.errorf(f.Type, InvalidSyntaxTree, "%s is not a method signature", typ)
                        }
                        continue // ignore
index 0469b000bb4b69e9684a040891a52440a3eeccee..3f151007e577beb4b8df409c7114b0f3b4d55438 100644 (file)
@@ -172,7 +172,7 @@ func operandString(x *operand, qf Qualifier) string {
 
        // <typ>
        if hasType {
-               if x.typ != Typ[Invalid] {
+               if isValid(x.typ) {
                        var intro string
                        if isGeneric(x.typ) {
                                intro = " of generic type "
@@ -245,7 +245,7 @@ func (x *operand) isNil() bool { return x.mode == nilvalue }
 // if assignableTo is invoked through an exported API call, i.e., when all
 // methods have been type-checked.
 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
-       if x.mode == invalid || T == Typ[Invalid] {
+       if x.mode == invalid || !isValid(T) {
                return true, 0 // avoid spurious errors
        }
 
index 872b874ecb4991487d892598ef06550f7c23532d..c48f926bf84350e4625f38627ecaba4b100441d7 100644 (file)
@@ -6,6 +6,9 @@
 
 package types2
 
+// isValid reports whether t is a valid type.
+func isValid(t Type) bool { return t != Typ[Invalid] }
+
 // The isX predicates below report whether t is an X.
 // If t is a type parameter the result is false; i.e.,
 // these predicates don't look inside a type parameter.
@@ -222,7 +225,7 @@ func (c *comparer) identical(x, y Type, p *ifacePair) bool {
                return true
        }
 
-       if c.ignoreInvalids && (x == Typ[Invalid] || y == Typ[Invalid]) {
+       if c.ignoreInvalids && (!isValid(x) || !isValid(y)) {
                return true
        }
 
index 7eeb7340f81ccfaa7f81abd59281ec4b434890c1..edd8d66f13702026c806eafa65eca23f0b14bfab 100644 (file)
@@ -208,7 +208,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                check.later(func() {
                        // spec: "The receiver type must be of the form T or *T where T is a type name."
                        rtyp, _ := deref(recv.typ)
-                       if rtyp == Typ[Invalid] {
+                       if !isValid(rtyp) {
                                return // error was reported before
                        }
                        // spec: "The type denoted by T is called the receiver base type; it must not
index 3b8c79f108a0ed5db9252adb26fd9bcf3ddf382b..a671002e1214c149cd31e06d9a1de29fed8004bc 100644 (file)
@@ -297,7 +297,7 @@ L:
                        check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
                } else {
                        T = check.varType(e)
-                       if T == Typ[Invalid] {
+                       if !isValid(T) {
                                continue L
                        }
                }
@@ -341,7 +341,7 @@ L:
 //                     hash = "<nil>" // avoid collision with a type named nil
 //             } else {
 //                     T = check.varType(e)
-//                     if T == Typ[Invalid] {
+//                     if !isValid(T) {
 //                             continue L
 //                     }
 //                     hash = typeHash(T, nil)
index 125e94647b36afb998b973f5f8f4e036279b3472..9e46b349a3920d186beca11d5bbd8f2764ad63f8 100644 (file)
@@ -147,7 +147,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
                                t, isPtr := deref(embeddedTyp)
                                switch u := under(t).(type) {
                                case *Basic:
-                                       if t == Typ[Invalid] {
+                                       if !isValid(t) {
                                                // error was reported before
                                                return
                                        }
index 46c2101c47513e5d23407dabff1283a9af03ba24..42b1a63915330be8b2e562f06e63360f1473fb71 100644 (file)
@@ -108,7 +108,7 @@ func (t *TypeParam) iface() *Interface {
        var ityp *Interface
        switch u := under(bound).(type) {
        case *Basic:
-               if u == Typ[Invalid] {
+               if !isValid(u) {
                        // error is reported elsewhere
                        return &emptyInterface
                }
index 70b9e36aef7e65bb06bd75ab2793accf48335c1b..719041657cbb33d6a4eb3f5fff63ba839a2d8df5 100644 (file)
@@ -290,7 +290,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
                        assert(len(tset.methods) == 0)
                        terms = tset.terms
                default:
-                       if u == Typ[Invalid] {
+                       if !isValid(u) {
                                continue
                        }
                        if check != nil && !check.verifyVersionf(pos, go1_18, "embedding non-interface type %s", typ) {
@@ -389,7 +389,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syn
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(t.typ))
                        terms = computeInterfaceTypeSet(check, pos, ui).terms
-               } else if u == Typ[Invalid] {
+               } else if !isValid(u) {
                        continue
                } else {
                        if t.tilde && !Identical(t.typ, u) {
index de420e39c7c1b2e4c6d8feaff99e92448374d6bd..47e9dbae8b961dad5957b824fea6944164fdf2a5 100644 (file)
@@ -78,7 +78,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
 
        case *Const:
                check.addDeclDep(obj)
-               if typ == Typ[Invalid] {
+               if !isValid(typ) {
                        return
                }
                if obj == universeIota {
@@ -108,7 +108,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
                        obj.used = true
                }
                check.addDeclDep(obj)
-               if typ == Typ[Invalid] {
+               if !isValid(typ) {
                        return
                }
                x.mode = variable
@@ -193,7 +193,7 @@ func (check *Checker) definedType(e syntax.Expr, def *Named) Type {
 func (check *Checker) genericType(e syntax.Expr, cause *string) Type {
        typ := check.typInternal(e, nil)
        assert(isTyped(typ))
-       if typ != Typ[Invalid] && !isGeneric(typ) {
+       if isValid(typ) && !isGeneric(typ) {
                if cause != nil {
                        *cause = check.sprintf("%s is not a generic type", typ)
                }
@@ -323,7 +323,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
                        // useful - even a valid dereferenciation will lead to an invalid
                        // type again, and in some cases we get unexpected follow-on errors
                        // (e.g., go.dev/issue/49005). Return an invalid type instead.
-                       if typ.base == Typ[Invalid] {
+                       if !isValid(typ.base) {
                                return Typ[Invalid]
                        }
                        return typ
@@ -416,7 +416,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
        if cause != "" {
                check.errorf(x, NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, cause)
        }
-       if gtyp == Typ[Invalid] {
+       if !isValid(gtyp) {
                return gtyp // error already reported
        }
 
@@ -520,7 +520,7 @@ func (check *Checker) typeList(list []syntax.Expr) []Type {
        res := make([]Type, len(list)) // res != nil even if len(list) == 0
        for i, x := range list {
                t := check.varType(x)
-               if t == Typ[Invalid] {
+               if !isValid(t) {
                        res = nil
                }
                if res != nil {
index 8f354a708fb66cd38807f6275b4dddec5e846f0b..1bf4353f264e34c7a6dc4c95e1f7bb4b48f3790e 100644 (file)
@@ -66,7 +66,7 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
                        return term.typ // typ already recorded through check.typ in parseTilde
                }
                if len(terms) >= maxTermCount {
-                       if u != Typ[Invalid] {
+                       if isValid(u) {
                                check.errorf(x, InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
                                u = Typ[Invalid]
                        }
@@ -80,7 +80,7 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
                }
        }
 
-       if u == Typ[Invalid] {
+       if !isValid(u) {
                return u
        }
 
@@ -89,7 +89,7 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
        // Note: This is a quadratic algorithm, but unions tend to be short.
        check.later(func() {
                for i, t := range terms {
-                       if t.typ == Typ[Invalid] {
+                       if !isValid(t.typ) {
                                continue
                        }
 
index dbe91dc08f30d3f6113814613091d3ab4371dc36..8337e0c8c757f84d471073d4916135bf0b4b1b51 100644 (file)
@@ -68,7 +68,7 @@ func (check *Checker) validType0(typ Type, nest, path []*Named) bool {
                // Don't report a 2nd error if we already know the type is invalid
                // (e.g., if a cycle was detected earlier, via under).
                // Note: ensure that t.orig is fully resolved by calling Underlying().
-               if t.Underlying() == Typ[Invalid] {
+               if !isValid(t.Underlying()) {
                        return false
                }
 
index 4583b4f7b59356937c2ecd8514ddd06fc3f469ee..30a9c1f3feeb3ccd60c3a49c84600f51a69b97c8 100644 (file)
@@ -446,7 +446,7 @@ func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, i
 func AssertableTo(V *Interface, T Type) bool {
        // Checker.newAssertableTo suppresses errors for invalid types, so we need special
        // handling here.
-       if T.Underlying() == Typ[Invalid] {
+       if !isValid(T.Underlying()) {
                return false
        }
        return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
@@ -484,7 +484,7 @@ func Implements(V Type, T *Interface) bool {
        }
        // Checker.implements suppresses errors for invalid types, so we need special
        // handling here.
-       if V.Underlying() == Typ[Invalid] {
+       if !isValid(V.Underlying()) {
                return false
        }
        return (*Checker)(nil).implements(0, V, T, false, nil)
index 1ea51142e0e3e6bc574978d076ac5b82d816e3d7..f9f0e8f20add230dca271b00bb03578326eb7dc8 100644 (file)
@@ -101,7 +101,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
 }
 
 func (check *Checker) initConst(lhs *Const, x *operand) {
-       if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
                if lhs.typ == nil {
                        lhs.typ = Typ[Invalid]
                }
@@ -136,7 +136,7 @@ func (check *Checker) initConst(lhs *Const, x *operand) {
 // or Typ[Invalid] in case of an error.
 // If the initialization check fails, x.mode is set to invalid.
 func (check *Checker) initVar(lhs *Var, x *operand, context string) {
-       if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
                if lhs.typ == nil {
                        lhs.typ = Typ[Invalid]
                }
@@ -201,7 +201,7 @@ func (check *Checker) lhsVar(lhs ast.Expr) Type {
                v.used = v_used // restore v.used
        }
 
-       if x.mode == invalid || x.typ == Typ[Invalid] {
+       if x.mode == invalid || !isValid(x.typ) {
                return Typ[Invalid]
        }
 
@@ -233,7 +233,7 @@ func (check *Checker) lhsVar(lhs ast.Expr) Type {
 // If the assignment check fails and x != nil, x.mode is set to invalid.
 func (check *Checker) assignVar(lhs, rhs ast.Expr, x *operand) {
        T := check.lhsVar(lhs) // nil if lhs is _
-       if T == Typ[Invalid] {
+       if !isValid(T) {
                if x != nil {
                        x.mode = invalid
                } else {
@@ -281,7 +281,7 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string {
                switch {
                case t == nil:
                        fallthrough // should not happen but be cautious
-               case t == Typ[Invalid]:
+               case !isValid(t):
                        s = "unknown type"
                case isUntyped(t):
                        if isNumeric(t) {
index 0f054e35aee20a3e0bc86952e8ec35641673550f..72b4c5370d2e004e075e6f9698f961449cb01e8b 100644 (file)
@@ -205,7 +205,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
                if mode == invalid {
                        // avoid error if underlying type is invalid
-                       if under(x.typ) != Typ[Invalid] {
+                       if isValid(under(x.typ)) {
                                code := InvalidCap
                                if id == _Len {
                                        code = InvalidLen
@@ -489,7 +489,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // (no argument evaluated yet)
                arg0 := argList[0]
                T := check.varType(arg0)
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        return
                }
 
@@ -599,7 +599,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // new(T)
                // (no argument evaluated yet)
                T := check.varType(argList[0])
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        return
                }
 
index 8a3cec7309eae53573185f5926c0fc7356fe64e9..f581a8ad51d6025c498d3306b40b7056902fac90 100644 (file)
@@ -795,7 +795,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, want
        obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
        if obj == nil {
                // Don't report another error if the underlying type was invalid (go.dev/issue/49541).
-               if under(x.typ) == Typ[Invalid] {
+               if !isValid(under(x.typ)) {
                        goto Error
                }
 
index 6aaab064c53bdc818524c2e2d07a6e9e45a62983..c714754fef68a57c44ec2dba7e76ad991ecc9fa6 100644 (file)
@@ -172,7 +172,7 @@ func (check *Checker) validAlias(alias *TypeName, typ Type) {
 
 // isBrokenAlias reports whether alias doesn't have a determined type yet.
 func (check *Checker) isBrokenAlias(alias *TypeName) bool {
-       return alias.typ == Typ[Invalid] && check.brokenAliases[alias]
+       return !isValid(alias.typ) && check.brokenAliases[alias]
 }
 
 func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
@@ -512,7 +512,7 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
                assert(val != nil)
                // We check allBasic(typ, IsConstType) here as constant expressions may be
                // recorded as type parameters.
-               assert(typ == Typ[Invalid] || allBasic(typ, IsConstType))
+               assert(!isValid(typ) || allBasic(typ, IsConstType))
        }
        if m := check.Types; m != nil {
                m[x] = TypeAndValue{mode, typ, val}
index 642d2604f9e93fbf4cbe8b791ab871ec742b6dfd..d347ede219d39c630da996a620c28205095561cb 100644 (file)
@@ -456,7 +456,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool)
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (go.dev/issue/22090)
-                       if under(t) != Typ[Invalid] {
+                       if isValid(under(t)) {
                                check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
                        }
                        obj.typ = Typ[Invalid]
index fd776c23502f2ff05b78540b81f379591ef98443..2b020a570a4ad3e9fe614b520b5d587f37ef245e 100644 (file)
@@ -356,7 +356,7 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) {
 // If x is a constant operand, the returned constant.Value will be the
 // representation of x in this context.
 func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, Code) {
-       if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
+       if x.mode == invalid || isTyped(x.typ) || !isValid(target) {
                return x.typ, nil, 0
        }
        // x is untyped
@@ -452,7 +452,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 // If switchCase is true, the operator op is ignored.
 func (check *Checker) comparison(x, y *operand, op token.Token, switchCase bool) {
        // Avoid spurious errors if any of the operands has an invalid type (go.dev/issue/54405).
-       if x.typ == Typ[Invalid] || y.typ == Typ[Invalid] {
+       if !isValid(x.typ) || !isValid(y.typ) {
                x.mode = invalid
                return
        }
@@ -810,7 +810,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token
        if !Identical(x.typ, y.typ) {
                // only report an error if we have valid types
                // (otherwise we had an error reported elsewhere already)
-               if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
+               if isValid(x.typ) && isValid(y.typ) {
                        var posn positioner = x
                        if e != nil {
                                posn = e
@@ -1290,7 +1290,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e ast.Expr, hint Type) ex
                                check.use(e)
                        }
                        // if utyp is invalid, an error was reported before
-                       if utyp != Typ[Invalid] {
+                       if isValid(utyp) {
                                check.errorf(e, InvalidLit, "invalid composite literal type %s", typ)
                                goto Error
                        }
@@ -1348,7 +1348,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e ast.Expr, hint Type) ex
                        goto Error
                }
                T := check.varType(e.Type)
-               if T == Typ[Invalid] {
+               if !isValid(T) {
                        goto Error
                }
                check.typeAssertion(e, x, T, false)
index c1c0f40e878d49d18cc86085b32e7541cacab76a..6f532a96c176ff76900e8c4ba362d6729be213ba 100644 (file)
@@ -30,7 +30,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst
                x.mode = invalid
                // TODO(gri) here we re-evaluate e.X - try to avoid this
                x.typ = check.varType(e.Orig)
-               if x.typ != Typ[Invalid] {
+               if isValid(x.typ) {
                        x.mode = typexpr
                }
                return false
@@ -421,7 +421,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
                validIndex := false
                eval := e
                if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
-                       if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
+                       if typ, i := check.index(kv.Key, length); isValid(typ) {
                                if i >= 0 {
                                        index = i
                                        validIndex = true
index 088b4338fcf7ba56cb5ee2897d707de145ba2892..34dfd85a260df24e3c015fc6ea524394826dc7f7 100644 (file)
@@ -194,10 +194,10 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type,
 func (check *Checker) implements(pos token.Pos, V, T Type, constraint bool, cause *string) bool {
        Vu := under(V)
        Tu := under(T)
-       if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
+       if !isValid(Vu) || !isValid(Tu) {
                return true // avoid follow-on errors
        }
-       if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
+       if p, _ := Vu.(*Pointer); p != nil && !isValid(under(p.base)) {
                return true // avoid follow-on errors (see go.dev/issue/49541 for an example)
        }
 
index 74562d8a893db1f7dedf67f08d5ceb219c25094e..ac909fa4d6139466c8d01493d0c0b92cdd517eef 100644 (file)
@@ -182,7 +182,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                typ := check.typ(f.Type)
                sig, _ := typ.(*Signature)
                if sig == nil {
-                       if typ != Typ[Invalid] {
+                       if isValid(typ) {
                                check.errorf(f.Type, InvalidSyntaxTree, "%s is not a method signature", typ)
                        }
                        continue // ignore
index d7719fdaaf7ac69361637f88d503be5236f256ac..d5c16346bf78303e9dc6f9b9cd6ed4cb7a66145c 100644 (file)
@@ -159,7 +159,7 @@ func operandString(x *operand, qf Qualifier) string {
 
        // <typ>
        if hasType {
-               if x.typ != Typ[Invalid] {
+               if isValid(x.typ) {
                        var intro string
                        if isGeneric(x.typ) {
                                intro = " of generic type "
@@ -232,7 +232,7 @@ func (x *operand) isNil() bool { return x.mode == value && x.typ == Typ[UntypedN
 // if assignableTo is invoked through an exported API call, i.e., when all
 // methods have been type-checked.
 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
-       if x.mode == invalid || T == Typ[Invalid] {
+       if x.mode == invalid || !isValid(T) {
                return true, 0 // avoid spurious errors
        }
 
index dcbf30a556bab92a5cfa36c1df9f34cdb81c5d43..331a8f69aa245377559aa64eb2baf4d3be208580 100644 (file)
@@ -8,6 +8,9 @@
 
 package types
 
+// isValid reports whether t is a valid type.
+func isValid(t Type) bool { return t != Typ[Invalid] }
+
 // The isX predicates below report whether t is an X.
 // If t is a type parameter the result is false; i.e.,
 // these predicates don't look inside a type parameter.
@@ -224,7 +227,7 @@ func (c *comparer) identical(x, y Type, p *ifacePair) bool {
                return true
        }
 
-       if c.ignoreInvalids && (x == Typ[Invalid] || y == Typ[Invalid]) {
+       if c.ignoreInvalids && (!isValid(x) || !isValid(y)) {
                return true
        }
 
index a366b9dd0d703dbd47d26c61649dd7841da3fc33..3c67fd9f157acfa183a6eba8285ae8132dcceeaf 100644 (file)
@@ -211,7 +211,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                check.later(func() {
                        // spec: "The receiver type must be of the form T or *T where T is a type name."
                        rtyp, _ := deref(recv.typ)
-                       if rtyp == Typ[Invalid] {
+                       if !isValid(rtyp) {
                                return // error was reported before
                        }
                        // spec: "The type denoted by T is called the receiver base type; it must not
index 7869f37077f3a13196fcf28810f62fd18d12184c..3e56d415b62a75e2e4236a779fccb9af35dd6821 100644 (file)
@@ -291,7 +291,7 @@ L:
                        check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
                } else {
                        T = check.varType(e)
-                       if T == Typ[Invalid] {
+                       if !isValid(T) {
                                continue L
                        }
                }
@@ -332,7 +332,7 @@ L:
 //                     hash = "<nil>" // avoid collision with a type named nil
 //             } else {
 //                     T = check.varType(e)
-//                     if T == Typ[Invalid] {
+//                     if !isValid(T) {
 //                             continue L
 //                     }
 //                     hash = typeHash(T, nil)
index 7247a25719ce5980e607e916eb9c26988f170929..935a5495307c95ef0707aca160b43c01a198e19b 100644 (file)
@@ -146,7 +146,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
                                t, isPtr := deref(embeddedTyp)
                                switch u := under(t).(type) {
                                case *Basic:
-                                       if t == Typ[Invalid] {
+                                       if !isValid(t) {
                                                // error was reported before
                                                return
                                        }
index 787926a367865de0c0fa4415bb36bdf551dea17c..b23601dc3ff57f93118d69f228dc6db1b8aa9b45 100644 (file)
@@ -110,7 +110,7 @@ func (t *TypeParam) iface() *Interface {
        var ityp *Interface
        switch u := under(bound).(type) {
        case *Basic:
-               if u == Typ[Invalid] {
+               if !isValid(u) {
                        // error is reported elsewhere
                        return &emptyInterface
                }
index 206aa3da08f78cd57c723b66f73551bee8ca4073..8d8c490c6aee3ff580e94625a130a7ef2dc86c07 100644 (file)
@@ -288,7 +288,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
                        assert(len(tset.methods) == 0)
                        terms = tset.terms
                default:
-                       if u == Typ[Invalid] {
+                       if !isValid(u) {
                                continue
                        }
                        if check != nil && !check.verifyVersionf(atPos(pos), go1_18, "embedding non-interface type %s", typ) {
@@ -387,7 +387,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos tok
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(t.typ))
                        terms = computeInterfaceTypeSet(check, pos, ui).terms
-               } else if u == Typ[Invalid] {
+               } else if !isValid(u) {
                        continue
                } else {
                        if t.tilde && !Identical(t.typ, u) {
index d92ac9cabdd0aeebc0f8013d1337f7464b841dc9..4c7c8a5ab5403299b1f32c665da447a9265c5cee 100644 (file)
@@ -79,7 +79,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
 
        case *Const:
                check.addDeclDep(obj)
-               if typ == Typ[Invalid] {
+               if !isValid(typ) {
                        return
                }
                if obj == universeIota {
@@ -109,7 +109,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
                        obj.used = true
                }
                check.addDeclDep(obj)
-               if typ == Typ[Invalid] {
+               if !isValid(typ) {
                        return
                }
                x.mode = variable
@@ -193,7 +193,7 @@ func (check *Checker) definedType(e ast.Expr, def *Named) Type {
 func (check *Checker) genericType(e ast.Expr, cause *string) Type {
        typ := check.typInternal(e, nil)
        assert(isTyped(typ))
-       if typ != Typ[Invalid] && !isGeneric(typ) {
+       if isValid(typ) && !isGeneric(typ) {
                if cause != nil {
                        *cause = check.sprintf("%s is not a generic type", typ)
                }
@@ -407,7 +407,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
        if cause != "" {
                check.errorf(ix.Orig, NotAGenericType, invalidOp+"%s (%s)", ix.Orig, cause)
        }
-       if gtyp == Typ[Invalid] {
+       if !isValid(gtyp) {
                return gtyp // error already reported
        }
 
@@ -511,7 +511,7 @@ func (check *Checker) typeList(list []ast.Expr) []Type {
        res := make([]Type, len(list)) // res != nil even if len(list) == 0
        for i, x := range list {
                t := check.varType(x)
-               if t == Typ[Invalid] {
+               if !isValid(t) {
                        res = nil
                }
                if res != nil {
index 085f507ad3ac93b0f8ad1f50198ffd6132301ba8..f2cfd6a737ad59ade15d80a84ff82c34afb10992 100644 (file)
@@ -67,7 +67,7 @@ func parseUnion(check *Checker, uexpr ast.Expr) Type {
                        return term.typ // typ already recorded through check.typ in parseTilde
                }
                if len(terms) >= maxTermCount {
-                       if u != Typ[Invalid] {
+                       if isValid(u) {
                                check.errorf(x, InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
                                u = Typ[Invalid]
                        }
@@ -81,7 +81,7 @@ func parseUnion(check *Checker, uexpr ast.Expr) Type {
                }
        }
 
-       if u == Typ[Invalid] {
+       if !isValid(u) {
                return u
        }
 
@@ -90,7 +90,7 @@ func parseUnion(check *Checker, uexpr ast.Expr) Type {
        // Note: This is a quadratic algorithm, but unions tend to be short.
        check.later(func() {
                for i, t := range terms {
-                       if t.typ == Typ[Invalid] {
+                       if !isValid(t.typ) {
                                continue
                        }
 
index d915fef825516bad9d356fad2d66d41c1eb54d15..0c0562b2873aec58a9ad2d98a9e2f00a243b8e9b 100644 (file)
@@ -70,7 +70,7 @@ func (check *Checker) validType0(typ Type, nest, path []*Named) bool {
                // Don't report a 2nd error if we already know the type is invalid
                // (e.g., if a cycle was detected earlier, via under).
                // Note: ensure that t.orig is fully resolved by calling Underlying().
-               if t.Underlying() == Typ[Invalid] {
+               if !isValid(t.Underlying()) {
                        return false
                }