From 9706437d1e49f31db1ae43faf2e988d480f9811f Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 23 May 2026 14:33:43 +0200 Subject: [PATCH 1/5] transpile: Rename `resolve_parens` to `unwrap_parens` --- c2rust-transpile/src/c_ast/mod.rs | 4 ++-- c2rust-transpile/src/translator/pointers.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 4bef8937e5..63476ac727 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -673,7 +673,7 @@ impl TypedAstContext { } /// Returns the expression inside any number of nested parentheses. - pub fn resolve_parens(&self, mut expr_id: CExprId) -> CExprId { + pub fn unwrap_parens(&self, mut expr_id: CExprId) -> CExprId { while let CExprKind::Paren(_, subexpr) = self.index(expr_id).kind { expr_id = subexpr; } @@ -692,7 +692,7 @@ impl TypedAstContext { /// Unwraps a predefined expression, if there is one. pub fn unwrap_predefined_ident(&self, mut expr_id: CExprId) -> CExprId { - expr_id = self.resolve_extension(self.resolve_parens(expr_id)); + expr_id = self.resolve_extension(self.unwrap_parens(expr_id)); if let CExprKind::Predefined(_, subexpr) = self.index(expr_id).kind { subexpr diff --git a/c2rust-transpile/src/translator/pointers.rs b/c2rust-transpile/src/translator/pointers.rs index a15fef518c..c165515427 100644 --- a/c2rust-transpile/src/translator/pointers.rs +++ b/c2rust-transpile/src/translator/pointers.rs @@ -23,7 +23,7 @@ impl<'c> Translation<'c> { cqual_type: CQualTypeId, arg: CExprId, ) -> TranslationResult>> { - let arg_kind = &self.ast_context[self.ast_context.resolve_parens(arg)].kind; + let arg_kind = &self.ast_context[self.ast_context.unwrap_parens(arg)].kind; match arg_kind { // C99 6.5.3.2 para 4 From 03512f826df56f0b0b44edb41c203a93478d9321 Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 23 May 2026 14:37:43 +0200 Subject: [PATCH 2/5] transpile: Add `index_unwrap_parens` function --- c2rust-transpile/src/c_ast/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 63476ac727..432632b7ee 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -681,6 +681,17 @@ impl TypedAstContext { expr_id } + /// Same as the index operator, but unwraps `Paren` expressions. + pub fn index_unwrap_parens(&self, expr_id: CExprId) -> &CExpr { + static BADEXPR: CExpr = Located { + loc: None, + kind: CExprKind::BadExpr, + }; + self.c_exprs + .get(&self.unwrap_parens(expr_id)) + .unwrap_or(&BADEXPR) + } + /// Returns the expression inside an `__extension__` operator. pub fn resolve_extension(&self, expr_id: CExprId) -> CExprId { if let CExprKind::Unary(_, CUnOp::Extension, subexpr, _) = self.index(expr_id).kind { From 55063c89727d2cf82694eefb05b49525de9b7b26 Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 23 May 2026 14:53:13 +0200 Subject: [PATCH 3/5] transpile: Replace all `CExprId` indexing with `index_unwrap_parens` --- c2rust-transpile/src/c_ast/mod.rs | 36 +++++++++------ c2rust-transpile/src/cfg/mod.rs | 32 ++++++++++--- c2rust-transpile/src/translator/atomics.rs | 16 +++++-- c2rust-transpile/src/translator/builtins.rs | 10 ++-- c2rust-transpile/src/translator/enums.rs | 4 +- c2rust-transpile/src/translator/functions.rs | 15 ++++-- c2rust-transpile/src/translator/literals.rs | 6 +-- c2rust-transpile/src/translator/macros.rs | 6 ++- c2rust-transpile/src/translator/mod.rs | 34 ++++++++------ .../src/translator/named_references.rs | 2 +- c2rust-transpile/src/translator/operators.rs | 22 +++++---- c2rust-transpile/src/translator/pointers.rs | 18 ++++---- c2rust-transpile/src/translator/simd.rs | 46 +++++++++++-------- .../src/translator/structs_unions.rs | 2 +- c2rust-transpile/src/translator/variadic.rs | 26 +++++------ 15 files changed, 166 insertions(+), 109 deletions(-) diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 432632b7ee..95c38eebf2 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -359,7 +359,7 @@ impl TypedAstContext { use SomeId::*; match id { Stmt(id) => self.index(id).loc, - Expr(id) => self.index(id).loc, + Expr(id) => self.index_unwrap_parens(id).loc, Decl(id) => self.index(id).loc, Type(id) => self.index(id).loc, } @@ -487,7 +487,7 @@ impl TypedAstContext { pub fn is_null_expr(&self, expr_id: CExprId) -> bool { use CExprKind::*; - match self[expr_id].kind { + match self.index_unwrap_parens(expr_id).kind { ExplicitCast(_, _, CastKind::NullToPointer, _, _) | ImplicitCast(_, _, CastKind::NullToPointer, _, _) => true, @@ -674,7 +674,7 @@ impl TypedAstContext { /// Returns the expression inside any number of nested parentheses. pub fn unwrap_parens(&self, mut expr_id: CExprId) -> CExprId { - while let CExprKind::Paren(_, subexpr) = self.index(expr_id).kind { + while let CExprKind::Paren(_, subexpr) = self[expr_id].kind { expr_id = subexpr; } @@ -694,7 +694,9 @@ impl TypedAstContext { /// Returns the expression inside an `__extension__` operator. pub fn resolve_extension(&self, expr_id: CExprId) -> CExprId { - if let CExprKind::Unary(_, CUnOp::Extension, subexpr, _) = self.index(expr_id).kind { + if let CExprKind::Unary(_, CUnOp::Extension, subexpr, _) = + self.index_unwrap_parens(expr_id).kind + { subexpr } else { expr_id @@ -705,7 +707,7 @@ impl TypedAstContext { pub fn unwrap_predefined_ident(&self, mut expr_id: CExprId) -> CExprId { expr_id = self.resolve_extension(self.unwrap_parens(expr_id)); - if let CExprKind::Predefined(_, subexpr) = self.index(expr_id).kind { + if let CExprKind::Predefined(_, subexpr) = self.index_unwrap_parens(expr_id).kind { subexpr } else { expr_id @@ -716,7 +718,8 @@ impl TypedAstContext { pub fn unwrap_cast_expr(&self, mut expr_id: CExprId) -> CExprId { while let CExprKind::Paren(_, subexpr) | CExprKind::ImplicitCast(_, subexpr, _, _, _) - | CExprKind::ExplicitCast(_, subexpr, _, _, _) = self.index(expr_id).kind + | CExprKind::ExplicitCast(_, subexpr, _, _, _) = + self.index_unwrap_parens(expr_id).kind { expr_id = subexpr; } @@ -726,7 +729,9 @@ impl TypedAstContext { /// Unwraps the underlying expression beneath any implicit casts. pub fn unwrap_implicit_cast_expr(&self, mut expr_id: CExprId) -> CExprId { - while let CExprKind::ImplicitCast(_, subexpr, _, _, _) = self.index(expr_id).kind { + while let CExprKind::ImplicitCast(_, subexpr, _, _, _) = + self.index_unwrap_parens(expr_id).kind + { expr_id = subexpr; } @@ -736,7 +741,7 @@ impl TypedAstContext { /// Resolve true expression type, iterating through any casts and variable /// references. pub fn resolve_expr_type_id(&self, expr_id: CExprId) -> Option<(CExprId, CTypeId)> { - let expr = &self.index(expr_id).kind; + let expr = &self.index_unwrap_parens(expr_id).kind; let mut ty = expr.get_type(); use CExprKind::*; match expr { @@ -815,9 +820,10 @@ impl TypedAstContext { /// Looks for ImplicitCast(FunctionToPointerDecay, DeclRef(function_decl)) pub fn fn_declref_decl(&self, func_expr: CExprId) -> Option<&CDeclKind> { use CastKind::FunctionToPointerDecay; - if let CExprKind::ImplicitCast(_, fexp, FunctionToPointerDecay, _, _) = self[func_expr].kind + if let CExprKind::ImplicitCast(_, fexp, FunctionToPointerDecay, _, _) = + self.index_unwrap_parens(func_expr).kind { - if let CExprKind::DeclRef(_ty, decl_id, _rv) = &self[fexp].kind { + if let CExprKind::DeclRef(_ty, decl_id, _rv) = &self.index_unwrap_parens(fexp).kind { let decl = &self.index(*decl_id).kind; assert!(matches!(decl, CDeclKind::Function { .. })); return Some(decl); @@ -879,7 +885,7 @@ impl TypedAstContext { pub fn is_expr_pure(&self, expr: CExprId) -> bool { use CExprKind::*; let pure = |expr| self.is_expr_pure(expr); - match self.index(expr).kind { + match self.index_unwrap_parens(expr).kind { BadExpr | ShuffleVector(..) | ConvertVector(..) | @@ -923,12 +929,12 @@ impl TypedAstContext { /// Pessimistically try to check if an expression doesn't return. /// If it does, or we can't tell that it doesn't, return `false`. pub fn expr_diverges(&self, expr_id: CExprId) -> bool { - let func_id = match self.index(expr_id).kind { + let func_id = match self.index_unwrap_parens(expr_id).kind { CExprKind::Call(_, func_id, _) => func_id, _ => return false, }; - let type_id = match self[func_id].kind.get_type() { + let type_id = match self.index_unwrap_parens(func_id).kind.get_type() { None => return false, Some(t) => t, }; @@ -951,7 +957,7 @@ impl TypedAstContext { let is_const = |expr| self.is_const_expr(expr); use CExprKind::*; - match self[expr].kind { + match self.index_unwrap_parens(expr).kind { // A literal is always `const`. Literal(_, _) => true, // Unary ops should be `const`. @@ -1185,7 +1191,7 @@ impl TypedAstContext { } Expr(expr_id) => { - let expr = self.index(expr_id); + let expr = self.index_unwrap_parens(expr_id); if let Some(macs) = self.macro_invocations.get(&expr_id) { for mac_id in macs { if wanted.insert(*mac_id) { diff --git a/c2rust-transpile/src/cfg/mod.rs b/c2rust-transpile/src/cfg/mod.rs index 9e02c779ad..2f7bd67128 100644 --- a/c2rust-transpile/src/cfg/mod.rs +++ b/c2rust-transpile/src/cfg/mod.rs @@ -1453,7 +1453,11 @@ impl CfgBuilder { .discard_unsafe(); wip.extend(stmts); - let cond_val = translator.ast_context[scrutinee].kind.get_bool(); + let cond_val = translator + .ast_context + .index_unwrap_parens(scrutinee) + .kind + .get_bool(); self.add_wip_block( wip, match cond_val { @@ -1520,7 +1524,11 @@ impl CfgBuilder { let (stmts, val) = translator .convert_condition(ctx, true, condition)? .discard_unsafe(); - let cond_val = translator.ast_context[condition].kind.get_bool(); + let cond_val = translator + .ast_context + .index_unwrap_parens(condition) + .kind + .get_bool(); let mut cond_wip = self.new_wip_block(cond_entry.clone()); cond_wip.extend(stmts); @@ -1595,7 +1603,11 @@ impl CfgBuilder { let (stmts, val) = translator .convert_condition(ctx, true, condition)? .discard_unsafe(); - let cond_val = translator.ast_context[condition].kind.get_bool(); + let cond_val = translator + .ast_context + .index_unwrap_parens(condition) + .kind + .get_bool(); let mut cond_wip = self.new_wip_block(cond_entry); cond_wip.extend(stmts); self.add_wip_block( @@ -1646,7 +1658,11 @@ impl CfgBuilder { let (stmts, val) = translator .convert_condition(ctx, true, cond)? .discard_unsafe(); - let cond_val = translator.ast_context[cond].kind.get_bool(); + let cond_val = translator + .ast_context + .index_unwrap_parens(cond) + .kind + .get_bool(); let mut cond_wip = slf.new_wip_block(cond_entry.clone()); cond_wip.extend(stmts); slf.add_wip_block( @@ -1772,9 +1788,11 @@ impl CfgBuilder { // We simply inline the common statement at this point rather // than to try and create new control-flow blocks. let blk_or_wip = if let CExprKind::Unary(_, CUnOp::Extension, sube, _) = - translator.ast_context[expr].kind + translator.ast_context.index_unwrap_parens(expr).kind { - if let CExprKind::Statements(_, stmtid) = translator.ast_context[sube].kind { + if let CExprKind::Statements(_, stmtid) = + translator.ast_context.index_unwrap_parens(sube).kind + { let comp_entry = self.fresh_label(); self.add_wip_block(wip, Jump(comp_entry.clone())); let next_lbl = self.convert_stmt_help( @@ -1858,7 +1876,7 @@ impl CfgBuilder { // Case let resolved = translator.ast_context.unwrap_cast_expr(case_expr); - let branch = match translator.ast_context.index(resolved).kind { + let branch = match translator.ast_context.index_unwrap_parens(resolved).kind { CExprKind::Literal(..) | CExprKind::ConstantExpr(_, _, Some(_)) => { match translator .convert_expr(ctx.used(), resolved, None)? diff --git a/c2rust-transpile/src/translator/atomics.rs b/c2rust-transpile/src/translator/atomics.rs index a1994147ea..5c21c90184 100644 --- a/c2rust-transpile/src/translator/atomics.rs +++ b/c2rust-transpile/src/translator/atomics.rs @@ -98,14 +98,14 @@ impl<'c> Translation<'c> { fn convert_constant_bool(&self, expr: CExprId) -> Option { let val = self.ast_context.unwrap_cast_expr(expr); - match self.ast_context.index(val).kind { + match self.ast_context.index_unwrap_parens(val).kind { CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i != 0), _ => None, } } fn convert_memordering(&self, expr: CExprId) -> Option { - let memorder = &self.ast_context[expr]; + let memorder = &self.ast_context.index_unwrap_parens(expr); let i = match memorder.kind { CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i), CExprKind::DeclRef(_, decl_id, LRValue::RValue) => { @@ -295,8 +295,12 @@ impl<'c> Translation<'c> { } .ok_or_else(|| { format_translation_err!( - self.ast_context - .display_loc(&self.ast_context[order_fail_id.unwrap()].loc), + self.ast_context.display_loc( + &self + .ast_context + .index_unwrap_parens(order_fail_id.unwrap()) + .loc + ), "Invalid failure memory ordering", ) })?; @@ -337,7 +341,9 @@ impl<'c> Translation<'c> { let order = static_order(order); let val = val1.expect("__atomic arithmetic operations must have a val argument"); - let val_type_id = self.ast_context[val1_id.unwrap()] + let val_type_id = self + .ast_context + .index_unwrap_parens(val1_id.unwrap()) .kind .get_qual_type() .ok_or_else(|| format_err!("bad val1 type"))?; diff --git a/c2rust-transpile/src/translator/builtins.rs b/c2rust-transpile/src/translator/builtins.rs index 36946d86e0..ae05d76ab4 100644 --- a/c2rust-transpile/src/translator/builtins.rs +++ b/c2rust-transpile/src/translator/builtins.rs @@ -52,7 +52,7 @@ impl<'c> Translation<'c> { fexp: CExprId, args: &[CExprId], ) -> TranslationResult>> { - let expr = &self.ast_context[fexp]; + let expr = &self.ast_context.index_unwrap_parens(fexp); let src_loc = &expr.loc; let decl_id = match expr.kind { CExprKind::DeclRef(_, decl_id, _) => decl_id, @@ -590,7 +590,9 @@ impl<'c> Translation<'c> { if let Some(atomic_op) = CAtomicBinOp::from_sync_builtin_fn(builtin_name) { let arg0 = self.convert_expr(ctx.used(), args[0], None)?; let arg1 = self.convert_expr(ctx.used(), args[1], None)?; - let arg1_type_id = self.ast_context[args[1]] + let arg1_type_id = self + .ast_context + .index_unwrap_parens(args[1]) .kind .get_qual_type() .ok_or_else(|| format_err!("bad arg1 type"))?; @@ -611,7 +613,9 @@ impl<'c> Translation<'c> { } fn import_num_traits(&self, arg_id: CExprId) -> TranslationResult<()> { - let arg_type_id = self.ast_context[arg_id] + let arg_type_id = self + .ast_context + .index_unwrap_parens(arg_id) .kind .get_qual_type() .ok_or_else(|| format_err!("bad arg type"))?; diff --git a/c2rust-transpile/src/translator/enums.rs b/c2rust-transpile/src/translator/enums.rs index d1a9c0b8c9..88a9045b13 100644 --- a/c2rust-transpile/src/translator/enums.rs +++ b/c2rust-transpile/src/translator/enums.rs @@ -89,7 +89,7 @@ impl<'c> Translation<'c> { val: Box, ) -> TranslationResult> { if let Some(expr) = expr { - match self.ast_context[expr].kind { + match self.ast_context.index_unwrap_parens(expr).kind { // This is the case of finding a variable which is an `EnumConstant` of the same // enum we are casting to. Here, we can just remove the extraneous cast instead of // generating a new one. @@ -112,7 +112,7 @@ impl<'c> Translation<'c> { CExprKind::Unary(_, CUnOp::Negate, subexpr_id, _) => { if let &CExprKind::Literal(_, CLiteral::Integer(i, _)) = - &self.ast_context[subexpr_id].kind + &self.ast_context.index_unwrap_parens(subexpr_id).kind { return Ok(self.enum_for_i64(enum_type_id, -(i as i64))); } diff --git a/c2rust-transpile/src/translator/functions.rs b/c2rust-transpile/src/translator/functions.rs index 7071bff675..bedff5e479 100644 --- a/c2rust-transpile/src/translator/functions.rs +++ b/c2rust-transpile/src/translator/functions.rs @@ -365,7 +365,8 @@ impl<'c> Translation<'c> { let fn_ty = self .ast_context .get_pointee_qual_type( - self.ast_context[func] + self.ast_context + .index_unwrap_parens(func) .kind .get_type() .ok_or_else(|| format_err!("Invalid callee expression {:?}", func))?, @@ -384,12 +385,12 @@ impl<'c> Translation<'c> { None }; - let func = match self.ast_context[func].kind { + let func = match self.ast_context.index_unwrap_parens(func).kind { // Direct function call CExprKind::ImplicitCast(_, fexp, CastKind::FunctionToPointerDecay, _, _) // Only a direct function call with pointer decay if the // callee is a declref - if matches!(self.ast_context[fexp].kind, CExprKind::DeclRef(..)) => + if matches!(self.ast_context.index_unwrap_parens(fexp).kind, CExprKind::DeclRef(..)) => { self.convert_expr(ctx.used(), fexp, None)? } @@ -507,8 +508,12 @@ impl<'c> Translation<'c> { ) -> TranslationResult>> { let mut val; - if (self.ast_context.index(expr_id).kind.get_qual_type()) - .map_or(false, |qtype| self.ast_context.is_va_list(qtype.ctype)) + if (self + .ast_context + .index_unwrap_parens(expr_id) + .kind + .get_qual_type()) + .map_or(false, |qtype| self.ast_context.is_va_list(qtype.ctype)) { // No `override_ty` to avoid unwanted casting. val = self.convert_expr(ctx, expr_id, None)?; diff --git a/c2rust-transpile/src/translator/literals.rs b/c2rust-transpile/src/translator/literals.rs index e1bfeca9f3..1bd9539f9c 100644 --- a/c2rust-transpile/src/translator/literals.rs +++ b/c2rust-transpile/src/translator/literals.rs @@ -233,7 +233,7 @@ impl<'c> Translation<'c> { // we manually insert the otherwise elided casts in this // particular context. if let CExprKind::ImplicitCast(ty, _, CastKind::ConstCast, _, _) = - self.ast_context[id].kind + self.ast_context.index_unwrap_parens(id).kind { let t = self.convert_type(ty.ctype)?; Ok(mk().cast_expr(x, t)) @@ -259,7 +259,7 @@ impl<'c> Translation<'c> { // * the expr kind being a string literal (`CExprKind::Literal` of a `CLiteral::String`). let is_string_literal = |id: CExprId| { let ty_kind = &self.ast_context.resolve_type(ty).kind; - let expr_kind = &self.ast_context.index(id).kind; + let expr_kind = &self.ast_context.index_unwrap_parens(id).kind; let is_char_array = matches!(*ty_kind, CTypeKind::Char); let is_str_literal = matches!(*expr_kind, CExprKind::Literal(_, CLiteral::String { .. })); @@ -268,7 +268,7 @@ impl<'c> Translation<'c> { let is_zero_literal = |id: CExprId| { matches!( - self.ast_context.index(id).kind, + self.ast_context.index_unwrap_parens(id).kind, CExprKind::Literal(_, CLiteral::Integer(0, _base)) ) }; diff --git a/c2rust-transpile/src/translator/macros.rs b/c2rust-transpile/src/translator/macros.rs index 148e60a199..5d390f5905 100644 --- a/c2rust-transpile/src/translator/macros.rs +++ b/c2rust-transpile/src/translator/macros.rs @@ -74,7 +74,9 @@ impl<'c> Translation<'c> { .try_fold::>, CTypeId)>, _, _>(None, |canonical, &id| { self.can_convert_const_macro_expansion(id)?; - let ty = self.ast_context[id] + let ty = self + .ast_context + .index_unwrap_parens(id) .kind .get_type() .ok_or_else(|| format_err!("Invalid expression type"))?; @@ -196,7 +198,7 @@ impl<'c> Translation<'c> { let val = WithStmts::new_val(mk().path_expr(vec![rust_name])); - let expr_kind = &self.ast_context[expr_id].kind; + let expr_kind = &self.ast_context.index_unwrap_parens(expr_id).kind; // TODO We'd like to get rid of this cast eventually (see #1321). // Currently, const macros do not get the correct `override_ty` themselves, // so they aren't declared with the correct portable type, diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index d4bfb88c37..bf7e491910 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -1661,7 +1661,7 @@ impl<'c> Translation<'c> { }; use CExprKind::*; - match self.ast_context[expr_id].kind { + match self.ast_context.index_unwrap_parens(expr_id).kind { // Technically we're being conservative here, but it's only the most // contrived array indexing initializers that would be accepted ArraySubscript(..) => return true, @@ -1694,8 +1694,10 @@ impl<'c> Translation<'c> { } } Unary(_, AddressOf, expr_id, _) => { - if let Member(_, expr_id, _, _, _) = self.ast_context[expr_id].kind { - if let DeclRef(..) = self.ast_context[expr_id].kind { + if let Member(_, expr_id, _, _, _) = + self.ast_context.index_unwrap_parens(expr_id).kind + { + if let DeclRef(..) = self.ast_context.index_unwrap_parens(expr_id).kind { return true; } } @@ -2230,7 +2232,9 @@ impl<'c> Translation<'c> { target: bool, cond_id: CExprId, ) -> TranslationResult>> { - let ty_id = self.ast_context[cond_id] + let ty_id = self + .ast_context + .index_unwrap_parens(cond_id) .kind .get_type() .ok_or_else(|| format_err!("bad condition type"))?; @@ -2238,7 +2242,9 @@ impl<'c> Translation<'c> { let null_pointer_case = |ptr: CExprId, is_null: bool| -> TranslationResult>> { let val = self.convert_expr(ctx.used().decay_ref(), ptr, None)?; - let ptr_type = self.ast_context[ptr] + let ptr_type = self + .ast_context + .index_unwrap_parens(ptr) .kind .get_type() .ok_or_else(|| format_err!("bad pointer type for condition"))?; @@ -2246,7 +2252,7 @@ impl<'c> Translation<'c> { val.try_map(|val| self.convert_pointer_is_null(ctx, ptr_type, val, is_null)) }; - match self.ast_context[cond_id].kind { + match self.ast_context.index_unwrap_parens(cond_id).kind { CExprKind::Binary(_, CBinOp::EqualEqual, null_expr, ptr, _, _) if self.ast_context.is_null_expr(null_expr) => { @@ -2304,7 +2310,7 @@ impl<'c> Translation<'c> { let mut iter = DFExpr::new(&self.ast_context, expr_id.into()); while let Some(x) = iter.next() { match x { - SomeId::Expr(e) => match self.ast_context[e].kind { + SomeId::Expr(e) => match self.ast_context.index_unwrap_parens(e).kind { CExprKind::DeclRef(_, d, _) if d == decl_id => return true, CExprKind::UnaryType(_, _, Some(_), _) => iter.prune(1), _ => {} @@ -2533,7 +2539,8 @@ impl<'c> Translation<'c> { ctypeid: CTypeId, initializer: Option, ) -> bool { - let initializer_kind = initializer.map(|expr_id| &self.ast_context[expr_id].kind); + let initializer_kind = + initializer.map(|expr_id| &self.ast_context.index_unwrap_parens(expr_id).kind); // If the RHS is a func call, we should be able to skip type annotation // because we get a type from the function return type @@ -2926,12 +2933,12 @@ impl<'c> Translation<'c> { let Located { loc: src_loc, kind: expr_kind, - } = &self.ast_context[expr_id]; + } = &self.ast_context.index_unwrap_parens(expr_id); trace!( "Converting expr {:?}: {:?}", expr_id, - self.ast_context[expr_id] + self.ast_context.index_unwrap_parens(expr_id) ); if let Some(converted) = self.convert_const_macro_expansion(ctx, expr_id, override_ty)? { @@ -3223,7 +3230,7 @@ impl<'c> Translation<'c> { _ => {} } - let expr_kind = &self.ast_context[expr].kind; + let expr_kind = &self.ast_context.index_unwrap_parens(expr).kind; let target_ty = override_ty.unwrap_or(ty); // In general, if we are casting the result of an expression, then the inner @@ -3236,7 +3243,7 @@ impl<'c> Translation<'c> { let mut is_negated = false; if let &CExprKind::Unary(_, CUnOp::Negate, subexpr_id, _) = literal_expr_kind { - literal_expr_kind = &self.ast_context[subexpr_id].kind; + literal_expr_kind = &self.ast_context.index_unwrap_parens(subexpr_id).kind; is_negated = true; } @@ -3281,7 +3288,8 @@ impl<'c> Translation<'c> { CQualTypeId::new(func_ptr_ty) } else { - self.ast_context[expr] + self.ast_context + .index_unwrap_parens(expr) .kind .get_qual_type() .ok_or_else(|| format_err!("bad source type"))? diff --git a/c2rust-transpile/src/translator/named_references.rs b/c2rust-transpile/src/translator/named_references.rs index ede42c8fab..640fb42be1 100644 --- a/c2rust-transpile/src/translator/named_references.rs +++ b/c2rust-transpile/src/translator/named_references.rs @@ -102,7 +102,7 @@ impl<'c> Translation<'c> { ) -> TranslationResult>>>> { let reference_ty = self .ast_context - .index(reference) + .index_unwrap_parens(reference) .kind .get_qual_type() .ok_or_else(|| format_err!("bad reference type"))?; diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index a03f240ffe..07d99e441f 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -19,8 +19,8 @@ impl<'c> Translation<'c> { ctx.ternary_needs_parens = true; } - let lhs_loc = &self.ast_context[lhs].loc; - let rhs_loc = &self.ast_context[rhs].loc; + let lhs_loc = &self.ast_context.index_unwrap_parens(lhs).loc; + let rhs_loc = &self.ast_context.index_unwrap_parens(rhs).loc; use CBinOp::*; match op { Comma => { @@ -68,14 +68,14 @@ impl<'c> Translation<'c> { let ty = self.convert_type(expr_type_id.ctype)?; - let lhs_kind = &self.ast_context.index(lhs).kind; + let lhs_kind = &self.ast_context.index_unwrap_parens(lhs).kind; let mut lhs_type_id = lhs_kind.get_qual_type().ok_or_else(|| { format_translation_err!( self.ast_context.display_loc(lhs_loc), "bad lhs type for assignment" ) })?; - let rhs_kind = &self.ast_context.index(rhs).kind; + let rhs_kind = &self.ast_context.index_unwrap_parens(rhs).kind; let mut rhs_type_id = rhs_kind.get_qual_type().ok_or_else(|| { format_translation_err!( self.ast_context.display_loc(rhs_loc), @@ -266,11 +266,11 @@ impl<'c> Translation<'c> { let rhs_type_id = self .ast_context - .index(rhs) + .index_unwrap_parens(rhs) .kind .get_qual_type() .ok_or_else(|| format_err!("bad assignment rhs type"))?; - let lhs_kind = &self.ast_context.index(lhs).kind; + let lhs_kind = &self.ast_context.index_unwrap_parens(lhs).kind; let lhs_type_id = lhs_kind .get_qual_type() .ok_or_else(|| format_err!("bad initial lhs type"))?; @@ -340,7 +340,7 @@ impl<'c> Translation<'c> { let result_type_id = compute_res_type_id.unwrap_or(expr_type_id); let expr_or_comp_type_id = compute_lhs_type_id.unwrap_or(expr_type_id); - let initial_lhs = &self.ast_context.index(lhs).kind; + let initial_lhs = &self.ast_context.index_unwrap_parens(lhs).kind; let initial_lhs_type_id = initial_lhs .get_qual_type() .ok_or_else(|| format_err!("bad initial lhs type"))?; @@ -618,7 +618,9 @@ impl<'c> Translation<'c> { op: CBinOp, arg: CExprId, ) -> TranslationResult>> { - let arg_type = self.ast_context[arg] + let arg_type = self + .ast_context + .index_unwrap_parens(arg) .kind .get_qual_type() .ok_or_else(|| format_err!("bad arg type"))?; @@ -678,7 +680,7 @@ impl<'c> Translation<'c> { .expect("not an valid assignment operator"); let ty = self .ast_context - .index(arg) + .index_unwrap_parens(arg) .kind .get_qual_type() .ok_or_else(|| format_err!("bad post inc type"))?; @@ -836,7 +838,7 @@ impl<'c> Translation<'c> { .is_unsigned_integral_type(); if let (&CExprKind::Literal(_, CLiteral::Integer(val, base)), false, false) = ( - &self.ast_context[arg_id].kind, + &self.ast_context.index_unwrap_parens(arg_id).kind, is_unsigned_integral_type, self.expr_is_expanded_macro(ctx, arg_id, Some(expr_type_id)), ) { diff --git a/c2rust-transpile/src/translator/pointers.rs b/c2rust-transpile/src/translator/pointers.rs index c165515427..5428ce9e6b 100644 --- a/c2rust-transpile/src/translator/pointers.rs +++ b/c2rust-transpile/src/translator/pointers.rs @@ -1,5 +1,3 @@ -use std::ops::Index; - use c2rust_ast_builder::{mk, properties::Mutability}; use c2rust_ast_exporter::clang_ast::LRValue; use failure::{err_msg, format_err}; @@ -23,7 +21,7 @@ impl<'c> Translation<'c> { cqual_type: CQualTypeId, arg: CExprId, ) -> TranslationResult>> { - let arg_kind = &self.ast_context[self.ast_context.unwrap_parens(arg)].kind; + let arg_kind = &self.ast_context.index_unwrap_parens(arg).kind; match arg_kind { // C99 6.5.3.2 para 4 @@ -100,7 +98,7 @@ impl<'c> Translation<'c> { ) -> TranslationResult>> { let arg_expr_kind = arg.map(|arg| { let arg = self.ast_context.unwrap_predefined_ident(arg); - &self.ast_context.index(arg).kind + &self.ast_context.index_unwrap_parens(arg).kind }); let pointee_cty = self .ast_context @@ -198,7 +196,7 @@ impl<'c> Translation<'c> { cqual_type: CQualTypeId, arg: CExprId, ) -> TranslationResult>> { - let arg_expr_kind = &self.ast_context.index(arg).kind; + let arg_expr_kind = &self.ast_context.index_unwrap_parens(arg).kind; if let &CExprKind::Unary(_, CUnOp::AddressOf, arg, _) = arg_expr_kind { return self.convert_expr(ctx.used(), arg, None); @@ -227,8 +225,8 @@ impl<'c> Translation<'c> { override_ty: Option, deref: bool, ) -> TranslationResult>> { - let lhs_node = &self.ast_context.index(lhs).kind; - let rhs_node = &self.ast_context.index(rhs).kind; + let lhs_node = &self.ast_context.index_unwrap_parens(lhs).kind; + let rhs_node = &self.ast_context.index_unwrap_parens(rhs).kind; let lhs_node_type = lhs_node .get_type() @@ -267,7 +265,7 @@ impl<'c> Translation<'c> { } else { match lhs_node { &CExprKind::ImplicitCast(_, arr, CastKind::ArrayToPointerDecay, _, _) => { - match self.ast_context[arr].kind { + match self.ast_context.index_unwrap_parens(arr).kind { CExprKind::Member(_, _, field_decl, _, _) if self .potential_flexible_array_members @@ -296,7 +294,9 @@ impl<'c> Translation<'c> { // If the LHS just underwent an implicit cast from array to pointer, bypass that // to make an actual Rust indexing operation - let t = self.ast_context[arr] + let t = self + .ast_context + .index_unwrap_parens(arr) .kind .get_type() .ok_or_else(|| format_err!("bad arr type"))?; diff --git a/c2rust-transpile/src/translator/simd.rs b/c2rust-transpile/src/translator/simd.rs index cca06186e9..4edbff959e 100644 --- a/c2rust-transpile/src/translator/simd.rs +++ b/c2rust-transpile/src/translator/simd.rs @@ -185,7 +185,7 @@ impl<'c> Translation<'c> { /// This function will strip either an implicitly casted int or explicitly casted /// vector as both casts are unnecessary (and problematic) for our purposes fn clean_int_or_vector_param(&self, expr_id: CExprId) -> CExprId { - match self.ast_context[expr_id].kind { + match self.ast_context.index_unwrap_parens(expr_id).kind { // For some reason there seems to be an incorrect implicit cast here to char // it's possible the builtin takes a char even though the function takes an int ImplicitCast(_, expr_id, IntegralCast, _, _) => expr_id, @@ -424,7 +424,9 @@ impl<'c> Translation<'c> { // _mm_shufflehi_epi16 mask params start with const int, // _mm_shufflelo_epi16 does not let expr_id = &child_expr_ids[2]; - if let Literal(_, Integer(0, IntBase::Dec)) = self.ast_context[*expr_id].kind { + if let Literal(_, Integer(0, IntBase::Dec)) = + self.ast_context.index_unwrap_parens(*expr_id).kind + { "_mm_shufflehi_epi16" } else { "_mm_shufflelo_epi16" @@ -434,7 +436,9 @@ impl<'c> Translation<'c> { // _mm256_shufflehi_epi16 mask params start with const int, // _mm256_shufflelo_epi16 does not let expr_id = &child_expr_ids[2]; - if let Literal(_, Integer(0, IntBase::Dec)) = self.ast_context[*expr_id].kind { + if let Literal(_, Integer(0, IntBase::Dec)) = + self.ast_context.index_unwrap_parens(*expr_id).kind + { "_mm256_shufflehi_epi16" } else { "_mm256_shufflelo_epi16" @@ -465,9 +469,9 @@ impl<'c> Translation<'c> { /// is likely redundant (external type), the other is not (internal type). We remove both of the /// casts for simplicity and readability fn strip_vector_explicit_cast(&self, expr_id: CExprId) -> (&CTypeKind, CExprId, usize) { - match self.ast_context[expr_id].kind { + match self.ast_context.index_unwrap_parens(expr_id).kind { ExplicitCast(CQualTypeId { ctype, .. }, expr_id, _, _, _) => { - let expr_id = match &self.ast_context[expr_id].kind { + let expr_id = match &self.ast_context.index_unwrap_parens(expr_id).kind { ExplicitCast(_, expr_id, _, _, _) => *expr_id, // The expr_id wont be used in this case (the function only has one // vector param, not two, despite the following type match), so it's @@ -505,14 +509,14 @@ impl<'c> Translation<'c> { fn unknown_mask_format(e: &CExprKind) -> Result { Err(format_err!("Found unknown mask format: {:?}", e).into()) } - match self.ast_context[expr_ids[0]].kind { + match self.ast_context.index_unwrap_parens(expr_ids[0]).kind { // Need to unmask which looks like this most of the time: X + (((mask) >> Y) & Z): Binary(_, Add, _, rhs_expr_id, None, None) => { self.get_shuffle_vector_mask(&[rhs_expr_id]) } // Sometimes there is a mask like this: ((mask) >> X) & Y: Binary(_, BitAnd, lhs_expr_id, _, None, None) => { - match self.ast_context[lhs_expr_id].kind { + match self.ast_context.index_unwrap_parens(lhs_expr_id).kind { Binary(_, ShiftRight, lhs_expr_id, _, None, None) => Ok(lhs_expr_id), ref e => unknown_mask_format(e), } @@ -520,20 +524,22 @@ impl<'c> Translation<'c> { // Sometimes you find a constant and the mask is used further down the expr list Literal(_, Integer(0, IntBase::Dec)) => self.get_shuffle_vector_mask(&[expr_ids[4]]), // format: ((char)(mask) & A) ? B : C - (char)(mask) - Conditional(_, lhs_expr_id, _, _) => match self.ast_context[lhs_expr_id].kind { - Binary(_, BitAnd, lhs_expr_id, _, None, None) => { - match self.ast_context[lhs_expr_id].kind { - ImplicitCast(_, expr_id, IntegralCast, _, _) => { - match self.ast_context[expr_id].kind { - ExplicitCast(_, expr_id, IntegralCast, _, _) => Ok(expr_id), - ref e => unknown_mask_format(e), + Conditional(_, lhs_expr_id, _, _) => { + match self.ast_context.index_unwrap_parens(lhs_expr_id).kind { + Binary(_, BitAnd, lhs_expr_id, _, None, None) => { + match self.ast_context.index_unwrap_parens(lhs_expr_id).kind { + ImplicitCast(_, expr_id, IntegralCast, _, _) => { + match self.ast_context.index_unwrap_parens(expr_id).kind { + ExplicitCast(_, expr_id, IntegralCast, _, _) => Ok(expr_id), + ref e => unknown_mask_format(e), + } } + ref e => unknown_mask_format(e), } - ref e => unknown_mask_format(e), } + ref e => unknown_mask_format(e), } - ref e => unknown_mask_format(e), - }, + } ref e => unknown_mask_format(e), } } @@ -548,13 +554,13 @@ impl<'c> Translation<'c> { ) -> bool { use self::CastKind::BuiltinFnToFnPtr; - match self.ast_context[expr_id].kind { + match self.ast_context.index_unwrap_parens(expr_id).kind { CExprKind::ShuffleVector(..) => is_explicit && kind == CastKind::BitCast, CExprKind::Call(_, fn_id, _) => { - let fn_expr = &self.ast_context[fn_id].kind; + let fn_expr = &self.ast_context.index_unwrap_parens(fn_id).kind; if let CExprKind::ImplicitCast(_, expr_id, BuiltinFnToFnPtr, _, _) = fn_expr { - let expr = &self.ast_context[*expr_id].kind; + let expr = &self.ast_context.index_unwrap_parens(*expr_id).kind; if let CExprKind::DeclRef(_, decl_id, _) = expr { let decl = &self.ast_context[*decl_id].kind; diff --git a/c2rust-transpile/src/translator/structs_unions.rs b/c2rust-transpile/src/translator/structs_unions.rs index db21177a4d..a14821c472 100644 --- a/c2rust-transpile/src/translator/structs_unions.rs +++ b/c2rust-transpile/src/translator/structs_unions.rs @@ -995,7 +995,7 @@ impl<'a> Translation<'a> { MemberKind::Dot => self.convert_expr(ctx, expr, None)?, MemberKind::Arrow => { if let CExprKind::Unary(_, CUnOp::AddressOf, subexpr_id, _) = - self.ast_context[expr].kind + self.ast_context.index_unwrap_parens(expr).kind { // Special-case the `(&x)->field` pattern // Convert it directly into `x.field` diff --git a/c2rust-transpile/src/translator/variadic.rs b/c2rust-transpile/src/translator/variadic.rs index 0357085340..66c7a313fa 100644 --- a/c2rust-transpile/src/translator/variadic.rs +++ b/c2rust-transpile/src/translator/variadic.rs @@ -68,9 +68,9 @@ impl<'c> Translation<'c> { pub fn match_vastart(&self, expr: CExprId) -> Option { // struct-based va_list (e.g. x86_64) fn match_vastart_struct(ast_context: &TypedAstContext, expr: CExprId) -> Option { - match_or! { [ast_context[expr].kind] + match_or! { [ast_context.index_unwrap_parens(expr).kind] CExprKind::ImplicitCast(_, e, _, _, _) => e } - match_or! { [ast_context[e].kind] + match_or! { [ast_context.index_unwrap_parens(e).kind] CExprKind::DeclRef(_, va_id, _) => va_id } Some(va_id) } @@ -81,11 +81,11 @@ impl<'c> Translation<'c> { ast_context: &TypedAstContext, expr: CExprId, ) -> Option { - match_or! { [ast_context[expr].kind] + match_or! { [ast_context.index_unwrap_parens(expr).kind] CExprKind::ImplicitCast(_, me, _, _, _) => me } - match_or! { [ast_context[me].kind] + match_or! { [ast_context.index_unwrap_parens(me).kind] CExprKind::Member(_, e, _, _, _) => e } - match_or! { [ast_context[e].kind] + match_or! { [ast_context.index_unwrap_parens(e).kind] CExprKind::DeclRef(_, va_id, _) => va_id } Some(va_id) } @@ -96,20 +96,20 @@ impl<'c> Translation<'c> { ast_context: &TypedAstContext, expr: CExprId, ) -> Option { - match_or! { [ast_context[expr].kind] + match_or! { [ast_context.index_unwrap_parens(expr).kind] CExprKind::ImplicitCast(_, me, _, _, _) => me } - match_or! { [ast_context[me].kind] + match_or! { [ast_context.index_unwrap_parens(me).kind] CExprKind::Member(_, ie, _, _, _) => ie } - match_or! { [ast_context[ie].kind] + match_or! { [ast_context.index_unwrap_parens(ie).kind] CExprKind::ImplicitCast(_, e, _, _, _) => e } - match_or! { [ast_context[e].kind] + match_or! { [ast_context.index_unwrap_parens(e).kind] CExprKind::DeclRef(_, va_id, _) => va_id } Some(va_id) } // char pointer-based va_list (e.g. x86) fn match_vastart_pointer(ast_context: &TypedAstContext, expr: CExprId) -> Option { - match_or! { [ast_context[expr].kind] + match_or! { [ast_context.index_unwrap_parens(expr).kind] CExprKind::DeclRef(_, va_id, _) => va_id } Some(va_id) } @@ -134,11 +134,11 @@ impl<'c> Translation<'c> { } pub fn match_vapart(&self, expr: CExprId) -> Option { - match_or! { [self.ast_context[expr].kind] + match_or! { [self.ast_context.index_unwrap_parens(expr).kind] CExprKind::Call(_, func, ref args) => (func, args) } - match_or! { [self.ast_context[func].kind] + match_or! { [self.ast_context.index_unwrap_parens(func).kind] CExprKind::ImplicitCast(_, fexp, CastKind::BuiltinFnToFnPtr, _, _) => fexp } - match_or! { [self.ast_context[fexp].kind] + match_or! { [self.ast_context.index_unwrap_parens(fexp).kind] CExprKind::DeclRef(_, decl_id, _) => decl_id } match_or! { [self.ast_context[decl_id].kind] CDeclKind::Function { ref name, .. } => name } From 43c1525b0d84a0339d464a45487d7e8e8605a835 Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 23 May 2026 14:54:34 +0200 Subject: [PATCH 4/5] transpile: Do not unwrap `Paren` when indexing with `CExprId` --- c2rust-transpile/src/c_ast/mod.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 95c38eebf2..d6baeae523 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -1519,6 +1519,7 @@ impl Index for TypedAstContext { impl Index for TypedAstContext { type Output = CExpr; + fn index(&self, index: CExprId) -> &CExpr { static BADEXPR: CExpr = Located { loc: None, @@ -1526,14 +1527,7 @@ impl Index for TypedAstContext { }; match self.c_exprs.get(&index) { None => &BADEXPR, // panic!("Could not find {:?} in TypedAstContext", index), - Some(e) => { - // Transparently index through Paren expressions - if let CExprKind::Paren(_, subexpr) = e.kind { - self.index(subexpr) - } else { - e - } - } + Some(e) => e, } } } From 9351ea955f9d62232742642d73651c9d9a4cdcbd Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 23 May 2026 15:30:54 +0200 Subject: [PATCH 5/5] transpile: Use plain `CExprId` indexing where `Paren` is explicitly handled --- c2rust-transpile/src/c_ast/mod.rs | 11 +++++------ c2rust-transpile/src/translator/mod.rs | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index d6baeae523..68cb038d5f 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -718,8 +718,7 @@ impl TypedAstContext { pub fn unwrap_cast_expr(&self, mut expr_id: CExprId) -> CExprId { while let CExprKind::Paren(_, subexpr) | CExprKind::ImplicitCast(_, subexpr, _, _, _) - | CExprKind::ExplicitCast(_, subexpr, _, _, _) = - self.index_unwrap_parens(expr_id).kind + | CExprKind::ExplicitCast(_, subexpr, _, _, _) = self[expr_id].kind { expr_id = subexpr; } @@ -741,7 +740,7 @@ impl TypedAstContext { /// Resolve true expression type, iterating through any casts and variable /// references. pub fn resolve_expr_type_id(&self, expr_id: CExprId) -> Option<(CExprId, CTypeId)> { - let expr = &self.index_unwrap_parens(expr_id).kind; + let expr = &self[expr_id].kind; let mut ty = expr.get_type(); use CExprKind::*; match expr { @@ -885,7 +884,7 @@ impl TypedAstContext { pub fn is_expr_pure(&self, expr: CExprId) -> bool { use CExprKind::*; let pure = |expr| self.is_expr_pure(expr); - match self.index_unwrap_parens(expr).kind { + match self[expr].kind { BadExpr | ShuffleVector(..) | ConvertVector(..) | @@ -957,7 +956,7 @@ impl TypedAstContext { let is_const = |expr| self.is_const_expr(expr); use CExprKind::*; - match self.index_unwrap_parens(expr).kind { + match self[expr].kind { // A literal is always `const`. Literal(_, _) => true, // Unary ops should be `const`. @@ -1271,7 +1270,7 @@ impl TypedAstContext { _ => return, }; - let new_ty = match self.ast_context.c_exprs[&e].kind { + let new_ty = match self.ast_context[e].kind { CExprKind::Conditional(_ty, _cond, lhs, rhs) => { let lhs_type_id = self.ast_context.c_exprs[&lhs].kind.get_qual_type().unwrap(); diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index bf7e491910..36f1b689f7 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -2933,12 +2933,12 @@ impl<'c> Translation<'c> { let Located { loc: src_loc, kind: expr_kind, - } = &self.ast_context.index_unwrap_parens(expr_id); + } = &self.ast_context[expr_id]; trace!( "Converting expr {:?}: {:?}", expr_id, - self.ast_context.index_unwrap_parens(expr_id) + self.ast_context[expr_id] ); if let Some(converted) = self.convert_const_macro_expansion(ctx, expr_id, override_ty)? {