@@ -1561,6 +1561,8 @@ int swift::compareDependentTypes(Type type1, Type type2) {
1561
1561
return 0 ;
1562
1562
}
1563
1563
1564
+ #pragma mark Generic signature verification
1565
+
1564
1566
void GenericSignature::verify () const {
1565
1567
auto canSig = getCanonicalSignature ();
1566
1568
@@ -1738,6 +1740,116 @@ void GenericSignature::verify() const {
1738
1740
}
1739
1741
}
1740
1742
1743
+ void swift::validateGenericSignature (ASTContext &context,
1744
+ GenericSignature sig) {
1745
+ llvm::errs () << " Validating generic signature: " ;
1746
+ sig->print (llvm::errs ());
1747
+ llvm::errs () << " \n " ;
1748
+
1749
+ // Try building a new signature having the same requirements.
1750
+ SmallVector<GenericTypeParamType *, 2 > genericParams;
1751
+ for (auto *genericParam : sig.getGenericParams ())
1752
+ genericParams.push_back (genericParam);
1753
+
1754
+ SmallVector<Requirement, 2 > requirements;
1755
+ for (auto requirement : sig.getRequirements ())
1756
+ requirements.push_back (requirement);
1757
+
1758
+ {
1759
+ PrettyStackTraceGenericSignature debugStack (" verifying" , sig);
1760
+
1761
+ auto newSigWithError = evaluateOrDefault (
1762
+ context.evaluator ,
1763
+ AbstractGenericSignatureRequest{
1764
+ nullptr ,
1765
+ genericParams,
1766
+ requirements},
1767
+ GenericSignatureWithError ());
1768
+
1769
+ // If there were any errors, the signature was invalid.
1770
+ if (newSigWithError.getInt ()) {
1771
+ context.Diags .diagnose (SourceLoc (), diag::generic_signature_not_valid,
1772
+ sig->getAsString ());
1773
+ }
1774
+
1775
+ auto newSig = newSigWithError.getPointer ();
1776
+
1777
+ // The new signature should be equal.
1778
+ if (!newSig->isEqual (sig)) {
1779
+ context.Diags .diagnose (SourceLoc (), diag::generic_signature_not_equal,
1780
+ sig->getAsString (), newSig->getAsString ());
1781
+ }
1782
+ }
1783
+
1784
+ // Try removing each requirement in turn.
1785
+ for (unsigned victimIndex : indices (requirements)) {
1786
+ PrettyStackTraceGenericSignature debugStack (" verifying" , sig, victimIndex);
1787
+
1788
+ // Add the requirements *except* the victim.
1789
+ SmallVector<Requirement, 2 > newRequirements;
1790
+ for (unsigned i : indices (requirements)) {
1791
+ if (i != victimIndex)
1792
+ newRequirements.push_back (requirements[i]);
1793
+ }
1794
+
1795
+ auto newSigWithError = evaluateOrDefault (
1796
+ context.evaluator ,
1797
+ AbstractGenericSignatureRequest{
1798
+ nullptr ,
1799
+ genericParams,
1800
+ newRequirements},
1801
+ GenericSignatureWithError ());
1802
+
1803
+ // If there were any errors, we formed an invalid signature, so
1804
+ // just continue.
1805
+ if (newSigWithError.getInt ())
1806
+ continue ;
1807
+
1808
+ auto newSig = newSigWithError.getPointer ();
1809
+
1810
+ // If the new signature once again contains the removed requirement, it's
1811
+ // not redundant.
1812
+ if (newSig->isEqual (sig))
1813
+ continue ;
1814
+
1815
+ // If the removed requirement is satisfied by the new generic signature,
1816
+ // it is redundant. Complain.
1817
+ if (newSig->isRequirementSatisfied (requirements[victimIndex])) {
1818
+ SmallString<32 > reqString;
1819
+ {
1820
+ llvm::raw_svector_ostream out (reqString);
1821
+ requirements[victimIndex].print (out, PrintOptions ());
1822
+ }
1823
+ context.Diags .diagnose (SourceLoc (), diag::generic_signature_not_minimal,
1824
+ reqString, sig->getAsString ());
1825
+ }
1826
+ }
1827
+ }
1828
+
1829
+ void swift::validateGenericSignaturesInModule (ModuleDecl *module ) {
1830
+ LoadedFile *loadedFile = nullptr ;
1831
+ for (auto fileUnit : module ->getFiles ()) {
1832
+ loadedFile = dyn_cast<LoadedFile>(fileUnit);
1833
+ if (loadedFile) break ;
1834
+ }
1835
+
1836
+ if (!loadedFile) return ;
1837
+
1838
+ // Check all of the (canonical) generic signatures.
1839
+ SmallVector<GenericSignature, 8 > allGenericSignatures;
1840
+ SmallPtrSet<CanGenericSignature, 4 > knownGenericSignatures;
1841
+ (void )loadedFile->getAllGenericSignatures (allGenericSignatures);
1842
+ ASTContext &context = module ->getASTContext ();
1843
+ for (auto genericSig : allGenericSignatures) {
1844
+ // Check whether this is the first time we've checked this (canonical)
1845
+ // signature.
1846
+ auto canGenericSig = genericSig.getCanonicalSignature ();
1847
+ if (!knownGenericSignatures.insert (canGenericSig).second ) continue ;
1848
+
1849
+ validateGenericSignature (context, canGenericSig);
1850
+ }
1851
+ }
1852
+
1741
1853
GenericSignature
1742
1854
swift::buildGenericSignature (ASTContext &ctx,
1743
1855
GenericSignature baseSignature,
0 commit comments