Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Change to cargo-hax:
Changes to hax-lib:

Changes to the Lean backend:
- Add support for base-expressions of structs (#1736)

Miscellaneous:

Expand Down
30 changes: 27 additions & 3 deletions rust-engine/src/backends/lean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,23 @@ const _: () = {
}
}

/// Prints fields of structures (when in braced notation)
fn struct_fields<'a, 'b, A: 'a + Clone, D>(
&'a self,
fields: &'b [(GlobalId, D)],
) -> DocBuilder<'a, Self, A>
where
&'b D: Pretty<'a, Self, A>,
{
macro_rules! line {($($tt:tt)*) => {disambiguated_line!($($tt)*)};}
docs![intersperse!(
fields
.iter()
.map(|(id, e)| { docs![self.render_last(id), reflow!(" := "), e].group() }),
docs![",", line!()]
)]
.group()
}
/// Prints named arguments (record) of a variant or constructor of struct
fn named_arguments<'a, 'b, A: 'a + Clone, D>(
&'a self,
Expand Down Expand Up @@ -487,14 +504,21 @@ set_option linter.unusedVariables false
ExprKind::Construct {
constructor,
is_record,
is_struct: _,
is_struct,
fields,
base,
} => {
if fields.is_empty() && base.is_none() {
docs![constructor]
} else if base.is_some() {
emit_error!(issue 1637, "Unsupported base expressions for structs.")
} else if let Some(base) = base {
if !(*is_record && *is_struct) {
unreachable!(
"Constructors with base expressions are necessarily structs with record-like arguments"
)
}
docs![base, line!(), reflow!("with "), self.struct_fields(fields)]
.braces()
.group()
} else {
docs![constructor, line!(), self.arguments(fields, is_record)]
.nest(INDENT)
Expand Down
21 changes: 21 additions & 0 deletions test-harness/src/snapshots/toolchain__lean-tests into-lean.snap
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,27 @@ def Lean_tests.Structs.Miscellaneous.test_tuples
(Rust_primitives.Hax.Tuple2.mk z z)));
(Rust_primitives.Hax.Tuple2.mk (1 : i32) (2 : i32))

structure Lean_tests.Structs.Base_expressions.S where
f1 : u32
f2 : u32
f3 : u32

def Lean_tests.Structs.Base_expressions.test
(_ : Rust_primitives.Hax.Tuple0)
: Result Rust_primitives.Hax.Tuple0
:= do
let s1 : Lean_tests.Structs.Base_expressions.S ← (pure
(Lean_tests.Structs.Base_expressions.S.mk
(f1 := (1 : u32)) (f2 := (2 : u32)) (f3 := (3 : u32))));
let _ ← (pure {s1 with f1 := (0 : u32)});
let _ ← (pure {s1 with f2 := (0 : u32)});
let _ ← (pure {s1 with f3 := (0 : u32)});
let _ ← (pure {s1 with f1 := (0 : u32), f2 := (1 : u32)});
let _ ← (pure {s1 with f2 := (0 : u32), f3 := (1 : u32)});
let _ ← (pure {s1 with f3 := (0 : u32), f1 := (2 : u32)});
let _ ← (pure {s1 with f1 := (0 : u32), f2 := (1 : u32), f3 := (0 : u32)});
Rust_primitives.Hax.Tuple0.mk

structure Lean_tests.Structs.T0 where


Expand Down
29 changes: 29 additions & 0 deletions tests/lean-tests/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,32 @@ mod miscellaneous {
(1, 2)
}
}

mod base_expressions {

struct S {
f1: u32,
f2: u32,
f3: u32,
}

fn test() {
let s1 = S {
f1: 1,
f2: 2,
f3: 3,
};
let _ = S { f1: 0, ..s1 };
let _ = S { f2: 0, ..s1 };
let _ = S { f3: 0, ..s1 };
let _ = S { f1: 0, f2: 1, ..s1 };
let _ = S { f2: 0, f3: 1, ..s1 };
let _ = S { f3: 0, f1: 2, ..s1 };
let _ = S {
f1: 0,
f2: 1,
f3: 0,
..s1
};
}
}
Loading