Nimblesite / Nimblesite/Basilisk
calls_argument_type checks str.join arguments syntactically: 4 false positives on valid list displays, and a missed genuine error
@abdushakoor12 is already working on this.
Since Jul 25, 2026.
- Dominant language
- Rust
- Stars
- 54
- Forks
- 3
- PR merge metrics
- No merged PRs in 30d
Description
Summary
calls_argument_type checks built-in method arguments against the syntactic shape of the expression (RhsKind), not against its type. For str.join, the effect is a rule that is wrong in both directions: it rejects valid code whenever a list/tuple/set display contains anything other than a string literal, and it silently accepts a genuinely wrong argument.
This is the remaining half of #332. The dict-display and returned-tuple cases from that report are fixed on main; the list-display cases are not, and the underlying cause is unrelated to the contextual-inference fix that closed the dict half.
False positives
Every line below is valid Python and valid typing. All four are flagged.
def f(p: list[str], s: str) -> None:
" ".join(["a", *p]) # error — unpack element (the case reported in #332)
" ".join(["a", s]) # error — plain `str` variable element
" ".join([s.upper()]) # error — method call element
" ".join(("a", s)) # error — tuple form
error[calls_argument_type]: Argument `iterable` of `join` expects `Iterable[LiteralString] | Iterable[str]`
but received an argument incompatible with `Iterable[LiteralString] | Iterable[str]` (List([StrLiteral, Other]))
These pass, which is why it hides until a variable is involved:
" ".join(p) # OK — bare name
" ".join(["a", "b"]) # OK — all literals
" ".join([f"{s}!"]) # OK — f-string
False negative, from the same defect
def g(nums: list[int]) -> None:
" ".join(nums) # genuine type error — NOT reported
A bare name is RhsKind::Other and Other is accepted unconditionally at the top level, so the declared list[int] is never consulted.
Relatedly, " ".join(["a", n]) with n: int is reported — but only by accident. n classifies as Other, exactly like the valid s: str case above, and the emitted diagnostic is byte-identical. The rule cannot distinguish them.
Cause
stub_argument_compatible, in the Iterable[str] | Iterable[LiteralString] branch:
RhsKind::StrLiteral | RhsKind::EmptyList | RhsKind::Other
| RhsKind::CallExpr | RhsKind::KnownCall(_) => true, // unknown ⇒ accept
RhsKind::List(items) | RhsKind::Tuple(items) | RhsKind::Set(items) => {
items.iter().all(|item| matches!(item, RhsKind::StrLiteral)) // elements: literals only
}
Other and CallExpr are given the benefit of the doubt at the top level, but the same kinds are rejected one level down as elements. The benefit-of-the-doubt policy simply stops at the container boundary. Since no branch resolves an element to a type, a correct list[str] and an incorrect list[int] are indistinguishable once they reach the element check.
Expected
- The four false-positive forms check cleanly.
" ".join(nums)withnums: list[int]is reported.- The negative controls that already work keep working:
" ".join([1, 2])still errors.
The fix is to resolve each element's declared type rather than matching on syntax; that closes the false positives and the false negative together. Extending the top-level "unknown ⇒ accept" rule to elements would silence the false positives alone, but would leave join unable to catch anything real.
Message quality
The rendered type is a Rust Debug of an internal enum, printed to the user verbatim at calls_argument_type.rs:157 (format!("... ({rhs:?})")):
(List([StrLiteral, Other]))
Other is meaningless to a user and List([...]) is not Python syntax. This should render a Python type.
Version
Reproduced identically on released 0.37.3 and on main @ adb158df (0.0.0-PLACEHOLDER) — 4 false positives and 1 false negative on both, so this is not a regression from the #332 work.
Repro lives at issue-332-dict-literal/app.py in the repro workspace (lines 76, 87, 117).
Refs
Refs #332
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.