1  
     2  
     3  
     4  
     5  
     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  
    18  type operandMode byte
    19  
    20  const (
    21  	invalid   operandMode = iota 
    22  	novalue                      
    23  	builtin                      
    24  	typexpr                      
    25  	constant_                    
    26  	variable                     
    27  	mapindex                     
    28  	value                        
    29  	nilvalue                     
    30  	commaok                      
    31  	commaerr                     
    32  	cgofunc                      
    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", 
    45  	commaok:   "comma, ok expression",
    46  	commaerr:  "comma, error expression",
    47  	cgofunc:   "cgo function",
    48  }
    49  
    50  
    51  
    52  
    53  
    54  
    55  type operand struct {
    56  	mode operandMode
    57  	expr syntax.Expr
    58  	typ  Type
    59  	val  constant.Value
    60  	id   builtinId
    61  }
    62  
    63  
    64  
    65  func (x *operand) Pos() syntax.Pos {
    66  	
    67  	if x.expr == nil {
    68  		return nopos
    69  	}
    70  	return x.expr.Pos()
    71  }
    72  
    73  
    74  
    75  
    76  
    77  
    78  
    79  
    80  
    81  
    82  
    83  
    84  
    85  
    86  
    87  
    88  
    89  
    90  
    91  
    92  
    93  
    94  
    95  
    96  
    97  
    98  
    99  
   100  
   101  
   102  
   103  
   104  
   105  
   106  
   107  
   108  
   109  func operandString(x *operand, qf Qualifier) string {
   110  	
   111  	if isTypes2 {
   112  		if x.mode == nilvalue {
   113  			switch x.typ {
   114  			case nil, Typ[Invalid]:
   115  				return "nil (with invalid type)"
   116  			case Typ[UntypedNil]:
   117  				return "nil"
   118  			default:
   119  				return fmt.Sprintf("nil (of type %s)", TypeString(x.typ, qf))
   120  			}
   121  		}
   122  	} else { 
   123  		if x.mode == value && x.typ == Typ[UntypedNil] {
   124  			return "nil"
   125  		}
   126  	}
   127  
   128  	var buf bytes.Buffer
   129  
   130  	var expr string
   131  	if x.expr != nil {
   132  		expr = ExprString(x.expr)
   133  	} else {
   134  		switch x.mode {
   135  		case builtin:
   136  			expr = predeclaredFuncs[x.id].name
   137  		case typexpr:
   138  			expr = TypeString(x.typ, qf)
   139  		case constant_:
   140  			expr = x.val.String()
   141  		}
   142  	}
   143  
   144  	
   145  	if expr != "" {
   146  		buf.WriteString(expr)
   147  		buf.WriteString(" (")
   148  	}
   149  
   150  	
   151  	hasType := false
   152  	switch x.mode {
   153  	case invalid, novalue, builtin, typexpr:
   154  		
   155  	default:
   156  		
   157  		if x.typ != nil {
   158  			if isUntyped(x.typ) {
   159  				buf.WriteString(x.typ.(*Basic).name)
   160  				buf.WriteByte(' ')
   161  				break
   162  			}
   163  			hasType = true
   164  		}
   165  	}
   166  
   167  	
   168  	buf.WriteString(operandModeString[x.mode])
   169  
   170  	
   171  	if x.mode == constant_ {
   172  		if s := x.val.String(); s != expr {
   173  			buf.WriteByte(' ')
   174  			buf.WriteString(s)
   175  		}
   176  	}
   177  
   178  	
   179  	if hasType {
   180  		if isValid(x.typ) {
   181  			var desc string
   182  			if isGeneric(x.typ) {
   183  				desc = "generic "
   184  			}
   185  
   186  			
   187  			
   188  			
   189  			
   190  			tpar, _ := Unalias(x.typ).(*TypeParam)
   191  			if tpar == nil {
   192  				switch x.typ.(type) {
   193  				case *Alias, *Named:
   194  					what := compositeKind(x.typ)
   195  					if what == "" {
   196  						
   197  						what = under(x.typ).(*Basic).name
   198  					}
   199  					desc += what + " "
   200  				}
   201  			}
   202  			
   203  
   204  			buf.WriteString(" of " + desc + "type ")
   205  			WriteType(&buf, x.typ, qf)
   206  
   207  			if tpar != nil {
   208  				buf.WriteString(" constrained by ")
   209  				WriteType(&buf, tpar.bound, qf) 
   210  				
   211  				if hasEmptyTypeset(tpar) {
   212  					buf.WriteString(" with empty type set")
   213  				}
   214  			}
   215  		} else {
   216  			buf.WriteString(" with invalid type")
   217  		}
   218  	}
   219  
   220  	
   221  	if expr != "" {
   222  		buf.WriteByte(')')
   223  	}
   224  
   225  	return buf.String()
   226  }
   227  
   228  
   229  
   230  
   231  func compositeKind(typ Type) string {
   232  	switch under(typ).(type) {
   233  	case *Basic:
   234  		return ""
   235  	case *Array:
   236  		return "array"
   237  	case *Slice:
   238  		return "slice"
   239  	case *Struct:
   240  		return "struct"
   241  	case *Pointer:
   242  		return "pointer"
   243  	case *Signature:
   244  		return "func"
   245  	case *Interface:
   246  		return "interface"
   247  	case *Map:
   248  		return "map"
   249  	case *Chan:
   250  		return "chan"
   251  	case *Tuple:
   252  		return "tuple"
   253  	case *Union:
   254  		return "union"
   255  	default:
   256  		panic("unreachable")
   257  	}
   258  }
   259  
   260  func (x *operand) String() string {
   261  	return operandString(x, nil)
   262  }
   263  
   264  
   265  func (x *operand) setConst(k syntax.LitKind, lit string) {
   266  	var kind BasicKind
   267  	switch k {
   268  	case syntax.IntLit:
   269  		kind = UntypedInt
   270  	case syntax.FloatLit:
   271  		kind = UntypedFloat
   272  	case syntax.ImagLit:
   273  		kind = UntypedComplex
   274  	case syntax.RuneLit:
   275  		kind = UntypedRune
   276  	case syntax.StringLit:
   277  		kind = UntypedString
   278  	default:
   279  		panic("unreachable")
   280  	}
   281  
   282  	val := makeFromLiteral(lit, k)
   283  	if val.Kind() == constant.Unknown {
   284  		x.mode = invalid
   285  		x.typ = Typ[Invalid]
   286  		return
   287  	}
   288  	x.mode = constant_
   289  	x.typ = Typ[kind]
   290  	x.val = val
   291  }
   292  
   293  
   294  func (x *operand) isNil() bool {
   295  	if isTypes2 {
   296  		return x.mode == nilvalue
   297  	} else { 
   298  		return x.mode == value && x.typ == Typ[UntypedNil]
   299  	}
   300  }
   301  
   302  
   303  
   304  
   305  
   306  
   307  
   308  func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
   309  	if x.mode == invalid || !isValid(T) {
   310  		return true, 0 
   311  	}
   312  
   313  	origT := T
   314  	V := Unalias(x.typ)
   315  	T = Unalias(T)
   316  
   317  	
   318  	if Identical(V, T) {
   319  		return true, 0
   320  	}
   321  
   322  	Vu := under(V)
   323  	Tu := under(T)
   324  	Vp, _ := V.(*TypeParam)
   325  	Tp, _ := T.(*TypeParam)
   326  
   327  	
   328  	if isUntyped(Vu) {
   329  		assert(Vp == nil)
   330  		if Tp != nil {
   331  			
   332  			
   333  			return Tp.is(func(t *term) bool {
   334  				if t == nil {
   335  					return false
   336  				}
   337  				
   338  				
   339  				
   340  				newType, _, _ := check.implicitTypeAndValue(x, t.typ)
   341  				return newType != nil
   342  			}), IncompatibleAssign
   343  		}
   344  		newType, _, _ := check.implicitTypeAndValue(x, T)
   345  		return newType != nil, IncompatibleAssign
   346  	}
   347  	
   348  
   349  	
   350  	
   351  	
   352  	if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
   353  		return true, 0
   354  	}
   355  
   356  	
   357  	
   358  	
   359  	if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
   360  		if check.implements(V, T, false, cause) {
   361  			return true, 0
   362  		}
   363  		
   364  		
   365  		if Vp == nil {
   366  			return false, InvalidIfaceAssign
   367  		}
   368  		if cause != nil {
   369  			*cause = ""
   370  		}
   371  	}
   372  
   373  	
   374  	if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
   375  		if check.implements(T, V, false, nil) {
   376  			
   377  			if cause != nil {
   378  				*cause = "need type assertion"
   379  			}
   380  			return false, IncompatibleAssign
   381  		}
   382  	}
   383  
   384  	
   385  	
   386  	
   387  	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
   388  		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
   389  			return !hasName(V) || !hasName(T), InvalidChanAssign
   390  		}
   391  	}
   392  
   393  	
   394  	if Vp == nil && Tp == nil {
   395  		return false, IncompatibleAssign
   396  	}
   397  
   398  	errorf := func(format string, args ...any) {
   399  		if check != nil && cause != nil {
   400  			msg := check.sprintf(format, args...)
   401  			if *cause != "" {
   402  				msg += "\n\t" + *cause
   403  			}
   404  			*cause = msg
   405  		}
   406  	}
   407  
   408  	
   409  	
   410  	if !hasName(V) && Tp != nil {
   411  		ok := false
   412  		code := IncompatibleAssign
   413  		Tp.is(func(T *term) bool {
   414  			if T == nil {
   415  				return false 
   416  			}
   417  			ok, code = x.assignableTo(check, T.typ, cause)
   418  			if !ok {
   419  				errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
   420  				return false
   421  			}
   422  			return true
   423  		})
   424  		return ok, code
   425  	}
   426  
   427  	
   428  	
   429  	
   430  	if Vp != nil && !hasName(T) {
   431  		x := *x 
   432  		ok := false
   433  		code := IncompatibleAssign
   434  		Vp.is(func(V *term) bool {
   435  			if V == nil {
   436  				return false 
   437  			}
   438  			x.typ = V.typ
   439  			ok, code = x.assignableTo(check, T, cause)
   440  			if !ok {
   441  				errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
   442  				return false
   443  			}
   444  			return true
   445  		})
   446  		return ok, code
   447  	}
   448  
   449  	return false, IncompatibleAssign
   450  }
   451  
View as plain text