You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Shapes::keyExists should refine optional shape fields #8012
3.22.0 with enable_experimental_tc_features = optional_shape_field
Standalone code, or other way to reproduce the problem
<?hh //strict
function myfunc(shape(?'optional' => mixed) $var): void {
if (Shapes::keyExists($var, 'optional')) {
print $var['optional'];
} else {
print 'optional field does not exist';
}
}
Expected result
hh_client - no errors!
Actual result
Invalid index operation: 'optional' is marked as an optional shape field. It may not be present in the shape. Use Shapes::idx instead. (Typing[4165])
As it is, dealing with optional fields would require at least 1 Shapes::keyExists and 1 Shapes::idx. This is really really verbose.
Even better solution
Allow the php error control operator (@) to suppress type errors in addition to runtime errors. This has the additional advantage of allowing me to null coalesce optional fields.
We plan on making changes to Hack that will better define when and how type refinement will be performed. We hadn't considered this case, but we will take this use case in mind for the change. I rather focus our attention on the future, especially since we hope to get the feature out within the next 3-6 months.
If there was a pull request that made the change I would consider merging it, but not something anyone on the team will work on at the moment.
For some reason, this doesn't work with invariant. Is this expected?
<?hh //strict
function myfunc(shape(?'optional' => string) $var): void {
\invariant(Shapes::keyExists($var, 'optional'), '');
// Invalid index operation: 'optional' is marked as an optional shape field....print$var['optional'];
}
function myfunc2(shape(?'optional' => string) $var): void {
if (!Shapes::keyExists($var, 'optional')) thrownewException();
// OKprint$var['optional'];
}
hh_client
Invalid index operation: 'optional' is marked as an optional shape field. It may not be present in the shape. Use the `??` operator instead. (Typing[4165])
hhvm --version
HipHop VM 3.27.1 (rel)
Compiler: 1532025848_857759529
Repo schema: 6f2a65dfa3a360d8c159fe76a8bee0e26ba4e45a
This might be asking too much of the type checker but it would be nice if this worked on more than 1 level.
<?hh //strict
function myfunc(shape(?'optional' => shape(?'optional' => string)) $var): void {
if (!Shapes::keyExists($var, 'optional')) thrownewException();
if (!Shapes::keyExists($var['optional'], 'optional')) thrownewException();
// Invalid index operation: 'optional' is marked as an optional shape field....print$var['optional']['optional'];
}
Activity
fredemmott commentedon Sep 29, 2017
The PHP error control operator is not part of hack, and we don't plan on adding it. See https://docs.hhvm.com/hack/typechecker/special for ways to suppress this.
michaeltingley commentedon Sep 29, 2017
Seems like a reasonable request, I'll see what we can do.
dlreeves commentedon Oct 4, 2017
We plan on making changes to Hack that will better define when and how type refinement will be performed. We hadn't considered this case, but we will take this use case in mind for the change. I rather focus our attention on the future, especially since we hope to get the feature out within the next 3-6 months.
If there was a pull request that made the change I would consider merging it, but not something anyone on the team will work on at the moment.
ryangreenberg commentedon Jul 25, 2018
I think this issue can be closed with the release of 3.27:
eryi commentedon Jul 29, 2018
For some reason, this doesn't work with invariant. Is this expected?
hh_client
hhvm --version
eryi commentedon Jul 29, 2018
This might be asking too much of the type checker but it would be nice if this worked on more than 1 level.