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  // 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 intro string
   186  			if isGeneric(x.typ) {
   187  				intro = " of generic type "
   188  			} else {
   189  				intro = " of type "
   190  			}
   191  			buf.WriteString(intro)
   192  			WriteType(&buf, x.typ, qf)
   193  			if tpar, _ := Unalias(x.typ).(*TypeParam); tpar != nil {
   194  				buf.WriteString(" constrained by ")
   195  				WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
   196  				// If we have the type set and it's empty, say so for better error messages.
   197  				if hasEmptyTypeset(tpar) {
   198  					buf.WriteString(" with empty type set")
   199  				}
   200  			}
   201  		} else {
   202  			buf.WriteString(" with invalid type")
   203  		}
   204  	}
   205  
   206  	// )
   207  	if expr != "" {
   208  		buf.WriteByte(')')
   209  	}
   210  
   211  	return buf.String()
   212  }
   213  
   214  func (x *operand) String() string {
   215  	return operandString(x, nil)
   216  }
   217  
   218  // setConst sets x to the untyped constant for literal lit.
   219  func (x *operand) setConst(k token.Token, lit string) {
   220  	var kind BasicKind
   221  	switch k {
   222  	case token.INT:
   223  		kind = UntypedInt
   224  	case token.FLOAT:
   225  		kind = UntypedFloat
   226  	case token.IMAG:
   227  		kind = UntypedComplex
   228  	case token.CHAR:
   229  		kind = UntypedRune
   230  	case token.STRING:
   231  		kind = UntypedString
   232  	default:
   233  		panic("unreachable")
   234  	}
   235  
   236  	val := makeFromLiteral(lit, k)
   237  	if val.Kind() == constant.Unknown {
   238  		x.mode = invalid
   239  		x.typ = Typ[Invalid]
   240  		return
   241  	}
   242  	x.mode = constant_
   243  	x.typ = Typ[kind]
   244  	x.val = val
   245  }
   246  
   247  // isNil reports whether x is the (untyped) nil value.
   248  func (x *operand) isNil() bool {
   249  	if isTypes2 {
   250  		return x.mode == nilvalue
   251  	} else { // go/types
   252  		return x.mode == value && x.typ == Typ[UntypedNil]
   253  	}
   254  }
   255  
   256  // assignableTo reports whether x is assignable to a variable of type T. If the
   257  // result is false and a non-nil cause is provided, it may be set to a more
   258  // detailed explanation of the failure (result != ""). The returned error code
   259  // is only valid if the (first) result is false. The check parameter may be nil
   260  // if assignableTo is invoked through an exported API call, i.e., when all
   261  // methods have been type-checked.
   262  func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
   263  	if x.mode == invalid || !isValid(T) {
   264  		return true, 0 // avoid spurious errors
   265  	}
   266  
   267  	origT := T
   268  	V := Unalias(x.typ)
   269  	T = Unalias(T)
   270  
   271  	// x's type is identical to T
   272  	if Identical(V, T) {
   273  		return true, 0
   274  	}
   275  
   276  	Vu := under(V)
   277  	Tu := under(T)
   278  	Vp, _ := V.(*TypeParam)
   279  	Tp, _ := T.(*TypeParam)
   280  
   281  	// x is an untyped value representable by a value of type T.
   282  	if isUntyped(Vu) {
   283  		assert(Vp == nil)
   284  		if Tp != nil {
   285  			// T is a type parameter: x is assignable to T if it is
   286  			// representable by each specific type in the type set of T.
   287  			return Tp.is(func(t *term) bool {
   288  				if t == nil {
   289  					return false
   290  				}
   291  				// A term may be a tilde term but the underlying
   292  				// type of an untyped value doesn't change so we
   293  				// don't need to do anything special.
   294  				newType, _, _ := check.implicitTypeAndValue(x, t.typ)
   295  				return newType != nil
   296  			}), IncompatibleAssign
   297  		}
   298  		newType, _, _ := check.implicitTypeAndValue(x, T)
   299  		return newType != nil, IncompatibleAssign
   300  	}
   301  	// Vu is typed
   302  
   303  	// x's type V and T have identical underlying types
   304  	// and at least one of V or T is not a named type
   305  	// and neither V nor T is a type parameter.
   306  	if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
   307  		return true, 0
   308  	}
   309  
   310  	// T is an interface type, but not a type parameter, and V implements T.
   311  	// Also handle the case where T is a pointer to an interface so that we get
   312  	// the Checker.implements error cause.
   313  	if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
   314  		if check.implements(x.Pos(), V, T, false, cause) {
   315  			return true, 0
   316  		}
   317  		// V doesn't implement T but V may still be assignable to T if V
   318  		// is a type parameter; do not report an error in that case yet.
   319  		if Vp == nil {
   320  			return false, InvalidIfaceAssign
   321  		}
   322  		if cause != nil {
   323  			*cause = ""
   324  		}
   325  	}
   326  
   327  	// If V is an interface, check if a missing type assertion is the problem.
   328  	if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
   329  		if check.implements(x.Pos(), T, V, false, nil) {
   330  			// T implements V, so give hint about type assertion.
   331  			if cause != nil {
   332  				*cause = "need type assertion"
   333  			}
   334  			return false, IncompatibleAssign
   335  		}
   336  	}
   337  
   338  	// x is a bidirectional channel value, T is a channel
   339  	// type, x's type V and T have identical element types,
   340  	// and at least one of V or T is not a named type.
   341  	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
   342  		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
   343  			return !hasName(V) || !hasName(T), InvalidChanAssign
   344  		}
   345  	}
   346  
   347  	// optimization: if we don't have type parameters, we're done
   348  	if Vp == nil && Tp == nil {
   349  		return false, IncompatibleAssign
   350  	}
   351  
   352  	errorf := func(format string, args ...any) {
   353  		if check != nil && cause != nil {
   354  			msg := check.sprintf(format, args...)
   355  			if *cause != "" {
   356  				msg += "\n\t" + *cause
   357  			}
   358  			*cause = msg
   359  		}
   360  	}
   361  
   362  	// x's type V is not a named type and T is a type parameter, and
   363  	// x is assignable to each specific type in T's type set.
   364  	if !hasName(V) && Tp != nil {
   365  		ok := false
   366  		code := IncompatibleAssign
   367  		Tp.is(func(T *term) bool {
   368  			if T == nil {
   369  				return false // no specific types
   370  			}
   371  			ok, code = x.assignableTo(check, T.typ, cause)
   372  			if !ok {
   373  				errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
   374  				return false
   375  			}
   376  			return true
   377  		})
   378  		return ok, code
   379  	}
   380  
   381  	// x's type V is a type parameter and T is not a named type,
   382  	// and values x' of each specific type in V's type set are
   383  	// assignable to T.
   384  	if Vp != nil && !hasName(T) {
   385  		x := *x // don't clobber outer x
   386  		ok := false
   387  		code := IncompatibleAssign
   388  		Vp.is(func(V *term) bool {
   389  			if V == nil {
   390  				return false // no specific types
   391  			}
   392  			x.typ = V.typ
   393  			ok, code = x.assignableTo(check, T, cause)
   394  			if !ok {
   395  				errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
   396  				return false
   397  			}
   398  			return true
   399  		})
   400  		return ok, code
   401  	}
   402  
   403  	return false, IncompatibleAssign
   404  }
   405  

View as plain text