Skip to content

api(deepdata): change merge_deep_pixels return type, add OIIO_NODISCARD_ERROR#5253

Open
luna-y-kim wants to merge 1 commit into
AcademySoftwareFoundation:mainfrom
luna-y-kim:nodiscard-deepdata-h
Open

api(deepdata): change merge_deep_pixels return type, add OIIO_NODISCARD_ERROR#5253
luna-y-kim wants to merge 1 commit into
AcademySoftwareFoundation:mainfrom
luna-y-kim:nodiscard-deepdata-h

Conversation

@luna-y-kim

@luna-y-kim luna-y-kim commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

merge_deep_pixels() calls copy_deep_sample(), which has an error status return, so change merge_deep_pixels()'s return type from void to bool.

For OIIO_NODISCARD_ERROR, all internal calls that previously ignored return values are handled:

  • OIIO_CONTRACT_ASSERT where the call can't fail in context, or the caller is a void function or a constructor.
  • return false where the caller already returns a bool error state.
  • (void) cast for the deprecated internal overload.

Follow-up to #5252
Part of #4781

Tests

N/A

Checklist:

  • I have read the guidelines on contributions and code review procedures.
  • I have read the Policy on AI Coding Assistants
    and if I used AI coding assistants, I have an Assisted-by: TOOL / MODEL
    line in the pull request description above.
  • (N/A) I have updated the documentation if my PR adds features or changes
    behavior.
  • (N/A) I am sure that this PR's changes are tested in the testsuite.
  • I have run and passed the testsuite in CI before submitting the
    PR, by pushing the changes to my fork and seeing that the automated CI
    passed there. (Exceptions: If most tests pass and you can't figure out why
    the remaining ones fail, it's ok to submit the PR and ask for help. Or if
    any failures seem entirely unrelated to your change; sometimes things break
    on the GitHub runners.)
  • My code follows the prevailing code style of this project and I
    fixed any problems reported by the clang-format CI test.
  • If I added or modified a public C++ API call, I have also amended the
    corresponding Python bindings. If altering ImageBufAlgo functions, I also
    exposed the new functionality as oiiotool options.

insert_samples(pixel, s + 1);
copy_deep_sample(pixel, s + 1, *this, pixel, s);
bool ok = copy_deep_sample(pixel, s + 1, *this, pixel, s);
OIIO_CONTRACT_ASSERT(ok);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like OIIO_CONTRACT_ASSERT is the right choice for those DeepData::DeepData constructors, since not much can go wrong and they can't return an error anyway.

But in this case, DD::split() does return a bool, so maybe if copy_deep_sample fails, just return false here instead of asserting?

And similar to the other assertions inside functions that return an error status bool.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept going in circles, and I keep coming back to return false not quite fitting here. (I might be overthinking it.) I'd like to hear your thoughts about this.

DD::split()'s docs say it returns "true if any splits occurred, false if the pixel was not modified." So false is a normal "nothing to split" result, not an error, which is also why I couldn't put OIIO_NODISCARD_ERROR on it.

And by the time DD::copy_deep_sample() is called, we're mid-loop with the pixel already partially modified (even for the first round because DD::insert_samples() ran just before, which bumps up m_nsamples[pixel]). Having return false there would go against the documented behavior.

Also, the false branch in DD::copy_deep_sample() is unreachable at this point anyways (src is *this, so the number of channels is equal, and the zf/zb guard already rules out a null data pointer).

p.s. I thought about the idea of flipping split() to return a real success/failure bool, but that would change behavior for the caller that relies on "true = a split occurred", so it seems too risky.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, you are right, this is a tricky case.

It's not an error status, since asking it to split any samples that span the z value might have had a sample that needs to be split, but might not, and neither of those is an error.

But also, it's not the kind of "pure function" result (like the return value from sin(x), or the "essential" return of ImageInput::create()) where the only conceivable reason to call the function is for the return value, so it surely indicates an error if you don't use that result.

For DD::split(), the primary rationale is that you want the sample, if it exists, to be split. The return value provides the secondary service of telling you whether it needed to split anything or not, but it's easy to imagine that some callers don't need to know, they just want to ensure that no samples span that z value.

So I say: this function should have NEITHER annotation. It's actually OKAY to ignore the return value, and that does not indicate any bug or mis-programming.

int dstpixel = dst.pixelindex(x, y, z, true);
dstdd.copy_deep_pixel(dstpixel, srcdd, srcpixel);
bool ok = dstdd.copy_deep_pixel(dstpixel, srcdd, srcpixel);
OIIO_CONTRACT_ASSERT(ok);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here, too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one makes sense. I'll update it!

@luna-y-kim

Copy link
Copy Markdown
Contributor Author

Separately (slightly off topic): DD::merge_deep_pixels() returns void, but its doc comment says it returns a bool error state. Which was intended (void or bool)?

@luna-y-kim luna-y-kim force-pushed the nodiscard-deepdata-h branch 2 times, most recently from 5de6de0 to ccc9436 Compare June 28, 2026 00:42
@luna-y-kim

Copy link
Copy Markdown
Contributor Author

I forgot to rebase, so I re-pushed. Sorry for the noise.

@lgritz

lgritz commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Separately (slightly off topic): DD::merge_deep_pixels() returns void, but its doc comment says it returns a bool error state. Which was intended (void or bool)?

Good catch!

It calls copy_deep_sample, which does have an error status return, so I think we should change the new merge_deep_pixels() to to return bool and bubble that up.

In this one case it is safe to change the return value, only because we already added the new function signature, and it's only in main, and has not been backported to any release branches. So we lucked out again, and we are free for you to make this change. It would not be able to get backported (at least not separately from #5252), since C++ can't overload based on return type alone.

Would you mind quickly making that change as part of this PR, and we can merge and make it right? Thanks.

@luna-y-kim

Copy link
Copy Markdown
Contributor Author

On it! I'll push shortly.

…CARD_ERROR

`merge_deep_pixels()` calls `copy_deep_sample()`, which has an error
status return, so change `merge_deep_pixels()`'s return type from void
to bool.

For OIIO_NODISCARD_ERROR, all internal calls that previously ignored
return values are handled:
 - OIIO_CONTRACT_ASSERT where the call can't fail in context, or the
   caller is a void function or a constructor.
 - `return false` where the caller already returns a bool error state.
 - `(void)` cast for the deprecated internal overload.

Follow-up to AcademySoftwareFoundation#5252
Part of AcademySoftwareFoundation#4781

Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
@luna-y-kim luna-y-kim force-pushed the nodiscard-deepdata-h branch from ccc9436 to b98ef56 Compare June 29, 2026 19:55
@luna-y-kim luna-y-kim changed the title api(deepdata.h): add OIIO_NODISCARD_ERROR api(deepdata): change merge_deep_pixels return type, add OIIO_NODISCARD_ERROR Jun 29, 2026
@luna-y-kim

luna-y-kim commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

I couldn't get make pystubs to run locally, and the CI stub check is disabled, so I left it as is for now. Would that be ok?

(src/python/stubs/OpenImageIO/__init__.pyi:266)

def merge_deep_pixels(self, pixel: typing.SupportsInt, src: DeepData, srcpixel: typing.SupportsInt) -> None: ...

@lgritz

lgritz commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Yeah, that's ok. Lots of us have trouble running it locally. Sometimes the change is obvious how we do it by hand, and other times, we just let it fail and regenerate in CI, and then the download artifact from that CI run has the new version of the file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants