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:
Paul Berry 2018-10-11 00:10:48 +00:00 committed by commit-bot@chromium.org
parent c47879d354
commit 0ab8e42fea
3 changed files with 54 additions and 12 deletions

View file

@ -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 {

View file

@ -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

View file

@ -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> {