Skip to content

Commit 8905337

Browse files
authored
Unrolled build for #149722
Rollup merge of #149722 - dawidl022:contracts/fix/parsing-compound-statements, r=jieyouxu contracts: fix lowering final declaration without trailing semicolon Lowering for contract delcarations introduced in #144444 incorrectly handled the final declaration statement when it didn't end in a semicolon. This change fixes the issue. See the included regression test for the minimal reproducible example. Contracts tracking issue: #128044
2 parents 5549523 + d54fee8 commit 8905337

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

compiler/rustc_ast_lowering/src/contract.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2323
// The order in which things are lowered is important! I.e to
2424
// refer to variables in contract_decls from postcond/precond,
2525
// we must lower it first!
26-
let contract_decls = self.lower_stmts(&contract.declarations).0;
26+
let contract_decls = self.lower_decls(contract);
2727

2828
match (&contract.requires, &contract.ensures) {
2929
(Some(req), Some(ens)) => {
@@ -124,6 +124,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
124124
}
125125
}
126126

127+
fn lower_decls(&mut self, contract: &rustc_ast::FnContract) -> &'hir [rustc_hir::Stmt<'hir>] {
128+
let (decls, decls_tail) = self.lower_stmts(&contract.declarations);
129+
130+
if let Some(e) = decls_tail {
131+
// include the tail expression in the declaration statements
132+
let tail = self.stmt_expr(e.span, *e);
133+
self.arena.alloc_from_iter(decls.into_iter().map(|d| *d).chain([tail].into_iter()))
134+
} else {
135+
decls
136+
}
137+
}
138+
127139
/// Lower the precondition check intrinsic.
128140
fn lower_precond(&mut self, req: &Box<rustc_ast::Expr>) -> rustc_hir::Stmt<'hir> {
129141
let lowered_req = self.lower_expr_mut(&req);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ run-pass
2+
//@ compile-flags: -Zcontract-checks=yes
3+
4+
#![expect(incomplete_features)]
5+
#![feature(contracts)]
6+
extern crate core;
7+
use core::contracts::requires;
8+
9+
// Compound statements (those using [ExpressionWithBlock]
10+
// (https://doc.rust-lang.org/beta/reference/expressions.html#railroad-ExpressionWithBlock))
11+
// like blocks, if-expressions, and loops require no trailing semicolon. This
12+
// regression test captures the case where the last statement in the contract
13+
// declarations has no trailing semicolon.
14+
#[requires(
15+
{}
16+
true
17+
)]
18+
fn foo() {}
19+
20+
fn main() {
21+
foo()
22+
}

0 commit comments

Comments
 (0)