OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; | 5 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; |
6 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'
; | 6 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'
; |
7 import 'package:kernel/ast.dart'; | 7 import 'package:kernel/ast.dart'; |
8 import 'package:kernel/type_algebra.dart'; | 8 import 'package:kernel/type_algebra.dart'; |
9 | 9 |
10 /// Creates a collection of [TypeConstraint]s corresponding to type parameters, | 10 /// Creates a collection of [TypeConstraint]s corresponding to type parameters, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 return false; | 85 return false; |
86 } | 86 } |
87 if (subtype.positionalParameters.length < | 87 if (subtype.positionalParameters.length < |
88 supertype.positionalParameters.length) { | 88 supertype.positionalParameters.length) { |
89 return false; | 89 return false; |
90 } | 90 } |
91 if (subtype.typeParameters.isNotEmpty || | 91 if (subtype.typeParameters.isNotEmpty || |
92 supertype.typeParameters.isNotEmpty) { | 92 supertype.typeParameters.isNotEmpty) { |
93 var subtypeSubstitution = <TypeParameter, DartType>{}; | 93 var subtypeSubstitution = <TypeParameter, DartType>{}; |
94 var supertypeSubstitution = <TypeParameter, DartType>{}; | 94 var supertypeSubstitution = <TypeParameter, DartType>{}; |
| 95 var freshTypeVariables = <TypeParameter>[]; |
95 if (!_matchTypeFormals(subtype.typeParameters, supertype.typeParameters, | 96 if (!_matchTypeFormals(subtype.typeParameters, supertype.typeParameters, |
96 subtypeSubstitution, supertypeSubstitution)) { | 97 subtypeSubstitution, supertypeSubstitution, freshTypeVariables)) { |
97 return false; | 98 return false; |
98 } | 99 } |
99 | 100 |
100 // TODO(paulberry): try to push this functionality into kernel. | 101 subtype = substituteTypeParams( |
101 FunctionType substituteTypeParams( | 102 subtype, subtypeSubstitution, freshTypeVariables); |
102 FunctionType type, Map<TypeParameter, DartType> substitutionMap) { | 103 supertype = substituteTypeParams( |
103 var substitution = Substitution.fromMap(substitutionMap); | 104 supertype, supertypeSubstitution, freshTypeVariables); |
104 return new FunctionType( | |
105 type.positionalParameters.map(substitution.substituteType).toList(), | |
106 substitution.substituteType(type.returnType), | |
107 namedParameters: type.namedParameters | |
108 .map((named) => new NamedType( | |
109 named.name, substitution.substituteType(named.type))) | |
110 .toList(), | |
111 typeParameters: substitutionMap.keys.toList(), | |
112 requiredParameterCount: type.requiredParameterCount); | |
113 } | |
114 | |
115 subtype = substituteTypeParams(subtype, subtypeSubstitution); | |
116 supertype = substituteTypeParams(supertype, supertypeSubstitution); | |
117 } | 105 } |
118 | 106 |
119 // Test the return types. | 107 // Test the return types. |
120 if (supertype.returnType is! VoidType && | 108 if (supertype.returnType is! VoidType && |
121 !_isSubtypeMatch(subtype.returnType, supertype.returnType)) { | 109 !_isSubtypeMatch(subtype.returnType, supertype.returnType)) { |
122 return false; | 110 return false; |
123 } | 111 } |
124 | 112 |
125 // Test the parameter types. | 113 // Test the parameter types. |
126 for (int i = 0; i < supertype.positionalParameters.length; ++i) { | 114 for (int i = 0; i < supertype.positionalParameters.length; ++i) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 /// bounds are compatible. | 324 /// bounds are compatible. |
337 /// | 325 /// |
338 /// The return value indicates whether a match was found. If it was, entries | 326 /// The return value indicates whether a match was found. If it was, entries |
339 /// are added to [substitution1] and [substitution2] which substitute a fresh | 327 /// are added to [substitution1] and [substitution2] which substitute a fresh |
340 /// set of type variables for the type parameters [params1] and [params2], | 328 /// set of type variables for the type parameters [params1] and [params2], |
341 /// respectively, allowing further comparison. | 329 /// respectively, allowing further comparison. |
342 bool _matchTypeFormals( | 330 bool _matchTypeFormals( |
343 List<TypeParameter> params1, | 331 List<TypeParameter> params1, |
344 List<TypeParameter> params2, | 332 List<TypeParameter> params2, |
345 Map<TypeParameter, DartType> substitution1, | 333 Map<TypeParameter, DartType> substitution1, |
346 Map<TypeParameter, DartType> substitution2) { | 334 Map<TypeParameter, DartType> substitution2, |
| 335 List<TypeParameter> freshTypeVariables) { |
347 int count = params1.length; | 336 int count = params1.length; |
348 if (count != params2.length) return false; | 337 if (count != params2.length) return false; |
349 // TODO(paulberry): in imitation of analyzer, we're checking the bounds as | 338 // TODO(paulberry): in imitation of analyzer, we're checking the bounds as |
350 // we build up the substitutions. But I don't think that's correct--I think | 339 // we build up the substitutions. But I don't think that's correct--I think |
351 // we should build up both substitutions completely before checking any | 340 // we should build up both substitutions completely before checking any |
352 // bounds. See dartbug.com/29629. | 341 // bounds. See dartbug.com/29629. |
353 for (int i = 0; i < count; i++) { | 342 for (int i = 0; i < count; i++) { |
354 TypeParameter pFresh = new TypeParameter(params2[i].name); | 343 TypeParameter pFresh = new TypeParameter(params2[i].name); |
| 344 freshTypeVariables.add(pFresh); |
355 DartType variableFresh = new TypeParameterType(pFresh); | 345 DartType variableFresh = new TypeParameterType(pFresh); |
356 substitution1[params1[i]] = variableFresh; | 346 substitution1[params1[i]] = variableFresh; |
357 substitution2[params2[i]] = variableFresh; | 347 substitution2[params2[i]] = variableFresh; |
358 DartType bound1 = substitute(params1[i].bound, substitution1); | 348 DartType bound1 = substitute(params1[i].bound, substitution1); |
359 DartType bound2 = substitute(params2[i].bound, substitution2); | 349 DartType bound2 = substitute(params2[i].bound, substitution2); |
360 pFresh.bound = bound2; | 350 pFresh.bound = bound2; |
361 if (!_isSubtypeMatch(bound2, bound1)) return false; | 351 if (!_isSubtypeMatch(bound2, bound1)) return false; |
362 } | 352 } |
363 return true; | 353 return true; |
364 } | 354 } |
365 } | 355 } |
366 | 356 |
367 /// Tracks a single constraint on a single type variable. | 357 /// Tracks a single constraint on a single type variable. |
368 /// | 358 /// |
369 /// This is called "_ProtoConstraint" to distinguish from [TypeConstraint], | 359 /// This is called "_ProtoConstraint" to distinguish from [TypeConstraint], |
370 /// which tracks the upper and lower bounds that are together implied by a set | 360 /// which tracks the upper and lower bounds that are together implied by a set |
371 /// of [_ProtoConstraint]s. | 361 /// of [_ProtoConstraint]s. |
372 class _ProtoConstraint { | 362 class _ProtoConstraint { |
373 final TypeParameter parameter; | 363 final TypeParameter parameter; |
374 | 364 |
375 final DartType bound; | 365 final DartType bound; |
376 | 366 |
377 final bool isUpper; | 367 final bool isUpper; |
378 | 368 |
379 _ProtoConstraint.lower(this.parameter, this.bound) : isUpper = false; | 369 _ProtoConstraint.lower(this.parameter, this.bound) : isUpper = false; |
380 | 370 |
381 _ProtoConstraint.upper(this.parameter, this.bound) : isUpper = true; | 371 _ProtoConstraint.upper(this.parameter, this.bound) : isUpper = true; |
382 } | 372 } |
OLD | NEW |