diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 48dd1a5b58301..b2866e493daf7 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2444,7 +2444,7 @@ class HasImplementationOnlyImportsRequest class ResolveTypeRequest : public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -2457,7 +2457,7 @@ class ResolveTypeRequest friend SimpleRequest; // Evaluation. - Type evaluate(Evaluator &evaluator, TypeResolution *resolution, + Type evaluate(Evaluator &evaluator, const TypeResolution *resolution, TypeRepr *repr) const; }; diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 2f5ee6f22796a..f9cfdb060ecf9 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -240,7 +240,8 @@ SWIFT_REQUEST(TypeChecker, ResolveTypeEraserTypeRequest, Type(ProtocolDecl *, TypeEraserAttr *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ResolveTypeRequest, - Type (TypeResolution *, TypeRepr *), Uncached, NoLocationInfo) + Type (const TypeResolution *, TypeRepr *), + Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, SPIGroupsRequest, llvm::ArrayRef(Decl *), Cached, NoLocationInfo) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index e561afbb1568b..eb79a8c795818 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1445,12 +1445,19 @@ namespace { diag::super_with_no_base_class); } - Type resolveTypeReferenceInExpression(TypeRepr *repr, - TypeResolverContext resCtx) { - TypeResolutionOptions options(resCtx); - options |= TypeResolutionFlags::AllowUnboundGenerics; - auto result = TypeResolution::forContextual(CS.DC, options) - .resolveType(repr); + Type + resolveTypeReferenceInExpression(TypeRepr *repr, TypeResolverContext resCtx, + OpenUnboundGenericTypeFn unboundTyOpener) { + if (!unboundTyOpener) { + unboundTyOpener = [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }; + } + const auto result = + TypeResolution::forContextual(CS.DC, resCtx, unboundTyOpener) + .resolveType(repr); if (result->hasError()) { return Type(); } @@ -1460,20 +1467,21 @@ namespace { Type visitTypeExpr(TypeExpr *E) { Type type; // If this is an implicit TypeExpr, don't validate its contents. + auto *const locator = CS.getConstraintLocator(E); if (E->isImplicit()) { type = CS.getInstanceType(CS.cacheType(E)); assert(type && "Implicit type expr must have type set!"); + type = CS.openUnboundGenericTypes(type, locator); } else { auto *repr = E->getTypeRepr(); assert(repr && "Explicit node has no type repr!"); type = resolveTypeReferenceInExpression( - repr, TypeResolverContext::InExpression); + repr, TypeResolverContext::InExpression, + OpenUnboundGenericType(CS, locator)); } if (!type || type->hasError()) return Type(); - - auto locator = CS.getConstraintLocator(E); - type = CS.openUnboundGenericTypes(type, locator); + return MetatypeType::get(type); } @@ -1711,12 +1719,15 @@ namespace { // Bind the specified generic arguments to the type variables in the // open type. - auto locator = CS.getConstraintLocator(expr); + auto *const locator = CS.getConstraintLocator(expr); + const auto options = + TypeResolutionOptions(TypeResolverContext::InExpression); for (size_t i = 0, size = specializations.size(); i < size; ++i) { - TypeResolutionOptions options(TypeResolverContext::InExpression); - options |= TypeResolutionFlags::AllowUnboundGenerics; - auto result = TypeResolution::forContextual(CS.DC, options) - .resolveType(specializations[i]); + const auto resolution = TypeResolution::forContextual( + CS.DC, options, + // Introduce type variables for unbound generics. + OpenUnboundGenericType(CS, locator)); + const auto result = resolution.resolveType(specializations[i]); if (result->hasError()) return Type(); @@ -2190,7 +2201,7 @@ namespace { return resolveTypeReferenceInExpression( closure->getExplicitResultTypeRepr(), - TypeResolverContext::InExpression); + TypeResolverContext::InExpression, nullptr); }; Type resultTy; @@ -2493,17 +2504,12 @@ namespace { case PatternKind::Is: { auto isPattern = cast(pattern); - Type castType = resolveTypeReferenceInExpression( - isPattern->getCastTypeRepr(), TypeResolverContext::InExpression); - - if (!castType) - return Type(); - - castType = CS.openUnboundGenericTypes( - castType, - locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); - - assert(castType); + const Type castType = resolveTypeReferenceInExpression( + isPattern->getCastTypeRepr(), TypeResolverContext::InExpression, + OpenUnboundGenericType(CS, + locator.withPathElement( + LocatorPathElt::PatternMatch(pattern)))); + if (!castType) return Type(); auto *subPattern = isPattern->getSubPattern(); Type subPatternType = getTypeForPattern( @@ -2559,7 +2565,14 @@ namespace { } return resolveTypeReferenceInExpression( enumPattern->getParentTypeRepr(), - TypeResolverContext::InExpression); + TypeResolverContext::InExpression, [](auto unboundTy) { + // FIXME: We ought to pass an OpenUnboundGenericType object + // rather than calling CS.openUnboundGenericType below, but + // sometimes the parent type is resolved eagerly in + // ResolvePattern::visitUnresolvedDotExpr, letting unbound + // generics escape. + return unboundTy; + }); }(); if (!parentType) @@ -2725,9 +2738,10 @@ namespace { // of is-patterns applied to an irrefutable pattern. pattern = pattern->getSemanticsProvidingPattern(); while (auto isp = dyn_cast(pattern)) { - Type castType = TypeResolution::forContextual( - CS.DC, TypeResolverContext::InExpression) - .resolveType(isp->getCastTypeRepr()); + const Type castType = TypeResolution::forContextual( + CS.DC, TypeResolverContext::InExpression, + /*unboundTyOpener*/ nullptr) + .resolveType(isp->getCastTypeRepr()); if (castType->hasError()) { return false; } @@ -3051,14 +3065,14 @@ namespace { auto *const repr = expr->getCastTypeRepr(); // Validate the resulting type. - const auto type = resolveTypeReferenceInExpression( - repr, TypeResolverContext::ExplicitCastExpr); - if (!type) + const auto toType = resolveTypeReferenceInExpression( + repr, TypeResolverContext::ExplicitCastExpr, + // Introduce type variables for unbound generics. + OpenUnboundGenericType(CS, CS.getConstraintLocator(expr))); + if (!toType) return nullptr; - // Open the type we're casting to. - const auto toType = - CS.openUnboundGenericTypes(type, CS.getConstraintLocator(expr)); + // Cache the type we're casting to. if (repr) CS.setType(repr, toType); auto fromType = CS.getType(fromExpr); @@ -3079,7 +3093,14 @@ namespace { // Validate the resulting type. auto *const repr = expr->getCastTypeRepr(); const auto type = resolveTypeReferenceInExpression( - repr, TypeResolverContext::ExplicitCastExpr); + repr, TypeResolverContext::ExplicitCastExpr, [](auto unboundTy) { + // FIXME: We ought to pass an OpenUnboundGenericType object rather + // than calling CS.openUnboundGenericType after resolving, but + // sometimes the type expression is resolved eagerly in + // PreCheckExpression::simplifyTypeConstructionWithLiteralArg, + // letting unbound generics escape. + return unboundTy; + }); if (!type) return nullptr; @@ -3111,14 +3132,14 @@ namespace { // Validate the resulting type. auto *const repr = expr->getCastTypeRepr(); - const auto type = resolveTypeReferenceInExpression( - repr, TypeResolverContext::ExplicitCastExpr); - if (!type) + const auto toType = resolveTypeReferenceInExpression( + repr, TypeResolverContext::ExplicitCastExpr, + // Introduce type variables for unbound generics. + OpenUnboundGenericType(CS, CS.getConstraintLocator(expr))); + if (!toType) return nullptr; - // Open the type we're casting to. - const auto toType = - CS.openUnboundGenericTypes(type, CS.getConstraintLocator(expr)); + // Cache the type we're casting to. if (repr) CS.setType(repr, toType); auto fromType = CS.getType(fromExpr); @@ -3137,17 +3158,16 @@ namespace { Type visitIsExpr(IsExpr *expr) { // Validate the type. + // FIXME: Locator for the cast type? auto &ctx = CS.getASTContext(); - const auto type = resolveTypeReferenceInExpression( - expr->getCastTypeRepr(), - TypeResolverContext::ExplicitCastExpr); - if (!type) + const auto toType = resolveTypeReferenceInExpression( + expr->getCastTypeRepr(), TypeResolverContext::ExplicitCastExpr, + // Introduce type variables for unbound generics. + OpenUnboundGenericType(CS, CS.getConstraintLocator(expr))); + if (!toType) return nullptr; - // Open up the type we're checking. - // FIXME: Locator for the cast type? - const auto toType = - CS.openUnboundGenericTypes(type, CS.getConstraintLocator(expr)); + // Cache the type we're checking. CS.setType(expr->getCastTypeRepr(), toType); // Add a checked cast constraint. @@ -3353,7 +3373,7 @@ namespace { // Just resolve the referenced type. // FIXME: The type reference needs to be opened into context. return resolveTypeReferenceInExpression( - placeholderRepr, TypeResolverContext::InExpression); + placeholderRepr, TypeResolverContext::InExpression, nullptr); } auto locator = CS.getConstraintLocator(E); @@ -3423,11 +3443,13 @@ namespace { // If a root type was explicitly given, then resolve it now. if (auto rootRepr = E->getRootType()) { - auto rootObjectTy = resolveTypeReferenceInExpression( - rootRepr, TypeResolverContext::InExpression); + const auto rootObjectTy = resolveTypeReferenceInExpression( + rootRepr, TypeResolverContext::InExpression, + // Introduce type variables for unbound generics. + OpenUnboundGenericType(CS, locator)); if (!rootObjectTy || rootObjectTy->hasError()) return Type(); - rootObjectTy = CS.openUnboundGenericTypes(rootObjectTy, locator); + // Allow \Derived.property to be inferred as \Base.property to // simulate a sort of covariant conversion from // KeyPath to KeyPath. @@ -3887,6 +3909,9 @@ static Type generateWrappedPropertyTypeConstraints( auto wrapperAttributes = wrappedVar->getAttachedPropertyWrappers(); for (unsigned i : indices(wrapperAttributes)) { + // FIXME: We should somehow pass an OpenUnboundGenericTypeFn to + // AttachedPropertyWrapperTypeRequest::evaluate to open up unbound + // generics on the fly. Type rawWrapperType = wrappedVar->getAttachedPropertyWrapperType(i); auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i); if (rawWrapperType->hasError() || !wrapperInfo) diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 295400c49eb62..162a8395901ab 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -997,8 +997,14 @@ void ConstraintSystem::shrink(Expr *expr) { auto *const typeRepr = coerceExpr->getCastTypeRepr(); if (typeRepr && isSuitableCollection(typeRepr)) { - auto resolution = TypeResolution::forContextual(CS.DC, None); - auto coercionType = resolution.resolveType(typeRepr); + const auto coercionType = + TypeResolution::forContextual( + CS.DC, None, + // FIXME: Should we really be unconditionally complaining + // about unbound generics here? For example: + // let foo: [Array] = [[0], [1], [2]] as [Array] + /*unboundTyOpener*/ nullptr) + .resolveType(typeRepr); // Looks like coercion type is invalid, let's skip this sub-tree. if (coercionType->hasError()) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 0da14419ee002..1141966e1df13 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -698,7 +698,8 @@ Type ConstraintSystem::openUnboundGenericType( // handle generic TypeAliases elsewhere, this can just become a // call to BoundGenericType::get(). return TypeChecker::applyUnboundGenericArguments( - decl, parentTy, SourceLoc(), TypeResolution::forContextual(DC, None), + decl, parentTy, SourceLoc(), + TypeResolution::forContextual(DC, None, /*unboundTyOpener*/ nullptr), arguments); } @@ -1217,7 +1218,8 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // Resolve the reference to this type declaration in our current context. auto type = TypeChecker::resolveTypeInContext( typeDecl, nullptr, - TypeResolution::forContextual(useDC, TypeResolverContext::InExpression), + TypeResolution::forContextual(useDC, TypeResolverContext::InExpression, + /*unboundTyOpener*/ nullptr), /*isSpecialized=*/false); checkNestedTypeConstraints(*this, type, locator); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 7af0b67cdc10b..0b641c7f111c0 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -5027,6 +5027,25 @@ class ConstraintSystem { void print(raw_ostream &out, Expr *) const; }; +/// A function object suitable for use as an \c OpenUnboundGenericTypeFn that +/// "opens" the given unbound type by introducing fresh type variables for +/// generic parameters and constructing a bound generic type from these +/// type variables. +class OpenUnboundGenericType { + ConstraintSystem &cs; + const ConstraintLocatorBuilder &locator; + +public: + explicit OpenUnboundGenericType(ConstraintSystem &cs, + const ConstraintLocatorBuilder &locator) + : cs(cs), locator(locator) {} + + Type operator()(UnboundGenericType *unboundTy) const { + return cs.openUnboundGenericType(unboundTy->getDecl(), + unboundTy->getParent(), locator); + } +}; + /// Compute the shuffle required to map from a given tuple type to /// another tuple type. /// diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 9fa57e3ddef36..147affbcbc40e 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2660,8 +2660,11 @@ ResolveTypeEraserTypeRequest::evaluate(Evaluator &evaluator, ProtocolDecl *PD, TypeEraserAttr *attr) const { if (auto *typeEraserRepr = attr->getParsedTypeEraserTypeRepr()) { - auto resolution = TypeResolution::forContextual(PD, None); - return resolution.resolveType(typeEraserRepr); + return TypeResolution::forContextual(PD, None, + // Unbound generics are not allowed + // within this attribute. + /*unboundTyOpener*/ nullptr) + .resolveType(typeEraserRepr); } else { auto *LazyResolver = attr->Resolver; assert(LazyResolver && "type eraser was neither parsed nor deserialized?"); @@ -2842,11 +2845,8 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) { Type T = attr->getProtocolType(); if (!T && attr->getProtocolTypeRepr()) { - TypeResolutionOptions options = None; - options |= TypeResolutionFlags::AllowUnboundGenerics; - - T = TypeResolution::forContextual(DC, options) - .resolveType(attr->getProtocolTypeRepr()); + T = TypeResolution::forContextual(DC, None, /*unboundTyOpener*/ nullptr) + .resolveType(attr->getProtocolTypeRepr()); } // Definite error-types were already diagnosed in resolveType. @@ -4572,11 +4572,12 @@ static bool typeCheckDerivativeAttr(ASTContext &Ctx, Decl *D, Type baseType; if (auto *baseTypeRepr = attr->getBaseTypeRepr()) { - TypeResolutionOptions options = None; - options |= TypeResolutionFlags::AllowModule; - auto resolution = - TypeResolution::forContextual(derivative->getDeclContext(), options); - baseType = resolution.resolveType(baseTypeRepr); + const auto options = + TypeResolutionOptions(None) | TypeResolutionFlags::AllowModule; + baseType = + TypeResolution::forContextual(derivative->getDeclContext(), options, + /*unboundTyOpener*/ nullptr) + .resolveType(baseTypeRepr); } if (baseType && baseType->hasError()) return true; @@ -5142,11 +5143,12 @@ void AttributeChecker::visitTransposeAttr(TransposeAttr *attr) { return None; }; - auto resolution = - TypeResolution::forContextual(transpose->getDeclContext(), None); Type baseType; - if (attr->getBaseTypeRepr()) - baseType = resolution.resolveType(attr->getBaseTypeRepr()); + if (attr->getBaseTypeRepr()) { + baseType = TypeResolution::forContextual(transpose->getDeclContext(), None, + /*unboundTyOpener*/ nullptr) + .resolveType(attr->getBaseTypeRepr()); + } auto lookupOptions = (attr->getBaseTypeRepr() ? defaultMemberLookupOptions : defaultUnqualifiedLookupOptions) | diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index efb53703b0381..bfb4c58e5646e 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1391,11 +1391,16 @@ TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) { // Resolve the TypeRepr to get the base type for the lookup. // Disable availability diagnostics here, because the final // TypeRepr will be resolved again when generating constraints. - TypeResolutionOptions options(TypeResolverContext::InExpression); - options |= TypeResolutionFlags::AllowUnboundGenerics; - options |= TypeResolutionFlags::AllowUnavailable; - auto resolution = TypeResolution::forContextual(DC, options); - auto BaseTy = resolution.resolveType(InnerTypeRepr); + const auto options = + TypeResolutionOptions(TypeResolverContext::InExpression) | + TypeResolutionFlags::AllowUnavailable; + const auto resolution = + TypeResolution::forContextual(DC, options, [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }); + const auto BaseTy = resolution.resolveType(InnerTypeRepr); if (BaseTy->mayHaveMembers()) { auto lookupOptions = defaultMemberLookupOptions; @@ -1919,11 +1924,15 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { } else { const auto options = TypeResolutionOptions(TypeResolverContext::InExpression) | - TypeResolutionFlags::AllowUnboundGenerics | TypeResolutionFlags::SilenceErrors; - auto result = TypeResolution::forContextual(DC, options) - .resolveType(typeExpr->getTypeRepr()); + const auto resolution = + TypeResolution::forContextual(DC, options, [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }); + const auto result = resolution.resolveType(typeExpr->getTypeRepr()); if (result->hasError()) return nullptr; castTy = result; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 145de572b43c3..92638c7f25699 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -816,9 +816,10 @@ DefaultDefinitionTypeRequest::evaluate(Evaluator &evaluator, TypeRepr *defaultDefinition = assocType->getDefaultDefinitionTypeRepr(); if (defaultDefinition) { - auto resolution = - TypeResolution::forInterface(assocType->getDeclContext(), None); - return resolution.resolveType(defaultDefinition); + return TypeResolution::forInterface(assocType->getDeclContext(), None, + // Diagnose unbound generics. + /*unboundTyOpener*/ nullptr) + .resolveType(defaultDefinition); } return Type(); @@ -1445,9 +1446,16 @@ static NominalTypeDecl *resolveSingleNominalTypeDecl( auto *TyR = new (Ctx) SimpleIdentTypeRepr(DeclNameLoc(loc), DeclNameRef(ident)); - TypeResolutionOptions options = TypeResolverContext::TypeAliasDecl; - options |= flags; - auto result = TypeResolution::forInterface(DC, options).resolveType(TyR); + const auto options = + TypeResolutionOptions(TypeResolverContext::TypeAliasDecl) | flags; + + const auto result = + TypeResolution::forInterface(DC, options, + // FIXME: Should unbound generics be allowed + // to appear amongst designated types? + /*unboundTyOpener*/ nullptr) + .resolveType(TyR); + if (result->hasError()) return nullptr; return result->getAnyNominal(); @@ -1759,8 +1767,10 @@ UnderlyingTypeRequest::evaluate(Evaluator &evaluator, return ErrorType::get(typeAlias->getASTContext()); } - auto result = TypeResolution::forInterface(typeAlias, options) - .resolveType(underlyingRepr); + const auto result = TypeResolution::forInterface(typeAlias, options, + /*unboundTyOpener*/ nullptr) + .resolveType(underlyingRepr); + if (result->hasError()) { typeAlias->setInvalid(); return ErrorType::get(typeAlias->getASTContext()); @@ -2006,10 +2016,11 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { : ErrorType::get(ctx)); } - auto *dc = decl->getInnermostDeclContext(); - auto resolution = - TypeResolution::forInterface(dc, TypeResolverContext::FunctionResult); - return resolution.resolveType(resultTyRepr); + const auto options = + TypeResolutionOptions(TypeResolverContext::FunctionResult); + auto *const dc = decl->getInnermostDeclContext(); + return TypeResolution::forInterface(dc, options, /*unboundTyOpener*/ nullptr) + .resolveType(resultTyRepr); } ParamSpecifier @@ -2087,10 +2098,15 @@ static Type validateParameterType(ParamDecl *decl) { auto *dc = decl->getDeclContext(); TypeResolutionOptions options(None); + OpenUnboundGenericTypeFn unboundTyOpener = nullptr; if (isa(dc)) { options = TypeResolutionOptions(TypeResolverContext::ClosureExpr); options |= TypeResolutionFlags::AllowUnspecifiedTypes; - options |= TypeResolutionFlags::AllowUnboundGenerics; + unboundTyOpener = [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }; } else if (isa(dc)) { options = TypeResolutionOptions(TypeResolverContext::AbstractFunctionDecl); } else if (isa(dc)) { @@ -2108,9 +2124,11 @@ static Type validateParameterType(ParamDecl *decl) { TypeResolverContext::FunctionInput); options |= TypeResolutionFlags::Direct; + const auto resolution = + TypeResolution::forInterface(dc, options, unboundTyOpener); + auto Ty = resolution.resolveType(decl->getTypeRepr()); + auto &ctx = dc->getASTContext(); - auto Ty = TypeResolution::forInterface(dc, options) - .resolveType(decl->getTypeRepr()); if (Ty->hasError()) { decl->setInvalid(); return ErrorType::get(ctx); @@ -2613,10 +2631,16 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const { return error(); // Compute the extended type. - TypeResolutionOptions options(TypeResolverContext::ExtensionBinding); - options |= TypeResolutionFlags::AllowUnboundGenerics; - auto tr = TypeResolution::forStructural(ext->getDeclContext(), options); - auto extendedType = tr.resolveType(extendedRepr); + const TypeResolutionOptions options(TypeResolverContext::ExtensionBinding); + const auto resolution = TypeResolution::forStructural( + ext->getDeclContext(), TypeResolverContext::ExtensionBinding, + [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }); + + const auto extendedType = resolution.resolveType(extendedRepr); if (extendedType->hasError()) return error(); diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index c18cc16e3d965..9aadc7c3bdfec 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -127,14 +127,15 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, UnavailabilityReason::requiresVersionRange(availability.getOSVersion())); } } - + // Try to resolve the constraint repr. It should be some kind of existential - // type. - TypeResolutionOptions options(TypeResolverContext::GenericRequirement); - // Pass along the error type if resolving the repr failed. + // type. Pass along the error type if resolving the repr failed. auto constraintType = TypeResolution::forInterface( - dc, dc->getGenericSignatureOfContext(), options) + dc, TypeResolverContext::GenericRequirement, + // Unbound generics are meaningless in opaque types. + /*unboundTyOpener*/ nullptr) .resolveType(repr->getConstraint()); + if (constraintType->hasError()) return nullptr; @@ -652,25 +653,27 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, // For functions and subscripts, resolve the parameter and result types and // note them as inference sources. if (subscr || func) { - // Gather requirements from the parameter list. - TypeResolutionOptions options = - (func ? TypeResolverContext::AbstractFunctionDecl - : TypeResolverContext::SubscriptDecl); + const auto baseOptions = + TypeResolutionOptions(func ? TypeResolverContext::AbstractFunctionDecl + : TypeResolverContext::SubscriptDecl); - auto resolution = TypeResolution::forStructural(GC, options); + const auto resolution = + TypeResolution::forStructural(GC, baseOptions, + /*unboundTyOpener*/ nullptr); auto params = func ? func->getParameters() : subscr->getIndices(); for (auto param : *params) { auto *typeRepr = param->getTypeRepr(); if (typeRepr == nullptr) continue; - auto paramOptions = options; + auto paramOptions = baseOptions; paramOptions.setContext(param->isVariadic() ? TypeResolverContext::VariadicFunctionInput : TypeResolverContext::FunctionInput); paramOptions |= TypeResolutionFlags::Direct; - auto type = resolution.withOptions(paramOptions).resolveType(typeRepr); + const auto type = + resolution.withOptions(paramOptions).resolveType(typeRepr); if (auto *specifier = dyn_cast(typeRepr)) typeRepr = specifier->getBase(); @@ -689,7 +692,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, } }(); if (resultTypeRepr && !isa(resultTypeRepr)) { - auto resultType = + const auto resultType = resolution.withOptions(TypeResolverContext::FunctionResult) .resolveType(resultTypeRepr); @@ -916,15 +919,18 @@ RequirementRequest::evaluate(Evaluator &evaluator, unsigned index, TypeResolutionStage stage) const { // Figure out the type resolution. - TypeResolutionOptions options = TypeResolverContext::GenericRequirement; + const auto options = + TypeResolutionOptions(TypeResolverContext::GenericRequirement); Optional resolution; switch (stage) { case TypeResolutionStage::Structural: - resolution = TypeResolution::forStructural(owner.dc, options); + resolution = TypeResolution::forStructural(owner.dc, options, + /*unboundTyOpener*/ nullptr); break; case TypeResolutionStage::Interface: - resolution = TypeResolution::forInterface(owner.dc, options); + resolution = TypeResolution::forInterface(owner.dc, options, + /*unboundTyOpener*/ nullptr); break; case TypeResolutionStage::Contextual: @@ -975,8 +981,9 @@ Type StructuralTypeRequest::evaluate(Evaluator &evaluator, return ErrorType::get(ctx); } - auto resolution = TypeResolution::forStructural(typeAlias, options); - auto type = resolution.resolveType(underlyingTypeRepr); + const auto type = TypeResolution::forStructural(typeAlias, options, + /*unboundTyOpener*/ nullptr) + .resolveType(underlyingTypeRepr); auto genericSig = typeAlias->getGenericSignature(); SubstitutionMap subs; diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index f24f3df0c0c0e..8d0dc39ebef4a 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -467,14 +467,19 @@ class ResolvePattern : public ASTVisitorgetBase())) return nullptr; - TypeResolutionOptions options = None; - options |= TypeResolutionFlags::AllowUnboundGenerics; - options |= TypeResolutionFlags::SilenceErrors; + const auto options = + TypeResolutionOptions(None) | TypeResolutionFlags::SilenceErrors; auto *repr = IdentTypeRepr::create(Context, components); // See if the repr resolves to a type. - auto ty = TypeResolution::forContextual(DC, options).resolveType(repr); + const auto resolution = + TypeResolution::forContextual(DC, options, [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }); + const auto ty = resolution.resolveType(repr); auto *enumDecl = dyn_cast_or_null(ty->getAnyNominal()); if (!enumDecl) return nullptr; @@ -564,17 +569,20 @@ class ResolvePattern : public ASTVisitorgetDeclaredTypeInContext(), Context); } else { - TypeResolutionOptions options = None; - options |= TypeResolutionFlags::AllowUnboundGenerics; - options |= TypeResolutionFlags::SilenceErrors; + const auto options = + TypeResolutionOptions(None) | TypeResolutionFlags::SilenceErrors; // Otherwise, see whether we had an enum type as the penultimate // component, and look up an element inside it. auto *prefixRepr = IdentTypeRepr::create(Context, components); // See first if the entire repr resolves to a type. - Type enumTy = TypeResolution::forContextual(DC, options) - .resolveType(prefixRepr); + const Type enumTy = + TypeResolution::forContextual(DC, options, [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }).resolveType(prefixRepr); auto *enumDecl = dyn_cast_or_null(enumTy->getAnyNominal()); if (!enumDecl) return nullptr; @@ -726,7 +734,6 @@ static TypeResolutionOptions applyContextualPatternOptions( TypeResolutionOptions options, ContextualPattern pattern) { if (pattern.allowsInference()) { options |= TypeResolutionFlags::AllowUnspecifiedTypes; - options |= TypeResolutionFlags::AllowUnboundGenerics; } return options; @@ -770,8 +777,17 @@ Type PatternTypeRequest::evaluate(Evaluator &evaluator, // If we see an explicit type annotation, coerce the sub-pattern to // that type. case PatternKind::Typed: { - auto resolution = TypeResolution::forContextual(dc, options); - return validateTypedPattern(cast(P), resolution); + OpenUnboundGenericTypeFn unboundTyOpener = nullptr; + if (pattern.allowsInference()) { + unboundTyOpener = [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }; + } + return validateTypedPattern( + cast(P), + TypeResolution::forContextual(dc, options, unboundTyOpener)); } // A wildcard or name pattern cannot appear by itself in a context @@ -824,9 +840,17 @@ Type PatternTypeRequest::evaluate(Evaluator &evaluator, // typed pattern, the resulting pattern must have optional type. auto somePat = cast(P); if (somePat->isImplicit() && isa(somePat->getSubPattern())) { - auto resolution = TypeResolution::forContextual(dc, options); + OpenUnboundGenericTypeFn unboundTyOpener = nullptr; + if (pattern.allowsInference()) { + unboundTyOpener = [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }; + } TypedPattern *TP = cast(somePat->getSubPattern()); - auto type = validateTypedPattern(TP, resolution); + const auto type = validateTypedPattern( + TP, TypeResolution::forContextual(dc, options, unboundTyOpener)); if (type && !type->hasError()) { return OptionalType::get(type); } @@ -1230,9 +1254,12 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern, auto IP = cast(P); // Type-check the type parameter. - TypeResolutionOptions paramOptions(TypeResolverContext::InExpression); - auto castType = TypeResolution::forContextual(dc, paramOptions) - .resolveType(IP->getCastTypeRepr()); + const auto castType = + TypeResolution::forContextual(dc, TypeResolverContext::InExpression, + // FIXME: Should we really unconditionally + // complain about unbound generics here? + /*unboundTyOpener*/ nullptr) + .resolveType(IP->getCastTypeRepr()); if (castType->hasError()) return nullptr; IP->setCastType(castType); diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp index cda70bdc3ee53..b7ed0d06bd0cc 100644 --- a/lib/Sema/TypeCheckRequestFunctions.cpp +++ b/lib/Sema/TypeCheckRequestFunctions.cpp @@ -42,19 +42,20 @@ InheritedTypeRequest::evaluate( dc = typeDecl->getDeclContext(); } } else { - auto ext = decl.get(); - dc = ext; + dc = decl.get(); options |= TypeResolutionFlags::AllowUnavailableProtocol; } Optional resolution; switch (stage) { case TypeResolutionStage::Structural: - resolution = TypeResolution::forStructural(dc, options); + resolution = + TypeResolution::forStructural(dc, options, /*unboundTyOpener*/ nullptr); break; case TypeResolutionStage::Interface: - resolution = TypeResolution::forInterface(dc, options); + resolution = + TypeResolution::forInterface(dc, options, /*unboundTyOpener*/ nullptr); break; case TypeResolutionStage::Contextual: { diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c3f88e324c88d..ac2b44d348d2a 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -56,40 +56,42 @@ using namespace swift; /// Type resolution. -TypeResolution TypeResolution::forStructural(DeclContext *dc, - TypeResolutionOptions options) { - return TypeResolution(dc, TypeResolutionStage::Structural, options); -} - -TypeResolution TypeResolution::forInterface(DeclContext *dc, - TypeResolutionOptions options) { - return forInterface(dc, dc->getGenericSignatureOfContext(), options); -} - -TypeResolution TypeResolution::forInterface(DeclContext *dc, - GenericSignature genericSig, - TypeResolutionOptions options) { - TypeResolution result(dc, TypeResolutionStage::Interface, options); - result.complete.genericSig = genericSig; +TypeResolution +TypeResolution::forStructural(DeclContext *dc, TypeResolutionOptions options, + OpenUnboundGenericTypeFn unboundTyOpener) { + return TypeResolution(dc, TypeResolutionStage::Structural, options, + unboundTyOpener); +} + +TypeResolution +TypeResolution::forInterface(DeclContext *dc, TypeResolutionOptions options, + OpenUnboundGenericTypeFn unboundTyOpener) { + TypeResolution result(dc, TypeResolutionStage::Interface, options, + unboundTyOpener); + result.complete.genericSig = dc->getGenericSignatureOfContext(); result.complete.builder = nullptr; return result; } -TypeResolution TypeResolution::forContextual(DeclContext *dc, - TypeResolutionOptions options) { - return forContextual(dc, dc->getGenericEnvironmentOfContext(), options); +TypeResolution +TypeResolution::forContextual(DeclContext *dc, TypeResolutionOptions options, + OpenUnboundGenericTypeFn unboundTyOpener) { + return forContextual(dc, dc->getGenericEnvironmentOfContext(), options, + unboundTyOpener); } -TypeResolution TypeResolution::forContextual(DeclContext *dc, - GenericEnvironment *genericEnv, - TypeResolutionOptions options) { - TypeResolution result(dc, TypeResolutionStage::Contextual, options); +TypeResolution +TypeResolution::forContextual(DeclContext *dc, GenericEnvironment *genericEnv, + TypeResolutionOptions options, + OpenUnboundGenericTypeFn unboundTyOpener) { + TypeResolution result(dc, TypeResolutionStage::Contextual, options, + unboundTyOpener); result.genericEnv = genericEnv; return result; } TypeResolution TypeResolution::withOptions(TypeResolutionOptions opts) const { - TypeResolution result(dc, stage, opts); + TypeResolution result(dc, stage, opts, unboundTyOpener); result.genericEnv = genericEnv; result.complete = complete; return result; @@ -679,11 +681,20 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, auto *generic = dyn_cast(comp); if (!generic) { - if (type->is() && - !options.is(TypeResolverContext::TypeAliasDecl) && - !options.contains(TypeResolutionFlags::AllowUnboundGenerics)) { - diagnoseUnboundGenericType(type, loc); - return ErrorType::get(type->getASTContext()); + if (auto *const unboundTy = type->getAs()) { + if (!options.is(TypeResolverContext::TypeAliasDecl)) { + // If the resolution object carries an opener, attempt to open + // the unbound generic type. + if (const auto openerFn = resolution.getUnboundTypeOpener()) + if (const auto boundTy = openerFn(unboundTy)) + return boundTy; + + // Complain if we're allowed to and bail out with an error. + if (!options.contains(TypeResolutionFlags::SilenceErrors)) + diagnoseUnboundGenericType(type, loc); + + return ErrorType::get(resolution.getASTContext()); + } } if (resolution.getStage() == TypeResolutionStage::Structural) @@ -1518,7 +1529,7 @@ resolveIdentTypeComponent(TypeResolution resolution, auto comp = components.back(); // The first component uses unqualified lookup. - auto parentComps = components.slice(0, components.size()-1); + const auto parentComps = components.drop_back(); if (parentComps.empty()) { return resolveTopLevelIdentTypeComponent(resolution, comp); } @@ -1782,7 +1793,7 @@ namespace { }; } // end anonymous namespace -Type TypeResolution::resolveType(TypeRepr *TyR) { +Type TypeResolution::resolveType(TypeRepr *TyR) const { auto &ctx = getASTContext(); auto Ty = evaluateOrDefault(ctx.evaluator, ResolveTypeRequest{this, TyR}, Type()); @@ -1792,7 +1803,7 @@ Type TypeResolution::resolveType(TypeRepr *TyR) { } Type ResolveTypeRequest::evaluate(Evaluator &evaluator, - TypeResolution *resolution, + const TypeResolution *resolution, TypeRepr *TyR) const { const auto options = resolution->getOptions(); auto &ctx = resolution->getASTContext(); @@ -2745,8 +2756,8 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr, Optional> useSILBoxGenericEnv; if (auto env = repr->getGenericEnvironment()) { - resolveSILBoxGenericParams = - TypeResolution::forContextual(DC, env, options); + resolveSILBoxGenericParams = TypeResolution::forContextual( + DC, env, options, resolution.getUnboundTypeOpener()); useSILBoxGenericEnv.emplace(resolution, *resolveSILBoxGenericParams); } @@ -2825,8 +2836,8 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, Optional> useSILFunctionGenericEnv; if (componentTypeEnv) { - resolveSILFunctionGenericParams = - TypeResolution::forContextual(DC, componentTypeEnv, options); + resolveSILFunctionGenericParams = TypeResolution::forContextual( + DC, componentTypeEnv, options, resolution.getUnboundTypeOpener()); useSILFunctionGenericEnv.emplace(resolution, *resolveSILFunctionGenericParams); } @@ -2889,8 +2900,8 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, Optional resolveSILFunctionGenericParams; Optional> useSILFunctionGenericEnv; if (genericEnv) { - resolveSILFunctionGenericParams = - TypeResolution::forContextual(DC, genericEnv, options); + resolveSILFunctionGenericParams = TypeResolution::forContextual( + DC, genericEnv, options, resolution.getUnboundTypeOpener()); useSILFunctionGenericEnv.emplace(resolution, *resolveSILFunctionGenericParams); } @@ -3859,15 +3870,22 @@ void TypeChecker::checkUnsupportedProtocolType( Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr, DeclContext *dc, CustomAttrTypeKind typeKind) const { - TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl); + const TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl); + OpenUnboundGenericTypeFn unboundTyOpener = nullptr; // Property delegates allow their type to be an unbound generic. - if (typeKind == CustomAttrTypeKind::PropertyDelegate) - options |= TypeResolutionFlags::AllowUnboundGenerics; + if (typeKind == CustomAttrTypeKind::PropertyDelegate) { + unboundTyOpener = [](auto unboundTy) { + // FIXME: Don't let unbound generic types + // escape type resolution. For now, just + // return the unbound generic type. + return unboundTy; + }; + } ASTContext &ctx = dc->getASTContext(); - auto type = TypeResolution::forContextual(dc, options) - .resolveType(attr->getTypeRepr()); + const auto type = TypeResolution::forContextual(dc, options, unboundTyOpener) + .resolveType(attr->getTypeRepr()); // We always require the type to resolve to a nominal type. if (!type->getAnyNominal()) { diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index 2736f76d13e43..b2052545d665c 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -35,40 +35,37 @@ enum class TypeResolutionFlags : uint16_t { /// Whether to allow unspecified types within a pattern. AllowUnspecifiedTypes = 1 << 0, - /// Whether to allow unbound generic types. - AllowUnboundGenerics = 1 << 1, - /// Whether an unavailable protocol can be referenced. - AllowUnavailableProtocol = 1 << 2, + AllowUnavailableProtocol = 1 << 1, /// Whether we should allow references to unavailable types. - AllowUnavailable = 1 << 3, + AllowUnavailable = 1 << 2, /// Whether the given type can override the type of a typed pattern. - OverrideType = 1 << 4, + OverrideType = 1 << 3, /// Whether we are validating the type for SIL. // FIXME: Move this flag to TypeResolverContext. - SILType = 1 << 5, + SILType = 1 << 4, /// Whether we are parsing a SIL file. Not the same as SILType, /// because the latter is not set if we're parsing an AST type. - SILMode = 1 << 6, + SILMode = 1 << 5, /// Whether this is a resolution based on a non-inferred type pattern. - FromNonInferredPattern = 1 << 7, + FromNonInferredPattern = 1 << 6, /// Whether this type resolution is guaranteed not to affect downstream files. - KnownNonCascadingDependency = 1 << 8, + KnownNonCascadingDependency = 1 << 7, /// Whether we are at the direct base of a type expression. - Direct = 1 << 9, + Direct = 1 << 8, /// Whether we should not produce diagnostics if the type is invalid. - SilenceErrors = 1 << 10, + SilenceErrors = 1 << 9, /// Whether to allow module declaration types. - AllowModule = 1 << 11 + AllowModule = 1 << 10 }; /// Type resolution contexts that require special handling. @@ -275,6 +272,13 @@ class TypeResolutionOptions { } }; +/// A function reference used to "open" the given unbound generic type +/// by introducing generic arguments and constructing a \c BoundGenericType +/// out of them. +/// +/// \returns the \c null type on failure. +using OpenUnboundGenericTypeFn = llvm::function_ref; + /// Handles the resolution of types within a given declaration context, /// which might involve resolving generic parameters to a particular /// stage. @@ -282,7 +286,9 @@ class TypeResolution { DeclContext *dc; TypeResolutionStage stage; TypeResolutionOptions options; + OpenUnboundGenericTypeFn unboundTyOpener; +private: union { /// The generic environment used to map to archetypes. GenericEnvironment *genericEnv; @@ -299,41 +305,45 @@ class TypeResolution { }; TypeResolution(DeclContext *dc, TypeResolutionStage stage, - TypeResolutionOptions options) - : dc(dc), stage(stage), options(options) {} + TypeResolutionOptions options, + OpenUnboundGenericTypeFn unboundTyOpener) + : dc(dc), stage(stage), options(options), + unboundTyOpener(unboundTyOpener) {} GenericSignatureBuilder *getGenericSignatureBuilder() const; + /// Retrieves the generic signature for the context, or NULL if there is + /// no generic signature to resolve types. + GenericSignature getGenericSignature() const; + public: /// Form a type resolution for the structure of a type, which does not /// attempt to resolve member types of type parameters to a particular /// associated type. static TypeResolution forStructural(DeclContext *dc, - TypeResolutionOptions opts); - - /// Form a type resolution for an interface type, which is a complete - /// description of the type using generic parameters. - static TypeResolution forInterface(DeclContext *dc, - TypeResolutionOptions opts); + TypeResolutionOptions opts, + OpenUnboundGenericTypeFn unboundTyOpener); /// Form a type resolution for an interface type, which is a complete /// description of the type using generic parameters. static TypeResolution forInterface(DeclContext *dc, - GenericSignature genericSig, - TypeResolutionOptions opts); + TypeResolutionOptions opts, + OpenUnboundGenericTypeFn unboundTyOpener); /// Form a type resolution for a contextual type, which is a complete /// description of the type using the archetypes of the given declaration /// context. static TypeResolution forContextual(DeclContext *dc, - TypeResolutionOptions opts); + TypeResolutionOptions opts, + OpenUnboundGenericTypeFn unboundTyOpener); /// Form a type resolution for a contextual type, which is a complete /// description of the type using the archetypes of the given generic /// environment. static TypeResolution forContextual(DeclContext *dc, GenericEnvironment *genericEnv, - TypeResolutionOptions opts); + TypeResolutionOptions opts, + OpenUnboundGenericTypeFn unboundTyOpener); public: TypeResolution withOptions(TypeResolutionOptions opts) const; @@ -351,9 +361,9 @@ class TypeResolution { TypeResolutionOptions getOptions() const { return options; } - /// Retrieves the generic signature for the context, or NULL if there is - /// no generic signature to resolve types. - GenericSignature getGenericSignature() const; + OpenUnboundGenericTypeFn getUnboundTypeOpener() const { + return unboundTyOpener; + } /// Resolves a TypeRepr to a type. /// @@ -363,7 +373,7 @@ class TypeResolution { /// \param TyR The type representation to check. /// /// \returns A well-formed type that is never null, or an \c ErrorType in case of an error. - Type resolveType(TypeRepr *TyR); + Type resolveType(TypeRepr *TyR) const; /// Whether this type resolution uses archetypes (vs. generic parameters). bool usesArchetypes() const; diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 8a4e64efc8d22..7beba6d51f001 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -375,16 +375,20 @@ bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T, DeclContext *DC, bool ProduceDiagnostics) { TypeResolutionOptions options = None; - - // Fine to have unbound generic types. - options |= TypeResolutionFlags::AllowUnboundGenerics; if (isSILMode) { options |= TypeResolutionFlags::SILMode; } if (isSILType) options |= TypeResolutionFlags::SILType; - auto resolution = TypeResolution::forContextual(DC, GenericEnv, options); + const auto resolution = + TypeResolution::forContextual(DC, GenericEnv, options, + [](auto unboundTy) { + // FIXME: Don't let unbound generic types escape type resolution. + // For now, just return the unbound generic type. + return unboundTy; + }); + Optional suppression; if (!ProduceDiagnostics) suppression.emplace(Ctx.Diags); diff --git a/validation-test/compiler_crashers/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift b/validation-test/compiler_crashers_fixed/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift similarity index 89% rename from validation-test/compiler_crashers/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift rename to validation-test/compiler_crashers_fixed/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift index 1b7f74bac86c9..c6642cf831504 100644 --- a/validation-test/compiler_crashers/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift +++ b/validation-test/compiler_crashers_fixed/28782-superclass-superclass-isequal-t-should-have-diagnosed-multiple-superclasses-by-n.swift @@ -6,7 +6,7 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // REQUIRES: asserts -// RUN: not --crash %target-swift-frontend %s -emit-ir +// RUN: not %target-swift-frontend %s -emit-ir [.a{}ExtendedGraphemeClusterLiteralConvertible & ManagedBuffer & ManagedBuffer