@@ -157,8 +157,10 @@ namespace {
157
157
class ConcreteContraction {
158
158
bool Debug;
159
159
160
- llvm::SmallDenseMap<GenericParamKey, Type> ConcreteTypes;
161
- llvm::SmallDenseMap<GenericParamKey, Type> Superclasses;
160
+ llvm::SmallDenseMap<GenericParamKey,
161
+ llvm::SmallDenseSet<Type, 1 >> ConcreteTypes;
162
+ llvm::SmallDenseMap<GenericParamKey,
163
+ llvm::SmallDenseSet<Type, 1 >> Superclasses;
162
164
llvm::SmallDenseMap<GenericParamKey,
163
165
llvm::SmallVector<ProtocolDecl *, 1 >> Conformances;
164
166
@@ -229,32 +231,44 @@ Optional<Type> ConcreteContraction::substTypeParameter(
229
231
if (!substBaseType)
230
232
return None;
231
233
232
- auto *decl = (*substBaseType)->getAnyNominal ();
233
- if (decl == nullptr ) {
234
- llvm::dbgs () << " @@@ Not a nominal type: " << *substBaseType << " \n " ;
235
- return None;
236
- }
237
-
238
- auto *module = decl->getParentModule ();
239
-
240
234
// A resolved DependentMemberType stores an associated type declaration.
241
235
//
242
236
// Handle this by looking up the corresponding type witness in the base
243
237
// type's conformance to the associated type's protocol.
244
238
if (auto *assocType = memberType->getAssocType ()) {
245
- auto conformance = module ->lookupConformance (
246
- *substBaseType, assocType->getProtocol ());
239
+ auto *proto = assocType->getProtocol ();
240
+ auto *module = proto->getParentModule ();
241
+
242
+ auto conformance = ((*substBaseType)->isTypeParameter ()
243
+ ? ProtocolConformanceRef (proto)
244
+ : module ->lookupConformance (*substBaseType, proto));
247
245
248
246
// The base type doesn't conform, in which case the requirement remains
249
247
// unsubstituted.
250
- if (!conformance)
248
+ if (!conformance) {
249
+ if (Debug) {
250
+ llvm::dbgs () << " @@@ " << substBaseType << " does not conform to "
251
+ << proto->getName () << " \n " ;
252
+ }
251
253
return None;
254
+ }
252
255
253
256
return assocType->getDeclaredInterfaceType ()
254
257
->castTo <DependentMemberType>()
255
258
->substBaseType (module , *substBaseType);
256
259
}
257
260
261
+ auto *decl = (*substBaseType)->getAnyNominal ();
262
+ if (decl == nullptr ) {
263
+ if (Debug) {
264
+ llvm::dbgs () << " @@@ Not a nominal type: " << *substBaseType << " \n " ;
265
+ }
266
+
267
+ return None;
268
+ }
269
+
270
+ auto *module = decl->getParentModule ();
271
+
258
272
// An unresolved DependentMemberType stores an identifier. Handle this
259
273
// by performing a name lookup into the base type.
260
274
auto *typeDecl = lookupConcreteNestedType (module , decl,
@@ -293,20 +307,22 @@ Type ConcreteContraction::substTypeParameter(
293
307
Type concreteType;
294
308
{
295
309
auto found = ConcreteTypes.find (key);
296
- if (found != ConcreteTypes.end ())
297
- concreteType = found->second ;
310
+ if (found != ConcreteTypes.end () && found-> second . size () == 1 )
311
+ concreteType = * found->second . begin () ;
298
312
}
299
313
300
314
Type superclass;
301
315
{
302
316
auto found = Superclasses.find (key);
303
- if (found != Superclasses.end ())
304
- superclass = found->second ;
317
+ if (found != Superclasses.end () && found-> second . size () == 1 )
318
+ superclass = * found->second . begin () ;
305
319
}
306
320
307
321
if (!concreteType && !superclass)
308
322
return type;
309
323
324
+ // If we have both, prefer the concrete type requirement since it is more
325
+ // specific.
310
326
if (!concreteType) {
311
327
assert (superclass);
312
328
@@ -431,35 +447,15 @@ bool ConcreteContraction::performConcreteContraction(
431
447
if (constraintType->isTypeParameter ())
432
448
break ;
433
449
434
- auto entry = std::make_pair (GenericParamKey (genericParam),
435
- constraintType);
436
- bool inserted = ConcreteTypes.insert (entry).second ;
437
- if (!inserted) {
438
- if (Debug) {
439
- llvm::dbgs () << " @ Concrete contraction cannot proceed: "
440
- << " duplicate concrete type requirements\n " ;
441
- }
442
- return false ;
443
- }
444
-
450
+ ConcreteTypes[GenericParamKey (genericParam)].insert (constraintType);
445
451
break ;
446
452
}
447
453
case RequirementKind::Superclass: {
448
454
auto constraintType = req.req .getSecondType ();
449
455
assert (!constraintType->isTypeParameter () &&
450
456
" You forgot to call desugarRequirement()" );
451
457
452
- auto entry = std::make_pair (GenericParamKey (genericParam),
453
- constraintType);
454
- bool inserted = Superclasses.insert (entry).second ;
455
- if (!inserted) {
456
- if (Debug) {
457
- llvm::dbgs () << " @ Concrete contraction cannot proceed: "
458
- << " duplicate superclass requirements\n " ;
459
- }
460
- return false ;
461
- }
462
-
458
+ Superclasses[GenericParamKey (genericParam)].insert (constraintType);
463
459
break ;
464
460
}
465
461
case RequirementKind::Conformance: {
@@ -481,10 +477,10 @@ bool ConcreteContraction::performConcreteContraction(
481
477
for (const auto &pair : Conformances) {
482
478
auto subjectType = pair.first ;
483
479
auto found = Superclasses.find (subjectType);
484
- if (found == Superclasses.end ())
480
+ if (found == Superclasses.end () || found-> second . size () != 1 )
485
481
continue ;
486
482
487
- auto superclassTy = found->second ;
483
+ auto superclassTy = * found->second . begin () ;
488
484
489
485
for (const auto *proto : pair.second ) {
490
486
if (auto otherSuperclassTy = proto->getSuperclass ()) {
@@ -508,35 +504,27 @@ bool ConcreteContraction::performConcreteContraction(
508
504
if (ConcreteTypes.empty () && Superclasses.empty ())
509
505
return false ;
510
506
511
- // If a generic parameter is subject to both a concrete type and superclass
512
- // requirement, bail out because we're not smart enough to figure out what's
513
- // going on.
514
- for (auto pair : ConcreteTypes) {
515
- auto subjectType = pair.first ;
516
-
517
- if (Superclasses.find (subjectType) != Superclasses.end ()) {
518
- if (Debug) {
519
- llvm::dbgs () << " @ Concrete contraction cannot proceed; "
520
- << " τ_" << subjectType.Depth << " _" << subjectType.Index
521
- << " has both a concrete type and superclass requirement" ;
522
- }
523
- return false ;
524
- }
525
- }
526
-
527
507
if (Debug) {
528
508
llvm::dbgs () << " @ Concrete types: @\n " ;
529
509
for (auto pair : ConcreteTypes) {
530
510
llvm::dbgs () << " - τ_" << pair.first .Depth
531
- << " _" << pair.first .Index << " == "
532
- << pair.second << " \n " ;
511
+ << " _" << pair.first .Index ;
512
+ if (pair.second .size () == 1 ) {
513
+ llvm::dbgs () << " == " << *pair.second .begin () << " \n " ;
514
+ } else {
515
+ llvm::dbgs () << " has duplicate concrete type requirements\n " ;
516
+ }
533
517
}
534
518
535
519
llvm::dbgs () << " @ Superclasses: @\n " ;
536
520
for (auto pair : Superclasses) {
537
521
llvm::dbgs () << " - τ_" << pair.first .Depth
538
- << " _" << pair.first .Index << " : "
539
- << pair.second << " \n " ;
522
+ << " _" << pair.first .Index ;
523
+ if (pair.second .size () == 1 ) {
524
+ llvm::dbgs () << " : " << *pair.second .begin () << " \n " ;
525
+ } else {
526
+ llvm::dbgs () << " has duplicate superclass requirements\n " ;
527
+ }
540
528
}
541
529
}
542
530
0 commit comments