// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.// Source: ../../cmd/compile/internal/types2/conversions.go// Copyright 2012 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.// This file implements typechecking of conversions.package typesimport (.)// conversion type-checks the conversion T(x).// The result is in x.func ( *Checker) ( *operand, Type) { := .mode == constant_ := func( Type, *constant.Value) bool {switch , := under().(*Basic); {case == nil:// nothing to docaserepresentableConst(.val, , , ):returntruecaseisInteger(.typ) && isString(): := unicode.ReplacementCharif , := constant.Uint64Val(.val); && <= unicode.MaxRune { = rune() }if != nil { * = constant.MakeString(string()) }returntrue }returnfalse }varboolvarstringswitch {case && isConstType():// constant conversion = (, &.val)// A conversion from an integer constant to an integer type // can only fail if there's overflow. Give a concise error. // (go.dev/issue/63563)if ! && isInteger(.typ) && isInteger() { .errorf(, InvalidConversion, "constant %s overflows %s", .val, ) .mode = invalidreturn }case && isTypeParam():// x is convertible to T if it is convertible // to each specific type in the type set of T. // If T's type set is empty, or if it doesn't // have specific types, constant x cannot be // converted. = underIs(, func( Type) bool {// u is nil if there are no specific type termsif == nil { = .sprintf("%s does not contain specific types", )returnfalse }ifisString(.typ) && isBytesOrRunes() {returntrue }if !(, nil) {ifisInteger(.typ) && isInteger() {// see comment above on constant conversion = .sprintf("constant %s overflows %s (in %s)", .val, , ) } else { = .sprintf("cannot convert %s to type %s (in %s)", , , ) }returnfalse }returntrue }) .mode = value// type parameters are not constantscase .convertibleTo(, , &):// non-constant conversion = true .mode = value }if ! {if != "" { .errorf(, InvalidConversion, "cannot convert %s to type %s: %s", , , ) } else { .errorf(, InvalidConversion, "cannot convert %s to type %s", , ) } .mode = invalidreturn }// The conversion argument types are final. For untyped values the // conversion provides the type, per the spec: "A constant may be // given a type explicitly by a constant declaration or conversion,...".ifisUntyped(.typ) { := // - For conversions to interfaces, except for untyped nil arguments // and isTypes2, use the argument's default type. // - For conversions of untyped constants to non-constant types, also // use the default type (e.g., []byte("foo") should report string // not []byte as type for the constant "foo"). // - If !isTypes2, keep untyped nil for untyped nil arguments. // - For constant integer to string conversions, keep the argument type. // (See also the TODO below.)ifisTypes2 && .typ == Typ[UntypedNil] {// ok } elseifisNonTypeParamInterface() || && !isConstType() || !isTypes2 && .isNil() { = Default(.typ) // default type of untyped nil is untyped nil } elseif .mode == constant_ && isInteger(.typ) && allString() { = .typ } .updateExprType(.expr, , true) } .typ = }// TODO(gri) convertibleTo checks if T(x) is valid. It assumes that the type// of x is fully known, but that's not the case for say string(1<<s + 1.0):// Here, the type of 1<<s + 1.0 will be UntypedFloat which will lead to the// (correct!) refusal of the conversion. But the reported error is essentially// "cannot convert untyped float value to string", yet the correct error (per// the spec) is that we cannot shift a floating-point value: 1 in 1<<s should// be converted to UntypedFloat because of the addition of 1.0. Fixing this// is tricky because we'd have to run updateExprType on the argument first.// (go.dev/issue/21982.)// convertibleTo reports whether T(x) is valid. In the failure case, *cause// may be set to the cause for the failure.// The check parameter may be nil if convertibleTo is invoked through an// exported API call, i.e., when all methods have been type-checked.func ( *operand) ( *Checker, Type, *string) bool {// "x is assignable to T"if , := .assignableTo(, , ); {returntrue } := := Unalias(.typ) = Unalias() := under() := under() , := .(*TypeParam) , := .(*TypeParam)// "V and T have identical underlying types if tags are ignored // and V and T are not type parameters"ifIdenticalIgnoreTags(, ) && == nil && == nil {returntrue }// "V and T are unnamed pointer types and their pointer base types // have identical underlying types if tags are ignored // and their pointer base types are not type parameters"if , := .(*Pointer); {if , := .(*Pointer); {ifIdenticalIgnoreTags(under(.base), under(.base)) && !isTypeParam(.base) && !isTypeParam(.base) {returntrue } } }// "V and T are both integer or floating point types"ifisIntegerOrFloat() && isIntegerOrFloat() {returntrue }// "V and T are both complex types"ifisComplex() && isComplex() {returntrue }// "V is an integer or a slice of bytes or runes and T is a string type"if (isInteger() || isBytesOrRunes()) && isString() {returntrue }// "V is a string and T is a slice of bytes or runes"ifisString() && isBytesOrRunes() {returntrue }// package unsafe: // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"if (isPointer() || isUintptr()) && isUnsafePointer() {returntrue }// "and vice versa"ifisUnsafePointer() && (isPointer() || isUintptr()) {returntrue }// "V is a slice, T is an array or pointer-to-array type, // and the slice and array types have identical element types."if , := .(*Slice); != nil {switch a := .(type) {case *Array:ifIdentical(.Elem(), .Elem()) {if == nil || .allowVersion(go1_20) {returntrue }// check != nilif != nil {// TODO(gri) consider restructuring versionErrorf so we can use it here and below * = "conversion of slice to array requires go1.20 or later" }returnfalse }case *Pointer:if , := under(.Elem()).(*Array); != nil {ifIdentical(.Elem(), .Elem()) {if == nil || .allowVersion(go1_17) {returntrue }// check != nilif != nil { * = "conversion of slice to array pointer requires go1.17 or later" }returnfalse } } } }// optimization: if we don't have type parameters, we're doneif == nil && == nil {returnfalse } := func( string, ...any) {if != nil && != nil { := .sprintf(, ...)if * != "" { += "\n\t" + * } * = } }// generic cases with specific type terms // (generic operands cannot be constants, so we can ignore x.val)switch {case != nil && != nil: := * // don't clobber outer xreturn .is(func( *term) bool {if == nil {returnfalse// no specific types } .typ = .typreturn .is(func( *term) bool {if == nil {returnfalse// no specific types }if !.(, .typ, ) { ("cannot convert %s (in %s) to type %s (in %s)", .typ, , .typ, )returnfalse }returntrue }) })case != nil: := * // don't clobber outer xreturn .is(func( *term) bool {if == nil {returnfalse// no specific types } .typ = .typif !.(, , ) { ("cannot convert %s (in %s) to type %s", .typ, , )returnfalse }returntrue })case != nil:return .is(func( *term) bool {if == nil {returnfalse// no specific types }if !.(, .typ, ) { ("cannot convert %s to type %s (in %s)", .typ, .typ, )returnfalse }returntrue }) }returnfalse}func isUintptr( Type) bool { , := under().(*Basic)return != nil && .kind == Uintptr}func isUnsafePointer( Type) bool { , := under().(*Basic)return != nil && .kind == UnsafePointer}func isPointer( Type) bool { , := under().(*Pointer)return}func isBytesOrRunes( Type) bool {if , := under().(*Slice); != nil { , := under(.elem).(*Basic)return != nil && (.kind == Byte || .kind == Rune) }returnfalse}
The pages are generated with Goldsv0.7.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.