@@ -708,6 +708,7 @@ type Checker struct {
708708 circularityMark int // Length of discard log when the cycle in progress was detected
709709 innerCycles []innerCycle // Cycles detected inside the one in progress; see extendCircularity
710710 flowDepthFailures map[FlowLoopKey]int // Largest depth budget known to be too small for a flow walk from a node; see getTypeAtFlowNode
711+ observedHead int32 // 1 + index in resolutions of the lowest head of a cycle observed by the innermost type resolution in progress, or 0
711712 cycleParticipants []TypeResolution // Computations that observed a cycle in progress
712713 effectsMarkDepth int // 1 + resolution index of the innermost effects mark that may be discarded, or 0
713714 varianceStack []VarianceStackEntry
@@ -20327,9 +20328,20 @@ type cycleYield struct {
2032720328 savedResolutionStart int
2032820329 savedVisibleStart int
2032920330 savedDepths [3]depthLimit
20331+ savedReverseMapped reverseMappedState
20332+ savedContextual []ContextualInfo
20333+ savedInference []InferenceContextInfo
20334+ floor int
2033020335 shadowed []shadowedResolving
2033120336}
2033220337
20338+ type reverseMappedState struct {
20339+ sourceStack []*Type
20340+ targetStack []*Type
20341+ expandingFlags ExpandingFlags
20342+ start int32
20343+ }
20344+
2033320345type shadowedResolving struct {
2033420346 key memoKey
2033520347 index int32
@@ -20513,7 +20525,15 @@ func (c *Checker) beginCycleYield(target TypeSystemEntity, propertyName TypeSyst
2051320525 savedResolutionStart: c.resolutionStart,
2051420526 savedVisibleStart: c.visibleStart,
2051520527 savedDepths: [3]depthLimit{c.serializationLevel, c.inlineLevel, c.conditionalConstraintDepth},
20528+ savedReverseMapped: reverseMappedState{c.reverseMappedSourceStack, c.reverseMappedTargetStack, c.reverseExpandingFlags, c.reverseMappedStart},
20529+ savedContextual: c.contextualInfos,
20530+ savedInference: c.inferenceContextInfos,
20531+ floor: floor,
2051620532 })
20533+ // The contexts the hidden resolutions entered are hidden too, so that the
20534+ // recomputation is from scratch.
20535+ c.reverseMappedSourceStack, c.reverseMappedTargetStack, c.reverseExpandingFlags, c.reverseMappedStart = nil, nil, 0, 0
20536+ c.contextualInfos, c.inferenceContextInfos = nil, nil
2051720537 c.resolutionStart = n
2051820538 c.visibleStart = n
2051920539 c.serializationLevel, c.inlineLevel, c.conditionalConstraintDepth = depthLimit{}, depthLimit{}, depthLimit{}
@@ -20524,6 +20544,9 @@ func (c *Checker) endCycleYield() {
2052420544 c.resolutionStart = y.savedResolutionStart
2052520545 c.visibleStart = y.savedVisibleStart
2052620546 c.serializationLevel, c.inlineLevel, c.conditionalConstraintDepth = y.savedDepths[0], y.savedDepths[1], y.savedDepths[2]
20547+ r := y.savedReverseMapped
20548+ c.reverseMappedSourceStack, c.reverseMappedTargetStack, c.reverseExpandingFlags, c.reverseMappedStart = r.sourceStack, r.targetStack, r.expandingFlags, r.start
20549+ c.contextualInfos, c.inferenceContextInfos = y.savedContextual, y.savedInference
2052720550 for _, sh := range y.shadowed {
2052820551 c.resolving.set(sh.key, sh.index)
2052920552 }
@@ -20789,6 +20812,42 @@ func (c *Checker) markTypeResolutionCircular(start int) {
2078920812 c.markCircular(start)
2079020813}
2079120814
20815+ // keepsResultInCycle reports whether the type resolution at index n, which
20816+ // observed the cycles whose lowest head is observed (see Checker.observedHead),
20817+ // computes what it computes first from scratch although a cycle is in
20818+ // progress, so that its result is kept as a participant of the cycle:
20819+ // - The resolution re-entered a hidden resolution of itself, which a
20820+ // computation from scratch of the outer one always does, and what it
20821+ // observed in progress was all entered by the outer one, so its result is
20822+ // what the outer one computes first from scratch.
20823+ // - The resolution is the one a cycle yield computes again from scratch,
20824+ // with everything below it hidden, and it observed nothing hidden.
20825+ // - The resolution is inside the outermost measurement of variances, which
20826+ // hides what is below it and is measured from the canonical entry of its
20827+ // circularity, so what it computes is the same whatever led to it, and it
20828+ // only observed its incomplete variances. Computing it first from scratch
20829+ // reaches the measurement and computes it again inside, the same way.
20830+ func (c *Checker) keepsResultInCycle(n int, f *resolution, observed int32) bool {
20831+ r := &f.typeResolution
20832+ if r.outerSelf != 0 && observed != 0 && observed >= r.outerSelf && int(observed) <= n {
20833+ return true
20834+ }
20835+ if len(c.cycleYields) != 0 {
20836+ y := &c.cycleYields[len(c.cycleYields)-1]
20837+ if n >= y.floor && int(f.prevTypeResolution) <= y.floor && (observed == 0 || int(observed) > y.floor) {
20838+ return true
20839+ }
20840+ }
20841+ return c.observedOnlyOutermostMeasurement(n)
20842+ }
20843+
20844+ func minObservedHead(a int32, b int32) int32 {
20845+ if a == 0 || b != 0 && b < a {
20846+ return b
20847+ }
20848+ return a
20849+ }
20850+
2079220851// observedOnlyOutermostMeasurement reports whether the cycle in progress is
2079320852// the one headed by the outermost measurement of variances, which the
2079420853// resolution at index n is inside, and no other.
@@ -20847,21 +20906,9 @@ func (c *Checker) popTypeResolution() bool {
2084720906 debug.Assert(c.typeResolutionTop == n+1, "resolutions left above a type resolution")
2084820907 f := &c.resolutions[n]
2084920908 result := f.typeResolution.result
20850- if r := &f.typeResolution; r.outerSelf != 0 && result && c.circularityStart != 0 && c.circularityStart <= n && c.circularityStart >= int(r.outerSelf) && !r.participant {
20851- // The resolution re-entered a hidden resolution of itself, which a
20852- // computation from scratch of the outer one always does, and what it
20853- // observed in progress was all entered by the outer one, so its result
20854- // is what the outer one computes first from scratch: the outer one
20855- // keeps it, as must the cycle.
20856- r.participant = true
20857- c.cycleParticipants = append(c.cycleParticipants, *r)
20858- } else if r := &f.typeResolution; result && !r.participant && c.observedOnlyOutermostMeasurement(n) {
20859- // The outermost measurement of variances hides what is below it and
20860- // is measured from the canonical entry of its circularity, so what
20861- // it computes is the same whatever led to it. This resolution only
20862- // observed its incomplete variances, so its result is what it
20863- // computes first from scratch too, which reaches the measurement and
20864- // computes it again inside, as main keeps the first result set.
20909+ observed := c.observedHead
20910+ c.observedHead = minObservedHead(f.prevObservedHead, observed)
20911+ if r := &f.typeResolution; result && !r.participant && c.circularityStart != 0 && c.keepsResultInCycle(n, f, observed) {
2086520912 r.participant = true
2086620913 c.cycleParticipants = append(c.cycleParticipants, *r)
2086720914 }
@@ -20893,6 +20940,8 @@ func (c *Checker) beginTypeResolution(target TypeSystemEntity, propertyName Type
2089320940 f.prevMemo = int32(c.memoTop)
2089420941 f.isTypeResolution = true
2089520942 f.prevTypeResolution = int32(c.typeResolutionTop)
20943+ f.prevObservedHead = c.observedHead
20944+ c.observedHead = 0
2089620945 f.typeResolution.target = target
2089720946 f.typeResolution.propertyName = propertyName
2089820947 f.typeResolution.result = true
0 commit comments