Skip to content

Add Complex type and repr(complex) - #158885

Open
folkertdev wants to merge 12 commits into
rust-lang:mainfrom
folkertdev:complex-layout
Open

Add Complex type and repr(complex)#158885
folkertdev wants to merge 12 commits into
rust-lang:mainfrom
folkertdev:complex-layout

Conversation

@folkertdev

@folkertdev folkertdev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

View all comments

tracking issue: #154023

See also #t-compiler > representing `_Complex`. The RFC states that the Complex type should match the ABI of _Complex in C, but provides little detail on how to actually achieve this. We concluded that repr(complex) is probably the best approach. Like clang, that means we "desugar" the representation early: _Complex is not natively represented in LLVM IR.

I've derived the ABI from clang for 28 targets, a decent sample of what we actually support. For now I'm only actually testing x86_64 because (as you'll see) updating the tests is quite labor-intensive. If we're happy with this direction I can fill more of them in, likely in a separate PR.

The libs side of the type is very bare-bones: I'm not as interested in that part. Others can fill in the various instances, methods, write tests for those, and improve the docs.

r? workingjubilee

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` 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. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 6, 2026
@rustbot

rustbot commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@folkertdev folkertdev Jul 6, 2026

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.

Commit e4c802f shows how our LLVM IR representation differs from clang. For instance instead of <2 x float> we just use double, and sometimes we pass { double, double} instead of two separate double arguments.

Based on what I know that is perfectly compatible on an ABI-level, it's just textually different from clang.

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.

Usually yes.

@mejrs mejrs left a comment

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.

Please also add #[repr(complex)] to tests/ui/attributes/attr-on-mac-call.rs

View changes since this review

Comment thread compiler/rustc_attr_parsing/src/attributes/repr.rs
Comment thread tests/ui/feature-gates/feature-gate-repr-complex.rs Outdated

@teor2345 teor2345 left a comment

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.

Looks good to me!

View changes since this review

@bjorn3

bjorn3 commented Jul 6, 2026

Copy link
Copy Markdown
Member

Is it me or is the callconv implementation missing? I don't see any users of fn is_complex().

@rust-log-analyzer

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
Contributor Author

Is it me or is the callconv implementation missing? I don't see any users of fn is_complex().

For x86_64 we only need custom behavior for f80. I've not yet implemented a target where it is needed, and I'd kind of prefer to do that in a follow-up

use FfiResult::*;

if !def.repr().c() && !def.repr().transparent() {
if !def.repr().c() && !def.repr().transparent() && !def.repr().complex() {

@asquared31415 asquared31415 Jul 6, 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.

This likely needs some work, for example Complex<{integer}> or even weirder types like Complex<String> (if that's even allowed by the compiler) should not be considered FFI safe. Easily done in a followup however.

View changes since the review

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.

Actually Complex<{integer}> might be de-facto fine under GCC and Clang, I'm not certain. It's a non-standard C extension though, so not sure what we want to do about that.

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 recommend we err conservatively and treat it as nonsense for now until anyone asks for it.

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.

Right, takes some more logic but we now only accept (transparently wrapped) float types, anything else triggers improper_ctypes.

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.

btw it is my intention to make Complex<{integer}> just be abi-compatible in practice, but whether we actually guarantee it can be discussed later.

AndyGauge added a commit to AndyGauge/rust-reviewer that referenced this pull request Jul 6, 2026
Part 18: runs rust-lang/rust#158885 (Add Complex type / repr(complex), a novel
feature) through the full pipeline. Critic emits 26 comments; base judge keeps 6
(6 accept / 20 reject). The 6 survivors are a real maintainer review; the rejects
expose a NEW failure mode distinct from Part 17's knowledge blind spot — grounding
failures, where the critic asks for what the diff already contains because it's
pattern-matching the form of a review, not reading the hunk. Argues the judge's
accept rate (8/12 cookbook vs 6/26 here) is a distribution meter: an unlabeled
readout of how far out of depth the critic is on a given PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@folkertdev
folkertdev force-pushed the complex-layout branch 2 times, most recently from 7300c0a to a63e0f1 Compare July 7, 2026 12:21
Comment thread compiler/rustc_attr_parsing/src/attributes/repr.rs
Comment on lines +1557 to +1558
// repr(complex) is internal, so this check is not as thorough as we'd require if it were
// user-facing.

@folkertdev folkertdev Jul 7, 2026

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.

Lmk if we should be more thorough here, but given that we never want to stabilize repr(complex), only Complex<T>, this seems (more than) adequate.

View changes since the review

use FfiResult::*;

if !def.repr().c() && !def.repr().transparent() {
if !def.repr().c() && !def.repr().transparent() && !def.repr().complex() {

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.

Right, takes some more logic but we now only accept (transparently wrapped) float types, anything else triggers improper_ctypes.

Comment on lines +110 to +113
#[repr(complex)]
//~^ ERROR attribute cannot be used on macro calls
//~| ERROR `repr(complex)` is experimental
unreachable!();

@folkertdev folkertdev Jul 7, 2026

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.

added this, it's already an error because there is no compatibility concern

View changes since the review

Comment thread tests/ui/feature-gates/feature-gate-repr-complex.rs Outdated
@rust-log-analyzer

This comment has been minimized.

@mejrs mejrs left a comment

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.

The attribute part of this looks good to me.

View changes since this review

@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdev marked this pull request as ready for review July 7, 2026 16:13
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 7, 2026
@rustbot

rustbot commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

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

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_hir/src/attrs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 7, 2026
@rust-bors

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

This comment has been minimized.

@folkertdev folkertdev added the F-complex_numbers `#![feature(complex_numbers)]` label Jul 26, 2026
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

rustbot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_attr_ir

cc @jdonszelmann, @JonathanBrouwer

@rustbot

rustbot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Comment thread compiler/rustc_abi/src/layout/ty.rs Outdated

@workingjubilee workingjubilee 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.

I don't know how an "r" got into this comment.

View changes since this review

)
.emit();
}
cx.check_target("(complex)", &AllowedTargets::AllowList(&[Allow(Target::Struct)]));

