Skip to content

Commit 043faef

Browse files
committed
Sema: Fix a failure to emit a diagnostic when generic requirements aren't satisfied
In the stuctural type resolution stage we don't have enough information to check conformance and same-type requirements involving type parameters, so we would just ignore such requirements, assuming they will be checked later in the interface stage. However, there was a case where we would return an error type without emitting a diagnostic, assuming that at least one other requirement fails. If a TypeLoc has an error type we don't resolve it again in the interface type stage. So we would end up with an error type and no diagnostic. Fix this by not checking generic arguments in the structural stage at all; we will do the complete check in interface stage, where we know how to check everything and emit all the right diagnostics. Fixes <rdar://problem/45271500>.
1 parent f44973f commit 043faef

File tree

3 files changed

+13
-12
lines changed

3 files changed

+13
-12
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,6 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
824824
SmallVector<RequirementSet, 8> pendingReqs;
825825
pendingReqs.push_back({requirements, {}});
826826

827-
auto *env = dc->getGenericEnvironmentOfContext();
828827
ASTContext &ctx = dc->getASTContext();
829828
while (!pendingReqs.empty()) {
830829
auto current = pendingReqs.pop_back_val();
@@ -845,21 +844,15 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
845844
auto kind = req.getKind();
846845
Type rawFirstType = rawReq.getFirstType();
847846
Type firstType = req.getFirstType();
848-
if (firstType->hasTypeParameter()) {
849-
if (!env)
850-
continue;
851-
firstType = env->mapTypeIntoContext(firstType);
852-
}
847+
if (firstType->hasTypeParameter())
848+
firstType = dc->mapTypeIntoContext(firstType);
853849

854850
Type rawSecondType, secondType;
855851
if (kind != RequirementKind::Layout) {
856852
rawSecondType = rawReq.getSecondType();
857853
secondType = req.getSecondType();
858-
if (secondType->hasTypeParameter()) {
859-
if (!env)
860-
continue;
861-
secondType = env->mapTypeIntoContext(secondType);
862-
}
854+
if (secondType->hasTypeParameter())
855+
secondType = dc->mapTypeIntoContext(secondType);
863856
}
864857

865858
// Don't do further checking on error types.

lib/Sema/TypeCheckType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,8 @@ Type TypeChecker::applyUnboundGenericArguments(
817817
// Check the generic arguments against the requirements of the declaration's
818818
// generic signature.
819819
auto dc = resolution.getDeclContext();
820-
if (!hasTypeVariable) {
820+
if (!hasTypeVariable &&
821+
resolution.getStage() > TypeResolutionStage::Structural) {
821822
auto result =
822823
checkGenericArguments(dc, loc, noteLoc, unboundType,
823824
genericSig->getGenericParams(),

test/Generics/invalid.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,10 @@ protocol Foo {
117117
}
118118

119119
protocol Wibble : Foo where Bar.EvenMoreNonsense == Int { } // expected-error{{'EvenMoreNonsense' is not a member type of 'Self.Bar'}}
120+
121+
// rdar://45271500 - failure to emit a diagnostic
122+
enum Cat<A> {}
123+
protocol Tail { associatedtype T }
124+
struct Dog<B, C : Tail> where C.T == B {}
125+
func foo<B, A>() -> Dog<B, Cat<A>> {}
126+
// expected-error@-1 {{type 'Cat<A>' does not conform to protocol 'Tail'}}

0 commit comments

Comments
 (0)