{"record":{"id":"973fbc4e664594b5","repo":"astral-sh/ruff","slug":"module-to-include-at-least-one-segment","errorCode":null,"errorMessage":"module to include at least one segment","messagePattern":"module to include at least one segment","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/ruff_linter/src/rules/isort/types.rs","lineNumber":51,"sourceCode":"}\n\n#[derive(Debug, Default, Clone)]\npub(crate) struct ImportFromCommentSet<'a> {\n    pub(crate) atop: Vec<Cow<'a, str>>,\n    pub(crate) inline: Vec<Cow<'a, str>>,\n    pub(crate) trailing: Vec<Cow<'a, str>>,\n}\n\npub(crate) trait Importable<'a> {\n    fn module_name(&self) -> Cow<'a, str>;\n\n    fn module_base(&self) -> Cow<'a, str> {\n        match self.module_name() {\n            Cow::Borrowed(module_name) => Cow::Borrowed(\n                module_name\n                    .split('.')\n                    .next()\n                    .expect(\"module to include at least one segment\"),\n            ),\n            Cow::Owned(module_name) => Cow::Owned(\n                module_name\n                    .split('.')\n                    .next()\n                    .expect(\"module to include at least one segment\")\n                    .to_owned(),\n            ),\n        }\n    }\n}\n\nimpl<'a> Importable<'a> for AliasData<'a> {\n    fn module_name(&self) -> Cow<'a, str> {\n        Cow::Borrowed(self.name)\n    }\n}\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_linter/src/rules/isort/types.rs#L33-L69","documentation":"isort's `module_base` returns the first dot-separated segment of a module name (e.g. `foo` from `foo.bar.baz`). The `.expect(\"module to include at least one segment\")` encodes the invariant that `str::split` always yields at least one item — which is true for any &str, since splitting never produces an empty iterator. The panic is therefore unreachable for borrowed module names.","triggerScenarios":"Not triggerable by user input: `\"\".split('.')` still yields one empty string. It could only fire if the code were changed to a different splitting method (e.g. a filter that drops empty segments) or if module_name could be a non-str type.","commonSituations":"Contributors hit this only as a false-positive code smell (clippy/analysis tools flagging the expect) or when refactoring module_name to an Option<Vec<Segment>> representation.","solutions":["Leave as-is: split().next() on a &str is infallible; consider documenting the invariant in the comment","If desired, use `match module_name.split('.').next() { Some(base) => ..., None => unreachable via types }` or model the module name as a non-empty type","Avoid switching to a filtering split that could legitimately return empty"],"exampleFix":"// before\nmodule_name.split('.').next().expect(\"module to include at least one segment\")\n// after\n// split always yields at least one item; keep expect or switch to a non-empty type\nmodule_name.split('.').next().unwrap_or(module_name)","handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn module_base_safe(name: &str) -> &str { name.split('.').next().unwrap_or(name) }","tryCatchPattern":null,"preventionTips":["Remember str::split never yields an empty iterator — this expect is unreachable","Document the invariant where the expect lives","Model non-empty strings in the type system if the invariant matters"],"tags":["rust","panic","isort","invariant"],"backgroundTag":"unreachable-expect-panic","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}