Implement singleton binary literal types#10816
Open
williamthome wants to merge 13 commits intoerlang:masterfrom
Open
Implement singleton binary literal types#10816williamthome wants to merge 13 commits intoerlang:masterfrom
williamthome wants to merge 13 commits intoerlang:masterfrom
Conversation
Erlang's type system supports singleton types for atoms ('foo') and
integers (42), but not for binaries. This adds Phase 1 support for
binary literal types like <<"hello">> in -type, -spec, and -callback
declarations.
In this phase, Dialyzer treats <<"foo">> structurally as <<_:24>>
(by bit size). Full value tracking is planned for Phase 2.
Changes:
- Parser: grammar rule for `<< string >>` producing {bin_type, Anno, Binary}
- Linter: accept {bin_type, _, Value} in type positions
- Pretty printer: render bin_type back as <<"...">>
- Dialyzer: from_form maps to t_bitstr(0, BitSize), t_form_to_string
- Syntax tools: binary_literal_type node type with constructor/accessor/revert
- Documentation: abstract format and type spec reference updated
- Tests: erl_lint, erl_pp, syntax_tools, and dialyzer test data
Extend Dialyzer to track binary literal values, not just bit sizes.
<<"foo">> is now a distinct tracked value rather than just <<_:24>>,
enabling type narrowing, map key tracking, and set operations.
Uses the qualifier field of #c{} (unused for binary types) to store
an ordset of known binary values, following the same pattern as atom
and integer singleton sets.
Changes in erl_types.erl:
- ?bitstr_vals macro and t_binary_val/1 constructor
- from_form uses t_binary_val for value-level precision
- t_from_term tracks binary values (not just bitstring sizes)
- t_sup_aux: union of binary value sets with SET_LIMIT widening
- t_inf_aux: intersection with value sets and structural types
- t_subtract_aux: element-wise subtraction of value sets
- is_singleton_type: recognizes single-value binary sets
- separate_key: expands binary value sets for map key tracking
- t_to_string/t_elements: render and expand value sets
Add a unit test in erl_types_SUITE that directly exercises
type_form_to_remote_modules with {bin_type, _, _} forms, verifying
that binary literal types are correctly treated as leaf types with
no module dependencies.
Also extend the small_SUITE bin_type integration test with a type
that combines a binary literal and a remote type reference
(<<"hello">> | binary:part()), exercising the full Dialyzer pipeline
through get_modules_mentioned.
Fix missing binary_literal_type clauses in erl_prettypr:lay_2/2, erl_syntax:concrete/1, and erl_syntax:is_literal/1 that would crash or return wrong results for binary literal type nodes. Add comprehensive tests for binary val type operations in erl_types, empty binary edge cases in erl_pp and erl_lint, and concrete/is_literal coverage in syntax_tools.
Dialyzer's check_record_fields/3 was missing a clause for {bin_type, _, _}
forms, causing a function_clause crash when analyzing records with binary
literal type fields (e.g., -record(msg, {tag :: <<"hello">>})).
Support <<"..."/utf8>>, <<"..."/utf16>>, <<"..."/utf32>>, <<"..."/latin1>>,
and ~"..." sigil syntax in type specifications. Only the parser needed
changes since {bin_type, Anno, Bin} stores the final binary value.
Reuse existing non-terminals (opt_bit_type_list, sigil) instead of duplicating grammar structure. Reduces 3 rules to 2 and unifies builder functions, while producing identical AST output.
Contributor
CT Test Results 6 files 257 suites 2h 8m 27s ⏱️ Results for commit eeaacb5. ♻️ This comment has been updated with latest results. To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts// Erlang/OTP Github Action Bot |
The t_from_term change now tracks exact binary values (like atoms), producing more precise type names in Dialyzer output: - <<>> becomes <<"">> - <<_:8>> becomes <<"f">> or <<"*">> for known values - <<_:16>> becomes <<"hi">> for known values - Binary map keys show as singleton values (e.g., <<"50">>) Also fix make_bitstr_vals to properly compute Unit/Base from filtered values after intersection, rather than assuming uniform sizes.
The CI license-header check requires headers on modified files. The test comparator skips %-prefixed lines, so headers are safe.
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.
This is an implementation of singleton binary literal types as described in erlang/eep#84.