Skip to content

Conversation

@kulst
Copy link
Contributor

@kulst kulst commented Jan 1, 2026

NVPTX does not support cycles in static initializers (see #146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.

  1. Calculate the strongly connected components (SCCs) of the graph.
  2. Check for cycles (more than one node in an SCC or one node that references itself).

@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 Jan 1, 2026
@kulst
Copy link
Contributor Author

kulst commented Jan 1, 2026

@rustbot label: +O-NVPTX

@rustbot rustbot added the O-NVPTX Target: the NVPTX LLVM backend for running rust on GPUs, https://llvm.org/docs/NVPTXUsage.html label Jan 1, 2026
@rust-log-analyzer

This comment has been minimized.

@kulst kulst force-pushed the check_static_initializer_acyclic branch from 10f31cc to 18143a8 Compare January 1, 2026 20:53
Copy link
Member

@workingjubilee workingjubilee left a comment

Choose a reason for hiding this comment

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

Thanks for doing this. Haven't checked the logic closely yet.

View changes since this review

@kulst
Copy link
Contributor Author

kulst commented Jan 1, 2026

Thank you for the reviews so far! I will address them over the next few days.

I am happy to receive comments and suggestions, especially since this is my first larger contribution to the compiler.

This is still an early version, but I wanted to ensure that my implementation does not negatively affect other components of the compiler. I also wanted to gather feedback on the general approach and the optimal location for this analysis within the code. I plan to add more tests and documentation as well.

On that note, would documenting this restriction inside the target description be sufficient? Is there a place to document nonconformity in general?

Copy link
Member

@workingjubilee workingjubilee left a comment

Choose a reason for hiding this comment

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

Yes, I think that putting it in the platform support documentation would be fine. Or at least, I'm not aware of a better place at the moment.

View changes since this review

@workingjubilee workingjubilee changed the title Ensure that static initializers are acyclic for targets that require this Ensure that static initializers are acyclic for NVPTX Jan 1, 2026
@kulst kulst force-pushed the check_static_initializer_acyclic branch from 18143a8 to 639e93f Compare January 3, 2026 02:59
@rustbot rustbot added the A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` label Jan 3, 2026
@rust-log-analyzer

This comment has been minimized.

@kulst kulst force-pushed the check_static_initializer_acyclic branch 7 times, most recently from 6ab2f24 to 2a1afe3 Compare January 5, 2026 19:00
@kulst kulst marked this pull request as ready for review January 5, 2026 19:02
@rustbot
Copy link
Collaborator

rustbot commented Jan 5, 2026

Some changes occurred in src/doc/rustc/src/platform-support

cc @Noratrieb

This PR modifies tests/auxiliary/minicore.rs.

cc @jieyouxu

These commits modify compiler targets.
(See the Target Tier Policy.)

These commits modify the Cargo.lock file. Unintentional changes to Cargo.lock can be introduced when switching branches and rebasing PRs.

If this was unintentional then you should revert the changes before this PR is merged.
Otherwise, you can ignore this comment.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 5, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 5, 2026

r? @nnethercote

rustbot has assigned @nnethercote.
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

@rustbot

This comment has been minimized.

@kulst
Copy link
Contributor Author

kulst commented Jan 5, 2026

I think I now have a simpler implementation. Instead of computing the graph myself, I'm using the mono item graph. Since this is the first check in rustc_monomorphize that operates on the entire graph, I added some infrastructure.
I chose not to create a separate query for the check because it only needs to be executed once. The graph is only available in collect_and_partition_mono_items, so I could not think of a scenario in which a query would be beneficial.

cc @kjetilkjeka

@nnethercote
Copy link
Contributor

cc @FractalFir, who filed #146787.

@kulst kulst force-pushed the check_static_initializer_acyclic branch from f4c3911 to 800dc45 Compare January 6, 2026 12:53
NVPTX does not support cycles in static initializers. LLVM produces an error when attempting to codegen such constructs (like self referential structs).

To not produce LLVM UB we instead emit a post-monomorphization error on
Rust side before reaching codegen.

This is achieved by analysing a subgraph of the "mono item graph" that
only contains statics:
1. Calculate the strongly connected components (SCCs) of the graph
2. Check for cycles (more than one node in a SCC or exactly one node
   which references itself)
@kulst kulst force-pushed the check_static_initializer_acyclic branch from 800dc45 to 630c759 Compare January 6, 2026 16:00
}
};
// Emit errors for all cycles
for nodes in nodes_of_sccs.iter_mut().filter(|nodes| is_cyclic(nodes)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Minor adjustment:
I now iterate directly over the SCC-grouped nodes and check for cyclicality instead of acyclicality, which makes it possible to filter.


mod statics;

pub(super) fn target_specific_checks<'tcx, 'a, 'b>(
Copy link
Member

Choose a reason for hiding this comment

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

In a way this is sort of a misnomer because target feature checks are also target-specific but they're also kinda not?

I'm not gonna stress over it.

@workingjubilee
Copy link
Member

The test looks good. I know that this is in a safe place now. The code cleaned up nicely. I have been previously assigned other PRs that add target-informed checks so I know there is at least appetite for adding similar-ish constraints.

LLVM does currently error on this case, so this is technically a "no-op" change. If it does have consequence, it will be because LLVM removed the error... which is something they have previously done, expecting frontends to handle some target-specific check instead. So the only thing this can do, as far as I can tell, is protect us from UB.

With all that in mind,

@bors r+ rollup

But this is a novel sort of check, affecting how sound, safe Rust code builds for a specific target. That is one of the things highlighted by our review policy. So despite being a no-op, I feel I should also cc @davidtwco @wesleywiser so that they know a rustc target has impaired functionality.

@bors
Copy link
Collaborator

bors commented Jan 6, 2026

📌 Commit 630c759 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jan 6, 2026
…clic, r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
bors added a commit that referenced this pull request Jan 7, 2026
…uwer

Rollup of 3 pull requests

Successful merges:

 - #150094 (`c_variadic`: provide our own `va_arg` implementation for more targets)
 - #150569 (Ensure that static initializers are acyclic for NVPTX)
 - #150668 (Unix implementation for stdio set/take/replace)

r? `@ghost`
`@rustbot` modify labels: rollup
jhpratt added a commit to jhpratt/rust that referenced this pull request Jan 8, 2026
Ensure that static initializers are acyclic for NVPTX

Commit rust-lang#147526 removed the following code and replaced it with the `AllocatorMethod`. However, its input is empty, resulting in behavior inconsistent with the previous code.

```rust
  create_wrapper_function(
      tcx,
      &cx,
      &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
      Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))),
      &[usize, usize], // size, align
      None,
      true,
      &CodegenFnAttrs::new(),
  );
  ```

  resolves rust-lang#150755
jhpratt added a commit to jhpratt/rust that referenced this pull request Jan 8, 2026
Ensure that static initializers are acyclic for NVPTX

With this, we should no longer need to turn off the default features, so we can undo rust-lang#149550.

@bjorn3 you seem to have a test setup to check if this works properly in terms of skipping all the work that should not be required -- could you test if this PR works as intended?

FWIW we could now remove `default_features` from `run_tool_check_step`. Not sure if that's worth it.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 8, 2026
…r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 8, 2026
…r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 8, 2026
…r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 8, 2026
…r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 8, 2026
…r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see rust-lang#146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
rust-bors bot added a commit that referenced this pull request Jan 8, 2026
Rollup of 11 pull requests

Successful merges:

 - #149976 (Add waker_fn and local_waker_fn to std::task)
 - #150074 (Update provider API docs)
 - #150094 (`c_variadic`: provide our own `va_arg` implementation for more targets)
 - #150164 (rustc: Fix `-Zexport-executable-symbols` on wasm)
 - #150569 (Ensure that static initializers are acyclic for NVPTX)
 - #150607 (Add amdgpu_dispatch_ptr intrinsic)
 - #150694 (./x check miri: enable check_only feature)
 - #150717 (Thread `--jobs` from `bootstrap` -> `compiletest` -> `run-make-support`)
 - #150736 (Add AtomicPtr::null)
 - #150787 (Add myself as co-maintainer for s390x-unknown-linux-musl)
 - #150789 (Fix copy-n-paste error in `vtable_for` docs)

r? @ghost
rust-bors bot added a commit that referenced this pull request Jan 8, 2026
Rollup of 10 pull requests

Successful merges:

 - #149976 (Add waker_fn and local_waker_fn to std::task)
 - #150074 (Update provider API docs)
 - #150094 (`c_variadic`: provide our own `va_arg` implementation for more targets)
 - #150164 (rustc: Fix `-Zexport-executable-symbols` on wasm)
 - #150569 (Ensure that static initializers are acyclic for NVPTX)
 - #150694 (./x check miri: enable check_only feature)
 - #150717 (Thread `--jobs` from `bootstrap` -> `compiletest` -> `run-make-support`)
 - #150736 (Add AtomicPtr::null)
 - #150787 (Add myself as co-maintainer for s390x-unknown-linux-musl)
 - #150789 (Fix copy-n-paste error in `vtable_for` docs)

r? @ghost
@rust-bors rust-bors bot merged commit 3481c0d into rust-lang:main Jan 8, 2026
11 checks passed
@rustbot rustbot added this to the 1.94.0 milestone Jan 8, 2026
rust-timer added a commit that referenced this pull request Jan 8, 2026
Rollup merge of #150569 - check_static_initializer_acyclic, r=workingjubilee

Ensure that static initializers are acyclic for NVPTX

NVPTX does not support cycles in static initializers (see #146787). LLVM produces an error when attempting to generate code for such constructs, like self-referential structs.

To avoid LLVM UB, we emit a post-monomorphization error on the Rust side before reaching codegen.

This is achieved by analyzing a subgraph of the "mono item graph" that only contains statics.
1. Calculate the strongly connected components (SCCs) of the graph.
2. Check for cycles (more than one node in an SCC or one node that references itself).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` O-NVPTX Target: the NVPTX LLVM backend for running rust on GPUs, https://llvm.org/docs/NVPTXUsage.html S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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