Skip to content

Commit 4878889

Browse files
committed
Sema: Better fix for <rdar://problem/36449760>
1 parent 3ae11e6 commit 4878889

File tree

2 files changed

+32
-57
lines changed

2 files changed

+32
-57
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,31 +1053,6 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
10531053
return { valueType, valueType };
10541054
}
10551055

1056-
static Type getInnermostConformingType(TypeChecker &TC, DeclContext *DC,
1057-
ProtocolDecl *protocol) {
1058-
do {
1059-
if (DC->isTypeContext()) {
1060-
if (protocol == DC->getAsProtocolOrProtocolExtensionContext())
1061-
return DC->mapTypeIntoContext(DC->getProtocolSelfType());
1062-
1063-
auto *NTD = DC->getAsNominalTypeOrNominalTypeExtensionContext();
1064-
auto type = NTD->getDeclaredType();
1065-
1066-
ConformanceCheckOptions options;
1067-
options |= ConformanceCheckFlags::InExpression;
1068-
options |= ConformanceCheckFlags::SuppressDependencyTracking;
1069-
options |= ConformanceCheckFlags::SkipConditionalRequirements;
1070-
1071-
auto result =
1072-
TC.conformsToProtocol(type, protocol, NTD->getDeclContext(), options);
1073-
1074-
if (result)
1075-
return DC->getDeclaredTypeInContext();
1076-
}
1077-
} while ((DC = DC->getParent()));
1078-
1079-
return nullptr;
1080-
}
10811056
/// Bind type variables for archetypes that are determined from
10821057
/// context.
10831058
///
@@ -1093,10 +1068,10 @@ static Type getInnermostConformingType(TypeChecker &TC, DeclContext *DC,
10931068
///
10941069
/// A final case we have to handle, even though it is invalid, is
10951070
/// when a type is nested inside another protocol. We bind the
1096-
/// protocol type variable for the protocol Self to its archetype
1097-
/// in protocol context. This of course makes no sense, but we
1098-
/// can't leave the type variable dangling, because then we crash
1099-
/// later.
1071+
/// protocol type variable for the protocol Self to an unresolved
1072+
/// type, since it will conform to anything. This of course makes
1073+
/// no sense, but we can't leave the type variable dangling,
1074+
/// because then we crash later.
11001075
///
11011076
/// If we ever do want to allow nominal types to be nested inside
11021077
/// protocols, the key is to set their declared type to a
@@ -1117,43 +1092,43 @@ static void bindArchetypesFromContext(
11171092

11181093
auto *genericEnv = cs.DC->getGenericEnvironmentOfContext();
11191094

1095+
auto bindContextArchetype = [&](Type paramTy, Type contextTy) {
1096+
auto found = replacements.find(cast<GenericTypeParamType>(
1097+
paramTy->getCanonicalType()));
1098+
1099+
// We might not have a type variable for this generic parameter
1100+
// because either we're opening up an UnboundGenericType,
1101+
// in which case we only want to infer the innermost generic
1102+
// parameters, or because this generic parameter was constrained
1103+
// away into a concrete type.
1104+
if (found != replacements.end()) {
1105+
auto typeVar = found->second;
1106+
cs.addConstraint(ConstraintKind::Bind, typeVar, contextTy,
1107+
locatorPtr);
1108+
}
1109+
};
1110+
1111+
// Find the innermost non-type context.
11201112
for (const auto *parentDC = outerDC;
11211113
!parentDC->isModuleScopeContext();
11221114
parentDC = parentDC->getParent()) {
1123-
if (parentDC->isTypeContext() &&
1124-
(parentDC == outerDC ||
1125-
!parentDC->getAsProtocolOrProtocolExtensionContext()))
1115+
if (parentDC->isTypeContext()) {
1116+
if (parentDC != outerDC && parentDC->getAsProtocolOrProtocolExtensionContext()) {
1117+
auto selfTy = parentDC->getSelfInterfaceType();
1118+
auto contextTy = cs.TC.Context.TheUnresolvedType;
1119+
bindContextArchetype(selfTy, contextTy);
1120+
}
11261121
continue;
1122+
}
11271123

1124+
// If it's not generic, there's nothing to do.
11281125
auto *genericSig = parentDC->getGenericSignatureOfContext();
11291126
if (!genericSig)
11301127
break;
11311128

11321129
for (auto *paramTy : genericSig->getGenericParams()) {
1133-
auto found = replacements.find(cast<GenericTypeParamType>(
1134-
paramTy->getCanonicalType()));
1135-
1136-
// We might not have a type variable for this generic parameter
1137-
// because either we're opening up an UnboundGenericType,
1138-
// in which case we only want to infer the innermost generic
1139-
// parameters, or because this generic parameter was constrained
1140-
// away into a concrete type.
1141-
if (found != replacements.end()) {
1142-
Type contextTy;
1143-
1144-
if (genericEnv) {
1145-
contextTy = genericEnv->mapTypeIntoContext(paramTy);
1146-
} else {
1147-
auto *protocol = parentDC->getAsProtocolOrProtocolExtensionContext();
1148-
contextTy = getInnermostConformingType(cs.TC, cs.DC, protocol);
1149-
}
1150-
1151-
assert(contextTy);
1152-
1153-
auto typeVar = found->second;
1154-
cs.addConstraint(ConstraintKind::Bind, typeVar, contextTy,
1155-
locatorPtr);
1156-
}
1130+
Type contextTy = genericEnv->mapTypeIntoContext(paramTy);
1131+
bindContextArchetype(paramTy, contextTy);
11571132
}
11581133

11591134
break;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
protocol P}{{{<(}}}{}extension P{class a{func<(t:a

0 commit comments

Comments
 (0)