Skip to content

Commit 0a2cf99

Browse files
authored
Merge pull request #12304 from xedin/fix-func-input-canonicalization
[AST] Fix canonicalization of the function input types
2 parents b156fbe + 7d2e29a commit 0a2cf99

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)