-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Suppress error caused by intermediate types in getTypeOfExpression
#54380
Merged
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
tests/baselines/reference/controlFlowNoIntermediateErrors.symbols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
=== tests/cases/conformance/controlFlow/controlFlowNoIntermediateErrors.ts === | ||
// Repros from #46475 | ||
|
||
function f1() { | ||
>f1 : Symbol(f1, Decl(controlFlowNoIntermediateErrors.ts, 0, 0)) | ||
|
||
let code: 0 | 1 | 2 = 0; | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 3, 7)) | ||
|
||
const otherCodes: (0 | 1 | 2)[] = [2, 0, 1, 0, 2, 2, 2, 0, 1, 0, 2, 1, 1, 0, 2, 1]; | ||
>otherCodes : Symbol(otherCodes, Decl(controlFlowNoIntermediateErrors.ts, 4, 9)) | ||
|
||
for (const code2 of otherCodes) { | ||
>code2 : Symbol(code2, Decl(controlFlowNoIntermediateErrors.ts, 5, 14)) | ||
>otherCodes : Symbol(otherCodes, Decl(controlFlowNoIntermediateErrors.ts, 4, 9)) | ||
|
||
if (code2 === 0) { | ||
>code2 : Symbol(code2, Decl(controlFlowNoIntermediateErrors.ts, 5, 14)) | ||
|
||
code = code === 2 ? 1 : 0; | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 3, 7)) | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 3, 7)) | ||
} | ||
else { | ||
code = 2; | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 3, 7)) | ||
} | ||
} | ||
} | ||
|
||
function f2() { | ||
>f2 : Symbol(f2, Decl(controlFlowNoIntermediateErrors.ts, 13, 1)) | ||
|
||
let code: 0 | 1 = 0; | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 16, 7)) | ||
|
||
while (true) { | ||
code = code === 1 ? 0 : 1; | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 16, 7)) | ||
>code : Symbol(code, Decl(controlFlowNoIntermediateErrors.ts, 16, 7)) | ||
} | ||
} | ||
|
80 changes: 80 additions & 0 deletions
80
tests/baselines/reference/controlFlowNoIntermediateErrors.types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
=== tests/cases/conformance/controlFlow/controlFlowNoIntermediateErrors.ts === | ||
// Repros from #46475 | ||
|
||
function f1() { | ||
>f1 : () => void | ||
|
||
let code: 0 | 1 | 2 = 0; | ||
>code : 0 | 1 | 2 | ||
>0 : 0 | ||
|
||
const otherCodes: (0 | 1 | 2)[] = [2, 0, 1, 0, 2, 2, 2, 0, 1, 0, 2, 1, 1, 0, 2, 1]; | ||
>otherCodes : (0 | 1 | 2)[] | ||
>[2, 0, 1, 0, 2, 2, 2, 0, 1, 0, 2, 1, 1, 0, 2, 1] : (0 | 1 | 2)[] | ||
>2 : 2 | ||
>0 : 0 | ||
>1 : 1 | ||
>0 : 0 | ||
>2 : 2 | ||
>2 : 2 | ||
>2 : 2 | ||
>0 : 0 | ||
>1 : 1 | ||
>0 : 0 | ||
>2 : 2 | ||
>1 : 1 | ||
>1 : 1 | ||
>0 : 0 | ||
>2 : 2 | ||
>1 : 1 | ||
|
||
for (const code2 of otherCodes) { | ||
>code2 : 0 | 1 | 2 | ||
>otherCodes : (0 | 1 | 2)[] | ||
|
||
if (code2 === 0) { | ||
>code2 === 0 : boolean | ||
>code2 : 0 | 1 | 2 | ||
>0 : 0 | ||
|
||
code = code === 2 ? 1 : 0; | ||
>code = code === 2 ? 1 : 0 : 0 | 1 | ||
>code : 0 | 1 | 2 | ||
>code === 2 ? 1 : 0 : 0 | 1 | ||
>code === 2 : boolean | ||
>code : 0 | 1 | 2 | ||
>2 : 2 | ||
>1 : 1 | ||
>0 : 0 | ||
} | ||
else { | ||
code = 2; | ||
>code = 2 : 2 | ||
>code : 0 | 1 | 2 | ||
>2 : 2 | ||
} | ||
} | ||
} | ||
|
||
function f2() { | ||
>f2 : () => void | ||
|
||
let code: 0 | 1 = 0; | ||
>code : 0 | 1 | ||
>0 : 0 | ||
|
||
while (true) { | ||
>true : true | ||
|
||
code = code === 1 ? 0 : 1; | ||
>code = code === 1 ? 0 : 1 : 0 | 1 | ||
>code : 0 | 1 | ||
>code === 1 ? 0 : 1 : 0 | 1 | ||
>code === 1 : boolean | ||
>code : 0 | 1 | ||
>1 : 1 | ||
>0 : 0 | ||
>1 : 1 | ||
} | ||
} | ||
|
24 changes: 24 additions & 0 deletions
24
tests/cases/conformance/controlFlow/controlFlowNoIntermediateErrors.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// @strict: true | ||
// @noEmit: true | ||
|
||
// Repros from #46475 | ||
|
||
function f1() { | ||
let code: 0 | 1 | 2 = 0; | ||
const otherCodes: (0 | 1 | 2)[] = [2, 0, 1, 0, 2, 2, 2, 0, 1, 0, 2, 1, 1, 0, 2, 1]; | ||
for (const code2 of otherCodes) { | ||
if (code2 === 0) { | ||
code = code === 2 ? 1 : 0; | ||
} | ||
else { | ||
code = 2; | ||
} | ||
} | ||
} | ||
|
||
function f2() { | ||
let code: 0 | 1 = 0; | ||
while (true) { | ||
code = code === 1 ? 0 : 1; | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Type-only” is an overloaded term that sounds like it refers to type-only imports. Would
SkipDiagnostics
be more clear?Also, there are a number of mechanisms like this already in the checker, and it’s confusing which one to use.
getSignatureApplicabilityError
,compareSignaturesRelated
, andcheckApplicableSignatureForJsxOpeningLikeElement
all take both aCheckMode
and areportErrors
parameter. It now seems possible for those two to disagree. And there are surely lots of other functions that take aCheckMode
but haven’t been updated to suppress errors forTypeOnly
.It seems like it might be better to add use a
reportErrors
parameter tocheckBinaryLikeExpressionWorker
, unless we’re prepared to handle this newCheckMode
everywhereCheckMode
s are passed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new flag indicates that the originating call came from
getTypeOfExpression
, meaning that diagnostics can optionally be omitted with no ill effects. But unless we're dealing with an expression that could possibly cause new errors when operands are given narrower types than their declared types, there is no requirement that diagnostics must be omitted. It's bit of a mouthful, not sure what a good short name for that concept is.I don't think there's an issue with disagreement between
checkMode
andreportErrors
since the flag can be safely ignored in practically all scenarios--in fact, beyond the error for non-comparable operands, nothing needs to change as of now. But if we later discover other issues similar to this, we now have a mechanism to address them.The only way to properly propagate the information is through a
CheckMode
flag.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I kinda agree with Andrew and from time to time I find myself wishing we had a better way to control when to report errors and when to not to based on whether we're actually checking things, or just getting types. But since we're nowhere close to doing this, I'm ok with the
CheckMode
trick for now.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, in an ideal world we'd have more separation between the process of resolving types and that of checking the types. But given that both of those processes have a lot of common code paths (i.e. the entire top-down recursive decomposition is pretty much the same), we've chosen to conflate the them. This does occasionally muddle things, but it definitely also saves a lot of code.