about summary refs log tree commit diff
path: root/tests/ui/contracts/contract-attributes-generics.rs
diff options
context:
space:
mode:
authorCelina G. Val <celinval@amazon.com>2025-01-15 13:54:04 -0800
committerCelina G. Val <celinval@amazon.com>2025-02-03 13:55:15 -0800
commit804cce47d96d7b30f3798b51a1377c6697011c54 (patch)
treefe9addffcc69d9d44739bb7ed5a046605c6f5e65 /tests/ui/contracts/contract-attributes-generics.rs
parent6a6c6b891bb0350b3f16abd3e84ff12dbd1b4c5b (diff)
downloadrust-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.rs70
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);
+}