@@ -490,47 +490,64 @@ static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type,
490
490
// info than that, unlike a typealias
491
491
}
492
492
493
+ if (!parentTy)
494
+ return ;
495
+
493
496
// If this decl is generic, the constraints are handled when the generic
494
497
// parameters are applied, so we don't have to handle them here (which makes
495
498
// getting the right substitution maps easier).
496
- if (decl && !decl->isGeneric ()) {
497
- auto extension = dyn_cast<ExtensionDecl>(decl->getDeclContext ());
498
- if (parentTy && extension && extension->isConstrainedExtension ()) {
499
- auto contextSubMap = parentTy->getContextSubstitutionMap (
500
- extension->getParentModule (),
501
- extension->getSelfNominalTypeDecl ());
502
- if (!subMap) {
503
- // The substitution map wasn't set above, meaning we should grab the map
504
- // for the extension itself.
505
- subMap = parentTy->getContextSubstitutionMap (
506
- extension->getParentModule (), extension);
507
- }
499
+ if (!decl || decl->isGeneric ())
500
+ return ;
508
501
509
- if (auto *signature = decl->getGenericSignature ()) {
510
- cs.openGenericRequirements (
511
- extension, signature, /* skipProtocolSelfConstraint*/ true , locator,
512
- [&](Type type) {
513
- // Why do we look in two substitution maps? We have to use the
514
- // context substitution map to find types, because we need to
515
- // avoid thinking about them when handling the constraints, or all
516
- // the requirements in the signature become tautologies (if the
517
- // extension has 'T == Int', subMap will map T -> Int, so the
518
- // requirement becomes Int == Int no matter what the actual types
519
- // are here). However, we need the conformances for the extension
520
- // because the requirements might look like `T: P, T.U: Q`, where
521
- // U is an associated type of protocol P.
522
- return type.subst (QuerySubstitutionMap{contextSubMap},
523
- LookUpConformanceInSubstitutionMap (subMap),
524
- SubstFlags::UseErrorType);
525
- });
526
- }
502
+ // struct A<T> {
503
+ // let foo: [T]
504
+ // }
505
+ //
506
+ // extension A : Codable where T: Codable {
507
+ // enum CodingKeys: String, CodingKey {
508
+ // case foo = "foo"
509
+ // }
510
+ // }
511
+ //
512
+ // Reference to `A.CodingKeys.foo` would point to `A` as an
513
+ // unbound generic type. Conditional requirements would be
514
+ // added when `A` is "opened". Les delay this check until then.
515
+ if (parentTy->hasUnboundGenericType ())
516
+ return ;
517
+
518
+ auto extension = dyn_cast<ExtensionDecl>(decl->getDeclContext ());
519
+ if (extension && extension->isConstrainedExtension ()) {
520
+ auto contextSubMap = parentTy->getContextSubstitutionMap (
521
+ extension->getParentModule (), extension->getSelfNominalTypeDecl ());
522
+ if (!subMap) {
523
+ // The substitution map wasn't set above, meaning we should grab the map
524
+ // for the extension itself.
525
+ subMap = parentTy->getContextSubstitutionMap (extension->getParentModule (),
526
+ extension);
527
527
}
528
528
529
- // And now make sure sure the parent is okay, for things like X<T>.Y.Z.
530
- if (parentTy) {
531
- checkNestedTypeConstraints (cs, parentTy, locator);
529
+ if (auto *signature = decl->getGenericSignature ()) {
530
+ cs.openGenericRequirements (
531
+ extension, signature, /* skipProtocolSelfConstraint*/ true , locator,
532
+ [&](Type type) {
533
+ // Why do we look in two substitution maps? We have to use the
534
+ // context substitution map to find types, because we need to
535
+ // avoid thinking about them when handling the constraints, or all
536
+ // the requirements in the signature become tautologies (if the
537
+ // extension has 'T == Int', subMap will map T -> Int, so the
538
+ // requirement becomes Int == Int no matter what the actual types
539
+ // are here). However, we need the conformances for the extension
540
+ // because the requirements might look like `T: P, T.U: Q`, where
541
+ // U is an associated type of protocol P.
542
+ return type.subst (QuerySubstitutionMap{contextSubMap},
543
+ LookUpConformanceInSubstitutionMap (subMap),
544
+ SubstFlags::UseErrorType);
545
+ });
532
546
}
533
547
}
548
+
549
+ // And now make sure sure the parent is okay, for things like X<T>.Y.Z.
550
+ checkNestedTypeConstraints (cs, parentTy, locator);
534
551
}
535
552
536
553
Type ConstraintSystem::openUnboundGenericType (
0 commit comments