24
24
#include " swift/AST/GenericSignature.h"
25
25
#include " swift/AST/ParameterList.h"
26
26
#include " swift/AST/Pattern.h"
27
+ #include " swift/AST/ProtocolConformance.h"
28
+ #include " swift/AST/ProtocolConformanceRef.h"
27
29
#include " swift/AST/Types.h"
28
30
#include " swift/Basic/SourceLoc.h"
29
31
#include " swift/Parse/Lexer.h"
@@ -88,19 +90,54 @@ Type RequirementFailure::getOwnerType() const {
88
90
}
89
91
90
92
const GenericContext *RequirementFailure::getGenericContext () const {
93
+ // For conditional requirements, this is easy because all
94
+ // required information is contained in the conformance
95
+ // reference.
96
+ if (isConditional ()) {
97
+ auto *conformance = getConformanceRef ().getConcrete ();
98
+ auto *DC = conformance->getDeclContext ();
99
+ return DC->getAsDecl ()->getAsGenericContext ();
100
+ }
101
+
91
102
if (auto *genericCtx = AffectedDecl->getAsGenericContext ())
92
103
return genericCtx;
93
104
return AffectedDecl->getDeclContext ()->getAsDecl ()->getAsGenericContext ();
94
105
}
95
106
96
107
const Requirement &RequirementFailure::getRequirement () const {
108
+ // If this is a conditional requirement failure we need to
109
+ // fetch conformance from constraint system associated with
110
+ // type requirement this conditional conformance belongs to.
111
+ if (isConditional ()) {
112
+ auto conformanceRef = getConformanceRef ();
113
+ return conformanceRef.getConditionalRequirements ()[getRequirementIndex ()];
114
+ }
115
+
97
116
return getGenericContext ()->getGenericRequirements ()[getRequirementIndex ()];
98
117
}
99
118
119
+ ProtocolConformanceRef RequirementFailure::getConformanceRef () const {
120
+ assert (isConditional ());
121
+
122
+ auto &cs = getConstraintSystem ();
123
+ auto *locator = getLocator ();
124
+
125
+ auto *typeReqLoc =
126
+ cs.getConstraintLocator (getRawAnchor (), locator->getPath ().drop_back (),
127
+ /* summaryFlags=*/ 0 );
128
+
129
+ auto conformance = llvm::find_if (
130
+ cs.CheckedConformances ,
131
+ [&](const std::pair<ConstraintLocator *, ProtocolConformanceRef>
132
+ &conformance) { return conformance.first == typeReqLoc; });
133
+ assert (conformance != cs.CheckedConformances .end ());
134
+ return conformance->second ;
135
+ }
136
+
100
137
ValueDecl *RequirementFailure::getDeclRef () const {
101
138
auto &cs = getConstraintSystem ();
102
139
103
- auto *anchor = getAnchor ();
140
+ auto *anchor = getRawAnchor ();
104
141
auto *locator = cs.getConstraintLocator (anchor);
105
142
if (auto *AE = dyn_cast<CallExpr>(anchor)) {
106
143
assert (isa<TypeExpr>(AE->getFn ()));
@@ -142,6 +179,13 @@ ValueDecl *RequirementFailure::getDeclRef() const {
142
179
}
143
180
144
181
const DeclContext *RequirementFailure::getRequirementDC () const {
182
+ // In case of conditional requirement failure, we don't
183
+ // have to guess where the it comes from.
184
+ if (isConditional ()) {
185
+ auto *conformance = getConformanceRef ().getConcrete ();
186
+ return conformance->getDeclContext ();
187
+ }
188
+
145
189
const auto &req = getRequirement ();
146
190
auto *DC = AffectedDecl->getDeclContext ();
147
191
@@ -159,23 +203,26 @@ bool RequirementFailure::diagnoseAsError() {
159
203
if (!canDiagnoseFailure ())
160
204
return false ;
161
205
162
- auto *anchor = getAnchor ();
206
+ auto *anchor = getRawAnchor ();
163
207
const auto *reqDC = getRequirementDC ();
164
208
auto *genericCtx = getGenericContext ();
165
209
210
+ auto lhs = resolveType (getLHS ());
211
+ auto rhs = resolveType (getRHS ());
212
+
166
213
if (reqDC != genericCtx) {
167
214
auto *NTD = reqDC->getSelfNominalTypeDecl ();
168
215
emitDiagnostic (anchor->getLoc (), getDiagnosticInRereference (),
169
216
AffectedDecl->getDescriptiveKind (),
170
- AffectedDecl->getFullName (), NTD->getDeclaredType (),
171
- getLHS (), getRHS () );
217
+ AffectedDecl->getFullName (), NTD->getDeclaredType (), lhs,
218
+ rhs );
172
219
} else {
173
220
emitDiagnostic (anchor->getLoc (), getDiagnosticOnDecl (),
174
221
AffectedDecl->getDescriptiveKind (),
175
- AffectedDecl->getFullName (), getLHS (), getRHS () );
222
+ AffectedDecl->getFullName (), lhs, rhs );
176
223
}
177
224
178
- emitRequirementNote (reqDC->getAsDecl ());
225
+ emitRequirementNote (reqDC->getAsDecl (), lhs, rhs );
179
226
return true ;
180
227
}
181
228
@@ -188,23 +235,32 @@ bool RequirementFailure::diagnoseAsNote() {
188
235
return true ;
189
236
}
190
237
191
- void RequirementFailure::emitRequirementNote (const Decl *anchor) const {
238
+ void RequirementFailure::emitRequirementNote (const Decl *anchor, Type lhs,
239
+ Type rhs) const {
192
240
auto &req = getRequirement ();
193
241
194
- if (getRHS ()->isEqual (req.getSecondType ())) {
242
+ if (isConditional ()) {
243
+ auto *conformance = getConformanceRef ().getConcrete ();
244
+ emitDiagnostic (anchor, diag::requirement_implied_by_conditional_conformance,
245
+ resolveType (conformance->getType ()),
246
+ conformance->getProtocol ()->getDeclaredInterfaceType ());
247
+ return ;
248
+ }
249
+
250
+ if (rhs->isEqual (req.getSecondType ())) {
195
251
emitDiagnostic (anchor, diag::where_requirement_failure_one_subst,
196
- req.getFirstType (), getLHS () );
252
+ req.getFirstType (), lhs );
197
253
return ;
198
254
}
199
255
200
- if (getLHS () ->isEqual (req.getFirstType ())) {
256
+ if (lhs ->isEqual (req.getFirstType ())) {
201
257
emitDiagnostic (anchor, diag::where_requirement_failure_one_subst,
202
- req.getSecondType (), getRHS () );
258
+ req.getSecondType (), rhs );
203
259
return ;
204
260
}
205
261
206
262
emitDiagnostic (anchor, diag::where_requirement_failure_both_subst,
207
- req.getFirstType (), getLHS () , req.getSecondType (), getRHS () );
263
+ req.getFirstType (), lhs , req.getSecondType (), rhs );
208
264
}
209
265
210
266
bool MissingConformanceFailure::diagnoseAsError () {
0 commit comments