You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
π€ Filed by Claude, not the account owner β acting on their behalf via their GitHub credentials.
Follow-up to #1229 / the in-progress fix in #1231 (branch fix-1229-intersection-types). While rolling out A & B intersection types across apiology/checkoff's test suite (via a custom typed_let_mock/typed_mock@!macro that expands to @!method $1 @return [Mocha::Mock & $2]), I found a reliable, order-dependent bug: a real method definition placed after a macro-expanding call (e.g. typed_let_mock) in the same class body corrupts type resolution for that call. Moving the macro call above the method definition fixes it every time.
Two manifestations observed
False positive: multiple stacked @!parse-based type overrides for def_delegators-generated methods in one class β whichever override is declared last fails with Declared return type X does not match inferred type nil for ClassName#method_name, regardless of grouping (one comment block vs. several) or which symbol happens to be last.
Silent revert to untyped: a typed_let_mock :task, Asana::Resources::Task call placed after a real method definition (with two unrelated let_mock lines in between) silently reverts to plain Mocha::Mock β no error at that call, but every downstream call site using the mock then fails as if the intersection type was never applied.
Reproduction (manifestation #2, from the real checkoff project)
test/unit/test_tasks.rb, minimal diff that introduces the bug (moving typed_let_mock :task from before the client method to after it, past two intervening let_mock lines):
# rubocop:disable YARD/TagTypeSyntax# @return [Mocha::Mock & Asana::Client]# @sg-ignore TestTasks#client return type could not be inferreddefclient# @sg-ignore Unresolved call to client on MyOpenStructmocks.clientend# rubocop:enable YARD/TagTypeSyntax
With the diff applied (typed_let_mock :task after client), bundle exec solargraph typecheck test/unit/test_tasks.rb --level strong --directory . reports 18 problems, all of the form:
Wrong argument type for Checkoff::Tasks#<method>: task expected Asana::Resources::Task, received Mocha::Mock
at 18 distinct call sites (lines 92, 110, 128, 154, 171, 219, 232, 258, 311, 436, 454, 502, 525, 543, 562, 573, 590, 607) β every use of the task helper in the file, as if typed_let_mock :task, Asana::Resources::Task had never been called at all.
Reverting the diff (moving typed_let_mock :task back above client, no other changes) restores a clean 0 problems found.
I could not get a minimal reproduction to work in an isolated scratch directory (Unresolved call to typed_let_mock β the macro itself failed to register outside the real project's bundle/workspace context), so the reproduction above is against the real apiology/checkoff project. Happy to provide more of that project's Solargraph config (config/annotations_misc.rb, .solargraph.yml) if useful.
Workaround in use: always declare macro-expanding calls (typed_let_mock, typed_mock) before any real method definitions in the same class body.
π€ Filed by Claude, not the account owner β acting on their behalf via their GitHub credentials.
Follow-up to #1229 / the in-progress fix in #1231 (branch
fix-1229-intersection-types). While rolling outA & Bintersection types acrossapiology/checkoff's test suite (via a customtyped_let_mock/typed_mock@!macrothat expands to@!method $1 @return [Mocha::Mock & $2]), I found a reliable, order-dependent bug: a real method definition placed after a macro-expanding call (e.g.typed_let_mock) in the same class body corrupts type resolution for that call. Moving the macro call above the method definition fixes it every time.Two manifestations observed
@!parse-based type overrides fordef_delegators-generated methods in one class β whichever override is declared last fails withDeclared return type X does not match inferred type nil for ClassName#method_name, regardless of grouping (one comment block vs. several) or which symbol happens to be last.typed_let_mock :task, Asana::Resources::Taskcall placed after a real method definition (with two unrelatedlet_mocklines in between) silently reverts to plainMocha::Mockβ no error at that call, but every downstream call site using the mock then fails as if the intersection type was never applied.Reproduction (manifestation #2, from the real checkoff project)
test/unit/test_tasks.rb, minimal diff that introduces the bug (movingtyped_let_mock :taskfrom before theclientmethod to after it, past two interveninglet_mocklines):Where
typed_let_mockis defined via:and
clientis a real accessor method:With the diff applied (
typed_let_mock :taskafterclient),bundle exec solargraph typecheck test/unit/test_tasks.rb --level strong --directory .reports 18 problems, all of the form:at 18 distinct call sites (lines 92, 110, 128, 154, 171, 219, 232, 258, 311, 436, 454, 502, 525, 543, 562, 573, 590, 607) β every use of the
taskhelper in the file, as iftyped_let_mock :task, Asana::Resources::Taskhad never been called at all.Reverting the diff (moving
typed_let_mock :taskback aboveclient, no other changes) restores a clean0 problems found.Notes
fix-1229-intersection-typesbranch (Add intersection (A & B), union (|), and grouping ([...]) type syntaxΒ #1231) β I haven't checked whether it reproduces onmasterwith plain (non-intersection)@!method/@!macrooverrides, since the checkoff test suite's use of this pattern only exists because of the intersection-type work in Add intersection (A & B), union (|), and grouping ([...]) type syntaxΒ #1231.Unresolved call to typed_let_mockβ the macro itself failed to register outside the real project's bundle/workspace context), so the reproduction above is against the realapiology/checkoffproject. Happy to provide more of that project's Solargraph config (config/annotations_misc.rb,.solargraph.yml) if useful.typed_let_mock,typed_mock) before any real method definitions in the same class body.