diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 600042bf07563..8b372835d08b1 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1030,12 +1030,12 @@ class RequirementRepr { SourceLoc SeparatorLoc; RequirementReprKind Kind : 2; bool Invalid : 1; - TypeLoc FirstType; + TypeRepr *FirstType; /// The second element represents the right-hand side of the constraint. /// It can be e.g. a type or a layout constraint. union { - TypeLoc SecondType; + TypeRepr *SecondType; LayoutConstraintLoc SecondLayout; }; @@ -1044,16 +1044,16 @@ class RequirementRepr { StringRef AsWrittenString; RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind, - TypeLoc FirstType, TypeLoc SecondType) + TypeRepr *FirstType, TypeRepr *SecondType) : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), FirstType(FirstType), SecondType(SecondType) { } RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind, - TypeLoc FirstType, LayoutConstraintLoc SecondLayout) + TypeRepr *FirstType, LayoutConstraintLoc SecondLayout) : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), FirstType(FirstType), SecondLayout(SecondLayout) { } - void printImpl(ASTPrinter &OS, bool AsWritten) const; + void printImpl(ASTPrinter &OS) const; public: /// Construct a new type-constraint requirement. @@ -1064,9 +1064,9 @@ class RequirementRepr { /// this requirement was implied. /// \param Constraint The protocol or protocol composition to which the /// subject must conform, or superclass from which the subject must inherit. - static RequirementRepr getTypeConstraint(TypeLoc Subject, + static RequirementRepr getTypeConstraint(TypeRepr *Subject, SourceLoc ColonLoc, - TypeLoc Constraint) { + TypeRepr *Constraint) { return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint }; } @@ -1076,9 +1076,9 @@ class RequirementRepr { /// \param EqualLoc The location of the '==' in the same-type constraint, or /// an invalid location if this requirement was implied. /// \param SecondType The second type. - static RequirementRepr getSameType(TypeLoc FirstType, + static RequirementRepr getSameType(TypeRepr *FirstType, SourceLoc EqualLoc, - TypeLoc SecondType) { + TypeRepr *SecondType) { return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType }; } @@ -1090,7 +1090,7 @@ class RequirementRepr { /// this requirement was implied. /// \param Layout The layout requirement to which the /// subject must conform. - static RequirementRepr getLayoutConstraint(TypeLoc Subject, + static RequirementRepr getLayoutConstraint(TypeRepr *Subject, SourceLoc ColonLoc, LayoutConstraintLoc Layout) { return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject, @@ -1108,25 +1108,7 @@ class RequirementRepr { /// For a type-bound requirement, return the subject of the /// conformance relationship. - Type getSubject() const { - assert(getKind() == RequirementReprKind::TypeConstraint || - getKind() == RequirementReprKind::LayoutConstraint); - return FirstType.getType(); - } - TypeRepr *getSubjectRepr() const { - assert(getKind() == RequirementReprKind::TypeConstraint || - getKind() == RequirementReprKind::LayoutConstraint); - return FirstType.getTypeRepr(); - } - - TypeLoc &getSubjectLoc() { - assert(getKind() == RequirementReprKind::TypeConstraint || - getKind() == RequirementReprKind::LayoutConstraint); - return FirstType; - } - - const TypeLoc &getSubjectLoc() const { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return FirstType; @@ -1134,22 +1116,7 @@ class RequirementRepr { /// For a type-bound requirement, return the protocol or to which /// the subject conforms or superclass it inherits. - Type getConstraint() const { - assert(getKind() == RequirementReprKind::TypeConstraint); - return SecondType.getType(); - } - TypeRepr *getConstraintRepr() const { - assert(getKind() == RequirementReprKind::TypeConstraint); - return SecondType.getTypeRepr(); - } - - TypeLoc &getConstraintLoc() { - assert(getKind() == RequirementReprKind::TypeConstraint); - return SecondType; - } - - const TypeLoc &getConstraintLoc() const { assert(getKind() == RequirementReprKind::TypeConstraint); return SecondType; } @@ -1170,43 +1137,13 @@ class RequirementRepr { } /// Retrieve the first type of a same-type requirement. - Type getFirstType() const { - assert(getKind() == RequirementReprKind::SameType); - return FirstType.getType(); - } - TypeRepr *getFirstTypeRepr() const { - assert(getKind() == RequirementReprKind::SameType); - return FirstType.getTypeRepr(); - } - - TypeLoc &getFirstTypeLoc() { - assert(getKind() == RequirementReprKind::SameType); - return FirstType; - } - - const TypeLoc &getFirstTypeLoc() const { assert(getKind() == RequirementReprKind::SameType); return FirstType; } /// Retrieve the second type of a same-type requirement. - Type getSecondType() const { - assert(getKind() == RequirementReprKind::SameType); - return SecondType.getType(); - } - TypeRepr *getSecondTypeRepr() const { - assert(getKind() == RequirementReprKind::SameType); - return SecondType.getTypeRepr(); - } - - TypeLoc &getSecondTypeLoc() { - assert(getKind() == RequirementReprKind::SameType); - return SecondType; - } - - const TypeLoc &getSecondTypeLoc() const { assert(getKind() == RequirementReprKind::SameType); return SecondType; } @@ -1217,19 +1154,13 @@ class RequirementRepr { return SeparatorLoc; } - SourceRange getSourceRange() const { - if (getKind() == RequirementReprKind::LayoutConstraint) - return SourceRange(FirstType.getSourceRange().Start, - SecondLayout.getSourceRange().End); - return SourceRange(FirstType.getSourceRange().Start, - SecondType.getSourceRange().End); - } + SourceRange getSourceRange() const; /// Retrieve the first or subject type representation from the \c repr, /// or \c nullptr if \c repr is null. static TypeRepr *getFirstTypeRepr(const RequirementRepr *repr) { if (!repr) return nullptr; - return repr->FirstType.getTypeRepr(); + return repr->FirstType; } /// Retrieve the second or constraint type representation from the \c repr, @@ -1238,7 +1169,7 @@ class RequirementRepr { if (!repr) return nullptr; assert(repr->getKind() == RequirementReprKind::TypeConstraint || repr->getKind() == RequirementReprKind::SameType); - return repr->SecondType.getTypeRepr(); + return repr->SecondType; } SWIFT_DEBUG_DUMP; diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 75392765ce473..46d6b5ae0810a 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -441,7 +441,7 @@ class RequirementRequest : public SimpleRequest { + RequestFlags::Cached> { public: using SimpleRequest::SimpleRequest; @@ -464,10 +464,8 @@ class RequirementRequest : // Cycle handling. void noteCycleStep(DiagnosticEngine &diags) const; - // Separate caching. + // Caching. bool isCached() const; - Optional getCachedResult() const; - void cacheResult(Requirement value) const; }; /// Generate the USR for the given declaration. diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 4df761af7c2d2..2acdda4869312 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -176,7 +176,7 @@ SWIFT_REQUEST(TypeChecker, ProtocolRequiresClassRequest, bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, RequirementRequest, Requirement(WhereClauseOwner, unsigned, TypeResolutionStage), - SeparatelyCached, HasNearestLocation) + Cached, HasNearestLocation) SWIFT_REQUEST(TypeChecker, RequirementSignatureRequest, ArrayRef(ProtocolDecl *), SeparatelyCached, NoLocationInfo) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 4aef9bc3905ca..a8c26677f43bc 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -121,15 +121,7 @@ void RequirementRepr::dump() const { llvm::errs() << "\n"; } -void RequirementRepr::printImpl(ASTPrinter &out, bool AsWritten) const { - auto printTy = [&](const TypeLoc &TyLoc) { - if (AsWritten && TyLoc.getTypeRepr()) { - TyLoc.getTypeRepr()->print(out, PrintOptions()); - } else { - TyLoc.getType().print(out, PrintOptions()); - } - }; - +void RequirementRepr::printImpl(ASTPrinter &out) const { auto printLayoutConstraint = [&](const LayoutConstraintLoc &LayoutConstraintLoc) { LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions()); @@ -137,31 +129,41 @@ void RequirementRepr::printImpl(ASTPrinter &out, bool AsWritten) const { switch (getKind()) { case RequirementReprKind::LayoutConstraint: - printTy(getSubjectLoc()); + if (auto *repr = getSubjectRepr()) { + repr->print(out, PrintOptions()); + } out << " : "; printLayoutConstraint(getLayoutConstraintLoc()); break; case RequirementReprKind::TypeConstraint: - printTy(getSubjectLoc()); + if (auto *repr = getSubjectRepr()) { + repr->print(out, PrintOptions()); + } out << " : "; - printTy(getConstraintLoc()); + if (auto *repr = getConstraintRepr()) { + repr->print(out, PrintOptions()); + } break; case RequirementReprKind::SameType: - printTy(getFirstTypeLoc()); + if (auto *repr = getFirstTypeRepr()) { + repr->print(out, PrintOptions()); + } out << " == "; - printTy(getSecondTypeLoc()); + if (auto *repr = getSecondTypeRepr()) { + repr->print(out, PrintOptions()); + } break; } } void RequirementRepr::print(raw_ostream &out) const { StreamPrinter printer(out); - printImpl(printer, /*AsWritten=*/true); + printImpl(printer); } void RequirementRepr::print(ASTPrinter &out) const { - printImpl(out, /*AsWritten=*/true); + printImpl(out); } static void printTrailingRequirements(ASTPrinter &Printer, diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 57d4cda33ff27..e121f3528db75 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -1345,15 +1345,15 @@ class Traversal : public ASTVisitor genericParams; + SmallVector genericParams; for (unsigned i = 0; i != numParameters; ++i) genericParams.push_back(createGenericParam(ctx, GenericParamNames[i], i)); - - if (isAnyObject) { - CanType ao = ctx.getAnyObjectType(); - SmallVector req; - req.push_back(RequirementRepr::getTypeConstraint(TypeLoc::withoutLoc(genericParams[0]->getInterfaceType()), SourceLoc(), - TypeLoc::withoutLoc(ao))); - - auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams, - SourceLoc(), req, SourceLoc()); - return paramList; - } - auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams, SourceLoc()); return paramList; @@ -474,9 +461,15 @@ namespace { public: BuiltinFunctionBuilder(ASTContext &ctx, unsigned numGenericParams = 1, - bool isAnyObject = false) + bool wantsAdditionalAnyObjectRequirement = false) : Context(ctx) { - TheGenericParamList = getGenericParams(ctx, numGenericParams, isAnyObject); + TheGenericParamList = getGenericParams(ctx, numGenericParams); + if (wantsAdditionalAnyObjectRequirement) { + Requirement req(RequirementKind::Conformance, + TheGenericParamList->getParams()[0]->getInterfaceType(), + ctx.getAnyObjectType()); + addedRequirements.push_back(req); + } for (auto gp : TheGenericParamList->getParams()) { genericParamTypes.push_back( gp->getDeclaredInterfaceType()->castTo()); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 81706cee2a48b..53bede44749f5 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -875,6 +875,15 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const { return !fromContext.isContainedIn(containingContext); } + +SourceRange RequirementRepr::getSourceRange() const { + if (getKind() == RequirementReprKind::LayoutConstraint) + return SourceRange(FirstType->getSourceRange().Start, + SecondLayout.getSourceRange().End); + return SourceRange(FirstType->getSourceRange().Start, + SecondType->getSourceRange().End); +} + GenericParamList::GenericParamList(SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 36311b7f85644..156c511cb590e 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -857,8 +857,6 @@ SelfBoundsFromWhereClauseRequest::evaluate( if (auto identTypeRepr = dyn_cast(typeRepr)) isSelfLHS = (identTypeRepr->getNameRef().getBaseIdentifier() == ctx.Id_Self); - } else if (Type type = req.getSubject()) { - isSelfLHS = type->isEqual(dc->getSelfInterfaceType()); } if (!isSelfLHS) continue; @@ -867,8 +865,6 @@ SelfBoundsFromWhereClauseRequest::evaluate( DirectlyReferencedTypeDecls rhsDecls; if (auto typeRepr = req.getConstraintRepr()) { rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, lookupDC); - } else if (Type type = req.getConstraint()) { - rhsDecls = directReferencesForType(type); } SmallVector modulesFound; @@ -899,30 +895,24 @@ TypeDeclsFromWhereClauseRequest::evaluate(Evaluator &evaluator, ASTContext &ctx = ext->getASTContext(); TinyPtrVector result; + auto resolve = [&](TypeRepr *typeRepr) { + auto decls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext); + result.insert(result.end(), decls.begin(), decls.end()); + }; for (const auto &req : ext->getGenericParams()->getTrailingRequirements()) { - auto resolve = [&](TypeLoc loc) { - DirectlyReferencedTypeDecls decls; - if (auto *typeRepr = loc.getTypeRepr()) - decls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext); - else if (Type type = loc.getType()) - decls = directReferencesForType(type); - - result.insert(result.end(), decls.begin(), decls.end()); - }; - switch (req.getKind()) { case RequirementReprKind::TypeConstraint: - resolve(req.getSubjectLoc()); - resolve(req.getConstraintLoc()); + resolve(req.getSubjectRepr()); + resolve(req.getConstraintRepr()); break; case RequirementReprKind::SameType: - resolve(req.getFirstTypeLoc()); - resolve(req.getSecondTypeLoc()); + resolve(req.getFirstTypeRepr()); + resolve(req.getSecondTypeRepr()); break; case RequirementReprKind::LayoutConstraint: - resolve(req.getSubjectLoc()); + resolve(req.getSubjectRepr()); break; } } diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 6ecd7c87e2b50..41276bd6d1956 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -459,60 +459,6 @@ bool RequirementRequest::isCached() const { return std::get<2>(getStorage()) == TypeResolutionStage::Interface; } -Optional RequirementRequest::getCachedResult() const { - auto &reqRepr = getRequirement(); - switch (reqRepr.getKind()) { - case RequirementReprKind::TypeConstraint: - if (!reqRepr.getSubjectLoc().wasValidated() || - !reqRepr.getConstraintLoc().wasValidated()) - return None; - - return Requirement(reqRepr.getConstraint()->getClassOrBoundGenericClass() - ? RequirementKind::Superclass - : RequirementKind::Conformance, - reqRepr.getSubject(), - reqRepr.getConstraint()); - - case RequirementReprKind::SameType: - if (!reqRepr.getFirstTypeLoc().wasValidated() || - !reqRepr.getSecondTypeLoc().wasValidated()) - return None; - - return Requirement(RequirementKind::SameType, reqRepr.getFirstType(), - reqRepr.getSecondType()); - - case RequirementReprKind::LayoutConstraint: - if (!reqRepr.getSubjectLoc().wasValidated()) - return None; - - return Requirement(RequirementKind::Layout, reqRepr.getSubject(), - reqRepr.getLayoutConstraint()); - } - llvm_unreachable("unhandled kind"); -} - -void RequirementRequest::cacheResult(Requirement value) const { - auto &reqRepr = getRequirement(); - switch (value.getKind()) { - case RequirementKind::Conformance: - case RequirementKind::Superclass: - reqRepr.getSubjectLoc().setType(value.getFirstType()); - reqRepr.getConstraintLoc().setType(value.getSecondType()); - break; - - case RequirementKind::SameType: - reqRepr.getFirstTypeLoc().setType(value.getFirstType()); - reqRepr.getSecondTypeLoc().setType(value.getSecondType()); - break; - - case RequirementKind::Layout: - reqRepr.getSubjectLoc().setType(value.getFirstType()); - reqRepr.getLayoutConstraintLoc() - .setLayoutConstraint(value.getLayoutConstraint()); - break; - } -} - //----------------------------------------------------------------------------// // DefaultTypeRequest. //----------------------------------------------------------------------------// diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index f08dbc88235fc..90603b27bfbf3 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -174,7 +174,7 @@ namespace { /// A callback to be invoked every time a type was deserialized. std::function ParsedTypeCallback; - bool performTypeLocChecking(TypeLoc &T, bool IsSILType, + Type performTypeLocChecking(TypeRepr *TyR, bool IsSILType, GenericEnvironment *GenericEnv = nullptr); void convertRequirements(SILFunction *F, ArrayRef From, @@ -868,17 +868,15 @@ void SILParser::convertRequirements(SILFunction *F, IdentTypeReprLookup PerformLookup(P); // Use parser lexical scopes to resolve references // to the generic parameters. - auto ResolveToInterfaceType = [&](TypeLoc Ty) -> Type { - Ty.getTypeRepr()->walk(PerformLookup); - performTypeLocChecking(Ty, /* IsSIL */ false); - assert(Ty.getType()); - return Ty.getType()->mapTypeOutOfContext(); + auto ResolveToInterfaceType = [&](TypeRepr *Ty) -> Type { + Ty->walk(PerformLookup); + return performTypeLocChecking(Ty, /* IsSIL */ false)->mapTypeOutOfContext(); }; for (auto &Req : From) { if (Req.getKind() == RequirementReprKind::SameType) { - auto FirstType = ResolveToInterfaceType(Req.getFirstTypeLoc()); - auto SecondType = ResolveToInterfaceType(Req.getSecondTypeLoc()); + auto FirstType = ResolveToInterfaceType(Req.getFirstTypeRepr()); + auto SecondType = ResolveToInterfaceType(Req.getSecondTypeRepr()); Requirement ConvertedRequirement(RequirementKind::SameType, FirstType, SecondType); To.push_back(ConvertedRequirement); @@ -886,8 +884,8 @@ void SILParser::convertRequirements(SILFunction *F, } if (Req.getKind() == RequirementReprKind::TypeConstraint) { - auto Subject = ResolveToInterfaceType(Req.getSubjectLoc()); - auto Constraint = ResolveToInterfaceType(Req.getConstraintLoc()); + auto Subject = ResolveToInterfaceType(Req.getSubjectRepr()); + auto Constraint = ResolveToInterfaceType(Req.getConstraintRepr()); Requirement ConvertedRequirement(RequirementKind::Conformance, Subject, Constraint); To.push_back(ConvertedRequirement); @@ -895,7 +893,7 @@ void SILParser::convertRequirements(SILFunction *F, } if (Req.getKind() == RequirementReprKind::LayoutConstraint) { - auto Subject = ResolveToInterfaceType(Req.getSubjectLoc()); + auto Subject = ResolveToInterfaceType(Req.getSubjectRepr()); Requirement ConvertedRequirement(RequirementKind::Layout, Subject, Req.getLayoutConstraint()); To.push_back(ConvertedRequirement); @@ -1094,14 +1092,16 @@ static bool parseDeclSILOptional(bool *isTransparent, return false; } -bool SILParser::performTypeLocChecking(TypeLoc &T, bool IsSILType, +Type SILParser::performTypeLocChecking(TypeRepr *T, bool IsSILType, GenericEnvironment *GenericEnv) { if (GenericEnv == nullptr) GenericEnv = ContextGenericEnv; - return swift::performTypeLocChecking(P.Context, T, + TypeLoc loc(T); + (void) swift::performTypeLocChecking(P.Context, loc, /*isSILMode=*/true, IsSILType, GenericEnv, &P.SF); + return loc.getType(); } /// Find the top-level ValueDecl or Module given a name. @@ -1155,17 +1155,17 @@ static ValueDecl *lookupMember(Parser &P, Type Ty, DeclBaseName Name, bool SILParser::parseASTType(CanType &result, GenericEnvironment *env) { ParserResult parsedType = P.parseType(); if (parsedType.isNull()) return true; - TypeLoc loc = parsedType.get(); - if (performTypeLocChecking(loc, /*IsSILType=*/ false, env)) + auto resolvedType = performTypeLocChecking(parsedType.get(), /*IsSILType=*/ false, env); + if (resolvedType->hasError()) return true; if (env) - result = loc.getType()->mapTypeOutOfContext()->getCanonicalType(); + result = resolvedType->mapTypeOutOfContext()->getCanonicalType(); else - result = loc.getType()->getCanonicalType(); + result = resolvedType->getCanonicalType(); // Invoke the callback on the parsed type. - ParsedTypeCallback(loc.getType()); + ParsedTypeCallback(resolvedType); return false; } @@ -1244,16 +1244,16 @@ bool SILParser::parseSILType(SILType &Result, ParsedGenericEnv = env; // Apply attributes to the type. - TypeLoc Ty = P.applyAttributeToType(TyR.get(), attrs, specifier, specifierLoc); - - if (performTypeLocChecking(Ty, /*IsSILType=*/true, OuterGenericEnv)) + auto *attrRepr = P.applyAttributeToType(TyR.get(), attrs, specifier, specifierLoc); + auto Ty = performTypeLocChecking(attrRepr, /*IsSILType=*/true, OuterGenericEnv); + if (Ty->hasError()) return true; - Result = SILType::getPrimitiveType(Ty.getType()->getCanonicalType(), + Result = SILType::getPrimitiveType(Ty->getCanonicalType(), category); // Invoke the callback on the parsed type. - ParsedTypeCallback(Ty.getType()); + ParsedTypeCallback(Ty); return false; } @@ -1644,34 +1644,34 @@ bool SILParser::parseSILBBArgsAtBranch(SmallVector &Args, /// /// FIXME: This is a hack to work around the lack of a DeclContext for /// witness tables. -static void bindProtocolSelfInTypeRepr(TypeLoc &TL, ProtocolDecl *proto) { - if (auto typeRepr = TL.getTypeRepr()) { - // AST walker to update 'Self' references. - class BindProtocolSelf : public ASTWalker { - ProtocolDecl *proto; - GenericTypeParamDecl *selfParam; - Identifier selfId; - - public: - BindProtocolSelf(ProtocolDecl *proto) - : proto(proto), - selfParam(proto->getProtocolSelfType()->getDecl()), - selfId(proto->getASTContext().Id_Self) { - } +static void bindProtocolSelfInTypeRepr(TypeRepr *typeRepr, ProtocolDecl *proto) { + assert(typeRepr); - virtual bool walkToTypeReprPre(TypeRepr *T) override { - if (auto ident = dyn_cast(T)) { - auto firstComponent = ident->getComponentRange().front(); - if (firstComponent->getNameRef().isSimpleName(selfId)) - firstComponent->setValue(selfParam, proto); - } + // AST walker to update 'Self' references. + class BindProtocolSelf : public ASTWalker { + ProtocolDecl *proto; + GenericTypeParamDecl *selfParam; + Identifier selfId; - return true; + public: + BindProtocolSelf(ProtocolDecl *proto) + : proto(proto), + selfParam(proto->getProtocolSelfType()->getDecl()), + selfId(proto->getASTContext().Id_Self) { + } + + virtual bool walkToTypeReprPre(TypeRepr *T) override { + if (auto ident = dyn_cast(T)) { + auto firstComponent = ident->getComponentRange().front(); + if (firstComponent->getNameRef().isSimpleName(selfId)) + firstComponent->setValue(selfParam, proto); } - }; - typeRepr->walk(BindProtocolSelf(proto)); - } + return true; + } + }; + + typeRepr->walk(BindProtocolSelf(proto)); } /// Parse the substitution list for an apply instruction or @@ -1693,12 +1693,13 @@ bool SILParser::parseSubstitutions(SmallVectorImpl &parsed, ParserResult TyR = P.parseType(); if (TyR.isNull()) return true; - TypeLoc Ty = TyR.get(); if (defaultForProto) - bindProtocolSelfInTypeRepr(Ty, defaultForProto); - if (performTypeLocChecking(Ty, /*IsSILType=*/ false, GenericEnv)) + bindProtocolSelfInTypeRepr(TyR.get(), defaultForProto); + + auto Ty = performTypeLocChecking(TyR.get(), /*IsSILType=*/ false, GenericEnv); + if (Ty->hasError()) return true; - parsed.push_back({Loc, Ty.getType()}); + parsed.push_back({Loc, Ty}); } while (P.consumeIf(tok::comma)); // Consume the closing '>'. @@ -2090,31 +2091,27 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Member, bool FnTypeRequired) { GenericsScope.reset(); if (TyR.isNull()) return true; - TypeLoc Ty = TyR.get(); // The type can be polymorphic. GenericEnvironment *genericEnv = nullptr; if (auto fnType = dyn_cast(TyR.get())) { if (auto generics = fnType->getGenericParams()) { - assert(!Ty.wasValidated() && Ty.getType().isNull()); - genericEnv = handleSILGenericParams(generics, &P.SF); fnType->setGenericEnvironment(genericEnv); } if (auto generics = fnType->getPatternGenericParams()) { - assert(!Ty.wasValidated() && Ty.getType().isNull()); - genericEnv = handleSILGenericParams(generics, &P.SF); fnType->setPatternGenericEnvironment(genericEnv); } } - if (performTypeLocChecking(Ty, /*IsSILType=*/ false, genericEnv)) + auto Ty = performTypeLocChecking(TyR.get(), /*IsSILType=*/ false, genericEnv); + if (Ty->hasError()) return true; // Pick the ValueDecl that has the right type. ValueDecl *TheDecl = nullptr; - auto declTy = Ty.getType()->getCanonicalType(); + auto declTy = Ty->getCanonicalType(); for (unsigned I = 0, E = values.size(); I < E; ++I) { auto *decl = values[I]; @@ -6306,14 +6303,13 @@ ProtocolConformanceRef SILParser::parseProtocolConformanceHelper( ParserResult TyR = P.parseType(); if (TyR.isNull()) return ProtocolConformanceRef(); - TypeLoc Ty = TyR.get(); if (defaultForProto) { - bindProtocolSelfInTypeRepr(Ty, defaultForProto); + bindProtocolSelfInTypeRepr(TyR.get(), defaultForProto); } - if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv)) + auto ConformingTy = performTypeLocChecking(TyR.get(), /*IsSILType=*/ false, witnessEnv); + if (ConformingTy->hasError()) return ProtocolConformanceRef(); - auto ConformingTy = Ty.getType(); if (P.parseToken(tok::colon, diag::expected_sil_witness_colon)) return ProtocolConformanceRef(); @@ -6429,7 +6425,7 @@ static bool parseSILVTableEntry( return true; TypeLoc Ty = TyR.get(); if (isDefaultWitnessTable) - bindProtocolSelfInTypeRepr(Ty, proto); + bindProtocolSelfInTypeRepr(TyR.get(), proto); if (swift::performTypeLocChecking(P.Context, Ty, /*isSILMode=*/false, /*isSILType=*/false, @@ -6490,7 +6486,7 @@ static bool parseSILVTableEntry( return true; TypeLoc Ty = TyR.get(); if (isDefaultWitnessTable) - bindProtocolSelfInTypeRepr(Ty, proto); + bindProtocolSelfInTypeRepr(TyR.get(), proto); if (swift::performTypeLocChecking(P.Context, Ty, /*isSILMode=*/false, /*isSILType=*/false, diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 912161abf0f84..f28617e430ebd 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -924,7 +924,7 @@ static void checkProtocolSelfRequirements(ProtocolDecl *proto, if (reqRepr && req.getFirstType()->isEqual(proto->getSelfInterfaceType())) { auto &diags = proto->getASTContext().Diags; - diags.diagnose(reqRepr->getSubjectLoc().getLoc(), + diags.diagnose(reqRepr->getSubjectRepr()->getLoc(), diag::protocol_where_clause_self_requirement); } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index ee60881ea9634..c18cc16e3d965 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -931,21 +931,11 @@ RequirementRequest::evaluate(Evaluator &evaluator, llvm_unreachable("No clients care about this. Use mapTypeIntoContext()"); } - auto resolveType = [&](TypeLoc &typeLoc) -> Type { - Type result; - if (auto typeRepr = typeLoc.getTypeRepr()) - result = resolution->resolveType(typeRepr); - else - result = typeLoc.getType(); - - return result ? result : ErrorType::get(owner.dc->getASTContext()); - }; - auto &reqRepr = getRequirement(); switch (reqRepr.getKind()) { case RequirementReprKind::TypeConstraint: { - Type subject = resolveType(reqRepr.getSubjectLoc()); - Type constraint = resolveType(reqRepr.getConstraintLoc()); + Type subject = resolution->resolveType(reqRepr.getSubjectRepr()); + Type constraint = resolution->resolveType(reqRepr.getConstraintRepr()); return Requirement(constraint->getClassOrBoundGenericClass() ? RequirementKind::Superclass : RequirementKind::Conformance, @@ -954,12 +944,12 @@ RequirementRequest::evaluate(Evaluator &evaluator, case RequirementReprKind::SameType: return Requirement(RequirementKind::SameType, - resolveType(reqRepr.getFirstTypeLoc()), - resolveType(reqRepr.getSecondTypeLoc())); + resolution->resolveType(reqRepr.getFirstTypeRepr()), + resolution->resolveType(reqRepr.getSecondTypeRepr())); case RequirementReprKind::LayoutConstraint: return Requirement(RequirementKind::Layout, - resolveType(reqRepr.getSubjectLoc()), + resolution->resolveType(reqRepr.getSubjectRepr()), reqRepr.getLayoutConstraint()); } llvm_unreachable("unhandled kind"); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index b9cd51877744e..b674225c27244 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -3103,43 +3103,57 @@ diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) { /// /// \returns None if there is no such constraint; a non-empty optional that /// may have the \c RequirementRepr for the actual constraint. -static Optional +static Optional> getAdopteeSelfSameTypeConstraint(ClassDecl *selfClass, ValueDecl *witness) { auto genericSig = witness->getInnermostDeclContext()->getGenericSignatureOfContext(); if (!genericSig) return None; - for (const auto &req : genericSig->getRequirements()) { + // First, search for any bogus requirements. + auto it = llvm::find_if(genericSig->getRequirements(), + [&selfClass](const auto &req) { if (req.getKind() != RequirementKind::SameType) - continue; + return false; - if (req.getFirstType()->getAnyNominal() == selfClass || - req.getSecondType()->getAnyNominal() == selfClass) { - // Try to find the requirement-as-written. - GenericParamList *genericParams = nullptr; - - if (auto func = dyn_cast(witness)) - genericParams = func->getGenericParams(); - else if (auto subscript = dyn_cast(witness)) - genericParams = subscript->getGenericParams(); - if (genericParams) { - for (auto &req : genericParams->getRequirements()) { - if (req.getKind() != RequirementReprKind::SameType) - continue; + return req.getFirstType()->getAnyNominal() == selfClass + || req.getSecondType()->getAnyNominal() == selfClass; + }); + if (it == genericSig->getRequirements().end()) { + return None; + } - if (req.getFirstType()->getAnyNominal() == selfClass || - req.getSecondType()->getAnyNominal() == selfClass) - return &req; - } - } + // Got it! Now try to find the requirement-as-written. + GenericParamList *genericParams = nullptr; + if (auto func = dyn_cast(witness)) + genericParams = func->getGenericParams(); + else if (auto subscript = dyn_cast(witness)) + genericParams = subscript->getGenericParams(); - // Form an optional(nullptr) to indicate that we don't have the - // requirement itself. - return nullptr; - } + // A null repr indicates we don't have a valid location to diagnose. But + // at least we have a requirement we can signal is bogus. + Optional> target + = std::make_pair((RequirementRepr *)nullptr, Requirement(*it)); + if (!genericParams) { + return target; } - return None; + // Resolve and search for a written requirement to match our bogus one. + WhereClauseOwner(cast(witness), genericParams) + .visitRequirements(TypeResolutionStage::Structural, + [&](Requirement req, RequirementRepr *repr) { + if (req.getKind() != RequirementKind::SameType) { + return false; + } + + if (req.getFirstType()->getAnyNominal() != selfClass && + req.getSecondType()->getAnyNominal() != selfClass) { + return false; + } + + target.emplace(repr, req); + return true; + }); + return target; } void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, @@ -3239,7 +3253,7 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, }); } } else if (selfKind.requirement) { - if (auto constraint = getAdopteeSelfSameTypeConstraint(classDecl, + if (auto targetPair = getAdopteeSelfSameTypeConstraint(classDecl, witness)) { // A "Self ==" constraint works incorrectly with subclasses. Complain. auto proto = Conformance->getProtocol(); @@ -3254,11 +3268,11 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, proto->getDeclaredType()); emitDeclaredHereIfNeeded(diags, diagLoc, witness); - if (auto requirementRepr = *constraint) { + if (auto requirementRepr = targetPair->first) { diags.diagnose(requirementRepr->getSeparatorLoc(), diag::witness_self_weaken_same_type, - requirementRepr->getFirstType(), - requirementRepr->getSecondType()) + targetPair->second.getFirstType(), + targetPair->second.getSecondType()) .fixItReplace(requirementRepr->getSeparatorLoc(), ":"); } } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 3f368011f8aa1..9d142ebf69ad7 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -3804,9 +3804,9 @@ class UnsupportedProtocolVisitor void visitRequirements(ArrayRef reqts) { for (auto reqt : reqts) { if (reqt.getKind() == RequirementReprKind::SameType) { - if (auto *repr = reqt.getFirstTypeLoc().getTypeRepr()) + if (auto *repr = reqt.getFirstTypeRepr()) repr->walk(*this); - if (auto *repr = reqt.getSecondTypeLoc().getTypeRepr()) + if (auto *repr = reqt.getSecondTypeRepr()) repr->walk(*this); } }