Skip to content

feat: require bound_type on Alias - #650

Merged
lesnik512 merged 1 commit into
mainfrom
feat/alias-bound-type-required
Oct 10, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
feat/alias-bound-type-required

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Follow-up to #646. Alias(source_type, *, bound_type) now has no default for bound_type.

The old default was source_type, and #646 made that combination raise AliasBoundToSourceError, so the default had become a value that always fails. With the argument required, type checkers flag Alias(X) before the code runs, and Python raises its own TypeError for the missing argument at runtime.

bound_type=X still raises AliasBoundToSourceError, since a required argument can't stop someone passing the source type. bound_type=None still means reference only.

Who this affects

Nobody beyond #646. Every Alias(X) without bound_type already raises on main; it now raises TypeError instead, and the type checker reports it first. 3.6.0 had the same default, so the migration guide gets a section for anyone coming from 3.x.

Changes

Tests

Written first and seen failing: test_alias_without_bound_type_is_a_type_error in tests/test_typing.py. It checks the runtime TypeError, and its ty: ignore[missing-argument] fails lint under unused-ignore-comment if ty ever stops flagging the call. The runtime test from #646 for the missing argument is removed, since this one covers it. Two tests about other TypeErrors (scope=, source_type passed twice) now pass a bound_type so they keep testing only their own error.

just lint, just test-ci (1016 passed, 100% coverage) and just docs-build pass.

bound_type defaulted to source_type, which always raises
AliasBoundToSourceError. Without a default, type checkers flag Alias(X)
and Python raises TypeError for the missing argument.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Details
Benchmark suite Current: 71038ec Previous: 02071cc Ratio
benchmarks/test_guard_by_type.py::test_g16_resolve_by_type 3652825.793157862 iter/sec (stddev: 3.052138332552558e-8) 3771031.134909357 iter/sec (stddev: 2.2697911849196207e-8) 1.03
benchmarks/test_guard_by_type.py::test_g17_resolve_by_type_large_registry 3576660.7151042814 iter/sec (stddev: 4.522240669160052e-8) 3887826.5618839283 iter/sec (stddev: 1.0260530248332096e-8) 1.09
benchmarks/test_guard_cold.py::test_g8_cold_first_resolve 22650.486446058476 iter/sec (stddev: 0.00004431769531873288) 22441.704313680017 iter/sec (stddev: 0.00004412944571357344) 0.99
benchmarks/test_guard_cold.py::test_g8b_cold_first_resolve_cached 17759.377417815682 iter/sec (stddev: 0.00012770391666123155) 17603.078417214652 iter/sec (stddev: 0.00013542680043615116) 0.99
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[1] 407.4404621567322 iter/sec (stddev: 0.00007363170046857377) 408.43119416709146 iter/sec (stddev: 0.00010427636428722899) 1.00
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[2] 407.47866093779 iter/sec (stddev: 0.0000920279631462072) 395.2852403439341 iter/sec (stddev: 0.0001094598941065125) 0.97
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[4] 391.9457498161211 iter/sec (stddev: 0.00009224319809182048) 391.6201715214159 iter/sec (stddev: 0.00009392825429081774) 1.00
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[1] 13685.441495823556 iter/sec (stddev: 0.000009092019551017633) 12800.775556184068 iter/sec (stddev: 0.000010560008810318503) 0.94
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[2] 6242.155041609591 iter/sec (stddev: 0.00002407312787098234) 6283.932252330921 iter/sec (stddev: 0.000022001425859916024) 1.01
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[4] 3370.1860367984273 iter/sec (stddev: 0.0000411582506586621) 3260.5591032773677 iter/sec (stddev: 0.00005761145959583982) 0.97
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[1] 9578.899599990891 iter/sec (stddev: 0.000009111796327427525) 9251.708694159923 iter/sec (stddev: 0.000010083168814429893) 0.97
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[2] 4029.6636976965883 iter/sec (stddev: 0.000021936690138557797) 4029.181481175781 iter/sec (stddev: 0.00002307266929669685) 1.00
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[4] 1889.897203293902 iter/sec (stddev: 0.00005004968859759734) 1881.1827717207736 iter/sec (stddev: 0.00004167427385347354) 1.00
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[1] 39031.65076563238 iter/sec (stddev: 0.000004908977403966846) 40079.1295601759 iter/sec (stddev: 0.000005602768582894001) 1.03
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[2] 15560.379849626814 iter/sec (stddev: 0.000011237970047804437) 12348.719185702148 iter/sec (stddev: 0.00001258996154921884) 0.79
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[4] 5741.28561356304 iter/sec (stddev: 0.00003987448027805772) 5713.354437583002 iter/sec (stddev: 0.00003331587696267436) 1.00
benchmarks/test_guard_lifecycle.py::test_g6_build_child_container 1521802.0784530693 iter/sec (stddev: 3.8746334340703666e-8) 1566427.2043408991 iter/sec (stddev: 3.20358578644225e-8) 1.03
benchmarks/test_guard_lifecycle.py::test_g6b_build_child_container_auto_scope 1648408.142554846 iter/sec (stddev: 3.365928606671137e-8) 1625403.4302058667 iter/sec (stddev: 1.925213949232657e-8) 0.99
benchmarks/test_guard_lifecycle.py::test_g7_request_lifecycle_batch 2983.626042719132 iter/sec (stddev: 0.000021692725367947783) 3017.4513574050607 iter/sec (stddev: 0.000009553031815838268) 1.01
benchmarks/test_guard_lifecycle.py::test_g7c_event_loop_floor_control 56711.82765181261 iter/sec (stddev: 0.0000024689097904005288) 57669.71026466182 iter/sec (stddev: 0.0000019005288362012417) 1.02
benchmarks/test_guard_lifecycle.py::test_g7b_request_cycle_sync 367376.4293560273 iter/sec (stddev: 9.443576255412015e-8) 383933.90194029326 iter/sec (stddev: 6.111975852560899e-8) 1.05
benchmarks/test_guard_lifecycle.py::test_g13_teardown_at_scale 54306.298341961105 iter/sec (stddev: 0.00000409692014701901) 56808.28515367137 iter/sec (stddev: 0.0000017103516033227298) 1.05
benchmarks/test_guard_lifecycle.py::test_g13b_teardown_at_scale_async_no_finalizers 485.7630324258854 iter/sec (stddev: 0.0012462466689660294) 516.2632230113996 iter/sec (stddev: 0.00112600069681073) 1.06
benchmarks/test_guard_resolve.py::test_g1_transient_resolve 2125014.045014 iter/sec (stddev: 2.997938604304902e-8) 2086784.1352414158 iter/sec (stddev: 2.959879955530313e-8) 0.98
benchmarks/test_guard_resolve.py::test_g2_cached_resolve 3655421.54211567 iter/sec (stddev: 2.5237120735459072e-8) 3373592.094591901 iter/sec (stddev: 2.354920508531505e-8) 0.92
benchmarks/test_guard_resolve.py::test_g3_deep_chain 691985.4094181784 iter/sec (stddev: 1.4859778130925508e-7) 693903.8740511406 iter/sec (stddev: 5.367846392605914e-8) 1.00
benchmarks/test_guard_resolve.py::test_g4_wide_resolve 421123.38030620915 iter/sec (stddev: 4.401946891463989e-7) 429222.02799145726 iter/sec (stddev: 3.8330953894827824e-7) 1.02
benchmarks/test_guard_resolve.py::test_g5_cross_scope 1956714.2521670747 iter/sec (stddev: 2.731344186870257e-8) 1908001.6915968661 iter/sec (stddev: 3.008664045323894e-8) 0.98
benchmarks/test_guard_resolve.py::test_g9_context_resolve 1340601.8980793608 iter/sec (stddev: 1.645990070033704e-7) 1299465.2830285751 iter/sec (stddev: 1.500584814424013e-7) 0.97
benchmarks/test_guard_resolve.py::test_g12_override_active_resolve 709883.2213716456 iter/sec (stddev: 6.309472968022296e-8) 693255.198846221 iter/sec (stddev: 6.30245483837302e-8) 0.98
benchmarks/test_guard_resolve.py::test_g18_alias_hop 3646438.5471754665 iter/sec (stddev: 1.327642294272253e-8) 3593750.123527228 iter/sec (stddev: 1.9561460060166087e-8) 0.99
benchmarks/test_guard_validate.py::test_g10_validate_deep_chain 31366.074405767158 iter/sec (stddev: 0.0002490582072934034) 35779.575346193335 iter/sec (stddev: 0.000017501401196388185) 1.14
benchmarks/test_guard_validate.py::test_g11_validate_wide 20458.43548652921 iter/sec (stddev: 0.000027813941547641654) 20941.999478002366 iter/sec (stddev: 0.00002653444190673139) 1.02

This comment was automatically generated by workflow using github-action-benchmark.

@lesnik512
lesnik512 merged commit 56ccced into main Oct 10, 2026
11 checks passed
@lesnik512
lesnik512 deleted the feat/alias-bound-type-required branch October 10, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant