Skip to content

Remove DynType and resculpt ast::Type #1322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open

Conversation

tyranron
Copy link
Member

@tyranron tyranron commented May 20, 2025

Follows #1247

Synopsis

In #1247 the ast::Type was made generic over the string type used for name.

pub enum Type<N = ArcStr> {
    Named(N),
    List(Box<Type<N>>, Option<usize>),
    NonNullNamed(N),
    NonNullList(Box<Type<N>>, Option<usize>),
}

In the codebase, there are numerous places where it's required to convert both ast::Type<ArcStr> and ast::Type<&str> to some singular representation stored in ValidatorContext or similar places.

However, the current ast::Type enum representation using Boxes introduces a problem that it's not possible to cheaply receive a borrowed version of ast::Type<ArcStr> as ast::Type<&str> without re-allocating all those Boxes. Furthermore, using Boxes involves redundant re-allocations on Cloneing even when &str is used.

Thus, @audunhalland came up with a temporary DynType solution to solve this problem:

pub enum DynType<'a> {
    Named(&'a str),
    List(&'a dyn AsDynType, Option<usize>),
    NonNullNamed(&'a str),
    NonNullList(&'a dyn AsDynType, Option<usize>),
}

pub trait AsDynType: fmt::Debug {
    fn as_dyn_type(&self) -> DynType<'_>;
}
impl AsDynType for ast::Type<ArcStr> { }
impl AsDynType for ast::Type<&str> {}

The problem with this solution, that it duplicates ast::Type inner logic and pollutes some potentially public APIs.

Solution

As @audunhalland kindly suggested in TODO comment:

// TODO: Ideally this type should not exist, but the reason it currently does is that `Type` has a
//       recursive design to allow arbitrary number of list wrappings.
//       The list layout could instead be modelled as a modifier so that type becomes a tuple of
//       (name, modifier).
//       If `Type` is modelled like this it becomes easier to project it as a borrowed version of
//       itself, i.e. [Type<ArcStr>] vs [Type<&str>].

This PR resculpts ast::Type in this manner:

pub enum TypeModifier {
    NonNull,
    List(Option<usize>),
}

pub(crate) type BorrowedType<'a> = Type<&'a str, &'a [TypeModifier]>;

#[derive(Clone, Debug)]
pub struct Type<N = ArcStr, M = Box<[TypeModifier]>> {
    name: N,
    modifiers: M,
}

Checklist

  • Docs are updated
  • Tests are updated
  • CHANGELOG.md updated

@tyranron tyranron added this to the 0.17.0 milestone May 20, 2025
@tyranron tyranron self-assigned this May 20, 2025
@tyranron tyranron added enhancement Improvement of existing features or bugfix semver::breaking Breaking change in terms of SemVer k::api Related to API (application interface) k::performance Related to performance k::refactor Refactoring, technical debt elimination and other improvements of existing code base labels May 20, 2025
@tyranron tyranron marked this pull request as ready for review May 22, 2025 15:12
@tyranron
Copy link
Member Author

@audunhalland it would be nice if you provide some input of this, if you have time to spare. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvement of existing features or bugfix k::api Related to API (application interface) k::performance Related to performance k::refactor Refactoring, technical debt elimination and other improvements of existing code base semver::breaking Breaking change in terms of SemVer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant