Skip to content

Commit 40aa87c

Browse files
committed
Sema: Clean up checkGenericArguments() a bit
1 parent e0b8de4 commit 40aa87c

File tree

3 files changed

+72
-72
lines changed

3 files changed

+72
-72
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ void ParentConditionalConformance::diagnoseConformanceStack(
216216
ArrayRef<ParentConditionalConformance> conformances) {
217217
for (auto history : llvm::reverse(conformances)) {
218218
diags.diagnose(loc, diag::requirement_implied_by_conditional_conformance,
219-
history.ConformingType, history.Protocol);
219+
history.ConformingType, history.Protocol->getDeclaredInterfaceType());
220220
}
221221
}
222222

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,12 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
774774
auto req = rawReq;
775775
if (current.Parents.empty()) {
776776
auto substed = rawReq.subst(
777-
substitutions,
777+
[&](SubstitutableType *type) -> Type {
778+
auto substType = substitutions(type);
779+
if (substType->hasTypeParameter())
780+
return dc->mapTypeIntoContext(substType);
781+
return substType;
782+
},
778783
LookUpConformanceInModule(module),
779784
options);
780785
if (!substed) {
@@ -786,105 +791,100 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
786791
req = *substed;
787792
}
788793

789-
auto kind = req.getKind();
790-
Type rawFirstType = rawReq.getFirstType();
791-
Type firstType = req.getFirstType();
792-
if (firstType->hasTypeParameter())
793-
firstType = dc->mapTypeIntoContext(firstType);
794-
795-
Type rawSecondType, secondType;
796-
if (kind != RequirementKind::Layout) {
797-
rawSecondType = rawReq.getSecondType();
798-
secondType = req.getSecondType();
799-
if (secondType->hasTypeParameter())
800-
secondType = dc->mapTypeIntoContext(secondType);
801-
}
802-
803-
// Don't do further checking on error types.
804-
if (firstType->hasError() || (secondType && secondType->hasError())) {
805-
// Another requirement will fail later; just continue.
806-
valid = false;
807-
continue;
808-
}
794+
auto checkRequirement = [&]() {
795+
switch (req.getKind()) {
796+
case RequirementKind::Conformance: {
797+
// Protocol conformance requirements.
798+
auto proto = req.getProtocolDecl();
799+
auto conformance = module->lookupConformance(
800+
req.getFirstType(), proto);
809801

810-
bool requirementFailure = false;
802+
if (!conformance)
803+
return false;
811804

812-
Diag<Type, Type, Type> diagnostic;
813-
Diag<Type, Type, StringRef> diagnosticNote;
814-
815-
switch (kind) {
816-
case RequirementKind::Conformance: {
817-
// Protocol conformance requirements.
818-
auto proto = secondType->castTo<ProtocolType>();
819-
auto conformance = module->lookupConformance(firstType, proto->getDecl());
820-
821-
if (conformance) {
822805
auto conditionalReqs = conformance.getConditionalRequirements();
823806
if (!conditionalReqs.empty()) {
824807
auto history = current.Parents;
825-
history.push_back({firstType, proto});
808+
history.push_back({req.getFirstType(), proto});
826809
pendingReqs.push_back({conditionalReqs, std::move(history)});
827810
}
828-
continue;
811+
812+
return true;
829813
}
830814

831-
if (loc.isValid())
832-
diagnoseConformanceFailure(firstType, proto->getDecl(), module, loc);
815+
case RequirementKind::Layout: {
816+
// TODO: Statically check other layout constraints, once they can
817+
// be spelled in Swift.
818+
if (req.getLayoutConstraint()->isClass() &&
819+
!req.getFirstType()->satisfiesClassConstraint())
820+
return false;
833821

834-
if (current.Parents.empty())
835-
return RequirementCheckResult::Failure;
822+
return true;
823+
}
836824

837-
// Failure needs to emit a diagnostic.
838-
diagnostic = diag::type_does_not_conform_owner;
839-
diagnosticNote = diag::type_does_not_inherit_or_conform_requirement;
840-
requirementFailure = true;
841-
break;
842-
}
825+
case RequirementKind::Superclass:
826+
return req.getSecondType()->isExactSuperclassOf(req.getFirstType());
827+
828+
case RequirementKind::SameType:
829+
return req.getFirstType()->isEqual(req.getSecondType());
830+
}
831+
};
832+
833+
if (checkRequirement())
834+
continue;
835+
836+
if (loc.isValid()) {
837+
Diag<Type, Type, Type> diagnostic;
838+
Diag<Type, Type, StringRef> diagnosticNote;
839+
840+
switch (req.getKind()) {
841+
case RequirementKind::Conformance: {
842+
diagnoseConformanceFailure(req.getFirstType(), req.getProtocolDecl(),
843+
module, loc);
844+
845+
if (current.Parents.empty())
846+
return RequirementCheckResult::Failure;
847+
848+
diagnostic = diag::type_does_not_conform_owner;
849+
diagnosticNote = diag::type_does_not_inherit_or_conform_requirement;
850+
break;
851+
}
843852

844-
case RequirementKind::Layout:
845-
// TODO: Statically check other layout constraints, once they can
846-
// be spelled in Swift.
847-
if (req.getLayoutConstraint()->isClass() &&
848-
!firstType->satisfiesClassConstraint()) {
853+
case RequirementKind::Layout:
849854
diagnostic = diag::type_is_not_a_class;
850855
diagnosticNote = diag::anyobject_requirement;
851-
requirementFailure = true;
852-
}
853-
break;
856+
break;
854857

855-
case RequirementKind::Superclass: {
856-
// Superclass requirements.
857-
if (!secondType->isExactSuperclassOf(firstType)) {
858+
case RequirementKind::Superclass:
858859
diagnostic = diag::type_does_not_inherit;
859860
diagnosticNote = diag::type_does_not_inherit_or_conform_requirement;
860-
requirementFailure = true;
861-
}
862-
break;
863-
}
861+
break;
864862

865-
case RequirementKind::SameType:
866-
if (!firstType->isEqual(secondType)) {
863+
case RequirementKind::SameType:
867864
diagnostic = diag::types_not_equal;
868865
diagnosticNote = diag::types_not_equal_requirement;
869-
requirementFailure = true;
866+
break;
870867
}
871-
break;
872-
}
873868

874-
if (!requirementFailure)
875-
continue;
869+
Type rawSecondType, secondType;
870+
if (req.getKind() != RequirementKind::Layout) {
871+
rawSecondType = rawReq.getSecondType();
872+
secondType = req.getSecondType();
873+
}
876874

877-
if (loc.isValid()) {
878875
// FIXME: Poor source-location information.
879-
ctx.Diags.diagnose(loc, diagnostic, owner, firstType, secondType);
876+
ctx.Diags.diagnose(loc, diagnostic, owner,
877+
req.getFirstType(), secondType);
880878

881879
std::string genericParamBindingsText;
882880
if (!genericParams.empty()) {
883881
genericParamBindingsText =
884882
gatherGenericParamBindingsText(
885-
{rawFirstType, rawSecondType}, genericParams, substitutions);
883+
{rawReq.getFirstType(), rawSecondType},
884+
genericParams, substitutions);
886885
}
887-
ctx.Diags.diagnose(noteLoc, diagnosticNote, rawFirstType, rawSecondType,
886+
ctx.Diags.diagnose(noteLoc, diagnosticNote,
887+
rawReq.getFirstType(), rawSecondType,
888888
genericParamBindingsText);
889889

890890
ParentConditionalConformance::diagnoseConformanceStack(

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ enum class Comparison {
188188
/// formatted with \c diagnoseConformanceStack.
189189
struct ParentConditionalConformance {
190190
Type ConformingType;
191-
ProtocolType *Protocol;
191+
ProtocolDecl *Protocol;
192192

193193
/// Format the stack \c conformances as a series of notes that trace a path of
194194
/// conditional conformances that lead to some other failing requirement (that

0 commit comments

Comments
 (0)