Fix rti encoding of generic methods

R=sigmund@google.com

Review-Url: https://codereview.chromium.org/2565413002 .
This commit is contained in:
Johnni Winther 2016-12-13 10:27:59 +01:00
parent 53dd819a4c
commit d4c9dc92e1
4 changed files with 74 additions and 17 deletions

View file

@ -1434,8 +1434,11 @@ class Types implements DartTypes {
* [type], or [:null:] if [type] does not contain type variables.
*/
static ClassElement getClassContext(DartType type) {
TypeVariableType typeVariable = type.typeVariableOccurrence;
if (typeVariable == null) return null;
ClassElement contextClass;
type.forEachTypeVariable((TypeVariableType typeVariable) {
if (typeVariable.element.typeDeclaration is! ClassElement) return;
contextClass = typeVariable.element.typeDeclaration;
});
// GENERIC_METHODS: When generic method support is complete enough to
// include a runtime value for method type variables this must be updated.
// For full support the global assumption that all type variables are
@ -1444,8 +1447,7 @@ class Types implements DartTypes {
// type cannot be [ClassElement] and the caller must be prepared to look in
// two locations, not one. Currently we ignore method type variables by
// returning in the next statement.
if (typeVariable.element.typeDeclaration is! ClassElement) return null;
return typeVariable.element.typeDeclaration;
return contextClass;
}
/**

View file

@ -609,8 +609,10 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
jsAst.Expression getTypeRepresentation(
DartType type, OnVariableCallback onVariable,
[ShouldEncodeTypedefCallback shouldEncodeTypedef]) {
// GENERIC_METHODS: When generic method support is complete enough to
// include a runtime value for method type variables this must be updated.
return representationGenerator.getTypeRepresentation(
type, onVariable, shouldEncodeTypedef);
type.dynamifyMethodTypeVariableType, onVariable, shouldEncodeTypedef);
}
@override

View file

@ -2607,18 +2607,21 @@ abstract class Closure implements Function {
})(#, #)''',
RAW_DART_FUNCTION_REF(getType),
functionType);
} else if (!isStatic
&& JS('bool', 'typeof # == "function"', functionType)) {
var getReceiver = isIntercepted
? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf)
: RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
signatureFunction = JS(
'',
'function(f,r){'
'return function(){'
'return f.apply({\$receiver:r(this)},arguments)'
'}'
'}(#,#)', functionType, getReceiver);
} else if (JS('bool', 'typeof # == "function"', functionType)) {
if (isStatic) {
signatureFunction = functionType;
} else {
var getReceiver = isIntercepted
? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf)
: RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
signatureFunction = JS(
'',
'function(f,r){'
'return function(){'
'return f.apply({\$receiver:r(this)},arguments)'
'}'
'}(#,#)', functionType, getReceiver);
}
} else {
throw 'Error in reflectionInfo.';
}

View file

@ -0,0 +1,50 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:expect/expect.dart';
typedef O Convert<I, O>(I input);
typedef Other(a, b);
class Mixin<E> {
E convert1<I>(I input) => null;
}
class Class<F> extends Object with Mixin<F> {
O convert2<O>(F input) => null;
}
O convert<I, O>(I input) => null;
test1() {
var val = new Class<String>();
Expect.isTrue(val.convert1 is Convert);
Expect.isTrue(val.convert1 is Convert<String, String>);
Expect.isTrue(val.convert1 is Convert<int, String>);
Expect.isFalse(val.convert1 is Convert<String, int>);
Expect.isFalse(val.convert1 is Other);
}
test2() {
var val = new Class<String>();
Expect.isTrue(val.convert2 is Convert);
Expect.isTrue(val.convert2 is Convert<String, String>);
Expect.isTrue(val.convert2 is Convert<String, int>);
Expect.isFalse(val.convert2 is Convert<int, String>);
Expect.isFalse(val.convert2 is Other);
}
test3() {
Expect.isTrue(convert is Convert);
Expect.isTrue(convert is Convert<String, String>);
Expect.isTrue(convert is Convert<String, int>);
Expect.isTrue(convert is Convert<int, String>);
Expect.isFalse(convert is Other);
}
main() {
test1(); /// 01: ok
test2(); /// 02: ok
test3(); /// 03: ok
}