mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-06 12:57:14 +03:00
Fixed a bug that results in a false positive error when assigning a TypeGuard[T]
or TypeIs[T]
to a supertype of bool
(like int
). This addresses #8769. (#8771)
This commit is contained in:
parent
ea55470da5
commit
c42a1587b4
@ -400,6 +400,7 @@ interface ScopedTypeVarResult {
|
||||
interface AliasMapEntry {
|
||||
alias: string;
|
||||
module: 'builtins' | 'collections' | 'self';
|
||||
implicitBaseClass?: string;
|
||||
isSpecialForm?: boolean;
|
||||
isIllegalInIsinstance?: boolean;
|
||||
typeParamVariance?: Variance;
|
||||
@ -15083,10 +15084,7 @@ export function createTypeEvaluator(
|
||||
return type;
|
||||
}
|
||||
|
||||
// Creates a "TypeGuard" and "TypeIs" type. This is an alias for 'bool', which
|
||||
// isn't a generic type and therefore doesn't have a typeParam.
|
||||
// We'll abuse our internal types a bit by specializing it with
|
||||
// a type argument anyway.
|
||||
// Creates a "TypeGuard" and "TypeIs" type.
|
||||
function createTypeGuardType(
|
||||
classType: ClassType,
|
||||
errorNode: ParseNode,
|
||||
@ -15948,7 +15946,7 @@ export function createTypeEvaluator(
|
||||
specialClassType.shared.flags |= ClassTypeFlags.TypingExtensionClass;
|
||||
}
|
||||
|
||||
const baseClassName = aliasMapEntry.alias || 'object';
|
||||
const baseClassName = aliasMapEntry.implicitBaseClass || aliasMapEntry.alias || 'object';
|
||||
|
||||
let baseClass: Type | undefined;
|
||||
if (aliasMapEntry.module === 'builtins') {
|
||||
@ -16021,7 +16019,13 @@ export function createTypeEvaluator(
|
||||
['Concatenate', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
[
|
||||
'TypeGuard',
|
||||
{ alias: '', module: 'builtins', isSpecialForm: true, typeParamVariance: Variance.Covariant },
|
||||
{
|
||||
alias: '',
|
||||
module: 'builtins',
|
||||
implicitBaseClass: 'bool',
|
||||
isSpecialForm: true,
|
||||
typeParamVariance: Variance.Covariant,
|
||||
},
|
||||
],
|
||||
['Unpack', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
['Required', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
@ -16031,7 +16035,16 @@ export function createTypeEvaluator(
|
||||
['Never', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
['LiteralString', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
['ReadOnly', { alias: '', module: 'builtins', isSpecialForm: true }],
|
||||
['TypeIs', { alias: '', module: 'builtins', isSpecialForm: true, typeParamVariance: Variance.Invariant }],
|
||||
[
|
||||
'TypeIs',
|
||||
{
|
||||
alias: '',
|
||||
module: 'builtins',
|
||||
implicitBaseClass: 'bool',
|
||||
isSpecialForm: true,
|
||||
typeParamVariance: Variance.Invariant,
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const aliasMapEntry = specialTypes.get(assignedName);
|
||||
@ -22719,14 +22732,6 @@ export function createTypeEvaluator(
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the type is a bool created with a `TypeGuard` or `TypeIs`, it is
|
||||
// considered a subtype of `bool`.
|
||||
if (isInstantiableClass(srcType) && ClassType.isBuiltIn(srcType, ['TypeGuard', 'TypeIs'])) {
|
||||
if (isInstantiableClass(destType) && ClassType.isBuiltIn(destType, 'bool')) {
|
||||
return (flags & AssignTypeFlags.Invariant) === 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & AssignTypeFlags.Invariant) === 0 || ClassType.isSameGenericClass(srcType, destType)) {
|
||||
if (isDerivedFrom) {
|
||||
assert(inheritanceChain.length > 0);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
import os
|
||||
from typing import Any, Callable, TypeVar
|
||||
|
||||
from typing_extensions import TypeGuard # pyright: ignore[reportMissingModuleSource]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
@ -124,3 +125,9 @@ takes_int_typeguard(bool_typeguard)
|
||||
|
||||
# This should generate an error because TypeGuard is covariant.
|
||||
takes_int_typeguard(str_typeguard)
|
||||
|
||||
|
||||
v0 = is_int(int)
|
||||
v1: bool = v0
|
||||
v2: int = v0
|
||||
v3 = v0 & v0
|
||||
|
@ -172,3 +172,9 @@ def func10(
|
||||
|
||||
def func10(v: tuple[int | str, ...], b: bool = True) -> bool:
|
||||
...
|
||||
|
||||
|
||||
v0 = is_int(int)
|
||||
v1: bool = v0
|
||||
v2: int = v0
|
||||
v3 = v0 & v0
|
||||
|
Loading…
Reference in New Issue
Block a user