diff options
| author | Celina G. Val <celinval@amazon.com> | 2025-01-15 13:54:04 -0800 | 
|---|---|---|
| committer | Celina G. Val <celinval@amazon.com> | 2025-02-03 13:55:15 -0800 | 
| commit | 804cce47d96d7b30f3798b51a1377c6697011c54 (patch) | |
| tree | fe9addffcc69d9d44739bb7ed5a046605c6f5e65 /tests/ui/contracts/contract-attributes-generics.rs | |
| parent | 6a6c6b891bb0350b3f16abd3e84ff12dbd1b4c5b (diff) | |
| download | rust-804cce47d96d7b30f3798b51a1377c6697011c54.tar.gz rust-804cce47d96d7b30f3798b51a1377c6697011c54.zip | |
Refactor contract builtin macro + error handling
Instead of parsing the different components of a function signature, eagerly look for either the `where` keyword or the function body. - Also address feedback to use `From` instead of `TryFrom` in cranelift contract and ubcheck codegen.
Diffstat (limited to 'tests/ui/contracts/contract-attributes-generics.rs')
| -rw-r--r-- | tests/ui/contracts/contract-attributes-generics.rs | 70 | 
1 files changed, 70 insertions, 0 deletions
| diff --git a/tests/ui/contracts/contract-attributes-generics.rs b/tests/ui/contracts/contract-attributes-generics.rs new file mode 100644 index 00000000000..87088ce9de2 --- /dev/null +++ b/tests/ui/contracts/contract-attributes-generics.rs @@ -0,0 +1,70 @@ +//! Test that contracts can be applied to generic functions. + +//@ revisions: unchk_pass chk_pass chk_fail_pre chk_fail_post chk_const_fail +// +//@ [unchk_pass] run-pass +//@ [chk_pass] run-pass +// +//@ [chk_fail_pre] run-fail +//@ [chk_fail_post] run-fail +//@ [chk_const_fail] run-fail +// +//@ [unchk_pass] compile-flags: -Zcontract-checks=no +// +//@ [chk_pass] compile-flags: -Zcontract-checks=yes +//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes +//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes +//@ [chk_const_fail] compile-flags: -Zcontract-checks=yes + +#![feature(rustc_contracts)] + +use std::ops::Sub; + +/// Dummy fn contract that precondition fails for val < 0, and post-condition fail for val == 1 +#[core::contracts::requires(val > 0u8.into())] +#[core::contracts::ensures(|ret| *ret > 0u8.into())] +fn decrement<T>(val: T) -> T +where T: PartialOrd + Sub<Output=T> + From<u8> +{ + val - 1u8.into() +} + +/// Create a structure that takes a constant parameter. +#[allow(dead_code)] +struct Capped<const MAX: usize>(usize); + +/// Now declare a function to create stars which shouldn't exceed 5 stars. +// Add redundant braces to ensure the built-in macro can handle this syntax. +#[allow(unused_braces)] +#[core::contracts::requires(num <= 5)] +unsafe fn stars_unchecked(num: usize) -> Capped<{ 5 }> { + Capped(num) +} + + +fn main() { + check_decrement(); + check_stars(); +} + +fn check_stars() { + // This should always pass. + let _ = unsafe { stars_unchecked(3) }; + + // This violates the contract. + #[cfg(any(unchk_pass, chk_const_fail))] + let _ = unsafe { stars_unchecked(10) }; +} + +fn check_decrement() { + // This should always pass + assert_eq!(decrement(10u8), 9u8); + + // This should fail requires but pass with no contract check. + #[cfg(any(unchk_pass, chk_fail_pre))] + assert_eq!(decrement(-2i128), -3i128); + + // This should fail ensures but pass with no contract check. + #[cfg(any(unchk_pass, chk_fail_post))] + assert_eq!(decrement(1i32), 0i32); +} | 
