Skip to content

Generalize Decodable impl for arrays to all types - #160111

Open
panstromek wants to merge 2 commits into
rust-lang:mainfrom
panstromek:generalize-decodable-array
Open

Generalize Decodable impl for arrays to all types#160111
panstromek wants to merge 2 commits into
rust-lang:mainfrom
panstromek:generalize-decodable-array

Conversation

@panstromek

@panstromek panstromek commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

View all comments

This is almost the only impl that is not symetric with its Encodable counterpart. I tried to find out why in the history but it looks like this impl predates most of the generic symetric ones that are in this file, so it looks like it's not intentional.

I bumped into this randomly by changing a Vec to an array in some Mir types. The error was pretty confusing and It took me a while to figure out so I think it's worth generalizing this for somebody else in the future, even though it's technically not necessary at the moment.

We piggyback off of SmallVec impl to avoid adding a Default bound or MaybeUninit unsafe dance. This moves the assert from the begining to the end of the loop. We use array::from_fn

@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 Jul 29, 2026
@rustbot

rustbot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

r? @mu001999

rustbot has assigned @mu001999.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 74 candidates
  • Random selection from 17 candidates

@rust-log-analyzer

This comment has been minimized.

@panstromek
panstromek force-pushed the generalize-decodable-array branch from 8ee8971 to 98eff47 Compare July 29, 2026 05:51
@Kobzol

Kobzol commented Jul 29, 2026

Copy link
Copy Markdown
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 29, 2026
Generalize Decodable impl for arrays to all types
@rust-bors

rust-bors Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 8676bf1 (8676bf14a48b8e3b819b9a4f4e2afaeff884ac20)
Base parent: 701a651 (701a6513a48eac30d49110ba06187648b7553622)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (8676bf1): comparison URL.

