Skip to content

Commit 7c153e8

Browse files
committed
[Sema] InvertibleAnnotationRequest: Resolve requirements only if constraint is an InverseTypeRepr
This avoid a cycle in recursive and invalid code where one of the requirements references the subject type.
1 parent 2ded8ba commit 7c153e8

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

lib/Sema/TypeCheckDecl.cpp

+32-23
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ InvertibleAnnotationRequest::evaluate(Evaluator &evaluator,
982982
result.positive.setIfUnset(Kind::Explicit, loc);
983983

984984
if (isInverseTarget(type))
985-
result.inverse.setIfUnset(Kind::Explicit, loc);
985+
result.inverse.setIfUnset(Kind::Explicit, loc);
986986
}
987987

988988
return result;
@@ -1008,38 +1008,47 @@ InvertibleAnnotationRequest::evaluate(Evaluator &evaluator,
10081008

10091009
Mark result;
10101010
// Next, scan the where clause and return the result.
1011-
WhereClauseOwner(genCtx).visitRequirements(TypeResolutionStage::Structural,
1012-
[&](Requirement req, RequirementRepr *repr) -> bool /* = stop search */ {
1013-
if (req.getKind() != RequirementKind::Conformance)
1014-
return false;
1011+
auto whereClause = genCtx->getTrailingWhereClause();
1012+
if (!whereClause)
1013+
return result;
1014+
1015+
auto requirements = whereClause->getRequirements();
1016+
for (unsigned i : indices(requirements)) {
1017+
auto requirementRepr = requirements[i];
1018+
if (requirementRepr.getKind() != RequirementReprKind::TypeConstraint)
1019+
continue;
1020+
1021+
auto *constraintRepr =
1022+
dyn_cast<InverseTypeRepr>(requirementRepr.getConstraintRepr());
1023+
if (!constraintRepr || constraintRepr->isInvalid())
1024+
continue;
1025+
1026+
auto req = evaluator(
1027+
RequirementRequest{genCtx, i, TypeResolutionStage::Structural},
1028+
[&]() {
1029+
return Requirement(RequirementKind::SameType,
1030+
ErrorType::get(ctx),
1031+
ErrorType::get(ctx));
1032+
});
1033+
1034+
if (req.hasError() || req.getKind() != RequirementKind::Conformance)
1035+
continue;
10151036

10161037
auto subject = req.getFirstType();
10171038
if (!subject->isTypeParameter())
1018-
return false;
1039+
continue;
10191040

10201041
// Skip outer params and implicit ones.
10211042
auto *param = subject->getRootGenericParam()->getDecl();
10221043
if (!param || !params.contains(param))
1023-
return false;
1024-
1025-
// Check constraint type
1026-
auto constraint = req.getSecondType();
1027-
1028-
// Found it?
1029-
if (isInverseTarget(constraint)) {
1030-
// Try to find a good location.
1031-
SourceLoc loc;
1032-
if (repr && !repr->isInvalid())
1033-
if (auto *constraintRepr = repr->getConstraintRepr())
1034-
if (!repr->isInvalid())
1035-
loc = constraintRepr->getLoc();
1044+
continue;
10361045

1037-
result.set(Kind::Inferred, loc);
1038-
return true;
1046+
if (isInverseTarget(req.getSecondType())) {
1047+
result.set(Kind::Inferred, constraintRepr->getLoc());
1048+
break;
10391049
}
1050+
}
10401051

1041-
return false;
1042-
});
10431052
return result;
10441053
};
10451054

0 commit comments

Comments
 (0)