Skip to content

Commit 7d2e29a

Browse files
committed
[AST] Fix canonicalization of the function input types
Currently canonicalization of the input type was happening standalone which means that outer parens are regarded as suger and removed, this is incorrect after SE-0110 and such parens can't be stripped.
1 parent b164fdb commit 7d2e29a

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

lib/AST/Type.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,27 @@ void ProtocolType::canonicalizeProtocols(
10221022
llvm::array_pod_sort(protocols.begin(), protocols.end(), compareProtocols);
10231023
}
10241024

1025+
static Type
1026+
getCanonicalInputType(AnyFunctionType *funcType,
1027+
llvm::function_ref<CanType(Type)> getCanonicalType) {
1028+
auto origInputType = funcType->getInput();
1029+
bool isParen = isa<ParenType>(origInputType.getPointer());
1030+
Type inputType = getCanonicalType(origInputType);
1031+
1032+
if (!isParen && AnyFunctionType::isCanonicalFunctionInputType(inputType))
1033+
return inputType;
1034+
1035+
auto flags = ParameterTypeFlags().withInOut(inputType->is<InOutType>());
1036+
if (auto *parenTy = dyn_cast<ParenType>(origInputType.getPointer()))
1037+
flags = flags.withShared(parenTy->getParameterFlags().isShared());
1038+
1039+
inputType = ParenType::get(inputType->getASTContext(),
1040+
inputType->getInOutObjectType(), flags);
1041+
assert(AnyFunctionType::isCanonicalFunctionInputType(inputType));
1042+
1043+
return inputType;
1044+
}
1045+
10251046
/// getCanonicalType - Return the canonical version of this type, which has
10261047
/// sugar from all levels stripped off.
10271048
CanType TypeBase::getCanonicalType() {
@@ -1124,15 +1145,10 @@ CanType TypeBase::getCanonicalType() {
11241145
// Transform the input and result types.
11251146
auto &ctx = function->getInput()->getASTContext();
11261147
auto &mod = *ctx.TheBuiltinModule;
1127-
Type inputTy = function->getInput()->getCanonicalType(sig, mod);
1128-
if (!AnyFunctionType::isCanonicalFunctionInputType(inputTy)) {
1129-
auto flags = ParameterTypeFlags().withInOut(inputTy->is<InOutType>());
1130-
if (auto parenTy = dyn_cast<ParenType>(function->getInput().getPointer()))
1131-
flags = flags.withShared(parenTy->getParameterFlags().isShared());
1132-
inputTy = ParenType::get(ctx, inputTy->getInOutObjectType(), flags);
1133-
}
1148+
auto inputTy = getCanonicalInputType(function, [&](Type type) -> CanType {
1149+
return type->getCanonicalType(sig, mod);
1150+
});
11341151
auto resultTy = function->getResult()->getCanonicalType(sig, mod);
1135-
11361152
Result = GenericFunctionType::get(sig, inputTy, resultTy,
11371153
function->getExtInfo());
11381154
assert(Result->isCanonical());
@@ -1146,14 +1162,8 @@ CanType TypeBase::getCanonicalType() {
11461162

11471163
case TypeKind::Function: {
11481164
FunctionType *FT = cast<FunctionType>(this);
1149-
Type In = FT->getInput()->getCanonicalType();
1150-
if (!AnyFunctionType::isCanonicalFunctionInputType(In)) {
1151-
auto flags = ParameterTypeFlags().withInOut(In->is<InOutType>());
1152-
if (auto parenTy = dyn_cast<ParenType>(FT->getInput().getPointer()))
1153-
flags = flags.withShared(parenTy->getParameterFlags().isShared());
1154-
In = ParenType::get(In->getASTContext(), In->getInOutObjectType(), flags);
1155-
assert(AnyFunctionType::isCanonicalFunctionInputType(In));
1156-
}
1165+
auto In = getCanonicalInputType(
1166+
FT, [](Type type) -> CanType { return type->getCanonicalType(); });
11571167
Type Out = FT->getResult()->getCanonicalType();
11581168
Result = FunctionType::get(In, Out, FT->getExtInfo());
11591169
break;

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func f8<T:P2>(_ n: T, _ f: @escaping (T) -> T) {}
9797
f8(3, f4) // expected-error {{in argument type '(Int) -> Int', 'Int' does not conform to expected type 'P2'}}
9898
typealias Tup = (Int, Double)
9999
func f9(_ x: Tup) -> Tup { return x }
100-
f8((1,2.0), f9) // expected-error {{in argument type '(Tup) -> Tup' (aka '(Int, Double) -> (Int, Double)'), 'Tup' (aka '(Int, Double)') does not conform to expected type 'P2'}}
100+
f8((1,2.0), f9) // expected-error {{in argument type '(Tup) -> Tup' (aka '((Int, Double)) -> (Int, Double)'), 'Tup' (aka '(Int, Double)') does not conform to expected type 'P2'}}
101101

102102
// <rdar://problem/19658691> QoI: Incorrect diagnostic for calling nonexistent members on literals
103103
1.doesntExist(0) // expected-error {{value of type 'Int' has no member 'doesntExist'}}

0 commit comments

Comments
 (0)