Skip to content

Commit e9ba848

Browse files
AlexWaygoodclaude
andauthored
[ty] Fix excess subscript argument inference for non-generic types (#24354)
## Summary When a non-generic type (like `list[int]`) is subscripted with excess arguments (e.g., `list[int][0]`), the excess arguments should be inferred as regular expressions, not type expressions. This prevents spurious "Int literals are not allowed in this context" errors. The fix checks if the base type has any type variables. If `typevars_len == 0`, we know it's not a generic type, so excess subscript arguments are inferred using `infer_expression()` with a default context instead of `infer_type_expression()`. This allows us to properly handle non-type values in excess subscripts while still reporting the primary error that the type is not subscriptable. This change also eliminates a duplicate error message in the test case `list[int][0]`, reducing the error count from two to one. ## Test Plan mdtests updated Co-authored-by: Claude <[email protected]>
1 parent 60d4694 commit e9ba848

2 files changed

Lines changed: 9 additions & 4 deletions

File tree

crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,7 @@ def _(doubly_specialized: DoublySpecialized):
674674
# error: [not-subscriptable] "Cannot subscript non-generic type `<class 'list[int]'>`"
675675
List = list[int][int]
676676

677-
# TODO: one error would be enough here
678-
#
679677
# error: [not-subscriptable] "Cannot subscript non-generic type `<class 'list[int]'>`"
680-
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
681678
WorseList = list[int][0]
682679

683680
def _(doubly_specialized: List, doubly_specialized_2: WorseList):

crates/ty_python_semantic/src/types/infer/builder/subscript.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,15 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
632632
}
633633
}
634634
EitherOrBoth::Right(expr) => {
635-
inferred_type_arguments.push(self.infer_type_expression(expr));
635+
// If there are no typevars at all, this is not a generic type,
636+
// so we should not infer excess arguments as type expressions.
637+
// For example, `list[int][0]` — the `0` is not a type expression.
638+
if typevars_len == 0 {
639+
inferred_type_arguments
640+
.push(self.infer_expression(expr, TypeContext::default()));
641+
} else {
642+
inferred_type_arguments.push(self.infer_type_expression(expr));
643+
}
636644
first_excess_type_argument_index.get_or_insert(index);
637645
}
638646
}

0 commit comments

Comments
 (0)