@@ -774,7 +774,12 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
774
774
auto req = rawReq;
775
775
if (current.Parents .empty ()) {
776
776
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
+ },
778
783
LookUpConformanceInModule (module ),
779
784
options);
780
785
if (!substed) {
@@ -786,105 +791,100 @@ RequirementCheckResult TypeChecker::checkGenericArguments(
786
791
req = *substed;
787
792
}
788
793
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);
809
801
810
- bool requirementFailure = false ;
802
+ if (!conformance)
803
+ return false ;
811
804
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) {
822
805
auto conditionalReqs = conformance.getConditionalRequirements ();
823
806
if (!conditionalReqs.empty ()) {
824
807
auto history = current.Parents ;
825
- history.push_back ({firstType , proto});
808
+ history.push_back ({req. getFirstType () , proto});
826
809
pendingReqs.push_back ({conditionalReqs, std::move (history)});
827
810
}
828
- continue ;
811
+
812
+ return true ;
829
813
}
830
814
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 ;
833
821
834
- if (current. Parents . empty ())
835
- return RequirementCheckResult::Failure;
822
+ return true ;
823
+ }
836
824
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
+ }
843
852
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:
849
854
diagnostic = diag::type_is_not_a_class;
850
855
diagnosticNote = diag::anyobject_requirement;
851
- requirementFailure = true ;
852
- }
853
- break ;
856
+ break ;
854
857
855
- case RequirementKind::Superclass: {
856
- // Superclass requirements.
857
- if (!secondType->isExactSuperclassOf (firstType)) {
858
+ case RequirementKind::Superclass:
858
859
diagnostic = diag::type_does_not_inherit;
859
860
diagnosticNote = diag::type_does_not_inherit_or_conform_requirement;
860
- requirementFailure = true ;
861
- }
862
- break ;
863
- }
861
+ break ;
864
862
865
- case RequirementKind::SameType:
866
- if (!firstType->isEqual (secondType)) {
863
+ case RequirementKind::SameType:
867
864
diagnostic = diag::types_not_equal;
868
865
diagnosticNote = diag::types_not_equal_requirement;
869
- requirementFailure = true ;
866
+ break ;
870
867
}
871
- break ;
872
- }
873
868
874
- if (!requirementFailure)
875
- continue ;
869
+ Type rawSecondType, secondType;
870
+ if (req.getKind () != RequirementKind::Layout) {
871
+ rawSecondType = rawReq.getSecondType ();
872
+ secondType = req.getSecondType ();
873
+ }
876
874
877
- if (loc.isValid ()) {
878
875
// 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);
880
878
881
879
std::string genericParamBindingsText;
882
880
if (!genericParams.empty ()) {
883
881
genericParamBindingsText =
884
882
gatherGenericParamBindingsText (
885
- {rawFirstType, rawSecondType}, genericParams, substitutions);
883
+ {rawReq.getFirstType (), rawSecondType},
884
+ genericParams, substitutions);
886
885
}
887
- ctx.Diags .diagnose (noteLoc, diagnosticNote, rawFirstType, rawSecondType,
886
+ ctx.Diags .diagnose (noteLoc, diagnosticNote,
887
+ rawReq.getFirstType (), rawSecondType,
888
888
genericParamBindingsText);
889
889
890
890
ParentConditionalConformance::diagnoseConformanceStack (
0 commit comments