Repository navigation
[NFC] Rename Type::is{,Non}NullableRef - #9286
Conversation
Rename Type::isNullable and Type::isNonNullable to Type::isNullableRef and Type::isNonNullableRef to make it clear that they already check that the type is a reference, and remove redundant isRef() checks at call sites.
There was a problem hiding this comment.
Code Review
This pull request renames isNullable() to isNullableRef() and isNonNullable() to isNonNullableRef() across the codebase to clarify that these methods check reference types. Two critical issues were identified in the review: first, a logical contradiction in DeadArgumentElimination.cpp where a return type is checked for being both null and non-nullable, which always evaluates to false; second, an unsafe call to getHeapType() in wasm-validator.cpp that could cause a crash on invalid modules if the type is not first verified to be a reference type.
| bool wasReturnUninhabitable = | ||
| func->getResults().isNull() && func->getResults().isNonNullable(); | ||
| func->getResults().isNull() && func->getResults().isNonNullableRef(); |
There was a problem hiding this comment.
There is a logical contradiction in this check. func->getResults().isNull() checks if the type is the null type (which is a nullable reference type), while func->getResults().isNonNullableRef() checks if it is non-nullable. A type cannot be both null and non-nullable, so wasReturnUninhabitable will always evaluate to false. Based on the comment, you likely want to check if the return type is a non-nullable reference.
| bool wasReturnUninhabitable = | |
| func->getResults().isNull() && func->getResults().isNonNullable(); | |
| func->getResults().isNull() && func->getResults().isNonNullableRef(); | |
| bool wasReturnUninhabitable = | |
| func->getResults().isNonNullableRef(); |
There was a problem hiding this comment.
This is not correct, but also points to a good renaming we could do. I'll also rename "isNull" to "isBottomRef".
|
|
||
| if (!shouldBeTrue(curr->type.isRef() && | ||
| curr->type.getHeapType().isContinuation(), | ||
| if (!shouldBeTrue(curr->type.getHeapType().isContinuation(), |
There was a problem hiding this comment.
Calling curr->type.getHeapType() directly is unsafe here because curr->type is not guaranteed to be a reference type if the module being validated is invalid (e.g., if it is annotated with a basic type like i32). This will cause an assertion failure or crash in getHeapType(). You should restore the curr->type.isRef() check to ensure short-circuiting protects the getHeapType() call.
| if (!shouldBeTrue(curr->type.getHeapType().isContinuation(), | |
| if (!shouldBeTrue(curr->type.isRef() && | |
| curr->type.getHeapType().isContinuation(), |
There was a problem hiding this comment.
Looks like a false positive since we'll early return if it's not a ref
|
Isn't |
|
Since it's a negative, it's arguably ambiguous whether |
| // if it is null. | ||
| void notePossibleTrap(Expression* expr) { | ||
| if (!expr->type.isRef() || expr->type.isNonNullable()) { | ||
| if (!expr->type.isNullableRef()) { |
There was a problem hiding this comment.
This looks equivalent to !isRef || !isNullable while the original code is !isRef || isNonNullable. Is !isNullable the same as isNonNullable? I guess this is only in the case when isRef so yes?
There was a problem hiding this comment.
Yeah, I think this should be good.
Non-refs: take the branch before and after.
nullable refs: do not take the branch before and after.
non-nullable refs: take the branch before and after.
|
@tlively I suppose that is arguable... but have you ever read "this is a non-nullable type" and thought "well that might be an i32"..? 🤔 |
|
I've been uncertain about this in the past. And Gemini Code Assist was certainly confused about it here: #9282 (comment). |
|
@stevenfontanella that code you linked to could be shortened, but it would need to be reordered (so it is safe to call getHeapType) - maybe that is the reason it is more verbose? Anyhow, we can fix such code paths. @tlively If this is an AI issue, can we fix it with docs for the AI? If it is really an issue for you, I'd like to understand this better. I think using longer, excessively-verbose names makes the code harder to read and less fun, as I wrote in the other PR. But I'll change my mind if we have a nice and short option to switch to, or if there is a real (non-AI) problem of understanding here. |
|
|
|
I can live with |
|
There were lots of redundant code paths, and I think that points to a real problem with the existing names. Both authors and reviewers are currently missing the redundancy.
|
|
Just to add my 2 cents to the bikeshed, I would prefer |
I agree FWIW |
|
Ok, fair enough, I don't disagree that strongly. sgtm |
Rename Type::isNullable and Type::isNonNullable to Type::isNullableRef and Type::isNonNullableRef to make it clear that they already check that the type is a reference, and remove redundant isRef() checks at call sites.