diff --git a/.changes/unreleased/fixed-20260901-020000.yaml b/.changes/unreleased/fixed-20260901-020000.yaml new file mode 100644 index 00000000..26299d3b --- /dev/null +++ b/.changes/unreleased/fixed-20260901-020000.yaml @@ -0,0 +1,3 @@ +kind: Fixed +body: Generated proto2 defaults for `inf`, `-inf`, and `nan` now use absolute primitive paths, so protobuf packages or modules named `f32` or `f64` cannot shadow them. +time: 2026-09-01T02:00:00+02:00 diff --git a/buffa-codegen/src/defaults.rs b/buffa-codegen/src/defaults.rs index 1f30545f..ace9aa5f 100644 --- a/buffa-codegen/src/defaults.rs +++ b/buffa-codegen/src/defaults.rs @@ -221,23 +221,23 @@ where match s { "inf" | "infinity" => { if is_f32 { - Ok(quote! { f32::INFINITY }) + Ok(quote! { ::core::primitive::f32::INFINITY }) } else { - Ok(quote! { f64::INFINITY }) + Ok(quote! { ::core::primitive::f64::INFINITY }) } } "-inf" | "-infinity" => { if is_f32 { - Ok(quote! { f32::NEG_INFINITY }) + Ok(quote! { ::core::primitive::f32::NEG_INFINITY }) } else { - Ok(quote! { f64::NEG_INFINITY }) + Ok(quote! { ::core::primitive::f64::NEG_INFINITY }) } } "nan" => { if is_f32 { - Ok(quote! { f32::NAN }) + Ok(quote! { ::core::primitive::f32::NAN }) } else { - Ok(quote! { f64::NAN }) + Ok(quote! { ::core::primitive::f64::NAN }) } } _ => { @@ -514,19 +514,22 @@ mod tests { #[test] fn parse_float_inf() { let ts = parse_float_default::("inf").unwrap(); - assert!(ts.to_string().contains("INFINITY")); + assert_eq!(ts.to_string(), ":: core :: primitive :: f32 :: INFINITY"); } #[test] fn parse_float_neg_inf() { let ts = parse_float_default::("-inf").unwrap(); - assert!(ts.to_string().contains("NEG_INFINITY")); + assert_eq!( + ts.to_string(), + ":: core :: primitive :: f64 :: NEG_INFINITY" + ); } #[test] fn parse_float_nan() { let ts = parse_float_default::("nan").unwrap(); - assert!(ts.to_string().contains("NAN")); + assert_eq!(ts.to_string(), ":: core :: primitive :: f32 :: NAN"); } #[test] diff --git a/buffa-test/build.rs b/buffa-test/build.rs index e971ad2a..dd6beaaf 100644 --- a/buffa-test/build.rs +++ b/buffa-test/build.rs @@ -237,6 +237,17 @@ fn main() { .compile() .expect("buffa_build failed for prelude_shadow.proto"); + // Special float defaults in a package named `f32` must not resolve + // against generated `f32`/`f64` modules. The nested extension constants + // deliberately occupy all six shadowable paths; compilation is the + // regression assertion. + buffa_build::Config::new() + .files(&["protos/float_default_shadow.proto"]) + .includes(&["protos/"]) + .generate_views(false) + .compile() + .expect("buffa_build failed for float_default_shadow.proto"); + // Nested-package pair (gh#80) — `test.nestpkg` + `test.nestpkg.inner`. // `lib.rs` wraps these with the same `pub mod a { use super::*; pub mod // a_b { use super::*; … } }` chain that `buffa-build`'s `_include.rs` diff --git a/buffa-test/protos/float_default_shadow.proto b/buffa-test/protos/float_default_shadow.proto new file mode 100644 index 00000000..d9fc4811 --- /dev/null +++ b/buffa-test/protos/float_default_shadow.proto @@ -0,0 +1,30 @@ +syntax = "proto2"; + +package f32; + +message F32 { + extensions 100 to 200; + extend F32 { + optional float INFINITY = 100; + optional float NEG_INFINITY = 101; + optional float NAN = 102; + } +} + +message F64 { + extensions 200 to 300; + extend F64 { + optional double INFINITY = 200; + optional double NEG_INFINITY = 201; + optional double NAN = 202; + } +} + +message Defaults { + required float pos_inf = 1 [default = inf]; + required float neg_inf = 2 [default = -inf]; + required float nan_value = 3 [default = nan]; + required double double_pos_inf = 4 [default = inf]; + required double double_neg_inf = 5 [default = -inf]; + required double double_nan = 6 [default = nan]; +} diff --git a/buffa-test/src/lib.rs b/buffa-test/src/lib.rs index 3e7b3199..5fc13fc4 100644 --- a/buffa-test/src/lib.rs +++ b/buffa-test/src/lib.rs @@ -553,6 +553,11 @@ pub mod prelude_shadow { buffa::include_proto!("test.prelude_shadow"); } +#[allow(clippy::derivable_impls, clippy::match_single_binding, dead_code)] +pub mod float_default_shadow { + buffa::include_proto!("f32"); +} + // Nested-package pair, wrapped exactly the way `buffa-build`'s // `_include.rs` would. The chain of `use super::*;` glob imports makes the // outer package's `__buffa` reachable from `inner`'s scope, which is the