Skip to content

-Ctarget-feature=+crt-static always wins over -crt-static regardless of order (should be last-wins) #154388

@will-j-wright

Description

@will-j-wright

When running:

rustc --target x86_64-unknown-linux-musl -Ctarget-feature=+crt-static -Ctarget-feature=-crt-static --print cfg | grep crt

I expected to see this happen: No output, because -crt-static appears last and should override +crt-static, consistent with how other -C flags work (last wins). For example, -Cforce-unwind-tables=no -Cforce-unwind-tables=yes correctly produces yes.

Instead, this happened: target_feature="crt-static" is still present — +crt-static always wins regardless of order.


The root cause is in session.rs:374-377:

let found_negative = requested_features.clone().any(|r| r == "-crt-static");
let found_positive = requested_features.clone().any(|r| r == "+crt-static");

if found_positive || found_negative {
    found_positive
}

This uses any() which is order-independent. This means if +crt-static appears anywhere in the features, found_positive is true and the function returns true. Compare with other -C flags like force-unwind-tables which use parse_opt_bool with *slot = Some(value), where each occurrence overwrites the previous (last wins).

This makes it impossible to override +crt-static from .cargo/config.toml via Cargo's --config mechanism, which appends flags rather than replacing them. This is a blocker for use cases like AddressSanitizer where ASAN requires -crt-static but the project's base config sets +crt-static for all musl builds.

Suggested fix: Replace the any() logic with iteration that tracks the last occurrence:

let mut crt_static = None;
for feature in requested_features {
    match feature {
        "+crt-static" => crt_static = Some(true),
        "-crt-static" => crt_static = Some(false),
        _ => {}
    }
}

if let Some(val) = crt_static {
    val
} else if /* proc-macro check */ {
    false
} else {
    self.target.crt_static_default
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions