diff --git a/src/interpreter.h b/src/interpreter.h index 1e5deeefbae51c39565df065bb4e92b41146cd40..03778a16fbd990bc27215372353b747c1393c5fc 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -1296,25 +1296,42 @@ static int eval_instruction(unsigned char *pc) /* Stack: type_string, value */ #ifdef PIKE_DEBUG if (sp[-2].type != T_STRING) { + /* FIXME: The type should really be T_TYPE... */ fatal("Argument 1 to soft_cast isn't a string!\n"); } #endif /* PIKE_DEBUG */ if (runtime_options & RUNTIME_CHECK_TYPES) { struct pike_string *sval_type = get_type_of_svalue(sp-1); - if (!pike_types_le(sval_type, sp[-2].u.string)) { - struct pike_string *t; - ONERROR tmp; - - free_string(sval_type); - - t = describe_type(sp[-2].u.string); - SET_ONERROR(tmp, do_free_string, t); - bad_arg_error("soft_cast", sp-1, 1, 1, t->str, sp-1, - "Assertion failed in soft_cast(). Expected %s\n", - t->str); - /* NOT_REACHED */ - UNSET_ONERROR(tmp); - free_string(t); + if (!pike_types_le(sval_type, sp[-2].u.string) { + /* get_type_from_svalue() doesn't return a fully specified type + * for array, mapping and multiset, so we perform a more lenient + * check for them. + */ + if (!pike_types_le(sval_type, weak_type_type_string) || + !match_types(sval_type, sp[-2].u.string)) { + struct pike_string *t1; + struct pike_string *t2; + ONERROR tmp1; + ONERROR tmp2; + + t1 = describe_type(sp[-2].u.string); + SET_ONERROR(tmp1, do_free_string, t1); + + t2 = describe_type(sval_type); + SET_ONERROR(tmp2, do_free_string, t2); + + free_string(sval_type); + + bad_arg_error("soft_cast", sp-1, 1, 1, t1->str, sp-1, + "Assertion failed in soft_cast(). " + "Expected %s, got %s\n", + t1->str, t2->str); + /* NOT_REACHED */ + UNSET_ONERROR(tmp2); + UNSET_ONERROR(tmp1); + free_string(t2); + free_string(t1); + } } free_string(sval_type); #ifdef PIKE_DEBUG