Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
godot
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
community
godot
Commits
2bc98194
Unverified
Commit
2bc98194
authored
Mar 04, 2019
by
Rémi Verschelde
Committed by
GitHub
Mar 04, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #26573 from godotengine/revert-26562-gdscript-no-implicit-cast
Revert "Forbid implicit type conversion in GDScript"
parents
49d82f24
425ec691
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
110 additions
and
16 deletions
+110
-16
gdscript_function.cpp
modules/gdscript/gdscript_function.cpp
+8
-3
gdscript_function.h
modules/gdscript/gdscript_function.h
+6
-2
gdscript_parser.cpp
modules/gdscript/gdscript_parser.cpp
+95
-10
gdscript_parser.h
modules/gdscript/gdscript_parser.h
+1
-1
No files found.
modules/gdscript/gdscript_function.cpp
View file @
2bc98194
...
...
@@ -328,8 +328,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
continue
;
}
if
(
!
argument_types
[
i
].
is_type
(
*
p_args
[
i
]))
{
if
(
argument_types
[
i
].
is_type
(
Variant
()))
{
if
(
!
argument_types
[
i
].
is_type
(
*
p_args
[
i
]
,
true
))
{
if
(
argument_types
[
i
].
is_type
(
Variant
()
,
true
))
{
memnew_placement
(
&
stack
[
i
],
Variant
);
continue
;
}
else
{
...
...
@@ -339,7 +339,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
return
Variant
();
}
}
memnew_placement
(
&
stack
[
i
],
Variant
(
*
p_args
[
i
]));
if
(
argument_types
[
i
].
kind
==
GDScriptDataType
::
BUILTIN
)
{
Variant
arg
=
Variant
::
construct
(
argument_types
[
i
].
builtin_type
,
&
p_args
[
i
],
1
,
r_err
);
memnew_placement
(
&
stack
[
i
],
Variant
(
arg
));
}
else
{
memnew_placement
(
&
stack
[
i
],
Variant
(
*
p_args
[
i
]));
}
}
for
(
int
i
=
p_argcount
;
i
<
_stack_size
;
i
++
)
{
memnew_placement
(
&
stack
[
i
],
Variant
);
...
...
modules/gdscript/gdscript_function.h
View file @
2bc98194
...
...
@@ -55,7 +55,7 @@ struct GDScriptDataType {
StringName
native_type
;
Ref
<
Script
>
script_type
;
bool
is_type
(
const
Variant
&
p_variant
)
const
{
bool
is_type
(
const
Variant
&
p_variant
,
bool
p_allow_implicit_conversion
=
false
)
const
{
if
(
!
has_type
)
return
true
;
// Can't type check
switch
(
kind
)
{
...
...
@@ -63,7 +63,11 @@ struct GDScriptDataType {
break
;
case
BUILTIN
:
{
Variant
::
Type
var_type
=
p_variant
.
get_type
();
return
builtin_type
==
var_type
;
bool
valid
=
builtin_type
==
var_type
;
if
(
!
valid
&&
p_allow_implicit_conversion
)
{
valid
=
Variant
::
can_convert_strict
(
var_type
,
builtin_type
);
}
return
valid
;
}
break
;
case
NATIVE
:
{
if
(
p_variant
.
get_type
()
==
Variant
::
NIL
)
{
...
...
modules/gdscript/gdscript_parser.cpp
View file @
2bc98194
...
...
@@ -5801,7 +5801,7 @@ Variant::Operator GDScriptParser::_get_variant_operation(const OperatorNode::Ope
}
}
bool
GDScriptParser
::
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
)
const
{
bool
GDScriptParser
::
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
,
bool
p_allow_implicit_conversion
)
const
{
// Ignore for completion
if
(
!
check_types
||
for_completion
)
{
return
true
;
...
...
@@ -5817,6 +5817,9 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
if
(
p_container
.
kind
==
DataType
::
BUILTIN
&&
p_expression
.
kind
==
DataType
::
BUILTIN
)
{
bool
valid
=
p_container
.
builtin_type
==
p_expression
.
builtin_type
;
if
(
p_allow_implicit_conversion
)
{
valid
=
valid
||
Variant
::
can_convert_strict
(
p_expression
.
builtin_type
,
p_container
.
builtin_type
);
}
return
valid
;
}
...
...
@@ -6685,7 +6688,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
arg_type
.
native_type
=
mi
.
arguments
[
i
].
class_name
;
}
if
(
!
_is_type_compatible
(
arg_type
,
par_types
[
i
]))
{
if
(
!
_is_type_compatible
(
arg_type
,
par_types
[
i
]
,
true
))
{
types_match
=
false
;
break
;
}
else
{
...
...
@@ -6927,7 +6930,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if
(
par_type
.
may_yield
&&
p_call
->
arguments
[
i
]
->
type
==
Node
::
TYPE_OPERATOR
)
{
_add_warning
(
GDScriptWarning
::
FUNCTION_MAY_YIELD
,
p_call
->
line
,
_find_function_name
(
static_cast
<
OperatorNode
*>
(
p_call
->
arguments
[
i
])));
}
}
else
if
(
!
_is_type_compatible
(
arg_types
[
i
-
arg_diff
],
par_type
))
{
}
else
if
(
!
_is_type_compatible
(
arg_types
[
i
-
arg_diff
],
par_type
,
true
))
{
// Supertypes are acceptable for dynamic compliance
if
(
!
_is_type_compatible
(
par_type
,
arg_types
[
i
-
arg_diff
]))
{
_set_error
(
"At '"
+
callee_name
+
"()' call, argument "
+
itos
(
i
-
arg_diff
+
1
)
+
". Assigned type ("
+
...
...
@@ -7390,6 +7393,33 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
// Try supertype test
if
(
_is_type_compatible
(
expr_type
,
v
.
data_type
))
{
_mark_line_as_unsafe
(
v
.
line
);
}
else
{
// Try with implicit conversion
if
(
v
.
data_type
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
v
.
data_type
,
expr_type
,
true
))
{
_set_error
(
"Assigned expression type ("
+
expr_type
.
to_string
()
+
") doesn't match the variable's type ("
+
v
.
data_type
.
to_string
()
+
")."
,
v
.
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
v
.
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
v
.
line
;
tgt_type
->
value
=
(
int
)
v
.
data_type
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
v
.
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
v
.
expression
);
convert_call
->
arguments
.
push_back
(
tgt_type
);
v
.
expression
=
convert_call
;
v
.
initial_assignment
->
arguments
.
write
[
1
]
=
convert_call
;
}
}
...
...
@@ -7430,7 +7460,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
// Check export hint
if
(
v
.
data_type
.
has_type
&&
v
.
_export
.
type
!=
Variant
::
NIL
)
{
DataType
export_type
=
_type_from_property
(
v
.
_export
);
if
(
!
_is_type_compatible
(
v
.
data_type
,
export_type
))
{
if
(
!
_is_type_compatible
(
v
.
data_type
,
export_type
,
true
))
{
_set_error
(
"Export hint type ("
+
export_type
.
to_string
()
+
") doesn't match the variable's type ("
+
v
.
data_type
.
to_string
()
+
")."
,
v
.
line
);
...
...
@@ -7551,7 +7581,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
}
else
{
p_function
->
return_type
=
_resolve_type
(
p_function
->
return_type
,
p_function
->
line
);
if
(
!
_is_type_compatible
(
p_function
->
argument_types
[
i
],
def_type
))
{
if
(
!
_is_type_compatible
(
p_function
->
argument_types
[
i
],
def_type
,
true
))
{
String
arg_name
=
p_function
->
arguments
[
i
];
_set_error
(
"Value type ("
+
def_type
.
to_string
()
+
") doesn't match the type of argument '"
+
arg_name
+
"' ("
+
p_function
->
arguments
[
i
]
+
")"
,
...
...
@@ -7739,13 +7769,41 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
}
#endif // DEBUG_ENABLED
if
(
check_types
&&
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
))
{
if
(
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
))
{
// Try supertype test
if
(
_is_type_compatible
(
assign_type
,
lv
->
datatype
))
{
_mark_line_as_unsafe
(
lv
->
line
);
}
else
{
_set_error
(
"Assigned value type ("
+
assign_type
.
to_string
()
+
") does not match variable type ("
+
lv
->
datatype
.
to_string
()
+
")"
,
lv
->
line
);
return
;
// Try implict conversion
if
(
lv
->
datatype
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
,
true
))
{
_set_error
(
"Assigned value type ("
+
assign_type
.
to_string
()
+
") doesn't match the variable's type ("
+
lv
->
datatype
.
to_string
()
+
")."
,
lv
->
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
lv
->
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
lv
->
line
;
tgt_type
->
value
=
(
int
)
lv
->
datatype
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
lv
->
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
lv
->
assign
);
convert_call
->
arguments
.
push_back
(
tgt_type
);
lv
->
assign
=
convert_call
;
lv
->
assign_op
->
arguments
.
write
[
1
]
=
convert_call
;
#ifdef DEBUG_ENABLED
if
(
lv
->
datatype
.
builtin_type
==
Variant
::
INT
&&
assign_type
.
builtin_type
==
Variant
::
REAL
)
{
_add_warning
(
GDScriptWarning
::
NARROWING_CONVERSION
,
lv
->
line
);
}
#endif // DEBUG_ENABLED
}
}
if
(
lv
->
datatype
.
infer_type
)
{
...
...
@@ -7847,8 +7905,35 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if
(
_is_type_compatible
(
rh_type
,
lh_type
))
{
_mark_line_as_unsafe
(
op
->
line
);
}
else
{
_set_error
(
"Assigned value type ("
+
rh_type
.
to_string
()
+
") does not match variable type ("
+
lh_type
.
to_string
()
+
")"
,
op
->
line
);
return
;
// Try implict conversion
if
(
lh_type
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
lh_type
,
rh_type
,
true
))
{
_set_error
(
"Assigned value type ("
+
rh_type
.
to_string
()
+
") doesn't match the variable's type ("
+
lh_type
.
to_string
()
+
")."
,
op
->
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
op
->
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
op
->
line
;
tgt_type
->
value
=
(
int
)
lh_type
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
op
->
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
op
->
arguments
[
1
]);
convert_call
->
arguments
.
push_back
(
tgt_type
);
op
->
arguments
.
write
[
1
]
=
convert_call
;
#ifdef DEBUG_ENABLED
if
(
lh_type
.
builtin_type
==
Variant
::
INT
&&
rh_type
.
builtin_type
==
Variant
::
REAL
)
{
_add_warning
(
GDScriptWarning
::
NARROWING_CONVERSION
,
op
->
line
);
}
#endif // DEBUG_ENABLED
}
}
#ifdef DEBUG_ENABLED
...
...
modules/gdscript/gdscript_parser.h
View file @
2bc98194
...
...
@@ -607,7 +607,7 @@ private:
Variant
::
Operator
_get_variant_operation
(
const
OperatorNode
::
Operator
&
p_op
)
const
;
bool
_get_function_signature
(
DataType
&
p_base_type
,
const
StringName
&
p_function
,
DataType
&
r_return_type
,
List
<
DataType
>
&
r_arg_types
,
int
&
r_default_arg_count
,
bool
&
r_static
,
bool
&
r_vararg
)
const
;
bool
_get_member_type
(
const
DataType
&
p_base_type
,
const
StringName
&
p_member
,
DataType
&
r_member_type
)
const
;
bool
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
)
const
;
bool
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
,
bool
p_allow_implicit_conversion
=
false
)
const
;
DataType
_reduce_node_type
(
Node
*
p_node
);
DataType
_reduce_function_call_type
(
const
OperatorNode
*
p_call
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment