Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hook/error_return.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,14 @@ var _errorReturnNonnilArgs = map[trustedSig]struct {
enclosingRegex: regexp.MustCompile(`^encoding/(json|xml)$`),
nameRegex: regexp.MustCompile(`^Unmarshal$`),
}: {action: pointeeOfArg, argIndex: 1},

// `(cadence).Future.Get(ctx, &v)` blocks until the future is ready and, on success (a nil error
// return), populates the value pointed to by `&v`, so a nil error return implies `v != nil`. The
// `Future` interface lives in `go.uber.org/cadence/internal` and is re-exported (via a type alias)
// as `go.uber.org/cadence/workflow.Future`, so the method's declaring package is the internal one.
{
kind: _method,
enclosingRegex: regexp.MustCompile(`^(stubs/)?go\.uber\.org/cadence/internal\.Future$`),
nameRegex: regexp.MustCompile(`^Get$`),
}: {action: pointeeOfArg, argIndex: 1},
}
38 changes: 38 additions & 0 deletions testdata/src/go.uber.org/trustedfunc/inference/cadence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package inference

import "stubs/go.uber.org/cadence/workflow"

// testCadenceFutureGet exercises the `ErrorReturnNonnilArg` hook for cadence's `Future.Get`:
// `f.Get(ctx, &v)` populates `v`, so the pointee is treated as non-nil once the error return is
// checked to be nil.
func testCadenceFutureGet(ctx workflow.Context, f workflow.Future) {
// `err != nil` early return: pointee is non-nil on the fallthrough (error-is-nil) path.
var v1 *int
if err := f.Get(ctx, &v1); err != nil {
return
}
print(*v1) // safe

// `err == nil` positive check: pointee is non-nil inside the block.
var v2 *int
err := f.Get(ctx, &v2)
if err == nil {
print(*v2) // safe
}

// Error return not checked at all: no guarantee.
var v3 *int
f.Get(ctx, &v3)
print(*v3) //want "unassigned variable `v3` dereferenced"

// Error return discarded into the blank identifier: no guarantee.
var v4 *int
_ = f.Get(ctx, &v4)
print(*v4) //want "unassigned variable `v4` dereferenced"

// Dereference on the error path (`err != nil`): pointee is not guarded here.
var v5 *int
if err := f.Get(ctx, &v5); err != nil {
print(*v5) //want "unassigned variable `v5` dereferenced"
}
}
30 changes: 30 additions & 0 deletions testdata/src/stubs/go.uber.org/cadence/internal/internal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2026 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package internal is a minimal stub of `go.uber.org/cadence/internal`, which is where the `Future`
// interface (re-exported as `go.uber.org/cadence/workflow.Future`) is actually declared.
package internal

// Context is a minimal stub of cadence's workflow context.
type Context interface {
Value(key interface{}) interface{}
}

// Future is a minimal stub of cadence's `Future` interface. Its `Get` method blocks until the
// future is ready and, on success (a nil error return), populates the value pointed to by
// `valuePtr` (passed by address as `&v`).
type Future interface {
Get(ctx Context, valuePtr interface{}) error
IsReady() bool
}
26 changes: 26 additions & 0 deletions testdata/src/stubs/go.uber.org/cadence/workflow/workflow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2026 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package workflow is a minimal stub of `go.uber.org/cadence/workflow`. Like the real package, it
// re-exports the `Future` and `Context` types from the internal package via type aliases, so a call
// to `f.Get(ctx, &v)` resolves to the method declared in `go.uber.org/cadence/internal`.
package workflow

import "stubs/go.uber.org/cadence/internal"

// Context aliases internal.Context, mirroring the real cadence package.
type Context = internal.Context

// Future aliases internal.Future, mirroring the real cadence package.
type Future = internal.Future
Loading