Skip to content

Commit 3b19f8d

Browse files
committed
Implement Structural for Result<T, E>
Option<T> was already marked Structural (added incidentally in #1695), but Result<T, E>, the other pervasive std type raised in #178, was not. This meant generic code with a `T: Structural` bound (needed to connect exec-mode == to spec-mode ==) could not be instantiated with Result, even though Result's PartialEq is already fieldwise/structural. Fix: add `unsafe impl<T: Structural, E: Structural> Structural for core::result::Result<T, E> {}` in builtin/src/lib.rs, mirroring the existing Option impl. Result is a core (not alloc/std) type, so this needs no extra dependency and sidesteps the no_std/orphan-rule concern raised in the issue for alloc-backed types like Vec/String. Verified: - vstd still verifies fully (2044/0) after the change - New regression test in rust_verify_test/tests/structural.rs fails without the fix (E0277: Result<u32,u32> does not implement Structural) and passes with it - structural.rs, eq_cmp.rs, partial_eq.rs, operators.rs, option.rs, results.rs, adts.rs, impl.rs, marker_traits.rs, generics.rs, external_type_specification.rs test suites all pass with no regressions Assisted-by: Claude Code:claude-sonnet-5
1 parent 74e001a commit 3b19f8d

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

source/builtin/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,8 @@ impl_structural! {
856856

857857
unsafe impl<T: Structural> Structural for Option<T> {}
858858

859+
unsafe impl<T: Structural, E: Structural> Structural for core::result::Result<T, E> {}
860+
859861
pub struct NoCopy {}
860862
#[cfg(verus_keep_ghost)]
861863
impl !Copy for NoCopy {}

source/rust_verify_test/tests/structural.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@ test_verify_one_file! {
8080
} => Ok(())
8181
}
8282

83+
test_verify_one_file! {
84+
// https://github.com/verus-lang/verus/issues/178
85+
#[test] test_result_is_structural verus_code! {
86+
use vstd::prelude::*;
87+
88+
fn eq_generic<T: PartialEq + Structural>(a: &T, b: &T) -> (r: bool)
89+
ensures r == (a == b),
90+
{
91+
a == b
92+
}
93+
94+
fn test_result(a: Result<u32, u32>, b: Result<u32, u32>) {
95+
let r = eq_generic(&a, &b);
96+
assert(r == (a == b));
97+
}
98+
} => Ok(())
99+
}
100+
83101
test_verify_one_file_with_options! {
84102
#[test] test_structural_trait_bound ["exec_allows_no_decreases_clause"] => verus_code! {
85103
use vstd::prelude::*;

0 commit comments

Comments
 (0)