@@ -45,7 +45,7 @@ use crate::types::constraints::{
45
45
use crate :: types:: context:: { LintDiagnosticGuard , LintDiagnosticGuardBuilder } ;
46
46
use crate :: types:: diagnostic:: { INVALID_AWAIT , INVALID_TYPE_FORM , UNSUPPORTED_BOOL_CONVERSION } ;
47
47
pub use crate :: types:: display:: DisplaySettings ;
48
- use crate :: types:: enums:: { enum_member_literals , enum_metadata, is_single_member_enum} ;
48
+ use crate :: types:: enums:: { enum_metadata, is_single_member_enum} ;
49
49
use crate :: types:: function:: {
50
50
DataclassTransformerParams , FunctionDecorators , FunctionSpans , FunctionType , KnownFunction ,
51
51
} ;
@@ -4987,23 +4987,29 @@ impl<'db> Type<'db> {
4987
4987
}
4988
4988
Type :: StringLiteral ( string_literal_ty) => {
4989
4989
let string_literal = string_literal_ty. value ( db) ;
4990
- if string_literal. len ( ) < MAX_TUPLE_LENGTH {
4991
- return Ok ( Cow :: Owned ( TupleSpec :: heterogeneous (
4990
+ let spec = if string_literal. len ( ) < MAX_TUPLE_LENGTH {
4991
+ TupleSpec :: heterogeneous (
4992
4992
string_literal
4993
4993
. chars ( )
4994
4994
. map ( |c| Type :: string_literal ( db, & c. to_string ( ) ) ) ,
4995
- ) ) ) ;
4996
- }
4995
+ )
4996
+ } else {
4997
+ TupleSpec :: homogeneous ( self )
4998
+ } ;
4999
+ return Ok ( Cow :: Owned ( spec) ) ;
4997
5000
}
4998
5001
Type :: BytesLiteral ( bytes) => {
4999
5002
let bytes_literal = bytes. value ( db) ;
5000
- if bytes_literal. len ( ) < MAX_TUPLE_LENGTH {
5001
- return Ok ( Cow :: Owned ( TupleSpec :: heterogeneous (
5003
+ let spec = if bytes_literal. len ( ) < MAX_TUPLE_LENGTH {
5004
+ TupleSpec :: heterogeneous (
5002
5005
bytes_literal
5003
5006
. iter ( )
5004
5007
. map ( |b| Type :: IntLiteral ( i64:: from ( * b) ) ) ,
5005
- ) ) ) ;
5006
- }
5008
+ )
5009
+ } else {
5010
+ TupleSpec :: homogeneous ( self )
5011
+ } ;
5012
+ return Ok ( Cow :: Owned ( spec) ) ;
5007
5013
}
5008
5014
Type :: Never => {
5009
5015
// The dunder logic below would have us return `tuple[Never, ...]`, which eagerly
@@ -5028,15 +5034,6 @@ impl<'db> Type<'db> {
5028
5034
"should not be able to iterate over type variable {} in inferable position" ,
5029
5035
self . display( db)
5030
5036
) ,
5031
- Type :: ClassLiteral ( class) => {
5032
- if let Some ( enum_members) = enum_member_literals ( db, class, None ) {
5033
- if enum_metadata ( db, class)
5034
- . is_some_and ( |metadata| metadata. members . len ( ) < MAX_TUPLE_LENGTH )
5035
- {
5036
- return Ok ( Cow :: Owned ( TupleSpec :: heterogeneous ( enum_members) ) ) ;
5037
- }
5038
- }
5039
- }
5040
5037
Type :: Dynamic ( _)
5041
5038
| Type :: FunctionLiteral ( _)
5042
5039
| Type :: GenericAlias ( _)
@@ -5047,6 +5044,11 @@ impl<'db> Type<'db> {
5047
5044
| Type :: DataclassTransformer ( _)
5048
5045
| Type :: Callable ( _)
5049
5046
| Type :: ModuleLiteral ( _)
5047
+ // We could infer a precise tuple spec for enum classes with members,
5048
+ // but it's not clear whether that's worth the added complexity:
5049
+ // you'd have to check that `EnumMeta.__iter__` is not overridden for it to be sound
5050
+ // (enums can have `EnumMeta` subclasses as their metaclasses).
5051
+ | Type :: ClassLiteral ( _)
5050
5052
| Type :: SubclassOf ( _)
5051
5053
| Type :: ProtocolInstance ( _)
5052
5054
| Type :: SpecialForm ( _)
0 commit comments