[vm] Delete BoundedType class in VM.

In Dart2, type bounds checking is either performed by the common front-end or
by explicitly generated code, but not by type finalization or runtime anymore,
as it was done in Dart1.
Consequently, the class BoundedType is not needed anymore, and malbounded or
malformed types are not seen by the runtime either.

Change-Id: I5d6e4c68d153d6730fa7ff7f6d9dcfa611299c16
Reviewed-on: https://dart-review.googlesource.com/c/86687
Commit-Queue: Régis Crelier <regis@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Samir Jindel <sjindel@google.com>
This commit is contained in:
Régis Crelier 2018-12-10 23:15:27 +00:00 committed by commit-bot@chromium.org
parent 5768e513f8
commit 5f36c5f9d8
51 changed files with 322 additions and 1970 deletions

View file

@ -101,7 +101,7 @@ regress/issue_29975: Fail # Issue 29975.
regress/issue_29976: RuntimeError # Tests runtime behavior of error recovery.
regress/issue_29982: RuntimeError # Tests runtime behavior of error recovery.
regress/issue_30836: RuntimeError # Issue 30836.
regress/issue_32200: RuntimeError # Invalid type.
regress/issue_32200: Pass # Invalid type mapped to dynamic type in kernel translation helper.
regress/issue_32972: RuntimeError
regress/issue_33452: RuntimeError # Test has an intentional error
regress/issue_34225: RuntimeError

View file

@ -112,9 +112,8 @@ DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 3) {
// Arg1: src value.
// Arg2: dst type.
// Arg3: dst name.
// Arg4: type error message.
// Return value: none, throws an exception.
DEFINE_NATIVE_ENTRY(TypeError_throwNew, 5) {
DEFINE_NATIVE_ENTRY(TypeError_throwNew, 4) {
// No need to type check the arguments. This function can only be called
// internally from the VM.
const TokenPosition location = TokenPosition(
@ -125,12 +124,9 @@ DEFINE_NATIVE_ENTRY(TypeError_throwNew, 5) {
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(2));
const String& dst_name =
String::CheckedHandle(zone, arguments->NativeArgAt(3));
const String& error_msg =
String::CheckedHandle(zone, arguments->NativeArgAt(4));
const AbstractType& src_type =
AbstractType::Handle(src_value.GetType(Heap::kNew));
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
error_msg);
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name);
UNREACHABLE();
return Object::null();
}

View file

@ -86,19 +86,7 @@ class _TypeError extends _AssertionError implements TypeError {
: super._create("is assignable", url, line, column, errorMsg);
static _throwNew(int location, Object src_value, _Type dst_type,
String dst_name, String bound_error_msg) native "TypeError_throwNew";
static _throwNewIfNotLoaded(
_LibraryPrefix prefix,
int location,
Object src_value,
_Type dst_type,
String dst_name,
String bound_error_msg) {
if (!prefix.isLoaded()) {
_throwNew(location, src_value, dst_type, dst_name, bound_error_msg);
}
}
String dst_name) native "TypeError_throwNew";
String toString() => super.message;
}

View file

@ -23,11 +23,6 @@ namespace dart {
#if !defined(DART_PRECOMPILED_RUNTIME)
#define PROPAGATE_IF_MALFORMED(type) \
if (type.IsMalformed()) { \
Exceptions::PropagateError(Error::Handle(type.error())); \
}
#define RETURN_OR_PROPAGATE(expr) \
RawObject* result = expr; \
if (RawObject::IsErrorClassId(result->GetClassIdMayBeSmi())) { \
@ -220,7 +215,6 @@ static RawInstance* CreateTypeVariableList(const Class& cls) {
for (intptr_t i = 0; i < args.Length(); i++) {
type ^= args.TypeAt(i);
ASSERT(type.IsTypeParameter());
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
name ^= type.name();
result.SetAt(2 * i, name);
@ -511,8 +505,7 @@ static RawInstance* CreateTypeMirror(const AbstractType& type) {
return CreateTypeMirror(ref_type);
}
ASSERT(type.IsFinalized());
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsCanonical() || type.IsTypeParameter() || type.IsBoundedType());
ASSERT(type.IsCanonical() || type.IsTypeParameter());
if (type.IsFunctionType()) {
const Class& scope_class = Class::Handle(Type::Cast(type).type_class());
@ -539,10 +532,6 @@ static RawInstance* CreateTypeMirror(const AbstractType& type) {
} else if (type.IsTypeParameter()) {
return CreateTypeVariableMirror(TypeParameter::Cast(type),
Object::null_instance());
} else if (type.IsBoundedType()) {
AbstractType& actual_type =
AbstractType::Handle(BoundedType::Cast(type).type());
return CreateTypeMirror(actual_type);
}
UNREACHABLE();
return Instance::null();
@ -591,8 +580,7 @@ static RawAbstractType* InstantiateType(const AbstractType& type,
// Generic function type parameters are not reified, but mapped to dynamic,
// i.e. all function type parameters are free with a null vector.
ASSERT(type.IsFinalized());
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsCanonical() || type.IsTypeParameter() || type.IsBoundedType());
ASSERT(type.IsCanonical() || type.IsTypeParameter());
if (type.IsInstantiated()) {
return type.Canonicalize();
@ -600,17 +588,11 @@ static RawAbstractType* InstantiateType(const AbstractType& type,
TypeArguments& instantiator_type_args = TypeArguments::Handle();
if (!instantiator.IsNull()) {
ASSERT(instantiator.IsFinalized());
PROPAGATE_IF_MALFORMED(instantiator);
instantiator_type_args = instantiator.arguments();
}
Error& bound_error = Error::Handle();
AbstractType& result = AbstractType::Handle(type.InstantiateFrom(
instantiator_type_args, Object::null_type_arguments(), kAllFree,
&bound_error, NULL, NULL, Heap::kOld));
if (!bound_error.IsNull()) {
Exceptions::PropagateError(bound_error);
UNREACHABLE();
}
instantiator_type_args, Object::null_type_arguments(), kAllFree, NULL,
Heap::kOld));
ASSERT(result.IsFinalized());
return result.Canonicalize();
}
@ -728,7 +710,6 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
ASSERT(type.HasTypeClass());
const Class& cls = Class::Handle(type.type_class());
@ -795,17 +776,6 @@ DEFINE_NATIVE_ENTRY(Mirrors_instantiateGenericType, 2) {
Type& instantiated_type =
Type::Handle(Type::New(clz, type_args_obj, TokenPosition::kNoSource));
instantiated_type ^= ClassFinalizer::FinalizeType(clz, instantiated_type);
if (instantiated_type.IsMalbounded()) {
const LanguageError& type_error =
LanguageError::Handle(instantiated_type.error());
const Array& error_args = Array::Handle(Array::New(3));
error_args.SetAt(0, args);
error_args.SetAt(1, String::Handle(String::New("typeArguments")));
error_args.SetAt(2, String::Handle(type_error.FormatMessage()));
Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args);
UNREACHABLE();
}
return instantiated_type.raw();
}
@ -903,7 +873,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_libraryUri, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
@ -913,7 +882,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
@ -922,7 +890,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
@ -935,7 +902,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
@ -958,7 +924,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_mixin, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
AbstractType& mixin_type = AbstractType::Handle();
@ -976,7 +941,6 @@ DEFINE_NATIVE_ENTRY(ClassMirror_mixin_instantiated, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, instantiator,
arguments->NativeArgAt(1));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
AbstractType& mixin_type = AbstractType::Handle();
@ -1390,14 +1354,9 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) {
// The type arguments of the redirection type are instantiated from the
// type arguments of the type reflected by the class mirror.
ASSERT(redirect_type.IsInstantiated(kFunctions));
Error& bound_error = Error::Handle();
redirect_type ^= redirect_type.InstantiateFrom(
type_arguments, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kOld);
if (!bound_error.IsNull()) {
Exceptions::PropagateError(bound_error);
UNREACHABLE();
}
type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kOld);
redirect_type ^= redirect_type.Canonicalize();
}
@ -1675,7 +1634,7 @@ DEFINE_NATIVE_ENTRY(VariableMirror_type, 2) {
DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
return Bool::Get(a.IsSubtypeOf(b, NULL, NULL, Heap::kNew)).raw();
return Bool::Get(a.IsSubtypeOf(b, Heap::kNew)).raw();
}
#endif // !DART_PRECOMPILED_RUNTIME

View file

