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)
| 365 | // table. |
| 366 | // Adapted from org_golang_x_tools/go/analysis/passes/nilness/nilness.go |
| 367 | func (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, |
no test coverage detected