MCPcopy
hub / github.com/uber-go/nilaway / nilnessOf

Method nilnessOf

assertion/function/functioncontracts/infer.go:367–449  ·  view source on GitHub ↗

nilnessOf reports whether v is definitely nil, definitely not nil, or unknown given the nilness table. Adapted from org_golang_x_tools/go/analysis/passes/nilness/nilness.go

(v ssa.Value)

Source from the content-addressed store, hash-verified

365// table.
366// Adapted from org_golang_x_tools/go/analysis/passes/nilness/nilness.go
367func (t nilnessTable) nilnessOf(v ssa.Value) nilness {
368 switch v := v.(type) {
369 // unwrap ChangeInterface and Slice values recursively, to detect if underlying values have any
370 // facts recorded or are otherwise known with regard to nilness.
371 //
372 // This work must be in addition to expanding facts about ChangeInterfaces during
373 // inference/fact gathering because this covers cases where the nilness of a value is
374 // intrinsic, rather than based on inferred facts, such as a zero value interface variable.
375 // That said, this work alone would only inform us when facts are about underlying values,
376 // rather than outer values, when the analysis is transitive in both directions.
377 case *ssa.ChangeInterface:
378 if underlying := t.nilnessOf(v.X); underlying != unknown {
379 return underlying
380 }
381 case *ssa.MakeInterface:
382 if underlying := t.nilnessOf(v.X); underlying != unknown {
383 return underlying
384 }
385 case *ssa.Slice:
386 if underlying := t.nilnessOf(v.X); underlying != unknown {
387 return underlying
388 }
389 case *ssa.SliceToArrayPointer:
390 nn := t.nilnessOf(v.X)
391 // Get the length of underlying array pointer of slice
392 if v.Type().(*types.Pointer).Elem().Underlying().(*types.Array).Len() > 0 {
393 if nn == isnil {
394 // We know that *(*[1]byte)(nil) is going to panic because of the conversion. So
395 // return unknown to the caller, prevent useless nil deference reporting due to *
396 // operator.
397 return unknown
398 }
399 // Otherwise, the conversion will yield a non-nil pointer to array. Note that the
400 // instruction can still panic if array length greater than slice length. If the value
401 // is used by another instruction, that instruction can assume the panic did not happen
402 // when that instruction is reached.
403 return isnonnil
404 }
405 // In case array length is zero, the conversion result depends on nilness of the slice.
406 if nn != unknown {
407 return nn
408 }
409 case *ssa.Call:
410 if !isBuiltinAppendCall(v) {
411 break
412 }
413 // append(s, x) always returns a nonnil.
414 if len(v.Call.Args) > 1 {
415 return isnonnil
416 }
417 // append(s) depends on the nilability of s.
418 return t.nilnessOf(v.Call.Args[0])
419 }
420
421 // Is value intrinsically nil or non-nil?
422 switch v := v.(type) {
423 case *ssa.Alloc,
424 *ssa.FieldAddr,

Callers 3

inferContractsFunction · 0.80
learnNilnessFunction · 0.80
deriveContractsFunction · 0.80

Calls 3

isBuiltinAppendCallFunction · 0.85
IsNilMethod · 0.80
LenMethod · 0.45

Tested by

no test coverage detected