@@ -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
@@ -229,32 +231,44 @@ Optional<Type> ConcreteContraction::substTypeParameter(
229231 if (!substBaseType)
230232 return None;
231233
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-
240234 // A resolved DependentMemberType stores an associated type declaration.
241235 //
242236 // Handle this by looking up the corresponding type witness in the base
243237 // type's conformance to the associated type's protocol.
244238 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));
247245
248246 // The base type doesn't conform, in which case the requirement remains
249247 // unsubstituted.
250- if (!conformance)
248+ if (!conformance) {
249+ if (Debug) {
250+ llvm::dbgs () << " @@@ " << substBaseType << " does not conform to "
251+ << proto->getName () << " \n " ;
252+ }
251253 return None;
254+ }
252255
253256 return assocType->getDeclaredInterfaceType ()
254257 ->castTo <DependentMemberType>()
255258 ->substBaseType (module , *substBaseType);
256259 }
257260
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+
258272 // An unresolved DependentMemberType stores an identifier. Handle this
259273 // by performing a name lookup into the base type.
260274 auto *typeDecl = lookupConcreteNestedType (module , decl,
@@ -293,20 +307,22 @@ Type ConcreteContraction::substTypeParameter(
293307 Type concreteType;
294308 {
295309 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 () ;
298312 }
299313
300314 Type superclass;
301315 {
302316 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 () ;
305319 }
306320
307321 if (!concreteType && !superclass)
308322 return type;
309323
324+ // If we have both, prefer the concrete type requirement since it is more
325+ // specific.
310326 if (!concreteType) {
311327 assert (superclass);
312328
@@ -431,35 +447,15 @@ bool ConcreteContraction::performConcreteContraction(
431447 if (constraintType->isTypeParameter ())
432448 break ;
433449
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);
445451 break ;
446452 }
447453 case RequirementKind::Superclass: {
448454 auto constraintType = req.req .getSecondType ();
449455 assert (!constraintType->isTypeParameter () &&
450456 " You forgot to call desugarRequirement()" );
451457
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);
463459 break ;
464460 }
465461 case RequirementKind::Conformance: {
@@ -481,10 +477,10 @@ bool ConcreteContraction::performConcreteContraction(
481477 for (const auto &pair : Conformances) {
482478 auto subjectType = pair.first ;
483479 auto found = Superclasses.find (subjectType);
484- if (found == Superclasses.end ())
480+ if (found == Superclasses.end () || found-> second . size () != 1 )
485481 continue ;
486482
487- auto superclassTy = found->second ;
483+ auto superclassTy = * found->second . begin () ;
488484
489485 for (const auto *proto : pair.second ) {
490486 if (auto otherSuperclassTy = proto->getSuperclass ()) {
@@ -508,35 +504,27 @@ bool ConcreteContraction::performConcreteContraction(
508504 if (ConcreteTypes.empty () && Superclasses.empty ())
509505 return false ;
510506
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-
527507 if (Debug) {
528508 llvm::dbgs () << " @ Concrete types: @\n " ;
529509 for (auto pair : ConcreteTypes) {
530510 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+ }
533517 }
534518
535519 llvm::dbgs () << " @ Superclasses: @\n " ;
536520 for (auto pair : Superclasses) {
537521 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+ }
540528 }
541529 }
542530
0 commit comments