[5.5] New CastChecked Test/Shipping behavior

Our project is currently updating to UE 5.5, and we have experienced an unexpected behavior change to CastChecked (Casts.h)

template <typename To, typename From> FUNCTION_NON_NULL_RETURN_START FORCEINLINE To* CastChecked(From* Src) FUNCTION_NON_NULL_RETURN_END { static_assert(sizeof(From) > 0 && sizeof(To) > 0, "Attempting to cast between incomplete types"); // This code is removed if (!Src) { return nullptr; }Since the below code ignores the optional argument CheckType, this has the effect of causing a consitent crash when passing nullptr to the CastChecked function, even when ECastCheckedType::NullAllowed is sent.

The behavior is different in the DO_CHECK version above, which correctly allows nullptr

`template <typename To, typename From>
To* CastChecked(From* Src, ECastCheckedType::Type CheckType)
{
static_assert(sizeof(From) > 0 && sizeof(To) > 0, “Attempting to cast between incomplete types”);

if (Src)
{
To* Result = Cast(Src);
if (!Result)
{
CastLogError(*GetFullNameForCastLogError(Src), *GetTypeName());
}

return Result;
}

if (CheckType == ECastCheckedType::NullChecked)
{
CastLogError(TEXT(“nullptr”), *GetTypeName());
}

return nullptr;
}We plan to change this code in our project to allow sending nulls when NullAllowed` is passed, but wanted to verify that the behavior change is intended, and that it is intended to be different between builds that have checks enabled and builds that do not (usually, Test/Shipping)

Steps to Reproduce
MyClass* Object = CastChecked<MyClass>(nullptr, ECastCheckedType::NullAllowed);crashes in builds without `DO_CHECK`

Hi Kyle,

After taking a look at the related code, I don’t believe that this change is intended. It is more likely an oversight from CLs 35133078 and 35245469. The pair of macros FUNCTION_NON_NULL_RETURN_START/END annotate a function as never returning nullptr, so the change made by those CLs is actually correct, but I believe the code

if (!Src) { return nullptr; }should have been moved to the version of CastChecked() that takes ECastCheckedType::Type CheckType as a parameter, since nullptr is indeed a valid return for it.

I am filing an internal bug report now about this issue. I’ll get back to you with a tracking number once I have one, so you’ll be able to make sure that it eventually gets marked as “fixed” and not “by design”.

Best regards,

Vitor

Hi Kyle,

Sorry about the delay, here’s the bug tracker link: UE-297173. It should become available once the devs mark it as public.

Best regards,

Vitor

Thank you Vitor! We put in a patch fix in our code which checked for that specific enum value, good to know it was not intended.

note - for the crash, the null pointer was a UObject* and the To class was an interface. It looks like an interface should be involved either From or To to reproduce the crash.