Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Even better model panics #1721

Merged
merged 9 commits into from
Mar 27, 2023
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 12 additions & 57 deletions crates/fj-proc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ mod expand;
mod parse;

use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use syn::{
parse_macro_input, punctuated::Punctuated, token::Paren, Expr, ExprCall,
ExprPath, FnArg, ItemFn, PathArguments, PathSegment, Stmt,
};
use syn::{parse_macro_input, FnArg, ItemFn};

/// Define a function-based model.
///
Expand Down Expand Up @@ -95,67 +91,26 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream {

match parse::parse(&item) {
Ok(init) => {
let mut item = without_param_attrs(item);
let item = without_param_attrs(item);

// Yes, all of this is to add `fj::abi::initialize_panic_handling();` to the top of the function.
item.block.stmts.insert(
0,
Stmt::Semi(
Expr::Call(ExprCall {
attrs: vec![],
func: Box::new(Expr::Path(ExprPath {
attrs: vec![],
qself: None,
path: syn::Path {
leading_colon: None,
segments: {
let mut segments = Punctuated::new();
let attrs = item.attrs;
let vis = item.vis;
let sig = item.sig;
let statements = item.block.stmts;

segments.push(PathSegment {
ident: Ident::new(
"fj",
Span::call_site(),
),
arguments: PathArguments::None,
});

segments.push(PathSegment {
ident: Ident::new(
"abi",
Span::call_site(),
),
arguments: PathArguments::None,
});

segments.push(PathSegment {
ident: Ident::new(
"initialize_panic_handling",
Span::call_site(),
),
arguments: PathArguments::None,
});

segments
},
},
})),
paren_token: Paren {
span: Span::call_site(),
},
args: Punctuated::new(),
}),
syn::token::Semi::default(),
),
);
let item = quote::quote! {
#(#attrs)* #vis #sig {
fj::abi::initialize_panic_handling();
#(#statements)*
}
};

let tokens = quote::quote! {
#item
#init

};

eprintln!("TOKENS: {}", tokens);

tokens.into()
}
Err(e) => e.into_compile_error().into(),
Expand Down
1 change: 1 addition & 0 deletions crates/fj/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ anyhow = "1.0.70"

[dependencies]
fj-proc.workspace = true
backtrace = "0.3.67"

[dependencies.serde]
version = "1.0.158"
Expand Down
11 changes: 10 additions & 1 deletion crates/fj/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ mod host;
mod metadata;
mod model;

use backtrace::Backtrace;
use std::{any::Any, fmt::Display, panic, sync::Mutex};

pub use self::{
Expand Down Expand Up @@ -122,6 +123,7 @@ pub const INIT_FUNCTION_NAME: &str = "fj_model_init";
struct PanicInfo {
message: Option<String>,
location: Option<Location>,
backtrace: Backtrace,
}

impl Display for PanicInfo {
Expand All @@ -139,6 +141,8 @@ impl Display for PanicInfo {
write!(f, "no location given")?;
}

writeln!(f, "\nBacktrace:\n{:?}", self.backtrace)?;

Ok(())
}
}
Expand Down Expand Up @@ -180,7 +184,12 @@ pub fn initialize_panic_handling() {
column: location.column(),
});

*last_panic = Some(PanicInfo { message, location });
let backtrace = backtrace::Backtrace::new();
*last_panic = Some(PanicInfo {
message,
location,
backtrace,
});
}));
}

Expand Down