@@ -55,6 +55,7 @@ use crate::types::{
55
55
typing_extensions_symbol_ty, BytesLiteralType , ClassType , FunctionType , KnownFunction ,
56
56
StringLiteralType , Truthiness , TupleType , Type , TypeArrayDisplay , UnionType ,
57
57
} ;
58
+ use crate :: util:: subscript:: PythonSubscript ;
58
59
use crate :: Db ;
59
60
60
61
use super :: { KnownClass , UnionBuilder } ;
@@ -1466,8 +1467,9 @@ impl<'db> TypeInferenceBuilder<'db> {
1466
1467
}
1467
1468
1468
1469
/// Emit a diagnostic declaring that an index is out of bounds for a tuple.
1469
- pub ( super ) fn tuple_index_out_of_bounds_diagnostic (
1470
+ pub ( super ) fn index_out_of_bounds_diagnostic (
1470
1471
& mut self ,
1472
+ kind : & ' static str ,
1471
1473
node : AnyNodeRef ,
1472
1474
tuple_ty : Type < ' db > ,
1473
1475
length : usize ,
@@ -1477,30 +1479,12 @@ impl<'db> TypeInferenceBuilder<'db> {
1477
1479
node,
1478
1480
"index-out-of-bounds" ,
1479
1481
format_args ! (
1480
- "Index {index} is out of bounds for tuple of type `{}` with length {length}" ,
1482
+ "Index {index} is out of bounds for {kind} `{}` with length {length}" ,
1481
1483
tuple_ty. display( self . db)
1482
1484
) ,
1483
1485
) ;
1484
1486
}
1485
1487
1486
- /// Emit a diagnostic declaring that an index is out of bounds for a string.
1487
- pub ( super ) fn string_index_out_of_bounds_diagnostic (
1488
- & mut self ,
1489
- node : AnyNodeRef ,
1490
- string_ty : Type < ' db > ,
1491
- length : usize ,
1492
- index : i64 ,
1493
- ) {
1494
- self . add_diagnostic (
1495
- node,
1496
- "index-out-of-bounds" ,
1497
- format_args ! (
1498
- "Index {index} is out of bounds for string `{}` with length {length}" ,
1499
- string_ty. display( self . db)
1500
- ) ,
1501
- ) ;
1502
- }
1503
-
1504
1488
/// Emit a diagnostic declaring that a type does not support subscripting.
1505
1489
pub ( super ) fn non_subscriptable_diagnostic (
1506
1490
& mut self ,
@@ -3192,30 +3176,15 @@ impl<'db> TypeInferenceBuilder<'db> {
3192
3176
) -> Type < ' db > {
3193
3177
match ( value_ty, slice_ty) {
3194
3178
// Ex) Given `("a", "b", "c", "d")[1]`, return `"b"`
3195
- ( Type :: Tuple ( tuple_ty) , Type :: IntLiteral ( int) ) if int >= 0 => {
3179
+ ( Type :: Tuple ( tuple_ty) , Type :: IntLiteral ( int) ) => {
3196
3180
let elements = tuple_ty. elements ( self . db ) ;
3197
- usize:: try_from ( int)
3198
- . ok ( )
3199
- . and_then ( |index| elements. get ( index) . copied ( ) )
3200
- . unwrap_or_else ( || {
3201
- self . tuple_index_out_of_bounds_diagnostic (
3202
- value_node. into ( ) ,
3203
- value_ty,
3204
- elements. len ( ) ,
3205
- int,
3206
- ) ;
3207
- Type :: Unknown
3208
- } )
3209
- }
3210
- // Ex) Given `("a", "b", "c", "d")[-1]`, return `"c"`
3211
- ( Type :: Tuple ( tuple_ty) , Type :: IntLiteral ( int) ) if int < 0 => {
3212
- let elements = tuple_ty. elements ( self . db ) ;
3213
- int. checked_neg ( )
3214
- . and_then ( |int| usize:: try_from ( int) . ok ( ) )
3215
- . and_then ( |index| elements. len ( ) . checked_sub ( index) )
3216
- . and_then ( |index| elements. get ( index) . copied ( ) )
3181
+ elements
3182
+ . iter ( )
3183
+ . python_subscript ( int)
3184
+ . copied ( )
3217
3185
. unwrap_or_else ( || {
3218
- self . tuple_index_out_of_bounds_diagnostic (
3186
+ self . index_out_of_bounds_diagnostic (
3187
+ "tuple" ,
3219
3188
value_node. into ( ) ,
3220
3189
value_ty,
3221
3190
elements. len ( ) ,
@@ -3231,19 +3200,20 @@ impl<'db> TypeInferenceBuilder<'db> {
3231
3200
Type :: IntLiteral ( i64:: from ( bool) ) ,
3232
3201
) ,
3233
3202
// Ex) Given `"value"[1]`, return `"a"`
3234
- ( Type :: StringLiteral ( literal_ty) , Type :: IntLiteral ( int) ) if int >= 0 => {
3203
+ ( Type :: StringLiteral ( literal_ty) , Type :: IntLiteral ( int) ) => {
3235
3204
let literal_value = literal_ty. value ( self . db ) ;
3236
- usize :: try_from ( int )
3237
- . ok ( )
3238
- . and_then ( |index| literal_value . chars ( ) . nth ( index ) )
3205
+ literal_value
3206
+ . chars ( )
3207
+ . python_subscript ( int )
3239
3208
. map ( |ch| {
3240
3209
Type :: StringLiteral ( StringLiteralType :: new (
3241
3210
self . db ,
3242
3211
ch. to_string ( ) . into_boxed_str ( ) ,
3243
3212
) )
3244
3213
} )
3245
3214
. unwrap_or_else ( || {
3246
- self . string_index_out_of_bounds_diagnostic (
3215
+ self . index_out_of_bounds_diagnostic (
3216
+ "string" ,
3247
3217
value_node. into ( ) ,
3248
3218
value_ty,
3249
3219
literal_value. chars ( ) . count ( ) ,
@@ -3252,31 +3222,28 @@ impl<'db> TypeInferenceBuilder<'db> {
3252
3222
Type :: Unknown
3253
3223
} )
3254
3224
}
3255
- // Ex) Given `"value"[- 1]`, return `"e "`
3256
- ( Type :: StringLiteral ( literal_ty) , Type :: IntLiteral ( int) ) if int < 0 => {
3225
+ // Ex) Given `b "value"[1]`, return `b"a "`
3226
+ ( Type :: BytesLiteral ( literal_ty) , Type :: IntLiteral ( int) ) => {
3257
3227
let literal_value = literal_ty. value ( self . db ) ;
3258
- int. checked_neg ( )
3259
- . and_then ( |int| usize:: try_from ( int) . ok ( ) )
3260
- . and_then ( |index| index. checked_sub ( 1 ) )
3261
- . and_then ( |index| literal_value. chars ( ) . rev ( ) . nth ( index) )
3262
- . map ( |ch| {
3263
- Type :: StringLiteral ( StringLiteralType :: new (
3264
- self . db ,
3265
- ch. to_string ( ) . into_boxed_str ( ) ,
3266
- ) )
3228
+ literal_value
3229
+ . iter ( )
3230
+ . python_subscript ( int)
3231
+ . map ( |byte| {
3232
+ Type :: BytesLiteral ( BytesLiteralType :: new ( self . db , [ * byte] . as_slice ( ) ) )
3267
3233
} )
3268
3234
. unwrap_or_else ( || {
3269
- self . string_index_out_of_bounds_diagnostic (
3235
+ self . index_out_of_bounds_diagnostic (
3236
+ "bytes literal" ,
3270
3237
value_node. into ( ) ,
3271
3238
value_ty,
3272
- literal_value. chars ( ) . count ( ) ,
3239
+ literal_value. len ( ) ,
3273
3240
int,
3274
3241
) ;
3275
3242
Type :: Unknown
3276
3243
} )
3277
3244
}
3278
3245
// Ex) Given `"value"[True]`, return `"a"`
3279
- ( Type :: StringLiteral ( _) , Type :: BooleanLiteral ( bool) ) => self
3246
+ ( Type :: StringLiteral ( _) | Type :: BytesLiteral ( _ ) , Type :: BooleanLiteral ( bool) ) => self
3280
3247
. infer_subscript_expression_types (
3281
3248
value_node,
3282
3249
value_ty,
0 commit comments