@@ -85,11 +85,6 @@ struct GenericSignatureBuilder::Implementation {
85
85
// / The potential archetypes for the generic parameters in \c GenericParams.
86
86
SmallVector<PotentialArchetype *, 4 > PotentialArchetypes;
87
87
88
- // / The number of nested types that haven't yet been resolved to archetypes.
89
- // / Once all requirements have been added, this will be zero in well-formed
90
- // / code.
91
- unsigned NumUnresolvedNestedTypes = 0 ;
92
-
93
88
// / The nested types that have been renamed.
94
89
SmallVector<PotentialArchetype *, 4 > RenamedNestedTypes;
95
90
@@ -1099,9 +1094,6 @@ void GenericSignatureBuilder::PotentialArchetype::resolveAssociatedType(
1099
1094
isUnresolvedNestedType = false ;
1100
1095
identifier.assocTypeOrConcrete = assocType;
1101
1096
assert (assocType->getName () == getNestedName ());
1102
- assert (builder.Impl ->NumUnresolvedNestedTypes > 0 &&
1103
- " Mismatch in number of unresolved nested types" );
1104
- --builder.Impl ->NumUnresolvedNestedTypes ;
1105
1097
}
1106
1098
1107
1099
void GenericSignatureBuilder::PotentialArchetype::resolveConcreteType (
@@ -1111,9 +1103,6 @@ void GenericSignatureBuilder::PotentialArchetype::resolveConcreteType(
1111
1103
isUnresolvedNestedType = false ;
1112
1104
identifier.assocTypeOrConcrete = concreteDecl;
1113
1105
assert (concreteDecl->getName () == getNestedName ());
1114
- assert (builder.Impl ->NumUnresolvedNestedTypes > 0 &&
1115
- " Mismatch in number of unresolved nested types" );
1116
- --builder.Impl ->NumUnresolvedNestedTypes ;
1117
1106
}
1118
1107
1119
1108
Optional<ConcreteConstraint>
@@ -1214,8 +1203,6 @@ void EquivalenceClass::dump() const {
1214
1203
1215
1204
void GenericSignatureBuilder::recordUnresolvedType (
1216
1205
PotentialArchetype *unresolvedPA) {
1217
- ++Impl->NumUnresolvedNestedTypes ;
1218
-
1219
1206
Impl->DelayedRequirements .push_back (
1220
1207
{DelayedRequirement::Unresolved, unresolvedPA, RequirementRHS (),
1221
1208
FloatingRequirementSource::forAbstract ()});
@@ -2806,8 +2793,59 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2806
2793
return ConstraintResult::Resolved;
2807
2794
}
2808
2795
2796
+ // / Perform typo correction on the given nested type, producing the
2797
+ // / corrected name (if successful).
2798
+ static Identifier typoCorrectNestedType (
2799
+ GenericSignatureBuilder::PotentialArchetype *pa) {
2800
+ StringRef name = pa->getNestedName ().str ();
2801
+
2802
+ // Look through all of the associated types of all of the protocols
2803
+ // to which the parent conforms.
2804
+ llvm::SmallVector<Identifier, 2 > bestMatches;
2805
+ unsigned bestEditDistance = 0 ;
2806
+ unsigned maxScore = (name.size () + 1 ) / 3 ;
2807
+ for (auto proto : pa->getParent ()->getConformsTo ()) {
2808
+ for (auto member : getProtocolMembers (proto)) {
2809
+ auto assocType = dyn_cast<AssociatedTypeDecl>(member);
2810
+ if (!assocType)
2811
+ continue ;
2812
+
2813
+ unsigned dist = name.edit_distance (assocType->getName ().str (),
2814
+ /* AllowReplacements=*/ true ,
2815
+ maxScore);
2816
+ assert (dist > 0 && " nested type should have matched associated type" );
2817
+ if (bestEditDistance == 0 || dist == bestEditDistance) {
2818
+ bestEditDistance = dist;
2819
+ maxScore = bestEditDistance;
2820
+ bestMatches.push_back (assocType->getName ());
2821
+ } else if (dist < bestEditDistance) {
2822
+ bestEditDistance = dist;
2823
+ maxScore = bestEditDistance;
2824
+ bestMatches.clear ();
2825
+ bestMatches.push_back (assocType->getName ());
2826
+ }
2827
+ }
2828
+ }
2829
+
2830
+ // FIXME: Look through the superclass.
2831
+
2832
+ // If we didn't find any matches at all, fail.
2833
+ if (bestMatches.empty ())
2834
+ return Identifier ();
2835
+
2836
+ // Make sure that we didn't find more than one match at the best
2837
+ // edit distance.
2838
+ for (auto other : llvm::makeArrayRef (bestMatches).slice (1 )) {
2839
+ if (other != bestMatches.front ())
2840
+ return Identifier ();
2841
+ }
2842
+
2843
+ return bestMatches.front ();
2844
+ }
2845
+
2809
2846
ConstraintResult GenericSignatureBuilder::resolveUnresolvedType (
2810
- PotentialArchetype *pa) {
2847
+ PotentialArchetype *pa,
2848
+ bool allowTypoCorrection) {
2811
2849
// If something else resolved this type, we're done.
2812
2850
if (!pa->isUnresolved ())
2813
2851
return ConstraintResult::Resolved;
@@ -2828,8 +2866,31 @@ ConstraintResult GenericSignatureBuilder::resolveUnresolvedType(
2828
2866
return ConstraintResult::Resolved;
2829
2867
}
2830
2868
2831
- // We are unable to resolve this constraint.
2832
- return ConstraintResult::Unresolved;
2869
+ // If we aren't allowed to perform typo correction, we can't resolve the
2870
+ // constraint.
2871
+ if (!allowTypoCorrection)
2872
+ return ConstraintResult::Unresolved;
2873
+
2874
+ // Try to typo correct to a nested type name.
2875
+ Identifier correction = typoCorrectNestedType (pa);
2876
+ if (correction.empty ()) {
2877
+ pa->setInvalid ();
2878
+ return ConstraintResult::Conflicting;
2879
+ }
2880
+
2881
+ // Note that this is being renamed.
2882
+ pa->saveNameForRenaming ();
2883
+ Impl->RenamedNestedTypes .push_back (pa);
2884
+
2885
+ // Resolve the associated type and merge the potential archetypes.
2886
+ auto replacement = pa->getParent ()->getNestedType (correction, *this );
2887
+ pa->resolveAssociatedType (replacement->getResolvedAssociatedType (),
2888
+ *this );
2889
+ addSameTypeRequirement (pa, replacement,
2890
+ RequirementSource::forNestedTypeNameMatch (pa),
2891
+ UnresolvedHandlingKind::GenerateConstraints);
2892
+
2893
+ return ConstraintResult::Resolved;
2833
2894
}
2834
2895
2835
2896
ConstraintResult GenericSignatureBuilder::addLayoutRequirementDirect (
@@ -3749,56 +3810,6 @@ void GenericSignatureBuilder::inferRequirements(
3749
3810
}
3750
3811
}
3751
3812
3752
- // / Perform typo correction on the given nested type, producing the
3753
- // / corrected name (if successful).
3754
- static Identifier typoCorrectNestedType (
3755
- GenericSignatureBuilder::PotentialArchetype *pa) {
3756
- StringRef name = pa->getNestedName ().str ();
3757
-
3758
- // Look through all of the associated types of all of the protocols
3759
- // to which the parent conforms.
3760
- llvm::SmallVector<Identifier, 2 > bestMatches;
3761
- unsigned bestEditDistance = 0 ;
3762
- unsigned maxScore = (name.size () + 1 ) / 3 ;
3763
- for (auto proto : pa->getParent ()->getConformsTo ()) {
3764
- for (auto member : getProtocolMembers (proto)) {
3765
- auto assocType = dyn_cast<AssociatedTypeDecl>(member);
3766
- if (!assocType)
3767
- continue ;
3768
-
3769
- unsigned dist = name.edit_distance (assocType->getName ().str (),
3770
- /* AllowReplacements=*/ true ,
3771
- maxScore);
3772
- assert (dist > 0 && " nested type should have matched associated type" );
3773
- if (bestEditDistance == 0 || dist == bestEditDistance) {
3774
- bestEditDistance = dist;
3775
- maxScore = bestEditDistance;
3776
- bestMatches.push_back (assocType->getName ());
3777
- } else if (dist < bestEditDistance) {
3778
- bestEditDistance = dist;
3779
- maxScore = bestEditDistance;
3780
- bestMatches.clear ();
3781
- bestMatches.push_back (assocType->getName ());
3782
- }
3783
- }
3784
- }
3785
-
3786
- // FIXME: Look through the superclass.
3787
-
3788
- // If we didn't find any matches at all, fail.
3789
- if (bestMatches.empty ())
3790
- return Identifier ();
3791
-
3792
- // Make sure that we didn't find more than one match at the best
3793
- // edit distance.
3794
- for (auto other : llvm::makeArrayRef (bestMatches).slice (1 )) {
3795
- if (other != bestMatches.front ())
3796
- return Identifier ();
3797
- }
3798
-
3799
- return bestMatches.front ();
3800
- }
3801
-
3802
3813
namespace swift {
3803
3814
template <typename T>
3804
3815
bool operator <(const Constraint<T> &lhs, const Constraint<T> &rhs) {
@@ -4104,33 +4115,6 @@ GenericSignatureBuilder::finalize(SourceLoc loc,
4104
4115
}
4105
4116
}
4106
4117
}
4107
-
4108
- // If any nested types remain unresolved, produce diagnostics.
4109
- if (Impl->NumUnresolvedNestedTypes > 0 ) {
4110
- visitPotentialArchetypes ([&](PotentialArchetype *pa) {
4111
- // We only care about nested types that haven't been resolved.
4112
- if (!pa->isUnresolved ()) return ;
4113
-
4114
- // Try to typo correct to a nested type name.
4115
- Identifier correction = typoCorrectNestedType (pa);
4116
- if (correction.empty ()) {
4117
- pa->setInvalid ();
4118
- return ;
4119
- }
4120
-
4121
- // Note that this is being renamed.
4122
- pa->saveNameForRenaming ();
4123
- Impl->RenamedNestedTypes .push_back (pa);
4124
-
4125
- // Resolve the associated type and merge the potential archetypes.
4126
- auto replacement = pa->getParent ()->getNestedType (correction, *this );
4127
- pa->resolveAssociatedType (replacement->getResolvedAssociatedType (),
4128
- *this );
4129
- addSameTypeRequirement (pa, replacement,
4130
- RequirementSource::forNestedTypeNameMatch (pa),
4131
- UnresolvedHandlingKind::GenerateConstraints);
4132
- });
4133
- }
4134
4118
}
4135
4119
4136
4120
bool GenericSignatureBuilder::diagnoseRemainingRenames (
@@ -4162,12 +4146,17 @@ static GenericSignatureBuilder::UnresolvedType asUnresolvedType(
4162
4146
4163
4147
void GenericSignatureBuilder::processDelayedRequirements () {
4164
4148
bool anySolved = !Impl->DelayedRequirements .empty ();
4149
+ bool allowTypoCorrection = false ;
4165
4150
while (anySolved) {
4166
4151
// Steal the delayed requirements so we can reprocess them.
4167
4152
anySolved = false ;
4168
4153
auto delayed = std::move (Impl->DelayedRequirements );
4169
4154
Impl->DelayedRequirements .clear ();
4170
4155
4156
+ // Whether we saw any unresolve type constraints that we couldn't
4157
+ // resolve.
4158
+ bool hasUnresolvedUnresolvedTypes = false ;
4159
+
4171
4160
// Process delayed requirements.
4172
4161
for (const auto &req : delayed) {
4173
4162
// Reprocess the delayed requirement.
@@ -4192,7 +4181,9 @@ void GenericSignatureBuilder::processDelayedRequirements() {
4192
4181
break ;
4193
4182
4194
4183
case DelayedRequirement::Unresolved:
4195
- reqResult = resolveUnresolvedType (req.lhs .get <PotentialArchetype *>());
4184
+ reqResult = resolveUnresolvedType (
4185
+ req.lhs .get <PotentialArchetype *>(),
4186
+ allowTypoCorrection);
4196
4187
break ;
4197
4188
}
4198
4189
@@ -4210,9 +4201,19 @@ void GenericSignatureBuilder::processDelayedRequirements() {
4210
4201
case ConstraintResult::Unresolved:
4211
4202
// Add the requirement back.
4212
4203
Impl->DelayedRequirements .push_back (req);
4204
+
4205
+ if (req.kind == DelayedRequirement::Unresolved)
4206
+ hasUnresolvedUnresolvedTypes = true ;
4213
4207
break ;
4214
4208
}
4215
4209
}
4210
+
4211
+ // If we didn't solve anything, but we did see some unresolved types,
4212
+ // try again with typo correction enabled.
4213
+ if (!anySolved && hasUnresolvedUnresolvedTypes && !allowTypoCorrection) {
4214
+ allowTypoCorrection = true ;
4215
+ anySolved = true ;
4216
+ }
4216
4217
}
4217
4218
}
4218
4219
0 commit comments