diff options
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/codes.go | 1 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 37 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 15 |
3 files changed, 52 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go index fb4fb4a886..c1ee8d15c5 100644 --- a/src/cmd/compile/internal/noder/codes.go +++ b/src/cmd/compile/internal/noder/codes.go @@ -58,6 +58,7 @@ const ( exprNil exprFuncInst exprRecv + exprReshape ) type codeAssign int diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 5f770166db..cf1e1440df 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -89,7 +89,7 @@ func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pk } } -// A writer provides APIs for reading an individual element. +// A reader provides APIs for reading an individual element. type reader struct { pkgbits.Decoder @@ -2367,6 +2367,41 @@ func (r *reader) expr() (res ir.Node) { typ := r.exprType() return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ)) + case exprReshape: + typ := r.typ() + x := r.expr() + + if types.IdenticalStrict(x.Type(), typ) { + return x + } + + // Comparison expressions are constructed as "untyped bool" still. + // + // TODO(mdempsky): It should be safe to reshape them here too, but + // maybe it's better to construct them with the proper type + // instead. + if x.Type() == types.UntypedBool && typ.IsBoolean() { + return x + } + + base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ) + base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ) + + // We use ir.HasUniquePos here as a check that x only appears once + // in the AST, so it's okay for us to call SetType without + // breaking any other uses of it. + // + // Notably, any ONAMEs should already have the exactly right shape + // type and been caught by types.IdenticalStrict above. + base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x) + + if base.Debug.Reshape != 0 { + base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ) + } + + x.SetType(typ) + return x + case exprConvert: implicit := r.Bool() typ := r.typ() diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index c2c3567220..75ff000249 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1629,6 +1629,16 @@ func (w *writer) expr(expr syntax.Expr) { w.typ(tv.Type) return } + + // With shape types (and particular pointer shaping), we may have + // an expression of type "go.shape.*uint8", but need to reshape it + // to another shape-identical type to allow use in field + // selection, indexing, etc. + if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) { + w.Code(exprReshape) + w.typ(typ) + // fallthrough + } } if obj != nil { @@ -2199,6 +2209,11 @@ func isUntyped(typ types2.Type) bool { return ok && basic.Info()&types2.IsUntyped != 0 } +func isTuple(typ types2.Type) bool { + _, ok := typ.(*types2.Tuple) + return ok +} + func (w *writer) itab(typ, iface types2.Type) { typ = types2.Default(typ) iface = types2.Default(iface) |
