@@ -129,6 +129,7 @@ import {
129129 TypeResult ,
130130} from './typeEvaluatorTypes' ;
131131import {
132+ enumerateLiteralsForType ,
132133 getElementTypeForContainerNarrowing ,
133134 getIsInstanceClassTypes ,
134135 narrowTypeForContainerElementType ,
@@ -2142,8 +2143,8 @@ export class Checker extends ParseTreeWalker {
21422143 rightExpression = rightExpression . d . leftExpr ;
21432144 }
21442145
2145- const leftType = this . _evaluator . getType ( node . d . leftExpr ) ;
2146- const rightType = this . _evaluator . getType ( rightExpression ) ;
2146+ let leftType = this . _evaluator . getType ( node . d . leftExpr ) ;
2147+ let rightType = this . _evaluator . getType ( rightExpression ) ;
21472148
21482149 if ( ! leftType || ! rightType ) {
21492150 return ;
@@ -2159,6 +2160,44 @@ export class Checker extends ParseTreeWalker {
21592160 : LocMessage . comparisonAlwaysTrue ( ) ;
21602161 } ;
21612162
2163+ const replaceEnumTypeWithLiteralValue = ( type : Type ) => {
2164+ return mapSubtypes ( type , ( subtype ) => {
2165+ if (
2166+ ! isClassInstance ( subtype ) ||
2167+ ! ClassType . isEnumClass ( subtype ) ||
2168+ ! subtype . shared . mro . some (
2169+ ( base ) => isClass ( base ) && ClassType . isBuiltIn ( base , [ 'int' , 'str' , 'bytes' ] )
2170+ )
2171+ ) {
2172+ return subtype ;
2173+ }
2174+
2175+ // If this is an enum literal, replace it with its literal value.
2176+ if ( subtype . priv . literalValue instanceof EnumLiteral ) {
2177+ return subtype . priv . literalValue . itemType ;
2178+ }
2179+
2180+ // If this is an enum class, replace it with the type of its members.
2181+ const literalValues = enumerateLiteralsForType ( this . _evaluator , subtype ) ;
2182+ if ( literalValues && literalValues . length > 0 ) {
2183+ return combineTypes (
2184+ literalValues . map ( ( literalClass ) => {
2185+ const literalValue = literalClass . priv . literalValue ;
2186+ assert ( literalValue instanceof EnumLiteral ) ;
2187+ return literalValue . itemType ;
2188+ } )
2189+ ) ;
2190+ }
2191+
2192+ return subtype ;
2193+ } ) ;
2194+ } ;
2195+
2196+ // Handle enum literals that are assignable to another (non-Enum) literal.
2197+ // This can happen for IntEnum and StrEnum members.
2198+ leftType = replaceEnumTypeWithLiteralValue ( leftType ) ;
2199+ rightType = replaceEnumTypeWithLiteralValue ( rightType ) ;
2200+
21622201 // Check for the special case where the LHS and RHS are both literals.
21632202 if ( isLiteralTypeOrUnion ( rightType ) && isLiteralTypeOrUnion ( leftType ) ) {
21642203 if (
@@ -2171,13 +2210,13 @@ export class Checker extends ParseTreeWalker {
21712210 let isPossiblyTrue = false ;
21722211
21732212 doForEachSubtype ( leftType , ( leftSubtype ) => {
2174- if ( this . _evaluator . assignType ( rightType , leftSubtype ) ) {
2213+ if ( this . _evaluator . assignType ( rightType ! , leftSubtype ) ) {
21752214 isPossiblyTrue = true ;
21762215 }
21772216 } ) ;
21782217
21792218 doForEachSubtype ( rightType , ( rightSubtype ) => {
2180- if ( this . _evaluator . assignType ( leftType , rightSubtype ) ) {
2219+ if ( this . _evaluator . assignType ( leftType ! , rightSubtype ) ) {
21812220 isPossiblyTrue = true ;
21822221 }
21832222 } ) ;
@@ -2201,7 +2240,7 @@ export class Checker extends ParseTreeWalker {
22012240 return ;
22022241 }
22032242
2204- this . _evaluator . mapSubtypesExpandTypeVars ( rightType , { } , ( rightSubtype ) => {
2243+ this . _evaluator . mapSubtypesExpandTypeVars ( rightType ! , { } , ( rightSubtype ) => {
22052244 if ( isComparable ) {
22062245 return ;
22072246 }
0 commit comments