@@ -178,93 +178,129 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
178
178
? outerGenericSignature.getGenericParams ().back ()->getDepth () + 1
179
179
: 0 ;
180
180
181
- SmallVector<GenericTypeParamType *, 2 > genericParamTypes;
182
- SmallVector<Requirement, 2 > requirements;
183
-
184
- auto opaqueReprs = collectOpaqueReturnTypeReprs (repr);
185
- if (opaqueReprs.size () > 1 ) {
186
- ctx.Diags .diagnose (repr->getLoc (), diag::more_than_one_opaque_type, repr);
187
- return nullptr ;
188
- }
189
-
190
- // TODO [OPAQUE SUPPORT]: right now we only allow one structural 'some' type,
191
- // but *very* soon we will allow more than one such type.
192
- for (unsigned i = 0 ; i < opaqueReprs.size (); ++i) {
193
- auto *currentRepr = opaqueReprs[i];
194
-
195
- // Usually, we resolve the opaque constraint and bail if it isn't a class or
196
- // existential type (see below). However, in this case we know we will fail,
197
- // so we can bail early and provide a better diagnostic.
198
- if (auto *optionalRepr =
199
- dyn_cast<OptionalTypeRepr>(currentRepr->getConstraint ())) {
200
- std::string buf;
201
- llvm::raw_string_ostream stream (buf);
202
- stream << " (some " << optionalRepr->getBase () << " )?" ;
203
-
204
- ctx.Diags .diagnose (currentRepr->getLoc (),
205
- diag::opaque_type_invalid_constraint);
206
- ctx.Diags
207
- .diagnose (currentRepr->getLoc (), diag::opaque_of_optional_rewrite)
208
- .fixItReplaceChars (currentRepr->getStartLoc (),
209
- currentRepr->getEndLoc (), stream.str ());
181
+ // Determine the context of the opaque type declaration we'll be creating.
182
+ auto parentDC = originatingDecl->getDeclContext ();
183
+ auto originatingGenericContext = originatingDecl->getAsGenericContext ();
184
+ GenericParamList *genericParams;
185
+ GenericSignature interfaceSignature;
186
+
187
+ // FIXME: The generic parameter that serves as the underlying type of the
188
+ // opaque result type. This should become unnecessary, once we have fully
189
+ // implemented structural opaque result types.
190
+ GenericTypeParamType *underlyingGenericParamType;
191
+
192
+ CollectedOpaqueReprs opaqueReprs;
193
+ if (auto namedOpaque = dyn_cast<NamedOpaqueReturnTypeRepr>(repr)) {
194
+ // Produce the generic signature for the opaque type.
195
+ genericParams = namedOpaque->getGenericParams ();
196
+ genericParams->setDepth (opaqueSignatureDepth);
197
+
198
+ InferredGenericSignatureRequest request{
199
+ originatingDC->getParentModule (),
200
+ outerGenericSignature.getPointer (),
201
+ genericParams,
202
+ WhereClauseOwner (originatingDC, genericParams),
203
+ /* addedRequirements=*/ {},
204
+ /* inferenceSources=*/ {},
205
+ /* allowConcreteGenericParams=*/ false };
206
+
207
+ interfaceSignature = evaluateOrDefault (
208
+ ctx.evaluator , request, GenericSignatureWithError ())
209
+ .getPointer ();
210
+ if (!interfaceSignature) {
211
+ // Already produced an error.
210
212
return nullptr ;
211
213
}
212
214
213
- auto *paramType = GenericTypeParamType::get (/* type sequence*/ false ,
214
- opaqueSignatureDepth, i, ctx);
215
- genericParamTypes.push_back (paramType);
216
-
217
- // Try to resolve the constraint repr in the parent decl context. It should
218
- // be some kind of existential type. Pass along the error type if resolving
219
- // the repr failed.
220
- auto constraintType = TypeResolution::forInterface (
221
- dc, TypeResolverContext::GenericRequirement,
222
- // Unbound generics and placeholders are
223
- // meaningless in opaque types.
224
- /* unboundTyOpener*/ nullptr ,
225
- /* placeholderHandler*/ nullptr )
226
- .resolveType (currentRepr->getConstraint ());
227
-
228
- if (constraintType->hasError ())
229
- return nullptr ;
230
-
231
- // Error out if the constraint type isn't a class or existential type.
232
- if (!constraintType->getClassOrBoundGenericClass () &&
233
- !constraintType->isExistentialType ()) {
234
- ctx.Diags .diagnose (currentRepr->getLoc (),
235
- diag::opaque_type_invalid_constraint);
215
+ underlyingGenericParamType = interfaceSignature.getGenericParams ()[0 ];
216
+ } else {
217
+ opaqueReprs = collectOpaqueReturnTypeReprs (repr);
218
+ if (opaqueReprs.size () > 1 ) {
219
+ ctx.Diags .diagnose (repr->getLoc (), diag::more_than_one_opaque_type, repr);
236
220
return nullptr ;
237
221
}
238
222
239
- if (constraintType->hasArchetype ())
240
- constraintType = constraintType->mapTypeOutOfContext ();
223
+ // TODO [OPAQUE SUPPORT]: right now we only allow one structural 'some' type,
224
+ // but *very* soon we will allow more than one such type.
225
+ SmallVector<GenericTypeParamType *, 2 > genericParamTypes;
226
+ SmallVector<Requirement, 2 > requirements;
227
+ for (unsigned i = 0 ; i < opaqueReprs.size (); ++i) {
228
+ auto *currentRepr = opaqueReprs[i];
229
+
230
+ // Usually, we resolve the opaque constraint and bail if it isn't a class
231
+ // or existential type (see below). However, in this case we know we will
232
+ // fail, so we can bail early and provide a better diagnostic.
233
+ if (auto *optionalRepr =
234
+ dyn_cast<OptionalTypeRepr>(currentRepr->getConstraint ())) {
235
+ std::string buf;
236
+ llvm::raw_string_ostream stream (buf);
237
+ stream << " (some " << optionalRepr->getBase () << " )?" ;
238
+
239
+ ctx.Diags .diagnose (currentRepr->getLoc (),
240
+ diag::opaque_type_invalid_constraint);
241
+ ctx.Diags
242
+ .diagnose (currentRepr->getLoc (), diag::opaque_of_optional_rewrite)
243
+ .fixItReplaceChars (currentRepr->getStartLoc (),
244
+ currentRepr->getEndLoc (), stream.str ());
245
+ return nullptr ;
246
+ }
241
247
242
- if (constraintType->getClassOrBoundGenericClass ()) {
243
- requirements.push_back (
244
- Requirement (RequirementKind::Superclass, paramType, constraintType));
245
- } else {
246
- // In this case, the constraint type is an existential
247
- requirements.push_back (
248
- Requirement (RequirementKind::Conformance, paramType, constraintType));
248
+ auto *paramType = GenericTypeParamType::get (/* type sequence*/ false ,
249
+ opaqueSignatureDepth, i, ctx);
250
+ genericParamTypes.push_back (paramType);
251
+
252
+ // Try to resolve the constraint repr in the parent decl context. It
253
+ // should be some kind of existential type. Pass along the error type if
254
+ // resolving the repr failed.
255
+ auto constraintType = TypeResolution::forInterface (
256
+ dc, TypeResolverContext::GenericRequirement,
257
+ // Unbound generics and placeholders are
258
+ // meaningless in opaque types.
259
+ /* unboundTyOpener*/ nullptr ,
260
+ /* placeholderHandler*/ nullptr )
261
+ .resolveType (currentRepr->getConstraint ());
262
+
263
+ if (constraintType->hasError ())
264
+ return nullptr ;
265
+
266
+ // Error out if the constraint type isn't a class or existential type.
267
+ if (!constraintType->getClassOrBoundGenericClass () &&
268
+ !constraintType->isExistentialType ()) {
269
+ ctx.Diags .diagnose (currentRepr->getLoc (),
270
+ diag::opaque_type_invalid_constraint);
271
+ return nullptr ;
272
+ }
273
+
274
+ if (constraintType->hasArchetype ())
275
+ constraintType = constraintType->mapTypeOutOfContext ();
276
+
277
+ if (constraintType->getClassOrBoundGenericClass ()) {
278
+ requirements.push_back (
279
+ Requirement (RequirementKind::Superclass, paramType,
280
+ constraintType));
281
+ } else {
282
+ // In this case, the constraint type is an existential
283
+ requirements.push_back (
284
+ Requirement (RequirementKind::Conformance, paramType,
285
+ constraintType));
286
+ }
249
287
}
250
- }
251
288
252
- auto interfaceSignature = buildGenericSignature (ctx, outerGenericSignature,
253
- genericParamTypes,
254
- std::move (requirements));
289
+ interfaceSignature = buildGenericSignature (ctx, outerGenericSignature,
290
+ genericParamTypes,
291
+ std::move (requirements));
292
+ genericParams = originatingGenericContext
293
+ ? originatingGenericContext->getGenericParams ()
294
+ : nullptr ;
295
+ underlyingGenericParamType = genericParamTypes[0 ];
296
+ }
255
297
256
298
// Create the OpaqueTypeDecl for the result type.
257
- // It has the same parent context and generic environment as the originating
258
- // decl.
259
- auto parentDC = originatingDecl->getDeclContext ();
260
- auto originatingGenericContext = originatingDecl->getAsGenericContext ();
261
- GenericParamList *genericParams = originatingGenericContext
262
- ? originatingGenericContext->getGenericParams ()
263
- : nullptr ;
264
-
265
299
auto opaqueDecl = new (ctx)
266
300
OpaqueTypeDecl (originatingDecl, genericParams, parentDC,
267
- interfaceSignature, opaqueReprs[0 ], genericParamTypes[0 ]);
301
+ interfaceSignature,
302
+ opaqueReprs.empty () ? 0 : opaqueReprs[0 ],
303
+ underlyingGenericParamType);
268
304
opaqueDecl->copyFormalAccessFrom (originatingDecl);
269
305
if (auto originatingSig = originatingDC->getGenericSignatureOfContext ()) {
270
306
opaqueDecl->setGenericSignature (originatingSig);
0 commit comments