Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make enum size not depend on the order of variants #131684

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

adwinwhite
Copy link
Contributor

Fixes #117238.

I fixed the off-by-one error by allocating discriminant starting from the variant after the untagged variant and wrapping around to the first variant when it reaches the last variant.

enum {
    A,           // 1
    B,           // 2
    C(bool),     // untagged_variant, no discriminant
    D,           // has a discriminant of 0
}

Check the detailed algorithm in the definition of TagEncoding::Niche.
This is only applied when the untagged_variant is contained in the niche_variants wasting one value from the niche range.

Undoubtedly this complicates the codegen, but it should not have a large performance penalty.
It adds one arithmetic instruction in the general case and no additional branch instruction.

I'm not totally sure if the complexity is justified, considering the use case is rare.

r? @the8472

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 14, 2024
@rustbot
Copy link
Collaborator

rustbot commented Oct 14, 2024

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rust-log-analyzer

This comment has been minimized.

@adwinwhite adwinwhite force-pushed the niche-layout-not-depend-on-ordering branch from 1af0330 to 7af5de3 Compare October 14, 2024 13:44
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#16 2.701 Building wheels for collected packages: reuse
#16 2.702   Building wheel for reuse (pyproject.toml): started
#16 2.948   Building wheel for reuse (pyproject.toml): finished with status 'done'
#16 2.949   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132720 sha256=026f3bb0f1aa8090b861fd0a0939cb1a782396d84c8aab7875096557d637a0f6
#16 2.950   Stored in directory: /tmp/pip-ephem-wheel-cache-1szk5pft/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#16 2.952 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#16 3.352 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#16 3.353 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#16 DONE 3.4s
---
    Checking rustc_codegen_cranelift v0.1.0 (/checkout/compiler/rustc_codegen_cranelift)
error[E0425]: cannot find value `relative_discr` in this scope
   --> src/discriminant.rs:168:53
    |
168 |                 let tagged_discr = clif_intcast(fx, relative_discr, cast_to, false);

error[E0308]: `if` and `else` have incompatible types
  --> src/discriminant.rs:66:21
   |
   |
61 |                   let discr = if niche_variants.contains(&untagged_variant) {
62 | |                     let adj_untagged_idx =
62 | |                     let adj_untagged_idx =
63 | |                         untagged_variant.index() - niche_variants.start().index();
64 | |                     (adj_idx + discr_len - adj_untagged_idx) % discr_len - 1;
   | |                     |                                                       |
   | |                     |                                                       help: consider removing this semicolon
   | |                     expected because of this
65 | |                 } else {
65 | |                 } else {
66 | |                     adj_idx
   | |                     ^^^^^^^ expected `()`, found `usize`
67 | |                 };
   | |_________________- `if` and `else` have incompatible types
error[E0308]: mismatched types
   --> src/discriminant.rs:161:72
    |
    |
161 |                 let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start);
    |                                ----------------                        ^^^^^^^^^^^ expected `i128`, found `Value`
    |                                arguments to this function are incorrect
    |
note: function defined here
   --> src/common.rs:118:15
   --> src/common.rs:118:15
    |
118 | pub(crate) fn codegen_icmp_imm(
    |               ^^^^^^^^^^^^^^^^
...
122 |     rhs: i128,
    |     ---------

error[E0277]: the trait bound `i128: From<usize>` is not satisfied
    |
    |
174 |                         i128::from(discr_len - 1),
    |                         ^^^^ the trait `From<usize>` is not implemented for `i128`
    = help: the following other types implement trait `From<T>`:
    = help: the following other types implement trait `From<T>`:
              `i128` implements `From<&FluentNumber>`
              `i128` implements `From<FluentNumber>`
              `i128` implements `From<bool>`
              `i128` implements `From<deranged::RangedI128<MIN, MAX>>`
              `i128` implements `From<i16>`
              `i128` implements `From<i32>`
              `i128` implements `From<i64>`
              `i128` implements `From<i8>`


error[E0277]: the trait bound `i128: From<usize>` is not satisfied
    |
    |
223 |                         i128::from(discr_len - 1),
    |                         ^^^^ the trait `From<usize>` is not implemented for `i128`
    = help: the following other types implement trait `From<T>`:
    = help: the following other types implement trait `From<T>`:
              `i128` implements `From<&FluentNumber>`
              `i128` implements `From<FluentNumber>`
              `i128` implements `From<bool>`
              `i128` implements `From<deranged::RangedI128<MIN, MAX>>`
              `i128` implements `From<i16>`
              `i128` implements `From<i32>`
              `i128` implements `From<i64>`
              `i128` implements `From<i8>`

Some errors have detailed explanations: E0277, E0308, E0425.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `rustc_codegen_cranelift` (lib) due to 5 previous errors

@adwinwhite adwinwhite marked this pull request as draft October 14, 2024 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enum size depends on ordering of members
4 participants