Commit dfd73ac6 authored by Stefan Behnel's avatar Stefan Behnel

Do not infer C types for arguments with Python default value.

Closes #1972.
parent 8ad16fc8
...@@ -68,8 +68,9 @@ def embed_position(pos, docstring): ...@@ -68,8 +68,9 @@ def embed_position(pos, docstring):
return doc return doc
def analyse_type_annotation(annotation, env): def analyse_type_annotation(annotation, env, assigned_value=None):
base_type = None base_type = None
is_ambiguous = False
explicit_pytype = explicit_ctype = False explicit_pytype = explicit_ctype = False
if annotation.is_dict_literal: if annotation.is_dict_literal:
warning(annotation.pos, warning(annotation.pos,
...@@ -88,6 +89,13 @@ def analyse_type_annotation(annotation, env): ...@@ -88,6 +89,13 @@ def analyse_type_annotation(annotation, env):
warning(annotation.pos, "Duplicate type declarations found in signature annotation") warning(annotation.pos, "Duplicate type declarations found in signature annotation")
arg_type = annotation.analyse_as_type(env) arg_type = annotation.analyse_as_type(env)
if annotation.is_name and not annotation.cython_attribute and annotation.name in ('int', 'long', 'float'): if annotation.is_name and not annotation.cython_attribute and annotation.name in ('int', 'long', 'float'):
# Map builtin numeric Python types to C types in safe cases.
if assigned_value is not None and arg_type is not None and not arg_type.is_pyobject:
assigned_type = assigned_value.infer_type(env)
if assigned_type and assigned_type.is_pyobject:
# C type seems unsafe, e.g. due to 'None' default value => ignore annotation type
is_ambiguous = True
arg_type = None
# ignore 'int' and require 'cython.int' to avoid unsafe integer declarations # ignore 'int' and require 'cython.int' to avoid unsafe integer declarations
if arg_type in (PyrexTypes.c_long_type, PyrexTypes.c_int_type, PyrexTypes.c_float_type): if arg_type in (PyrexTypes.c_long_type, PyrexTypes.c_int_type, PyrexTypes.c_float_type):
arg_type = PyrexTypes.c_double_type if annotation.name == 'float' else py_object_type arg_type = PyrexTypes.c_double_type if annotation.name == 'float' else py_object_type
...@@ -100,6 +108,8 @@ def analyse_type_annotation(annotation, env): ...@@ -100,6 +108,8 @@ def analyse_type_annotation(annotation, env):
"Python type declaration in signature annotation does not refer to a Python type") "Python type declaration in signature annotation does not refer to a Python type")
base_type = CAnalysedBaseTypeNode( base_type = CAnalysedBaseTypeNode(
annotation.pos, type=arg_type, is_arg=True) annotation.pos, type=arg_type, is_arg=True)
elif is_ambiguous:
warning(annotation.pos, "Ambiguous types in annotation, ignoring")
else: else:
warning(annotation.pos, "Unknown type declaration in annotation, ignoring") warning(annotation.pos, "Unknown type declaration in annotation, ignoring")
return base_type, arg_type return base_type, arg_type
...@@ -890,7 +900,7 @@ class CArgDeclNode(Node): ...@@ -890,7 +900,7 @@ class CArgDeclNode(Node):
annotation = self.annotation annotation = self.annotation
if not annotation: if not annotation:
return None return None
base_type, arg_type = analyse_type_annotation(annotation, env) base_type, arg_type = analyse_type_annotation(annotation, env, assigned_value=self.default)
if base_type is not None: if base_type is not None:
self.base_type = base_type self.base_type = base_type
return arg_type return arg_type
......
...@@ -215,6 +215,22 @@ class LateClass(object): ...@@ -215,6 +215,22 @@ class LateClass(object):
pass pass
def py_float_default(price : float=None, ndigits=4):
"""
Python default arguments should prevent C type inference.
>>> py_float_default()
(None, 4)
>>> py_float_default(2)
(2, 4)
>>> py_float_default(2.0)
(2.0, 4)
>>> py_float_default(2, 3)
(2, 3)
"""
return price, ndigits
_WARNINGS = """ _WARNINGS = """
8:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly. 8:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
8:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly. 8:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
...@@ -223,6 +239,7 @@ _WARNINGS = """ ...@@ -223,6 +239,7 @@ _WARNINGS = """
8:85: Python type declaration in signature annotation does not refer to a Python type 8:85: Python type declaration in signature annotation does not refer to a Python type
8:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly. 8:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
211:44: Unknown type declaration in annotation, ignoring 211:44: Unknown type declaration in annotation, ignoring
218:29: Ambiguous types in annotation, ignoring
# BUG: # BUG:
46:6: 'pytypes_cpdef' redeclared 46:6: 'pytypes_cpdef' redeclared
121:0: 'struct_io' redeclared 121:0: 'struct_io' redeclared
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment