Skip to content

Commit

Permalink
Refactor types resolution, compute default types for type parameters.
Browse files Browse the repository at this point in the history
R=brianwilkerson@google.com

Change-Id: If8b89c611c10c0026ec40773aed2a38a5fb37b23
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100787
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
  • Loading branch information
scheglov committed Apr 29, 2019
1 parent 6436104 commit c944328
Show file tree
Hide file tree
Showing 18 changed files with 1,143 additions and 463 deletions.
10 changes: 10 additions & 0 deletions pkg/analyzer/lib/src/dart/element/element.dart
Expand Up @@ -9441,6 +9441,16 @@ class TypeParameterElementImpl extends ElementImpl
return super.codeOffset;
}

/// The default value of the type parameter. It is used to provide the
/// corresponding missing type argument in type annotations and as the
/// fall-back type value in type inference.
DartType get defaultType {
if (linkedNode != null) {
return linkedContext.getDefaultType(linkedNode);
}
return null;
}

@override
String get displayName => name;

Expand Down
57 changes: 57 additions & 0 deletions pkg/analyzer/lib/src/dart/element/type_algebra.dart
Expand Up @@ -7,6 +7,8 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_visitor.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';

/// Generates a fresh copy of the given type parameters, with their bounds
/// substituted to reference the new parameters.
Expand Down Expand Up @@ -322,6 +324,46 @@ abstract class _TypeSubstitutor extends DartTypeVisitor<DartType> {
return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters);
}

@override
DartType visitFunctionTypeBuilder(FunctionTypeBuilder type) {
// This is a bit tricky because we have to generate fresh type parameters
// in order to change the bounds. At the same time, if the function type
// was unaltered, we have to return the [type] object (not a copy!).
// Substituting a type for a fresh type variable should not be confused
// with a "real" substitution.
//
// Create an inner environment to generate fresh type parameters. The use
// counter on the inner environment tells if the fresh type parameters have
// any uses, but does not tell if the resulting function type is distinct.
// Our own use counter will get incremented if something from our
// environment has been used inside the function.
var inner = type.typeFormals.isEmpty ? this : newInnerEnvironment();
int before = this.useCounter;

// Invert the variance when translating parameters.
inner.invertVariance();

var typeFormals = inner.freshTypeParameters(type.typeFormals);

var parameters = type.parameters.map((parameter) {
var type = inner.visit(parameter.type);
return ParameterElementImpl.synthetic(
parameter.name,
type,
// ignore: deprecated_member_use_from_same_package
parameter.parameterKind,
);
}).toList();

inner.invertVariance();

var returnType = inner.visit(type.returnType);

if (this.useCounter == before) return type;

return FunctionTypeBuilder(typeFormals, parameters, returnType);
}