@workingjubilee workingjubilee Aug 12, 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.

...hm.

...What happens if I put in repr(simd, complex), or repr(C, complex)?

We don't need to make this specifically a repr attribute.

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.

Yeah maybe a lang item is sufficient actually. Then the type could just be repr(C) and that would do the right thing for like Complex<String> etc.

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.

Yes, if you find that impl to work out similar to this then that would also be good.

Comment on lines +7 to +9
pub re: T,
/// The imaginary component.
pub im: T,

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.

Huh, odd. I kind of would expect r and i or real and imaginary.

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.

There might be some value in matching the C function names real and imag, but I don't personally think it's compelling:
https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Complex-Data-Types.html

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 just following the RFC here, libs can re-litigate it later

Comment on lines +5 to +10
pub struct Complex<T> {
/// The real component.
pub re: T,
/// The imaginary component.
pub im: T,
}

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.

Unsure if public fields is desirable here.

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.

Having to call a method just to get the real or imaginary part seems annoying

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.

Again this is just per the RFC #154023

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.

Ah, OK, I didn't notice that on my scan.

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.

Usually yes.

Comment on lines +1 to +5
// Currently we only guarantee that repr(complex) on a Complex<{float}> is ABI-compatible.
#![feature(repr_complex)]
#![feature(f16, f128)]
#![deny(improper_ctypes)]
#![crate_type = "lib"]

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.

Hmm. What sort of linting occurs with use of this in a by-reference fashion, if any?

Comment on lines +10 to +14
#[repr(C)]
//~^ ERROR conflicting representation hints
//~| WARN this was previously accepted
#[repr(complex)] //~ ERROR: `repr(complex)` is experimental
struct ConflictingRepr(u64, u64);

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.

Ah so this happens at the "multiple reprs" level, my earlier question is about specifically the "one parens, two annotations" case.

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` F-complex_numbers `#![feature(complex_numbers)]` 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. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants