Skip to content

Conversation

@dianne
Copy link
Contributor

@dianne dianne commented Sep 27, 2025

When lowering non-overloaded indexing operations to MIR, this uses the temporary lifetime of the index expression for the index temporary, rather than applying the temporary lifetime of the indexing operation as a whole to the index.

For example, in

let x = &xs[i];

previously, the temporary containing the result of evaluating i would live until the end of the block due to the indexing operation being lifetime-extended. Under this PR, the index temporary only lives to the end of the let statement because it uses the more precise temporary lifetime of the index expression.

I don't think this will affect semantics in an observable way, but the more precise StorageDead placement may slightly improve analysis/codegen performance.

r? mir

When lowering non-overloaded indexing operations to MIR, this uses the
temporary lifetime of the index expression for the index, rather than
applying the temporary lifetime of the indexing operation as a whole to
the index.
@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 Sep 27, 2025
@traviscross traviscross added the I-lang-radar Items that are on lang's radar and will need eventual work or consideration. label Sep 27, 2025
@dianne
Copy link
Contributor Author

dianne commented Oct 23, 2025

Let's see if this actually helps with perf on its own. My hope is that it accounts for the regression in #146098, but there's a chance it does something alone. @bors try @rust-timer queue

Also, since the exact lifetime used for the index is a bit subtle, I feel I should justify it. I think this still doesn't quite match the reference spec: since the index isn't a place expression context, I think destructors.scope.operands would apply rather than using the index expression's temporary scope, but this doesn't quite work for MIR semantics / implementation detail reasons. Per that rule, as I understand it, the temporary holding the index would be associated with the indexing operator expression and dropped after evaluating it. However, the Place representing xs[i] holds the temporary's Local in it, so the temporary holding i has to live until xs[i] is referenced/used, e.g. by Rvalue::Ref or Rvalue::Use from a parent expression/statement. Using the temporary scope of the indexed expression should allow the temporary to live long enough for that, I think: no expressions corresponding to PlaceElems introduce terminating scopes, and if they did, that would have caused problems for the current implementation that uses the indexing operator expression's temporary scope. Since this only applies to built-in array/slice indexing, the temporary living a bit longer than specified shouldn't be observable, I think.

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Oct 23, 2025
Do not lifetime-extend array/slice indices
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 23, 2025
@rust-timer

This comment has been minimized.

@dianne
Copy link
Contributor Author

dianne commented Oct 23, 2025

Writing this in a separate message rather than editing so I don't re-request the perf run again (oops): a more precise (but more involved) alternative to this could be to add a scope argument to Builder::expr_as_place, to be used for indices' scopes. That way the index could be dropped right after evaluating whichever expression/statement references/uses the xs[i] place.

@rust-bors
Copy link

rust-bors bot commented Oct 23, 2025

☀️ Try build successful (CI)
Build commit: 566fcb8 (566fcb89f4c9284b4072877aea113e03b1bc065e, parent: 6244effd0372d5d88fc859d3bf17ce1efcc2c9ec)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (566fcb8): comparison URL.

Overall result: ✅ improvements - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@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)
-1.4% [-1.4%, -1.4%] 1
Improvements ✅
(secondary)
-1.4% [-1.4%, -1.4%] 1
All ❌✅ (primary) -1.4% [-1.4%, -1.4%] 1

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

Results (secondary -3.2%)

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
Improvements ✅
(secondary)
-3.2% [-3.2%, -3.2%] 1
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 471.983s -> 473.334s (0.29%)
Artifact size: 390.70 MiB -> 390.73 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-lang-radar Items that are on lang's radar and will need eventual work or consideration. 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.

5 participants