Skip to content

Widen inference candidates for error reporting #15221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from

Conversation

sandersn
Copy link
Member

Both type inference and type inference error reporting widen candidates the same way now.

Previously error reporting hit an assert when checking for best common supertype: it hit a condition that indicated there there was a best common supertype, even though the error reporting should only be called when there is no best common supertype.

Both type inference and error reporting call getInferenceCandidates, so I just moved the additional widening code from type inference to getInferenceCandidates.

Fixes #15116

They are widened the same way for checking for best common super type
and for reporting the error now. Previously error reporting forgot to
widen and hit an assert.
Add a test to show that error reporting for type inference widens the
same way that type inference proper does. Previously it asserted.

Also update other baselines with the widened type.
Previously it discarded and re-added *top-level* nulls and undefineds in
the inference candidate list. Which doesn't make much sense.
Now it discards and re-adds nulls and undefineds that are unioned with
types in the inference candidate list.

This makes the new test pass now instead of failing.
@sandersn
Copy link
Member Author

This PR now fixes the bad inference that led to the error in the first place. getCommonSupertype wasn't correctly discarding | null | undefined from types.

Previous commit mistakenly only updated baselines
@@ -10338,17 +10345,8 @@ namespace ts {
if (!inferredType) {
const inferences = getInferenceCandidates(context, index);
if (inferences.length) {
// We widen inferred literal types if
Copy link
Member Author

Choose a reason for hiding this comment

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

This code moves into getInferenceCandidates so that both type inference (this section) and type inference error reporting (the other call to getInferenceCandidates) widen the same way.

@ahejlsberg
Copy link
Member

ahejlsberg commented Jun 8, 2017

Would you mind merging master into this branch to get things updated, then I'll take a look.

@sandersn
Copy link
Member Author

sandersn commented Jun 8, 2017

I forgot how much has changed in inference in the last few weeks! It's merged now but it needed some rewriting to work with InferenceInfo.

Add getOptionalType to support the common case of just adding undefined.
@sandersn
Copy link
Member Author

sandersn commented Jun 8, 2017

Travis failed because getNullableType doesn't handle all the cases that includeFalsyTypes used to -- void, in this case. I changed getNullableType to handle void, and added getOptionalType to handle the common case of adding | undefined to a type. (All other calls to getNullableType just passed TypeFlags.Undefined, so I changed them to call getOptionalType.)

const supertype = getSupertypeOrUnion(primaryTypes);
return supertype && getNullableType(supertype, getFalsyFlagsOfTypes(types) & TypeFlags.Nullable);
const supertype = getSupertypeOrUnion(map(types, getNonNullableType));
return supertype && getNullableType(supertype, getFalsyFlagsOfTypes(types) & (TypeFlags.Nullable | TypeFlags.Void));
Copy link
Member Author

Choose a reason for hiding this comment

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

Here's what caused the addition TypeFlags.Void to getFalsyFlagsOfTypes. When types contains void, the old filter(types ... code did not remove it because void only has TypeFlags.Void. But map(types, getNonNullableType) relies on getTypeFacts, which treats void and undefined exactly the same. So it removes void and undefined both. This causes the following bug:

declare function f<T>(cb: () => T | undefined): T;
f(() => { });
  ~~~~~~~~~
  Argument of type '() => void' is not assignable to parameter of type '() => undefined'.

I would like getNonNullableType not to remove void, but I'm not sure how to do that without changing getTypeFacts, which I am not at all comfortable doing.

sandersn added 2 commits June 9, 2017 15:09
This changes the new test's baseline. Note that the new test exists to
show that the compiler no longer crashes, so errors are fine.
@typescript-bot
Copy link
Collaborator

Thanks for your contribution. This PR has not been updated in a while and cannot be automatically merged at the time being. For housekeeping purposes we are closing stale PRs. If you'd still like to continue working on this PR, please leave a message and one of the maintainers can reopen it.

@RyanCavanaugh RyanCavanaugh deleted the widen-inference-candidates-for-error-reporting branch June 16, 2022 21:42
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.

5 participants