blob: fd2d9d027e38a39fad6b65d199dd5fb2a2d917d4 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(dmitryas): Delete the file when a special representation for FutureOr
// is landed.
import '../ast.dart';
Nullability uniteNullabilities(Nullability a, Nullability b) {
if (a == Nullability.nullable || b == Nullability.nullable) {
return Nullability.nullable;
}
if (a == Nullability.legacy || b == Nullability.legacy) {
return Nullability.legacy;
}
if (a == Nullability.undetermined || b == Nullability.undetermined) {
return Nullability.undetermined;
}
return Nullability.nonNullable;
}
Nullability intersectNullabilities(Nullability a, Nullability b) {
if (a == Nullability.nonNullable || b == Nullability.nonNullable) {
return Nullability.nonNullable;
}
if (a == Nullability.undetermined || b == Nullability.undetermined) {
return Nullability.undetermined;
}
if (a == Nullability.legacy || b == Nullability.legacy) {
return Nullability.legacy;
}
return Nullability.nonNullable;
}
Nullability computeNullabilityOfFutureOr(
InterfaceType futureOr, Class futureOrClass) {
assert(futureOr.classNode == futureOrClass);
// Performance note: the algorithm is linear.
DartType argument = futureOr.typeArguments.single;
if (argument is InterfaceType && argument.classNode == futureOrClass) {
return uniteNullabilities(
computeNullabilityOfFutureOr(argument, futureOrClass),
futureOr.nullability);
}
if (argument is TypeParameterType && argument.promotedBound != null) {
DartType promotedBound = argument.promotedBound;
if (promotedBound is InterfaceType &&
promotedBound.className == futureOrClass) {
return uniteNullabilities(
intersectNullabilities(argument.typeParameterTypeNullability,
computeNullabilityOfFutureOr(promotedBound, futureOrClass)),
futureOr.nullability);
}
}
Nullability argumentNullability =
argument is InvalidType ? Nullability.undetermined : argument.nullability;
return uniteNullabilities(argumentNullability, futureOr.nullability);
}
Nullability computeNullability(DartType type, Class futureOrClass) {
if (type is InterfaceType && type.classNode == futureOrClass) {
return computeNullabilityOfFutureOr(type, futureOrClass);
}
return type.nullability;
}