Skip to content

Commit b4de684

Browse files
committed
Remove implicit **kwargs injection
Using {**name} without declaring **name as a parameter would silently inject it into the function signature. This is wrong — the name could refer to a local variable, not an intended parameter. Spread requires explicit declaration, same as Python.
1 parent 0d60a35 commit b4de684

5 files changed

Lines changed: 0 additions & 82 deletions

File tree

rust/src/generate/python.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,15 +1704,6 @@ impl Generator for PythonGenerator {
17041704
}
17051705
}
17061706

1707-
// Implicit **kwargs: if body uses a single {**name} and no **kwargs param
1708-
// is declared, auto-add **name to the signature
1709-
let implicit_kwargs_name = if star_star_kwargs.is_none() && metadata.spread_names.len() == 1
1710-
{
1711-
metadata.spread_names.iter().next().cloned()
1712-
} else {
1713-
None
1714-
};
1715-
17161707
// Emit _content parameter first if default slot is used
17171708
let mut param_count = 0;
17181709
if has_default_slot {
@@ -1786,12 +1777,6 @@ impl Generator for PythonGenerator {
17861777
output.push(": ");
17871778
output.push(type_hint);
17881779
}
1789-
} else if let Some(name) = &implicit_kwargs_name {
1790-
if param_count > 0 || !regular_params.is_empty() || has_named_slots {
1791-
output.push(", ");
1792-
}
1793-
output.push("**");
1794-
output.push(name);
17951780
}
17961781

17971782
output.push("):");

rust/src/transform/metadata.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ pub struct TransformMetadata {
77
pub helpers_used: HashSet<String>,
88
pub is_async: bool,
99
pub slots_used: HashSet<String>,
10-
/// All {**name} spread variable names found in the body
11-
pub spread_names: HashSet<String>,
1210
}
1311

1412
impl TransformMetadata {

rust/src/transform/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ mod async_detect;
22
mod helper_detect;
33
mod metadata;
44
mod slot_detect;
5-
mod spread_detect;
65

76
pub use async_detect::AsyncDetectionPlugin;
87
pub use helper_detect::HelperDetectionPlugin;
98
pub use metadata::TransformMetadata;
109
pub use slot_detect::SlotDetectionPlugin;
11-
pub use spread_detect::SpreadDetectionPlugin;
1210

1311
use crate::ast::{Ast, Node};
1412

@@ -141,5 +139,4 @@ pub fn standard_plugins() -> Transformer {
141139
.add(HelperDetectionPlugin)
142140
.add(AsyncDetectionPlugin)
143141
.add(SlotDetectionPlugin)
144-
.add(SpreadDetectionPlugin)
145142
}

rust/src/transform/spread_detect.rs

Lines changed: 0 additions & 18 deletions
This file was deleted.

rust/tests/injection_tests.rs

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,47 +1412,3 @@ fn test_shorthand_and_spread_together_on_component() {
14121412
result.code
14131413
);
14141414
}
1415-
1416-
// ========================================================================
1417-
// Implicit spread edge cases
1418-
// ========================================================================
1419-
1420-
#[test]
1421-
fn test_implicit_spread_adds_kwargs_to_signature() {
1422-
// {**attrs} used without declaring **attrs — compiler auto-adds it
1423-
let source = "label: str\n---\n<button {**attrs}>{label}</button>";
1424-
let result = compile_with_ranges(source, "Test");
1425-
1426-
let sig = result.code.lines().find(|l| l.contains("def ")).unwrap();
1427-
assert!(
1428-
sig.contains("**attrs"),
1429-
"Implicit spread should add **attrs to signature. Got: {}",
1430-
sig
1431-
);
1432-
}
1433-
1434-
#[test]
1435-
fn test_multiple_spread_names_require_explicit_declaration() {
1436-
// Two elements use different spread names — implicit can't handle this
1437-
// (Python only allows one **kwargs), so both must be declared explicitly
1438-
let source = "container_attrs: dict\nbutton_attrs: dict\n---\n<div {**container_attrs}>\n <button {**button_attrs}>Click</button>\n</div>";
1439-
let result = compile_with_ranges(source, "Test");
1440-
1441-
assert!(
1442-
result.code.contains("spread_attrs(container_attrs)"),
1443-
"First spread should compile. Got:\n{}",
1444-
result.code
1445-
);
1446-
assert!(
1447-
result.code.contains("spread_attrs(button_attrs)"),
1448-
"Second spread should compile. Got:\n{}",
1449-
result.code
1450-
);
1451-
// Both are regular dict params, not **kwargs
1452-
let sig_line = result.code.lines().find(|l| l.contains("def ")).unwrap();
1453-
assert!(
1454-
sig_line.contains("container_attrs: dict") && sig_line.contains("button_attrs: dict"),
1455-
"Both should be regular dict params. Sig: {}",
1456-
sig_line
1457-
);
1458-
}

0 commit comments

Comments
 (0)