@@ -3103,43 +3103,57 @@ diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) {
3103
3103
// /
3104
3104
// / \returns None if there is no such constraint; a non-empty optional that
3105
3105
// / may have the \c RequirementRepr for the actual constraint.
3106
- static Optional<RequirementRepr *>
3106
+ static Optional<std::pair< RequirementRepr *, Requirement> >
3107
3107
getAdopteeSelfSameTypeConstraint (ClassDecl *selfClass, ValueDecl *witness) {
3108
3108
auto genericSig =
3109
3109
witness->getInnermostDeclContext ()->getGenericSignatureOfContext ();
3110
3110
if (!genericSig) return None;
3111
3111
3112
- for (const auto &req : genericSig->getRequirements ()) {
3112
+ // First, search for any bogus requirements.
3113
+ auto it = llvm::find_if (genericSig->getRequirements (),
3114
+ [&selfClass](const auto &req) {
3113
3115
if (req.getKind () != RequirementKind::SameType)
3114
- continue ;
3116
+ return false ;
3115
3117
3116
- if (req.getFirstType ()->getAnyNominal () == selfClass ||
3117
- req.getSecondType ()->getAnyNominal () == selfClass) {
3118
- // Try to find the requirement-as-written.
3119
- GenericParamList *genericParams = nullptr ;
3120
-
3121
- if (auto func = dyn_cast<AbstractFunctionDecl>(witness))
3122
- genericParams = func->getGenericParams ();
3123
- else if (auto subscript = dyn_cast<SubscriptDecl>(witness))
3124
- genericParams = subscript->getGenericParams ();
3125
- if (genericParams) {
3126
- for (auto &req : genericParams->getRequirements ()) {
3127
- if (req.getKind () != RequirementReprKind::SameType)
3128
- continue ;
3118
+ return req.getFirstType ()->getAnyNominal () == selfClass
3119
+ || req.getSecondType ()->getAnyNominal () == selfClass;
3120
+ });
3121
+ if (it == genericSig->getRequirements ().end ()) {
3122
+ return None;
3123
+ }
3129
3124
3130
- if (req.getFirstType ()->getAnyNominal () == selfClass ||
3131
- req.getSecondType ()->getAnyNominal () == selfClass)
3132
- return &req;
3133
- }
3134
- }
3125
+ // Got it! Now try to find the requirement-as-written.
3126
+ GenericParamList *genericParams = nullptr ;
3127
+ if (auto func = dyn_cast<AbstractFunctionDecl>(witness))
3128
+ genericParams = func->getGenericParams ();
3129
+ else if (auto subscript = dyn_cast<SubscriptDecl>(witness))
3130
+ genericParams = subscript->getGenericParams ();
3135
3131
3136
- // Form an optional(nullptr) to indicate that we don't have the
3137
- // requirement itself.
3138
- return nullptr ;
3139
- }
3132
+ // A null repr indicates we don't have a valid location to diagnose. But
3133
+ // at least we have a requirement we can signal is bogus.
3134
+ Optional<std::pair<RequirementRepr *, Requirement>> target
3135
+ = std::make_pair ((RequirementRepr *)nullptr , Requirement (*it));
3136
+ if (!genericParams) {
3137
+ return target;
3140
3138
}
3141
3139
3142
- return None;
3140
+ // Resolve and search for a written requirement to match our bogus one.
3141
+ WhereClauseOwner (cast<GenericContext>(witness), genericParams)
3142
+ .visitRequirements (TypeResolutionStage::Structural,
3143
+ [&](Requirement req, RequirementRepr *repr) {
3144
+ if (req.getKind () != RequirementKind::SameType) {
3145
+ return false ;
3146
+ }
3147
+
3148
+ if (req.getFirstType ()->getAnyNominal () != selfClass &&
3149
+ req.getSecondType ()->getAnyNominal () != selfClass) {
3150
+ return false ;
3151
+ }
3152
+
3153
+ target.emplace (repr, req);
3154
+ return true ;
3155
+ });
3156
+ return target;
3143
3157
}
3144
3158
3145
3159
void ConformanceChecker::checkNonFinalClassWitness (ValueDecl *requirement,
@@ -3239,7 +3253,7 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3239
3253
});
3240
3254
}
3241
3255
} else if (selfKind.requirement ) {
3242
- if (auto constraint = getAdopteeSelfSameTypeConstraint (classDecl,
3256
+ if (auto targetPair = getAdopteeSelfSameTypeConstraint (classDecl,
3243
3257
witness)) {
3244
3258
// A "Self ==" constraint works incorrectly with subclasses. Complain.
3245
3259
auto proto = Conformance->getProtocol ();
@@ -3254,11 +3268,11 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3254
3268
proto->getDeclaredType ());
3255
3269
emitDeclaredHereIfNeeded (diags, diagLoc, witness);
3256
3270
3257
- if (auto requirementRepr = *constraint ) {
3271
+ if (auto requirementRepr = targetPair-> first ) {
3258
3272
diags.diagnose (requirementRepr->getSeparatorLoc (),
3259
3273
diag::witness_self_weaken_same_type,
3260
- requirementRepr-> getFirstType (),
3261
- requirementRepr-> getSecondType ())
3274
+ targetPair-> second . getFirstType (),
3275
+ targetPair-> second . getSecondType ())
3262
3276
.fixItReplace (requirementRepr->getSeparatorLoc (), " :" );
3263
3277
}
3264
3278
}
0 commit comments