Skip to content

Commit 8df8549

Browse files
ArquintLclaude
andcommitted
Encodes the length of a pointer to an array as the array type's length
In Go, the length of a pointer to an array is the length constant of the array type; this holds even for a nil pointer. Previously, the length was encoded by dereferencing the pointer, which made it unprovable for pointers that are not known to be non-nil. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c6691f0 commit 8df8549

2 files changed

Lines changed: 13 additions & 6 deletions

File tree

src/main/scala/viper/gobra/translator/encodings/arrays/ArrayEncoding.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import viper.gobra.translator.context.Context
1818
import viper.gobra.translator.library.embeddings.EmbeddingParameter
1919
import viper.gobra.translator.util.FunctionGenerator
2020
import viper.gobra.translator.util.ViperUtil.synthesized
21-
import viper.gobra.translator.util.ViperWriter.CodeWriter
21+
import viper.gobra.translator.util.ViperWriter.{CodeLevel, CodeWriter}
2222
import viper.gobra.util.Violation
2323
import viper.silver.plugin.standard.termination
2424
import viper.silver.{ast => vpr}
@@ -181,11 +181,11 @@ class ArrayEncoding extends TypeEncoding with SharedArrayEmbedding {
181181
case Shared => ctx.reference(e.asInstanceOf[in.Location]).map(sh.length(_, cptParam(len, t)(ctx))(n)(ctx))
182182
}
183183

184-
case in.Length(exp :: ctx.*(t: in.ArrayT)) =>
185-
val expInfo = exp.info
186-
val derefExp = in.Deref(exp, in.PointerT(t, t.addressability))(expInfo)
187-
val newLenExpr = in.Length(derefExp)(expInfo)
188-
expression(ctx)(newLenExpr)
184+
case n@in.Length(_ :: ctx.*(t: in.ArrayT)) =>
185+
// In Go, the length of a pointer to an array is the array type's length; this holds even
186+
// for a nil pointer and, thus, neither requires a dereference nor a nil check:
187+
val (pos, info, errT) = n.vprMeta
188+
CodeLevel.unit(vpr.IntLit(t.length)(pos, info, errT))
189189

190190
case n@in.Capacity(e :: ctx.Array(len, t) / m) =>
191191
m match {

src/test/resources/regressions/issues/000491-4.gobra

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,10 @@ func quantifierWithAddrTriggerInCode(s []byte) {
186186
func lengthOfNestedArray(a *[4][8]byte, idx int) int {
187187
return len(a[idx])
188188
}
189+
190+
// The length of a *[N]byte is the constant N; in Go, this holds even for a nil
191+
// pointer and, thus, must not generate a nil-ness proof obligation.
192+
func lenOfNilArrayPointer() {
193+
var p *[8]byte = nil
194+
assert len(p) == 8
195+
}

0 commit comments

Comments
 (0)