Repository navigation
Keep accepts() reasons and messages of big types readable on bleeding edge - #6850
Draft
ondrejmirtes wants to merge 1 commit into
Draft
ondrejmirtes wants to merge 1 commit into
ondrejmirtes wants to merge 1 commit into
Conversation
… edge A return type mismatch in a data provider built by closures (with closureSignaturesFromUsages inferring literal shapes per call) produced an 8 KB message and a 31 KB tip of 68 near-identical lines. On bleeding edge: - Nested array reasons are offset paths (`Offset 'case 0' › 0 › 0 (T): reason`) instead of repeating the whole accepted type at every level; ArrayType::accepts() now names the entry each reason comes from. - Reasons differing only in their offset path are reported once, listing the offsets; at most 5 reasons are shown in a tip. - A sealed shape rejecting an extra key names its value (`extra key 5 => true`). - Unsealed shapes report their extra offsets as offset paths too. - Object shapes report missing properties in one reason. - "is not a list" / "might be empty" do not repeat a long accepted array. - "Sealed array shapes cannot be intersected" describes the shapes without literal values, so union members with the same keys share the reason. - return.type and argument.type describe an accepted type longer than 1000 characters with literal values widened and big shapes generalized. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RFQVeuWzHD5AobZdsRHdT3
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
A
return.typeerror in a real-world data provider (rows built by stored closures, typed per call byclosureSignaturesFromUsages) came with an 8 KB message and a 31 KB tip of 68 lines. Each line embedded a full literal shape, and the root cause was one missingboolin a@returnarray shape. This PR keeps such errors readable. Everything is bleeding edge only; the legacy output is unchanged.Before / after on that case
Message: 8,148 → 401 chars, and it now shows the difference directly:
Tip: 31.5 KB / 68 lines → 395 chars / 2 lines:
Changes
Offset paths (
AcceptsReasonHelper):ArrayType::accepts()now says which entry a reason belongs to.ConstantArrayType::checkOurKeys()builds paths (Offset 'a' › 0 › 1 (T): reason) instead of repeating the whole accepted type at every nesting level. Only the innermost offset names its types.Grouping in tips:
RuleErrorBuilder::acceptsReasonsTip()merges reasons that differ only in their offset path, listing 3 offsets and a count. A tip shows at most 5 reasons, thenN more reasons not shown.Changes to individual reasons:
Sealed array shape does not accept array with extra key 5 => true.now names the value of the extra key.ObjectShapeTypemerges missing properties into one reason:Foo does not have properties $a, $b, $c and 17 more.IntersectionType:… is not a list/… might be emptyno longer repeat an accepted array described in more than 120 chars; it becomesArray.Sealed array shapes … cannot be intersecteddescribes both shapes without their literal values. Union members that share keys (e.g.ArrayIteratorof literal rows) then produce one reason instead of one per member.Long messages (
AcceptedTypeDescriptionHelper, used forreturn.typeandargument.type): an accepted type whose description exceeds 1000 chars is described with:lowercase-stringetc.),How I checked
I surveyed every reason-producing site in
accepts()/isSuperTypeOf()and reproduced the candidates with generated snippets. The table lists the ones that blew up:non-empty-list<lowercase-string>given a big possibly-empty literal listIterator<int, array{id: int}>given anArrayIteratorof 30 literal rowsSites that stayed small and are unchanged:
Type #n from the union), which grouping now mergesmixedsubtraction reasonsTurbo:
ArrayType,ConstantArrayType,IntersectionTypeandObjectShapeTypeare mirrored. PHP and native output are byte-identical on all scenarios, with bleeding edge on and off. The full suite passes with and without the extension. Smoke, side-by-side, signature parity andmake lint-turboall pass.Expectation changes in existing tests
Offset 0 › 'count')testObjectShapesbug-8146b: its 7 KB literal message is now the widened one-linerNew tests:
testNestedArrayShapeReturnReasonstestReadableAcceptsReasons— 6 cases, all failing without the changeAcceptsReasonHelperTest🤖 Generated with Claude Code
https://claude.ai/code/session_01RFQVeuWzHD5AobZdsRHdT3