|
30 | 30 |
|
31 | 31 | using namespace swift; |
32 | 32 |
|
33 | | -/// |
34 | | -/// Common code for generic functions, generic types |
35 | | -/// |
36 | | - |
37 | | -std::string |
38 | | -TypeChecker::gatherGenericParamBindingsText( |
39 | | - ArrayRef<Type> types, |
40 | | - TypeArrayView<GenericTypeParamType> genericParams, |
41 | | - TypeSubstitutionFn substitutions) { |
42 | | - llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams; |
43 | | - for (auto type : types) { |
44 | | - if (type.isNull()) continue; |
45 | | - |
46 | | - type.visit([&](Type type) { |
47 | | - if (auto gp = type->getAs<GenericTypeParamType>()) { |
48 | | - knownGenericParams.insert( |
49 | | - gp->getCanonicalType()->castTo<GenericTypeParamType>()); |
50 | | - } |
51 | | - }); |
52 | | - } |
53 | | - |
54 | | - if (knownGenericParams.empty()) |
55 | | - return ""; |
56 | | - |
57 | | - SmallString<128> result; |
58 | | - for (auto gp : genericParams) { |
59 | | - auto canonGP = gp->getCanonicalType()->castTo<GenericTypeParamType>(); |
60 | | - if (!knownGenericParams.count(canonGP)) |
61 | | - continue; |
62 | | - |
63 | | - if (result.empty()) |
64 | | - result += " [with "; |
65 | | - else |
66 | | - result += ", "; |
67 | | - result += gp->getName().str(); |
68 | | - result += " = "; |
69 | | - |
70 | | - auto type = substitutions(canonGP); |
71 | | - if (!type) |
72 | | - return ""; |
73 | | - |
74 | | - result += type.getString(); |
75 | | - } |
76 | | - |
77 | | - result += "]"; |
78 | | - return result.str().str(); |
79 | | -} |
80 | | - |
81 | | - |
82 | 33 | // |
83 | 34 | // Generic functions |
84 | 35 | // |
@@ -817,6 +768,61 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, |
817 | 768 | /// Checking bound generic type arguments |
818 | 769 | /// |
819 | 770 |
|
| 771 | +/// Create a text string that describes the bindings of generic parameters |
| 772 | +/// that are relevant to the given set of types, e.g., |
| 773 | +/// "[with T = Bar, U = Wibble]". |
| 774 | +/// |
| 775 | +/// \param types The types that will be scanned for generic type parameters, |
| 776 | +/// which will be used in the resulting type. |
| 777 | +/// |
| 778 | +/// \param genericParams The generic parameters to use to resugar any |
| 779 | +/// generic parameters that occur within the types. |
| 780 | +/// |
| 781 | +/// \param substitutions The generic parameter -> generic argument |
| 782 | +/// substitutions that will have been applied to these types. |
| 783 | +/// These are used to produce the "parameter = argument" bindings in the test. |
| 784 | +static std::string gatherGenericParamBindingsText( |
| 785 | + ArrayRef<Type> types, TypeArrayView<GenericTypeParamType> genericParams, |
| 786 | + TypeSubstitutionFn substitutions) { |
| 787 | + llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams; |
| 788 | + for (auto type : types) { |
| 789 | + if (type.isNull()) continue; |
| 790 | + |
| 791 | + type.visit([&](Type type) { |
| 792 | + if (auto gp = type->getAs<GenericTypeParamType>()) { |
| 793 | + knownGenericParams.insert( |
| 794 | + gp->getCanonicalType()->castTo<GenericTypeParamType>()); |
| 795 | + } |
| 796 | + }); |
| 797 | + } |
| 798 | + |
| 799 | + if (knownGenericParams.empty()) |
| 800 | + return ""; |
| 801 | + |
| 802 | + SmallString<128> result; |
| 803 | + for (auto gp : genericParams) { |
| 804 | + auto canonGP = gp->getCanonicalType()->castTo<GenericTypeParamType>(); |
| 805 | + if (!knownGenericParams.count(canonGP)) |
| 806 | + continue; |
| 807 | + |
| 808 | + if (result.empty()) |
| 809 | + result += " [with "; |
| 810 | + else |
| 811 | + result += ", "; |
| 812 | + result += gp->getName().str(); |
| 813 | + result += " = "; |
| 814 | + |
| 815 | + auto type = substitutions(canonGP); |
| 816 | + if (!type) |
| 817 | + return ""; |
| 818 | + |
| 819 | + result += type.getString(); |
| 820 | + } |
| 821 | + |
| 822 | + result += "]"; |
| 823 | + return result.str().str(); |
| 824 | +} |
| 825 | + |
820 | 826 | void TypeChecker::diagnoseRequirementFailure( |
821 | 827 | const CheckGenericArgumentsResult::RequirementFailureInfo &reqFailureInfo, |
822 | 828 | SourceLoc errorLoc, SourceLoc noteLoc, Type targetTy, |
@@ -871,9 +877,8 @@ void TypeChecker::diagnoseRequirementFailure( |
871 | 877 | ctx.Diags.diagnose(errorLoc, diagnostic, targetTy, substReq.getFirstType(), |
872 | 878 | substSecondTy); |
873 | 879 |
|
874 | | - const auto genericParamBindingsText = |
875 | | - TypeChecker::gatherGenericParamBindingsText( |
876 | | - {req.getFirstType(), secondTy}, genericParams, substitutions); |
| 880 | + const auto genericParamBindingsText = gatherGenericParamBindingsText( |
| 881 | + {req.getFirstType(), secondTy}, genericParams, substitutions); |
877 | 882 |
|
878 | 883 | ctx.Diags.diagnose(noteLoc, diagnosticNote, req.getFirstType(), secondTy, |
879 | 884 | genericParamBindingsText); |
|
0 commit comments