Skip to content

Commit 9ecf552

Browse files
feat(lean): add support for base expression of structs
1 parent 74a3d25 commit 9ecf552

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

rust-engine/src/backends/lean.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,23 @@ const _: () = {
258258
}
259259
}
260260

261+
/// Prints fields of structures (when in braced notation)
262+
fn struct_fields<'a, 'b, A: 'a + Clone, D>(
263+
&'a self,
264+
fields: &'b [(GlobalId, D)],
265+
) -> DocBuilder<'a, Self, A>
266+
where
267+
&'b D: Pretty<'a, Self, A>,
268+
{
269+
macro_rules! line {($($tt:tt)*) => {disambiguated_line!($($tt)*)};}
270+
docs![intersperse!(
271+
fields
272+
.iter()
273+
.map(|(id, e)| { docs![self.render_last(id), reflow!(" := "), e].group() }),
274+
docs![",", line!()]
275+
)]
276+
.group()
277+
}
261278
/// Prints named arguments (record) of a variant or constructor of struct
262279
fn named_arguments<'a, 'b, A: 'a + Clone, D>(
263280
&'a self,
@@ -487,14 +504,21 @@ set_option linter.unusedVariables false
487504
ExprKind::Construct {
488505
constructor,
489506
is_record,
490-
is_struct: _,
507+
is_struct,
491508
fields,
492509
base,
493510
} => {
494511
if fields.is_empty() && base.is_none() {
495512
docs![constructor]
496-
} else if base.is_some() {
497-
emit_error!(issue 1637, "Unsupported base expressions for structs.")
513+
} else if let Some(base) = base {
514+
if !(*is_record && *is_struct) {
515+
unreachable!(
516+
"Constructors with base expressions are necessarily structs with record-like arguments"
517+
)
518+
}
519+
docs![base, line!(), reflow!("with "), self.struct_fields(fields)]
520+
.braces()
521+
.group()
498522
} else {
499523
docs![constructor, line!(), self.arguments(fields, is_record)]
500524
.nest(INDENT)

test-harness/src/snapshots/toolchain__lean-tests into-lean.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,27 @@ def Lean_tests.Structs.Miscellaneous.test_tuples
273273
(Rust_primitives.Hax.Tuple2.mk z z)));
274274
(Rust_primitives.Hax.Tuple2.mk (1 : i32) (2 : i32))
275275

276+
structure Lean_tests.Structs.Base_expressions.S where
277+
f1 : u32
278+
f2 : u32
279+
f3 : u32
280+
281+
def Lean_tests.Structs.Base_expressions.test
282+
(_ : Rust_primitives.Hax.Tuple0)
283+
: Result Rust_primitives.Hax.Tuple0
284+
:= do
285+
let s1 : Lean_tests.Structs.Base_expressions.S ← (pure
286+
(Lean_tests.Structs.Base_expressions.S.mk
287+
(f1 := (1 : u32)) (f2 := (2 : u32)) (f3 := (3 : u32))));
288+
let _ ← (pure {s1 with f1 := (0 : u32)});
289+
let _ ← (pure {s1 with f2 := (0 : u32)});
290+
let _ ← (pure {s1 with f3 := (0 : u32)});
291+
let _ ← (pure {s1 with f1 := (0 : u32), f2 := (1 : u32)});
292+
let _ ← (pure {s1 with f2 := (0 : u32), f3 := (1 : u32)});
293+
let _ ← (pure {s1 with f3 := (0 : u32), f1 := (2 : u32)});
294+
let _ ← (pure {s1 with f1 := (0 : u32), f2 := (1 : u32), f3 := (0 : u32)});
295+
Rust_primitives.Hax.Tuple0.mk
296+
276297
structure Lean_tests.Structs.T0 where
277298

278299

tests/lean-tests/src/structs.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,32 @@ mod miscellaneous {
162162
(1, 2)
163163
}
164164
}
165+
166+
mod base_expressions {
167+
168+
struct S {
169+
f1: u32,
170+
f2: u32,
171+
f3: u32,
172+
}
173+
174+
fn test() {
175+
let s1 = S {
176+
f1: 1,
177+
f2: 2,
178+
f3: 3,
179+
};
180+
let _ = S { f1: 0, ..s1 };
181+
let _ = S { f2: 0, ..s1 };
182+
let _ = S { f3: 0, ..s1 };
183+
let _ = S { f1: 0, f2: 1, ..s1 };
184+
let _ = S { f2: 0, f3: 1, ..s1 };
185+
let _ = S { f3: 0, f1: 2, ..s1 };
186+
let _ = S {
187+
f1: 0,
188+
f2: 1,
189+
f3: 0,
190+
..s1
191+
};
192+
}
193+
}

0 commit comments

Comments
 (0)