From 1a043b2804170c30096ee8d50d4614f3ea20c9b8 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 28 Oct 2022 21:00:16 +0200 Subject: [PATCH] Replace pointer address checks in the parser The parser used to check the address of the `P` to determine whether a method it called had changed the value. This is undesirable for serveral reasons: - The `P::map` function allows changes while still maintaining address stability, which could break this code (although it isn't a problem right now) - Replacing it with a boolean flag is really simple - This is a Rust parser and I don't like casting pointers to integers in my Rust parser - I really dont. --- compiler/rustc_parse/src/parser/expr.rs | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a781748efc52a..0e7c6769d6495 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -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. @@ -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; @@ -971,7 +966,12 @@ impl<'a> Parser<'a> { } } - fn parse_dot_or_call_expr_with_(&mut self, mut e: P, lo: Span) -> PResult<'a, P> { + fn parse_dot_or_call_expr_with_( + &mut self, + mut e: P, + lo: Span, + ) -> PResult<'a, (P, bool)> { + 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` @@ -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; } @@ -998,13 +999,14 @@ impl<'a> Parser<'a> { continue; } 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; } }