} else {
// use first delegate parameter as instance
if (d_params.size == 0 || m.closure) {
- Report.error (node != null ? node.source_reference : null, "Cannot create delegate without target for instance method or closure");
- arg = new CCodeConstant ("NULL");
+ Report.error (node != null ? node.source_reference : null, "internal: Cannot create delegate wrapper");
+ arg = new CCodeInvalidExpression ();
} else {
arg = new CCodeIdentifier (get_ccode_name (d_params.get (0)));
i = 1;
delegates/fields.vala \
delegates/fields-no-target.vala \
delegates/incompatible.test \
+ delegates/incompatible-assignment.test \
+ delegates/incompatible-initializer.test \
delegates/incompatible-target.test \
delegates/instance-method-to-no-target.test \
+ delegates/instance-method-to-no-target-2.test \
delegates/lambda-mixed-instance-static.vala \
delegates/lambda-shared-closure.vala \
delegates/member-target-destroy.vala \
--- /dev/null
+Invalid Code
+
+[CCode (has_target = false)]
+delegate void Foo (string s);
+
+class Bar {
+ public void foo () {
+ }
+}
+
+void main () {
+ var bar = new Bar ();
+ Foo foo;
+ foo = bar.foo;
+}
--- /dev/null
+Invalid Code
+
+[CCode (has_target = false)]
+delegate void Foo (string s);
+
+class Bar {
+ public void foo () {
+ }
+}
+
+void main () {
+ var bar = new Bar ();
+ Foo foo = bar.foo;
+}
--- /dev/null
+Invalid Code
+
+[CCode (has_target = false)]
+delegate void Foo ();
+
+class Bar {
+ public void foo () {
+ }
+}
+
+void main () {
+ var bar = new Bar ();
+ Foo foo;
+ foo = bar.foo;
+}
error = true;
Report.error (source_reference, "`length' field of fixed length arrays is read-only");
return false;
- } else if (ma.symbol_reference is Variable && right.value_type == null) {
+ } else if (ma.symbol_reference is Variable && right.value_type is MethodType) {
unowned Variable variable = (Variable) ma.symbol_reference;
- if (right.symbol_reference is Method &&
- variable.variable_type is DelegateType) {
- unowned Method m = (Method) right.symbol_reference;
- unowned DelegateType dt = (DelegateType) variable.variable_type;
- unowned Delegate cb = dt.delegate_symbol;
-
+ if (variable.variable_type is DelegateType) {
/* check whether method matches callback type */
- if (!cb.matches_method (m, dt)) {
+ if (!right.value_type.compatible (variable.variable_type)) {
+ unowned Method m = (Method) right.symbol_reference;
+ unowned Delegate cb = ((DelegateType) variable.variable_type).delegate_symbol;
error = true;
- Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+ Report.error (source_reference, "Declaration of method `%s' is not compatible with delegate `%s'".printf (m.get_full_name (), cb.get_full_name ()));
return false;
}
-
- right.value_type = variable.variable_type.copy ();
} else {
error = true;
Report.error (source_reference, "Assignment: Invalid assignment attempt");
bool first = true;
foreach (Parameter param in parameters) {
+ DataType method_param_type;
/* use first callback parameter as instance parameter if
* an instance method is being compared to a static
* callback
*/
if (first && m.binding == MemberBinding.INSTANCE && !has_target) {
first = false;
- continue;
- }
-
- /* method is allowed to accept less arguments */
- if (!method_params_it.next ()) {
- break;
+ method_param_type = SemanticAnalyzer.get_data_type_for_symbol (m.parent_symbol);
+ } else {
+ /* method is allowed to accept less arguments */
+ if (!method_params_it.next ()) {
+ break;
+ }
+ method_param_type = method_params_it.get ().variable_type;
}
// method is allowed to accept arguments of looser types (weaker precondition)
- var method_param = method_params_it.get ();
- if (!param.variable_type.get_actual_type (dt, null, this).stricter (method_param.variable_type)) {
+ if (!param.variable_type.get_actual_type (dt, null, this).stricter (method_param_type)) {
return false;
}
}
+ // delegate without target for instance method or closure
+ if (first && m.binding == MemberBinding.INSTANCE && !has_target) {
+ return false;
+ }
+
/* method may not expect more arguments */
if (method_params_it.next ()) {
return false;
}
if (initializer != null && !initializer.error) {
- if (initializer.value_type == null) {
+ if (initializer.value_type is MethodType) {
if (!(initializer is MemberAccess) && !(initializer is LambdaExpression)) {
error = true;
Report.error (source_reference, "expression type not allowed as initializer");
return false;
}
- if (initializer.symbol_reference is Method &&
- variable_type is DelegateType) {
- var m = (Method) initializer.symbol_reference;
- var dt = (DelegateType) variable_type;
- var cb = dt.delegate_symbol;
-
+ if (variable_type is DelegateType) {
/* check whether method matches callback type */
- if (!cb.matches_method (m, dt)) {
+ if (!initializer.value_type.compatible (variable_type)) {
+ unowned Method m = (Method) initializer.symbol_reference;
+ unowned Delegate cb = ((DelegateType) variable_type).delegate_symbol;
error = true;
- Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+ Report.error (source_reference, "Declaration of method `%s' is not compatible with delegate `%s'".printf (m.get_full_name (), cb.get_full_name ()));
return false;
}
-
- initializer.value_type = variable_type;
} else {
error = true;
Report.error (source_reference, "expression type not allowed as initializer");
base_type.accept (visitor);
}
+ public override bool stricter (DataType type2) {
+ if (type2 is PointerType) {
+ return compatible (type2);
+ }
+
+ if (base_type is VoidType) {
+ // void* can hold reference types
+ return type2 is ReferenceType;
+ }
+
+ return base_type.stricter (type2);
+ }
+
public override void replace_type (DataType old_type, DataType new_type) {
if (base_type == old_type) {
base_type = new_type;