Skip to content

Conversation

Manishearth
Copy link
Member

This will be useful for the temporal_rs TimeZoneProvider design.

@Manishearth Manishearth requested a review from a team as a code owner August 26, 2025 23:33
Copy link

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

@@ -98,6 +98,10 @@ impl Debug for TzZoneData<'_> {
}
}

/// A way to index into ZoneInfo64 without performing string comparisons each time
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ZoneIndex(usize);
Copy link
Member

Choose a reason for hiding this comment

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

this could use a u16

/// a Copy type.
pub fn get_indexed(&'a self, index: ZoneIndex) -> Option<Zone<'a>> {
let idx = index.0;

#[expect(clippy::indexing_slicing)] // binary search
Copy link
Member

Choose a reason for hiding this comment

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

"binary search" is not correct anymore. the index type needs to state its invariants

Copy link
Member

@robertbastian robertbastian left a comment

Choose a reason for hiding this comment

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

I'm not sure I'm aligned on the goal here. The current get returns a Copy type already, so what exactly is the issue? The lifetime? This PR has the issue that the ZoneIndex is not tied to the ZoneInfo64 struct, so it could be an incorrect index. This can be fixed by borrowing the ZoneInfo64, so the lifetime is kind of required. Or is it the size? We could store only the index inside Zone and look up things when we need them, this would essentially make it the same as ZoneIndex (but with the reference to the ZoneInfo64).

@Manishearth
Copy link
Member Author

I'm not sure I'm aligned on the goal here. The current get returns a Copy type already, so what exactly is the issue? The lifetime?

In temporal_rs we'd like to be generic over returned type without actually using generics if possible. Having usize indices passed around would be most efficient.

The lifetime is definitely an issue, temporal_rs does not want to pass around TimeZone<'a>. They would rather use Rc and a cache in that case, which I don't want them to do.

I think our options are largely to return a usize or scrap the copy-TimeZone plan altogether.

@Manishearth
Copy link
Member Author

cc @nekevss

@@ -100,7 +100,7 @@ impl Debug for TzZoneData<'_> {

/// A way to index into ZoneInfo64 without performing string comparisons each time
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ZoneIndex(usize);
pub struct ZoneIndex(pub usize);
Copy link
Member

Choose a reason for hiding this comment

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

there's little point for a newtype if the single field is public.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm okay with just having a usize; the newtype helps make signatures clear.

@Manishearth
Copy link
Member Author

  • @Manishearth The trait we're building uses a usize to persist the time zone identity, so I want to add APIs in the zoneinfo64 crate that work with usize
  • @robertbastian Why not use assoc types? Newtypes can have invariants, etc/
  • @robertbastian Also not that many timezones so a u16 is enough.
  • @Manishearth then you get generics in temporal_rs everywhere, and the compiled
  • @robertbastian (discussion)
  • @Manishearth could have an associated type that is guaranteed convertible to usize for storage
  • @sffc I think associated types are the tool for the task
  • @Manishearth I don't: they work nicely for generic methods but this is pervasive to generic types
  • @robertbastian My fundamental issue is that the index doesn't carry around the database. My PR does this.
  • @sffc ICU4X does use generic assoc params everywhere. In ICU4X we have defaults which work.
  • @sffc temporal_rs is primarily for Temporal. I think there is some aspiration for it to be useful for others
  • @sffc I think we can just have a default generic parameter
  • @Manishearth doesn't work: engine implementors need something distinct here, there's not really a sensible default. maybe compiled data
  • @Manishearth I agree with robert's concern. But I also think it's largely for custom provider users, which are power users / engine implementors; and I'm okay with requiring them to do extra work
  • @sffc The stateyness of the provider can live in three places:
    • the type system
    • a runtime check, perhaps with a provider checksum
    • pinky promise
  • @Manishearth That's a choice that Temporal_rs needs to make. It doesn't impact how ICU4X exposes the time zone identity. I'd rather not
  • @robertbastian RawZone in my PR exposes what you need
  • @Manishearth (realized he had misunderstood the PR)
  • @robertbastian Remaining question is about getters/setters.. Should we be checksumming
  • @Manishearth just expose the u16. checksumming is the responsibility of whoever
  • @robertbastian

Conclusion: Accept #6903, with u16 getters/setters

Agreed: @Manishearth @sffc @robertbastian

@Manishearth
Copy link
Member Author

Closed in favor of #6903

robertbastian added a commit that referenced this pull request Aug 28, 2025
Alternative to #6902

This defers the lookups in `zones`, `names`, `rules`, and `regions` from
the constructor, only storing the index in the `Zone` struct.

This will cost an additional lookup at the beginning of each zone
operation, but these are fairly lookup-heavy already anyway. It also
saves the lookups for name and region, which are probably only needed
very rarely. In exchange, the size of `Zone` gets significantly
decreased.

Also adds a `RawZone` abstraction which can be GIGO converted to and
from `Zone`, with the invariant being that the same `ZoneInfo64`
instance is used throughout. Users like temporal can combine this with a
static `LazyLock<ZoneInfo64>` to provide a safe wrapper with minimal
size.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants