Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions internal/checker/relater.go
Original file line number Diff line number Diff line change
Expand Up @@ -3878,26 +3878,32 @@ func (r *Relater) typeArgumentsRelatedTo(sources []*Type, targets []*Type, varia
} else {
related = r.c.compareTypesIdentical(s, t)
}
} else if variance == VarianceFlagsCovariant {
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
} else if variance == VarianceFlagsContravariant {
related = r.isRelatedToEx(t, s, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
} else if variance == VarianceFlagsBivariant {
// In the bivariant case we first compare contravariantly without reporting
// errors. Then, if that doesn't succeed, we compare covariantly with error
// reporting. Thus, error elaboration will be based on the covariant check,
// which is generally easier to reason about.
related = r.isRelatedTo(t, s, RecursionFlagsBoth, false /*reportErrors*/)
if related == TernaryFalse {
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
}
} else {
// In the invariant case we first compare covariantly, and only when that
// succeeds do we proceed to compare contravariantly. Thus, error elaboration
// will typically be based on the covariant check.
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
if related != TernaryFalse {
related &= r.isRelatedToEx(t, s, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
// Propagate unreliable variance flag
if r.c.inVarianceComputation && varianceFlags&VarianceFlagsUnreliable != 0 {
r.c.instantiateType(s, r.c.reportUnreliableMapper)
}
if variance == VarianceFlagsCovariant {
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
} else if variance == VarianceFlagsContravariant {
related = r.isRelatedToEx(t, s, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
} else if variance == VarianceFlagsBivariant {
// In the bivariant case we first compare contravariantly without reporting
// errors. Then, if that doesn't succeed, we compare covariantly with error
// reporting. Thus, error elaboration will be based on the covariant check,
// which is generally easier to reason about.
related = r.isRelatedTo(t, s, RecursionFlagsBoth, false /*reportErrors*/)
if related == TernaryFalse {
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
}
} else {
// In the invariant case we first compare covariantly, and only when that
// succeeds do we proceed to compare contravariantly. Thus, error elaboration
// will typically be based on the covariant check.
related = r.isRelatedToEx(s, t, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
if related != TernaryFalse {
related &= r.isRelatedToEx(t, s, RecursionFlagsBoth, reportErrors, nil /*headMessage*/, intersectionState)
}
}
}
if related == TernaryFalse {
Expand Down