return base.Ctxt.PosTable.XPos(r.pos0())
}
+// origPos reads a position from the bitstream, and returns both the
+// original raw position and an inlining-adjusted position.
+func (r *reader) origPos() (origPos, inlPos src.XPos) {
+ r.suppressInlPos++
+ origPos = r.pos()
+ r.suppressInlPos--
+ inlPos = r.inlPos(origPos)
+ return
+}
+
func (r *reader) pos0() src.Pos {
r.Sync(pkgbits.SyncPos)
if !r.Bool() {
return typecheck.Callee(r.obj())
case exprFuncInst:
- pos := r.pos()
+ origPos, pos := r.origPos()
wrapperFn, baseFn, dictPtr := r.funcInst(pos)
if wrapperFn != nil {
return wrapperFn
}
- return r.curry(pos, false, baseFn, dictPtr, nil)
+ return r.curry(origPos, false, baseFn, dictPtr, nil)
case exprConst:
pos := r.pos()
case exprMethodVal:
recv := r.expr()
- pos := r.pos()
+ origPos, pos := r.origPos()
wrapperFn, baseFn, dictPtr := r.methodExpr()
// For simple wrapperFn values, the existing machinery for creating
// For more complicated method expressions, we construct a
// function literal wrapper.
- return r.curry(pos, true, baseFn, recv, dictPtr)
+ return r.curry(origPos, true, baseFn, recv, dictPtr)
case exprMethodExpr:
recv := r.typ()
addr = true
}
- pos := r.pos()
+ origPos, pos := r.origPos()
wrapperFn, baseFn, dictPtr := r.methodExpr()
// If we already have a wrapper and don't need to do anything with
return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), method.Sel)).(*ir.SelectorExpr)
}
- return r.methodExprWrap(pos, recv, implicits, deref, addr, baseFn, dictPtr)
+ return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr)
case exprIndex:
x := r.expr()
// If nilCheck is true and arg0 is an interface value, then it's
// checked to be non-nil as an initial step at the point of evaluating
// the function literal itself.
-func (r *reader) curry(pos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
+func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
var captured ir.Nodes
captured.Append(fun, arg0)
if arg1 != nil {
r.syntheticTailCall(pos, fun, args)
}
- return r.syntheticClosure(pos, typ, ifaceHack, captured, addBody)
+ return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
}
// methodExprWrap returns a function literal that changes method's
// first parameter's type to recv, and uses implicits/deref/addr to
// select the appropriate receiver parameter to pass to method.
-func (r *reader) methodExprWrap(pos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
+func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
var captured ir.Nodes
captured.Append(method)
r.syntheticTailCall(pos, fn, args)
}
- return r.syntheticClosure(pos, typ, false, captured, addBody)
+ return r.syntheticClosure(origPos, typ, false, captured, addBody)
}
// syntheticClosure constructs a synthetic function literal for
-// currying dictionary arguments. pos is the position used for the
-// closure. typ is the function literal's signature type.
+// currying dictionary arguments. origPos is the position used for the
+// closure, which must be a non-inlined position. typ is the function
+// literal's signature type.
//
// captures is a list of expressions that need to be evaluated at the
// point of function literal evaluation and captured by the function
// list of captured values passed back has the captured variables for
// use within the function literal, corresponding to the expressions
// in captures.
-func (r *reader) syntheticClosure(pos src.XPos, typ *types.Type, ifaceHack bool, captures ir.Nodes, addBody func(pos src.XPos, r *reader, captured []ir.Node)) ir.Node {
+func (r *reader) syntheticClosure(origPos src.XPos, typ *types.Type, ifaceHack bool, captures ir.Nodes, addBody func(pos src.XPos, r *reader, captured []ir.Node)) ir.Node {
// isSafe reports whether n is an expression that we can safely
// defer to evaluating inside the closure instead, to avoid storing
// them into the closure.
return false
}
- fn := ir.NewClosureFunc(pos, r.curfn != nil)
+ // The ODCLFUNC and its body need to use the original position, but
+ // the OCLOSURE node and any Init statements should use the inlined
+ // position instead. See also the explanation in reader.funcLit.
+ inlPos := r.inlPos(origPos)
+
+ fn := ir.NewClosureFunc(origPos, r.curfn != nil)
fn.SetWrapper(true)
clo := fn.OClosure
+ clo.SetPos(inlPos)
ir.NameClosure(clo, r.curfn)
setType(fn.Nname, typ)
continue // skip capture; can reference directly
}
- tmp := r.tempCopy(pos, n, &init)
- ir.NewClosureVar(pos, fn, tmp)
+ tmp := r.tempCopy(inlPos, n, &init)
+ ir.NewClosureVar(origPos, fn, tmp)
// We need to nil check interface receivers at the point of method
// value evaluation, ugh.
if ifaceHack && i == 1 && n.Type().IsInterface() {
- check := ir.NewUnaryExpr(pos, ir.OCHECKNIL, ir.NewUnaryExpr(pos, ir.OITAB, tmp))
+ check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
init.Append(typecheck.Stmt(check))
}
}
}
assert(next == len(r.closureVars))
- addBody(pos, r, captured)
+ addBody(origPos, r, captured)
}}
bodyReader[fn] = pri
pri.funcBody(fn)