@@ -6875,6 +6875,60 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
68756875 }
68766876 }
68776877
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+
68786932 // Handle "from specific" coercions before "catch all" coercions.
68796933 auto desugaredFromType = fromType->getDesugaredType ();
68806934 switch (desugaredFromType->getKind ()) {
@@ -7260,36 +7314,6 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
72607314 if (fromType->hasUnresolvedType () || toType->hasUnresolvedType ())
72617315 return cs.cacheType (new (ctx) UnresolvedTypeConversionExpr (expr, toType));
72627316
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-
72937317 llvm_unreachable (" Unhandled coercion" );
72947318}
72957319
0 commit comments