@@ -157,8 +157,10 @@ namespace {
157157class ConcreteContraction {
158158 bool Debug;
159159
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;
162164 llvm::SmallDenseMap<GenericParamKey,
163165 llvm::SmallVector<ProtocolDecl *, 1 >> Conformances;
164166
@@ -296,20 +298,22 @@ Type ConcreteContraction::substTypeParameter(
296298 Type concreteType;
297299 {
298300 auto found = ConcreteTypes.find (key);
299- if (found != ConcreteTypes.end ())
300- concreteType = found->second ;
301+ if (found != ConcreteTypes.end () && found-> second . size () == 1 )
302+ concreteType = * found->second . begin () ;
301303 }
302304
303305 Type superclass;
304306 {
305307 auto found = Superclasses.find (key);
306- if (found != Superclasses.end ())
307- superclass = found->second ;
308+ if (found != Superclasses.end () && found-> second . size () == 1 )
309+ superclass = * found->second . begin () ;
308310 }
309311
310312 if (!concreteType && !superclass)
311313 return type;
312314
315+ // If we have both, prefer the concrete type requirement since it is more
316+ // specific.
313317 if (!concreteType) {
314318 assert (superclass);
315319
@@ -434,35 +438,15 @@ bool ConcreteContraction::performConcreteContraction(
434438 if (constraintType->isTypeParameter ())
435439 break ;
436440
437- auto entry = std::make_pair (GenericParamKey (genericParam),
438- constraintType);
439- bool inserted = ConcreteTypes.insert (entry).second ;
440- if (!inserted) {
441- if (Debug) {
442- llvm::dbgs () << " @ Concrete contraction cannot proceed: "
443- << " duplicate concrete type requirements\n " ;
444- }
445- return false ;
446- }
447-
441+ ConcreteTypes[GenericParamKey (genericParam)].insert (constraintType);
448442 break ;
449443 }
450444 case RequirementKind::Superclass: {
451445 auto constraintType = req.req .getSecondType ();
452446 assert (!constraintType->isTypeParameter () &&
453447 " You forgot to call desugarRequirement()" );
454448
455- auto entry = std::make_pair (GenericParamKey (genericParam),
456- constraintType);
457- bool inserted = Superclasses.insert (entry).second ;
458- if (!inserted) {
459- if (Debug) {
460- llvm::dbgs () << " @ Concrete contraction cannot proceed: "
461- << " duplicate superclass requirements\n " ;
462- }
463- return false ;
464- }
465-
449+ Superclasses[GenericParamKey (genericParam)].insert (constraintType);
466450 break ;
467451 }
468452 case RequirementKind::Conformance: {
@@ -484,10 +468,10 @@ bool ConcreteContraction::performConcreteContraction(
484468 for (const auto &pair : Conformances) {
485469 auto subjectType = pair.first ;
486470 auto found = Superclasses.find (subjectType);
487- if (found == Superclasses.end ())
471+ if (found == Superclasses.end () || found-> second . size () != 1 )
488472 continue ;
489473
490- auto superclassTy = found->second ;
474+ auto superclassTy = * found->second . begin () ;
491475
492476 for (const auto *proto : pair.second ) {
493477 if (auto otherSuperclassTy = proto->getSuperclass ()) {
@@ -511,35 +495,27 @@ bool ConcreteContraction::performConcreteContraction(
511495 if (ConcreteTypes.empty () && Superclasses.empty ())
512496 return false ;
513497
514- // If a generic parameter is subject to both a concrete type and superclass
515- // requirement, bail out because we're not smart enough to figure out what's
516- // going on.
517- for (auto pair : ConcreteTypes) {
518- auto subjectType = pair.first ;
519-
520- if (Superclasses.find (subjectType) != Superclasses.end ()) {
521- if (Debug) {
522- llvm::dbgs () << " @ Concrete contraction cannot proceed; "
523- << " τ_" << subjectType.Depth << " _" << subjectType.Index
524- << " has both a concrete type and superclass requirement" ;
525- }
526- return false ;
527- }
528- }
529-
530498 if (Debug) {
531499 llvm::dbgs () << " @ Concrete types: @\n " ;
532500 for (auto pair : ConcreteTypes) {
533501 llvm::dbgs () << " - τ_" << pair.first .Depth
534- << " _" << pair.first .Index << " == "
535- << pair.second << " \n " ;
502+ << " _" << pair.first .Index ;
503+ if (pair.second .size () == 1 ) {
504+ llvm::dbgs () << " == " << *pair.second .begin () << " \n " ;
505+ } else {
506+ llvm::dbgs () << " has duplicate concrete type requirements\n " ;
507+ }
536508 }
537509
538510 llvm::dbgs () << " @ Superclasses: @\n " ;
539511 for (auto pair : Superclasses) {
540512 llvm::dbgs () << " - τ_" << pair.first .Depth
541- << " _" << pair.first .Index << " : "
542- << pair.second << " \n " ;
513+ << " _" << pair.first .Index ;
514+ if (pair.second .size () == 1 ) {
515+ llvm::dbgs () << " : " << *pair.second .begin () << " \n " ;
516+ } else {
517+ llvm::dbgs () << " has duplicate superclass requirements\n " ;
518+ }
543519 }
544520 }
545521
0 commit comments