-
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
Stricter criteria for eliminating types in unions during inference #32919
Changes from all commits
a81ce06
f929a25
6d46850
86d9153
abc61a0
ac2f151
c816cf2
af7ccf9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15486,8 +15486,7 @@ namespace ts { | |
let visited: Map<number>; | ||
let bivariant = false; | ||
let propagationType: Type; | ||
let inferenceMatch = false; | ||
let inferenceIncomplete = false; | ||
let inferencePriority = InferencePriority.MaxValue; | ||
let allowComplexConstraintInference = true; | ||
inferFromTypes(originalSource, originalTarget); | ||
|
||
|
@@ -15600,7 +15599,7 @@ namespace ts { | |
clearCachedInferences(inferences); | ||
} | ||
} | ||
inferenceMatch = true; | ||
inferencePriority = Math.min(inferencePriority, priority); | ||
return; | ||
} | ||
else { | ||
|
@@ -15694,19 +15693,15 @@ namespace ts { | |
const key = source.id + "," + target.id; | ||
const status = visited && visited.get(key); | ||
if (status !== undefined) { | ||
if (status & 1) inferenceMatch = true; | ||
if (status & 2) inferenceIncomplete = true; | ||
inferencePriority = Math.min(inferencePriority, status); | ||
return; | ||
} | ||
(visited || (visited = createMap<number>())).set(key, 0); | ||
const saveInferenceMatch = inferenceMatch; | ||
const saveInferenceIncomplete = inferenceIncomplete; | ||
inferenceMatch = false; | ||
inferenceIncomplete = false; | ||
(visited || (visited = createMap<number>())).set(key, InferencePriority.Circularity); | ||
const saveInferencePriority = inferencePriority; | ||
inferencePriority = InferencePriority.MaxValue; | ||
action(source, target); | ||
visited.set(key, (inferenceMatch ? 1 : 0) | (inferenceIncomplete ? 2 : 0)); | ||
inferenceMatch = inferenceMatch || saveInferenceMatch; | ||
inferenceIncomplete = inferenceIncomplete || saveInferenceIncomplete; | ||
visited.set(key, inferencePriority); | ||
inferencePriority = Math.min(inferencePriority, saveInferencePriority); | ||
} | ||
|
||
function inferFromMatchingType(source: Type, targets: Type[], matches: (s: Type, t: Type) => boolean) { | ||
|
@@ -15778,31 +15773,32 @@ namespace ts { | |
let nakedTypeVariable: Type | undefined; | ||
const sources = source.flags & TypeFlags.Union ? (<UnionType>source).types : [source]; | ||
const matched = new Array<boolean>(sources.length); | ||
const saveInferenceIncomplete = inferenceIncomplete; | ||
inferenceIncomplete = false; | ||
let inferenceCircularity = false; | ||
// First infer to types that are not naked type variables. For each source type we | ||
// track whether inferences were made from that particular type to some target. | ||
// track whether inferences were made from that particular type to some target with | ||
// equal priority (i.e. of equal quality) to what we would infer for a naked type | ||
// parameter. | ||
for (const t of targets) { | ||
if (getInferenceInfoForType(t)) { | ||
nakedTypeVariable = t; | ||
typeVariableCount++; | ||
} | ||
else { | ||
for (let i = 0; i < sources.length; i++) { | ||
const saveInferenceMatch = inferenceMatch; | ||
inferenceMatch = false; | ||
const saveInferencePriority = inferencePriority; | ||
inferencePriority = InferencePriority.MaxValue; | ||
inferFromTypes(sources[i], t); | ||
if (inferenceMatch) matched[i] = true; | ||
inferenceMatch = inferenceMatch || saveInferenceMatch; | ||
if (inferencePriority === priority) matched[i] = true; | ||
inferenceCircularity = inferenceCircularity || inferencePriority === InferencePriority.Circularity; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No |
||
inferencePriority = Math.min(inferencePriority, saveInferencePriority); | ||
} | ||
} | ||
} | ||
const inferenceComplete = !inferenceIncomplete; | ||
inferenceIncomplete = inferenceIncomplete || saveInferenceIncomplete; | ||
// If the target has a single naked type variable and inference completed (meaning we | ||
// explored the types fully), create a union of the source types from which no inferences | ||
// have been made so far and infer from that union to the naked type variable. | ||
if (typeVariableCount === 1 && inferenceComplete) { | ||
// If the target has a single naked type variable and no inference circularities were | ||
// encountered above (meaning we explored the types fully), create a union of the source | ||
// types from which no inferences have been made so far and infer from that union to the | ||
// naked type variable. | ||
if (typeVariableCount === 1 && !inferenceCircularity) { | ||
const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s); | ||
if (unmatched.length) { | ||
inferFromTypes(getUnionType(unmatched), nakedTypeVariable!); | ||
|
@@ -15905,7 +15901,7 @@ namespace ts { | |
const symbol = isNonConstructorObject ? target.symbol : undefined; | ||
if (symbol) { | ||
if (contains(symbolStack, symbol)) { | ||
inferenceIncomplete = true; | ||
inferencePriority = InferencePriority.Circularity; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't tell if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's because |
||
return; | ||
} | ||
(symbolStack || (symbolStack = [])).push(symbol); | ||
|
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.
Is the
-1
here (used asnumber
) the same-1
lower in the file?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.
Yes