diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 1ca5552879e..957295bdf09 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -30,7 +30,6 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node { } switch { case tv.IsBuiltin(): - // TODO(mdempsky): Handle in CallExpr? return g.use(expr.(*syntax.Name)) case tv.IsType(): return ir.TypeNode(g.typ(tv.Type)) @@ -82,8 +81,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { if _, isNil := g.info.Uses[expr].(*types2.Nil); isNil { return Nil(pos, g.typ(typ)) } - // TODO(mdempsky): Remove dependency on typecheck.Expr. - return typecheck.Expr(g.use(expr)) + return g.use(expr) case *syntax.CompositeLit: return g.compLit(typ, expr) @@ -157,8 +155,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { // Qualified identifier. if name, ok := expr.X.(*syntax.Name); ok { if _, ok := g.info.Uses[name].(*types2.PkgName); ok { - // TODO(mdempsky): Remove dependency on typecheck.Expr. - return typecheck.Expr(g.use(expr.Sel)) + return g.use(expr.Sel) } } return g.selectorExpr(pos, typ, expr) diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index b4e5c022dbf..6c8ed4af972 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -22,16 +22,26 @@ func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) { return g.obj(obj), obj } +// use returns the Name node associated with the use of name. The returned node +// will have the correct type and be marked as typechecked. func (g *irgen) use(name *syntax.Name) *ir.Name { - obj, ok := g.info.Uses[name] + obj2, ok := g.info.Uses[name] if !ok { base.FatalfAt(g.pos(name), "unknown name %v", name) } - return ir.CaptureName(g.pos(obj), ir.CurFunc, g.obj(obj)) + obj := ir.CaptureName(g.pos(obj2), ir.CurFunc, g.obj(obj2)) + if obj.Defn != nil && obj.Defn.Op() == ir.ONAME { + // If CaptureName created a closure variable, then transfer the + // type of the captured name to the new closure variable. + obj.SetTypecheck(1) + obj.SetType(obj.Defn.Type()) + } + return obj } -// obj returns the Name that represents the given object. If no such -// Name exists yet, it will be implicitly created. +// obj returns the Name that represents the given object. If no such Name exists +// yet, it will be implicitly created. The returned node will have the correct +// type and be marked as typechecked. // // For objects declared at function scope, ir.CurFunc must already be // set to the respective function when the Name is created. @@ -45,6 +55,7 @@ func (g *irgen) obj(obj types2.Object) *ir.Name { } n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) if n, ok := n.(*ir.Name); ok { + n.SetTypecheck(1) return n } base.FatalfAt(g.pos(obj), "failed to resolve %v", obj) @@ -117,6 +128,7 @@ func (g *irgen) obj(obj types2.Object) *ir.Name { } g.objs[obj] = name + name.SetTypecheck(1) return name }