Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/noder/expr.go

Documentation: cmd/compile/internal/noder

     1  // Copyright 2021 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  package noder
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/ir"
    10  	"cmd/compile/internal/syntax"
    11  	"cmd/compile/internal/typecheck"
    12  	"cmd/compile/internal/types"
    13  	"cmd/compile/internal/types2"
    14  	"cmd/internal/src"
    15  )
    16  
    17  func (g *irgen) expr(expr syntax.Expr) ir.Node {
    18  	if expr == nil {
    19  		return nil
    20  	}
    21  
    22  	if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
    23  		return ir.BlankNode
    24  	}
    25  
    26  	tv, ok := g.info.Types[expr]
    27  	if !ok {
    28  		base.FatalfAt(g.pos(expr), "missing type for %v (%T)", expr, expr)
    29  	}
    30  	switch {
    31  	case tv.IsBuiltin():
    32  		// Qualified builtins, such as unsafe.Add and unsafe.Slice.
    33  		if expr, ok := expr.(*syntax.SelectorExpr); ok {
    34  			if name, ok := expr.X.(*syntax.Name); ok {
    35  				if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
    36  					return g.use(expr.Sel)
    37  				}
    38  			}
    39  		}
    40  		return g.use(expr.(*syntax.Name))
    41  	case tv.IsType():
    42  		return ir.TypeNode(g.typ(tv.Type))
    43  	case tv.IsValue(), tv.IsVoid():
    44  		// ok
    45  	default:
    46  		base.FatalfAt(g.pos(expr), "unrecognized type-checker result")
    47  	}
    48  
    49  	// The gc backend expects all expressions to have a concrete type, and
    50  	// types2 mostly satisfies this expectation already. But there are a few
    51  	// cases where the Go spec doesn't require converting to concrete type,
    52  	// and so types2 leaves them untyped. So we need to fix those up here.
    53  	typ := tv.Type
    54  	if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
    55  		switch basic.Kind() {
    56  		case types2.UntypedNil:
    57  			// ok; can appear in type switch case clauses
    58  			// TODO(mdempsky): Handle as part of type switches instead?
    59  		case types2.UntypedBool:
    60  			typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
    61  		case types2.UntypedString:
    62  			typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
    63  		default:
    64  			base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", basic)
    65  		}
    66  	}
    67  
    68  	// Constant expression.
    69  	if tv.Value != nil {
    70  		return Const(g.pos(expr), g.typ(typ), tv.Value)
    71  	}
    72  
    73  	n := g.expr0(typ, expr)
    74  	if n.Typecheck() != 1 && n.Typecheck() != 3 {
    75  		base.FatalfAt(g.pos(expr), "missed typecheck: %+v", n)
    76  	}
    77  	if !g.match(n.Type(), typ, tv.HasOk()) {
    78  		base.FatalfAt(g.pos(expr), "expected %L to have type %v", n, typ)
    79  	}
    80  	return n
    81  }
    82  
    83  func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
    84  	pos := g.pos(expr)
    85  
    86  	switch expr := expr.(type) {
    87  	case *syntax.Name:
    88  		if _, isNil := g.info.Uses[expr].(*types2.Nil); isNil {
    89  			return Nil(pos, g.typ(typ))
    90  		}
    91  		return g.use(expr)
    92  
    93  	case *syntax.CompositeLit:
    94  		return g.compLit(typ, expr)
    95  
    96  	case *syntax.FuncLit:
    97  		return g.funcLit(typ, expr)
    98  
    99  	case *syntax.AssertExpr:
   100  		return Assert(pos, g.expr(expr.X), g.typeExpr(expr.Type))
   101  
   102  	case *syntax.CallExpr:
   103  		fun := g.expr(expr.Fun)
   104  
   105  		// The key for the Inferred map is the CallExpr (if inferring
   106  		// types required the function arguments) or the IndexExpr below
   107  		// (if types could be inferred without the function arguments).
   108  		if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 {
   109  			// This is the case where inferring types required the
   110  			// types of the function arguments.
   111  			targs := make([]ir.Node, len(inferred.Targs))
   112  			for i, targ := range inferred.Targs {
   113  				targs[i] = ir.TypeNode(g.typ(targ))
   114  			}
   115  			if fun.Op() == ir.OFUNCINST {
   116  				// Replace explicit type args with the full list that
   117  				// includes the additional inferred type args
   118  				fun.(*ir.InstExpr).Targs = targs
   119  			} else {
   120  				// Create a function instantiation here, given
   121  				// there are only inferred type args (e.g.
   122  				// min(5,6), where min is a generic function)
   123  				inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs)
   124  				typed(fun.Type(), inst)
   125  				fun = inst
   126  			}
   127  
   128  		}
   129  		return Call(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots)
   130  
   131  	case *syntax.IndexExpr:
   132  		var targs []ir.Node
   133  
   134  		if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 {
   135  			// This is the partial type inference case where the types
   136  			// can be inferred from other type arguments without using
   137  			// the types of the function arguments.
   138  			targs = make([]ir.Node, len(inferred.Targs))
   139  			for i, targ := range inferred.Targs {
   140  				targs[i] = ir.TypeNode(g.typ(targ))
   141  			}
   142  		} else if _, ok := expr.Index.(*syntax.ListExpr); ok {
   143  			targs = g.exprList(expr.Index)
   144  		} else {
   145  			index := g.expr(expr.Index)
   146  			if index.Op() != ir.OTYPE {
   147  				// This is just a normal index expression
   148  				return Index(pos, g.typ(typ), g.expr(expr.X), index)
   149  			}
   150  			// This is generic function instantiation with a single type
   151  			targs = []ir.Node{index}
   152  		}
   153  		// This is a generic function instantiation (e.g. min[int]).
   154  		// Generic type instantiation is handled in the type
   155  		// section of expr() above (using g.typ).
   156  		x := g.expr(expr.X)
   157  		if x.Op() != ir.ONAME || x.Type().Kind() != types.TFUNC {
   158  			panic("Incorrect argument for generic func instantiation")
   159  		}
   160  		n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs)
   161  		typed(g.typ(typ), n)
   162  		return n
   163  
   164  	case *syntax.ParenExpr:
   165  		return g.expr(expr.X) // skip parens; unneeded after parse+typecheck
   166  
   167  	case *syntax.SelectorExpr:
   168  		// Qualified identifier.
   169  		if name, ok := expr.X.(*syntax.Name); ok {
   170  			if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
   171  				return g.use(expr.Sel)
   172  			}
   173  		}
   174  		return g.selectorExpr(pos, typ, expr)
   175  
   176  	case *syntax.SliceExpr:
   177  		return Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2]))
   178  
   179  	case *syntax.Operation:
   180  		if expr.Y == nil {
   181  			return Unary(pos, g.typ(typ), g.op(expr.Op, unOps[:]), g.expr(expr.X))
   182  		}
   183  		switch op := g.op(expr.Op, binOps[:]); op {
   184  		case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
   185  			return Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y))
   186  		default:
   187  			return Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y))
   188  		}
   189  
   190  	default:
   191  		g.unhandled("expression", expr)
   192  		panic("unreachable")
   193  	}
   194  }
   195  
   196  // selectorExpr resolves the choice of ODOT, ODOTPTR, OCALLPART (eventually
   197  // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
   198  // than in typecheck.go.
   199  func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
   200  	x := g.expr(expr.X)
   201  	if x.Type().HasTParam() {
   202  		// Leave a method call on a type param as an OXDOT, since it can
   203  		// only be fully transformed once it has an instantiated type.
   204  		n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
   205  		typed(g.typ(typ), n)
   206  		return n
   207  	}
   208  
   209  	selinfo := g.info.Selections[expr]
   210  	// Everything up to the last selection is an implicit embedded field access,
   211  	// and the last selection is determined by selinfo.Kind().
   212  	index := selinfo.Index()
   213  	embeds, last := index[:len(index)-1], index[len(index)-1]
   214  
   215  	origx := x
   216  	for _, ix := range embeds {
   217  		x = Implicit(DotField(pos, x, ix))
   218  	}
   219  
   220  	kind := selinfo.Kind()
   221  	if kind == types2.FieldVal {
   222  		return DotField(pos, x, last)
   223  	}
   224  
   225  	// TODO(danscales,mdempsky): Interface method sets are not sorted the
   226  	// same between types and types2. In particular, using "last" here
   227  	// without conversion will likely fail if an interface contains
   228  	// unexported methods from two different packages (due to cross-package
   229  	// interface embedding).
   230  
   231  	var n ir.Node
   232  	method2 := selinfo.Obj().(*types2.Func)
   233  
   234  	if kind == types2.MethodExpr {
   235  		// OMETHEXPR is unusual in using directly the node and type of the
   236  		// original OTYPE node (origx) before passing through embedded
   237  		// fields, even though the method is selected from the type
   238  		// (x.Type()) reached after following the embedded fields. We will
   239  		// actually drop any ODOT nodes we created due to the embedded
   240  		// fields.
   241  		n = MethodExpr(pos, origx, x.Type(), last)
   242  	} else {
   243  		// Add implicit addr/deref for method values, if needed.
   244  		if x.Type().IsInterface() {
   245  			n = DotMethod(pos, x, last)
   246  		} else {
   247  			recvType2 := method2.Type().(*types2.Signature).Recv().Type()
   248  			_, wantPtr := recvType2.(*types2.Pointer)
   249  			havePtr := x.Type().IsPtr()
   250  
   251  			if havePtr != wantPtr {
   252  				if havePtr {
   253  					x = Implicit(Deref(pos, x.Type().Elem(), x))
   254  				} else {
   255  					x = Implicit(Addr(pos, x))
   256  				}
   257  			}
   258  			recvType2Base := recvType2
   259  			if wantPtr {
   260  				recvType2Base = types2.AsPointer(recvType2).Elem()
   261  			}
   262  			if len(types2.AsNamed(recvType2Base).TParams()) > 0 {
   263  				// recvType2 is the original generic type that is
   264  				// instantiated for this method call.
   265  				// selinfo.Recv() is the instantiated type
   266  				recvType2 = recvType2Base
   267  				// method is the generic method associated with the gen type
   268  				method := g.obj(types2.AsNamed(recvType2).Method(last))
   269  				n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, method.Sym())
   270  				n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
   271  				n.(*ir.SelectorExpr).Selection.Nname = method
   272  				typed(method.Type(), n)
   273  
   274  				// selinfo.Targs() are the types used to
   275  				// instantiate the type of receiver
   276  				targs2 := getTargs(selinfo)
   277  				targs := make([]ir.Node, len(targs2))
   278  				for i, targ2 := range targs2 {
   279  					targs[i] = ir.TypeNode(g.typ(targ2))
   280  				}
   281  
   282  				// Create function instantiation with the type
   283  				// args for the receiver type for the method call.
   284  				n = ir.NewInstExpr(pos, ir.OFUNCINST, n, targs)
   285  				typed(g.typ(typ), n)
   286  				return n
   287  			}
   288  
   289  			if !g.match(x.Type(), recvType2, false) {
   290  				base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
   291  			} else {
   292  				n = DotMethod(pos, x, last)
   293  			}
   294  		}
   295  	}
   296  	if have, want := n.Sym(), g.selector(method2); have != want {
   297  		base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
   298  	}
   299  	return n
   300  }
   301  
   302  // getTargs gets the targs associated with the receiver of a selected method
   303  func getTargs(selinfo *types2.Selection) []types2.Type {
   304  	r := selinfo.Recv()
   305  	if p := types2.AsPointer(r); p != nil {
   306  		r = p.Elem()
   307  	}
   308  	n := types2.AsNamed(r)
   309  	if n == nil {
   310  		base.Fatalf("Incorrect type for selinfo %v", selinfo)
   311  	}
   312  	return n.TArgs()
   313  }
   314  
   315  func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
   316  	switch expr := expr.(type) {
   317  	case nil:
   318  		return nil
   319  	case *syntax.ListExpr:
   320  		return g.exprs(expr.ElemList)
   321  	default:
   322  		return []ir.Node{g.expr(expr)}
   323  	}
   324  }
   325  
   326  func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
   327  	nodes := make([]ir.Node, len(exprs))
   328  	for i, expr := range exprs {
   329  		nodes[i] = g.expr(expr)
   330  	}
   331  	return nodes
   332  }
   333  
   334  func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
   335  	if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
   336  		n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
   337  		n.SetOp(ir.OPTRLIT)
   338  		return typed(g.typ(typ), n)
   339  	}
   340  
   341  	_, isStruct := typ.Underlying().(*types2.Struct)
   342  
   343  	exprs := make([]ir.Node, len(lit.ElemList))
   344  	for i, elem := range lit.ElemList {
   345  		switch elem := elem.(type) {
   346  		case *syntax.KeyValueExpr:
   347  			if isStruct {
   348  				exprs[i] = ir.NewStructKeyExpr(g.pos(elem), g.name(elem.Key.(*syntax.Name)), g.expr(elem.Value))
   349  			} else {
   350  				exprs[i] = ir.NewKeyExpr(g.pos(elem), g.expr(elem.Key), g.expr(elem.Value))
   351  			}
   352  		default:
   353  			exprs[i] = g.expr(elem)
   354  		}
   355  	}
   356  
   357  	n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs)
   358  	typed(g.typ(typ), n)
   359  	return transformCompLit(n)
   360  }
   361  
   362  func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
   363  	fn := ir.NewFunc(g.pos(expr))
   364  	fn.SetIsHiddenClosure(ir.CurFunc != nil)
   365  
   366  	fn.Nname = ir.NewNameAt(g.pos(expr), typecheck.ClosureName(ir.CurFunc))
   367  	ir.MarkFunc(fn.Nname)
   368  	typ := g.typ(typ2)
   369  	fn.Nname.Func = fn
   370  	fn.Nname.Defn = fn
   371  	typed(typ, fn.Nname)
   372  	fn.SetTypecheck(1)
   373  
   374  	fn.OClosure = ir.NewClosureExpr(g.pos(expr), fn)
   375  	typed(typ, fn.OClosure)
   376  
   377  	g.funcBody(fn, nil, expr.Type, expr.Body)
   378  
   379  	ir.FinishCaptureNames(fn.Pos(), ir.CurFunc, fn)
   380  
   381  	// TODO(mdempsky): ir.CaptureName should probably handle
   382  	// copying these fields from the canonical variable.
   383  	for _, cv := range fn.ClosureVars {
   384  		cv.SetType(cv.Canonical().Type())
   385  		cv.SetTypecheck(1)
   386  		cv.SetWalkdef(1)
   387  	}
   388  
   389  	g.target.Decls = append(g.target.Decls, fn)
   390  
   391  	return fn.OClosure
   392  }
   393  
   394  func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
   395  	n := g.expr(typ)
   396  	if n.Op() != ir.OTYPE {
   397  		base.FatalfAt(g.pos(typ), "expected type: %L", n)
   398  	}
   399  	return n.Type()
   400  }
   401  

View as plain text