1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements exported type predicates. 6 7 package types2 8 9 // AssertableTo reports whether a value of type V can be asserted to have type T. 10 // 11 // The behavior of AssertableTo is unspecified in three cases: 12 // - if T is Typ[Invalid] 13 // - if V is a generalized interface; i.e., an interface that may only be used 14 // as a type constraint in Go code 15 // - if T is an uninstantiated generic type 16 func AssertableTo(V *Interface, T Type) bool { 17 // Checker.newAssertableTo suppresses errors for invalid types, so we need special 18 // handling here. 19 if !isValid(T.Underlying()) { 20 return false 21 } 22 return (*Checker)(nil).newAssertableTo(nopos, V, T, nil) 23 } 24 25 // AssignableTo reports whether a value of type V is assignable to a variable 26 // of type T. 27 // 28 // The behavior of AssignableTo is unspecified if V or T is Typ[Invalid] or an 29 // uninstantiated generic type. 30 func AssignableTo(V, T Type) bool { 31 x := operand{mode: value, typ: V} 32 ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x 33 return ok 34 } 35 36 // ConvertibleTo reports whether a value of type V is convertible to a value of 37 // type T. 38 // 39 // The behavior of ConvertibleTo is unspecified if V or T is Typ[Invalid] or an 40 // uninstantiated generic type. 41 func ConvertibleTo(V, T Type) bool { 42 x := operand{mode: value, typ: V} 43 return x.convertibleTo(nil, T, nil) // check not needed for non-constant x 44 } 45 46 // Implements reports whether type V implements interface T. 47 // 48 // The behavior of Implements is unspecified if V is Typ[Invalid] or an uninstantiated 49 // generic type. 50 func Implements(V Type, T *Interface) bool { 51 if T.Empty() { 52 // All types (even Typ[Invalid]) implement the empty interface. 53 return true 54 } 55 // Checker.implements suppresses errors for invalid types, so we need special 56 // handling here. 57 if !isValid(V.Underlying()) { 58 return false 59 } 60 return (*Checker)(nil).implements(nopos, V, T, false, nil) 61 } 62 63 // Satisfies reports whether type V satisfies the constraint T. 64 // 65 // The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated 66 // generic type. 67 func Satisfies(V Type, T *Interface) bool { 68 return (*Checker)(nil).implements(nopos, V, T, true, nil) 69 } 70 71 // Identical reports whether x and y are identical types. 72 // Receivers of [Signature] types are ignored. 73 // 74 // Predicates such as [Identical], [Implements], and 75 // [Satisfies] assume that both operands belong to a 76 // consistent collection of symbols ([Object] values). 77 // For example, two [Named] types can be identical only if their 78 // [Named.Obj] methods return the same [TypeName] symbol. 79 // A collection of symbols is consistent if, for each logical 80 // package whose path is P, the creation of those symbols 81 // involved at most one call to [NewPackage](P, ...). 82 // To ensure consistency, use a single [Importer] for 83 // all loaded packages and their dependencies. 84 // For more information, see https://github.com/golang/go/issues/57497. 85 func Identical(x, y Type) bool { 86 var c comparer 87 return c.identical(x, y, nil) 88 } 89 90 // IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. 91 // Receivers of [Signature] types are ignored. 92 func IdenticalIgnoreTags(x, y Type) bool { 93 var c comparer 94 c.ignoreTags = true 95 return c.identical(x, y, nil) 96 } 97