Source file src/go/types/operand.go

     1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
     2  // Source: ../../cmd/compile/internal/types2/operand.go
     3  
     4  // Copyright 2012 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  // This file defines operands and associated operations.
     9  
    10  package types
    11  
    12  import (
    13  	"bytes"
    14  	"fmt"
    15  	"go/ast"
    16  	"go/constant"
    17  	"go/token"
    18  	. "internal/types/errors"
    19  )
    20  
    21  // An operandMode specifies the (addressing) mode of an operand.
    22  type operandMode byte
    23  
    24  const (
    25  	invalid   operandMode = iota // operand is invalid
    26  	novalue                      // operand represents no value (result of a function call w/o result)
    27  	builtin                      // operand is a built-in function
    28  	typexpr                      // operand is a type
    29  	constant_                    // operand is a constant; the operand's typ is a Basic type
    30  	variable                     // operand is an addressable variable
    31  	mapindex                     // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
    32  	value                        // operand is a computed value
    33  	nilvalue                     // operand is the nil value - only used by types2
    34  	commaok                      // like value, but operand may be used in a comma,ok expression
    35  	commaerr                     // like commaok, but second value is error, not boolean
    36  	cgofunc                      // operand is a cgo function
    37  )
    38  
    39  var operandModeString = [...]string{
    40  	invalid:   "invalid operand",
    41  	novalue:   "no value",
    42  	builtin:   "built-in",
    43  	typexpr:   "type",
    44  	constant_: "constant",
    45  	variable:  "variable",
    46  	mapindex:  "map index expression",
    47  	value:     "value",
    48  	nilvalue:  "nil", // only used by types2
    49  	commaok:   "comma, ok expression",
    50  	commaerr:  "comma, error expression",
    51  	cgofunc:   "cgo function",
    52  }
    53  
    54  // An operand represents an intermediate value during type checking.
    55  // Operands have an (addressing) mode, the expression evaluating to
    56  // the operand, the operand's type, a value for constants, and an id
    57  // for built-in functions.
    58  // The zero value of operand is a ready to use invalid operand.
    59  type operand struct {
    60  	mode_ operandMode
    61  	expr  ast.Expr
    62  	typ_  Type
    63  	val   constant.Value
    64  	id    builtinId
    65  }
    66  
    67  func (x *operand) mode() operandMode {
    68  	return x.mode_
    69  }
    70  
    71  func (x *operand) typ() Type {
    72  	return x.typ_
    73  }
    74  
    75  func (x *operand) isValid() bool {
    76  	return x.mode() != invalid
    77  }
    78  
    79  func (x *operand) invalidate() {
    80  	x.mode_ = invalid
    81  }
    82  
    83  // Pos returns the position of the expression corresponding to x.
    84  // If x is invalid the position is nopos.
    85  func (x *operand) Pos() token.Pos {
    86  	// x.expr may not be set if x is invalid
    87  	if x.expr == nil {
    88  		return nopos
    89  	}
    90  	return x.expr.Pos()
    91  }
    92  
    93  // Operand string formats
    94  // (not all "untyped" cases can appear due to the type system,
    95  // but they fall out naturally here)
    96  //
    97  // mode       format
    98  //
    99  // invalid    <expr> (               <mode>                    )
   100  // novalue    <expr> (               <mode>                    )
   101  // builtin    <expr> (               <mode>                    )
   102  // typexpr    <expr> (               <mode>                    )
   103  //
   104  // constant   <expr> (<untyped kind> <mode>                    )
   105  // constant   <expr> (               <mode>       of type <typ>)
   106  // constant   <expr> (<untyped kind> <mode> <val>              )
   107  // constant   <expr> (               <mode> <val> of type <typ>)
   108  //
   109  // variable   <expr> (<untyped kind> <mode>                    )
   110  // variable   <expr> (               <mode>       of type <typ>)
   111  //
   112  // mapindex   <expr> (<untyped kind> <mode>                    )
   113  // mapindex   <expr> (               <mode>       of type <typ>)
   114  //
   115  // value      <expr> (<untyped kind> <mode>                    )
   116  // value      <expr> (               <mode>       of type <typ>)
   117  //
   118  // nilvalue   untyped nil
   119  // nilvalue   nil    (                            of type <typ>)
   120  //
   121  // commaok    <expr> (<untyped kind> <mode>                    )
   122  // commaok    <expr> (               <mode>       of type <typ>)
   123  //
   124  // commaerr   <expr> (<untyped kind> <mode>                    )
   125  // commaerr   <expr> (               <mode>       of type <typ>)
   126  //
   127  // cgofunc    <expr> (<untyped kind> <mode>                    )
   128  // cgofunc    <expr> (               <mode>       of type <typ>)
   129  func operandString(x *operand, qf Qualifier) string {
   130  	// special-case nil
   131  	if isTypes2 {
   132  		if x.mode() == nilvalue {
   133  			switch x.typ() {
   134  			case nil, Typ[Invalid]:
   135  				return "nil (with invalid type)"
   136  			case Typ[UntypedNil]:
   137  				return "nil"
   138  			default:
   139  				return fmt.Sprintf("nil (of type %s)", TypeString(x.typ(), qf))
   140  			}
   141  		}
   142  	} else { // go/types
   143  		if x.mode() == value && x.typ() == Typ[UntypedNil] {
   144  			return "nil"
   145  		}
   146  	}
   147  
   148  	var buf bytes.Buffer
   149  
   150  	var expr string
   151  	if x.expr != nil {
   152  		expr = ExprString(x.expr)
   153  	} else {
   154  		switch x.mode() {
   155  		case builtin:
   156  			expr = predeclaredFuncs[x.id].name
   157  		case typexpr:
   158  			expr = TypeString(x.typ(), qf)
   159  		case constant_:
   160  			expr = x.val.String()
   161  		}
   162  	}
   163  
   164  	// <expr> (
   165  	if expr != "" {
   166  		buf.WriteString(expr)
   167  		buf.WriteString(" (")
   168  	}
   169  
   170  	// <untyped kind>
   171  	hasType := false
   172  	switch x.mode() {
   173  	case invalid, novalue, builtin, typexpr:
   174  		// no type
   175  	default:
   176  		// should have a type, but be cautious (don't crash during printing)
   177  		if x.typ() != nil {
   178  			if isUntyped(x.typ()) {
   179  				buf.WriteString(x.typ().(*Basic).name)
   180  				buf.WriteByte(' ')
   181  				break
   182  			}
   183  			hasType = true
   184  		}
   185  	}
   186  
   187  	// <mode>
   188  	buf.WriteString(operandModeString[x.mode()])
   189  
   190  	// <val>
   191  	if x.mode() == constant_ {
   192  		if s := x.val.String(); s != expr {
   193  			buf.WriteByte(' ')
   194  			buf.WriteString(s)
   195  		}
   196  	}
   197  
   198  	// <typ>
   199  	if hasType {
   200  		if isValid(x.typ()) {
   201  			var desc string
   202  			if isGeneric(x.typ()) {
   203  				desc = "generic "
   204  			}
   205  
   206  			// Describe the type structure if it is an *Alias or *Named type.
   207  			// If the type is a renamed basic type, describe the basic type,
   208  			// as in "int32 type MyInt" for a *Named type MyInt.
   209  			// If it is a type parameter, describe the constraint instead.
   210  			tpar, _ := Unalias(x.typ()).(*TypeParam)
   211  			if tpar == nil {
   212  				switch x.typ().(type) {
   213  				case *Alias, *Named:
   214  					what := compositeKind(x.typ())
   215  					if what == "" {
   216  						// x.typ must be basic type
   217  						what = x.typ().Underlying().(*Basic).name
   218  					}
   219  					desc += what + " "
   220  				}
   221  			}
   222  			// desc is "" or has a trailing space at the end
   223  
   224  			buf.WriteString(" of " + desc + "type ")
   225  			WriteType(&buf, x.typ(), qf)
   226  
   227  			if tpar != nil {
   228  				buf.WriteString(" constrained by ")
   229  				WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
   230  				// If we have the type set and it's empty, say so for better error messages.
   231  				if hasEmptyTypeset(tpar) {
   232  					buf.WriteString(" with empty type set")
   233  				}
   234  			}
   235  		} else {
   236  			buf.WriteString(" with invalid type")
   237  		}
   238  	}
   239  
   240  	// )
   241  	if expr != "" {
   242  		buf.WriteByte(')')
   243  	}
   244  
   245  	return buf.String()
   246  }
   247  
   248  // compositeKind returns the kind of the given composite type
   249  // ("array", "slice", etc.) or the empty string if typ is not
   250  // composite but a basic type.
   251  func compositeKind(typ Type) string {
   252  	switch typ.Underlying().(type) {
   253  	case *Basic:
   254  		return ""
   255  	case *Array:
   256  		return "array"
   257  	case *Slice:
   258  		return "slice"
   259  	case *Struct:
   260  		return "struct"
   261  	case *Pointer:
   262  		return "pointer"
   263  	case *Signature:
   264  		return "func"
   265  	case *Interface:
   266  		return "interface"
   267  	case *Map:
   268  		return "map"
   269  	case *Chan:
   270  		return "chan"
   271  	case *Tuple:
   272  		return "tuple"
   273  	case *Union:
   274  		return "union"
   275  	default:
   276  		panic("unreachable")
   277  	}
   278  }
   279  
   280  func (x *operand) String() string {
   281  	return operandString(x, nil)
   282  }
   283  
   284  // setConst sets x to the untyped constant for literal lit.
   285  func (x *operand) setConst(k token.Token, lit string) {
   286  	var kind BasicKind
   287  	switch k {
   288  	case token.INT:
   289  		kind = UntypedInt
   290  	case token.FLOAT:
   291  		kind = UntypedFloat
   292  	case token.IMAG:
   293  		kind = UntypedComplex
   294  	case token.CHAR:
   295  		kind = UntypedRune
   296  	case token.STRING:
   297  		kind = UntypedString
   298  	default:
   299  		panic("unreachable")
   300  	}
   301  
   302  	val := makeFromLiteral(lit, k)
   303  	if val.Kind() == constant.Unknown {
   304  		x.invalidate()
   305  		x.typ_ = Typ[Invalid]
   306  		return
   307  	}
   308  	x.mode_ = constant_
   309  	x.typ_ = Typ[kind]
   310  	x.val = val
   311  }
   312  
   313  // isNil reports whether x is the (untyped) nil value.
   314  func (x *operand) isNil() bool {
   315  	if isTypes2 {
   316  		return x.mode() == nilvalue
   317  	} else { // go/types
   318  		return x.mode() == value && x.typ() == Typ[UntypedNil]
   319  	}
   320  }
   321  
   322  // assignableTo reports whether x is assignable to a variable of type T. If the
   323  // result is false and a non-nil cause is provided, it may be set to a more
   324  // detailed explanation of the failure (result != ""). The returned error code
   325  // is only valid if the (first) result is false. The check parameter may be nil
   326  // if assignableTo is invoked through an exported API call, i.e., when all
   327  // methods have been type-checked.
   328  func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
   329  	if !x.isValid() || !isValid(T) {
   330  		return true, 0 // avoid spurious errors
   331  	}
   332  
   333  	origT := T
   334  	V := Unalias(x.typ())
   335  	T = Unalias(T)
   336  
   337  	// x's type is identical to T
   338  	if Identical(V, T) {
   339  		return true, 0
   340  	}
   341  
   342  	Vu := V.Underlying()
   343  	Tu := T.Underlying()
   344  	Vp, _ := V.(*TypeParam)
   345  	Tp, _ := T.(*TypeParam)
   346  
   347  	// x is an untyped value representable by a value of type T.
   348  	if isUntyped(Vu) {
   349  		assert(Vp == nil)
   350  		if Tp != nil {
   351  			// T is a type parameter: x is assignable to T if it is
   352  			// representable by each specific type in the type set of T.
   353  			return Tp.is(func(t *term) bool {
   354  				if t == nil {
   355  					return false
   356  				}
   357  				// A term may be a tilde term but the underlying
   358  				// type of an untyped value doesn't change so we
   359  				// don't need to do anything special.
   360  				newType, _, _ := check.implicitTypeAndValue(x, t.typ)
   361  				return newType != nil
   362  			}), IncompatibleAssign
   363  		}
   364  		newType, _, _ := check.implicitTypeAndValue(x, T)
   365  		return newType != nil, IncompatibleAssign
   366  	}
   367  	// Vu is typed
   368  
   369  	// x's type V and T have identical underlying types
   370  	// and at least one of V or T is not a named type
   371  	// and neither V nor T is a type parameter.
   372  	if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
   373  		return true, 0
   374  	}
   375  
   376  	// T is an interface type, but not a type parameter, and V implements T.
   377  	// Also handle the case where T is a pointer to an interface so that we get
   378  	// the Checker.implements error cause.
   379  	if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
   380  		if check.implements(V, T, false, cause) {
   381  			return true, 0
   382  		}
   383  		// V doesn't implement T but V may still be assignable to T if V
   384  		// is a type parameter; do not report an error in that case yet.
   385  		if Vp == nil {
   386  			return false, InvalidIfaceAssign
   387  		}
   388  		if cause != nil {
   389  			*cause = ""
   390  		}
   391  	}
   392  
   393  	// If V is an interface, check if a missing type assertion is the problem.
   394  	if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
   395  		if check.implements(T, V, false, nil) {
   396  			// T implements V, so give hint about type assertion.
   397  			if cause != nil {
   398  				*cause = "need type assertion"
   399  			}
   400  			return false, IncompatibleAssign
   401  		}
   402  	}
   403  
   404  	// x is a bidirectional channel value, T is a channel
   405  	// type, x's type V and T have identical element types,
   406  	// and at least one of V or T is not a named type.
   407  	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
   408  		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
   409  			return !hasName(V) || !hasName(T), InvalidChanAssign
   410  		}
   411  	}
   412  
   413  	// optimization: if we don't have type parameters, we're done
   414  	if Vp == nil && Tp == nil {
   415  		return false, IncompatibleAssign
   416  	}
   417  
   418  	errorf := func(format string, args ...any) {
   419  		if check != nil && cause != nil {
   420  			msg := check.sprintf(format, args...)
   421  			if *cause != "" {
   422  				msg += "\n\t" + *cause
   423  			}
   424  			*cause = msg
   425  		}
   426  	}
   427  
   428  	// x's type V is not a named type and T is a type parameter, and
   429  	// x is assignable to each specific type in T's type set.
   430  	if !hasName(V) && Tp != nil {
   431  		ok := false
   432  		code := IncompatibleAssign
   433  		Tp.is(func(T *term) bool {
   434  			if T == nil {
   435  				return false // no specific types
   436  			}
   437  			ok, code = x.assignableTo(check, T.typ, cause)
   438  			if !ok {
   439  				errorf("cannot assign %s to %s (in %s)", x.typ(), T.typ, Tp)
   440  				return false
   441  			}
   442  			return true
   443  		})
   444  		return ok, code
   445  	}
   446  
   447  	// x's type V is a type parameter and T is not a named type,
   448  	// and values x' of each specific type in V's type set are
   449  	// assignable to T.
   450  	if Vp != nil && !hasName(T) {
   451  		x := *x // don't clobber outer x
   452  		ok := false
   453  		code := IncompatibleAssign
   454  		Vp.is(func(V *term) bool {
   455  			if V == nil {
   456  				return false // no specific types
   457  			}
   458  			x.typ_ = V.typ
   459  			ok, code = x.assignableTo(check, T, cause)
   460  			if !ok {
   461  				errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
   462  				return false
   463  			}
   464  			return true
   465  		})
   466  		return ok, code
   467  	}
   468  
   469  	return false, IncompatibleAssign
   470  }
   471  

View as plain text