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