Correctly defer typedef references

Change-Id: I61fb5ebb399dcfca5193b7ae870badc10add23e5
Reviewed-on: https://dart-review.googlesource.com/37880
Reviewed-by: Emily Fortuna <efortuna@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Sigmund Cherem 2018-01-31 21:10:29 +00:00 committed by commit-bot@chromium.org
parent b74ceb0248
commit 3b6d39cc2c
9 changed files with 113 additions and 11 deletions

View file

@ -15,7 +15,8 @@ import 'constants/values.dart'
ConstantValue,
ConstructedConstantValue,
DeferredConstantValue,
DeferredGlobalConstantValue;
DeferredGlobalConstantValue,
TypeConstantValue;
import 'elements/types.dart';
import 'elements/elements.dart'
show AstElement, ClassElement, Element, MethodElement, LocalFunctionElement;
@ -370,6 +371,12 @@ abstract class DeferredLoadTask extends CompilerTask {
ClassEntity cls = constant.type.element;
_updateElementRecursive(cls, oldSet, newSet, queue);
}
if (constant is TypeConstantValue) {
var type = constant.representedType;
if (type is TypedefType) {
_updateElementRecursive(type.element, oldSet, newSet, queue);
}
}
constant.getDependencies().forEach((ConstantValue dependency) {
if (dependency is DeferredConstantValue) {
/// New deferred-imports are only discovered when we are visiting the

View file

@ -627,6 +627,8 @@ class ResolutionFunctionType extends ResolutionDartType
*/
final List<ResolutionDartType> namedParameterTypes;
TypedefType get typedefType => null;
factory ResolutionFunctionType(FunctionTypedElement element,
[ResolutionDartType returnType = const ResolutionDynamicType(),
List<ResolutionDartType> parameterTypes = const <ResolutionDartType>[],

View file

@ -499,13 +499,17 @@ class FunctionType extends DartType {
final List<FunctionTypeVariable> typeVariables;
/// The originating [TypedefType], if any.
final TypedefType typedefType;
FunctionType(
this.returnType,
this.parameterTypes,
this.optionalParameterTypes,
this.namedParameters,
this.namedParameterTypes,
this.typeVariables);
this.typeVariables,
this.typedefType);
bool get containsTypeVariables {
return returnType.containsTypeVariables ||
@ -573,7 +577,8 @@ class FunctionType extends DartType {
newOptionalParameterTypes,
namedParameters,
newNamedParameterTypes,
newTypeVariables);
newTypeVariables,
typedefType);
}
return this;
}

View file

@ -362,10 +362,13 @@ class ResolutionEnqueuer extends EnqueuerImpl {
}
break;
case TypeUseKind.TYPE_LITERAL:
TypedefType typedef;
if (type.isTypedef) {
TypedefType typedef = type;
worldBuilder.registerTypedef(typedef.element);
typedef = type;
} else if (type is FunctionType) {
typedef = type.typedefType;
}
if (typedef != null) worldBuilder.registerTypedef(typedef.element);
break;
}
}

View file

@ -170,6 +170,10 @@ class JsElementCreatorMixin {
return createClass(library, cls.name, isAbstract: cls.isAbstract);
}
TypedefEntity convertTypedef(LibraryEntity library, IndexedTypedef typedef) {
return createTypedef(library, typedef.name);
}
MemberEntity convertMember(
LibraryEntity library, ClassEntity cls, IndexedMember member) {
Name memberName = new Name(member.memberName.text, library,
@ -261,7 +265,8 @@ class TypeConverter implements DartTypeVisitor<DartType, EntityConverter> {
visitList(type.optionalParameterTypes, converter),
type.namedParameters,
visitList(type.namedParameterTypes, converter),
type.typeVariables);
type.typeVariables,
type.typedefType);
}
@override

View file

@ -88,6 +88,7 @@ class JsBackendStrategy implements KernelBackendStrategy {
Entity toBackendEntity(Entity entity) {
if (entity is ClassEntity) return map.toBackendClass(entity);
if (entity is MemberEntity) return map.toBackendMember(entity);
if (entity is TypedefEntity) return map.toBackendTypedef(entity);
if (entity is TypeVariableEntity) {
return map.toBackendTypeVariable(entity);
}
@ -683,6 +684,11 @@ class ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
var args = type.typeArguments.map(_handleType).toList();
return new InterfaceType(element, args);
}
if (type is TypedefType) {
var element = toBackendEntity(type.element);
var args = type.typeArguments.map(_handleType).toList();
return new TypedefType(element, args);
}
// TODO(redemption): handle other types.
return type;

View file

@ -462,7 +462,7 @@ abstract class KernelToElementMapBase extends KernelToElementMapBaseMixin {
}
return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
namedParameters, namedParameterTypes, typeVariables);
namedParameters, namedParameterTypes, typeVariables, null);
}
@override
@ -592,10 +592,15 @@ abstract class KernelToElementMapBase extends KernelToElementMapBaseMixin {
..sort((a, b) => a.compareTo(b));
List<DartType> namedParameterTypes =
new List.filled(namedParameters.length, dynamic);
data.callType = new FunctionType(dynamic, requiredParameterTypes,
optionalParameterTypes, namedParameters, namedParameterTypes,
data.callType = new FunctionType(
dynamic,
requiredParameterTypes,
optionalParameterTypes,
namedParameters,
namedParameterTypes,
// TODO(johnniwinther): Generate existential types here.
const <FunctionTypeVariable>[]);
const <FunctionTypeVariable>[],
null);
} else {
// The function type is not valid.
data.callType = const DynamicType();
@ -1650,6 +1655,10 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
}
index++;
}
DartType typedefType =
node.typedef == null ? null : elementMap.getTypedefType(node.typedef);
FunctionType type = new FunctionType(
visitType(node.returnType),
visitTypes(node.positionalParameters
@ -1660,7 +1669,8 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
.toList()),
node.namedParameters.map((n) => n.name).toList(),
node.namedParameters.map((n) => visitType(n.type)).toList(),
typeVariables ?? const <FunctionTypeVariable>[]);
typeVariables ?? const <FunctionTypeVariable>[],
typedefType);
for (ir.TypeParameter typeParameter in node.typeParameters) {
currentFunctionTypeParameters.remove(typeParameter);
}
@ -2073,6 +2083,10 @@ class JsToFrontendMapImpl extends JsToFrontendMapBase
return _backend._members.getEntity(member.memberIndex);
}
TypedefEntity toBackendTypedef(covariant IndexedTypedef typedef) {
return _backend._typedefs.getEntity(typedef.typedefIndex);
}
TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable) {
if (typeVariable is KLocalTypeVariable) {
failedAt(
@ -2134,6 +2148,25 @@ class JsKernelToElementMap extends KernelToElementMapBase
_classMap[env.cls] = _classes.register(newClass, data.copy(), env);
assert(newClass.classIndex == oldClass.classIndex);
}
for (int typedefIndex = 0;
typedefIndex < _elementMap._typedefs.length;
typedefIndex++) {
IndexedTypedef oldTypedef = _elementMap._typedefs.getEntity(typedefIndex);
TypedefData data = _elementMap._typedefs.getData(oldTypedef);
IndexedLibrary oldLibrary = oldTypedef.library;
LibraryEntity newLibrary = _libraries.getEntity(oldLibrary.libraryIndex);
IndexedTypedef newTypedef = convertTypedef(newLibrary, oldTypedef);
_typedefMap[data.node] = _typedefs.register(
newTypedef,
new TypedefData(
data.node,
newTypedef,
new TypedefType(
newTypedef,
new List<DartType>.filled(
data.node.typeParameters.length, const DynamicType()))));
assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
}
for (int memberIndex = 0;
memberIndex < _elementMap._members.length;
memberIndex++) {

View file

@ -0,0 +1,12 @@
// Copyright (c) 2014, 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 '../libs/deferred_typedef_lib1.dart' deferred as lib1;
/*element: main:OutputUnit(main, {})*/
main() async {
await lib1.loadLibrary();
print(lib1.cA);
print(lib1.cB);
}

View file

@ -0,0 +1,29 @@
// Copyright (c) 2014, 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.
library deferred_typedef_lib1;
class C {
/*element: C.a:OutputUnit(1, {lib1})*/
final a;
/*element: C.b:OutputUnit(1, {lib1})*/
final b;
/*element: C.:OutputUnit(1, {lib1})*/
const C(this.a, this.b);
}
typedef void MyF1();
typedef void MyF2();
/*element: topLevelMethod:OutputUnit(1, {lib1})*/
topLevelMethod() {}
/*element: cA:OutputUnit(1, {lib1})*/
const cA = /*OutputUnit(1, {lib1})*/ const C(MyF1, topLevelMethod);
/*element: cB:OutputUnit(1, {lib1})*/
const cB = /*OutputUnit(1, {lib1})*/ MyF2;