forked from python/mypy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
coerce.py
66 lines (53 loc) · 2.69 KB
/
coerce.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from nodes import Node, TypeInfo, CoerceExpr, JavaCast
from mtypes import (
Type, Instance, Void, NoneTyp, Any
)
from sametypes import is_same_type
from subtypes import is_proper_subtype
from rttypevars import translate_runtime_type_vars_in_context
Node coerce(Node expr, Type target_type, Type source_type, TypeInfo context,
bool is_wrapper_class=False, bool is_java=False):
"""Build an expression that coerces expr from source_type to target_type.
Return bare expr if the coercion is trivial (always a no-op).
"""
if is_trivial_coercion(target_type, source_type, is_java):
res = expr
else:
# Translate type variables to expressions that fetch the value of a
# runtime type variable.
target = translate_runtime_type_vars_in_context(target_type, context,
is_java)
source = translate_runtime_type_vars_in_context(source_type, context,
is_java)
res = CoerceExpr(expr, target, source, is_wrapper_class)
if is_java and ((isinstance(source_type, Instance) and
((Instance)source_type).erased)
or (isinstance(res, CoerceExpr) and
isinstance(target_type, Instance))):
res = JavaCast(res, target_type)
return res
bool is_trivial_coercion(Type target_type, Type source_type, bool is_java):
"""Is an implicit coercion from source_type to target_type a no-op?
Note that we omit coercions of form any <= C, unless C is a primitive that
may have a special representation.
"""
# FIX: Replace type vars in source type with any?
if isinstance(source_type, Void) or is_same_type(target_type, source_type):
return True
# Coercions from a primitive type to any other type are non-trivial, since
# we may have to change the representation.
if not is_java and is_special_primitive(source_type):
return False
return (is_proper_subtype(source_type, target_type)
or isinstance(source_type, NoneTyp)
or isinstance(target_type, Any))
bool is_special_primitive(Type type):
"""Is type a primitive with a special runtime representation?
There needs to be explicit corcions to/from special primitive types. For
example, floats need to boxed/unboxed. The special primitive types include
int, float and bool.
"""
return (isinstance(type, Instance)
and ((Instance)type).type.full_name() in ['builtins.int',
'builtins.float',
'builtins.bool'])