Skip to content
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

Replace pointer address checks in the parser #103700

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,12 +829,7 @@ impl<'a> Parser<'a> {
("cast", None)
};

// Save the memory location of expr before parsing any following postfix operators.
// This will be compared with the memory location of the output expression.
// If they different we can assume we parsed another expression because the existing expression is not reallocated.
let addr_before = &*cast_expr as *const _ as usize;
let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
let changed = addr_before != &*with_postfix as *const _ as usize;
let (with_postfix, changed) = self.parse_dot_or_call_expr_with_(cast_expr, span)?;

// Check if an illegal postfix operator has been added after the cast.
// If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator.
Expand Down Expand Up @@ -959,9 +954,9 @@ impl<'a> Parser<'a> {
// structure
let res = self.parse_dot_or_call_expr_with_(e0, lo);
if attrs.is_empty() {
res
res.map(|(expr, _)| expr)
} else {
res.map(|expr| {
res.map(|(expr, _)| {
expr.map(|mut expr| {
attrs.extend(expr.attrs);
expr.attrs = attrs;
Expand All @@ -971,7 +966,12 @@ impl<'a> Parser<'a> {
}
}

fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
fn parse_dot_or_call_expr_with_(
&mut self,
mut e: P<Expr>,
lo: Span,
) -> PResult<'a, (P<Expr>, bool)> {
Copy link
Member

Choose a reason for hiding this comment

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

maybe a (doc) comment describing what this bool means would be nice,,

Copy link
Member

Choose a reason for hiding this comment

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

galaxy brain: enum ParseDotOrCall { Changed(P<Expr>), Unchanged(P<Expr>) } 😅

but a bool is fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

enum ParseDotOrCall {
  Changed(P<Expr>),
  Unchanged(P<Expr>),
  CheckTheAddressJustToBeSure(P<Expr>),
}

let mut changed_expr = false;
loop {
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
// we are using noexpect here because we don't expect a `?` directly after a `return`
Expand All @@ -982,6 +982,7 @@ impl<'a> Parser<'a> {
};
if has_question {
// `expr?`
changed_expr = true;
e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
continue;
}
Expand All @@ -998,13 +999,14 @@ impl<'a> Parser<'a> {
continue;
Copy link
Member

Choose a reason for hiding this comment

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

You forgot a changed_expr on the previous line.

Copy link
Member

@compiler-errors compiler-errors Oct 28, 2022

Choose a reason for hiding this comment

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

Add the corresponding UI test please:

fn main() {
    (1,) as (i32,) .0
    //~^ ERROR cast cannot be followed by a field access
}

Copy link
Member

Choose a reason for hiding this comment

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

Actually, I feel like changed is redundant with the check on line 836:

if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed {

Why did we need changed in the first place??

Copy link
Member

Choose a reason for hiding this comment

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

Status update, as far as I can tell: we don't

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 like this

}
if self.expr_is_complete(&e) {
return Ok(e);
return Ok((e, changed_expr));
}
e = match self.token.kind {
token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
_ => return Ok(e),
}
_ => return Ok((e, changed_expr)),
};
changed_expr = true;
}
}

Expand Down