Skip to content

Commit 5e66329

Browse files
Support default trait associated consts
1 parent cf420a5 commit 5e66329

2 files changed

Lines changed: 92 additions & 9 deletions

File tree

source/rust_verify/src/rust_to_vir_trait.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,23 @@ pub(crate) fn translate_trait<'tcx>(
345345
method_names.push(fun);
346346
}
347347
}
348-
TraitItemKind::Const(_ty, None) => {
349-
let has_default = false;
348+
TraitItemKind::Const(_ty, body_opt) => {
349+
let param_names = vec![];
350+
let (body_id, has_default) = match body_opt {
351+
Some(_) if ex_trait_id_for.is_some() && !is_verus_spec => {
352+
return err_span(
353+
*span,
354+
format!("`external_trait_specification` functions cannot have bodies"),
355+
);
356+
}
357+
Some(rustc_hir::ConstItemRhs::Body(body_id)) => {
358+
(CheckItemFnEither::BodyId(body_id), true)
359+
}
360+
Some(_) => {
361+
crate::unsupported_err!(trait_span, "non-expression trait const default")
362+
}
363+
None => (CheckItemFnEither::ParamNames(param_names.as_slice()), false),
364+
};
350365
let mid_ty = ctxt.tcx.type_of(owner_id.to_def_id()).skip_binder();
351366
let typ = ctxt.mid_ty_to_vir(owner_id.to_def_id(), *span, &mid_ty, false, None)?;
352367
let fun = crate::rust_to_vir_func::check_item_fn(
@@ -361,7 +376,7 @@ pub(crate) fn translate_trait<'tcx>(
361376
crate::rust_to_vir_func::FnOrConstSig::const_var(*span, typ),
362377
Some((trait_generics, trait_def_id)),
363378
item_generics,
364-
crate::rust_to_vir_func::CheckItemFnEither::ParamNames(&[]),
379+
body_id,
365380
ex_trait_id_for.map(|d| (d, trait_extension_in_spec)),
366381
ex_item_id_for,
367382
external_info,
@@ -372,12 +387,6 @@ pub(crate) fn translate_trait<'tcx>(
372387
method_names.push(fun);
373388
}
374389
}
375-
TraitItemKind::Const(_ty, Some(_body_id)) => {
376-
return err_span(
377-
trait_span,
378-
"Verus does not yet support associated constants with default values",
379-
);
380-
}
381390
TraitItemKind::Type(_, Some(_)) => {
382391
return err_span(
383392
trait_span,

source/rust_verify_test/tests/traits.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4573,3 +4573,77 @@ test_verify_one_file! {
45734573
}
45744574
} => Err(err) => assert_vir_error_msg(err, "cannot read const with mode exec")
45754575
}
4576+
4577+
test_verify_one_file! {
4578+
#[test] trait_assoc_const1_default verus_code! {
4579+
trait U {}
4580+
4581+
trait T<A, B> {
4582+
const C: usize = 10;
4583+
const S: &str = "no";
4584+
const E: usize = 20;
4585+
}
4586+
4587+
impl U for u16 {}
4588+
4589+
const Q: u8 = 10;
4590+
4591+
impl<Z: U> T<u8, Z> for bool {
4592+
const C: usize = 13 - Q as usize;
4593+
const S: &str = "ha";
4594+
4595+
#[verifier::external_body]
4596+
const E: usize = 4;
4597+
}
4598+
4599+
impl<Z: U> T<u16, Z> for bool {
4600+
}
4601+
4602+
fn test1() {
4603+
assert(<bool as T<u8, u16>>::C == 3);
4604+
assert(<bool as T<u16, u16>>::C == 10);
4605+
let c = <bool as T<u8, u16>>::C;
4606+
assert(c == 3);
4607+
let c2 = <bool as T<u16, u16>>::C;
4608+
assert(c2 == 3); // FAILS
4609+
}
4610+
4611+
fn test2<A: T<u8, u16>>() {
4612+
assert(A::C == 3); // FAILS
4613+
}
4614+
4615+
fn test3<A: T<u8, u16>>() {
4616+
assert(A::C == 10); // FAILS
4617+
}
4618+
} => Err(err) => assert_fails(err, 3)
4619+
}
4620+
4621+
test_verify_one_file! {
4622+
#[test] trait_assoc_const2_default verus_code! {
4623+
const fn f() -> u8 { 3 }
4624+
trait T {
4625+
// implicitly dual exec-spec mode:
4626+
const C: u8 = f();
4627+
}
4628+
} => Err(err) => assert_vir_error_msg(err, "with mode exec")
4629+
}
4630+
4631+
test_verify_one_file! {
4632+
#[test] trait_assoc_const3_default verus_code! {
4633+
spec const Q: u8 = 3;
4634+
trait T {
4635+
// implicitly dual exec-spec mode:
4636+
const C: u8 = Q;
4637+
}
4638+
} => Err(err) => assert_vir_error_msg(err, "expected mode")
4639+
}
4640+
4641+
test_verify_one_file! {
4642+
#[test] trait_assoc_const4_default verus_code! {
4643+
exec const Q: u8 = 3;
4644+
trait T {
4645+
// implicitly dual exec-spec mode:
4646+
const C: u8 = Q;
4647+
}
4648+
} => Err(err) => assert_vir_error_msg(err, "cannot read const with mode exec")
4649+
}

0 commit comments

Comments
 (0)