@@ -167,27 +167,27 @@ export function getTypeNarrowingCallback(
167
167
168
168
// Look for "type(X) is Y" or "type(X) is not Y".
169
169
if ( isOrIsNotOperator && testExpression . leftExpression . nodeType === ParseNodeType . Call ) {
170
- const callType = evaluator . getTypeOfExpression (
171
- testExpression . leftExpression . leftExpression ,
172
- EvaluatorFlags . DoNotSpecialize
173
- ) . type ;
174
-
175
170
if (
176
- isInstantiableClass ( callType ) &&
177
- ClassType . isBuiltIn ( callType , 'type' ) &&
178
171
testExpression . leftExpression . arguments . length === 1 &&
179
172
testExpression . leftExpression . arguments [ 0 ] . argumentCategory === ArgumentCategory . Simple
180
173
) {
181
174
const arg0Expr = testExpression . leftExpression . arguments [ 0 ] . valueExpression ;
182
175
if ( ParseTreeUtils . isMatchingExpression ( reference , arg0Expr ) ) {
183
- const classType = evaluator . makeTopLevelTypeVarsConcrete (
184
- evaluator . getTypeOfExpression ( testExpression . rightExpression ) . type
185
- ) ;
176
+ const callType = evaluator . getTypeOfExpression (
177
+ testExpression . leftExpression . leftExpression ,
178
+ EvaluatorFlags . DoNotSpecialize
179
+ ) . type ;
180
+
181
+ if ( isInstantiableClass ( callType ) && ClassType . isBuiltIn ( callType , 'type' ) ) {
182
+ const classType = evaluator . makeTopLevelTypeVarsConcrete (
183
+ evaluator . getTypeOfExpression ( testExpression . rightExpression ) . type
184
+ ) ;
186
185
187
- if ( isInstantiableClass ( classType ) ) {
188
- return ( type : Type ) => {
189
- return narrowTypeForTypeIs ( type , classType , adjIsPositiveTest ) ;
190
- } ;
186
+ if ( isInstantiableClass ( classType ) ) {
187
+ return ( type : Type ) => {
188
+ return narrowTypeForTypeIs ( type , classType , adjIsPositiveTest ) ;
189
+ } ;
190
+ }
191
191
}
192
192
}
193
193
}
@@ -424,106 +424,112 @@ export function getTypeNarrowingCallback(
424
424
}
425
425
426
426
if ( testExpression . nodeType === ParseNodeType . Call ) {
427
- const callType = evaluator . getTypeOfExpression (
428
- testExpression . leftExpression ,
429
- EvaluatorFlags . DoNotSpecialize
430
- ) . type ;
431
-
432
427
// Look for "isinstance(X, Y)" or "issubclass(X, Y)".
433
- if (
434
- isFunction ( callType ) &&
435
- ( callType . details . builtInName === 'isinstance' || callType . details . builtInName === 'issubclass' ) &&
436
- testExpression . arguments . length === 2
437
- ) {
428
+ if ( testExpression . arguments . length === 2 ) {
438
429
// Make sure the first parameter is a supported expression type
439
430
// and the second parameter is a valid class type or a tuple
440
431
// of valid class types.
441
- const isInstanceCheck = callType . details . builtInName === 'isinstance' ;
442
432
const arg0Expr = testExpression . arguments [ 0 ] . valueExpression ;
443
433
const arg1Expr = testExpression . arguments [ 1 ] . valueExpression ;
444
434
if ( ParseTreeUtils . isMatchingExpression ( reference , arg0Expr ) ) {
445
- const arg1Type = evaluator . getTypeOfExpression (
446
- arg1Expr ,
447
- EvaluatorFlags . EvaluateStringLiteralAsType |
448
- EvaluatorFlags . ParamSpecDisallowed |
449
- EvaluatorFlags . TypeVarTupleDisallowed
435
+ const callType = evaluator . getTypeOfExpression (
436
+ testExpression . leftExpression ,
437
+ EvaluatorFlags . DoNotSpecialize
450
438
) . type ;
451
439
452
- const classTypeList = getIsInstanceClassTypes ( arg1Type ) ;
440
+ if (
441
+ isFunction ( callType ) &&
442
+ ( callType . details . builtInName === 'isinstance' || callType . details . builtInName === 'issubclass' )
443
+ ) {
444
+ const isInstanceCheck = callType . details . builtInName === 'isinstance' ;
445
+ const arg1Type = evaluator . getTypeOfExpression (
446
+ arg1Expr ,
447
+ EvaluatorFlags . EvaluateStringLiteralAsType |
448
+ EvaluatorFlags . ParamSpecDisallowed |
449
+ EvaluatorFlags . TypeVarTupleDisallowed
450
+ ) . type ;
453
451
454
- if ( classTypeList ) {
455
- return ( type : Type ) => {
456
- const narrowedType = narrowTypeForIsInstance (
457
- evaluator ,
458
- type ,
459
- classTypeList ,
460
- isInstanceCheck ,
461
- isPositiveTest ,
462
- /* allowIntersections */ false ,
463
- testExpression
464
- ) ;
465
- if ( ! isNever ( narrowedType ) ) {
466
- return narrowedType ;
467
- }
452
+ const classTypeList = getIsInstanceClassTypes ( arg1Type ) ;
468
453
469
- // Try again with intersection types allowed.
470
- return narrowTypeForIsInstance (
471
- evaluator ,
472
- type ,
473
- classTypeList ,
474
- isInstanceCheck ,
475
- isPositiveTest ,
476
- /* allowIntersections */ true ,
477
- testExpression
478
- ) ;
479
- } ;
454
+ if ( classTypeList ) {
455
+ return ( type : Type ) => {
456
+ const narrowedType = narrowTypeForIsInstance (
457
+ evaluator ,
458
+ type ,
459
+ classTypeList ,
460
+ isInstanceCheck ,
461
+ isPositiveTest ,
462
+ /* allowIntersections */ false ,
463
+ testExpression
464
+ ) ;
465
+ if ( ! isNever ( narrowedType ) ) {
466
+ return narrowedType ;
467
+ }
468
+
469
+ // Try again with intersection types allowed.
470
+ return narrowTypeForIsInstance (
471
+ evaluator ,
472
+ type ,
473
+ classTypeList ,
474
+ isInstanceCheck ,
475
+ isPositiveTest ,
476
+ /* allowIntersections */ true ,
477
+ testExpression
478
+ ) ;
479
+ } ;
480
+ }
480
481
}
481
482
}
482
483
}
483
484
484
485
// Look for "callable(X)"
485
- if (
486
- isFunction ( callType ) &&
487
- callType . details . builtInName === 'callable' &&
488
- testExpression . arguments . length === 1
489
- ) {
486
+ if ( testExpression . arguments . length === 1 ) {
490
487
const arg0Expr = testExpression . arguments [ 0 ] . valueExpression ;
491
488
if ( ParseTreeUtils . isMatchingExpression ( reference , arg0Expr ) ) {
492
- return ( type : Type ) => {
493
- let narrowedType = narrowTypeForCallable (
494
- evaluator ,
495
- type ,
496
- isPositiveTest ,
497
- testExpression ,
498
- /* allowIntersections */ false
499
- ) ;
500
- if ( isPositiveTest && isNever ( narrowedType ) ) {
501
- // Try again with intersections allowed.
502
- narrowedType = narrowTypeForCallable (
489
+ const callType = evaluator . getTypeOfExpression (
490
+ testExpression . leftExpression ,
491
+ EvaluatorFlags . DoNotSpecialize
492
+ ) . type ;
493
+
494
+ if ( isFunction ( callType ) && callType . details . builtInName === 'callable' ) {
495
+ return ( type : Type ) => {
496
+ let narrowedType = narrowTypeForCallable (
503
497
evaluator ,
504
498
type ,
505
499
isPositiveTest ,
506
500
testExpression ,
507
- /* allowIntersections */ true
501
+ /* allowIntersections */ false
508
502
) ;
509
- }
503
+ if ( isPositiveTest && isNever ( narrowedType ) ) {
504
+ // Try again with intersections allowed.
505
+ narrowedType = narrowTypeForCallable (
506
+ evaluator ,
507
+ type ,
508
+ isPositiveTest ,
509
+ testExpression ,
510
+ /* allowIntersections */ true
511
+ ) ;
512
+ }
510
513
511
- return narrowedType ;
512
- } ;
514
+ return narrowedType ;
515
+ } ;
516
+ }
513
517
}
514
518
}
515
519
516
520
// Look for "bool(X)"
517
- if (
518
- isInstantiableClass ( callType ) &&
519
- ClassType . isBuiltIn ( callType , 'bool' ) &&
520
- testExpression . arguments . length === 1 &&
521
- ! testExpression . arguments [ 0 ] . name
522
- ) {
521
+ if ( testExpression . arguments . length === 1 && ! testExpression . arguments [ 0 ] . name ) {
523
522
if ( ParseTreeUtils . isMatchingExpression ( reference , testExpression . arguments [ 0 ] . valueExpression ) ) {
524
- return ( type : Type ) => {
525
- return narrowTypeForTruthiness ( evaluator , type , isPositiveTest ) ;
526
- } ;
523
+ const callType = evaluator . getTypeOfExpression (
524
+ testExpression . leftExpression ,
525
+ EvaluatorFlags . DoNotSpecialize
526
+ ) . type ;
527
+
528
+ if ( isInstantiableClass ( callType ) && ClassType . isBuiltIn ( callType , 'bool' ) ) {
529
+ return ( type : Type ) => {
530
+ return narrowTypeForTruthiness ( evaluator , type , isPositiveTest ) ;
531
+ } ;
532
+ }
527
533
}
528
534
}
529
535
@@ -542,6 +548,11 @@ export function getTypeNarrowingCallback(
542
548
) ;
543
549
} ;
544
550
551
+ const callType = evaluator . getTypeOfExpression (
552
+ testExpression . leftExpression ,
553
+ EvaluatorFlags . DoNotSpecialize
554
+ ) . type ;
555
+
545
556
if ( isFunction ( callType ) && isFunctionReturnTypeGuard ( callType ) ) {
546
557
isPossiblyTypeGuard = true ;
547
558
} else if (
0 commit comments