Index: runtime/lib/mirrors.cc |
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc |
index f99b1113658259fec22b122b3e10ebedccef4fdb..a64dbed58cb89daa738b43516aaf357b4470175b 100644 |
--- a/runtime/lib/mirrors.cc |
+++ b/runtime/lib/mirrors.cc |
@@ -819,6 +819,70 @@ DEFINE_NATIVE_ENTRY(Mirrors_makeLocalTypeMirror, 1) { |
} |
+DEFINE_NATIVE_ENTRY(Mirrors_instantiateGenericType, 2) { |
+ GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0)); |
+ GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1)); |
+ |
+ ASSERT(type.HasResolvedTypeClass()); |
+ const Class& clz = Class::Handle(type.type_class()); |
+ if (!clz.IsGeneric()) { |
+ const Array& error_args = Array::Handle(Array::New(3)); |
+ error_args.SetAt(0, type); |
+ error_args.SetAt(1, String::Handle(String::New("key"))); |
+ error_args.SetAt(2, String::Handle(String::New( |
+ "Type must be a generic class or function."))); |
+ Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args); |
+ UNREACHABLE(); |
+ } |
+ if (clz.NumTypeParameters() != args.Length()) { |
+ 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(String::New( |
+ "Number of type arguments does not match."))); |
+ Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args); |
+ UNREACHABLE(); |
+ } |
+ |
+ intptr_t num_expected_type_arguments = args.Length(); |
+ TypeArguments& type_args_obj = TypeArguments::Handle(); |
+ type_args_obj ^= TypeArguments::New(num_expected_type_arguments); |
+ AbstractType& type_arg = AbstractType::Handle(); |
+ Instance& instance = Instance::Handle(); |
+ for (intptr_t i = 0; i < args.Length(); i++) { |
+ instance ^= args.At(i); |
+ if (!instance.IsType()) { |
+ 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(String::New( |
+ "Type arguments must be instances of Type."))); |
+ Exceptions::ThrowByType(Exceptions::kArgumentValue, error_args); |
+ UNREACHABLE(); |
+ } |
+ type_arg ^= args.At(i); |
+ type_args_obj.SetTypeAt(i, type_arg); |
+ } |
+ |
+ Type& instantiated_type = |
+ Type::Handle(Type::New(clz, type_args_obj, TokenPosition::kNoSource)); |
+ instantiated_type ^= ClassFinalizer::FinalizeType( |
+ clz, instantiated_type, ClassFinalizer::kCanonicalize); |
+ 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(); |
+} |
+ |
+ |
DEFINE_NATIVE_ENTRY(Mirrors_mangleName, 2) { |
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0)); |
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1)); |