Skip to content

Move hir::Params from Body of functions to FnDecl - #163758

Open
JonathanBrouwer wants to merge 13 commits into
rust-lang:mainfrom
JonathanBrouwer:param
Open

JonathanBrouwer wants to merge 13 commits into
rust-lang:mainfrom
JonathanBrouwer:param

Conversation

@JonathanBrouwer

@JonathanBrouwer JonathanBrouwer commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

View all comments

This PR implements MCP rust-lang/compiler-team#1044.
It is split up into commits, each commit passes tests, and reviewing commit by commit is therefore heavily recommended. Each commit contains a description. The first commit makes the big change, and the other commits are cleanup.

This PR causes a minor performance regression, specifically on the libc and externs benchmark:
#163758 (comment)
This is caused by that parameters on foreign functions are now assigned HIR IDs and Params are allocated for them, so slightly more work is needed.
Both of these crates are basically only foreign functions, so not very representative of an average rust program.

r? @Kivooeo

@rustbot rustbot added 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. labels Oct 4, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@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 Oct 4, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 4, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

💔 Test for be17f02 failed: CI. Failed jobs:

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 4, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: b0e36da (b0e36dabc37e5dc5550a520d05ab86f3c07ef73a)
Base parent: f48b3e6 (f48b3e61eeece268609bd920fcca1ded047db7ca)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (b0e36da): comparison URL.

Overall result: ❌✅ regressions and improvements - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never rustc-perf
@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.1% [0.1%, 0.1%] 3
Regressions ❌
(secondary)
1.8% [0.3%, 3.2%] 12
Improvements ✅
(primary)
-0.2% [-0.6%, -0.1%] 52
Improvements ✅
(secondary)
-0.3% [-0.6%, -0.0%] 56
All ❌✅ (primary) -0.2% [-0.6%, 0.1%] 55

Max RSS (memory usage)

Results (secondary 0.8%)

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)
2.3% [2.0%, 2.9%] 5
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-6.6% [-6.6%, -6.6%] 1
All ❌✅ (primary) - - 0

Cycles

Results (secondary 3.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.3% [2.2%, 6.8%] 9
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.6% [-1.6%, -1.6%] 1
All ❌✅ (primary) - - 0

Binary size

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

Bootstrap: 490.122s -> 491.234s (0.23%)
Artifact size: 408.65 MiB -> 409.03 MiB (0.09%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Oct 4, 2026
@rust-bors

This comment has been minimized.

@JonathanBrouwer
JonathanBrouwer force-pushed the param branch 3 times, most recently from 10e9505 to 67a82db Compare October 6, 2026 08:27
@rustbot rustbot added the A-attributes Area: Attributes (`#[…]`, `#![…]`) label Oct 6, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Member 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 Oct 6, 2026
@JonathanBrouwer
JonathanBrouwer force-pushed the param branch 2 times, most recently from 1ef0e8b to 6d88206 Compare November 5, 2026 12:17
This commit is by far the biggest one, and achieves the goal of this PR but leaves the code ugly in a lot of places. The next commits will be a lot of cleanup.

/// A `hir::Param` without a `ty`, which exists after the `Param` is lowered, before the corresponding `ty` is lowered.
#[derive(Clone, Debug)]
pub(crate) struct PartialParam<'hir> {

@JonathanBrouwer JonathanBrouwer Nov 5, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This PR introduces the PartialParam attempt in order to keep the control flow in this crate as much as possible the same, in an aim to keep things reviewable.

It will take some more refactoring to disentangle lowering Body with lowering the Param, mostly because of closures.
I'm aiming to do this in a follow-up PR, since this PR is already big enough.

View changes since the review

/// This variant is not always used to represent inference types, sometimes
/// [`GenericArg::Infer`] is used instead.
Infer(Unambig),
/// Only used as the type of C-variadic (...) parameters

@JonathanBrouwer JonathanBrouwer Nov 5, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This PR introduces the hir::TyKind::CVarArgs, this corresponds to ast::TyKind::CVargs.
Previously CVarArgs parameters were represented by a hir::Param, but NOT by a corresponding entry in FnDecl::inputs, causing the lists to be differing lengths. This is confusing and this PR fixes this.

View changes since the review

}

fn visit_body(&mut self, b: &rustc_hir::Body<'tcx>) -> Self::Result {
if let Some(decl) = self.tcx.hir_fn_decl_by_hir_id(self.tcx.hir_body_owner(b.id())) {

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A few visitors need to be adjusted to now also visit the fn_decl.
I couldn't really find a cleaner solution than this

View changes since the review

let input_tys = decl
.inputs
.iter()
.filter(|p| !matches!(p.ty.kind, hir::TyKind::CVarArgs))

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This filter will happen in a few places, previously CVarArgs were inherently ignored because they did not have an entry in decl.inputs, now they do (more consistent0 and we explicitly filter them out to keep the logic the same

View changes since the review

fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
// Ignore patterns in foreign items for now
// FIXME(#33995) remove this check
if let Node::ForeignItem(_) = cx

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removing this if would fix a bug, but this is a behaviour change so I would like to do that in a follow-up PR
#33995

View changes since the review

if let Some(hir_id) = hir_id
&& let hir::Node::Param(param) = self.tcx.hir_node(hir_id)
&& let Some(decl) = self.tcx.parent_hir_node(hir_id).fn_decl()
&& let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a weird hack to find the param ty from a param, we no longer need to do this :)

View changes since the review

impl Bar {
//@ has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \
// "const F: fn(&(dyn ToString + 'static))"
// "const F: fn(_: &(dyn ToString + 'static))"

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Previously rustdoc always filtered out wildcards, after this PR it matches what the user wrote doen, which I think is prettier (and makes the code easier :p)

View changes since the review

|
LL | fn dstfn(src: i32, dst: err);
| ^^^^^ ---
| ^^^^^ --------

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A lot of spans changed to show the entire parameter (incl ty) rather than just the name, I think this is prettier (and again, easier to program :p)

View changes since the review

hir-stats ForeignItemId 4 (NN.N%) 1 4
hir-stats ----------------------------------------------------------------
hir-stats Total 8_592 172
hir-stats Total 8_768 176

@JonathanBrouwer JonathanBrouwer Nov 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This got bigger because we now allocate Param for functions without bodies. This is probably also related to the small perf regression

View changes since the review

@rustbot

rustbot commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

HIR ty lowering was modified

cc @fmease

Changes to the size of AST and/or HIR nodes.

cc @nnethercote

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann

Some changes occurred in need_type_info.rs

cc @lcnr

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@ada4a Would you check the clippy diff for me?
I think you volunteered to do this at EuroRust :3

@Kivooeo

Kivooeo commented Nov 6, 2026

Copy link
Copy Markdown
Member

peaceful friday evening

me rn:

skeleton-fall (1)

jokes aside, just give me few more days, i'll review this eventually

@ada4a

ada4a commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

@ada4a Would you check the clippy diff for me? I think you volunteered to do this at EuroRust :3

I've been low on energy lately due to the move.. I'll try to get to this during this/next weekend^^

@Kivooeo

Kivooeo commented Nov 6, 2026

Copy link
Copy Markdown
Member

What this blocked on (asking because of s-blocked label)

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

This was blocked on the MCP being accepted, it now is :)

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@nnethercote would you like to take a look at this PR?
I think the perf regression from #163758 (comment) is just from doing more work, since we allocate more Params. This also explains the input-stats changes

@Kivooeo Kivooeo left a comment •

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.

Diagnostics for this code will change, and not in a better way

struct NeedsCopy<T: Copy>(T);
extern "C" {
    fn f(x: i32, ...) -> NeedsCopy<String>;
}

Previously it gave this:

error[E0277]: the trait bound `String: Copy` is not satisfied
 --> test.rs:3:26
  |
3 |     fn f(x: i32, ...) -> NeedsCopy<String>;
  |                          ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`

now it gives this:

error[E0277]: the trait bound `String: Copy` is not satisfied
 --> test.rs:3:18
  |
3 |     fn f(x: i32, ...) -> NeedsCopy<String>;
  |                  ^^^ the trait `Copy` is not implemented for `String`

View changes since this review

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

Fixed it + added a regression test.
Thanks for catching that! The root cause here is that c-variadics are just handled quite poorly in the THIR, we should improve that but I will not do that in this PR

}

#[derive(Debug, Copy, Clone)]
enum DiscardParams {

@Kivooeo Kivooeo Nov 7, 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.

It was deleted but there is a comment still referencing to it

/// `discard_params`: if `DiscardParams::Yes`, the parameters are lowered and then discarded. Set this to `DiscardParams::Yes`

View changes since the review

}

impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
fn visit_fn_decl(&mut self, _fd: &'tcx FnDecl<'tcx>) -> Self::Result {}

@Kivooeo Kivooeo Nov 7, 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.

I see what are you trying to do here, but it feel like you forget to update visit_nested_body to walk the pattern params, so currently it breaks (another thing that doesn't covers in tests, fun)

mod hidden {
    pub struct Record { secret: u8 }
}

fn leak(hidden::Record { secret }: hidden::Record) -> u8 {
    secret
}

This code is currently correctly rejects on main, but compiles under this PR

View changes since the review

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.

Also, please when you are going fix this, make sure this also rejects correctly

mod hidden {
    pub struct Record { secret: u8 }
}

fn f() -> [u8; { let _ = hidden::Record { secret: 1 }; 0 }] {
    []
}

cannot_remove: FxHashSet::default(),
desugar_binding_spans: Vec::new(),
};
finder.visit_fn_decl(tcx.hir_fn_decl(self.mir_hir_id()));

@Kivooeo Kivooeo Nov 7, 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.

This will 🧊

struct NonCopy(u8);

const C: () = {
    let &moved = &NonCopy(0);
};

View changes since the review

This branch has not been deployed

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) perf-regression Performance regression. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants