From 5efec7922a40a2cf7a31f069fda4d06adffbcc3f Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 21 Mar 2023 21:28:40 -0400 Subject: [PATCH 1/6] An attempt at a more advanced panic logger. --- crates/fj-app/src/main.rs | 4 ++ crates/fj/src/abi/mod.rs | 91 ++++++++++++++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index 1b4c51128..ffa435faa 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -19,6 +19,7 @@ mod path; use std::{env, error::Error}; use anyhow::{anyhow, Context}; +use fj::abi; use fj_export::export; use fj_host::Parameters; use fj_operations::shape_processor::ShapeProcessor; @@ -36,6 +37,9 @@ fn main() -> anyhow::Result<()> { .event_format(format().pretty()) .init(); + // We need to initialize panic handling before attempting to load a model. + abi::initialize_panic_handling(); + let args = Args::parse(); let config = Config::load()?; let model_path = ModelPath::from_args_and_config(&args, &config); diff --git a/crates/fj/src/abi/mod.rs b/crates/fj/src/abi/mod.rs index 5a237bc94..f31847a07 100644 --- a/crates/fj/src/abi/mod.rs +++ b/crates/fj/src/abi/mod.rs @@ -43,7 +43,7 @@ mod host; mod metadata; mod model; -use std::any::Any; +use std::{any::Any, fmt::Display, panic, sync::Mutex}; pub use self::{ context::Context, @@ -118,15 +118,86 @@ pub type ModelMetadataResult = /// pub const INIT_FUNCTION_NAME: &str = "fj_model_init"; -fn on_panic(payload: Box) -> crate::abi::ffi_safe::String { - let msg: &str = - if let Some(s) = payload.downcast_ref::() { - s.as_str() - } else if let Some(s) = payload.downcast_ref::<&str>() { - s +// Contains details about a panic that we need to pass back to the application from the panic hook. +struct PanicInfo { + message: Option, + location: Option, +} + +impl Display for PanicInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let message = self + .message + .as_ref() + .map_or("No error given", |message| message.as_str()); + + write!(f, "{}, ", message)?; + + if let Some(location) = self.location.as_ref() { + write!(f, "{}", location)?; + } else { + write!(f, "No location given")?; + } + + Ok(()) + } +} + +struct Location { + file: String, + line: u32, + column: u32, +} + +impl Display for Location { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}:{}", self.file, self.line, self.column) + } +} + +static LAST_PANIC: Mutex> = Mutex::new(None); + +/// Capturing panics is something Rust really doesn't want you to do, and as such, they make it convoluted. +/// This sets up all the machinery in the background to pull it off. +/// +/// It's okay to call this multiple times. +pub fn initialize_panic_handling() { + panic::set_hook(Box::new(|panic_info| { + let mut last_panic = + LAST_PANIC.lock().expect("Panic queue was poisoned."); // FIXME that can probably overflow the stack. + let message = if let Some(s) = + panic_info.payload().downcast_ref::() + { + Some(s.as_str()) } else { - "A panic occurred" - }; + panic_info.payload().downcast_ref::<&str>().copied() + } + .map(|s| s.to_string()); - crate::abi::ffi_safe::String::from(msg.to_string()) + let location = panic_info.location().map(|location| Location { + file: location.file().to_string(), + line: location.line(), + column: location.column(), + }); + + *last_panic = Some(PanicInfo { message, location }); + })); +} + +fn on_panic(_payload: Box) -> crate::abi::ffi_safe::String { + // The payload is technically no longer needed, but I left it there just in case a change to `catch_unwind` made + // it useful again. + if let Ok(mut panic_info) = LAST_PANIC.lock() { + if let Some(panic_info) = panic_info.take() { + crate::abi::ffi_safe::String::from(format!("{}", panic_info)) + } else { + crate::abi::ffi_safe::String::from( + "Panic in model: No details were given.".to_string(), + ) + } + } else { + crate::abi::ffi_safe::String::from( + "Panic in model, but due to a poisoned panic queue the information could not be collected." + .to_string()) + } } From 4c5bdb9e73fdc3cf6886b1ac2d4e2a67b982bfdf Mon Sep 17 00:00:00 2001 From: James Carl Date: Wed, 22 Mar 2023 22:06:40 -0400 Subject: [PATCH 2/6] Moved panic handler location to correct location. --- crates/fj-app/src/main.rs | 4 --- crates/fj-proc/src/lib.rs | 62 +++++++++++++++++++++++++++++++++++++-- crates/fj/src/abi/mod.rs | 9 ++++-- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index ffa435faa..1b4c51128 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -19,7 +19,6 @@ mod path; use std::{env, error::Error}; use anyhow::{anyhow, Context}; -use fj::abi; use fj_export::export; use fj_host::Parameters; use fj_operations::shape_processor::ShapeProcessor; @@ -37,9 +36,6 @@ fn main() -> anyhow::Result<()> { .event_format(format().pretty()) .init(); - // We need to initialize panic handling before attempting to load a model. - abi::initialize_panic_handling(); - let args = Args::parse(); let config = Config::load()?; let model_path = ModelPath::from_args_and_config(&args, &config); diff --git a/crates/fj-proc/src/lib.rs b/crates/fj-proc/src/lib.rs index a97357488..6566e247e 100644 --- a/crates/fj-proc/src/lib.rs +++ b/crates/fj-proc/src/lib.rs @@ -2,7 +2,11 @@ mod expand; mod parse; use proc_macro::TokenStream; -use syn::{parse_macro_input, FnArg, ItemFn}; +use proc_macro2::{Ident, Span}; +use syn::{ + parse_macro_input, punctuated::Punctuated, token::Paren, Expr, ExprCall, + ExprPath, FnArg, ItemFn, PathArguments, PathSegment, Stmt, +}; /// Define a function-based model. /// @@ -91,13 +95,67 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream { match parse::parse(&item) { Ok(init) => { - let item = without_param_attrs(item); + let mut 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(); + + 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 tokens = quote::quote! { #item #init + }; + eprintln!("TOKENS: {}", tokens); + tokens.into() } Err(e) => e.into_compile_error().into(), diff --git a/crates/fj/src/abi/mod.rs b/crates/fj/src/abi/mod.rs index f31847a07..f142539d4 100644 --- a/crates/fj/src/abi/mod.rs +++ b/crates/fj/src/abi/mod.rs @@ -131,12 +131,12 @@ impl Display for PanicInfo { .as_ref() .map_or("No error given", |message| message.as_str()); - write!(f, "{}, ", message)?; + write!(f, "\"{}\", ", message)?; if let Some(location) = self.location.as_ref() { write!(f, "{}", location)?; } else { - write!(f, "No location given")?; + write!(f, "no location given")?; } Ok(()) @@ -189,7 +189,10 @@ fn on_panic(_payload: Box) -> crate::abi::ffi_safe::String { // it useful again. if let Ok(mut panic_info) = LAST_PANIC.lock() { if let Some(panic_info) = panic_info.take() { - crate::abi::ffi_safe::String::from(format!("{}", panic_info)) + crate::abi::ffi_safe::String::from(format!( + "Panic in model: {}", + panic_info + )) } else { crate::abi::ffi_safe::String::from( "Panic in model: No details were given.".to_string(), From 583e726623230f0c196aec3d7cb484cd2c8cbbac Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 23 Mar 2023 17:08:01 -0400 Subject: [PATCH 3/6] Successfully printing backtraces. --- Cargo.lock | 1 + crates/fj/Cargo.toml | 1 + crates/fj/src/abi/mod.rs | 12 +++++++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f6d2aba8c..5dcd51494 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1039,6 +1039,7 @@ name = "fj" version = "0.41.0" dependencies = [ "anyhow", + "backtrace", "fj-proc", "serde", "serde_json", diff --git a/crates/fj/Cargo.toml b/crates/fj/Cargo.toml index 7e99f949a..212278e7b 100644 --- a/crates/fj/Cargo.toml +++ b/crates/fj/Cargo.toml @@ -17,6 +17,7 @@ anyhow = "1.0.70" [dependencies] fj-proc.workspace = true +backtrace = "0.3.67" [dependencies.serde] version = "1.0.158" diff --git a/crates/fj/src/abi/mod.rs b/crates/fj/src/abi/mod.rs index f142539d4..81ae41ec2 100644 --- a/crates/fj/src/abi/mod.rs +++ b/crates/fj/src/abi/mod.rs @@ -45,6 +45,8 @@ mod model; use std::{any::Any, fmt::Display, panic, sync::Mutex}; +use backtrace::Backtrace; + pub use self::{ context::Context, host::Host, @@ -122,6 +124,7 @@ pub const INIT_FUNCTION_NAME: &str = "fj_model_init"; struct PanicInfo { message: Option, location: Option, + backtrace: Backtrace, } impl Display for PanicInfo { @@ -139,6 +142,8 @@ impl Display for PanicInfo { write!(f, "no location given")?; } + writeln!(f, "\nBacktrace:\n{:?}", self.backtrace)?; + Ok(()) } } @@ -180,7 +185,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, + }); })); } From 5253636eedc1fe1f6c2c9fae63a8ea5e93519c0b Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 23 Mar 2023 17:36:26 -0400 Subject: [PATCH 4/6] Replaced syn cruft with quote macro. --- crates/fj-proc/src/lib.rs | 70 +++++++-------------------------------- 1 file changed, 12 insertions(+), 58 deletions(-) diff --git a/crates/fj-proc/src/lib.rs b/crates/fj-proc/src/lib.rs index 6566e247e..e2c4ae258 100644 --- a/crates/fj-proc/src/lib.rs +++ b/crates/fj-proc/src/lib.rs @@ -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. /// @@ -95,67 +91,25 @@ 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(), From 8aceee5990acfaf40d87e75d8c7a28cf4bfc8ed4 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 23 Mar 2023 17:45:39 -0400 Subject: [PATCH 5/6] Merge branch 'main' into better-model-panics --- .../fj-kernel/src/algorithms/approx/edge.rs | 2 +- .../fj-kernel/src/algorithms/reverse/cycle.rs | 2 +- .../fj-kernel/src/algorithms/reverse/face.rs | 2 +- .../fj-kernel/src/algorithms/sweep/curve.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/edge.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/face.rs | 2 +- .../fj-kernel/src/algorithms/sweep/sketch.rs | 2 +- .../fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- .../fj-kernel/src/algorithms/transform/mod.rs | 2 +- crates/fj-kernel/src/builder/cycle.rs | 2 +- crates/fj-kernel/src/builder/edge.rs | 2 +- crates/fj-kernel/src/builder/face.rs | 48 +----------- crates/fj-kernel/src/builder/mod.rs | 7 +- crates/fj-kernel/src/builder/shell.rs | 38 ---------- crates/fj-kernel/src/lib.rs | 2 +- crates/fj-kernel/src/operations/build/face.rs | 66 ++++++++++++++++ crates/fj-kernel/src/operations/build/mod.rs | 9 +++ .../fj-kernel/src/operations/build/shell.rs | 76 +++++++++++++++++++ .../{builder => operations/build}/surface.rs | 12 +-- .../fj-kernel/src/{ => operations}/insert.rs | 17 ++--- crates/fj-kernel/src/operations/mod.rs | 11 +++ .../fj-kernel/src/operations/update/cycle.rs | 32 ++++++++ .../fj-kernel/src/operations/update/edge.rs | 21 +++++ .../fj-kernel/src/operations/update/face.rs | 29 +++++++ crates/fj-kernel/src/operations/update/mod.rs | 9 +++ .../fj-kernel/src/operations/update/shell.rs | 45 +++++++++++ crates/fj-kernel/src/services/mod.rs | 5 +- crates/fj-kernel/src/services/objects.rs | 17 +---- crates/fj-kernel/src/validate/shell.rs | 67 ++++++---------- crates/fj-operations/src/difference_2d.rs | 2 +- crates/fj-operations/src/sketch.rs | 2 +- crates/fj-operations/src/sweep.rs | 2 +- crates/fj-proc/src/lib.rs | 3 + crates/fj/src/abi/mod.rs | 3 +- 34 files changed, 362 insertions(+), 183 deletions(-) delete mode 100644 crates/fj-kernel/src/builder/shell.rs create mode 100644 crates/fj-kernel/src/operations/build/face.rs create mode 100644 crates/fj-kernel/src/operations/build/mod.rs create mode 100644 crates/fj-kernel/src/operations/build/shell.rs rename crates/fj-kernel/src/{builder => operations/build}/surface.rs (62%) rename crates/fj-kernel/src/{ => operations}/insert.rs (68%) create mode 100644 crates/fj-kernel/src/operations/mod.rs create mode 100644 crates/fj-kernel/src/operations/update/cycle.rs create mode 100644 crates/fj-kernel/src/operations/update/edge.rs create mode 100644 crates/fj-kernel/src/operations/update/face.rs create mode 100644 crates/fj-kernel/src/operations/update/mod.rs create mode 100644 crates/fj-kernel/src/operations/update/shell.rs diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 2077cc34d..5901e0d8f 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -264,8 +264,8 @@ mod tests { algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint}, builder::HalfEdgeBuilder, geometry::{curve::GlobalPath, surface::SurfaceGeometry}, - insert::Insert, objects::Surface, + operations::Insert, services::Services, }; diff --git a/crates/fj-kernel/src/algorithms/reverse/cycle.rs b/crates/fj-kernel/src/algorithms/reverse/cycle.rs index 040316d93..0a8338bf6 100644 --- a/crates/fj-kernel/src/algorithms/reverse/cycle.rs +++ b/crates/fj-kernel/src/algorithms/reverse/cycle.rs @@ -1,8 +1,8 @@ use itertools::Itertools; use crate::{ - insert::Insert, objects::{Cycle, HalfEdge, Objects}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/reverse/face.rs b/crates/fj-kernel/src/algorithms/reverse/face.rs index 3330ee822..9d486855f 100644 --- a/crates/fj-kernel/src/algorithms/reverse/face.rs +++ b/crates/fj-kernel/src/algorithms/reverse/face.rs @@ -1,6 +1,6 @@ use crate::{ - insert::Insert, objects::{Face, Objects}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 5f519bb48..31cf95793 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -5,8 +5,8 @@ use crate::{ curve::{Curve, GlobalPath}, surface::SurfaceGeometry, }, - insert::Insert, objects::{Objects, Surface}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index e52bd5db5..4526b163b 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -3,8 +3,8 @@ use fj_math::{Point, Scalar, Vector}; use crate::{ builder::HalfEdgeBuilder, - insert::Insert, objects::{Cycle, Face, HalfEdge, Objects, Surface, Vertex}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 81006d69c..465c74d92 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -7,8 +7,8 @@ use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, builder::CycleBuilder, geometry::curve::GlobalPath, - insert::Insert, objects::{Face, Objects, Shell}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/sketch.rs b/crates/fj-kernel/src/algorithms/sweep/sketch.rs index 53170a768..0ff2c6fe5 100644 --- a/crates/fj-kernel/src/algorithms/sweep/sketch.rs +++ b/crates/fj-kernel/src/algorithms/sweep/sketch.rs @@ -1,8 +1,8 @@ use fj_math::Vector; use crate::{ - insert::Insert, objects::{Objects, Sketch, Solid}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index d2f86193c..44d98010b 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -1,8 +1,8 @@ use fj_math::Vector; use crate::{ - insert::Insert, objects::{GlobalEdge, Objects, Vertex}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/transform/mod.rs b/crates/fj-kernel/src/algorithms/transform/mod.rs index c56b78d22..e00d029bb 100644 --- a/crates/fj-kernel/src/algorithms/transform/mod.rs +++ b/crates/fj-kernel/src/algorithms/transform/mod.rs @@ -15,8 +15,8 @@ use fj_math::{Transform, Vector}; use type_map::TypeMap; use crate::{ - insert::Insert, objects::Objects, + operations::Insert, services::Service, storage::{Handle, ObjectId}, }; diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index ee8ae6697..00a19d165 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -3,8 +3,8 @@ use itertools::Itertools; use crate::{ geometry::curve::Curve, - insert::Insert, objects::{Cycle, HalfEdge, Objects}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index b4bbccf64..857856ccb 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -3,8 +3,8 @@ use fj_math::{Arc, Point, Scalar}; use crate::{ geometry::curve::Curve, - insert::Insert, objects::{GlobalEdge, HalfEdge, Objects, Surface, Vertex}, + operations::Insert, services::Service, storage::Handle, }; diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index c450d5f37..3dc980233 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -1,14 +1,13 @@ -use fj_interop::{ext::ArrayExt, mesh::Color}; -use fj_math::Point; +use fj_interop::mesh::Color; use crate::{ - insert::Insert, - objects::{Cycle, Face, GlobalEdge, Objects, Surface}, + objects::{Face, Objects, Surface}, + operations::Insert, services::Service, storage::Handle, }; -use super::{CycleBuilder, HalfEdgeBuilder, SurfaceBuilder}; +use super::CycleBuilder; /// Builder API for [`Face`] pub struct FaceBuilder { @@ -28,45 +27,6 @@ impl FaceBuilder { } } - /// Create a triangle - pub fn triangle( - points: [impl Into>; 3], - edges: [Option>; 3], - objects: &mut Service, - ) -> (Handle, [Handle; 3]) { - let [a, b, c] = points.map(Into::into); - - let surface = - SurfaceBuilder::plane_from_points([a, b, c]).insert(objects); - let (exterior, global_edges) = { - let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map( - |(points, global_form)| { - let mut builder = - HalfEdgeBuilder::line_segment_from_global_points( - points, &surface, None, - ); - - if let Some(global_form) = global_form { - builder = builder.with_global_form(global_form); - } - - builder.build(objects).insert(objects) - }, - ); - - let cycle = Cycle::new(half_edges.clone()).insert(objects); - - let global_edges = - half_edges.map(|half_edge| half_edge.global_form().clone()); - - (cycle, global_edges) - }; - - let face = Face::new(surface, exterior, [], None).insert(objects); - - (face, global_edges) - } - /// Replace the face's exterior cycle pub fn with_exterior(mut self, exterior: CycleBuilder) -> Self { self.exterior = exterior; diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 1cbad97ac..5349098a1 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -4,10 +4,5 @@ mod cycle; mod edge; mod face; -mod shell; -mod surface; -pub use self::{ - cycle::CycleBuilder, edge::HalfEdgeBuilder, face::FaceBuilder, - shell::ShellBuilder, surface::SurfaceBuilder, -}; +pub use self::{cycle::CycleBuilder, edge::HalfEdgeBuilder, face::FaceBuilder}; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs deleted file mode 100644 index 81f14bf95..000000000 --- a/crates/fj-kernel/src/builder/shell.rs +++ /dev/null @@ -1,38 +0,0 @@ -use fj_math::Point; - -use crate::{ - objects::{Objects, Shell}, - services::Service, -}; - -use super::FaceBuilder; - -/// Builder API for [`Shell`] -pub struct ShellBuilder {} - -impl ShellBuilder { - /// Create a tetrahedron from the provided points - pub fn tetrahedron( - points: [impl Into>; 4], - objects: &mut Service, - ) -> Shell { - let [a, b, c, d] = points.map(Into::into); - - let (base, [ab, bc, ca]) = - FaceBuilder::triangle([a, b, c], [None, None, None], objects); - let (side_a, [_, bd, da]) = - FaceBuilder::triangle([a, b, d], [Some(ab), None, None], objects); - let (side_b, [_, _, dc]) = FaceBuilder::triangle( - [c, a, d], - [Some(ca), Some(da), None], - objects, - ); - let (side_c, _) = FaceBuilder::triangle( - [b, c, d], - [Some(bc), Some(dc), Some(bd)], - objects, - ); - - Shell::new([base, side_a, side_b, side_c]) - } -} diff --git a/crates/fj-kernel/src/lib.rs b/crates/fj-kernel/src/lib.rs index 9f035bbc6..952e0fb27 100644 --- a/crates/fj-kernel/src/lib.rs +++ b/crates/fj-kernel/src/lib.rs @@ -90,8 +90,8 @@ pub mod algorithms; pub mod builder; pub mod geometry; -pub mod insert; pub mod objects; +pub mod operations; pub mod services; pub mod storage; pub mod validate; diff --git a/crates/fj-kernel/src/operations/build/face.rs b/crates/fj-kernel/src/operations/build/face.rs new file mode 100644 index 000000000..e4c5af4c3 --- /dev/null +++ b/crates/fj-kernel/src/operations/build/face.rs @@ -0,0 +1,66 @@ +use fj_interop::ext::ArrayExt; +use fj_math::Point; + +use crate::{ + builder::HalfEdgeBuilder, + objects::{Cycle, Face, GlobalEdge, Objects, Surface}, + operations::Insert, + services::Service, + storage::Handle, +}; + +use super::BuildSurface; + +/// Build a [`Face`] +pub trait BuildFace { + /// Build a triangle + fn triangle( + points: [impl Into>; 3], + edges: [Option>; 3], + objects: &mut Service, + ) -> Triangle { + let [a, b, c] = points.map(Into::into); + + let surface = Surface::plane_from_points([a, b, c]).insert(objects); + let (exterior, edges) = { + let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map( + |(points, global_form)| { + let mut builder = + HalfEdgeBuilder::line_segment_from_global_points( + points, &surface, None, + ); + + if let Some(global_form) = global_form { + builder = builder.with_global_form(global_form); + } + + builder.build(objects).insert(objects) + }, + ); + + let cycle = Cycle::new(half_edges.clone()).insert(objects); + + let global_edges = + half_edges.map(|half_edge| half_edge.global_form().clone()); + + (cycle, global_edges) + }; + + let face = Face::new(surface, exterior, [], None); + + Triangle { face, edges } + } +} + +impl BuildFace for Face {} + +/// A triangle +/// +/// Returned by [`BuildFace::triangle`]. +pub struct Triangle { + /// The face that forms the triangle + pub face: Face, + + /// The edges of the triangle + pub edges: [Handle; 3], +} diff --git a/crates/fj-kernel/src/operations/build/mod.rs b/crates/fj-kernel/src/operations/build/mod.rs new file mode 100644 index 000000000..8b0bd2521 --- /dev/null +++ b/crates/fj-kernel/src/operations/build/mod.rs @@ -0,0 +1,9 @@ +mod face; +mod shell; +mod surface; + +pub use self::{ + face::{BuildFace, Triangle}, + shell::{BuildShell, Tetrahedron}, + surface::BuildSurface, +}; diff --git a/crates/fj-kernel/src/operations/build/shell.rs b/crates/fj-kernel/src/operations/build/shell.rs new file mode 100644 index 000000000..a5b54957a --- /dev/null +++ b/crates/fj-kernel/src/operations/build/shell.rs @@ -0,0 +1,76 @@ +use fj_math::Point; + +use crate::{ + objects::{Face, Objects, Shell}, + operations::Insert, + services::Service, + storage::Handle, +}; + +use super::{BuildFace, Triangle}; + +/// Build a [`Shell`] +pub trait BuildShell { + /// Build a tetrahedron from the provided points + fn tetrahedron( + points: [impl Into>; 4], + objects: &mut Service, + ) -> Tetrahedron { + let [a, b, c, d] = points.map(Into::into); + + let Triangle { + face: face_abc, + edges: [ab, bc, ca], + } = Face::triangle([a, b, c], [None, None, None], objects); + let Triangle { + face: face_abd, + edges: [_, bd, da], + } = Face::triangle([a, b, d], [Some(ab), None, None], objects); + let Triangle { + face: face_cad, + edges: [_, _, dc], + } = Face::triangle([c, a, d], [Some(ca), Some(da), None], objects); + let Triangle { face: face_bcd, .. } = + Face::triangle([b, c, d], [Some(bc), Some(dc), Some(bd)], objects); + + let faces = [face_abc, face_abd, face_cad, face_bcd] + .map(|face| face.insert(objects)); + let shell = Shell::new(faces.clone()); + + let [face_abc, face_abd, face_cad, face_bcd] = faces; + + Tetrahedron { + shell, + face_abc, + face_abd, + face_cad, + face_bcd, + } + } +} + +impl BuildShell for Shell {} + +/// A tetrahedron +/// +/// A tetrahedron is constructed from 4 points and has 4 faces. For the purpose +/// of naming the fields of this struct, the points are named `a`, `b`, `c`, and +/// `d`, in the order in which they are passed. +/// +/// Returned by [`BuildShell::tetrahedron`]. +pub struct Tetrahedron { + /// The shell that forms the tetrahedron + pub shell: Shell, + + /// The face formed by the points `a`, `b`, and `c`. + pub face_abc: Handle, + + /// The face formed by the points `a`, `b`, and `d`. + pub face_abd: Handle, + + /// The face formed by the points `c`, `a`, and `d`. + pub face_cad: Handle, + + /// The face formed by the points `b`, `c`, and `d`. + pub face_bcd: Handle, +} diff --git a/crates/fj-kernel/src/builder/surface.rs b/crates/fj-kernel/src/operations/build/surface.rs similarity index 62% rename from crates/fj-kernel/src/builder/surface.rs rename to crates/fj-kernel/src/operations/build/surface.rs index 1b595f4aa..bd7bab739 100644 --- a/crates/fj-kernel/src/builder/surface.rs +++ b/crates/fj-kernel/src/operations/build/surface.rs @@ -5,12 +5,10 @@ use crate::{ objects::Surface, }; -/// Builder API for [`Surface`] -pub struct SurfaceBuilder {} - -impl SurfaceBuilder { - /// Create a plane from the provided points - pub fn plane_from_points(points: [impl Into>; 3]) -> Surface { +/// Build a [`Surface`] +pub trait BuildSurface { + /// Build a plane from the provided points + fn plane_from_points(points: [impl Into>; 3]) -> Surface { let [a, b, c] = points.map(Into::into); let geometry = SurfaceGeometry { @@ -21,3 +19,5 @@ impl SurfaceBuilder { Surface::new(geometry) } } + +impl BuildSurface for Surface {} diff --git a/crates/fj-kernel/src/insert.rs b/crates/fj-kernel/src/operations/insert.rs similarity index 68% rename from crates/fj-kernel/src/insert.rs rename to crates/fj-kernel/src/operations/insert.rs index 90b50ff41..ee1c77bf3 100644 --- a/crates/fj-kernel/src/insert.rs +++ b/crates/fj-kernel/src/operations/insert.rs @@ -1,19 +1,17 @@ -//! Convenience trait to insert objects into their respective stores -//! -//! See [`Insert`]. - use crate::{ objects::{ Cycle, Face, GlobalEdge, HalfEdge, Objects, Shell, Sketch, Solid, Surface, Vertex, }, - services::{Service, ServiceObjectsExt}, + services::{Operation, Service}, storage::Handle, - validate::Validate, }; -/// Convenience trait to insert objects into their respective stores -pub trait Insert: Sized + Validate { +/// Insert an object into its respective store +/// +/// This is the only primitive operation that is directly understood by +/// `Service`. All other operations are built on top of it. +pub trait Insert: Sized { /// Insert the object into its respective store fn insert(self, objects: &mut Service) -> Handle; } @@ -25,7 +23,8 @@ macro_rules! impl_insert { fn insert(self, objects: &mut Service) -> Handle { let handle = objects.$store.reserve(); - objects.insert((handle.clone(), self).into()); + let object = (handle.clone(), self).into(); + objects.execute(Operation::InsertObject { object }); handle } } diff --git a/crates/fj-kernel/src/operations/mod.rs b/crates/fj-kernel/src/operations/mod.rs new file mode 100644 index 000000000..6067f1735 --- /dev/null +++ b/crates/fj-kernel/src/operations/mod.rs @@ -0,0 +1,11 @@ +//! Operations to update shapes + +mod build; +mod insert; +mod update; + +pub use self::{ + build::{BuildFace, BuildShell, BuildSurface, Tetrahedron, Triangle}, + insert::Insert, + update::{UpdateCycle, UpdateFace, UpdateHalfEdge, UpdateShell}, +}; diff --git a/crates/fj-kernel/src/operations/update/cycle.rs b/crates/fj-kernel/src/operations/update/cycle.rs new file mode 100644 index 000000000..43e8d441b --- /dev/null +++ b/crates/fj-kernel/src/operations/update/cycle.rs @@ -0,0 +1,32 @@ +use crate::{ + objects::{Cycle, HalfEdge}, + storage::Handle, +}; + +/// Update a [`Cycle`] +pub trait UpdateCycle { + /// Update a half-edge of the cycle + fn update_half_edge( + &self, + index: usize, + f: impl FnMut(&Handle) -> Handle, + ) -> Cycle; +} + +impl UpdateCycle for Cycle { + fn update_half_edge( + &self, + index: usize, + mut f: impl FnMut(&Handle) -> Handle, + ) -> Cycle { + let half_edges = self.half_edges().enumerate().map(|(i, cycle)| { + if i == index { + f(cycle) + } else { + cycle.clone() + } + }); + + Cycle::new(half_edges) + } +} diff --git a/crates/fj-kernel/src/operations/update/edge.rs b/crates/fj-kernel/src/operations/update/edge.rs new file mode 100644 index 000000000..6a1f0f873 --- /dev/null +++ b/crates/fj-kernel/src/operations/update/edge.rs @@ -0,0 +1,21 @@ +use crate::{ + objects::{GlobalEdge, HalfEdge}, + storage::Handle, +}; + +/// Update a [`HalfEdge`] +pub trait UpdateHalfEdge { + /// Update the global form of the half-edge + fn update_global_form(&self, global_form: Handle) -> HalfEdge; +} + +impl UpdateHalfEdge for HalfEdge { + fn update_global_form(&self, global_form: Handle) -> HalfEdge { + HalfEdge::new( + self.curve(), + self.boundary(), + self.start_vertex().clone(), + global_form, + ) + } +} diff --git a/crates/fj-kernel/src/operations/update/face.rs b/crates/fj-kernel/src/operations/update/face.rs new file mode 100644 index 000000000..c4e27ebcd --- /dev/null +++ b/crates/fj-kernel/src/operations/update/face.rs @@ -0,0 +1,29 @@ +use crate::{ + objects::{Cycle, Face}, + storage::Handle, +}; + +/// Update a [`Face`] +pub trait UpdateFace { + /// Update the exterior of the face + fn update_exterior( + &self, + f: impl FnOnce(&Handle) -> Handle, + ) -> Face; +} + +impl UpdateFace for Face { + fn update_exterior( + &self, + f: impl FnOnce(&Handle) -> Handle, + ) -> Face { + let exterior = f(self.exterior()); + + Face::new( + self.surface().clone(), + exterior, + self.interiors().cloned(), + self.color(), + ) + } +} diff --git a/crates/fj-kernel/src/operations/update/mod.rs b/crates/fj-kernel/src/operations/update/mod.rs new file mode 100644 index 000000000..73f5d0874 --- /dev/null +++ b/crates/fj-kernel/src/operations/update/mod.rs @@ -0,0 +1,9 @@ +mod cycle; +mod edge; +mod face; +mod shell; + +pub use self::{ + cycle::UpdateCycle, edge::UpdateHalfEdge, face::UpdateFace, + shell::UpdateShell, +}; diff --git a/crates/fj-kernel/src/operations/update/shell.rs b/crates/fj-kernel/src/operations/update/shell.rs new file mode 100644 index 000000000..f8717e666 --- /dev/null +++ b/crates/fj-kernel/src/operations/update/shell.rs @@ -0,0 +1,45 @@ +use crate::{ + objects::{Face, Shell}, + storage::Handle, +}; + +/// Update a [`Shell`] +pub trait UpdateShell { + /// Update a face of the shell + fn update_face( + &self, + handle: &Handle, + f: impl FnMut(&Handle) -> Handle, + ) -> Shell; + + /// Remove a face from the shell + fn remove_face(&self, handle: &Handle) -> Shell; +} + +impl UpdateShell for Shell { + fn update_face( + &self, + handle: &Handle, + mut f: impl FnMut(&Handle) -> Handle, + ) -> Shell { + let faces = self.faces().into_iter().map(|face| { + if face.id() == handle.id() { + f(face) + } else { + face.clone() + } + }); + + Shell::new(faces) + } + + fn remove_face(&self, handle: &Handle) -> Shell { + let faces = self + .faces() + .into_iter() + .filter(|face| face.id() == handle.id()) + .cloned(); + + Shell::new(faces) + } +} diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index 346a3ef7a..d40d4a825 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -13,7 +13,7 @@ use parking_lot::Mutex; use crate::objects::Objects; pub use self::{ - objects::{InsertObject, Operation, ServiceObjectsExt}, + objects::{InsertObject, Operation}, service::{Service, State}, validation::{Validation, ValidationFailed}, }; @@ -23,9 +23,6 @@ pub struct Services { /// The objects service /// /// Allows for inserting objects into a store after they were created. - /// - /// [`ServiceObjectsExt`] is available to provide a convenient API around - /// this service. pub objects: Service, /// The validation service diff --git a/crates/fj-kernel/src/services/objects.rs b/crates/fj-kernel/src/services/objects.rs index d5f530fa8..d7b387fed 100644 --- a/crates/fj-kernel/src/services/objects.rs +++ b/crates/fj-kernel/src/services/objects.rs @@ -1,6 +1,6 @@ use crate::objects::{Object, Objects, WithHandle}; -use super::{Service, State}; +use super::State; impl State for Objects { type Command = Operation; @@ -23,9 +23,6 @@ pub enum Operation { /// /// This is the one primitive operation that all other operations are built /// upon. - /// - /// You might prefer to use [`ServiceObjectsExt::insert`], which is a - /// convenient wrapper around `Service::execute`. InsertObject { /// The object to insert object: Object, @@ -38,15 +35,3 @@ pub struct InsertObject { /// The object to insert pub object: Object, } - -/// Convenient API for `Service` -pub trait ServiceObjectsExt { - /// Insert an object - fn insert(&mut self, object: Object); -} - -impl ServiceObjectsExt for Service { - fn insert(&mut self, object: Object) { - self.execute(Operation::InsertObject { object }); - } -} diff --git a/crates/fj-kernel/src/validate/shell.rs b/crates/fj-kernel/src/validate/shell.rs index 7deba2f69..11d2815b9 100644 --- a/crates/fj-kernel/src/validate/shell.rs +++ b/crates/fj-kernel/src/validate/shell.rs @@ -193,9 +193,11 @@ impl ShellValidationError { mod tests { use crate::{ assert_contains_err, - builder::{CycleBuilder, FaceBuilder, ShellBuilder}, - insert::Insert, - objects::Shell, + objects::{GlobalEdge, Shell}, + operations::{ + BuildShell, Insert, UpdateCycle, UpdateFace, UpdateHalfEdge, + UpdateShell, + }, services::Services, validate::{shell::ShellValidationError, Validate, ValidationError}, }; @@ -204,35 +206,26 @@ mod tests { fn coincident_not_identical() -> anyhow::Result<()> { let mut services = Services::new(); - let valid = ShellBuilder::tetrahedron( + let valid = Shell::tetrahedron( [[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], &mut services.objects, ); - let invalid = { - let face1 = FaceBuilder::new(services.objects.surfaces.xy_plane()) - .with_exterior(CycleBuilder::polygon([ - [0., 0.], - [0., 1.], - [1., 1.], - [1., 0.], - ])) - .build(&mut services.objects) - .insert(&mut services.objects); - - let face2 = FaceBuilder::new(services.objects.surfaces.xz_plane()) - .with_exterior(CycleBuilder::polygon([ - [0., 0.], - [0., 1.], - [1., 1.], - [1., 0.], - ])) - .build(&mut services.objects) - .insert(&mut services.objects); - - Shell::new([face1, face2]) - }; + let invalid = valid.shell.update_face(&valid.face_abc, |face| { + face.update_exterior(|cycle| { + cycle + .update_half_edge(0, |half_edge| { + let global_form = + GlobalEdge::new().insert(&mut services.objects); + half_edge + .update_global_form(global_form) + .insert(&mut services.objects) + }) + .insert(&mut services.objects) + }) + .insert(&mut services.objects) + }); - valid.validate_and_return_first_error()?; + valid.shell.validate_and_return_first_error()?; assert_contains_err!( invalid, ValidationError::Shell( @@ -246,25 +239,13 @@ mod tests { fn shell_not_watertight() -> anyhow::Result<()> { let mut services = Services::new(); - let valid = ShellBuilder::tetrahedron( + let valid = Shell::tetrahedron( [[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], &mut services.objects, ); - let invalid = { - // Shell with single face is not watertight - let face = FaceBuilder::new(services.objects.surfaces.xy_plane()) - .with_exterior(CycleBuilder::polygon([ - [0., 0.], - [0., 1.], - [1., 1.], - [1., 0.], - ])) - .build(&mut services.objects) - .insert(&mut services.objects); - Shell::new([face]) - }; + let invalid = valid.shell.remove_face(&valid.face_abc); - valid.validate_and_return_first_error()?; + valid.shell.validate_and_return_first_error()?; assert_contains_err!( invalid, ValidationError::Shell(ShellValidationError::NotWatertight) diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index 758dd5210..7fd07ff5f 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -3,8 +3,8 @@ use std::ops::Deref; use fj_interop::{debug::DebugInfo, ext::ArrayExt, mesh::Color}; use fj_kernel::{ algorithms::reverse::Reverse, - insert::Insert, objects::{Face, Objects, Sketch}, + operations::Insert, services::Service, }; use fj_math::Aabb; diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 83b7ad565..72b071312 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -3,8 +3,8 @@ use std::ops::Deref; use fj_interop::{debug::DebugInfo, mesh::Color}; use fj_kernel::{ builder::{CycleBuilder, HalfEdgeBuilder}, - insert::Insert, objects::{Cycle, Face, Objects, Sketch}, + operations::Insert, services::Service, }; use fj_math::{Aabb, Point}; diff --git a/crates/fj-operations/src/sweep.rs b/crates/fj-operations/src/sweep.rs index 3235571d7..21ccf566e 100644 --- a/crates/fj-operations/src/sweep.rs +++ b/crates/fj-operations/src/sweep.rs @@ -3,8 +3,8 @@ use std::ops::Deref; use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::sweep::Sweep, - insert::Insert, objects::{Objects, Solid}, + operations::Insert, services::Service, }; use fj_math::{Aabb, Vector}; diff --git a/crates/fj-proc/src/lib.rs b/crates/fj-proc/src/lib.rs index e2c4ae258..dad85bd24 100644 --- a/crates/fj-proc/src/lib.rs +++ b/crates/fj-proc/src/lib.rs @@ -108,8 +108,11 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream { let tokens = quote::quote! { #item #init + }; + eprintln!("TOKENS: {}", tokens); + tokens.into() } Err(e) => e.into_compile_error().into(), diff --git a/crates/fj/src/abi/mod.rs b/crates/fj/src/abi/mod.rs index 81ae41ec2..d6e7c2363 100644 --- a/crates/fj/src/abi/mod.rs +++ b/crates/fj/src/abi/mod.rs @@ -43,9 +43,8 @@ mod host; mod metadata; mod model; -use std::{any::Any, fmt::Display, panic, sync::Mutex}; - use backtrace::Backtrace; +use std::{any::Any, fmt::Display, panic, sync::Mutex}; pub use self::{ context::Context, From 595c1b7b7fa38924cbbd6e64b187459fed6dbedd Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 25 Mar 2023 16:30:50 -0400 Subject: [PATCH 6/6] Cleaned up some leftover merge cruft. --- crates/fj-proc/src/lib.rs | 61 ++------------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/crates/fj-proc/src/lib.rs b/crates/fj-proc/src/lib.rs index fa7eeb706..9c43aec92 100644 --- a/crates/fj-proc/src/lib.rs +++ b/crates/fj-proc/src/lib.rs @@ -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. /// @@ -95,58 +91,7 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream { match parse::parse(&item) { Ok(init) => { - let mut 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(); - - 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 = without_param_attrs(item); let attrs = item.attrs; let vis = item.vis; @@ -166,8 +111,6 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream { }; - eprintln!("TOKENS: {}", tokens); - tokens.into() } Err(e) => e.into_compile_error().into(),