This reverts CL 520395.
Reason for revert: thanm@ pointed out failure cases.
Change-Id: I3fd60b73118be3652be2c08b77ab39e793b42110
Reviewed-on: https://go-review.googlesource.com/c/go/+/520596
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
// If the result of a string->[]byte conversion is never mutated,
// then it can simply reuse the string's memory directly.
- if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OSTR2BYTES && !loc.hasAttr(attrMutates) {
- if base.Flag.LowerM >= 1 {
- base.WarnfAt(n.Pos(), "zero-copy string->[]byte conversion")
+ //
+ // TODO(mdempsky): Enable in a subsequent CL. We need to ensure
+ // []byte("") evaluates to []byte{}, not []byte(nil).
+ if false {
+ if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OSTR2BYTES && !loc.hasAttr(attrMutates) {
+ if base.Flag.LowerM >= 1 {
+ base.WarnfAt(n.Pos(), "zero-copy string->[]byte conversion")
+ }
+ n.SetOp(ir.OSTR2BYTESTMP)
}
- n.SetOp(ir.OSTR2BYTESTMP)
}
}
}
n := n.(*ir.ConvExpr)
str := s.expr(n.X)
ptr := s.newValue1(ssa.OpStringPtr, s.f.Config.Types.BytePtr, str)
- if !n.NonNil() {
- // We need to ensure []byte("") evaluates to []byte{}, and not []byte(nil).
- //
- // TODO(mdempsky): Investigate using "len != 0" instead of "ptr != nil".
- cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], ptr, s.constNil(ptr.Type))
- zerobase := s.newValue1A(ssa.OpAddr, ptr.Type, ir.Syms.Zerobase, s.sb)
- ptr = s.ternary(cond, ptr, zerobase)
- }
len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], str)
return s.newValue3(ssa.OpSliceMake, n.Type(), ptr, len, len)
case ir.OCFUNC:
// Mark []byte(str) range expression to reuse string backing storage.
// It is safe because the storage cannot be mutated.
n := n.(*ir.RangeStmt)
- if x, ok := n.X.(*ir.ConvExpr); ok {
- switch x.Op() {
- case ir.OSTR2BYTES:
- x.SetOp(ir.OSTR2BYTESTMP)
- fallthrough
- case ir.OSTR2BYTESTMP:
- x.MarkNonNil() // "range []byte(nil)" is fine
- }
+ if n.X.Op() == ir.OSTR2BYTES {
+ n.X.(*ir.ConvExpr).SetOp(ir.OSTR2BYTESTMP)
}
t := o.markTemp()
// Convert expr to a []int8
slice := ir.NewConvExpr(base.Pos, ir.OSTR2BYTESTMP, types.NewSlice(types.Types[types.TINT8]), expr)
slice.SetTypecheck(1) // legacy typechecker doesn't handle this op
- slice.MarkNonNil()
// Load the byte we're splitting on.
load := ir.NewIndexExpr(base.Pos, slice, ir.NewInt(base.Pos, int64(bestIdx)))
// Compare with the value we're splitting on.
func stringtoslicebyte0() {
s := "foo"
- x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$" "zero-copy string->\[\]byte conversion"
+ x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$"
_ = x
}
func stringtoslicebyte0() {
s := "foo"
- x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$" "zero-copy string->\[\]byte conversion"
+ x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$"
_ = x
}