Index: runtime/vm/class_finalizer.cc |
=================================================================== |
--- runtime/vm/class_finalizer.cc (revision 30176) |
+++ runtime/vm/class_finalizer.cc (working copy) |
@@ -289,6 +289,10 @@ |
if (type.IsMalformed()) { |
ReportError(Error::Handle(type.malformed_error())); |
} |
+ Error& error = Error::Handle(); |
+ if (type.IsMalboundedWithError(&error)) { |
+ ReportError(error); |
+ } |
} |
} |
} |
@@ -316,8 +320,8 @@ |
// Check if target is already resolved. |
Type& type = Type::Handle(factory.RedirectionType()); |
Function& target = Function::Handle(factory.RedirectionTarget()); |
- if (type.IsMalformed()) { |
- // Already resolved to a malformed type. Will throw on usage. |
+ if (type.IsMalformed() || (type.IsResolved() && type.IsMalbounded())) { |
+ // Already resolved to a malformed or malbounded type. Will throw on usage. |
ASSERT(target.IsNull()); |
return; |
} |
@@ -334,7 +338,7 @@ |
ResolveType(cls, type, kCanonicalize); |
type ^= FinalizeType(cls, type, kCanonicalize); |
factory.SetRedirectionType(type); |
- if (type.IsMalformed()) { |
+ if (type.IsMalformed() || type.IsMalbounded()) { |
ASSERT(factory.RedirectionTarget() == Function::null()); |
return; |
} |
@@ -430,13 +434,14 @@ |
if (!target_type.IsInstantiated()) { |
const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( |
type.arguments()); |
- Error& malformed_error = Error::Handle(); |
- target_type ^= target_type.InstantiateFrom(type_args, &malformed_error); |
- if (malformed_error.IsNull()) { |
+ Error& bound_error = Error::Handle(); |
+ target_type ^= target_type.InstantiateFrom(type_args, &bound_error); |
+ if (bound_error.IsNull()) { |
target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
} else { |
+ ASSERT(target_type.IsInstantiated() && type_args.IsInstantiated()); |
const Script& script = Script::Handle(target_class.script()); |
- FinalizeMalformedType(malformed_error, script, target_type, |
+ FinalizeMalformedType(bound_error, script, target_type, |
"cannot resolve redirecting factory"); |
target_target = Function::null(); |
} |
@@ -596,14 +601,16 @@ |
if (!super_type_args.IsNull()) { |
super_type_arg = super_type_args.TypeAt(super_offset + i); |
if (!super_type_arg.IsInstantiated()) { |
- Error& malformed_error = Error::Handle(); |
- super_type_arg = super_type_arg.InstantiateFrom(arguments, |
- &malformed_error); |
- if (!malformed_error.IsNull()) { |
- if (!super_type_arg.IsInstantiated()) { |
- // CheckTypeArgumentBounds will insert a BoundedType. |
- } else if (bound_error->IsNull()) { |
- *bound_error = malformed_error.raw(); |
+ Error& error = Error::Handle(); |
+ super_type_arg = super_type_arg.InstantiateFrom(arguments, &error); |
+ 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(); |
} |
} |
} |
@@ -665,14 +672,13 @@ |
type_param.set_bound(declared_bound); |
} |
ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized()); |
- Error& malformed_error = Error::Handle(); |
+ Error& error = Error::Handle(); |
// Note that the bound may be malformed, in which case the bound check |
// will return an error and the bound check will be postponed to run time. |
if (declared_bound.IsInstantiated()) { |
instantiated_bound = declared_bound.raw(); |
} else { |
- instantiated_bound = |
- declared_bound.InstantiateFrom(arguments, &malformed_error); |
+ instantiated_bound = declared_bound.InstantiateFrom(arguments, &error); |
} |
if (!instantiated_bound.IsFinalized()) { |
// The bound refers to type parameters, creating a cycle; postpone |
@@ -684,35 +690,21 @@ |
arguments.SetTypeAt(offset + i, type_arg); |
continue; |
} |
- // TODO(regis): We could simplify this code if we could differentiate |
- // between a failed bound check and a bound check that is undecidable at |
- // compile time. |
// Shortcut the special case where we check a type parameter against its |
// declared upper bound. |
- bool below_bound = true; |
- if (malformed_error.IsNull() && |
- (!type_arg.Equals(type_param) || |
- !instantiated_bound.Equals(declared_bound))) { |
- // Pass NULL to prevent expensive and unnecessary error formatting in |
- // the case the bound check is postponed to run time. |
- below_bound = type_param.CheckBound(type_arg, instantiated_bound, NULL); |
- } |
- if (!malformed_error.IsNull() || !below_bound) { |
- if (!type_arg.IsInstantiated() || |
- !instantiated_bound.IsInstantiated()) { |
+ if (error.IsNull() && |
+ !(type_arg.Equals(type_param) && |
+ instantiated_bound.Equals(declared_bound))) { |
+ if (!type_param.CheckBound(type_arg, instantiated_bound, &error) && |
+ error.IsNull()) { |
+ // The bound cannot be checked at compile time; postpone to run time. |
type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); |
arguments.SetTypeAt(offset + i, type_arg); |
- } else if (bound_error->IsNull()) { |
- if (malformed_error.IsNull()) { |
- // Call CheckBound again to format error message. |
- type_param.CheckBound(type_arg, |
- instantiated_bound, |
- &malformed_error); |
- } |
- ASSERT(!malformed_error.IsNull()); |
- *bound_error = malformed_error.raw(); |
} |
} |
+ if (!error.IsNull() && bound_error->IsNull()) { |
+ *bound_error = error.raw(); |
+ } |
} |
} |
AbstractType& super_type = AbstractType::Handle(cls.super_type()); |