mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Check a complete array-new expression within a single constraint system.
Fixes <rdar://problem/15653973>. Swift SVN r11262
This commit is contained in:
@@ -787,30 +787,55 @@ namespace {
|
||||
}
|
||||
|
||||
Type visitNewArrayExpr(NewArrayExpr *expr) {
|
||||
// Validate the element type.
|
||||
auto &tc = CS.getTypeChecker();
|
||||
if (tc.validateType(expr->getElementTypeLoc(), CS.DC,
|
||||
/*allowUnboundGenerics=*/true))
|
||||
return nullptr;
|
||||
|
||||
// Open up the element type.
|
||||
auto elementTy = CS.openType(expr->getElementTypeLoc().getType());
|
||||
auto resultTy = elementTy;
|
||||
auto &tc = CS.getTypeChecker();
|
||||
for (unsigned i = expr->getBounds().size(); i != 1; --i) {
|
||||
// FIXME: To support multidimensional arrays, we'll need to look at
|
||||
// the expressions in here.
|
||||
auto &bound = expr->getBounds()[i-1];
|
||||
if (!bound.Value) {
|
||||
resultTy = tc.getArraySliceType(bound.Brackets.Start, resultTy);
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: When we get a constant expression evaluator, we'll have
|
||||
// to use it here.
|
||||
auto literal = cast<IntegerLiteralExpr>(
|
||||
bound.Value->getSemanticsProvidingExpr());
|
||||
resultTy = ArrayType::get(resultTy, literal->getValue().getZExtValue(),
|
||||
tc.Context);
|
||||
resultTy = tc.getArraySliceType(bound.Brackets.Start, resultTy);
|
||||
}
|
||||
|
||||
auto &outerBound = expr->getBounds()[0];
|
||||
|
||||
// The outer bound must be an ArrayBound.
|
||||
auto &outerBound = expr->getBounds()[0];
|
||||
auto arrayBoundProto = tc.getProtocol(expr->getLoc(),
|
||||
KnownProtocolKind::ArrayBound);
|
||||
if (!arrayBoundProto)
|
||||
return nullptr;
|
||||
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, outerBound.Value->getType(),
|
||||
arrayBoundProto->getDeclaredType(),
|
||||
CS.getConstraintLocator(outerBound.Value, { }));
|
||||
|
||||
// If we have an explicit constructor, make sure we can call it.
|
||||
// Either we have an explicit constructor closure or else ElementType must
|
||||
// be default constructible.
|
||||
if (!expr->hasConstructionFunction()) {
|
||||
if (expr->hasConstructionFunction()) {
|
||||
// FIXME: Assume the index type is DefaultIntegerLiteralType for now.
|
||||
auto intProto = tc.getProtocol(
|
||||
expr->getConstructionFunction()->getLoc(),
|
||||
KnownProtocolKind::IntegerLiteralConvertible);
|
||||
Type intTy = tc.getDefaultType(intProto, CS.DC);
|
||||
assert(intTy && "No default integer type?");
|
||||
|
||||
Expr *constructionFn = expr->getConstructionFunction();
|
||||
Type constructionTy = FunctionType::get(intTy,
|
||||
elementTy,
|
||||
tc.Context);
|
||||
|
||||
CS.addConstraint(ConstraintKind::Conversion, constructionFn->getType(),
|
||||
constructionTy,
|
||||
CS.getConstraintLocator(
|
||||
expr, ConstraintLocator::NewArrayConstructor));
|
||||
} else {
|
||||
// Otherwise, ElementType must be default constructible.
|
||||
Type defaultCtorTy = FunctionType::get(TupleType::getEmpty(tc.Context),
|
||||
elementTy,
|
||||
tc.Context);
|
||||
@@ -1143,12 +1168,8 @@ namespace {
|
||||
SanitizeExpr(TypeChecker &tc) : TC(tc) { }
|
||||
|
||||
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
|
||||
// Don't recur into array-new or default-value expressions.
|
||||
return {
|
||||
!isa<NewArrayExpr>(expr)
|
||||
&& !isa<DefaultValueExpr>(expr),
|
||||
expr
|
||||
};
|
||||
// Don't recurse into default-value expressions.
|
||||
return { !isa<DefaultValueExpr>(expr), expr };
|
||||
}
|
||||
|
||||
Expr *walkToExprPost(Expr *expr) override {
|
||||
@@ -1211,16 +1232,6 @@ namespace {
|
||||
return { true, expr };
|
||||
}
|
||||
|
||||
// For new array expressions, we visit the node but not any of its
|
||||
// children.
|
||||
// FIXME: If new array expressions gain an initializer, we'll need to
|
||||
// visit that first.
|
||||
if (auto newArray = dyn_cast<NewArrayExpr>(expr)) {
|
||||
auto type = CG.visitNewArrayExpr(newArray);
|
||||
expr->setType(type);
|
||||
return { false, expr };
|
||||
}
|
||||
|
||||
// We don't visit default value expressions; they've already been
|
||||
// type-checked.
|
||||
if (isa<DefaultValueExpr>(expr)) {
|
||||
|
||||
Reference in New Issue
Block a user