@override
DartType visitInterfaceType(InterfaceType type) {
if (type.typeArguments.isEmpty) {
Expand All @@ -337,6 +379,21 @@ abstract class _TypeSubstitutor extends DartTypeVisitor<DartType> {
return new InterfaceTypeImpl.explicit(type.element, typeArguments);
}

@override
DartType visitNamedType(NamedTypeBuilder type) {
if (type.arguments.isEmpty) {
return type;
}

int before = useCounter;
var arguments = type.arguments.map(visit).toList();
if (useCounter == before) {
return type;
}

return new NamedTypeBuilder(type.element, arguments);
}

@override
DartType visitTypeParameterType(TypeParameterType type) {
return getSubstitute(type.element) ?? type;
Expand Down
12 changes: 12 additions & 0 deletions pkg/analyzer/lib/src/dart/element/type_visitor.dart
Expand Up @@ -4,6 +4,8 @@

import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';

class DartTypeVisitor<R> {
const DartTypeVisitor();
Expand All @@ -16,8 +18,12 @@ class DartTypeVisitor<R> {

R visitFunctionType(FunctionType type) => defaultDartType(type);

R visitFunctionTypeBuilder(FunctionTypeBuilder type) => defaultDartType(type);

R visitInterfaceType(InterfaceType type) => defaultDartType(type);

R visitNamedType(NamedTypeBuilder type) => defaultDartType(type);

R visitTypeParameterType(TypeParameterType type) => defaultDartType(type);

R visitVoidType(VoidType type) => defaultDartType(type);
Expand All @@ -32,9 +38,15 @@ class DartTypeVisitor<R> {
if (type is FunctionType) {
return visitor.visitFunctionType(type);
}
if (type is FunctionTypeBuilder) {
return visitor.visitFunctionTypeBuilder(type);
}
if (type is InterfaceType) {
return visitor.visitInterfaceType(type);
}
if (type is NamedTypeBuilder) {
return visitor.visitNamedType(type);
}
if (type is TypeParameterType) {
return visitor.visitTypeParameterType(type);
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/analyzer/lib/src/summary/format.dart
Expand Up @@ -8093,6 +8093,12 @@ class LinkedNodeBuilder extends Object
return _variantField_23;
}

@override
LinkedNodeTypeBuilder get typeParameter_defaultType {
assert(kind == idl.LinkedNodeKind.typeParameter);
return _variantField_23;
}

set annotation_elementType(LinkedNodeTypeBuilder value) {
assert(kind == idl.LinkedNodeKind.annotation);
_variantField_23 = value;
Expand Down Expand Up @@ -8149,6 +8155,11 @@ class LinkedNodeBuilder extends Object
_variantField_23 = value;
}

set typeParameter_defaultType(LinkedNodeTypeBuilder value) {
assert(kind == idl.LinkedNodeKind.typeParameter);
_variantField_23 = value;
}

@override
LinkedNodeBuilder get annotation_name {
assert(kind == idl.LinkedNodeKind.annotation);
Expand Down Expand Up @@ -10886,6 +10897,7 @@ class LinkedNodeBuilder extends Object
LinkedNodeBuilder typeParameter_bound,
int typeParameter_extendsKeyword,
LinkedNodeBuilder typeParameter_name,
LinkedNodeTypeBuilder typeParameter_defaultType,
int codeLength,
int codeOffset,
}) : _kind = idl.LinkedNodeKind.typeParameter,
Expand All @@ -10894,6 +10906,7 @@ class LinkedNodeBuilder extends Object
_variantField_6 = typeParameter_bound,
_variantField_15 = typeParameter_extendsKeyword,
_variantField_7 = typeParameter_name,
_variantField_23 = typeParameter_defaultType,
_variantField_34 = codeLength,
_variantField_33 = codeOffset;

Expand Down Expand Up @@ -14401,6 +14414,14 @@ class _LinkedNodeImpl extends Object
return _variantField_23;
}

@override
idl.LinkedNodeType get typeParameter_defaultType {
assert(kind == idl.LinkedNodeKind.typeParameter);
_variantField_23 ??=
const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 23, null);
return _variantField_23;
}

@override
idl.LinkedNode get annotation_name {
assert(kind == idl.LinkedNodeKind.annotation);
Expand Down Expand Up @@ -16665,6 +16686,9 @@ abstract class _LinkedNodeMixin implements idl.LinkedNode {
_result["typeParameter_extendsKeyword"] = typeParameter_extendsKeyword;
if (typeParameter_name != null)
_result["typeParameter_name"] = typeParameter_name.toJson();
if (typeParameter_defaultType != null)
_result["typeParameter_defaultType"] =
typeParameter_defaultType.toJson();
if (codeLength != 0) _result["codeLength"] = codeLength;
if (codeOffset != 0) _result["codeOffset"] = codeOffset;
}
Expand Down Expand Up @@ -18121,6 +18145,7 @@ abstract class _LinkedNodeMixin implements idl.LinkedNode {
"typeParameter_bound": typeParameter_bound,
"typeParameter_extendsKeyword": typeParameter_extendsKeyword,
"typeParameter_name": typeParameter_name,
"typeParameter_defaultType": typeParameter_defaultType,
"codeLength": codeLength,
"codeOffset": codeOffset,
"isSynthetic": isSynthetic,
Expand Down
3 changes: 3 additions & 0 deletions pkg/analyzer/lib/src/summary/idl.dart
Expand Up @@ -2297,6 +2297,9 @@ abstract class LinkedNode extends base.SummaryClass {
@VariantId(6, variant: LinkedNodeKind.typeParameter)
LinkedNode get typeParameter_bound;

@VariantId(23, variant: LinkedNodeKind.typeParameter)
LinkedNodeType get typeParameter_defaultType;

@VariantId(15, variant: LinkedNodeKind.typeParameter)
int get typeParameter_extendsKeyword;

Expand Down
8 changes: 5 additions & 3 deletions pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
Expand Up @@ -1250,9 +1250,11 @@ class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
@override
LinkedNodeBuilder visitTypeParameter(TypeParameter node) {
var builder = LinkedNodeBuilder.typeParameter(
typeParameter_bound: node.bound?.accept(this),
typeParameter_extendsKeyword: _getToken(node.extendsKeyword),
typeParameter_name: node.name.accept(this));
typeParameter_bound: node.bound?.accept(this),
typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
typeParameter_extendsKeyword: _getToken(node.extendsKeyword),
typeParameter_name: node.name.accept(this),
);
_storeDeclaration(builder, node);
_storeCodeOffsetLength(builder, node);
return builder;
Expand Down
Expand Up @@ -20,6 +20,7 @@ import 'package:analyzer/src/summary2/metadata_resolver.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/reference_resolver.dart';
import 'package:analyzer/src/summary2/scope.dart';
import 'package:analyzer/src/summary2/types_builder.dart';

class SourceLibraryBuilder {
final Linker linker;
Expand Down Expand Up @@ -300,7 +301,7 @@ class SourceLibraryBuilder {
}
}

void resolveTypes(List<ast.AstNode> nodesToBuildType) {
void resolveTypes(NodesToBuildType nodesToBuildType) {
for (var unitContext in context.units) {
var unitRef = reference.getChild('@unit');
var unitReference = unitRef.getChild(unitContext.uriStr);
Expand Down

0 comments on commit c944328

Please sign in to comment.