{"record":{"id":"7981122301552a28","repo":"pydantic/monty","slug":"test-function-has-a-free-variable","errorCode":null,"errorMessage":"test function has a free variable","messagePattern":"test function has a free variable","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/monty/src/function.rs","lineNumber":319,"sourceCode":"                }\n            })\n        } else {\n            None\n        }\n    }\n\n    /// Injects a metadata fault for dump validation tests.\n    #[cfg(feature = \"test-hooks\")]\n    pub(crate) fn corrupt_metadata_for_tests(&mut self, fault: FunctionMetadataFault) {\n        match fault {\n            FunctionMetadataFault::SignatureSlotsBeyondNamespace => {\n                self.namespace_size = self.signature.total_slots() - 1;\n            }\n            FunctionMetadataFault::NamespaceTooLarge => {\n                self.namespace_size = usize::from(u16::MAX) + 1;\n            }\n            FunctionMetadataFault::FreeVarLengthMismatch => {\n                self.free_var_slots.pop().expect(\"test function has a free variable\");\n            }\n            FunctionMetadataFault::CellVarLengthMismatch => {\n                self.cell_param_indices.pop().expect(\"test function has an owned cell\");\n            }\n            FunctionMetadataFault::FreeVarSlotOutOfRange => {\n                let slot = NamespaceId::new(self.namespace_size).expect(\"test namespace fits in u16\");\n                *self\n                    .free_var_slots\n                    .first_mut()\n                    .expect(\"test function has a free variable\") = slot;\n            }\n            FunctionMetadataFault::CellVarSlotOutOfRange => {\n                let slot = NamespaceId::new(self.namespace_size).expect(\"test namespace fits in u16\");\n                *self\n                    .cell_var_slots\n                    .first_mut()\n                    .expect(\"test function has an owned cell\") = slot;\n            }","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/function.rs#L301-L337","documentation":"A panic raised by the memory-model test fault injector in `FunctionMetadata::corrupt_metadata_for_tests`. The `FreeVarLengthMismatch` fault pops a slot from `free_var_slots`, which only works when the function actually has free variables; `.expect(\"test function has a free variable\")` panics when the list is empty. This is a test-harness bug (wrong fault kind applied to a function with no free vars), not a runtime error users can hit.","triggerScenarios":"Calling `corrupt_metadata_for_tests` with `FunctionMetadataFault::FreeVarLengthMismatch` on a `FunctionMetadata` whose `free_var_slots` vector is empty (e.g. a function with no closure captures).","commonSituations":"Writing a new memory-model/refcount test that applies the fault to a fixture function that has no free variables, or reusing a fault helper against a simplified test function.","solutions":["Point the fault injection at a test function that closes over at least one free variable","Choose a different `FunctionMetadataFault` variant appropriate to the function's actual metadata","Guard the fault site: skip or fall back to another fault when `free_var_slots` is empty"],"exampleFix":"// before\nFunctionMetadataFault::FreeVarLengthMismatch => {\n    self.free_var_slots.pop().expect(\"test function has a free variable\");\n}\n\n// after (test selection side)\nlet func = funcs.iter().find(|f| !f.free_var_slots.is_empty())\n    .expect(\"fixture must include a function with free vars\");\nfunc.corrupt_metadata_for_tests(FunctionMetadataFault::FreeVarLengthMismatch);","handlingStrategy":"validation","validationCode":"// Only apply FreeVarLengthMismatch to functions that have free variables.\nfn can_inject(fault: Fault, meta: &FunctionMetadata) -> bool {\n    match fault {\n        Fault::FreeVarLengthMismatch => !meta.free_var_slots.is_empty(),\n        Fault::CellVarLengthMismatch => !meta.cell_param_indices.is_empty(),\n        _ => true,\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick fault fixtures whose metadata actually contains the field the fault mutates","Add a fixture function with at least one closure capture for free-var faults","Prefer skipping an inapplicable fault over expect()-panicking in test helpers"],"tags":["rust","panic","test-harness","fault-injection"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}