mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:37:12 +00:00
Use a special context for serializing generic function types.
This is necessary to ensure that type parameters that refer to the enclosing context get serialized correctly. Change-Id: I1e95cc4e83be76bf003faa037eff80728c1fb748 Reviewed-on: https://dart-review.googlesource.com/c/79145 Auto-Submit: Paul Berry <paulberry@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
parent
c47879d354
commit
0ab8e42fea
|
@ -7676,7 +7676,10 @@ class TypeParameterElementImpl extends ElementImpl
|
|||
|
||||
/// Mixin representing an element which can have type parameters.
|
||||
abstract class TypeParameterizedElementMixin
|
||||
implements TypeParameterizedElement, ElementImpl {
|
||||
implements
|
||||
TypeParameterizedElement,
|
||||
ElementImpl,
|
||||
TypeParameterSerializationContext {
|
||||
/// A cached list containing the type parameters declared by this element
|
||||
/// directly, or `null` if the elements have not been created yet. This does
|
||||
/// not include type parameters that are declared by any enclosing elements.
|
||||
|
@ -7727,10 +7730,7 @@ abstract class TypeParameterizedElementMixin
|
|||
/// TODO(scheglov) make private after switching linker to Impl
|
||||
List<UnlinkedTypeParam> get unlinkedTypeParams;
|
||||
|
||||
/// Return the given [typeParameter]'s de Bruijn index in this context, or
|
||||
/// `null` if it's not in scope.
|
||||
///
|
||||
/// If an [offset] is provided, then it is added to the computed index.
|
||||
@override
|
||||
int computeDeBruijnIndex(TypeParameterElement typeParameter,
|
||||
{int offset = 0}) {
|
||||
if (typeParameter.enclosingElement == this) {
|
||||
|
@ -7761,6 +7761,20 @@ abstract class TypeParameterizedElementMixin
|
|||
}
|
||||
}
|
||||
|
||||
/// Interface used by linker serialization methods to convert type parameter
|
||||
/// references into De Bruijn indices.
|
||||
abstract class TypeParameterSerializationContext {
|
||||
/// Return an object representing the location of this element in the element
|
||||
/// model. The object can be used to locate this element at a later time.
|
||||
ElementLocation get location;
|
||||
|
||||
/// Return the given [typeParameter]'s de Bruijn index in this context, or
|
||||
/// `null` if it's not in scope.
|
||||
///
|
||||
/// If an [offset] is provided, then it is added to the computed index.
|
||||
int computeDeBruijnIndex(TypeParameterElement typeParameter, {int offset: 0});
|
||||
}
|
||||
|
||||
/// Container with information about explicit top-level property accessors and
|
||||
/// corresponding implicit top-level variables.
|
||||
class UnitExplicitTopLevelAccessors {
|
||||
|
|
|
@ -181,7 +181,7 @@ List<EntityRef> _collectTypedefRhsTypes(UnlinkedTypedef unlinkedTypedef) {
|
|||
EntityRefBuilder _createLinkedType(
|
||||
DartType type,
|
||||
CompilationUnitElementInBuildUnit compilationUnit,
|
||||
TypeParameterizedElementMixin typeParameterContext,
|
||||
TypeParameterSerializationContext typeParameterContext,
|
||||
{int slot}) {
|
||||
EntityRefBuilder result = new EntityRefBuilder(slot: slot);
|
||||
if (type is InterfaceType) {
|
||||
|
@ -247,7 +247,8 @@ EntityRefBuilder _createLinkedType(
|
|||
}
|
||||
if (element is GenericFunctionTypeElementImpl) {
|
||||
// Function types are their own type parameter context
|
||||
typeParameterContext = element;
|
||||
typeParameterContext =
|
||||
new InlineFunctionTypeParameterContext(element, typeParameterContext);
|
||||
result.entityKind = EntityRefKind.genericFunctionType;
|
||||
result.syntheticReturnType = _createLinkedType(
|
||||
type.returnType, compilationUnit, typeParameterContext);
|
||||
|
@ -309,7 +310,7 @@ void _relink(
|
|||
UnlinkedParamBuilder _serializeSyntheticParam(
|
||||
ParameterElement parameter,
|
||||
CompilationUnitElementInBuildUnit compilationUnit,
|
||||
TypeParameterizedElementMixin typeParameterContext) {
|
||||
TypeParameterSerializationContext typeParameterContext) {
|
||||
UnlinkedParamBuilder b = new UnlinkedParamBuilder();
|
||||
b.name = parameter.name;
|
||||
if (parameter.isNotOptional) {
|
||||
|
@ -343,7 +344,7 @@ UnlinkedParamBuilder _serializeSyntheticParam(
|
|||
UnlinkedTypeParamBuilder _serializeSyntheticTypeParameter(
|
||||
TypeParameterElement typeParameter,
|
||||
CompilationUnitElementInBuildUnit compilationUnit,
|
||||
TypeParameterizedElementMixin typeParameterContext) {
|
||||
TypeParameterSerializationContext typeParameterContext) {
|
||||
TypeParameterElementImpl impl = typeParameter as TypeParameterElementImpl;
|
||||
EntityRefBuilder boundBuilder = typeParameter.bound != null
|
||||
? _createLinkedType(
|
||||
|
@ -387,7 +388,7 @@ void _storeTypeArguments(
|
|||
List<DartType> typeArguments,
|
||||
EntityRefBuilder encodedType,
|
||||
CompilationUnitElementInBuildUnit compilationUnit,
|
||||
TypeParameterizedElementMixin typeParameterContext) {
|
||||
TypeParameterSerializationContext typeParameterContext) {
|
||||
int count = typeArguments.length;
|
||||
List<EntityRefBuilder> encodedTypeArguments =
|
||||
new List<EntityRefBuilder>(count);
|
||||
|
@ -1645,7 +1646,7 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
|
|||
/// Store the given [linkedType] in the given [slot] of the this compilation
|
||||
/// unit's linked type list.
|
||||
void _storeLinkedType(int slot, DartType linkedType,
|
||||
TypeParameterizedElementMixin typeParameterContext) {
|
||||
TypeParameterSerializationContext typeParameterContext) {
|
||||
if (slot != 0) {
|
||||
if (linkedType != null && !linkedType.isDynamic) {
|
||||
_linkedUnit.types.add(_createLinkedType(
|
||||
|
@ -3364,6 +3365,34 @@ class GenericTypeAliasElementForLink extends Object
|
|||
String toString() => '$enclosingElement.$name';
|
||||
}
|
||||
|
||||
/// Context for serializing a possibly generic function type that is used in
|
||||
/// another context.
|
||||
class InlineFunctionTypeParameterContext
|
||||
implements TypeParameterSerializationContext {
|
||||
final GenericFunctionTypeElementImpl _functionTypeElement;
|
||||
|
||||
final TypeParameterSerializationContext _usageContext;
|
||||
|
||||
InlineFunctionTypeParameterContext(
|
||||
this._functionTypeElement, this._usageContext);
|
||||
|
||||
@override
|
||||
ElementLocation get location =>
|
||||
throw new UnimplementedError('TODO(paulberry)');
|
||||
|
||||
@override
|
||||
int computeDeBruijnIndex(TypeParameterElement typeParameter,
|
||||
{int offset: 0}) {
|
||||
var typeFormals = _functionTypeElement.typeParameters;
|
||||
var numTypeFormals = typeFormals.length;
|
||||
for (int i = 0; i < numTypeFormals; i++) {
|
||||
if (typeFormals[i] == typeParameter) return i + offset + 1;
|
||||
}
|
||||
return _usageContext.computeDeBruijnIndex(typeParameter,
|
||||
offset: offset + numTypeFormals);
|
||||
}
|
||||
}
|
||||
|
||||
/// Specialization of [DependencyWalker] for linking library cycles.
|
||||
class LibraryCycleDependencyWalker extends DependencyWalker<LibraryCycleNode> {
|
||||
@override
|
||||
|
|
|
@ -443,7 +443,6 @@ class C extends A<int> {
|
|||
expect(fType.parameters[0].type.toString(), 'int');
|
||||
}
|
||||
|
||||
@failingTest
|
||||
void test_inferredType_parameter_genericFunctionType_asTypeArgument() {
|
||||
var bundle = createPackageBundle('''
|
||||
class A<T> {
|
||||
|
|
Loading…
Reference in a new issue