@@ -187,15 +187,15 @@ def __init__(self,
187
187
# Names of type aliases encountered while analysing a type will be collected here.
188
188
self .aliases_used = set () # type: Set[str]
189
189
190
- def visit_unbound_type (self , t : UnboundType ) -> Type :
191
- typ = self .visit_unbound_type_nonoptional (t )
190
+ def visit_unbound_type (self , t : UnboundType , defining_literal : bool = False ) -> Type :
191
+ typ = self .visit_unbound_type_nonoptional (t , defining_literal )
192
192
if t .optional :
193
193
# We don't need to worry about double-wrapping Optionals or
194
194
# wrapping Anys: Union simplification will take care of that.
195
195
return make_optional_type (typ )
196
196
return typ
197
197
198
- def visit_unbound_type_nonoptional (self , t : UnboundType ) -> Type :
198
+ def visit_unbound_type_nonoptional (self , t : UnboundType , defining_literal : bool ) -> Type :
199
199
sym = self .lookup (t .name , t , suppress_errors = self .third_pass )
200
200
if '.' in t .name :
201
201
# Handle indirect references to imported names.
@@ -249,7 +249,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType) -> Type:
249
249
elif isinstance (node , TypeInfo ):
250
250
return self .analyze_unbound_type_with_type_info (t , node )
251
251
else :
252
- return self .analyze_unbound_type_without_type_info (t , sym )
252
+ return self .analyze_unbound_type_without_type_info (t , sym , defining_literal )
253
253
else : # sym is None
254
254
if self .third_pass :
255
255
self .fail ('Invalid type "{}"' .format (t .name ), t )
@@ -368,7 +368,8 @@ def analyze_unbound_type_with_type_info(self, t: UnboundType, info: TypeInfo) ->
368
368
fallback = instance )
369
369
return instance
370
370
371
- def analyze_unbound_type_without_type_info (self , t : UnboundType , sym : SymbolTableNode ) -> Type :
371
+ def analyze_unbound_type_without_type_info (self , t : UnboundType , sym : SymbolTableNode ,
372
+ defining_literal : bool ) -> Type :
372
373
"""Figure out what an unbound type that doesn't refer to a TypeInfo node means.
373
374
374
375
This is something unusual. We try our best to find out what it is.
@@ -377,6 +378,7 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl
377
378
if name is None :
378
379
assert sym .node is not None
379
380
name = sym .node .name ()
381
+
380
382
# Option 1:
381
383
# Something with an Any type -- make it an alias for Any in a type
382
384
# context. This is slightly problematic as it allows using the type 'Any'
@@ -385,14 +387,40 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl
385
387
if isinstance (sym .node , Var ) and isinstance (sym .node .type , AnyType ):
386
388
return AnyType (TypeOfAny .from_unimported_type ,
387
389
missing_import_name = sym .node .type .missing_import_name )
390
+
388
391
# Option 2:
389
392
# Unbound type variable. Currently these may be still valid,
390
393
# for example when defining a generic type alias.
391
394
unbound_tvar = (isinstance (sym .node , TypeVarExpr ) and
392
395
(not self .tvar_scope or self .tvar_scope .get_binding (sym ) is None ))
393
396
if self .allow_unbound_tvars and unbound_tvar and not self .third_pass :
394
397
return t
398
+
395
399
# Option 3:
400
+ # Enum value. Note: we only want to return a LiteralType when
401
+ # we're using this enum value specifically within context of
402
+ # a "Literal[...]" type. So, if `defining_literal` is not set,
403
+ # we bail out early with an error.
404
+ #
405
+ # If, in the distant future, we decide to permit things like
406
+ # `def foo(x: Color.RED) -> None: ...`, we can remove that
407
+ # check entirely.
408
+ if isinstance (sym .node , Var ) and not t .args and sym .node .info and sym .node .info .is_enum :
409
+ value = sym .node .name ()
410
+ base_enum_short_name = sym .node .info .name ()
411
+ if not defining_literal :
412
+ msg = message_registry .INVALID_TYPE_RAW_ENUM_VALUE .format (
413
+ base_enum_short_name , value )
414
+ self .fail (msg , t )
415
+ return AnyType (TypeOfAny .from_error )
416
+ return LiteralType (
417
+ value = value ,
418
+ fallback = Instance (sym .node .info , [], line = t .line , column = t .column ),
419
+ line = t .line ,
420
+ column = t .column ,
421
+ )
422
+
423
+ # Option 4:
396
424
# If it is not something clearly bad (like a known function, variable,
397
425
# type variable, or module), and it is still not too late, we try deferring
398
426
# this type using a forward reference wrapper. It will be revisited in
@@ -410,6 +438,7 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl
410
438
self .fail ('Unsupported forward reference to "{}"' .format (t .name ), t )
411
439
return AnyType (TypeOfAny .from_error )
412
440
return ForwardRef (t )
441
+
413
442
# None of the above options worked, we give up.
414
443
self .fail ('Invalid type "{}"' .format (name ), t )
415
444
if self .third_pass and isinstance (sym .node , TypeVarExpr ):
@@ -657,7 +686,11 @@ def analyze_literal_param(self, idx: int, arg: Type, ctx: Context) -> Optional[L
657
686
# If arg is an UnboundType that was *not* originally defined as
658
687
# a string, try expanding it in case it's a type alias or something.
659
688
if isinstance (arg , UnboundType ):
660
- arg = self .anal_type (arg )
689
+ self .nesting_level += 1
690
+ try :
691
+ arg = self .visit_unbound_type (arg , defining_literal = True )
692
+ finally :
693
+ self .nesting_level -= 1
661
694
662
695
# Literal[...] cannot contain Any. Give up and add an error message
663
696
# (if we haven't already).
0 commit comments