Overall result: ❌ regressions - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.3% [0.2%, 0.3%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -3.9%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-3.9% [-3.9%, -3.9%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -3.9% [-3.9%, -3.9%] 1

Cycles

Results (secondary 1.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
4.0% [2.1%, 5.2%] 4
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.8% [-3.4%, -2.2%] 2
All ❌✅ (primary) - - 0

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 491.747s -> 489.069s (-0.54%)
Artifact size: 390.11 MiB -> 390.13 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
@panstromek

Copy link
Copy Markdown
Contributor Author

Interesting. This is actually quite negative. The results are overwhelmingly red if you look at non-relevant results.

I guess the early assert was there to avoid bound checks in the loop?

Note: I found only one usage of this impl, which is for [u8; 32] field in SourceFileHash. That doesn't seem like it's used very much tbh.

Comment thread compiler/rustc_serialize/src/serialize.rs Outdated
@panstromek
panstromek force-pushed the generalize-decodable-array branch from 98eff47 to 95a4f1c Compare July 29, 2026 14:38
@panstromek

Copy link
Copy Markdown
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
rust-bors Bot pushed a commit that referenced this pull request Jul 29, 2026
Generalize Decodable impl for arrays to all types
@mu001999 mu001999 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 29, 2026
impl<D: Decoder, const N: usize> Decodable<D> for [u8; N] {
fn decode(d: &mut D) -> [u8; N] {
impl<D: Decoder, T: Decodable<D>, const N: usize> Decodable<D> for [T; N] {
fn decode(d: &mut D) -> [T; N] {
let len = d.read_usize();
assert!(len == N);

@cjgillot cjgillot Jul 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we go further stop encoding and decoding len?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hm, I'm not sure, can we? I thought it's there for some reason, like compatibility with other list types. But I don't really know the rules of the serialization system.

I will try it out. This is called a few thousands times in many benchmarks, so it might have an impact.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you encode [T;2] and then [T;3] after it, it wouldn't be distinguishable from encoding [T;3] and then [T;2] after it, right? This is an issue for stable hashing, and it's why we also hash the length there.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is an issue for stable hashing, and it's why we also hash the length there.

Is it? It's equivalent to confusing (T, T) and (T, T, T). The type system prevents it. If we ever have such a case, we will have some kind of enum discriminant that changed somewhere.

@mu001999 mu001999 Jul 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or could we downgrade this to debug_assert at least?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is an issue for stable hashing, and it's why we also hash the length there.

Is it? It's equivalent to confusing (T, T) and (T, T, T). The type system prevents it. If we ever have such a case, we will have some kind of enum discriminant that changed somewhere.

In stable hashing, the problem is that if in one compilation you hash [1, 2, 3], [4, 5], and in another [1, 2], [3, 4, 5], those would get the same hash, but clearly it's different compilation data.

I'm not sure if that's a potential problem also in decoding though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Where in the code could this happen? I only see Encodable/Decodable derived on types, and we know the exact length on those. Is there a place where we type erase something and decode blindly? But we would get some some type information from somewhere anyway, I suppose.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm inclined to just drop the second commit and postpone this concern for later. I feel like I don't have a good way to actually figure out whether this is a problem or not and it feels somewhat orthogonal to the original purpose of this PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm inclined to just drop the second commit

+1 to this

@rust-bors

rust-bors Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 7b88eb6 (7b88eb6604047572f5cc38c985aa9958563f6846)
Base parent: d366396 (d3663963ca08f465d01d283a7199778902623bb9)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (7b88eb6): comparison URL.

Overall result: ✅ improvements - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.8% [-2.8%, -2.8%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -1.2%, secondary 1.5%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.0% [0.4%, 1.7%] 4
Regressions ❌
(secondary)
1.5% [0.4%, 4.9%] 8
Improvements ✅
(primary)
-4.1% [-5.4%, -2.8%] 3
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.2% [-5.4%, 1.7%] 7

Cycles

Results (primary 0.8%, secondary 0.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.0% [0.5%, 1.4%] 7
Regressions ❌
(secondary)
1.3% [0.5%, 2.3%] 7
Improvements ✅
(primary)
-0.8% [-0.8%, -0.8%] 1
Improvements ✅
(secondary)
-1.8% [-2.5%, -0.5%] 3
All ❌✅ (primary) 0.8% [-0.8%, 1.4%] 8

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 489.658s -> 491.046s (0.28%)
Artifact size: 390.17 MiB -> 390.20 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
@panstromek

Copy link
Copy Markdown
Contributor Author

The large-workspace result is probably just return from a noise spike, but it's generally better than the first run. Let's try without encoding len.

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 29, 2026
Generalize Decodable impl for arrays to all types
@rust-bors

rust-bors Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 13951c5 (13951c57049b519431ad80dba70bebb4ce9d92ae)
Base parent: b5be620 (b5be620d5ac9824c4a6030df9fb72644ef4f459b)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (13951c5): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This perf run didn't have relevant results for this metric.

Max RSS (memory usage)

Results (primary 0.5%, secondary -1.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.5% [0.4%, 0.5%] 2
Regressions ❌
(secondary)
0.4% [0.4%, 0.4%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.9% [-3.9%, -3.9%] 1
All ❌✅ (primary) 0.5% [0.4%, 0.5%] 2

Cycles

Results (primary -0.1%, secondary -6.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.0% [0.5%, 2.1%] 4
Regressions ❌
(secondary)
1.5% [0.5%, 2.8%] 5
Improvements ✅
(primary)
-0.9% [-1.9%, -0.4%] 6
Improvements ✅
(secondary)
-9.8% [-17.6%, -0.5%] 14
All ❌✅ (primary) -0.1% [-1.9%, 2.1%] 10

Binary size

Results (primary -0.1%, secondary -0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.1% [-0.1%, -0.0%] 53
Improvements ✅
(secondary)
-0.0% [-0.1%, -0.0%] 31
All ❌✅ (primary) -0.1% [-0.1%, -0.0%] 53

Bootstrap: 489.76s -> 488.544s (-0.25%)
Artifact size: 390.94 MiB -> 390.15 MiB (-0.20%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 29, 2026
@panstromek

Copy link
Copy Markdown
Contributor Author

Not encoding len makes the metadata a tiny bit smaller which is cool, but otherwise there's not much impact. Let's decide based on how the discussion above settles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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.

7 participants