@@ -6875,6 +6875,60 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6875
6875
}
6876
6876
}
6877
6877
6878
+ // Use an opaque type to abstract a value of the underlying concrete type.
6879
+ // The full check here would be that `toType` and `fromType` are structurally
6880
+ // equal except in any position where `toType` has an opaque archetype. The
6881
+ // below is just an approximate check since the above would be expensive to
6882
+ // verify and still relies on the type checker ensuing `fromType` is
6883
+ // compatible with any opaque archetypes.
6884
+ if (toType->hasOpaqueArchetype () &&
6885
+ cs.getConstraintLocator (locator)->isForContextualType ()) {
6886
+ // Find the opaque type declaration. We need its generic signature.
6887
+ OpaqueTypeDecl *opaqueDecl = nullptr ;
6888
+ bool found = toType.findIf ([&](Type type) {
6889
+ if (auto opaqueType = type->getAs <OpaqueTypeArchetypeType>()) {
6890
+ opaqueDecl = opaqueType->getDecl ();
6891
+ return true ;
6892
+ }
6893
+
6894
+ return false ;
6895
+ });
6896
+ (void )found;
6897
+ assert (found && " No opaque type archetype?" );
6898
+
6899
+ // Compute the substitutions for the opaque type declaration.
6900
+ auto opaqueLocator = solution.getConstraintSystem ().getOpenOpaqueLocator (
6901
+ locator, opaqueDecl);
6902
+ SubstitutionMap substitutions = solution.computeSubstitutions (
6903
+ opaqueDecl->getOpaqueInterfaceGenericSignature (), opaqueLocator);
6904
+
6905
+ // If we don't have substitutions, this is an opaque archetype from
6906
+ // another declaration being manipulated, and not an erasure of a
6907
+ // concrete type to an opaque type inside its defining declaration.
6908
+ if (!substitutions.empty ()) {
6909
+ // Compute the underlying type by replacing all opaque archetypes with
6910
+ // the fixed type of their opened type.
6911
+ auto underlyingType = toType.subst (
6912
+ [&](SubstitutableType *type) -> Type {
6913
+ if (auto *opaqueType = type->getAs <OpaqueTypeArchetypeType>()) {
6914
+ if (opaqueType->getDecl () == opaqueDecl) {
6915
+ return opaqueType->getInterfaceType ().subst (substitutions);
6916
+ }
6917
+ }
6918
+ return type;
6919
+ },
6920
+ LookUpConformanceInModule (cs.DC ->getParentModule ()),
6921
+ SubstFlags::SubstituteOpaqueArchetypes);
6922
+
6923
+ // Coerce the result expression to the underlying type.
6924
+ // FIXME: Wrong locator?
6925
+ auto *subExpr = coerceToType (expr, underlyingType, locator);
6926
+
6927
+ return cs.cacheType (
6928
+ new (ctx) UnderlyingToOpaqueExpr (subExpr, toType, substitutions));
6929
+ }
6930
+ }
6931
+
6878
6932
// Handle "from specific" coercions before "catch all" coercions.
6879
6933
auto desugaredFromType = fromType->getDesugaredType ();
6880
6934
switch (desugaredFromType->getKind ()) {
@@ -7260,36 +7314,6 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
7260
7314
if (fromType->hasUnresolvedType () || toType->hasUnresolvedType ())
7261
7315
return cs.cacheType (new (ctx) UnresolvedTypeConversionExpr (expr, toType));
7262
7316
7263
- // Use an opaque type to abstract a value of the underlying concrete type.
7264
- // The full check here would be that `toType` and `fromType` are structurally
7265
- // equal except in any position where `toType` has an opaque archetype. The
7266
- // below is just an approximate check since the above would be expensive to
7267
- // verify and still relies on the type checker ensuing `fromType` is
7268
- // compatible with any opaque archetypes.
7269
- if (toType->hasOpaqueArchetype ()) {
7270
- // Find the opaque type declaration. We need its generic signature.
7271
- OpaqueTypeDecl *opaqueDecl = nullptr ;
7272
- bool found = toType.findIf ([&](Type type) {
7273
- if (auto opaqueType = type->getAs <OpaqueTypeArchetypeType>()) {
7274
- opaqueDecl = opaqueType->getDecl ();
7275
- return true ;
7276
- }
7277
-
7278
- return false ;
7279
- });
7280
- (void )found;
7281
- assert (found && " No opaque type archetype?" );
7282
-
7283
- // Compute the substitutions for the opaque type declaration.
7284
- auto opaqueLocator = solution.getConstraintSystem ().getOpenOpaqueLocator (
7285
- locator, opaqueDecl);
7286
- SubstitutionMap substitutions = solution.computeSubstitutions (
7287
- opaqueDecl->getOpaqueInterfaceGenericSignature (), opaqueLocator);
7288
- assert (!substitutions.empty () && " Missing substitutions for opaque type" );
7289
- return cs.cacheType (
7290
- new (ctx) UnderlyingToOpaqueExpr (expr, toType, substitutions));
7291
- }
7292
-
7293
7317
llvm_unreachable (" Unhandled coercion" );
7294
7318
}
7295
7319
0 commit comments