operand.go raw

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