Skip to content

windows: expose cfg for 64-bit time_t#5062

Open
dybucc wants to merge 1 commit into
rust-lang:mainfrom
dybucc:fix-windows-timet-cfg
Open

windows: expose cfg for 64-bit time_t#5062
dybucc wants to merge 1 commit into
rust-lang:mainfrom
dybucc:fix-windows-timet-cfg

Conversation

@dybucc

@dybucc dybucc commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Description

Under Windows GNU x86, time_t doesn't have the right size and alignment. This is a backwards-incompatible change, so for folks to experiment on stable, a cfg has been exposed to allow exposing a 64-bit time_t instead. Tests don't fail because we still skip time_t and records containing some value of such type whenever we're under this target platform/environment.

In #5059, we address the issue with routines involving time_t values by making them link to their 32-bit symbols on that platform/environment.

This should allow not breaking existing code (even though incorrect,) while still allowing new code to experiment with correct size/alignment for time_t values. The cfg tries to follow the new practices introduced in #4977.

An additional job was not added to the test matrix in CI because it was instead introduced as part of the tests in ci/run.sh that run only under 32-bit machine word and GNU-hosted targets.

Sources

None, if any the same as #5032 as this stems from it.

Checklist

  • Relevant tests in libc-test/semver have been updated
  • No placeholder or unstable values like *LAST or *MAX are included (see #3131)
  • Tested locally (cd libc-test && cargo test --target mytarget); especially relevant for platforms that may not be checked in CI

@rustbot label +stable-nominated

@rustbot rustbot added A-CI Area: CI-related items S-waiting-on-review stable-nominated This PR should be considered for cherry-pick to libc's stable release branch labels Apr 16, 2026
@dybucc dybucc mentioned this pull request Apr 16, 2026
3 tasks
@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 08f37e4 to 137efa8 Compare April 18, 2026 06:38
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 1c220d3 to 035eff8 Compare April 28, 2026 15:34
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 035eff8 to fafb602 Compare April 29, 2026 13:41
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from fafb602 to 622c7d8 Compare May 2, 2026 07:33
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 622c7d8 to bbd9d2c Compare May 5, 2026 12:48
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from bbd9d2c to 099bc00 Compare May 6, 2026 06:56
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 099bc00 to 065ec82 Compare May 7, 2026 14:37
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 065ec82 to 0d9de25 Compare May 13, 2026 07:00
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 0d9de25 to 7d899e8 Compare May 14, 2026 07:00
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 7d899e8 to b9a9de4 Compare May 15, 2026 09:17
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from b9a9de4 to ae099ec Compare May 15, 2026 12:47
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from ae099ec to dd02b72 Compare May 17, 2026 14:41
@dybucc

dybucc commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@rustbot ready

Comment thread build.rs Outdated
// Corresponds to `_FILE_OFFSET_BITS=64` in glibc
"gnu_file_offset_bits64",
// Corresponds to `_TIME_BITS=64` in glibc
// Corresponds to `_TIME_BITS=64` in glibc. `_USE_32BIT_TIME_T` in Windows.

@tgross35 tgross35 Jun 26, 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.

It shouldn't, right? That should only be applicable on win-msvc, and on MSVC targets time_t is already always 64 bits. I believe this should only affect i686-win-gnu, which uses the same _TIME_BITS=64.

View changes since the review

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.

That's not right. My comment is also wrong. Let me clarify.

In both MSVC and MinGW headers time_t is always 64-bit. In both of them one can use _USE_32BIT_TIME_T to get a 32-bits time_t. The _TIME_BITS feature test macro is sort of supported on MinGW. Though it's useless. It's only checked before checking that _USE_32BIT_TIME_T is defined [1].

What we expose is wrong. This PR is more of a bugfix on our side.

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.

What do you mean by useless? It appears to control what time_t is via _USE_32BIT_TIME_T https://github.com/mingw-w64/mingw-w64/blob/31bd54ab7d5fe03c67ed2bb1a57e531b9c7f8cc4/mingw-w64-headers/crt/time.h#L52-L59

@dybucc dybucc Jun 26, 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.

I'm referring to _TIME_BITS.

Comment thread libc-test/build.rs Outdated
Comment on lines +787 to +794
(gnu && i686).then(|| {
env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS")
.map_err(|_| ())
.and_then(|val| val.parse::<usize>().map_err(|_| ()))
.and_then(|v| (v == 64).then_some("gnu_time_bits64").ok_or(()))
.map(|op| _ = cfg.cfg(op, None))
.unwrap_or_default()
});

@tgross35 tgross35 Jun 26, 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.

There's no need to use then when there is no return value, if is more clear. But this can be simplified anyway:

if let Ok(tb) = env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS") {
    assert!(
        tb == "64" || tb == "32",
        "Invalid value for libc_unstable_gnu_time_bits. Must be 32, 64 or unset"
    );

    if gnu && i686 && tb == "64" {
        cfg.cfg("gnu_time_bits64", None);
    }
}

Do we need a cfg.define here? The other instances of CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS have one.

View changes since the review

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.

We don't. Windows with GNU (under MinGW) has the same behavior as MSVC. It exposes a 64-bit time_t by default. The feature test macro to use a 32-bit time_t is also the same as in MSVC.

Recall this cfg is meant as a bugfix to faulty bindings in the libc crate. time_t is currently 32-bits in main when in Windows x86 with GNU. This doesn't match MinGW headers. We just so happen to be "reusing" gnu_time_bits64.

_TIME_BITS is incompatible with _USE_32BIT_TIME_T in MinGW. The former is sort of supported. They check it's not defined when checking for the latter [1].

Comment thread build.rs Outdated
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from f4ccd58 to 4e34e51 Compare June 26, 2026 08:01
@rustbot

This comment has been minimized.

dybucc added a commit to dybucc/libc that referenced this pull request Jun 26, 2026
Adds a test to ensure the changes in rust-lang#5062 are correct. The test ensures
the wrong definition is kept on stable. It will use the right bit width
in the following cases.

- Under targets other than x86 with GNU.
- If the `gnu_time_bits64` `cfg` is set.
@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from c268685 to 647bde5 Compare June 26, 2026 09:20
@rustbot

This comment has been minimized.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 4bc0c62 to 0247682 Compare June 26, 2026 09:27
@dybucc

dybucc commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Seems done. We don't check for time_t on Windows x86 GNU if gnu_time_bits64 is not set.

@rustbot ready

dybucc added a commit to dybucc/libc that referenced this pull request Jun 26, 2026
Adds a test to ensure the changes in rust-lang#5062 are correct. The test ensures
the wrong definition is kept on stable. It will use the right bit width
in the following cases.

- Under targets other than x86 with GNU.
- If the `gnu_time_bits64` `cfg` is set.
@dybucc dybucc force-pushed the fix-windows-timet-cfg branch 4 times, most recently from c47fb60 to 4a1d9ac Compare June 27, 2026 15:00
@rustbot

rustbot commented Jun 27, 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.

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 4dbde24 to 50299b1 Compare June 27, 2026 15:36
@dybucc

dybucc commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

I had to add a cfg in the libc-test build script. The Windows test added on #5059 needs it with the changes in this PR.

I'm not sure if this is the way to go.

Comment thread libc-test/build.rs Outdated
Comment on lines +791 to +811
let redirect_time_t = if gnu && i686 {
if let Ok(v) = env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS") {
assert_matches!(
v.as_str(),
"32" | "64",
"Invalid value for `libc_unstable_gnu_time_bits`. Must be 32, 64 or unset."
);

if v == "64" {
cfg.cfg("gnu_time_bits64", None);
println!("cargo::rustc-cfg=gnu_time_bits64");
true
} else {
false
}
} else {
false
}
} else {
false
};

@tgross35 tgross35 Jun 27, 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.

Could replace the false chaining with:

let tb_env = env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS");
let redirect_time_t = match tb_env {
    Ok(tb) if tb == "64" => true,
    Ok(tb) if tb == "32" => false,
    Ok(x) => panic!("Invalid value`{x}` for ... "),
    Err(_) => false,
};

println!("rustc-check-cfg...");
if redirect_time_t {
    println!(...);
    cfg.cfg(...);
}

A name like win32_time64 would be more descriptive than redirect_time_t.

View changes since the review

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.

Done.

Comment thread build.rs Outdated
Comment on lines 27 to 29
// Corresponds to `_TIME_BITS=64` in glibc. Also used in Windows to fix
// faulty `time_t` bindings.
"gnu_time_bits64",

@tgross35 tgross35 Jun 27, 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.

Try to be more precise with wording like faulty/wrong/broken. In this case there should be nothing broken in Rust since the link name fix merged, it's just a mismatch to what users get on C. (Applies to the commit message and a few other PRs too).

Also 64-bit time_t wasn't even always an option until last year mingw-w64/mingw-w64@fe21b7e and uclibc a few years before that - libc's bindings just happen to predate that. (Even glibc and musl support didn't fully exist until ~2020.)

View changes since the review

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.

Noted.

Comment thread libc-test/build.rs Outdated
"ssize_t" if !gnu => true,
// FIXME(windows): The size and alignment of this type are incorrect
"time_t" if gnu && i686 => true,
"time_t" if gnu && i686 && !redirect_time_t => true,

@tgross35 tgross35 Jun 27, 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.

I think you may be able to delete the time_t exclusion entirely with:

if i686 && !redirect_time_t {
    cfg.define("_TIME_BITS", Some("32"));
}

View changes since the review

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.

Doesn't seem like it. It may be that the MinGW pre-defined macros target the x86_64 host even if the binary targets x86. That would make the conditional in 1 evaluate false.

Footnotes

  1. https://github.com/mingw-w64/mingw-w64/blob/master/mingw-w64-headers/crt/_mingw.h.in#L393

@dybucc dybucc force-pushed the fix-windows-timet-cfg branch 2 times, most recently from 4bcc1a0 to 618c6b8 Compare June 28, 2026 14:38
Use `gnu_time_bits64` on Windows x86 GNU to expose a 64-bit `time_t`.
`time_t` is always 64-bits on Windows. The target environment matters
not. There's a feature test macro to make it 32-bits wide. In `libc` we
expose it as 32-bits in Windows x86 GNU. This is not the same default as
in C. This `cfg` exposes the same default as in C.
@dybucc dybucc force-pushed the fix-windows-timet-cfg branch from 2838970 to fc36273 Compare June 28, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CI Area: CI-related items S-waiting-on-review stable-nominated This PR should be considered for cherry-pick to libc's stable release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants