@@ -3440,50 +3440,13 @@ DependentMemberType *DependentMemberType::get(Type base,
3440
3440
3441
3441
OpaqueTypeArchetypeType *
3442
3442
OpaqueTypeArchetypeType::get (OpaqueTypeDecl *Decl,
3443
- SubstitutionMap Substitutions) {
3443
+ SubstitutionMap Substitutions)
3444
+ {
3444
3445
// TODO: We could attempt to preserve type sugar in the substitution map.
3446
+ // Currently archetypes are assumed to be always canonical in many places,
3447
+ // though, so doing so would require fixing those places.
3445
3448
Substitutions = Substitutions.getCanonical ();
3446
-
3447
- // TODO: Eventually an opaque archetype ought to be arbitrarily substitutable
3448
- // into any generic environment. However, there isn't currently a good way to
3449
- // do this with GenericSignatureBuilder; in a situation like this:
3450
- //
3451
- // __opaque_type Foo<t_0_0: P>: Q // internal signature <t_0_0: P, t_1_0: Q>
3452
- //
3453
- // func bar<t_0_0, t_0_1, t_0_2: P>() -> Foo<t_0_2>
3454
- //
3455
- // we'd want to feed the GSB constraints to form:
3456
- //
3457
- // <t_0_0: P, t_1_0: Q where t_0_0 == t_0_2>
3458
- //
3459
- // even though t_0_2 isn't *in* this generic signature; it represents a type
3460
- // bound elsewhere from some other generic context. If we knew the generic
3461
- // environment `t_0_2` came from, then maybe we could map it into that context,
3462
- // but currently we have no way to know that with certainty.
3463
- //
3464
- // For now, opaque types cannot propagate across decls; every declaration
3465
- // with an opaque type has a unique opaque decl. Therefore, the only
3466
- // expressions involving opaque types ought to be contextualized inside
3467
- // function bodies, and the only time we need an opaque interface type should
3468
- // be for the opaque decl itself and the originating decl with the opaque
3469
- // result type, in which case the interface type mapping is identity and
3470
- // this problem can be temporarily avoided.
3471
- #ifndef NDEBUG
3472
- for (unsigned i : indices (Substitutions.getReplacementTypes ())) {
3473
- auto replacement = Substitutions.getReplacementTypes ()[i];
3474
-
3475
- if (!replacement->hasTypeParameter ())
3476
- continue ;
3477
-
3478
- auto replacementParam = replacement->getAs <GenericTypeParamType>();
3479
- if (!replacementParam)
3480
- llvm_unreachable (" opaque types cannot currently be parameterized by non-identity type parameter mappings" );
3481
-
3482
- assert (i == Decl->getGenericSignature ()->getGenericParamOrdinal (replacementParam)
3483
- && " opaque types cannot currently be parameterized by non-identity type parameter mappings" );
3484
- }
3485
- #endif
3486
-
3449
+
3487
3450
llvm::FoldingSetNodeID id;
3488
3451
Profile (id, Decl, Substitutions);
3489
3452
@@ -3517,7 +3480,34 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl,
3517
3480
// decl have all been same-type-bound to the arguments from our substitution
3518
3481
// map.
3519
3482
GenericSignatureBuilder builder (ctx);
3483
+
3520
3484
builder.addGenericSignature (Decl->getOpaqueInterfaceGenericSignature ());
3485
+ // TODO: The proper thing to do to build the environment in which the opaque
3486
+ // type's archetype exists would be to take the generic signature of the
3487
+ // decl, feed it into a GenericSignatureBuilder, then add same-type
3488
+ // constraints into the builder to bind the outer generic parameters
3489
+ // to their substituted types provided by \c Substitutions. However,
3490
+ // this is problematic for interface types. In a situation like this:
3491
+ //
3492
+ // __opaque_type Foo<t_0_0: P>: Q // internal signature <t_0_0: P, t_1_0: Q>
3493
+ //
3494
+ // func bar<t_0_0, t_0_1, t_0_2: P>() -> Foo<t_0_2>
3495
+ //
3496
+ // we'd want to feed the GSB constraints to form:
3497
+ //
3498
+ // <t_0_0: P, t_1_0: Q where t_0_0 == t_0_2>
3499
+ //
3500
+ // even though t_0_2 isn't *in* the generic signature being built; it
3501
+ // represents a type
3502
+ // bound elsewhere from some other generic context. If we knew the generic
3503
+ // environment `t_0_2` came from, then maybe we could map it into that context,
3504
+ // but currently we have no way to know that with certainty.
3505
+ //
3506
+ // Because opaque types are currently limited so that they only have immediate
3507
+ // protocol constraints, and therefore don't interact with the outer generic
3508
+ // parameters at all, we can get away without adding these constraints for now.
3509
+ // Adding where clauses would break this hack.
3510
+ #if DO_IT_CORRECTLY
3521
3511
// Same-type-constrain the arguments in the outer signature to their
3522
3512
// replacements in the substitution map.
3523
3513
if (auto outerSig = Decl->getGenericSignature ()) {
@@ -3529,7 +3519,24 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl,
3529
3519
[](Type, Type) { llvm_unreachable (" error?" ); });
3530
3520
}
3531
3521
}
3532
-
3522
+ #else
3523
+ // Assert that there are no same type constraints on the underlying type.
3524
+ // or its associated types.
3525
+ //
3526
+ // This should not be possible until we add where clause support.
3527
+ # ifndef NDEBUG
3528
+ for (auto reqt :
3529
+ Decl->getOpaqueInterfaceGenericSignature ()->getRequirements ()) {
3530
+ auto reqtBase = reqt.getFirstType ()->getRootGenericParam ();
3531
+ if (reqtBase->isEqual (Decl->getUnderlyingInterfaceType ())) {
3532
+ assert (reqt.getKind () != RequirementKind::SameType
3533
+ && " supporting where clauses on opaque types requires correctly "
3534
+ " setting up the generic environment for "
3535
+ " OpaqueTypeArchetypeTypes; see comment above" );
3536
+ }
3537
+ }
3538
+ # endif
3539
+ #endif
3533
3540
auto signature = std::move (builder)
3534
3541
.computeGenericSignature (SourceLoc ());
3535
3542
0 commit comments