From f0e2ba6e3a0ddb6b32722b9b91bc7a7e9e78485d Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sun, 29 Oct 2023 15:24:41 +0000 Subject: [PATCH] contracts: Put contract-bound function body in a `try` block if needed This makes Topola dependent on nightly Rust. If `try` blocks aren't stabilized before the first release, we'll trivially just undo this change temporarily, as contracts are just elaborate assertions. --- src/main.rs | 1 + .../contracts/src/implementation/codegen.rs | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8ff4c85..87ed6e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![feature(try_blocks)] extern crate sdl2; macro_rules! dbg_dot { diff --git a/vendor/contracts/src/implementation/codegen.rs b/vendor/contracts/src/implementation/codegen.rs index 3d82bf2..0e7090a 100644 --- a/vendor/contracts/src/implementation/codegen.rs +++ b/vendor/contracts/src/implementation/codegen.rs @@ -5,8 +5,8 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::ToTokens; use syn::{ - spanned::Spanned, visit_mut as visitor, Attribute, Expr, ExprCall, - ReturnType, TypeImplTrait, + spanned::Spanned, visit_mut as visitor, Attribute, Expr, ExprCall, ExprTry, + ReturnType, Type, TypeImplTrait, }; use crate::implementation::{ @@ -341,7 +341,14 @@ pub(crate) fn generate( if let ReturnType::Type(.., ref return_type) = func.function.sig.output { - break 'blk quote::quote! { let ret: #return_type = 'run: #block; }; + let mut try_detector = TryDetector { found_try: false }; + syn::visit::visit_block(&mut try_detector, &mut block); + + if try_detector.found_try { + break 'blk quote::quote! { let ret: #return_type = 'run: { try { #block? } }; }; + } else { + break 'blk quote::quote! { let ret: #return_type = 'run: #block; }; + } } } @@ -401,3 +408,13 @@ impl<'a> syn::visit::Visit<'a> for ImplDetector { self.found_impl = true; } } + +struct TryDetector { + found_try: bool, +} + +impl<'a> syn::visit::Visit<'a> for TryDetector { + fn visit_expr_try(&mut self, _node: &'a ExprTry) { + self.found_try = true; + } +}