@ -141,11 +141,8 @@ DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
Error& bound_error = Error::Handle(zone, Error::null());
const bool is_instance_of = instance.IsInstanceOf(
type, instantiator_type_arguments, function_type_arguments, &bound_error);
type, instantiator_type_arguments, function_type_arguments);
if (FLAG_trace_type_checks) {
const char* result_str = is_instance_of ? "true" : "false";
OS::PrintErr("Native Object.instanceOf: result %s\n", result_str);
@ -155,23 +152,6 @@ DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
String::Handle(zone, instance_type.Name()).ToCString());
OS::PrintErr(" test type: %s\n",
String::Handle(zone, type.Name()).ToCString());
if (!bound_error.IsNull()) {
OS::PrintErr(" bound error: %s\n", bound_error.ToErrorCString());
}
}
if (!is_instance_of && !bound_error.IsNull()) {
// Throw a dynamic type error only if the instanceof test fails.
DartFrameIterator iterator(thread,
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
const TokenPosition location = caller_frame->GetTokenPos();
String& bound_error_message =
String::Handle(zone, String::New(bound_error.ToErrorCString()));
Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
AbstractType::Handle(zone),
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
return Bool::Get(is_instance_of).raw();
}
@ -184,27 +164,9 @@ DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 2) {
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(1));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
ASSERT(type.IsInstantiated());
Error& bound_error = Error::Handle(zone, Error::null());
const bool is_instance_of =
instance.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments(), &bound_error);
if (!is_instance_of && !bound_error.IsNull()) {
// Throw a dynamic type error only if the instanceof test fails.
DartFrameIterator iterator(thread,
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
const TokenPosition location = caller_frame->GetTokenPos();
String& bound_error_message =
String::Handle(zone, String::New(bound_error.ToErrorCString()));
Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
AbstractType::Handle(zone),
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
const bool is_instance_of = instance.IsInstanceOf(
type, Object::null_type_arguments(), Object::null_type_arguments());
return Bool::Get(is_instance_of).raw();
}
@ -277,7 +239,6 @@ static bool ExtractInterfaceTypeArgs(Zone* zone,
AbstractType& interface = AbstractType::Handle(zone);
Class& cur_interface_cls = Class::Handle(zone);
TypeArguments& cur_interface_type_args = TypeArguments::Handle(zone);
Error& error = Error::Handle(zone);
while (true) {
// Additional subtyping rules related to 'FutureOr' are not applied.
if (cur_cls.raw() == interface_cls.raw()) {
@ -287,18 +248,14 @@ static bool ExtractInterfaceTypeArgs(Zone* zone,
interfaces = cur_cls.interfaces();
for (intptr_t i = 0; i < interfaces.Length(); i++) {
interface ^= interfaces.At(i);
ASSERT(interface.IsFinalized() && !interface.IsMalbounded());
ASSERT(interface.IsFinalized());
cur_interface_cls = interface.type_class();
cur_interface_type_args = interface.arguments();
if (!cur_interface_type_args.IsNull() &&
!cur_interface_type_args.IsInstantiated()) {
error = Error::null();
cur_interface_type_args = cur_interface_type_args.InstantiateFrom(
instance_type_args, Object::null_type_arguments(), kNoneFree,
&error, NULL, NULL, Heap::kNew);
if (!error.IsNull()) {
continue; // Another interface may work better.
}
instance_type_args, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kNew);
}
if (ExtractInterfaceTypeArgs(zone, cur_interface_cls,
cur_interface_type_args, interface_cls,
@ -442,20 +399,18 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 2) {
AbstractType& supertype = AbstractType::Handle(zone);
AbstractType& subtype = AbstractType::Handle(zone);
TypeParameter& parameter = TypeParameter::Handle(zone);
Error& bound_error = Error::Handle(zone);
for (intptr_t i = 0; i < bounds.Length(); ++i) {
parameter ^= bounds.TypeAt(i);
supertype = parameter.bound();
subtype = type_args_to_check.IsNull() ? Object::dynamic_type().raw()
: type_args_to_check.TypeAt(i);
ASSERT(!subtype.IsNull() && !subtype.IsMalformedOrMalbounded());
ASSERT(!supertype.IsNull() && !supertype.IsMalformedOrMalbounded());
ASSERT(!subtype.IsNull());
ASSERT(!supertype.IsNull());
// The supertype may not be instantiated.
if (!AbstractType::InstantiateAndTestSubtype(
&subtype, &supertype, &bound_error, instantiator_type_args,
function_type_args)) {
&subtype, &supertype, instantiator_type_args, function_type_args)) {
// Throw a dynamic type error.
TokenPosition location;
{
@ -465,13 +420,9 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 2) {
ASSERT(caller_frame != NULL);
location = caller_frame->GetTokenPos();
}
String& bound_error_message = String::Handle(zone);
if (!bound_error.IsNull()) {
bound_error_message = String::New(bound_error.ToErrorCString());
}
String& parameter_name = String::Handle(zone, parameter.Name());
Exceptions::CreateAndThrowTypeError(location, subtype, supertype,
parameter_name, bound_error_message);
parameter_name);
UNREACHABLE();
}
}

View file

@ -26,10 +26,6 @@ class _TypeRef extends _AbstractType {}
@pragma("vm:entry-point")
class _TypeParameter extends _AbstractType {}
// Equivalent of RawBoundedType.
@pragma("vm:entry-point")
class _BoundedType extends _AbstractType {}
// Equivalent of RawMixinAppType.
@pragma("vm:entry-point")
class _MixinAppType extends _AbstractType {}

View file

@ -128,7 +128,6 @@ class InstanceRefElement extends HtmlElement implements Renderable {
case M.InstanceKind.type:
case M.InstanceKind.typeRef:
case M.InstanceKind.typeParameter:
case M.InstanceKind.boundedType:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..text = _instance.name

View file

@ -15,7 +15,7 @@ abstract class FieldRef extends ObjectRef {
/// The declared type of this field.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter, BoundedType.
/// Type, TypeRef, TypeParameter.
InstanceRef get declaredType;
/// Is this field const?

View file

@ -120,9 +120,6 @@ enum InstanceKind {
/// An instance of the Dart class TypeRef.
typeRef,
/// An instance of the Dart class BoundedType.
boundedType,
}
bool isTypedData(InstanceKind kind) {
@ -163,7 +160,6 @@ bool isAbstractType(InstanceKind kind) {
case InstanceKind.type:
case InstanceKind.typeRef:
case InstanceKind.typeParameter:
case InstanceKind.boundedType:
return true;
default:
return false;
@ -376,25 +372,21 @@ abstract class Instance extends Object implements InstanceRef {
/// TypeParameter
int get parameterIndex;
/// [optional] The type bounded by a BoundedType instance
/// - or -
/// the referent of a TypeRef instance.
/// [optional] The referent of a TypeRef instance.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter, BoundedType.
/// Type, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// BoundedType
/// TypeRef
InstanceRef get targetType;
/// [optional] The bound of a TypeParameter or BoundedType.
/// [optional] The bound of a TypeParameter.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter, BoundedType.
/// Type, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// BoundedType
/// TypeParameter
InstanceRef get bound;

View file

@ -13,6 +13,6 @@ abstract class TypeArguments extends Object implements TypeArgumentsRef {
/// A list of types.
///
/// The value will always be one of the kinds:
/// Type, TypeRef, TypeParameter, BoundedType.
/// Type, TypeRef, TypeParameter.
Iterable<InstanceRef> get types;
}

View file

@ -2748,8 +2748,6 @@ M.InstanceKind stringToInstanceKind(String s) {
return M.InstanceKind.typeParameter;
case 'TypeRef':
return M.InstanceKind.typeRef;
case 'BoundedType':
return M.InstanceKind.boundedType;
}
var message = 'Unrecognized instance kind: $s';
Logger.root.severe(message);

View file

@ -156,7 +156,7 @@ namespace dart {
V(StackTrace_clearAsyncThreadStackTrace, 0) \
V(StackTrace_setAsyncThreadStackTrace, 1) \
V(StackTrace_current, 0) \
V(TypeError_throwNew, 5) \
V(TypeError_throwNew, 4) \
V(FallThroughError_throwNew, 1) \
V(AbstractClassInstantiationError_throwNew, 2) \
V(Stopwatch_now, 0) \

View file

@ -85,7 +85,7 @@ static void CollectFinalizedSuperClasses(
AbstractType& super_type = Type::Handle();
super_type = cls.super_type();
if (!super_type.IsNull()) {
if (!super_type.IsMalformed() && super_type.HasTypeClass()) {
if (super_type.HasTypeClass()) {
cls ^= super_type.type_class();
if (cls.is_finalized()) {
AddSuperType(super_type, finalized_super_classes);
@ -155,7 +155,6 @@ static void CollectImmediateSuperInterfaces(const Class& cls,
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < interfaces.Length(); ++i) {
type ^= interfaces.At(i);
if (type.IsMalformed()) continue;
if (!type.HasTypeClass()) continue;
ifc ^= type.type_class();
for (intptr_t j = 0; j < cids->length(); ++j) {
@ -313,16 +312,11 @@ void ClassFinalizer::ResolveRedirectingFactory(const Class& cls,
const Function& target = Function::Handle(factory.RedirectionTarget());
if (target.IsNull()) {
Type& type = Type::Handle(factory.RedirectionType());
if (!type.IsMalformed()) {
const GrowableObjectArray& visited_factories =
GrowableObjectArray::Handle(GrowableObjectArray::New());
ResolveRedirectingFactoryTarget(cls, factory, visited_factories);
}
const GrowableObjectArray& visited_factories =
GrowableObjectArray::Handle(GrowableObjectArray::New());
ResolveRedirectingFactoryTarget(cls, factory, visited_factories);
if (factory.is_const()) {
type = factory.RedirectionType();
if (type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(type.error()));
}
}
}
}
@ -347,11 +341,6 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
// Check if target is already resolved.
Type& type = Type::Handle(factory.RedirectionType());
Function& target = Function::Handle(factory.RedirectionTarget());
if (type.IsMalformedOrMalbounded()) {
// Already resolved to a malformed or malbounded type. Will throw on usage.
ASSERT(target.IsNull());
return;
}
if (!target.IsNull()) {
// Already resolved.
return;
@ -364,21 +353,8 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
}
type ^= FinalizeType(cls, type);
factory.SetRedirectionType(type);
if (type.IsMalformedOrMalbounded()) {
ASSERT(factory.RedirectionTarget() == Function::null());
return;
}
ASSERT(!type.IsTypeParameter()); // Resolved in parser.
if (type.IsDynamicType()) {
// Replace the type with a malformed type and compile a throw when called.
type = NewFinalizedMalformedType(Error::Handle(), // No previous error.
Script::Handle(cls.script()),
factory.token_pos(),
"factory may not redirect to 'dynamic'");
factory.SetRedirectionType(type);
ASSERT(factory.RedirectionTarget() == Function::null());
return;
}
ASSERT(!type.IsDynamicType());
const Class& target_class = Class::Handle(type.type_class());
String& target_class_name = String::Handle(target_class.Name());
String& target_name =
@ -393,20 +369,7 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
if (target.IsNull()) {
target = target_class.LookupFactory(target_name);
}
if (target.IsNull()) {
const String& user_visible_target_name =
identifier.IsNull() ? target_class_name : target_name;
// Replace the type with a malformed type and compile a throw when called.
type = NewFinalizedMalformedType(
Error::Handle(), // No previous error.
Script::Handle(target_class.script()), factory.token_pos(),
"class '%s' has no constructor or factory named '%s'",
target_class_name.ToCString(), user_visible_target_name.ToCString());
factory.SetRedirectionType(type);
ASSERT(factory.RedirectionTarget() == Function::null());
return;
}
ASSERT(!target.IsNull());
// Verify that the target is const if the redirecting factory is const.
if (factory.is_const() && !target.is_const()) {
ReportError(target_class, target.token_pos(),
@ -430,29 +393,15 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
ResolveRedirectingFactoryTarget(target_class, target, visited_factories);
Type& target_type = Type::Handle(target.RedirectionType());
Function& target_target = Function::Handle(target.RedirectionTarget());
if (target_target.IsNull()) {
ASSERT(target_type.IsMalformed());
} else {
// If the target type refers to type parameters, substitute them with the
// type arguments of the redirection type.
if (!target_type.IsInstantiated()) {
// We do not support generic constructors.
ASSERT(target_type.IsInstantiated(kFunctions));
const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
Error& bound_error = Error::Handle();
target_type ^= target_type.InstantiateFrom(
type_args, Object::null_type_arguments(), kNoneFree, &bound_error,
NULL, NULL, Heap::kOld);
if (bound_error.IsNull()) {
target_type ^= FinalizeType(cls, target_type);
} else {
ASSERT(target_type.IsInstantiated() && type_args.IsInstantiated());
const Script& script = Script::Handle(target_class.script());
FinalizeMalformedType(bound_error, script, target_type,
"cannot resolve redirecting factory");
target_target = Function::null();
}
}
ASSERT(!target_target.IsNull());
// If the target type refers to type parameters, substitute them with the
// type arguments of the redirection type.
if (!target_type.IsInstantiated()) {
// We do not support generic constructors.
ASSERT(target_type.IsInstantiated(kFunctions));
const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
target_type ^= target_type.InstantiateFrom(
type_args, Object::null_type_arguments(), kNoneFree, NULL, Heap::kOld);
}
factory.SetRedirectionType(target_type);
factory.SetRedirectionTarget(target_target);
@ -478,8 +427,7 @@ void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
// Promote the type to a function type in case its type class is a typedef.
// Note that the type may already be a function type if it was parsed as a
// formal parameter function type.
if (!type.IsFunctionType() && type_class.IsTypedefClass() &&
!type.IsMalformedOrMalbounded()) {
if (!type.IsFunctionType() && type_class.IsTypedefClass()) {
type.set_signature(Function::Handle(type_class.signature_function()));
}
ASSERT(!type_class.IsTypedefClass() ||
@ -495,10 +443,6 @@ void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
}
if (type.IsType()) {
ResolveTypeClass(cls, Type::Cast(type));
if (type.IsMalformed()) {
ASSERT(type.IsResolved());
return;
}
}
// Mark type as resolved before resolving its type arguments and, in case of a
// function type, its signature, in order to avoid cycles.
@ -657,16 +601,14 @@ void ClassFinalizer::CheckRecursiveType(const Class& cls,
!pending_arguments.IsSubvectorInstantiated(first_type_param,
num_type_params)) {
const TypeArguments& instantiated_arguments = TypeArguments::Handle(
zone,
arguments.InstantiateFrom(Object::null_type_arguments(),
Object::null_type_arguments(), kNoneFree,
NULL, NULL, NULL, Heap::kNew));
zone, arguments.InstantiateFrom(Object::null_type_arguments(),
Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew));
const TypeArguments& instantiated_pending_arguments =
TypeArguments::Handle(
zone, pending_arguments.InstantiateFrom(
Object::null_type_arguments(),
Object::null_type_arguments(), kNoneFree, NULL, NULL,
NULL, Heap::kNew));
TypeArguments::Handle(zone, pending_arguments.InstantiateFrom(
Object::null_type_arguments(),
Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew));
if (!instantiated_pending_arguments.IsSubvectorEquivalent(
instantiated_arguments, first_type_param, num_type_params)) {
const String& type_name = String::Handle(zone, type.Name());
@ -757,10 +699,7 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
type_arg = full_arguments.TypeAt(offset + i);
ASSERT(!type_arg.IsBeingFinalized());
type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
if (type_arg.IsMalformed()) {
// Malformed type arguments are mapped to dynamic.
type_arg = Type::DynamicType();
} else if (type_arg.IsFunctionType()) {
if (type_arg.IsFunctionType()) {
const Function& signature_function =
Function::Handle(zone, Type::Cast(type_arg).signature());
if (signature_function.IsGeneric()) {
@ -779,9 +718,8 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
}
if (offset > 0) {
TrailPtr instantiation_trail = new Trail(zone, 4);
Error& bound_error = Error::Handle(zone);
FinalizeTypeArguments(type_class, full_arguments, offset, &bound_error,
pending_types, instantiation_trail);
FinalizeTypeArguments(type_class, full_arguments, offset, pending_types,
instantiation_trail);
}
if (full_arguments.IsRaw(0, num_type_arguments)) {
// The parameterized_type is raw. Set its argument vector to null, which
@ -835,7 +773,6 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
const TypeArguments& arguments,
intptr_t num_uninitialized_arguments,
Error* bound_error,
PendingTypes* pending_types,
TrailPtr instantiation_trail) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
@ -906,20 +843,9 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
arguments.SetTypeAt(i, super_type_arg);
continue;
}
Error& error = Error::Handle();
super_type_arg = super_type_arg.InstantiateFrom(
arguments, Object::null_type_arguments(), kNoneFree, &error,
instantiation_trail, NULL, Heap::kOld);
if (!error.IsNull()) {
// InstantiateFrom does not report an error if the type is still
// uninstantiated. Instead, it will return a new BoundedType so
// that the check is postponed to run time.
ASSERT(super_type_arg.IsInstantiated());
// Keep only the first bound error.
if (bound_error->IsNull()) {
*bound_error = error.raw();
}
}
arguments, Object::null_type_arguments(), kNoneFree,
instantiation_trail, Heap::kOld);
if (super_type_arg.IsBeingFinalized()) {
// The super_type_arg was instantiated from a type being finalized.
// We need to finish finalizing its type arguments.
@ -947,7 +873,7 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
FinalizeTypeArguments(
super_cls, super_args,
super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
bound_error, pending_types, instantiation_trail);
pending_types, instantiation_trail);
if (FLAG_trace_type_finalization) {
THR_Print("Finalized instantiated TypeRef '%s': '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
@ -958,8 +884,8 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
}
arguments.SetTypeAt(i, super_type_arg);
}
FinalizeTypeArguments(super_class, arguments, super_offset, bound_error,
pending_types, instantiation_trail);
FinalizeTypeArguments(super_class, arguments, super_offset, pending_types,
instantiation_trail);
}
}
@ -971,10 +897,9 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
// types have been bound checked.
ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
if (type.IsFinalized()) {
// Ensure type is canonical if canonicalization is requested, unless type is
// malformed.
if ((finalization >= kCanonicalize) && !type.IsMalformed() &&
!type.IsCanonical() && type.IsType()) {
// Ensure type is canonical if canonicalization is requested.
if ((finalization >= kCanonicalize) && !type.IsCanonical() &&
type.IsType()) {
return type.Canonicalize();
}
return type.raw();
@ -993,11 +918,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
Zone* zone = Thread::Current()->zone();
ResolveType(cls, type);
// A malformed type gets mapped to a finalized type.
if (type.IsMalformed()) {
ASSERT(type.IsFinalized());
return type.raw();
}
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type '%s' for class '%s'\n",
@ -1457,8 +1377,6 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
super_type_args.SetTypeAt(cloned_index, cloned_param);
cloned_index++;
}
// The super type may have a BoundedType as type argument, but cannot be
// a BoundedType itself.
Type::Cast(super_type).set_arguments(super_type_args);
ASSERT(!super_type.IsFinalized());
}
@ -1504,7 +1422,6 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
// is not a problem since they will get finalized shortly as the mixin
// application class gets finalized.
if (has_uninstantiated_bounds) {
Error& bound_error = Error::Handle(zone);
for (intptr_t i = 0; i < num_mixin_type_params; i++) {
param ^= mixin_type_args.TypeAt(i);
param_bound = param.bound();
@ -1515,12 +1432,9 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
param.set_bound(param_bound); // In case part of recursive type.
}
param_bound = param_bound.InstantiateFrom(
instantiator, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(!param_bound.IsBoundedType());
ASSERT(bound_error.IsNull());
instantiator, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kOld);
// The instantiator contains only TypeParameter objects.
ASSERT(!param_bound.IsInstantiated());
param.set_bound(param_bound);
}
@ -1735,40 +1649,13 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
if ((num_aliased_mixin_type_params > 0) &&
!mixin_class_super_type_args.IsNull()) {
new_mixin_type_args = TypeArguments::New(num_aliased_mixin_type_params);
AbstractType& bounded_type = AbstractType::Handle(zone);
AbstractType& upper_bound = AbstractType::Handle(zone);
TypeParameter& type_parameter = TypeParameter::Handle(zone);
Error& bound_error = Error::Handle(zone);
const intptr_t offset =
mixin_class_super_type_args.Length() - num_aliased_mixin_type_params;
for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) {
type = mixin_class_super_type_args.TypeAt(offset + i);
if (!type.IsInstantiated()) {
// In the presence of bounds, the bounded type and the upper bound must
// be instantiated separately. Instantiating a BoundedType would wrap
// the BoundedType in another BoundedType.
if (type.IsBoundedType()) {
bounded_type = BoundedType::Cast(type).type();
bounded_type = bounded_type.InstantiateFrom(
instantiator, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(bound_error.IsNull());
upper_bound = BoundedType::Cast(type).bound();
upper_bound = upper_bound.InstantiateFrom(
instantiator, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
type_parameter = BoundedType::Cast(type).type_parameter();
// The type parameter that declared the bound does not change.
type = BoundedType::New(bounded_type, upper_bound, type_parameter);
} else {
type = type.InstantiateFrom(instantiator,
Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
}
type = type.InstantiateFrom(instantiator, Object::null_type_arguments(),
kNoneFree, NULL, Heap::kOld);
}
new_mixin_type_args.SetTypeAt(i, type);
}
@ -1867,10 +1754,6 @@ void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class,
ASSERT(!mixin_type.IsBeingFinalized());
mixin_type ^=
FinalizeType(mixin_app_class, mixin_type, kFinalize, pending_types);
// The mixin type cannot be malbounded, since it merely substitutes the
// type parameters of the mixin class with those of the mixin application
// class, but it does not instantiate them.
ASSERT(!mixin_type.IsMalbounded());
mixin_app_class.set_mixin(mixin_type);
}
@ -2074,13 +1957,6 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
// Finalize super type.
AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (!super_type.IsNull()) {
// In case of a bound error in the super type in production mode, the
// finalized super type will have a BoundedType as type argument for the
// out of bound type argument.
// It should not be a problem if the class is written to a snapshot and
// later executed in checked mode. Note that the finalized type argument
// vector of any type of the base class will contain a BoundedType for the
// out of bound type argument.
super_type = FinalizeType(cls, super_type);
cls.set_super_type(super_type);
}
@ -2443,7 +2319,7 @@ bool ClassFinalizer::IsTypedefCycleFree(const Class& cls,
ASSERT(visited != NULL);
ResolveType(cls, type);
bool checking_typedef = false;
if (type.IsType() && !type.IsMalformed()) {
if (type.IsType()) {
AbstractType& other_type = AbstractType::Handle();
if (type.IsFunctionType()) {
const Class& scope_class = Class::Handle(type.type_class());
@ -2589,15 +2465,10 @@ RawType* ClassFinalizer::ResolveMixinAppType(
AbstractType::Handle(zone, mixin_app_type.super_type());
ResolveType(cls, mixin_super_type);
ASSERT(mixin_super_type.HasTypeClass()); // Even if malformed.
if (mixin_super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, mixin_super_type.error()));
}
if (mixin_super_type.IsDynamicType()) {
ReportError(cls, cls.token_pos(), "class '%s' may not extend 'dynamic'",
String::Handle(zone, cls.Name()).ToCString());
}
// The super type may have a BoundedType as type argument, but cannot be
// a BoundedType itself.
CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args);
AbstractType& mixin_type = AbstractType::Handle(zone);
Class& mixin_app_class = Class::Handle(zone);
@ -2618,9 +2489,6 @@ RawType* ClassFinalizer::ResolveMixinAppType(
ResolveType(cls, mixin_type);
ASSERT(mixin_type.HasTypeClass()); // Even if malformed.
ASSERT(mixin_type.IsType());
if (mixin_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, mixin_type.error()));
}
if (mixin_type.IsDynamicType()) {
ReportError(cls, cls.token_pos(), "class '%s' may not mixin 'dynamic'",
String::Handle(zone, cls.Name()).ToCString());
@ -2824,9 +2692,6 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
// Resolve super type. Failures lead to a longjmp.
ResolveType(cls, super_type);
if (super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, super_type.error()));
}
if (super_type.IsDynamicType()) {
ReportError(cls, cls.token_pos(), "class '%s' may not extend 'dynamic'",
String::Handle(zone, cls.Name()).ToCString());
@ -2899,10 +2764,6 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
interface ^= super_interfaces.At(i);
ResolveType(cls, interface);
ASSERT(!interface.IsTypeParameter()); // Should be detected by parser.
// A malbounded interface is only reported when involved in a type test.
if (interface.IsMalformed()) {
ReportError(Error::Handle(zone, interface.error()));
}
if (interface.IsDynamicType()) {
ReportError(cls, cls.token_pos(),
"'dynamic' may not be used as interface");
@ -3017,77 +2878,6 @@ void ClassFinalizer::PrintClassInformation(const Class& cls) {
}
}
// Either report an error or mark the type as malformed.
void ClassFinalizer::MarkTypeMalformed(const Error& prev_error,
const Script& script,
const Type& type,
const char* format,
va_list args) {
LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
prev_error, script, type.token_pos(), Report::AtLocation,
Report::kMalformedType, Heap::kOld, format, args));
type.set_error(error);
// Make the type raw, since it may not be possible to
// properly finalize its type arguments.
type.set_type_class(Class::Handle(Object::dynamic_class()));
type.set_arguments(Object::null_type_arguments());
if (!type.IsFinalized()) {
type.SetIsFinalized();
// Do not canonicalize malformed types, since they contain an error field.
} else {
// The only case where the malformed type was already finalized is when its
// type arguments are not within bounds. In that case, we have a prev_error.
ASSERT(!prev_error.IsNull());
}
}
RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error,
const Script& script,
TokenPosition type_pos,
const char* format,
...) {
va_list args;
va_start(args, format);
// TODO(regis): Are malformed types still used in strong mode? Probably not.
const Type& type =
Type::Handle(Type::New(Class::Handle(Object::dynamic_class()),
Object::null_type_arguments(), type_pos));
MarkTypeMalformed(prev_error, script, type, format, args);
va_end(args);
ASSERT(type.IsMalformed());
ASSERT(type.IsFinalized());
return type.raw();
}
void ClassFinalizer::FinalizeMalformedType(const Error& prev_error,
const Script& script,
const Type& type,
const char* format,
...) {
va_list args;
va_start(args, format);
MarkTypeMalformed(prev_error, script, type, format, args);
va_end(args);
}
void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
const Script& script,
const AbstractType& type,
const char* format,
...) {
va_list args;
va_start(args, format);
LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
prev_error, script, type.token_pos(), Report::AtLocation,
Report::kMalboundedType, Heap::kOld, format, args));
va_end(args);
type.set_error(error);
if (!type.IsFinalized()) {
type.SetIsFinalized();
// Do not canonicalize malbounded types.
}
}
void ClassFinalizer::ReportError(const Error& error) {
Report::LongJump(error);
UNREACHABLE();
@ -3359,7 +3149,6 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
//
// * RawTypeRef (due to RawTypeRef::type_->type_class_id)
// * RawType (due to RawType::signature_'s result/parameter types)
// * RawBoundedType (due to RawBoundedType::type_parameter_)
// * RawTypeArguments (due to type references)
// * RawInstance (due to instance fields)
// * RawArray (due to type arguments & array entries)
@ -3368,7 +3157,6 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
//
// * RawType::hash_
// * RawTypeParameter::hash_
// * RawBoundedType::hash_
// * RawTypeArguments::hash_
//
// No caching of canonical hash codes (i.e. it gets re-computed every time)
@ -3389,8 +3177,7 @@ class ClearTypeHashVisitor : public ObjectVisitor {
explicit ClearTypeHashVisitor(Zone* zone)
: type_param_(TypeParameter::Handle(zone)),
type_(Type::Handle(zone)),
type_args_(TypeArguments::Handle(zone)),
bounded_type_(BoundedType::Handle(zone)) {}
type_args_(TypeArguments::Handle(zone)) {}
void VisitObject(RawObject* obj) {
if (obj->IsTypeParameter()) {
@ -3399,9 +3186,6 @@ class ClearTypeHashVisitor : public ObjectVisitor {
} else if (obj->IsType()) {
type_ ^= obj;
type_.SetHash(0);
} else if (obj->IsBoundedType()) {
bounded_type_ ^= obj;
bounded_type_.SetHash(0);
} else if (obj->IsTypeArguments()) {
type_args_ ^= obj;
type_args_.SetHash(0);
@ -3412,7 +3196,6 @@ class ClearTypeHashVisitor : public ObjectVisitor {
TypeParameter& type_param_;
Type& type_;
TypeArguments& type_args_;
BoundedType& bounded_type_;
};
void ClassFinalizer::RehashTypes() {

View file

@ -39,34 +39,6 @@ class ClassFinalizer : public AllStatic {
const Function& function,
FinalizationKind finalization = kCanonicalize);
// Allocate, finalize, and return a new malformed type as if it was declared
// in class cls at the given token position.
// If not null, prepend prev_error to the error message built from the format
// string and its arguments.
static RawType* NewFinalizedMalformedType(const Error& prev_error,
const Script& script,
TokenPosition type_pos,
const char* format,
...) PRINTF_ATTRIBUTE(4, 5);
// Mark the given type as malformed.
// If not null, prepend prev_error to the error message built from the format
// string and its arguments.
static void FinalizeMalformedType(const Error& prev_error,
const Script& script,
const Type& type,
const char* format,
...) PRINTF_ATTRIBUTE(4, 5);
// Mark the given type as malbounded.
// If not null, prepend prev_error to the error message built from the format
// string and its arguments.
static void FinalizeMalboundedType(const Error& prev_error,
const Script& script,
const AbstractType& type,
const char* format,
...) PRINTF_ATTRIBUTE(4, 5);
// Return false if we still have classes pending to be finalized.
static bool AllClassesFinalized();
@ -146,7 +118,6 @@ class ClassFinalizer : public AllStatic {
static void FinalizeTypeArguments(const Class& cls,
const TypeArguments& arguments,
intptr_t num_uninitialized_arguments,
Error* bound_error,
PendingTypes* pending_types,
TrailPtr trail);
static void CheckRecursiveType(const Class& cls,
@ -162,11 +133,6 @@ class ClassFinalizer : public AllStatic {
static void CollectInterfaces(const Class& cls,
GrowableArray<const Class*>* collected);
static void MarkTypeMalformed(const Error& prev_error,
const Script& script,
const Type& type,
const char* format,
va_list args);
static void ReportError(const Error& error);
static void ReportError(const Class& cls,
TokenPosition token_pos,

View file

@ -3057,70 +3057,6 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
Instructions& instr_;
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class BoundedTypeSerializationCluster : public SerializationCluster {
public:
BoundedTypeSerializationCluster() : SerializationCluster("BoundedType") {}
~BoundedTypeSerializationCluster() {}
void Trace(Serializer* s, RawObject* object) {
RawBoundedType* type = BoundedType::RawCast(object);
objects_.Add(type);
PushFromTo(type);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kBoundedTypeCid);
intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
RawBoundedType* type = objects_[i];
s->AssignRef(type);
}
}
void WriteFill(Serializer* s) {
intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
RawBoundedType* type = objects_[i];
AutoTraceObject(type);
WriteFromTo(type);
}
}
private:
GrowableArray<RawBoundedType*> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
class BoundedTypeDeserializationCluster : public DeserializationCluster {
public:
BoundedTypeDeserializationCluster() {}
~BoundedTypeDeserializationCluster() {}
void ReadAlloc(Deserializer* d) {
start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, BoundedType::InstanceSize()));
}
stop_index_ = d->next_index();
}
void ReadFill(Deserializer* d) {
bool is_vm_object = d->isolate() == Dart::vm_isolate();
for (intptr_t id = start_index_; id < stop_index_; id++) {
RawBoundedType* type = reinterpret_cast<RawBoundedType*>(d->Ref(id));
Deserializer::InitializeHeader(type, kBoundedTypeCid,
BoundedType::InstanceSize(), is_vm_object);
ReadFromTo(type);
}
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class ClosureSerializationCluster : public SerializationCluster {
public:
@ -4333,8 +4269,6 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
return new (Z) TypeRefSerializationCluster(type_testing_stubs_);
case kTypeParameterCid:
return new (Z) TypeParameterSerializationCluster(type_testing_stubs_);
case kBoundedTypeCid:
return new (Z) BoundedTypeSerializationCluster();
case kClosureCid:
return new (Z) ClosureSerializationCluster();
case kMintCid:
@ -4901,8 +4835,6 @@ DeserializationCluster* Deserializer::ReadCluster() {
return new (Z) TypeRefDeserializationCluster();
case kTypeParameterCid:
return new (Z) TypeParameterDeserializationCluster();
case kBoundedTypeCid:
return new (Z) BoundedTypeDeserializationCluster();
case kClosureCid:
return new (Z) ClosureDeserializationCluster();
case kMintCid:

View file

@ -648,12 +648,6 @@ void Precompiler::AddType(const AbstractType& abstype) {
const Function& func = Function::Handle(Z, type.signature());
AddTypesOf(func);
}
} else if (abstype.IsBoundedType()) {
AbstractType& type = AbstractType::Handle(Z);
type = BoundedType::Cast(abstype).type();
AddType(type);
type = BoundedType::Cast(abstype).bound();
AddType(type);
} else if (abstype.IsTypeRef()) {
AbstractType& type = AbstractType::Handle(Z);
type = TypeRef::Cast(abstype).type();
@ -1437,7 +1431,7 @@ void Precompiler::AttachOptimizedTypeTestingStub() {
continue;
}
if (type.IsResolved() && !type.IsMalformedOrMalbounded()) {
if (type.IsResolved()) {
if (type_usage_info->IsUsedInTypeTest(type)) {
instr = type_testing_stubs.OptimizedCodeForType(type);
type.SetTypeTestingStub(instr);

View file

@ -761,12 +761,9 @@ void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
const Instance& instance = Instance::Cast(value);
if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
instr->function_type_arguments()->BindsToConstantNull()) {
Error& bound_error = Error::Handle();
bool is_instance =
instance.IsInstanceOf(checked_type, Object::null_type_arguments(),
Object::null_type_arguments(), &bound_error);
// Can only have bound error with generics.
ASSERT(bound_error.IsNull());
Object::null_type_arguments());
SetValue(instr, Bool::Get(is_instance));
return;
}

View file

@ -2104,7 +2104,7 @@ void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
// caller side!
const Type& int_type = Type::Handle(zone(), Type::IntType());
bool is_non_smi = false;
if (int_type.IsSubtypeOf(dst_type, NULL, NULL, Heap::kOld)) {
if (int_type.IsSubtypeOf(dst_type, Heap::kOld)) {
__ BranchIfSmi(instance_reg, done);
is_non_smi = true;
}

View file

@ -247,12 +247,8 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
Error& bound_error = Error::Handle(zone());
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(type, &bound_error, NULL, Heap::kOld);
// Malformed type should have been handled at graph construction time.
ASSERT(smi_is_ok || bound_error.IsNull());
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ tst(kInstanceReg, Operand(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -284,12 +280,11 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (type_arguments.Length() == 1) {
const AbstractType& tp_argument =
AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
ASSERT(!tp_argument.IsMalformed());
if (tp_argument.IsType()) {
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -340,8 +335,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (smi_class.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL,
Heap::kOld)) {
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ b(is_instance_lbl, EQ);
} else {
@ -595,7 +589,7 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
ASSERT(type.IsFinalized());
ASSERT(!type.IsObjectType() && !type.IsDynamicType() && !type.IsVoidType());
const Register kInstantiatorTypeArgumentsReg = R2;
const Register kFunctionTypeArgumentsReg = R1;
@ -674,32 +668,11 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
ASSERT(!dst_type.IsNull());
ASSERT(dst_type.IsFinalized());
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType()));
ASSERT(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType());
const Register kInstantiatorTypeArgumentsReg = R2;
const Register kFunctionTypeArgumentsReg = R1;
// Generate throw new TypeError() if the type is malformed or malbounded.
if (dst_type.IsMalformedOrMalbounded()) {
// A null object is always assignable and is returned as result.
Label is_assignable;
__ CompareObject(R0, Object::null_object());
__ b(&is_assignable, EQ);
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the source object.
__ PushObject(dst_name); // Push the name of the destination.
__ PushObject(dst_type); // Push the type of the destination.
GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3,
locs);
// We should never return here.
__ bkpt(0);
__ Bind(&is_assignable); // For a null object.
return;
}
if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
dst_name, locs);

View file

@ -242,12 +242,8 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
Error& bound_error = Error::Handle(zone());
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(type, &bound_error, NULL, Heap::kOld);
// Malformed type should have been handled at graph construction time.
ASSERT(smi_is_ok || bound_error.IsNull());
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
// Fast case for type = FutureOr<int/num/top-type>.
__ BranchIfSmi(kInstanceReg,
smi_is_ok ? is_instance_lbl : is_not_instance_lbl);
@ -276,11 +272,10 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (type_arguments.Length() == 1) {
const AbstractType& tp_argument =
AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
ASSERT(!tp_argument.IsMalformed());
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -329,8 +324,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (smi_class.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL,
Heap::kOld)) {
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ BranchIfSmi(kInstanceReg, is_instance_lbl);
} else {
@ -579,7 +573,7 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
ASSERT(type.IsFinalized());
ASSERT(!type.IsObjectType() && !type.IsDynamicType() && !type.IsVoidType());
const Register kInstantiatorTypeArgumentsReg = R1;
const Register kFunctionTypeArgumentsReg = R2;
@ -657,32 +651,11 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
ASSERT(!dst_type.IsNull());
ASSERT(dst_type.IsFinalized());
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType()));
ASSERT(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType());
const Register kInstantiatorTypeArgumentsReg = R1;
const Register kFunctionTypeArgumentsReg = R2;
// Generate throw new TypeError() if the type is malformed or malbounded.
if (dst_type.IsMalformedOrMalbounded()) {
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
__ CompareObject(R0, Object::null_object());
__ b(&is_assignable, EQ);
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the source object.
__ PushObject(dst_name); // Push the name of the destination.
__ PushObject(dst_type); // Push the type of the destination.
GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3,
locs);
// We should never return here.
__ brk(0);
__ Bind(&is_assignable); // For a null object.
return;
}
if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
dst_name, locs);

View file

@ -231,21 +231,17 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ PushConstant(dst_type);
__ PushConstant(dst_name);
if (dst_type.IsMalformedOrMalbounded()) {
__ BadTypeError();
} else {
bool may_be_smi = false;
if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) {
const Class& type_class = Class::Handle(zone(), dst_type.type_class());
if (type_class.NumTypeArguments() == 0) {
const Class& smi_class = Class::Handle(zone(), Smi::Class());
may_be_smi = smi_class.IsSubtypeOf(
TypeArguments::Handle(zone()), type_class,
TypeArguments::Handle(zone()), NULL, NULL, Heap::kOld);
}
bool may_be_smi = false;
if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) {
const Class& type_class = Class::Handle(zone(), dst_type.type_class());
if (type_class.NumTypeArguments() == 0) {
const Class& smi_class = Class::Handle(zone(), Smi::Class());
may_be_smi =
smi_class.IsSubtypeOf(TypeArguments::Handle(zone()), type_class,
TypeArguments::Handle(zone()), Heap::kOld);
}
__ AssertAssignable(may_be_smi ? 1 : 0, __ AddConstant(test_cache));
}
__ AssertAssignable(may_be_smi ? 1 : 0, __ AddConstant(test_cache));
if (is_optimizing()) {
// Register allocator does not think that our first input (also used as

View file

@ -255,12 +255,8 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = EAX;
Error& bound_error = Error::Handle(zone());
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(type, &bound_error, NULL, Heap::kOld);
// Malformed type should have been handled at graph construction time.
ASSERT(smi_is_ok || bound_error.IsNull());
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ testl(kInstanceReg, Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -292,11 +288,10 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (type_arguments.Length() == 1) {
const AbstractType& tp_argument =
AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
ASSERT(!tp_argument.IsMalformed());
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -345,8 +340,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (smi_class.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL,
Heap::kOld)) {
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
} else {
@ -601,7 +595,7 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsFinalized());
ASSERT(!type.IsObjectType() && !type.IsDynamicType() && !type.IsVoidType());
__ pushl(EDX); // Store instantiator type arguments.
@ -681,9 +675,8 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
ASSERT(!dst_type.IsNull());
ASSERT(dst_type.IsFinalized());
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType()));
ASSERT(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType());
__ pushl(EDX); // Store instantiator type arguments.
__ pushl(ECX); // Store function type arguments.
// A null object is always assignable and is returned as result.
@ -693,23 +686,6 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ cmpl(EAX, raw_null);
__ j(EQUAL, &is_assignable);
// Generate throw new TypeError() if the type is malformed or malbounded.
if (dst_type.IsMalformedOrMalbounded()) {
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(EAX); // Push the source object.
__ PushObject(dst_name); // Push the name of the destination.
__ PushObject(dst_type); // Push the type of the destination.
GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3,
locs);
// We should never return here.
__ int3();
__ Bind(&is_assignable); // For a null object.
__ popl(ECX); // Remove pushed function type arguments.
__ popl(EDX); // Remove pushed instantiator type arguments.
return;
}
// Generate inline type check, linking to runtime call if not assignable.
SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
test_cache = GenerateInlineInstanceof(token_pos, dst_type, &is_assignable,

View file

@ -247,12 +247,8 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = RAX;
Error& bound_error = Error::Handle(zone());
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(type, &bound_error, NULL, Heap::kOld);
// Malformed type should have been handled at graph construction time.
ASSERT(smi_is_ok || bound_error.IsNull());
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ testq(kInstanceReg, Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -285,12 +281,11 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (type_arguments.Length() == 1) {
const AbstractType& tp_argument =
AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
ASSERT(!tp_argument.IsMalformed());
if (tp_argument.IsType()) {
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -344,8 +339,7 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (smi_class.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL,
Heap::kOld)) {
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
} else {
@ -602,7 +596,7 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsFinalized());
ASSERT(!type.IsObjectType() && !type.IsDynamicType() && !type.IsVoidType());
Label is_instance, is_not_instance;
@ -674,33 +668,12 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
ASSERT(!dst_type.IsNull());
ASSERT(dst_type.IsFinalized());
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType()));
ASSERT(!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
!dst_type.IsVoidType());
const Register kInstantiatorTypeArgumentsReg = RDX;
const Register kFunctionTypeArgumentsReg = RCX;
// A null object is always assignable and is returned as result.
// Generate throw new TypeError() if the type is malformed or malbounded.
if (dst_type.IsMalformedOrMalbounded()) {
Label is_assignable;
__ CompareObject(RAX, Object::null_object());
__ j(EQUAL, &is_assignable);
__ PushObject(Object::null_object()); // Make room for the result.
__ pushq(RAX); // Push the source object.
__ PushObject(dst_name); // Push the name of the destination.
__ PushObject(dst_type); // Push the type of the destination.
GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3,
locs);
// We should never return here.
__ int3();
__ Bind(&is_assignable); // For a null object.
return;
}
if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
dst_name, locs);

View file

@ -187,7 +187,7 @@ void HierarchyInfo::BuildRangesFor(ClassTable* table,
bool test_succeded = false;
if (use_subtype_test) {
cls_type = cls.RareType();
test_succeded = cls_type.IsSubtypeOf(dst_type, NULL, NULL, Heap::kNew);
test_succeded = cls_type.IsSubtypeOf(dst_type, Heap::kNew);
} else {
while (!cls.IsObjectClass()) {
if (cls.raw() == klass.raw()) {
@ -311,7 +311,7 @@ void HierarchyInfo::BuildRangesForJIT(ClassTable* table,
}
bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) {
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsFinalized());
if (!type.IsInstantiated() || !type.IsType() || type.IsFunctionType() ||
type.IsDartFunctionType()) {
@ -354,7 +354,7 @@ bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) {
bool HierarchyInfo::CanUseGenericSubtypeRangeCheckFor(
const AbstractType& type) {
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsFinalized());
if (!type.IsType() || type.IsFunctionType() || type.IsDartFunctionType()) {
return false;
@ -839,13 +839,11 @@ Instruction* AssertSubtypeInstr::Canonicalize(FlowGraph* flow_graph) {
const TypeArguments& function_type_args = TypeArguments::Handle(
Z, TypeArguments::RawCast(constant_function_type_args->value().raw()));
Error& error_bound = Error::Handle(Z);
AbstractType& sub_type = AbstractType::Handle(Z, sub_type_.raw());
AbstractType& super_type = AbstractType::Handle(Z, super_type_.raw());
if (AbstractType::InstantiateAndTestSubtype(
&sub_type, &super_type, &error_bound, instantiator_type_args,
function_type_args)) {
if (AbstractType::InstantiateAndTestSubtype(&sub_type, &super_type,
instantiator_type_args,
function_type_args)) {
return NULL;
}
}
@ -2760,13 +2758,12 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
}
if ((instantiator_type_args != nullptr) && (function_type_args != nullptr)) {
Error& bound_error = Error::Handle(Z);
AbstractType& new_dst_type = AbstractType::Handle(
Z, dst_type().InstantiateFrom(
*instantiator_type_args, *function_type_args, kAllFree,
&bound_error, nullptr, nullptr, Heap::kOld));
if (new_dst_type.IsMalformedOrMalbounded() || !bound_error.IsNull()) {
Z,
dst_type().InstantiateFrom(*instantiator_type_args, *function_type_args,
kAllFree, nullptr, Heap::kOld));
if (new_dst_type.IsNull()) {
// Failed instantiation in dead code.
return this;
}
if (new_dst_type.IsTypeRef()) {
@ -3062,8 +3059,7 @@ static bool MayBeBoxableNumber(intptr_t cid) {
static bool MaybeNumber(CompileType* type) {
ASSERT(Type::Handle(Type::Number())
.IsMoreSpecificThan(Type::Handle(Type::Number()), NULL, NULL,
Heap::kOld));
.IsMoreSpecificThan(Type::Handle(Type::Number()), Heap::kOld));
return type->ToAbstractType()->IsDynamicType() ||
type->ToAbstractType()->IsObjectType() ||
type->ToAbstractType()->IsTypeParameter() ||

View file

@ -543,11 +543,10 @@ void CompileType::Union(CompileType* other) {
}
const AbstractType* other_abstract_type = other->ToAbstractType();
if (abstract_type->IsMoreSpecificThan(*other_abstract_type, NULL, NULL,
Heap::kOld)) {
if (abstract_type->IsMoreSpecificThan(*other_abstract_type, Heap::kOld)) {
type_ = other_abstract_type;
return;
} else if (other_abstract_type->IsMoreSpecificThan(*abstract_type, NULL, NULL,
} else if (other_abstract_type->IsMoreSpecificThan(*abstract_type,
Heap::kOld)) {
return; // Nothing to do.
}
@ -558,7 +557,7 @@ void CompileType::Union(CompileType* other) {
Class& cls = Class::Handle(abstract_type->type_class());
for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
type_ = &AbstractType::ZoneHandle(cls.RareType());
if (other_abstract_type->IsSubtypeOf(*type_, NULL, NULL, Heap::kOld)) {
if (other_abstract_type->IsSubtypeOf(*type_, Heap::kOld)) {
// Found suitable supertype: keep type_ only.
cid_ = kDynamicCid;
return;
@ -596,8 +595,7 @@ CompileType* CompileType::ComputeRefinedType(CompileType* old_type,
const AbstractType* new_abstract_type = new_type->ToAbstractType();
CompileType* preferred_type;
if (old_abstract_type->IsMoreSpecificThan(*new_abstract_type, NULL, NULL,
Heap::kOld)) {
if (old_abstract_type->IsMoreSpecificThan(*new_abstract_type, Heap::kOld)) {
// Prefer old type, as it is clearly more specific.
preferred_type = old_type;
} else {
@ -692,8 +690,6 @@ intptr_t CompileType::ToNullableCid() {
if (type_ == NULL) {
// Type propagation is turned off or has not yet run.
return kDynamicCid;
} else if (type_->IsMalformed()) {
cid_ = kDynamicCid;
} else if (type_->IsVoidType()) {
cid_ = kDynamicCid;
} else if (type_->IsNullType()) {
@ -774,11 +770,6 @@ bool CompileType::CanComputeIsInstanceOf(const AbstractType& type,
bool is_nullable,
bool* is_instance) {
ASSERT(is_instance != NULL);
// We cannot give an answer if the given type is malformed or malbounded.
if (type.IsMalformedOrMalbounded()) {
return false;
}
if (type.IsDynamicType() || type.IsObjectType() || type.IsVoidType()) {
*is_instance = true;
return true;
@ -791,10 +782,6 @@ bool CompileType::CanComputeIsInstanceOf(const AbstractType& type,
// Consider the compile type of the value.
const AbstractType& compile_type = *ToAbstractType();
if (compile_type.IsMalformedOrMalbounded()) {
return false;
}
// The null instance is an instance of Null, of Object, and of dynamic.
// Functions that do not explicitly return a value, implicitly return null,
// except generative constructors, which return the object being constructed.
@ -811,7 +798,7 @@ bool CompileType::CanComputeIsInstanceOf(const AbstractType& type,
return false;
}
*is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld);
*is_instance = compile_type.IsMoreSpecificThan(type, Heap::kOld);
return *is_instance;
}
@ -820,7 +807,7 @@ bool CompileType::IsMoreSpecificThan(const AbstractType& other) {
return false;
}
return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld);
return ToAbstractType()->IsMoreSpecificThan(other, Heap::kOld);
}
CompileType* Value::Type() {

View file

@ -1224,7 +1224,7 @@ RawBool* CallSpecializer::InstanceOfAsBool(
ASSERT(results->is_empty());
ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only.
if (type.IsFunctionType() || type.IsDartFunctionType() ||
!type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
!type.IsInstantiated()) {
return Bool::null();
}
const Class& type_class = Class::Handle(Z, type.type_class());
@ -1263,8 +1263,7 @@ RawBool* CallSpecializer::InstanceOfAsBool(
? (type_class.IsNullClass() || type_class.IsObjectClass() ||
type_class.IsDynamicClass())
: cls.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL,
Heap::kOld);
Object::null_type_arguments(), Heap::kOld);
results->Add(cls.id());
results->Add(is_subtype);
if (prev.IsNull()) {
@ -1280,7 +1279,7 @@ RawBool* CallSpecializer::InstanceOfAsBool(
// Returns true if checking against this type is a direct class id comparison.
bool CallSpecializer::TypeCheckAsClassEquality(const AbstractType& type) {
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsFinalized());
// Requires CHA.
if (!type.IsInstantiated()) return false;
// Function types have different type checking rules.
@ -1583,7 +1582,7 @@ bool CallSpecializer::SpecializeTestCidsForNumericTypes(
const Class& type_class = Class::Handle(type.type_class());
const bool smi_is_subtype =
cls.IsSubtypeOf(Object::null_type_arguments(), type_class,
Object::null_type_arguments(), NULL, NULL, Heap::kOld);
Object::null_type_arguments(), Heap::kOld);
results->Add((*results)[results->length() - 2]);
results->Add((*results)[results->length() - 2]);
for (intptr_t i = results->length() - 3; i > 1; --i) {
@ -1593,7 +1592,7 @@ bool CallSpecializer::SpecializeTestCidsForNumericTypes(
(*results)[1] = smi_is_subtype;
}
ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded());
ASSERT(type.IsInstantiated());
ASSERT(results->length() >= 2);
if (type.IsSmiType()) {
ASSERT((*results)[0] == kSmiCid);

View file

@ -531,8 +531,6 @@ void ConstantEvaluator::EvaluateConstructorInvocationInternal() {
// TODO(27590): Can we move this code into [ReceiverType]?
type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type,
ClassFinalizer::kFinalize);
ASSERT(!type.IsMalformedOrMalbounded());
TypeArguments& canonicalized_type_arguments =
TypeArguments::ZoneHandle(Z, type.arguments());
canonicalized_type_arguments = canonicalized_type_arguments.Canonicalize();
@ -608,7 +606,7 @@ void ConstantEvaluator::EvaluateAsExpression() {
EvaluateExpression(helper_->ReaderOffset(), false);
const AbstractType& type = T.BuildType();
if (!type.IsInstantiated() || type.IsMalformed()) {
if (!type.IsInstantiated()) {
const String& type_str = String::Handle(type.UserVisibleName());
H.ReportError(
script_, position,
@ -619,9 +617,8 @@ void ConstantEvaluator::EvaluateAsExpression() {
const TypeArguments& instantiator_type_arguments = TypeArguments::Handle();
const TypeArguments& function_type_arguments = TypeArguments::Handle();
Error& error = Error::Handle();
if (!result_.IsInstanceOf(type, instantiator_type_arguments,
function_type_arguments, &error)) {
function_type_arguments)) {
const AbstractType& rtype =
AbstractType::Handle(result_.GetType(Heap::kNew));
const String& result_str = String::Handle(rtype.UserVisibleName());
@ -698,10 +695,6 @@ void ConstantEvaluator::EvaluateSymbolLiteral() {
void ConstantEvaluator::EvaluateTypeLiteral() {
const AbstractType& type = T.BuildType();
if (type.IsMalformed()) {
H.ReportError(script_, TokenPosition::kNoSource,
"Malformed type literal in constant expression.");
}
result_ = type.raw();
}

View file

@ -4086,8 +4086,6 @@ Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
// TODO(27590): Can we move this code into [ReceiverType]?
type ^= ClassFinalizer::FinalizeType(*active_class()->klass, type,
ClassFinalizer::kFinalize);
ASSERT(!type.IsMalformedOrMalbounded());
TypeArguments& canonicalized_type_arguments =
TypeArguments::ZoneHandle(Z, type.arguments());
canonicalized_type_arguments =
@ -4320,14 +4318,7 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) {
// special case this situation.
const Type& object_type = Type::Handle(Z, Type::ObjectType());
if (type.IsMalformed()) {
instructions += Drop();
instructions += ThrowTypeError();
return instructions;
}
if (type.IsInstantiated() &&
object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
if (type.IsInstantiated() && object_type.IsSubtypeOf(type, Heap::kOld)) {
// Evaluate the expression on the left but ignore it's result.
instructions += Drop();
@ -4380,10 +4371,7 @@ Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
Fragment instructions = BuildExpression(); // read operand.
const AbstractType& type = T.BuildType(); // read type.
if (type.IsMalformed()) {
instructions += Drop();
instructions += ThrowTypeError();
} else if (type.IsInstantiated() && type.IsTopType()) {
if (type.IsInstantiated() && type.IsTopType()) {
// We already evaluated the operand on the left and just leave it there as
// the result of the `obj as dynamic` expression.
} else {
@ -4414,10 +4402,6 @@ Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
if (position != NULL) *position = TokenPosition::kNoSource;
const AbstractType& type = T.BuildType(); // read type.
if (type.IsMalformed()) {
H.ReportError(script_, TokenPosition::kNoSource, "Malformed type literal");
}
Fragment instructions;
if (type.IsInstantiated()) {
instructions += Constant(type);
@ -5508,37 +5492,32 @@ Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
}
if (type_guard != NULL) {
if (type_guard->IsMalformed()) {
catch_body += ThrowTypeError();
catch_body += Drop();
catch_body += LoadLocal(CurrentException());
catch_body += PushArgument(); // exception
if (!type_guard->IsInstantiated(kCurrentClass)) {
catch_body += LoadInstantiatorTypeArguments();
} else {
catch_body += LoadLocal(CurrentException());
catch_body += PushArgument(); // exception
if (!type_guard->IsInstantiated(kCurrentClass)) {
catch_body += LoadInstantiatorTypeArguments();
} else {
catch_body += NullConstant();
}
catch_body += PushArgument(); // instantiator type arguments
if (!type_guard->IsInstantiated(kFunctions)) {
catch_body += LoadFunctionTypeArguments();
} else {
catch_body += NullConstant();
}
catch_body += PushArgument(); // function type arguments
catch_body += Constant(*type_guard);
catch_body += PushArgument(); // guard type
catch_body += InstanceCall(
position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 4);
TargetEntryInstr* catch_entry;
TargetEntryInstr* next_catch_entry;
catch_body += BranchIfTrue(&catch_entry, &next_catch_entry, false);
Fragment(catch_entry) + catch_handler_body;
catch_body = Fragment(next_catch_entry);
catch_body += NullConstant();
}
catch_body += PushArgument(); // instantiator type arguments
if (!type_guard->IsInstantiated(kFunctions)) {
catch_body += LoadFunctionTypeArguments();
} else {
catch_body += NullConstant();
}
catch_body += PushArgument(); // function type arguments
catch_body += Constant(*type_guard);
catch_body += PushArgument(); // guard type
catch_body += InstanceCall(
position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 4);
TargetEntryInstr* catch_entry;
TargetEntryInstr* next_catch_entry;
catch_body += BranchIfTrue(&catch_entry, &next_catch_entry, false);
Fragment(catch_entry) + catch_handler_body;
catch_body = Fragment(next_catch_entry);
} else {
catch_body += catch_handler_body;
}

View file

@ -1063,9 +1063,6 @@ Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type,
const String& dst_name,
AssertAssignableInstr::Kind kind) {
Fragment instructions;
if (dst_type.IsMalformed()) {
return ThrowTypeError();
}
if (!I->should_emit_strong_mode_checks()) {
return Fragment();
}

View file

@ -2717,35 +2717,10 @@ AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
return AbstractType::ZoneHandle(Z, result_.raw());
}
AbstractType& TypeTranslator::BuildVariableType() {
AbstractType& abstract_type = BuildType();
// We return a new `ZoneHandle` here on purpose: The intermediate language
// instructions do not make a copy of the handle, so we do it.
AbstractType& type = Type::ZoneHandle(Z);
if (abstract_type.IsMalformed()) {
type = AbstractType::dynamic_type().raw();
} else {
type = result_.raw();
}
return type;
}
void TypeTranslator::BuildTypeInternal(bool invalid_as_dynamic) {
void TypeTranslator::BuildTypeInternal() {
Tag tag = helper_->ReadTag();
switch (tag) {
case kInvalidType:
if (invalid_as_dynamic) {
result_ = Object::dynamic_type().raw();
} else {
result_ = ClassFinalizer::NewFinalizedMalformedType(
Error::Handle(Z), // No previous error.
Script::Handle(Z, Script::null()), TokenPosition::kNoSource,
"[InvalidType] in Kernel IR.");
}
break;
case kDynamicType:
result_ = Object::dynamic_type().raw();
break;
@ -2857,9 +2832,6 @@ void TypeTranslator::BuildFunctionType(bool simple) {
++pos;
for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
BuildTypeInternal(); // read ith positional parameter.
if (result_.IsMalformed()) {
result_ = AbstractType::dynamic_type().raw();
}
parameter_types.SetAt(pos, result_);
parameter_names.SetAt(pos, H.DartSymbolPlain("noname"));
}
@ -2876,9 +2848,6 @@ void TypeTranslator::BuildFunctionType(bool simple) {
// read string reference (i.e. named_parameters[i].name).
String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
BuildTypeInternal(); // read named_parameters[i].type.
if (result_.IsMalformed()) {
result_ = AbstractType::dynamic_type().raw();
}
parameter_types.SetAt(pos, result_);
parameter_names.SetAt(pos, name);
}
@ -2889,9 +2858,6 @@ void TypeTranslator::BuildFunctionType(bool simple) {
}
BuildTypeInternal(); // read return type.
if (result_.IsMalformed()) {
result_ = AbstractType::dynamic_type().raw();
}
signature_function.set_result_type(result_);
finalize_ = finalize;
@ -3007,7 +2973,7 @@ const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) {
if (!only_dynamic) {
type_arguments = TypeArguments::New(length);
for (intptr_t i = 0; i < length; ++i) {
BuildTypeInternal(true); // read ith type.
BuildTypeInternal(); // read ith type.
type_arguments.SetTypeAt(i, result_);
}
@ -3107,9 +3073,6 @@ void TypeTranslator::LoadAndSetupTypeParameters(
parameter.set_bound(Type::Handle(Z, I->object_store()->object_type()));
} else {
AbstractType& bound = BuildTypeWithoutFinalization(); // read ith bound.
if (bound.IsMalformedOrMalbounded()) {
bound = I->object_store()->object_type();
}
parameter.set_bound(bound);
}
@ -3208,8 +3171,7 @@ void TypeTranslator::SetupFunctionParameters(
helper_->SkipExpression(); // read (actual) initializer.
}
function.SetParameterTypeAt(
pos, type.IsMalformed() ? Type::dynamic_type() : type);
function.SetParameterTypeAt(pos, type);
function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
}
@ -3226,8 +3188,7 @@ void TypeTranslator::SetupFunctionParameters(
helper_->SkipExpression(); // read (actual) initializer.
}
function.SetParameterTypeAt(
pos, type.IsMalformed() ? Type::dynamic_type() : type);
function.SetParameterTypeAt(pos, type);
function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
}
@ -3237,8 +3198,7 @@ void TypeTranslator::SetupFunctionParameters(
if (!function.IsGenerativeConstructor()) {
const AbstractType& return_type =
BuildTypeWithoutFinalization(); // read return type.
function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type()
: return_type);
function.set_result_type(return_type);
function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType);
}
}

View file

@ -1212,19 +1212,11 @@ class TypeTranslator {
ActiveClass* active_class,
bool finalize = false);
// Can return a malformed type.
AbstractType& BuildType();
// Can return a malformed type.
AbstractType& BuildTypeWithoutFinalization();
// Is guaranteed to be not malformed.
AbstractType& BuildVariableType();
// Will return `TypeArguments::null()` in case any of the arguments are
// malformed.
const TypeArguments& BuildTypeArguments(intptr_t length);
// Will return `TypeArguments::null()` in case any of the arguments are
// malformed.
const TypeArguments& BuildInstantiatedTypeArguments(
const Class& receiver_class,
intptr_t length);
@ -1243,8 +1235,7 @@ class TypeTranslator {
FunctionNodeHelper* function_node_helper);
private:
// Can build a malformed type.
void BuildTypeInternal(bool invalid_as_dynamic = false);
void BuildTypeInternal();
void BuildInterfaceType(bool simple);
void BuildFunctionType(bool simple);
void BuildTypeParameterType();

View file

@ -1217,7 +1217,7 @@ void ScopeBuilder::VisitVariableDeclaration() {
AbstractType& ScopeBuilder::BuildAndVisitVariableType() {
const intptr_t offset = helper_.ReaderOffset();
AbstractType& type = T.BuildVariableType();
AbstractType& type = T.BuildType();
helper_.SetOffset(offset); // rewind
VisitDartType();
return type;

View file

@ -111,15 +111,13 @@ class CheckFunctionTypesVisitor : public ObjectVisitor {
// Verify that the result type of a function is canonical or a
// TypeParameter.
typeHandle_ ^= funcHandle_.result_type();
ASSERT(typeHandle_.IsMalformed() || typeHandle_.IsTypeParameter() ||
typeHandle_.IsCanonical());
ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
// Verify that the types in the function signature are all canonical or
// a TypeParameter.
const intptr_t num_parameters = funcHandle_.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
typeHandle_ = funcHandle_.ParameterTypeAt(i);
ASSERT(typeHandle_.IsMalformed() || typeHandle_.IsTypeParameter() ||
typeHandle_.IsCanonical());
ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
}
}
}
@ -139,11 +137,8 @@ static RawInstance* GetListInstance(Zone* zone, const Object& obj) {
ASSERT(!list_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(), list_class,
Object::null_type_arguments(),
&malformed_type_error, NULL, Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw List.
Object::null_type_arguments(), Heap::kNew)) {
return instance.raw();
}
}
@ -158,11 +153,8 @@ static RawInstance* GetMapInstance(Zone* zone, const Object& obj) {
ASSERT(!map_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(), map_class,
Object::null_type_arguments(),
&malformed_type_error, NULL, Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw Map.
Object::null_type_arguments(), Heap::kNew)) {
return instance.raw();
}
}
@ -1876,11 +1868,8 @@ DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
RETURN_TYPE_ERROR(Z, object, Instance);
}
CHECK_CALLBACK_STATE(T);
Error& malformed_type_error = Error::Handle(Z);
*value = instance.IsInstanceOf(type_obj, Object::null_type_arguments(),
Object::null_type_arguments(),
&malformed_type_error);
ASSERT(malformed_type_error.IsNull()); // Type was created from a class.
Object::null_type_arguments());
return Api::Success();
}
@ -1994,11 +1983,9 @@ DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
Class::Handle(I->object_store()->future_class());
ASSERT(!future_class.IsNull());
const Class& obj_class = Class::Handle(Z, obj.clazz());
Error& malformed_type_error = Error::Handle(Z);
bool is_future = obj_class.IsSubtypeOf(
Object::null_type_arguments(), future_class,
Object::null_type_arguments(), &malformed_type_error, NULL, Heap::kNew);
ASSERT(malformed_type_error.IsNull()); // Type is a raw Future.
bool is_future =
obj_class.IsSubtypeOf(Object::null_type_arguments(), future_class,
Object::null_type_arguments(), Heap::kNew);
return is_future;
}
return false;
@ -3817,23 +3804,16 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
ClassFinalizer::ResolveRedirectingFactory(cls, constructor);
Type& redirect_type = Type::Handle(constructor.RedirectionType());
constructor = constructor.RedirectionTarget();
if (constructor.IsNull()) {
ASSERT(redirect_type.IsMalformed());
return Api::NewHandle(T, redirect_type.error());
}
ASSERT(!constructor.IsNull());
if (!redirect_type.IsInstantiated()) {
// The type arguments of the redirection type are instantiated from the
// type arguments of the type argument.
// We do not support generic constructors.
ASSERT(redirect_type.IsInstantiated(kFunctions));
Error& bound_error = Error::Handle();
redirect_type ^= redirect_type.InstantiateFrom(
type_arguments, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kNew);
if (!bound_error.IsNull()) {
return Api::NewHandle(T, bound_error.raw());
}
type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kNew);
redirect_type ^= redirect_type.Canonicalize();
}

View file

@ -832,14 +832,11 @@ bool ActivationFrame::HandlesException(const Instance& exc_obj) {
ASSERT(!type.IsNull());
// Uninstantiated types are not added to ExceptionHandlers data.
ASSERT(type.IsInstantiated());
if (type.IsMalformed()) {
continue;
}
if (type.IsDynamicType()) {
return true;
}
if (exc_obj.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments(), NULL)) {
Object::null_type_arguments())) {
return true;
}
}

View file

@ -753,18 +753,14 @@ RawInstance* Exceptions::NewInstance(const char* class_name) {
void Exceptions::CreateAndThrowTypeError(TokenPosition location,
const AbstractType& src_type,
const AbstractType& dst_type,
const String& dst_name,
const String& bound_error_msg) {
const String& dst_name) {
ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Array& args = Array::Handle(zone, Array::New(4));
ExceptionType exception_type =
(bound_error_msg.IsNull() &&
(dst_name.raw() == Symbols::InTypeCast().raw()))
? kCast
: kType;
(dst_name.raw() == Symbols::InTypeCast().raw()) ? kCast : kType;
DartFrameIterator iterator(thread,
StackFrameIterator::kNoCrossThreadIteration);
@ -788,51 +784,38 @@ void Exceptions::CreateAndThrowTypeError(TokenPosition location,
const GrowableObjectArray& pieces =
GrowableObjectArray::Handle(zone, GrowableObjectArray::New(20));
// Print bound error first, if any.
if (!bound_error_msg.IsNull() && (bound_error_msg.Length() > 0)) {
pieces.Add(bound_error_msg);
pieces.Add(Symbols::NewLine());
}
// If dst_type is malformed or malbounded, only print the embedded error.
if (!dst_type.IsNull()) {
const LanguageError& error = LanguageError::Handle(zone, dst_type.error());
if (!error.IsNull()) {
// Print the embedded error only.
pieces.Add(String::Handle(zone, String::New(error.ToErrorCString())));
pieces.Add(Symbols::NewLine());
} else {
// Describe the type error.
if (!src_type.IsNull()) {
pieces.Add(Symbols::TypeQuote());
pieces.Add(String::Handle(zone, src_type.UserVisibleName()));
pieces.Add(Symbols::QuoteIsNotASubtypeOf());
}
// Describe the type error.
if (!src_type.IsNull()) {
pieces.Add(Symbols::TypeQuote());
pieces.Add(String::Handle(zone, dst_type.UserVisibleName()));
pieces.Add(String::Handle(zone, src_type.UserVisibleName()));
pieces.Add(Symbols::QuoteIsNotASubtypeOf());
}
pieces.Add(Symbols::TypeQuote());
pieces.Add(String::Handle(zone, dst_type.UserVisibleName()));
pieces.Add(Symbols::SingleQuote());
if (exception_type == kCast) {
pieces.Add(dst_name);
} else if (dst_name.Length() > 0) {
pieces.Add(Symbols::SpaceOfSpace());
pieces.Add(Symbols::SingleQuote());
if (exception_type == kCast) {
pieces.Add(dst_name);
} else if (dst_name.Length() > 0) {
pieces.Add(Symbols::SpaceOfSpace());
pieces.Add(Symbols::SingleQuote());
pieces.Add(dst_name);
pieces.Add(Symbols::SingleQuote());
}
// Print ambiguous URIs of src and dst types.
URIs uris(zone, 12);
if (!src_type.IsNull()) {
src_type.EnumerateURIs(&uris);
}
if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
dst_type.EnumerateURIs(&uris);
}
const String& formatted_uris =
String::Handle(zone, AbstractType::PrintURIs(&uris));
if (formatted_uris.Length() > 0) {
pieces.Add(Symbols::SpaceWhereNewLine());
pieces.Add(formatted_uris);
}
pieces.Add(dst_name);
pieces.Add(Symbols::SingleQuote());
}
// Print ambiguous URIs of src and dst types.
URIs uris(zone, 12);
if (!src_type.IsNull()) {
src_type.EnumerateURIs(&uris);
}
if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
dst_type.EnumerateURIs(&uris);
}
const String& formatted_uris =
String::Handle(zone, AbstractType::PrintURIs(&uris));
if (formatted_uris.Length() > 0) {
pieces.Add(Symbols::SpaceWhereNewLine());
pieces.Add(formatted_uris);
}
}
const Array& arr = Array::Handle(zone, Array::MakeFixedLength(pieces));

View file

@ -46,8 +46,7 @@ class Exceptions : AllStatic {
static void CreateAndThrowTypeError(TokenPosition location,
const AbstractType& src_type,
const AbstractType& dst_type,
const String& dst_name,
const String& bound_error_msg);
const String& dst_name);
enum ExceptionType {
kNone,

View file

@ -1119,7 +1119,6 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
if (type_tag == kSomething) {
AbstractType& super_type =
T.BuildTypeWithoutFinalization(); // read super class type (part 2).
if (super_type.IsMalformed()) H.ReportError("Malformed super type");
klass->set_super_type(super_type);
}
@ -1133,7 +1132,6 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
for (intptr_t i = 0; i < interface_count; i++) {
const AbstractType& type =
T.BuildTypeWithoutFinalization(); // read ith type.
if (type.IsMalformed()) H.ReportError("Malformed interface type.");
interfaces.SetAt(i, type);
}
class_helper->SetJustRead(ClassHelper::kImplementedClasses);

File diff suppressed because it is too large Load diff

View file

@ -941,8 +941,6 @@ class Class : public Object {
}
// The super type of this class, Object type if not explicitly specified.
// Note that the super type may be bounded, as in this example:
// class C<T> extends S<T> { }; class S<T extends num> { };
RawAbstractType* super_type() const { return raw_ptr()->super_type_; }
void set_super_type(const AbstractType& value) const;
static intptr_t super_type_offset() {
@ -1024,22 +1022,18 @@ class Class : public Object {
bool IsSubtypeOf(const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsSubtypeOf, type_arguments, other, other_type_arguments,
bound_error, bound_trail, space);
space);
}
// Check the 'more specific' relationship.
bool IsMoreSpecificThan(const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, type_arguments, other,
other_type_arguments, bound_error, bound_trail, space);
other_type_arguments, space);
}
// Check if this is the top level class.
@ -1477,8 +1471,6 @@ class Class : public Object {
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
// Returns true if the type specified by this class and type_arguments is a
@ -1488,8 +1480,6 @@ class Class : public Object {
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
static bool TypeTestNonRecursive(const Class& cls,
@ -1497,8 +1487,6 @@ class Class : public Object {
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space);
FINAL_HEAP_OBJECT_IMPLEMENTATION(Class, Object);
@ -2659,27 +2647,20 @@ class Function : public Object {
// Returns true if the type of this function is a subtype of the type of
// the other function.
bool IsSubtypeOf(const Function& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, bound_error, bound_trail, space);
return TypeTest(kIsSubtypeOf, other, space);
}
// Returns true if the type of this function is more specific than the type of
// the other function.
bool IsMoreSpecificThan(const Function& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other, bound_error, bound_trail,
space);
return TypeTest(kIsMoreSpecificThan, other, space);
}
// Check the subtype or 'more specific' relationship.
bool TypeTest(TypeTestKind test_kind,
const Function& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
bool IsDispatcherOrImplicitAccessor() const {
@ -3073,8 +3054,6 @@ class Function : public Object {
intptr_t parameter_position,
intptr_t other_parameter_position,
const Function& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
@ -5868,15 +5847,12 @@ class Instance : public Object {
// The type argument vectors are used to instantiate the other type if needed.
bool IsInstanceOf(const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments,
Error* bound_error) const;
const TypeArguments& other_function_type_arguments) const;
// Returns true if the type of this instance is a subtype of FutureOr<T>
// specified by instantiated type 'other'.
// Returns false if other type is not a FutureOr.
bool IsFutureOrInstanceOf(Zone* zone,
const AbstractType& other,
Error* bound_error) const;
bool IsFutureOrInstanceOf(Zone* zone, const AbstractType& other) const;
bool IsValidNativeIndex(int index) const {
return ((index >= 0) && (index < clazz()->ptr()->num_native_fields_));
@ -6102,11 +6078,8 @@ class TypeArguments : public Instance {
bool IsSubtypeOf(const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, from_index, len, bound_error,
bound_trail, space);
return TypeTest(kIsSubtypeOf, other, from_index, len, space);
}
// Check the 'more specific' relationship, considering only a subvector of
@ -6114,11 +6087,8 @@ class TypeArguments : public Instance {
bool IsMoreSpecificThan(const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other, from_index, len, bound_error,
bound_trail, space);
return TypeTest(kIsMoreSpecificThan, other, from_index, len, space);
}
// Check if the vectors are equal (they may be null).
@ -6154,7 +6124,6 @@ class TypeArguments : public Instance {
// finalized, or bounded.
bool IsResolved() const;
bool IsFinalized() const;
bool IsBounded() const;
// Return true if this vector contains a recursive type argument.
bool IsRecursive() const;
@ -6184,22 +6153,18 @@ class TypeArguments : public Instance {
// where each reference to a type parameter is replaced with the corresponding
// type from the various type argument vectors (class instantiator, function,
// or parent functions via the current context).
// If bound_error is not NULL, it may be set to reflect a bound error.
RawTypeArguments* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
// Runtime instantiation with canonicalization. Not to be used during type
// finalization at compile time.
RawTypeArguments* InstantiateAndCanonicalizeFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
Error* bound_error) const;
const TypeArguments& function_type_arguments) const;
// Return true if this type argument vector has cached instantiations.
bool HasInstantiations() const;
@ -6256,8 +6221,6 @@ class TypeArguments : public Instance {
const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
// Return the internal or public name of a subvector of this type argument
@ -6293,11 +6256,6 @@ class AbstractType : public Instance {
virtual void SetIsFinalized() const;
virtual bool IsBeingFinalized() const;
virtual void SetIsBeingFinalized() const;
virtual bool IsMalformed() const;
virtual bool IsMalbounded() const;
virtual bool IsMalformedOrMalbounded() const;
virtual RawLanguageError* error() const;
virtual void set_error(const LanguageError& value) const;
virtual bool IsResolved() const;
virtual void SetIsResolved() const;
virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
@ -6336,14 +6294,11 @@ class AbstractType : public Instance {
// must remain uninstantiated, because only T is a free variable in this type.
//
// Return a new type, or return 'this' if it is already instantiated.
// If bound_error is not NULL, it may be set to reflect a bound error.
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
// Return a clone of this unfinalized type or the type itself if it is
@ -6422,9 +6377,7 @@ class AbstractType : public Instance {
// Check if this type is a still uninitialized TypeRef.
bool IsNullTypeRef() const;
// Check if this type represents the 'dynamic' type or if it is malformed,
// since a malformed type is mapped to 'dynamic'.
// Call IsMalformed() first, if distinction is required.
// Check if this type represents the 'dynamic' type.
bool IsDynamicType() const;
// Check if this type represents the 'void' type.
@ -6474,20 +6427,13 @@ class AbstractType : public Instance {
bool IsDartClosureType() const;
// Check the subtype relationship.
bool IsSubtypeOf(const AbstractType& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, bound_error, bound_trail, space);
bool IsSubtypeOf(const AbstractType& other, Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, space);
}
// Check the 'more specific' relationship.
bool IsMoreSpecificThan(const AbstractType& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other, bound_error, bound_trail,
space);
bool IsMoreSpecificThan(const AbstractType& other, Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other, space);
}
// Returns true iff subtype is a subtype of supertype, false otherwise or if
@ -6495,7 +6441,6 @@ class AbstractType : public Instance {
static bool InstantiateAndTestSubtype(
AbstractType* subtype,
AbstractType* supertype,
Error* bound_error,
const TypeArguments& instantiator_type_args,
const TypeArguments& function_type_args);
@ -6513,16 +6458,12 @@ class AbstractType : public Instance {
// Check the 'is subtype of' or 'is more specific than' relationship.
bool TypeTest(TypeTestKind test_kind,
const AbstractType& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
// Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
// Returns false if other type is not a FutureOr.
bool FutureOrTypeTest(Zone* zone,
const AbstractType& other,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
// Return the internal or public name of this type, including the names of its
@ -6562,11 +6503,6 @@ class Type : public AbstractType {
return raw_ptr()->type_state_ == RawType::kBeingFinalized;
}
virtual void SetIsBeingFinalized() const;
virtual bool IsMalformed() const;
virtual bool IsMalbounded() const;
virtual bool IsMalformedOrMalbounded() const;
virtual RawLanguageError* error() const;
virtual void set_error(const LanguageError& value) const;
virtual bool IsResolved() const {
return raw_ptr()->type_state_ >= RawType::kResolved;
}
@ -6593,7 +6529,7 @@ class Type : public AbstractType {
// was parameterized to obtain the actual signature.
RawFunction* signature() const;
void set_signature(const Function& value) const;
static intptr_t signature_offset() { return OFFSET_OF(RawType, sig_or_err_); }
static intptr_t signature_offset() { return OFFSET_OF(RawType, signature_); }
virtual bool IsFunctionType() const {
return signature() != Function::null();
@ -6602,9 +6538,7 @@ class Type : public AbstractType {
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner,
@ -6712,18 +6646,6 @@ class TypeRef : public AbstractType {
const AbstractType& ref_type = AbstractType::Handle(type());
return ref_type.IsNull() || ref_type.IsBeingFinalized();
}
virtual bool IsMalformed() const {
return AbstractType::Handle(type()).IsMalformed();
}
virtual bool IsMalbounded() const {
return AbstractType::Handle(type()).IsMalbounded();
}
virtual bool IsMalformedOrMalbounded() const {
return AbstractType::Handle(type()).IsMalformedOrMalbounded();
}
virtual RawLanguageError* error() const {
return AbstractType::Handle(type()).error();
}
virtual bool IsResolved() const { return true; }
virtual bool HasTypeClass() const {
return (type() != AbstractType::null()) &&
@ -6753,9 +6675,7 @@ class TypeRef : public AbstractType {
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
virtual RawTypeRef* CloneUninstantiated(const Class& new_owner,
TrailPtr trail = NULL) const;
@ -6799,9 +6719,6 @@ class TypeParameter : public AbstractType {
}
virtual void SetIsFinalized() const;
virtual bool IsBeingFinalized() const { return false; }
virtual bool IsMalformed() const { return false; }
virtual bool IsMalbounded() const { return false; }
virtual bool IsMalformedOrMalbounded() const { return false; }
virtual bool IsResolved() const { return true; }
virtual bool HasTypeClass() const { return false; }
virtual classid_t type_class_id() const { return kIllegalCid; }
@ -6821,15 +6738,6 @@ class TypeParameter : public AbstractType {
void set_index(intptr_t value) const;
RawAbstractType* bound() const { return raw_ptr()->bound_; }
void set_bound(const AbstractType& value) const;
// Returns true if bounded_type is below upper_bound, otherwise return false
// and set bound_error if both bounded_type and upper_bound are instantiated.
// If one or both are not instantiated, returning false only means that the
// bound cannot be checked yet and this is not an error.
bool CheckBound(const AbstractType& bounded_type,
const AbstractType& upper_bound,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const;
virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
virtual bool IsInstantiated(Genericity genericity = kAny,
intptr_t num_free_fun_type_params = kAllFree,
@ -6841,9 +6749,7 @@ class TypeParameter : public AbstractType {
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner,
@ -6888,103 +6794,6 @@ class TypeParameter : public AbstractType {
friend class ClearTypeHashVisitor;
};
// A BoundedType represents a type instantiated at compile time from a type
// parameter specifying a bound that either cannot be checked at compile time
// because the type or the bound are still uninstantiated or can be checked and
// would trigger a bound error in checked mode. The bound must be checked at
// runtime once the type and its bound are instantiated and when the execution
// mode is known to be checked mode.
class BoundedType : public AbstractType {
public:
virtual bool IsFinalized() const {
return AbstractType::Handle(type()).IsFinalized();
}
virtual bool IsBeingFinalized() const {
return AbstractType::Handle(type()).IsBeingFinalized();
}
virtual bool IsMalformed() const;
virtual bool IsMalbounded() const;
virtual bool IsMalformedOrMalbounded() const;
virtual RawLanguageError* error() const;
virtual bool IsResolved() const { return true; }
virtual bool HasTypeClass() const {
return AbstractType::Handle(type()).HasTypeClass();
}
virtual classid_t type_class_id() const {
return AbstractType::Handle(type()).type_class_id();
}
virtual RawClass* type_class() const {
return AbstractType::Handle(type()).type_class();
}
virtual RawTypeArguments* arguments() const {
return AbstractType::Handle(type()).arguments();
}
RawAbstractType* type() const { return raw_ptr()->type_; }
RawAbstractType* bound() const { return raw_ptr()->bound_; }
RawTypeParameter* type_parameter() const {
return raw_ptr()->type_parameter_;
}
virtual TokenPosition token_pos() const {
return AbstractType::Handle(type()).token_pos();
}
virtual bool IsInstantiated(Genericity genericity = kAny,
intptr_t num_free_fun_type_params = kAllFree,
TrailPtr trail = NULL) const {
// It is not possible to encounter an instantiated bounded type with an
// uninstantiated upper bound. Therefore, we do not need to check if the
// bound is instantiated. Moreover, doing so could lead into cycles, as in
// class C<T extends C<C>> { }.
return AbstractType::Handle(type()).IsInstantiated(
genericity, num_free_fun_type_params, trail);
}
virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
virtual bool IsRecursive() const;
virtual void SetScopeFunction(const Function& function) const;
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
Error* bound_error,
TrailPtr instantiation_trail,
TrailPtr bound_trail,
Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner,
TrailPtr trail = NULL) const;
virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const {
return raw();
}
#if defined(DEBUG)
// Check if bounded type is canonical.
virtual bool CheckIsCanonical(Thread* thread) const { return true; }
#endif // DEBUG
virtual void EnumerateURIs(URIs* uris) const;
virtual intptr_t Hash() const;
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawBoundedType));
}
static RawBoundedType* New(const AbstractType& type,
const AbstractType& bound,
const TypeParameter& type_parameter);
private:
intptr_t ComputeHash() const;
void SetHash(intptr_t value) const;
void set_type(const AbstractType& value) const;
void set_bound(const AbstractType& value) const;
void set_type_parameter(const TypeParameter& value) const;
static RawBoundedType* New();
FINAL_HEAP_OBJECT_IMPLEMENTATION(BoundedType, AbstractType);
friend class Class;
friend class ClearTypeHashVisitor;
};
// A MixinAppType represents a parsed mixin application clause, e.g.
// "S<T> with M<U>, N<V>".
// MixinAppType objects do not survive finalization, so they do not
@ -6994,12 +6803,8 @@ class BoundedType : public AbstractType {
class MixinAppType : public AbstractType {
public:
// A MixinAppType object is unfinalized by definition, since it is replaced at
// class finalization time with a finalized (and possibly malformed or
// malbounded) Type object.
// class finalization time with a finalized Type object.
virtual bool IsFinalized() const { return false; }
virtual bool IsMalformed() const { return false; }
virtual bool IsMalbounded() const { return false; }
virtual bool IsMalformedOrMalbounded() const { return false; }
virtual bool IsResolved() const { return false; }
virtual bool HasTypeClass() const { return false; }
virtual RawString* Name() const;
@ -9603,20 +9408,6 @@ inline void TypeParameter::SetHash(intptr_t value) const {
StoreSmi(&raw_ptr()->hash_, Smi::New(value));
}
inline intptr_t BoundedType::Hash() const {
intptr_t result = Smi::Value(raw_ptr()->hash_);
if (result != 0) {
return result;
}
return ComputeHash();
}
inline void BoundedType::SetHash(intptr_t value) const {
// This is only safe because we create a new Smi, which does not cause
// heap allocation.
StoreSmi(&raw_ptr()->hash_, Smi::New(value));
}
inline intptr_t TypeArguments::Hash() const {
if (IsNull()) return 0;
intptr_t result = Smi::Value(raw_ptr()->hash_);

View file

@ -1154,21 +1154,6 @@ void TypeParameter::PrintJSONImpl(JSONStream* stream, bool ref) const {
jsobj.AddProperty("bound", upper_bound);
}
void BoundedType::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "BoundedType");
jsobj.AddServiceId(*this);
const String& user_name = String::Handle(UserVisibleName());
const String& vm_name = String::Handle(Name());
AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
if (ref) {
return;
}
jsobj.AddProperty("targetType", AbstractType::Handle(type()));
jsobj.AddProperty("bound", AbstractType::Handle(bound()));
}
void MixinAppType::PrintJSONImpl(JSONStream* stream, bool ref) const {
UNREACHABLE();
}

View file

@ -386,7 +386,6 @@ REGULAR_VISITOR(Bytecode)
REGULAR_VISITOR(Type)
REGULAR_VISITOR(TypeRef)
REGULAR_VISITOR(TypeParameter)
REGULAR_VISITOR(BoundedType)
REGULAR_VISITOR(MixinAppType)
REGULAR_VISITOR(PatchClass)
COMPRESSED_VISITOR(Closure)

View file

@ -60,7 +60,6 @@ typedef RawObject* RawCompressed;
V(Type) \
V(TypeRef) \
V(TypeParameter) \
V(BoundedType) \
V(MixinAppType) \
V(Closure) \
V(Number) \
@ -2036,15 +2035,8 @@ class RawType : public RawAbstractType {
RawSmi* hash_;
// This type object represents a function type if its signature field is a
// non-null function object.
// If this type is malformed or malbounded, the signature field gets
// overwritten by the error object in order to save space. If the type is a
// function type, its signature is lost, but the message in the error object
// can describe the issue without needing the signature.
union {
RawFunction* signature_; // If not null, this type is a function type.
RawLanguageError* error_; // If not null, type is malformed or malbounded.
} sig_or_err_;
VISIT_TO(RawObject*, sig_or_err_.error_)
RawFunction* signature_; // If not null, this type is a function type.
VISIT_TO(RawObject*, signature_)
TokenPosition token_pos_;
int8_t type_state_;
@ -2084,19 +2076,6 @@ class RawTypeParameter : public RawAbstractType {
friend class CidRewriteVisitor;
};
class RawBoundedType : public RawAbstractType {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(BoundedType);
VISIT_FROM(RawObject*, type_);
RawAbstractType* type_;
RawAbstractType* bound_;
RawSmi* hash_;
RawTypeParameter* type_parameter_; // For more detailed error reporting.
VISIT_TO(RawObject*, type_parameter_);
RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
};
class RawMixinAppType : public RawAbstractType {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(MixinAppType);

View file

@ -146,10 +146,6 @@ namespace dart {
F(TypeParameter, hash_) \
F(TypeParameter, bound_) \
F(TypeParameter, parameterized_function_) \
F(BoundedType, type_) \
F(BoundedType, bound_) \
F(BoundedType, hash_) \
F(BoundedType, type_parameter_) \
F(MixinAppType, super_type_) \
F(MixinAppType, mixin_types_) \
F(Closure, instantiator_type_arguments_) \

View file

@ -297,46 +297,6 @@ void RawTypeParameter::WriteTo(SnapshotWriter* writer,
writer->WriteObjectImpl(param_class, kAsReference);
}
RawBoundedType* BoundedType::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference) {
ASSERT(reader != NULL);
// Allocate bounded type object.
BoundedType& bounded_type =
BoundedType::ZoneHandle(reader->zone(), BoundedType::New());
reader->AddBackRef(object_id, &bounded_type, kIsDeserialized);
// Read the code object for the type testing stub and set its entrypoint.
reader->EnqueueTypePostprocessing(bounded_type);
// Set all the object fields.
READ_OBJECT_FIELDS(bounded_type, bounded_type.raw()->from(),
bounded_type.raw()->to(), kAsReference);
return bounded_type.raw();
}
void RawBoundedType::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind,
bool as_reference) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kBoundedTypeCid);
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer, kAsReference);
visitor.VisitPointers(from(), to());
}
RawMixinAppType* MixinAppType::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,

View file

@ -30,12 +30,6 @@ RawString* Report::PrependSnippet(Kind kind,
case kError:
message_header = "error";
break;
case kMalformedType:
message_header = "malformed type";
break;
case kMalboundedType:
message_header = "malbounded type";
break;
case kBailout:
message_header = "bailout";
break;

View file

@ -23,8 +23,6 @@ class Report : AllStatic {
enum Kind {
kWarning,
kError,
kMalformedType,
kMalboundedType,
kBailout,
};

View file

@ -323,20 +323,9 @@ DEFINE_RUNTIME_ENTRY(InstantiateType, 3) {
instantiator_type_arguments.IsInstantiated());
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsInstantiated());
Error& bound_error = Error::Handle(zone);
type =
type.InstantiateFrom(instantiator_type_arguments, function_type_arguments,
kAllFree, &bound_error, NULL, NULL, Heap::kOld);
if (!bound_error.IsNull()) {
// Throw a dynamic type error.
const TokenPosition location = GetCallerLocation();
String& bound_error_message =
String::Handle(zone, String::New(bound_error.ToErrorCString()));
Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
AbstractType::Handle(zone),
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
kAllFree, NULL, Heap::kOld);
if (type.IsTypeRef()) {
type = TypeRef::Cast(type).type();
ASSERT(!type.IsTypeRef());
@ -367,7 +356,7 @@ DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) {
// instantiator can be reused as type argument vector.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
instantiator_type_arguments, function_type_arguments, NULL);
instantiator_type_arguments, function_type_arguments);
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
}
@ -389,25 +378,18 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
AbstractType::CheckedHandle(zone, arguments.ArgAt(3));
const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4));
ASSERT(!subtype.IsNull() && !subtype.IsMalformedOrMalbounded());
ASSERT(!supertype.IsNull() && !supertype.IsMalformedOrMalbounded());
ASSERT(!subtype.IsNull());
ASSERT(!supertype.IsNull());
// The supertype or subtype may not be instantiated.
Error& bound_error = Error::Handle(zone);
if (AbstractType::InstantiateAndTestSubtype(
&subtype, &supertype, &bound_error, instantiator_type_args,
function_type_args)) {
&subtype, &supertype, instantiator_type_args, function_type_args)) {
return;
}
// Throw a dynamic type error.
const TokenPosition location = GetCallerLocation();
String& bound_error_message = String::Handle(zone);
if (!bound_error.IsNull()) {
bound_error_message = String::New(bound_error.ToErrorCString());
}
Exceptions::CreateAndThrowTypeError(location, subtype, supertype, dst_name,
bound_error_message);
Exceptions::CreateAndThrowTypeError(location, subtype, supertype, dst_name);
UNREACHABLE();
}
@ -549,19 +531,15 @@ static void PrintTypeCheck(const char* message,
Class::Handle(type.type_class()).id(), caller_frame->pc());
} else {
// Instantiate type before printing.
Error& bound_error = Error::Handle();
const AbstractType& instantiated_type =
AbstractType::Handle(type.InstantiateFrom(
instantiator_type_arguments, function_type_arguments, kAllFree,
&bound_error, NULL, NULL, Heap::kOld));
AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
kAllFree, NULL, Heap::kOld));
OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
message, String::Handle(instance_type.Name()).ToCString(),
(result.raw() == Bool::True().raw()) ? "is" : "is !",
String::Handle(instantiated_type.Name()).ToCString(),
String::Handle(type.Name()).ToCString(), caller_frame->pc());
if (!bound_error.IsNull()) {
OS::PrintErr(" bound error: %s\n", bound_error.ToErrorCString());
}
}
const Function& function =
Function::Handle(caller_frame->LookupDartFunction());
@ -675,11 +653,9 @@ static void UpdateTypeTestCache(
if (FLAG_trace_type_checks) {
AbstractType& test_type = AbstractType::Handle(zone, type.raw());
if (!test_type.IsInstantiated()) {
Error& bound_error = Error::Handle(zone);
test_type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, kAllFree,
&bound_error, NULL, NULL, Heap::kNew);
ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
function_type_arguments, kAllFree, NULL,
Heap::kNew);
}
const auto& type_class = Class::Handle(zone, test_type.type_class());
const auto& instance_class_name =
@ -727,28 +703,13 @@ DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
const SubtypeTestCache& cache =
SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed()); // Already checked in code generator.
ASSERT(!type.IsMalbounded()); // Already checked in code generator.
ASSERT(!type.IsDynamicType()); // No need to check assignment.
Error& bound_error = Error::Handle(zone);
const Bool& result =
Bool::Get(instance.IsInstanceOf(type, instantiator_type_arguments,
function_type_arguments, &bound_error));
const Bool& result = Bool::Get(instance.IsInstanceOf(
type, instantiator_type_arguments, function_type_arguments));
if (FLAG_trace_type_checks) {
PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments,
function_type_arguments, result);
}
if (!result.value() && !bound_error.IsNull()) {
// Throw a dynamic type error only if the instanceof test fails.
const TokenPosition location = GetCallerLocation();
String& bound_error_message =
String::Handle(zone, String::New(bound_error.ToErrorCString()));
Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
AbstractType::Handle(zone),
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
UpdateTypeTestCache(zone, instance, type, instantiator_type_arguments,
function_type_arguments, result, cache);
arguments.SetReturn(result);
@ -788,15 +749,11 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
ASSERT(mode == kTypeCheckFromInline);
#endif
ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator.
ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
Error& bound_error = Error::Handle(zone);
const bool is_instance_of =
src_instance.IsInstanceOf(dst_type, instantiator_type_arguments,
function_type_arguments, &bound_error);
const bool is_instance_of = src_instance.IsInstanceOf(
dst_type, instantiator_type_arguments, function_type_arguments);
if (FLAG_trace_type_checks) {
PrintTypeCheck("TypeCheck", src_instance, dst_type,
@ -812,13 +769,9 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
// Instantiate dst_type before reporting the error.
dst_type = dst_type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, kAllFree,
NULL, NULL, NULL, Heap::kNew);
NULL, Heap::kNew);
// Note that instantiated dst_type may be malbounded.
}
String& bound_error_message = String::Handle(zone);
if (!bound_error.IsNull()) {
UNREACHABLE();
}
if (dst_name.IsNull()) {
#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
// Can only come here from type testing stub.
@ -843,8 +796,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
#endif
}
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
bound_error_message);
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name);
UNREACHABLE();
}
@ -924,10 +876,8 @@ DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) {
const Type& bool_interface = Type::Handle(Type::BoolType());
const AbstractType& src_type =
AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
const String& no_bound_error = String::Handle(zone);
Exceptions::CreateAndThrowTypeError(location, src_type, bool_interface,
Symbols::BooleanExpression(),
no_bound_error);
Symbols::BooleanExpression());
UNREACHABLE();
}
@ -944,8 +894,7 @@ DEFINE_RUNTIME_ENTRY(BadTypeError, 3) {
AbstractType::CheckedHandle(zone, arguments.ArgAt(2));
const AbstractType& src_type =
AbstractType::Handle(zone, src_value.GetType(Heap::kNew));
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
String::Handle(zone));
Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name);
UNREACHABLE();
}
@ -1110,10 +1059,8 @@ RawFunction* InlineCacheMissHelper(const Instance& receiver,
static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
const AbstractType& type,
const ArgumentsDescriptor& desc) {
Error& error = Error::Handle();
bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments(), &error);
ASSERT(error.IsNull());
Object::null_type_arguments());
ObjectStore* store = Isolate::Current()->object_store();
const Function& target =
Function::Handle(result ? store->simple_instance_of_true_function()

View file

@ -39,7 +39,6 @@ class MegamorphicCache;
class PageSpace;
class RawApiError;
class RawArray;
class RawBoundedType;
class RawCapability;
class RawClass;
class RawClosure;
@ -447,7 +446,6 @@ class SnapshotReader : public BaseReader {
friend class ApiError;
friend class Array;
friend class BoundedType;
friend class Class;
friend class Closure;
friend class ClosureData;
@ -747,7 +745,6 @@ class SnapshotWriter : public BaseWriter {
friend class RawSubtypeTestCache;
friend class RawType;
friend class RawTypeRef;
friend class RawBoundedType;
friend class RawTypeArguments;
friend class RawTypeParameter;
friend class RawUserTag;

View file

@ -80,7 +80,6 @@ class ObjectPointerVisitor;
V(_CompileTimeError, "_CompileTimeError") \
V(ThrowNew, "_throwNew") \
V(ThrowNewInvocation, "_throwNewInvocation") \
V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded") \
V(EvaluateAssertion, "_evaluateAssertion") \
V(Symbol, "Symbol") \
V(SymbolCtor, "Symbol.") \
@ -168,7 +167,6 @@ class ObjectPointerVisitor;
V(_Type, "_Type") \
V(_TypeRef, "_TypeRef") \
V(_TypeParameter, "_TypeParameter") \
V(_BoundedType, "_BoundedType") \
V(_MixinAppType, "_MixinAppType") \
V(TypeArguments, "TypeArguments") \
V(Patch, "patch") \

View file

@ -117,7 +117,7 @@ RawInstructions* TypeTestingStubGenerator::DefaultCodeForType(
return should_specialize ? StubCode::LazySpecializeTypeTest().instructions()
: StubCode::DefaultTypeTest().instructions();
} else {
ASSERT(type.IsBoundedType() || type.IsMixinAppType());
ASSERT(type.IsMixinAppType());
return StubCode::UnreachableTypeTest().instructions();
}
}
@ -400,7 +400,7 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStubFastCases(
const CidRangeVector& ranges = hi->SubtypeRangesForClass(type_class);
const Type& int_type = Type::Handle(Type::IntType());
const bool smi_is_ok = int_type.IsSubtypeOf(type, NULL, NULL, Heap::kNew);
const bool smi_is_ok = int_type.IsSubtypeOf(type, Heap::kNew);
BuildOptimizedSubtypeRangeCheck(assembler, ranges, class_id_reg,
instance_reg, smi_is_ok);

View file

@ -266,9 +266,6 @@ class TypeArgumentClassFinder {
}
}
return true;
} else if (type.IsBoundedType()) {
// No support for bounded types.
return false;
}
UNREACHABLE();
return false;