mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[dart2wasm] Normalize FutureOrType.
Attempts to incorporate some of the missing cases in: https://github.com/dart-lang/language/blob/master/resources/type-system/normalization.md Particularly NORM(FutureOr<T>). I'm also trying to better handle one particular case in NORM(T?) for FutureOr and nullability. Particularly: if S is FutureOr<R> and R is nullable then S Change-Id: I4671f1f4992b9114b055df127d8807d168cc0a66 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261788 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
parent
a2e7decb7e
commit
c3573379c4
|
@ -780,7 +780,7 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConstantInfo? visitTypeLiteralConstant(TypeLiteralConstant constant) {
|
ConstantInfo? visitTypeLiteralConstant(TypeLiteralConstant constant) {
|
||||||
DartType type = constant.type;
|
DartType type = types.normalize(constant.type);
|
||||||
|
|
||||||
ClassInfo info = translator.classInfo[types.classForType(type)]!;
|
ClassInfo info = translator.classInfo[types.classForType(type)]!;
|
||||||
translator.functions.allocateClass(info.classId);
|
translator.functions.allocateClass(info.classId);
|
||||||
|
|
|
@ -114,7 +114,9 @@ class Types {
|
||||||
for (InterfaceType subtype in subtypes) {
|
for (InterfaceType subtype in subtypes) {
|
||||||
interfaceTypeEnvironment._add(subtype);
|
interfaceTypeEnvironment._add(subtype);
|
||||||
List<DartType>? typeArguments = translator.hierarchy
|
List<DartType>? typeArguments = translator.hierarchy
|
||||||
.getTypeArgumentsAsInstanceOf(subtype, superclass);
|
.getTypeArgumentsAsInstanceOf(subtype, superclass)
|
||||||
|
?.map(normalize)
|
||||||
|
.toList();
|
||||||
ClassInfo subclassInfo = translator.classInfo[subtype.classNode]!;
|
ClassInfo subclassInfo = translator.classInfo[subtype.classNode]!;
|
||||||
Map<int, List<DartType>> substitutionMap =
|
Map<int, List<DartType>> substitutionMap =
|
||||||
subtypeMap[subclassInfo.classId] ??= {};
|
subtypeMap[subclassInfo.classId] ??= {};
|
||||||
|
@ -311,6 +313,57 @@ class Types {
|
||||||
_makeTypeList(codeGen, type.typeArguments);
|
_makeTypeList(codeGen, type.typeArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DartType normalizeFutureOrType(FutureOrType type) {
|
||||||
|
final s = normalize(type.typeArgument);
|
||||||
|
|
||||||
|
// `coreTypes.isTope` and `coreTypes.isObject` take into account the
|
||||||
|
// normalization rules of `futureOr`.
|
||||||
|
if (coreTypes.isTop(type) || coreTypes.isObject(type)) {
|
||||||
|
return s;
|
||||||
|
} else if (s is NeverType) {
|
||||||
|
return InterfaceType(coreTypes.futureClass, Nullability.nonNullable,
|
||||||
|
const [const NeverType.nonNullable()]);
|
||||||
|
} else if (s is NullType) {
|
||||||
|
return InterfaceType(coreTypes.futureClass, Nullability.nullable,
|
||||||
|
const [const NullType()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type is normalized, and remains a `FutureOr` so now we normalize its
|
||||||
|
// nullability.
|
||||||
|
final declaredNullability = s.nullability == Nullability.nullable
|
||||||
|
? Nullability.nonNullable
|
||||||
|
: type.declaredNullability;
|
||||||
|
return FutureOrType(s, declaredNullability);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Normalizes a Dart type. Many rules are already applied for us, but some we
|
||||||
|
/// have to apply manually, particularly to [FutureOr].
|
||||||
|
DartType normalize(DartType type) {
|
||||||
|
if (type is InterfaceType) {
|
||||||
|
return InterfaceType(type.classNode, type.nullability,
|
||||||
|
type.typeArguments.map(normalize).toList());
|
||||||
|
} else if (type is FunctionType) {
|
||||||
|
return FunctionType(type.positionalParameters.map(normalize).toList(),
|
||||||
|
normalize(type.returnType), type.nullability,
|
||||||
|
namedParameters: type.namedParameters
|
||||||
|
.map((namedType) => NamedType(
|
||||||
|
namedType.name, normalize(namedType.type),
|
||||||
|
isRequired: namedType.isRequired))
|
||||||
|
.toList(),
|
||||||
|
typeParameters: type.typeParameters
|
||||||
|
.map((typeParameter) => TypeParameter(
|
||||||
|
typeParameter.name,
|
||||||
|
normalize(typeParameter.bound),
|
||||||
|
normalize(typeParameter.defaultType)))
|
||||||
|
.toList(),
|
||||||
|
requiredParameterCount: type.requiredParameterCount);
|
||||||
|
} else if (type is FutureOrType) {
|
||||||
|
return normalizeFutureOrType(type);
|
||||||
|
} else {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _makeFutureOrType(CodeGenerator codeGen, FutureOrType type) {
|
void _makeFutureOrType(CodeGenerator codeGen, FutureOrType type) {
|
||||||
w.Instructions b = codeGen.b;
|
w.Instructions b = codeGen.b;
|
||||||
w.DefinedFunction function = codeGen.function;
|
w.DefinedFunction function = codeGen.function;
|
||||||
|
@ -382,6 +435,8 @@ class Types {
|
||||||
/// TODO(joshualitt): Refactor this logic to remove the dependency on
|
/// TODO(joshualitt): Refactor this logic to remove the dependency on
|
||||||
/// CodeGenerator.
|
/// CodeGenerator.
|
||||||
w.ValueType makeType(CodeGenerator codeGen, DartType type) {
|
w.ValueType makeType(CodeGenerator codeGen, DartType type) {
|
||||||
|
// Always ensure type is normalized before making a type.
|
||||||
|
type = normalize(type);
|
||||||
w.Instructions b = codeGen.b;
|
w.Instructions b = codeGen.b;
|
||||||
if (_isTypeConstant(type)) {
|
if (_isTypeConstant(type)) {
|
||||||
translator.constants.instantiateConstant(
|
translator.constants.instantiateConstant(
|
||||||
|
|
Loading…
Reference in a new issue