@@ -155,12 +155,25 @@ ValueDecl *RequirementFailure::getDeclRef() const {
155
155
auto *anchor = getRawAnchor ();
156
156
auto *locator = cs.getConstraintLocator (anchor);
157
157
158
- if (isFromContextualType ()) {
159
- auto type = cs.getContextualType ();
158
+ // Get a declaration associated with given type (if any).
159
+ // This is used to retrieve affected declaration when
160
+ // failure is in any way contextual, and declaration can't
161
+ // be fetched directly from constraint system.
162
+ auto getAffectedDeclFromType = [](Type type) -> ValueDecl * {
160
163
assert (type);
161
- auto *alias = dyn_cast<TypeAliasType>(type.getPointer ());
162
- return alias ? alias->getDecl () : type->getAnyGeneric ();
163
- }
164
+ // If problem is related to a typealias, let's point this
165
+ // diagnostic directly to its declaration without desugaring.
166
+ if (auto *alias = dyn_cast<TypeAliasType>(type.getPointer ()))
167
+ return alias->getDecl ();
168
+
169
+ if (auto *opaque = type->getAs <OpaqueTypeArchetypeType>())
170
+ return opaque->getDecl ();
171
+
172
+ return type->getAnyGeneric ();
173
+ };
174
+
175
+ if (isFromContextualType ())
176
+ return getAffectedDeclFromType (cs.getContextualType ());
164
177
165
178
if (auto *AE = dyn_cast<CallExpr>(anchor)) {
166
179
// NOTE: In valid code, the function can only be a TypeExpr
@@ -196,11 +209,7 @@ ValueDecl *RequirementFailure::getDeclRef() const {
196
209
if (overload)
197
210
return overload->choice .getDecl ();
198
211
199
- auto ownerType = getOwnerType ();
200
- if (auto *NA = dyn_cast<TypeAliasType>(ownerType.getPointer ()))
201
- return NA->getDecl ();
202
-
203
- return ownerType->getAnyGeneric ();
212
+ return getAffectedDeclFromType (getOwnerType ());
204
213
}
205
214
206
215
GenericSignature *RequirementFailure::getSignature (ConstraintLocator *locator) {
@@ -263,6 +272,28 @@ bool RequirementFailure::diagnoseAsError() {
263
272
auto lhs = resolveType (getLHS ());
264
273
auto rhs = resolveType (getRHS ());
265
274
275
+ if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
276
+ auto *namingDecl = OTD->getNamingDecl ();
277
+ emitDiagnostic (
278
+ anchor->getLoc (), diag::type_does_not_conform_in_opaque_return,
279
+ namingDecl->getDescriptiveKind (), namingDecl->getFullName (), lhs, rhs);
280
+
281
+ TypeLoc returnLoc;
282
+ if (auto *VD = dyn_cast<VarDecl>(namingDecl)) {
283
+ returnLoc = VD->getTypeLoc ();
284
+ } else if (auto *FD = dyn_cast<FuncDecl>(namingDecl)) {
285
+ returnLoc = FD->getBodyResultTypeLoc ();
286
+ } else if (auto *SD = dyn_cast<SubscriptDecl>(namingDecl)) {
287
+ returnLoc = SD->getElementTypeLoc ();
288
+ }
289
+
290
+ if (returnLoc.hasLocation ()) {
291
+ emitDiagnostic (returnLoc.getLoc (), diag::opaque_return_type_declared_here)
292
+ .highlight (returnLoc.getSourceRange ());
293
+ }
294
+ return true ;
295
+ }
296
+
266
297
if (genericCtx != reqDC && (genericCtx->isChildContextOf (reqDC) ||
267
298
isStaticOrInstanceMember (AffectedDecl))) {
268
299
auto *NTD = reqDC->getSelfNominalTypeDecl ();
0 commit comments