checking: allow recursive Reflectable user instances#123
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
SummaryThis PR adjusts the primitive Reflectable handling so user-defined recursive Reflectable instances that build type-level lists via ordinary instance resolution are accepted. The change narrows the primitive Reflectable rejection path: when the first Reflectable solver argument is not a primitive literal or a unification variable, the primitive solver now yields None (no compiler solver applies) instead of Apart (permanent rejection). That allows the normal declared-instance resolution to attempt user-defined Reflectable instances and assemble recursive list evidence one cell at a time. The change is isolated to prim_reflectable and does not alter row solving or instance-chain backtracking. Technical details
Tests and fixtures
Code review observationsStrengths
Risks / considerations
Merge confidence: 4/5Rationale:
WalkthroughThe solver reorders compiler-instance matching based on a per-constraint ChangesConstraint Solver Instance-Matching Order
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
purefunctor
left a comment
There was a problem hiding this comment.
Nice! Verified that this checks in the original compiler.
Could you split this into two commits? The first one to add the failing test case and have the second commit be the fix?
7d7b5c9 to
9dea7c2
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
compiler-core/checking/src/core/constraint.rs (1)
246-260: 💤 Low valueConsider extracting duplicated compiler-instance matching logic.
Lines 247–259 duplicate the match handling from lines 210–222. A helper closure or local function could reduce repetition and ensure both paths stay in sync during future maintenance.
♻️ Possible refactor using a closure
+ let try_compiler_instance = + |work: &mut WorkList, + blocked: &mut FxHashSet<u32>, + blocked_on_skolem: &mut bool| + -> QueryResult<bool> { + match compiler::match_compiler_instance(state, context, wanted, &given)? { + Some(matching::MatchInstance::Match { unifications, constraints }) => { + work.extend_from_parts(unifications, constraints); + Ok(true) + } + Some(matching::MatchInstance::Stuck { stuck }) => { + blocked.extend(stuck); + Ok(false) + } + Some(matching::MatchInstance::Skolem) => { + *blocked_on_skolem = true; + Ok(false) + } + Some(matching::MatchInstance::Apart) | None => Ok(false), + } + }; + if !prefer_declared_instances { - match compiler::match_compiler_instance(state, context, wanted, &given)? { - Some(matching::MatchInstance::Match { unifications, constraints }) => { - work.extend_from_parts(unifications, constraints); - continue 'work; - } - Some(matching::MatchInstance::Stuck { stuck }) => { - blocked.extend(stuck); - } - Some(matching::MatchInstance::Skolem) => { - blocked_on_skolem = true; - } - Some(matching::MatchInstance::Apart) | None => (), + if try_compiler_instance(&mut work, &mut blocked, &mut blocked_on_skolem)? { + continue 'work; } }Apply analogous change to the deferred block at lines 246–260.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@compiler-core/checking/src/core/constraint.rs` around lines 246 - 260, The match handling of compiler::match_compiler_instance is duplicated; extract the logic into a small helper (closure or local fn) that takes the MatchInstance result and performs the actions now repeated (calling work.extend_from_parts with unifications/constraints, extending blocked with stuck, setting blocked_on_skolem, and no-op for Apart/None), then replace both match blocks (the one guarded by prefer_declared_instances and the earlier one) to call this helper with the result of compiler::match_compiler_instance(state, context, wanted, &given) so behavior stays in sync for symbols: prefer_declared_instances, compiler::match_compiler_instance, matching::MatchInstance, work.extend_from_parts, blocked, blocked_on_skolem.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@compiler-core/checking/src/core/constraint.rs`:
- Around line 246-260: The match handling of compiler::match_compiler_instance
is duplicated; extract the logic into a small helper (closure or local fn) that
takes the MatchInstance result and performs the actions now repeated (calling
work.extend_from_parts with unifications/constraints, extending blocked with
stuck, setting blocked_on_skolem, and no-op for Apart/None), then replace both
match blocks (the one guarded by prefer_declared_instances and the earlier one)
to call this helper with the result of compiler::match_compiler_instance(state,
context, wanted, &given) so behavior stays in sync for symbols:
prefer_declared_instances, compiler::match_compiler_instance,
matching::MatchInstance, work.extend_from_parts, blocked, blocked_on_skolem.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8b890595-261d-44fe-a131-df7a9e33b9de
📒 Files selected for processing (1)
compiler-core/checking/src/core/constraint.rs
9dea7c2 to
d70787e
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #123 +/- ##
=======================================
Coverage 83.09% 83.10%
=======================================
Files 130 130
Lines 23730 23757 +27
Branches 23730 23757 +27
=======================================
+ Hits 19719 19743 +24
- Misses 2237 2238 +1
- Partials 1774 1776 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
checking: allow recursive Reflectable user instances
Base branch:
mainReview Order
This PR is independent and can be reviewed against
mainat any time. It does not depend on the row-fundep/givens PR or the stacked instance/operator PRs.Summary
Reflectableinstances that build type-level lists through ordinary instance resolution.Reflectableimplementation from rejecting valid recursive list evidence too early.Motivation
This fixes a false positive found while checking real project code that encodes values through recursive type-level lists. PureScript accepts the recursive user instances, but the analyzer rejected them during primitive
Reflectablesolving.The primitive solver should cooperate with user-defined recursive evidence rather than treating the recursive structure as unsolvable. This lets ordinary instance resolution build the reflected value one list cell at a time.
Motivating Example
The checker should allow
Reflectableevidence to be assembled recursively through user instances:Before this change, recursive evidence like the
Conscase could be rejected too early even though PureScript can solve it.Implementation Notes
Reflectablerejection path so recursive user instance chains can produce the required reflected value.prim_reflectable; it does not alter row solving or instance-chain backtracking.Tests
Added fixture:
1778704560_reflectable_recursive_user_instancesValidation run locally: