oxc-project / oxc-project/backlog

Replace `Ancestor` methods with fields

Open
#43 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
7
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Ancestor types in oxc_traverse currently require field access via methods:

fn enter_expression(&mut self, expr: &Expression<'a>, ctx: &mut TraverseCtx<'a> {
    if let Ancestor::BinaryExpressionLeft(bin_expr) = ctx.parent() {
        let right = bin_expr.right(); // Method call
    }
}

This is a bit unnatural. Would be more ergonomic to use field accesses:

fn enter_expression(&mut self, expr: &Expression<'a>, ctx: &mut TraverseCtx<'a> {
    if let Ancestor::BinaryExpressionLeft(bin_expr) = ctx.parent() {
        let right = &bin_expr.right; // Field access
    }
}

Current implementation:

pub struct BinaryExpressionWithoutLeft<'a>(pub(crate) *const BinaryExpression<'a>);

impl<'a> BinaryExpressionWithoutLeft<'a> {
    pub fn span(&self) -> &Span {
        unsafe { &*((self.0 as *const u8).add(OFFSET_BINARY_EXPRESSION_SPAN) as *const Span) }
    }

    pub fn operator(&self) -> &BinaryOperator {
        unsafe { &*((self.0 as *const u8).add(OFFSET_BINARY_EXPRESSION_OPERATOR) as *const BinaryOperator) }
    }

    pub fn right(&self) -> &Expression<'a> {
        unsafe { &*((self.0 as *const u8).add(OFFSET_BINARY_EXPRESSION_RIGHT) as *const Expression<'a>) }
    }
}

With field accesses:

pub struct BinaryExpressionWithoutLeft<'a>(pub(crate) *const BinaryExpression<'a>);

impl<'a> Deref for BinaryExpressionWithoutLeft<'a> {
  type Target = BinaryExpressionWithoutLeftInner<'a>;

  fn deref(&self) -> &Self::Target {
    unsafe { &*(self.0 as *const Self::Target) }
  }
}

pub struct BinaryExpressionWithoutLeftInner {
    pub span: Span,
    _left: MaybeUninit<Expression<'a>>,
    pub operator: BinaryOperator,
    pub right: Expression<'a>,
}

Same as current implementation, access to left is made statically impossible, but without the methods.

Would require that BinaryExpression and BinaryExpressionWithoutLeftInner are both #[repr(C)] so that transmuting from one to the other is valid.

I am not sure if this would be sound or not, as it creates a reference from pointer of node which has been travelled through in current traverse "branch". But maybe it's OK!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the current Ancestor wrappers, BinaryExpressionWithoutLeft implementation, and the ctx.parent() usage shown in oxc_traverse. Investigate whether the proposed #[repr(C)] and Deref layout preserves soundness for traversed nodes. Done means field access replaces the relevant methods while keeping access to left statically impossible and the unsafe references sound.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.