21
21
#include " swift/AST/GenericSignature.h"
22
22
#include " swift/AST/Types.h"
23
23
#include " llvm/ADT/ArrayRef.h"
24
+ #include " llvm/ADT/SmallString.h"
24
25
25
26
using namespace swift ;
26
27
using namespace constraints ;
@@ -122,27 +123,59 @@ const DeclContext *RequirementFailure::getRequirementDC() const {
122
123
return AffectedDecl->getAsGenericContext ();
123
124
}
124
125
126
+ bool RequirementFailure::diagnose () {
127
+ if (!canDiagnoseFailure ())
128
+ return false ;
129
+
130
+ auto *anchor = getAnchor ();
131
+ const auto *reqDC = getRequirementDC ();
132
+ auto *genericCtx = AffectedDecl->getAsGenericContext ();
133
+
134
+ if (reqDC != genericCtx) {
135
+ auto *NTD = reqDC->getAsNominalTypeOrNominalTypeExtensionContext ();
136
+ emitDiagnostic (anchor->getLoc (), getDiagnosticInRereference (),
137
+ AffectedDecl->getDescriptiveKind (),
138
+ AffectedDecl->getFullName (), NTD->getDeclaredType (),
139
+ getLHS (), getRHS ());
140
+ } else {
141
+ emitDiagnostic (anchor->getLoc (), getDiagnosticOnDecl (),
142
+ AffectedDecl->getDescriptiveKind (),
143
+ AffectedDecl->getFullName (), getLHS (), getRHS ());
144
+ }
145
+
146
+ emitRequirementNote (reqDC->getAsDeclOrDeclExtensionContext ());
147
+ return true ;
148
+ }
149
+
150
+ void RequirementFailure::emitRequirementNote (const Decl *anchor) const {
151
+ auto &req = getRequirement ();
152
+
153
+ if (getRHS ()->isEqual (req.getSecondType ())) {
154
+ emitDiagnostic (anchor, diag::where_requirement_failure_one_subst,
155
+ req.getFirstType (), getLHS ());
156
+ return ;
157
+ }
158
+
159
+ if (getLHS ()->isEqual (req.getFirstType ())) {
160
+ emitDiagnostic (anchor, diag::where_requirement_failure_one_subst,
161
+ req.getSecondType (), getRHS ());
162
+ return ;
163
+ }
164
+
165
+ emitDiagnostic (anchor, diag::where_requirement_failure_both_subst,
166
+ req.getFirstType (), getLHS (), req.getSecondType (), getRHS ());
167
+ }
168
+
125
169
bool MissingConformanceFailure::diagnose () {
170
+ if (!canDiagnoseFailure ())
171
+ return false ;
172
+
126
173
auto *anchor = getAnchor ();
127
174
auto ownerType = getOwnerType ();
128
- auto type = getNonConformingType ();
129
- auto protocolType = getProtocolType ();
130
-
131
- // Find `ApplyExpr` based on a function expression attached to it.
132
- auto findApplyExpr = [](Expr *parent, Expr *fnExpr) -> ApplyExpr * {
133
- ApplyExpr *applyExpr = nullptr ;
134
- parent->forEachChildExpr ([&applyExpr, &fnExpr](Expr *subExpr) -> Expr * {
135
- auto *AE = dyn_cast<ApplyExpr>(subExpr);
136
- if (!AE || AE->getFn () != fnExpr)
137
- return subExpr;
138
-
139
- applyExpr = AE;
140
- return nullptr ;
141
- });
142
- return applyExpr;
143
- };
175
+ auto nonConformingType = getLHS ();
176
+ auto protocolType = getRHS ();
144
177
145
- auto getArgumentAt = [](ApplyExpr *AE, unsigned index) -> Expr * {
178
+ auto getArgumentAt = [](const ApplyExpr *AE, unsigned index) -> Expr * {
146
179
assert (AE);
147
180
148
181
auto *arg = AE->getArg ();
@@ -156,66 +189,45 @@ bool MissingConformanceFailure::diagnose() {
156
189
return arg;
157
190
};
158
191
159
- auto *applyExpr = findApplyExpr (getParentExpr (), anchor);
160
-
161
192
Optional<unsigned > atParameterPos;
162
193
// Sometimes fix is recorded by type-checking sub-expression
163
194
// during normal diagnostics, in such case call expression
164
195
// is unavailable.
165
- if (applyExpr) {
166
- // If this is a static, initializer or operator call,
167
- // let's not try to diagnose it here, but refer to expression
168
- // diagnostics.
169
- if (isa<PrefixUnaryExpr>(applyExpr) || isa<PostfixUnaryExpr>(applyExpr) ||
170
- isa<BinaryExpr>(applyExpr) || isa<TypeExpr>(anchor))
171
- return false ;
172
-
196
+ if (Apply) {
173
197
if (auto *fnType = ownerType->getAs <AnyFunctionType>()) {
174
198
auto parameters = fnType->getParams ();
175
199
for (auto index : indices (parameters)) {
176
- if (parameters[index].getType ()->isEqual (type )) {
200
+ if (parameters[index].getType ()->isEqual (nonConformingType )) {
177
201
atParameterPos = index;
178
202
break ;
179
203
}
180
204
}
181
205
}
182
206
}
183
207
184
- if (type ->isExistentialType ()) {
208
+ if (nonConformingType ->isExistentialType ()) {
185
209
auto diagnostic = diag::protocol_does_not_conform_objc;
186
- if (type ->isObjCExistentialType ())
210
+ if (nonConformingType ->isObjCExistentialType ())
187
211
diagnostic = diag::protocol_does_not_conform_static;
188
212
189
- emitDiagnostic (anchor->getLoc (), diagnostic, type, protocolType);
190
- } else if (atParameterPos) {
213
+ emitDiagnostic (anchor->getLoc (), diagnostic, nonConformingType,
214
+ protocolType);
215
+ return true ;
216
+ }
217
+
218
+ if (atParameterPos) {
191
219
// Requirement comes from one of the parameter types,
192
220
// let's try to point diagnostic to the argument expression.
193
- auto *argExpr = getArgumentAt (applyExpr , *atParameterPos);
221
+ auto *argExpr = getArgumentAt (Apply , *atParameterPos);
194
222
emitDiagnostic (argExpr->getLoc (),
195
- diag::cannot_convert_argument_value_protocol, type,
196
- protocolType);
197
- } else {
198
- const auto &req = getRequirement ();
199
- auto *genericCtx = AffectedDecl->getAsGenericContext ();
200
- const auto *reqDC = getRequirementDC ();
201
-
202
- if (reqDC != genericCtx) {
203
- auto *NTD = reqDC->getAsNominalTypeOrNominalTypeExtensionContext ();
204
- emitDiagnostic (anchor->getLoc (), diag::type_does_not_conform_in_decl_ref,
205
- AffectedDecl->getDescriptiveKind (),
206
- AffectedDecl->getFullName (), NTD->getDeclaredType (), type,
207
- protocolType);
208
- } else {
209
- emitDiagnostic (anchor->getLoc (), diag::type_does_not_conform_decl_owner,
210
- AffectedDecl->getDescriptiveKind (),
211
- AffectedDecl->getFullName (), type, protocolType);
212
- }
213
-
214
- emitDiagnostic (reqDC->getAsDeclOrDeclExtensionContext (),
215
- diag::where_type_does_not_conform_type, req.getFirstType (),
216
- type);
223
+ diag::cannot_convert_argument_value_protocol,
224
+ nonConformingType, protocolType);
225
+ return true ;
217
226
}
218
- return true ;
227
+
228
+ // If none of the special cases could be diagnosed,
229
+ // let's fallback to the most general diagnostic.
230
+ return RequirementFailure::diagnose ();
219
231
}
220
232
221
233
bool LabelingFailure::diagnose () {
0 commit comments