...

Source file src/cmd/compile/internal/types2/operand.go

Documentation: cmd/compile/internal/types2

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

View as plain text