mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
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:
parent
b74ceb0248
commit
3b6d39cc2c
|
@ -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
|
||||
|
|
|
@ -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>[],
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
Loading…
Reference in a new issue