diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index bc42a441ed2..02d8a479337 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -58,9 +58,6 @@ public: using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias using BuiltProtocolDecl = swift::ProtocolDecl *; explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {} - - /// The resolver to use for type checking, if necessary. - LazyResolver *Resolver = nullptr; ASTContext &getASTContext() { return Ctx; } DeclContext *getNotionalDC(); diff --git a/include/swift/AST/ASTTypeIDZone.def b/include/swift/AST/ASTTypeIDZone.def index 2ca97768b86..2d76e236bc7 100644 --- a/include/swift/AST/ASTTypeIDZone.def +++ b/include/swift/AST/ASTTypeIDZone.def @@ -33,6 +33,7 @@ SWIFT_TYPEID_NAMED(InfixOperatorDecl *, InfixOperatorDecl) SWIFT_TYPEID_NAMED(IterableDeclContext *, IterableDeclContext) SWIFT_TYPEID_NAMED(ModuleDecl *, ModuleDecl) SWIFT_TYPEID_NAMED(NominalTypeDecl *, NominalTypeDecl) +SWIFT_TYPEID_NAMED(OpaqueTypeDecl *, OpaqueTypeDecl) SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl) SWIFT_TYPEID_NAMED(Optional, PropertyWrapperMutability) diff --git a/include/swift/AST/ASTTypeIDs.h b/include/swift/AST/ASTTypeIDs.h index c05fde9e2d9..58eb5af7dac 100644 --- a/include/swift/AST/ASTTypeIDs.h +++ b/include/swift/AST/ASTTypeIDs.h @@ -34,6 +34,7 @@ class IterableDeclContext; class ModuleDecl; class NominalTypeDecl; class OperatorDecl; +class OpaqueTypeDecl; class PrecedenceGroupDecl; struct PropertyWrapperBackingPropertyInfo; struct PropertyWrapperTypeInfo; diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 571dffe1cc6..ac29577fd8a 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -418,7 +418,10 @@ protected: HasSingleExpressionBody : 1 ); - SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+2+1+1+2, + SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2, + /// Whether we've computed the 'static' flag yet. + IsStaticComputed : 1, + /// Whether this function is a 'static' method. IsStatic : 1, @@ -854,17 +857,6 @@ public: return getValidationState() > ValidationState::Unchecked; } - /// Manually indicate that validation is complete for the declaration. For - /// example: during importing, code synthesis, or derived conformances. - /// - /// For normal code validation, please use DeclValidationRAII instead. - /// - /// FIXME -- Everything should use DeclValidationRAII instead of this. - void setValidationToChecked() { - if (!isBeingValidated()) - Bits.Decl.ValidationState = unsigned(ValidationState::Checked); - } - bool escapedFromIfConfig() const { return Bits.Decl.EscapedFromIfConfig; } @@ -2605,6 +2597,9 @@ public: /// if the base declaration is \c open, the override might have to be too. bool hasOpenAccess(const DeclContext *useDC) const; + /// FIXME: This is deprecated. + bool isRecursiveValidation() const; + /// Retrieve the "interface" type of this value, which uses /// GenericTypeParamType if the declaration is generic. For a generic /// function, this will have a GenericFunctionType with a @@ -2764,12 +2759,6 @@ public: /// Get the representative for this value's opaque result type, if it has one. OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() const; - /// Set the opaque return type decl for this decl. - /// - /// `this` must be of a decl type that supports opaque return types, and - /// must not have previously had an opaque result type set. - void setOpaqueResultTypeDecl(OpaqueTypeDecl *D); - /// Retrieve the attribute associating this declaration with a /// function builder, if there is one. CustomAttr *getAttachedFunctionBuilder() const; @@ -4530,8 +4519,6 @@ protected: Bits.AbstractStorageDecl.IsStatic = IsStatic; } - OpaqueTypeDecl *OpaqueReturn = nullptr; - public: /// Should this declaration be treated as if annotated with transparent @@ -4789,14 +4776,6 @@ public: bool hasAnyDynamicReplacementAccessors() const; - OpaqueTypeDecl *getOpaqueResultTypeDecl() const { - return OpaqueReturn; - } - void setOpaqueResultTypeDecl(OpaqueTypeDecl *decl) { - assert(!OpaqueReturn && "already has opaque type decl"); - OpaqueReturn = decl; - } - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractStorageDecl && @@ -5976,14 +5955,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK); class FuncDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; friend class SelfAccessKindRequest; + friend class IsStaticRequest; SourceLoc StaticLoc; // Location of the 'static' token or invalid. SourceLoc FuncLoc; // Location of the 'func' token. TypeLoc FnRetType; - OpaqueTypeDecl *OpaqueReturn = nullptr; - protected: FuncDecl(DeclKind Kind, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, @@ -5999,14 +5977,14 @@ protected: StaticLoc(StaticLoc), FuncLoc(FuncLoc) { assert(!Name.getBaseName().isSpecial()); - Bits.FuncDecl.IsStatic = - StaticLoc.isValid() || StaticSpelling != StaticSpellingKind::None; Bits.FuncDecl.StaticSpelling = static_cast(StaticSpelling); Bits.FuncDecl.ForcedStaticDispatch = false; Bits.FuncDecl.SelfAccess = static_cast(SelfAccessKind::NonMutating); Bits.FuncDecl.SelfAccessComputed = false; + Bits.FuncDecl.IsStaticComputed = false; + Bits.FuncDecl.IsStatic = false; } private: @@ -6026,6 +6004,13 @@ private: return None; } + Optional getCachedIsStatic() const { + if (Bits.FuncDecl.IsStaticComputed) + return Bits.FuncDecl.IsStatic; + + return None; + } + public: /// Factory function only for use by deserialization. static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc, @@ -6048,9 +6033,8 @@ public: Identifier getName() const { return getFullName().getBaseIdentifier(); } - bool isStatic() const { - return Bits.FuncDecl.IsStatic; - } + bool isStatic() const; + /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast(Bits.FuncDecl.StaticSpelling); @@ -6058,6 +6042,7 @@ public: /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; void setStatic(bool IsStatic = true) { + Bits.FuncDecl.IsStaticComputed = true; Bits.FuncDecl.IsStatic = IsStatic; } @@ -6129,15 +6114,7 @@ public: } OperatorDecl *getOperatorDecl() const; - - OpaqueTypeDecl *getOpaqueResultTypeDecl() const { - return OpaqueReturn; - } - void setOpaqueResultTypeDecl(OpaqueTypeDecl *decl) { - assert(!OpaqueReturn && "already has opaque type decl"); - OpaqueReturn = decl; - } - + /// Returns true if the function is forced to be statically dispatched. bool hasForcedStaticDispatch() const { return Bits.FuncDecl.ForcedStaticDispatch; diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index c5fb6bb45a7..b4a3a9975a3 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -381,7 +381,7 @@ ERROR(cannot_convert_argument_value,none, (Type,Type)) NOTE(candidate_has_invalid_argument_at_position,none, - "candidate expects value of type %0 at position #%1", + "candidate expects value of type %0 for parameter #%1", (Type, unsigned)) ERROR(cannot_convert_array_to_variadic,none, diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index ba9997879c3..c58f8c194a0 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -60,8 +60,7 @@ public: /// Look up an opaque return type by the mangled name of the declaration /// that defines it. - virtual OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver) { + virtual OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName) { return nullptr; } diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 801fa0caef3..e74e344c20f 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -354,8 +354,7 @@ public: /// Look up an opaque return type by the mangled name of the declaration /// that defines it. - OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver); + OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName); /// Find ValueDecls in the module and pass them to the given consumer object. /// diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index b58966009fb..d0b92bb017b 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -117,6 +117,13 @@ private: /// The scope map that describes this source file. std::unique_ptr Scope; + /// The set of validated opaque return type decls in the source file. + llvm::SmallVector OpaqueReturnTypes; + llvm::StringMap ValidatedOpaqueReturnTypes; + /// The set of parsed decls with opaque return types that have not yet + /// been validated. + llvm::SetVector UnvalidatedDeclsWithOpaqueReturnTypes; + friend ASTContext; friend Impl; public: @@ -130,13 +137,6 @@ public: /// The list of local type declarations in the source file. llvm::SetVector LocalTypeDecls; - /// The set of validated opaque return type decls in the source file. - llvm::SmallVector OpaqueReturnTypes; - llvm::StringMap ValidatedOpaqueReturnTypes; - /// The set of parsed decls with opaque return types that have not yet - /// been validated. - llvm::DenseSet UnvalidatedDeclsWithOpaqueReturnTypes; - /// A set of special declaration attributes which require the /// Foundation module to be imported to work. If the foundation /// module is still not imported by the time type checking is @@ -430,14 +430,13 @@ public: void setSyntaxRoot(syntax::SourceFileSyntax &&Root); bool hasSyntaxRoot() const; - OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver) override; + OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName) override; void addUnvalidatedDeclWithOpaqueResultType(ValueDecl *vd) { UnvalidatedDeclsWithOpaqueReturnTypes.insert(vd); } - void markDeclWithOpaqueResultTypeAsValidated(ValueDecl *vd); + ArrayRef getOpaqueReturnTypeDecls(); private: diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 510a7c21032..68fa3b366bf 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1188,7 +1188,7 @@ public: void cacheResult(GenericSignature value) const; }; -/// Compute the interface type of the underlying definition type of a typealias declaration. +/// Compute the underlying interface type of a typealias. class UnderlyingTypeRequest : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + llvm::Expected + evaluate(Evaluator &evaluator, ValueDecl *VD) const; + +public: + // Caching. + bool isCached() const { return true; } +}; + +/// Determines if a function declaration is 'static'. +class IsStaticRequest : + public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + llvm::Expected + evaluate(Evaluator &evaluator, FuncDecl *value) const; + +public: + // Separate caching. + bool isCached() const { return true; } + Optional getCachedResult() const; + void cacheResult(bool value) const; +}; + // Allow AnyValue to compare two Type values, even though Type doesn't // support ==. template<> diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index c5e56a34a6a..3542963587b 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -88,6 +88,9 @@ SWIFT_REQUEST(TypeChecker, MangleLocalTypeDeclRequest, SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest, OpaqueReadOwnership(AbstractStorageDecl *), SeparatelyCached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest, + OpaqueTypeDecl *(ValueDecl *), + Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest, PrecedenceGroupDecl *(PrecedenceGroupDecl *), Cached, NoLocationInfo) @@ -144,3 +147,5 @@ SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest, bool(ValueDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, IsStaticRequest, + bool(FuncDecl *), SeparatelyCached, NoLocationInfo) diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 176d3fdfd87..e0577e1617f 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -36,9 +36,6 @@ namespace swift { class ValueDecl; class DeclName; - /// Typecheck a declaration parsed during code completion. - void typeCheckCompletionDecl(Decl *D); - /// Typecheck binding initializer at \p bindingIndex. void typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex); diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 758523419a0..cb1c1858141 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -278,7 +278,7 @@ public: virtual TypeDecl *lookupLocalType(StringRef MangledName) const override; virtual OpaqueTypeDecl * - lookupOpaqueResultType(StringRef MangledName, LazyResolver *resolver) override; + lookupOpaqueResultType(StringRef MangledName) override; virtual TypeDecl * lookupNestedType(Identifier name, diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index bb081f93a11..a20c44139c7 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -259,8 +259,7 @@ Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, if (!parentModule) return Type(); - auto opaqueDecl = parentModule->lookupOpaqueResultType(mangledName, - Resolver); + auto opaqueDecl = parentModule->lookupOpaqueResultType(mangledName); if (!opaqueDecl) return Type(); // TODO: multiple opaque types diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 0dc2435d1f4..4100d80450d 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -3190,12 +3190,6 @@ public: void verifyParsed(AccessorDecl *FD) { PrettyStackTraceDecl debugStack("verifying AccessorDecl", FD); - auto storage = FD->getStorage(); - if (storage->isStatic() != FD->isStatic()) { - Out << "accessor static-ness must match static-ness of storage\n"; - abort(); - } - verifyParsedBase(FD); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3808f1c99e7..5feea9a2a51 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2580,7 +2580,22 @@ void ValueDecl::setOverriddenDecls(ArrayRef overridden) { OpaqueReturnTypeRepr *ValueDecl::getOpaqueResultTypeRepr() const { TypeLoc returnLoc; if (auto *VD = dyn_cast(this)) { - returnLoc = VD->getTypeLoc(); + if (auto *P = VD->getParentPattern()) { + while (auto *PP = dyn_cast(P)) + P = PP->getSubPattern(); + + if (auto *TP = dyn_cast(P)) { + P = P->getSemanticsProvidingPattern(); + if (auto *NP = dyn_cast(P)) { + assert(NP->getDecl() == VD); + (void) NP; + + returnLoc = TP->getTypeLoc(); + } + } + } else { + returnLoc = VD->getTypeLoc(); + } } else if (auto *FD = dyn_cast(this)) { returnLoc = FD->getBodyResultTypeLoc(); } else if (auto *SD = dyn_cast(this)) { @@ -2591,23 +2606,12 @@ OpaqueReturnTypeRepr *ValueDecl::getOpaqueResultTypeRepr() const { } OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const { - if (auto func = dyn_cast(this)) { - return func->getOpaqueResultTypeDecl(); - } else if (auto storage = dyn_cast(this)) { - return storage->getOpaqueResultTypeDecl(); - } else { + if (getOpaqueResultTypeRepr() == nullptr) return nullptr; - } -} -void ValueDecl::setOpaqueResultTypeDecl(OpaqueTypeDecl *D) { - if (auto func = dyn_cast(this)) { - func->setOpaqueResultTypeDecl(D); - } else if (auto storage = dyn_cast(this)){ - storage->setOpaqueResultTypeDecl(D); - } else { - llvm_unreachable("decl does not support opaque result types"); - } + return evaluateOrDefault(getASTContext().evaluator, + OpaqueResultTypeRequest{const_cast(this)}, + nullptr); } bool ValueDecl::isObjC() const { @@ -2701,6 +2705,27 @@ bool ValueDecl::hasInterfaceType() const { return !TypeAndAccess.getPointer().isNull(); } +bool ValueDecl::isRecursiveValidation() const { + if (hasValidationStarted() && !hasInterfaceType()) + return true; + + if (auto *vd = dyn_cast(this)) + if (auto *pbd = vd->getParentPatternBinding()) + if (pbd->isBeingValidated()) + return true; + + auto *dc = getDeclContext(); + while (isa(dc)) + dc = dc->getParent(); + + if (auto *ext = dyn_cast(dc)) { + if (ext->isComputingGenericSignature()) + return true; + } + + return false; +} + Type ValueDecl::getInterfaceType() const { if (!hasInterfaceType()) { // Our clients that don't register the lazy resolver are relying on the @@ -6876,7 +6901,14 @@ OperatorDecl *FuncDecl::getOperatorDecl() const { const_cast(this) }, nullptr); - } +} + +bool FuncDecl::isStatic() const { + ASTContext &ctx = getASTContext(); + return evaluateOrDefault(ctx.evaluator, + IsStaticRequest{const_cast(this)}, + false); +} AccessorDecl *AccessorDecl::createImpl(ASTContext &ctx, SourceLoc declLoc, diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 109adc29df9..0682f69efa8 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -475,10 +475,9 @@ TypeDecl * ModuleDecl::lookupLocalType(StringRef MangledName) const { } OpaqueTypeDecl * -ModuleDecl::lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver) { +ModuleDecl::lookupOpaqueResultType(StringRef MangledName) { for (auto file : getFiles()) { - auto OTD = file->lookupOpaqueResultType(MangledName, resolver); + auto OTD = file->lookupOpaqueResultType(MangledName); if (OTD) return OTD; } @@ -670,9 +669,8 @@ void SourceFile::getLocalTypeDecls(SmallVectorImpl &Results) const { void SourceFile::getOpaqueReturnTypeDecls(SmallVectorImpl &Results) const { - for (auto &member : ValidatedOpaqueReturnTypes) { - Results.push_back(member.second); - } + auto result = const_cast(this)->getOpaqueReturnTypeDecls(); + llvm::copy(result, std::back_inserter(Results)); } TypeDecl *SourceFile::lookupLocalType(llvm::StringRef mangledName) const { @@ -1806,9 +1804,24 @@ void SourceFile::createReferencedNameTracker() { ReferencedNames.emplace(ReferencedNameTracker()); } +ArrayRef SourceFile::getOpaqueReturnTypeDecls() { + for (auto *vd : UnvalidatedDeclsWithOpaqueReturnTypes) { + if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) { + auto inserted = ValidatedOpaqueReturnTypes.insert( + {opaqueDecl->getOpaqueReturnTypeIdentifier().str(), + opaqueDecl}); + if (inserted.second) { + OpaqueReturnTypes.push_back(opaqueDecl); + } + } + } + + UnvalidatedDeclsWithOpaqueReturnTypes.clear(); + return OpaqueReturnTypes; +} + OpaqueTypeDecl * -SourceFile::lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver) { +SourceFile::lookupOpaqueResultType(StringRef MangledName) { // Check already-validated decls. auto found = ValidatedOpaqueReturnTypes.find(MangledName); if (found != ValidatedOpaqueReturnTypes.end()) @@ -1816,34 +1829,16 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName, // If there are unvalidated decls with opaque types, go through and validate // them now. - if (resolver && !UnvalidatedDeclsWithOpaqueReturnTypes.empty()) { - while (!UnvalidatedDeclsWithOpaqueReturnTypes.empty()) { - ValueDecl *decl = *UnvalidatedDeclsWithOpaqueReturnTypes.begin(); - UnvalidatedDeclsWithOpaqueReturnTypes.erase(decl); - // FIXME(InterfaceTypeRequest): Remove this. - (void)decl->getInterfaceType(); - } - - found = ValidatedOpaqueReturnTypes.find(MangledName); - if (found != ValidatedOpaqueReturnTypes.end()) - return found->second; - } + (void) getOpaqueReturnTypeDecls(); + + found = ValidatedOpaqueReturnTypes.find(MangledName); + if (found != ValidatedOpaqueReturnTypes.end()) + return found->second; // Otherwise, we don't have a matching opaque decl. return nullptr; } -void SourceFile::markDeclWithOpaqueResultTypeAsValidated(ValueDecl *vd) { - UnvalidatedDeclsWithOpaqueReturnTypes.erase(vd); - if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) { - auto inserted = ValidatedOpaqueReturnTypes.insert( - {opaqueDecl->getOpaqueReturnTypeIdentifier().str(), opaqueDecl}); - if (inserted.second) { - OpaqueReturnTypes.push_back(opaqueDecl); - } - } -} - //===----------------------------------------------------------------------===// // Miscellaneous //===----------------------------------------------------------------------===// diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index a96fc809be2..a66c80fd000 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -487,9 +487,9 @@ static void recordShadowedDecls(ArrayRef decls, // If the decl is currently being validated, this is likely a recursive // reference and we'll want to skip ahead so as to avoid having its type // attempt to desugar itself. - auto ifaceType = decl->getInterfaceType(); - if (!ifaceType) + if (decl->isRecursiveValidation()) continue; + auto ifaceType = decl->getInterfaceType(); // FIXME: the canonical type makes a poor signature, because we don't // canonicalize away default arguments. diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 2d5f98e164d..dae693e6467 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -895,3 +895,17 @@ void EnumRawValuesRequest::diagnoseCycle(DiagnosticEngine &diags) const { void EnumRawValuesRequest::noteCycleStep(DiagnosticEngine &diags) const { } + +//----------------------------------------------------------------------------// +// IsStaticRequest computation. +//----------------------------------------------------------------------------// + +Optional IsStaticRequest::getCachedResult() const { + auto *FD = std::get<0>(getStorage()); + return FD->getCachedIsStatic(); +} + +void IsStaticRequest::cacheResult(bool result) const { + auto *FD = std::get<0>(getStorage()); + FD->setStatic(result); +} \ No newline at end of file diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 5ef47a964d1..90b5ef280b9 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -52,6 +52,8 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { case DeclContextKind::SerializedLocal: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::EnumElementDecl: + case DeclContextKind::GenericTypeDecl: + case DeclContextKind::SubscriptDecl: // Nothing to do for these. break; @@ -61,7 +63,7 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { auto i = patternInit->getBindingIndex(); if (PBD->getInit(i)) { PBD->getPattern(i)->forEachVariable([](VarDecl *VD) { - typeCheckCompletionDecl(VD); + (void) VD->getInterfaceType(); }); if (!PBD->isInitializerChecked(i)) typeCheckPatternBinding(PBD, i); @@ -72,29 +74,18 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { case DeclContextKind::AbstractFunctionDecl: { auto *AFD = cast(DC); - - // FIXME: This shouldn't be necessary, but we crash otherwise. - if (auto *AD = dyn_cast(AFD)) - typeCheckCompletionDecl(AD->getStorage()); - typeCheckAbstractFunctionBodyUntil(AFD, Loc); break; } case DeclContextKind::ExtensionDecl: - typeCheckCompletionDecl(cast(DC)); - break; - - case DeclContextKind::GenericTypeDecl: - typeCheckCompletionDecl(cast(DC)); + // Make sure the extension has been bound, in case it is in an + // inactive #if or something weird like that. + cast(DC)->computeExtendedNominal(); break; case DeclContextKind::FileUnit: llvm_unreachable("module scope context handled above"); - - case DeclContextKind::SubscriptDecl: - typeCheckCompletionDecl(cast(DC)); - break; } } } // anonymous namespace diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 6a3bfd050e3..7bff9558019 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -440,7 +440,7 @@ void IRGenModule::emitSourceFile(SourceFile &SF) { emitGlobalDecl(decl); for (auto *localDecl : SF.LocalTypeDecls) emitGlobalDecl(localDecl); - for (auto *opaqueDecl : SF.OpaqueReturnTypes) + for (auto *opaqueDecl : SF.getOpaqueReturnTypeDecls()) maybeEmitOpaqueTypeDecl(opaqueDecl); SF.collectLinkLibraries([this](LinkLibrary linkLib) { diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 996c54ced0a..a9083af8901 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -221,20 +221,28 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const { if (!argExpr) return None; - ValueDecl *callee = nullptr; + Optional choice; Type rawFnType; if (auto overload = getChoiceFor(argLocator)) { // If we have resolved an overload for the callee, then use that to get the // function type and callee. - callee = overload->choice.getDeclOrNull(); + choice = overload->choice; rawFnType = overload->openedType; } else { - // If we didn't resolve an overload for the callee, we must be dealing with - // a call of an arbitrary function expr. - auto *call = cast(anchor); - assert(!shouldHaveDirectCalleeOverload(call) && - "Should we have resolved a callee for this?"); - rawFnType = cs.getType(call->getFn()); + // If we didn't resolve an overload for the callee, we should be dealing + // with a call of an arbitrary function expr. + if (auto *call = dyn_cast(anchor)) { + assert(!shouldHaveDirectCalleeOverload(call) && + "Should we have resolved a callee for this?"); + rawFnType = cs.getType(call->getFn()); + } else { + // FIXME: ArgumentMismatchFailure is currently used from CSDiag, meaning + // we can end up a BinaryExpr here with an unresolved callee. It should be + // possible to remove this once we've gotten rid of the old CSDiag logic + // and just assert that we have a CallExpr. + auto *apply = cast(anchor); + rawFnType = cs.getType(apply->getFn()); + } } // Try to resolve the function type by loading lvalues and looking through @@ -249,6 +257,7 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const { // Resolve the interface type for the function. Note that this may not be a // function type, for example it could be a generic parameter. Type fnInterfaceType; + auto *callee = choice ? choice->getDeclOrNull() : nullptr; if (callee && callee->hasInterfaceType()) { // If we have a callee with an interface type, we can use it. This is // preferable to resolveInterfaceType, as this will allow us to get a @@ -261,7 +270,7 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const { fnInterfaceType = callee->getInterfaceType(); // Strip off the curried self parameter if necessary. - if (callee->hasCurriedSelf()) + if (hasAppliedSelf(cs, *choice)) fnInterfaceType = fnInterfaceType->castTo()->getResult(); if (auto *fn = fnInterfaceType->getAs()) { @@ -5033,13 +5042,9 @@ bool ArgumentMismatchFailure::diagnoseAsError() { } bool ArgumentMismatchFailure::diagnoseAsNote() { - auto *locator = getLocator(); - auto argToParam = locator->findFirst(); - assert(argToParam); - - if (auto *decl = getDecl()) { - emitDiagnostic(decl, diag::candidate_has_invalid_argument_at_position, - getToType(), argToParam->getParamIdx()); + if (auto *callee = getCallee()) { + emitDiagnostic(callee, diag::candidate_has_invalid_argument_at_position, + getToType(), getParamPosition()); return true; } @@ -5066,11 +5071,10 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { // one would cover both arguments. if (getAnchor() == rhs && rhsType->is()) { auto &cs = getConstraintSystem(); - auto info = getFunctionArgApplyInfo(locator); - if (info && cs.hasFixFor(cs.getConstraintLocator( - binaryOp, {ConstraintLocator::ApplyArgument, - LocatorPathElt::ApplyArgToParam( - 0, 0, info->getParameterFlagsAtIndex(0))}))) + if (cs.hasFixFor(cs.getConstraintLocator( + binaryOp, {ConstraintLocator::ApplyArgument, + LocatorPathElt::ApplyArgToParam( + 0, 0, getParameterFlagsAtIndex(0))}))) return true; } @@ -5228,14 +5232,12 @@ bool ArgumentMismatchFailure::diagnoseMisplacedMissingArgument() const { if (!MissingArgumentsFailure::isMisplacedMissingArgument(cs, locator)) return false; - auto info = *getFunctionArgApplyInfo(locator); - auto *argType = cs.createTypeVariable( cs.getConstraintLocator(locator, LocatorPathElt::SynthesizedArgument(1)), /*flags=*/0); // Assign new type variable to a type of a parameter. - auto *fnType = info.getFnType(); + auto *fnType = getFnType(); const auto ¶m = fnType->getParams()[0]; cs.assignFixedType(argType, param.getOldType()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index e8a2b46b314..e90485b351e 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -195,6 +195,101 @@ private: std::pair computeAnchor() const; }; +/// Provides information about the application of a function argument to a +/// parameter. +class FunctionArgApplyInfo { + Expr *ArgExpr; + unsigned ArgIdx; + Type ArgType; + + unsigned ParamIdx; + + Type FnInterfaceType; + FunctionType *FnType; + const ValueDecl *Callee; + +public: + FunctionArgApplyInfo(Expr *argExpr, unsigned argIdx, Type argType, + unsigned paramIdx, Type fnInterfaceType, + FunctionType *fnType, const ValueDecl *callee) + : ArgExpr(argExpr), ArgIdx(argIdx), ArgType(argType), ParamIdx(paramIdx), + FnInterfaceType(fnInterfaceType), FnType(fnType), Callee(callee) {} + + /// \returns The argument being applied. + Expr *getArgExpr() const { return ArgExpr; } + + /// \returns The position of the argument, starting at 1. + unsigned getArgPosition() const { return ArgIdx + 1; } + + /// \returns The position of the parameter, starting at 1. + unsigned getParamPosition() const { return ParamIdx + 1; } + + /// \returns The type of the argument being applied, including any generic + /// substitutions. + /// + /// \param withSpecifier Whether to keep the inout or @lvalue specifier of + /// the argument, if any. + Type getArgType(bool withSpecifier = false) const { + return withSpecifier ? ArgType : ArgType->getWithoutSpecifierType(); + } + + /// \returns The interface type for the function being applied. Note that this + /// may not a function type, for example it could be a generic parameter. + Type getFnInterfaceType() const { return FnInterfaceType; } + + /// \returns The function type being applied, including any generic + /// substitutions. + FunctionType *getFnType() const { return FnType; } + + /// \returns The callee for the application. + const ValueDecl *getCallee() const { return Callee; } + +private: + Type getParamTypeImpl(AnyFunctionType *fnTy, + bool lookThroughAutoclosure) const { + auto param = fnTy->getParams()[ParamIdx]; + auto paramTy = param.getPlainType(); + if (lookThroughAutoclosure && param.isAutoClosure()) + paramTy = paramTy->castTo()->getResult(); + return paramTy; + } + +public: + /// \returns The type of the parameter which the argument is being applied to, + /// including any generic substitutions. + /// + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter + /// should be treated as being of type T. + Type getParamType(bool lookThroughAutoclosure = true) const { + return getParamTypeImpl(FnType, lookThroughAutoclosure); + } + + /// \returns The interface type of the parameter which the argument is being + /// applied to. + /// + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter + /// should be treated as being of type T. + Type getParamInterfaceType(bool lookThroughAutoclosure = true) const { + auto interfaceFnTy = FnInterfaceType->getAs(); + if (!interfaceFnTy) { + // If the interface type isn't a function, then just return the resolved + // parameter type. + return getParamType(lookThroughAutoclosure)->mapTypeOutOfContext(); + } + return getParamTypeImpl(interfaceFnTy, lookThroughAutoclosure); + } + + /// \returns The flags of the parameter which the argument is being applied + /// to. + ParameterTypeFlags getParameterFlags() const { + return FnType->getParams()[ParamIdx].getParameterFlags(); + } + + ParameterTypeFlags getParameterFlagsAtIndex(unsigned idx) const { + return FnType->getParams()[idx].getParameterFlags(); + } +}; + /// Base class for all of the diagnostics related to generic requirement /// failures, provides common information like failed requirement, /// declaration where such requirement comes from, etc. @@ -1657,10 +1752,17 @@ public: /// func bar(_ v: Int) { foo(v) } // `Int` is not convertible to `String` /// ``` class ArgumentMismatchFailure : public ContextualFailure { + // FIXME: Currently ArgumentMismatchFailure can be used from CSDiag, in which + // case it's possible we're not able to resolve the arg apply info. Once + // the CSDiag logic has been removed, we should be able to store Info + // unwrapped. + Optional Info; + public: ArgumentMismatchFailure(Expr *root, ConstraintSystem &cs, Type argType, Type paramType, ConstraintLocator *locator) - : ContextualFailure(root, cs, argType, paramType, locator) {} + : ContextualFailure(root, cs, argType, paramType, locator), + Info(getFunctionArgApplyInfo(getLocator())) {} bool diagnoseAsError() override; bool diagnoseAsNote() override; @@ -1677,6 +1779,84 @@ public: bool diagnoseUseOfReferenceEqualityOperator() const; protected: + /// \returns The position of the argument being diagnosed, starting at 1. + unsigned getArgPosition() const { return Info->getArgPosition(); } + + /// \returns The position of the parameter being diagnosed, starting at 1. + unsigned getParamPosition() const { return Info->getParamPosition(); } + + /// Returns the argument expression being diagnosed. + /// + /// Note this may differ from \c getAnchor(), which will return a smaller + /// sub-expression if the failed constraint is for a sub-expression within + /// an argument. For example, in an argument conversion from (T, U) to (U, U), + /// the conversion from T to U may fail. In this case, \c getArgExpr() will + /// return the (T, U) expression, whereas \c getAnchor() will return the T + /// expression. + Expr *getArgExpr() const { return Info->getArgExpr(); } + + /// Returns the argument type for the conversion being diagnosed. + /// + /// \param withSpecifier Whether to keep the inout or @lvalue specifier of + /// the argument, if any. + /// + /// Note this may differ from \c getFromType(), which will give the source + /// type of a failed constraint for the argument conversion. For example in + /// an argument conversion from T? to U?, the conversion from T to U may fail. + /// In this case, \c getArgType() will return T?, whereas \c getFromType() + /// will return T. + Type getArgType(bool withSpecifier = false) const { + return Info->getArgType(withSpecifier); + } + + /// \returns The interface type for the function being applied. + Type getFnInterfaceType() const { return Info->getFnInterfaceType(); } + + /// \returns The function type being applied, including any generic + /// substitutions. + FunctionType *getFnType() const { return Info->getFnType(); } + + /// \returns The callee for the argument conversion, if any. + const ValueDecl *getCallee() const { + return Info ? Info->getCallee() : nullptr; + } + + /// \returns The full name of the callee, or a null decl name if there is no + /// callee. + DeclName getCalleeFullName() const { + return getCallee() ? getCallee()->getFullName() : DeclName(); + } + + /// Returns the type of the parameter involved in the mismatch, including any + /// generic substitutions. + /// + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter + /// should be treated as being of type T. + /// + /// Note this may differ from \c getToType(), see the note on \c getArgType(). + Type getParamType(bool lookThroughAutoclosure = true) const { + return Info->getParamType(lookThroughAutoclosure); + } + + /// Returns the type of the parameter involved in the mismatch. + /// + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter + /// should be treated as being of type T. + /// + /// Note this may differ from \c getToType(), see the note on \c getArgType(). + Type getParamInterfaceType(bool lookThroughAutoclosure = true) const { + return Info->getParamInterfaceType(lookThroughAutoclosure); + } + + /// \returns The flags of the parameter involved in the mismatch. + ParameterTypeFlags getParameterFlags() const { + return Info->getParameterFlags(); + } + + /// \returns The flags of a parameter at a given index. + ParameterTypeFlags getParameterFlagsAtIndex(unsigned idx) const { + return Info->getParameterFlagsAtIndex(idx); + } /// Situations like this: /// @@ -1688,110 +1868,6 @@ protected: bool diagnoseMisplacedMissingArgument() const; SourceLoc getLoc() const { return getAnchor()->getLoc(); } - - ValueDecl *getDecl() const { - auto selectedOverload = getChoiceFor(getLocator()); - if (!selectedOverload) - return nullptr; - - auto choice = selectedOverload->choice; - return choice.getDeclOrNull(); - } -}; - -/// Provides information about the application of a function argument to a -/// parameter. -class FunctionArgApplyInfo { - Expr *ArgExpr; - unsigned ArgIdx; - Type ArgType; - - unsigned ParamIdx; - - Type FnInterfaceType; - FunctionType *FnType; - const ValueDecl *Callee; - -public: - FunctionArgApplyInfo(Expr *argExpr, unsigned argIdx, Type argType, - unsigned paramIdx, Type fnInterfaceType, - FunctionType *fnType, const ValueDecl *callee) - : ArgExpr(argExpr), ArgIdx(argIdx), ArgType(argType), ParamIdx(paramIdx), - FnInterfaceType(fnInterfaceType), FnType(fnType), Callee(callee) {} - - /// \returns The argument being applied. - Expr *getArgExpr() const { return ArgExpr; } - - /// \returns The position of the argument, starting at 1. - unsigned getArgPosition() const { return ArgIdx + 1; } - - /// \returns The position of the parameter, starting at 1. - unsigned getParamPosition() const { return ParamIdx + 1; } - - /// \returns The type of the argument being applied, including any generic - /// substitutions. - /// - /// \param withSpecifier Whether to keep the inout or @lvalue specifier of - /// the argument, if any. - Type getArgType(bool withSpecifier = false) const { - return withSpecifier ? ArgType : ArgType->getWithoutSpecifierType(); - } - - /// \returns The interface type for the function being applied. Note that this - /// may not a function type, for example it could be a generic parameter. - Type getFnInterfaceType() const { return FnInterfaceType; } - - /// \returns The function type being applied, including any generic - /// substitutions. - FunctionType *getFnType() const { return FnType; } - - /// \returns The callee for the application. - const ValueDecl *getCallee() const { return Callee; } - -private: - Type getParamTypeImpl(AnyFunctionType *fnTy, - bool lookThroughAutoclosure) const { - auto param = fnTy->getParams()[ParamIdx]; - auto paramTy = param.getPlainType(); - if (lookThroughAutoclosure && param.isAutoClosure()) - paramTy = paramTy->castTo()->getResult(); - return paramTy; - } - -public: - /// \returns The type of the parameter which the argument is being applied to, - /// including any generic substitutions. - /// - /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter - /// should be treated as being of type T. - Type getParamType(bool lookThroughAutoclosure = true) const { - return getParamTypeImpl(FnType, lookThroughAutoclosure); - } - - /// \returns The interface type of the parameter which the argument is being - /// applied to. - /// - /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter - /// should be treated as being of type T. - Type getParamInterfaceType(bool lookThroughAutoclosure = true) const { - auto interfaceFnTy = FnInterfaceType->getAs(); - if (!interfaceFnTy) { - // If the interface type isn't a function, then just return the resolved - // parameter type. - return getParamType(lookThroughAutoclosure)->mapTypeOutOfContext(); - } - return getParamTypeImpl(interfaceFnTy, lookThroughAutoclosure); - } - - /// \returns The flags of the parameter which the argument is being applied - /// to. - ParameterTypeFlags getParameterFlags() const { - return FnType->getParams()[ParamIdx].getParameterFlags(); - } - - ParameterTypeFlags getParameterFlagsAtIndex(unsigned idx) const { - return FnType->getParams()[idx].getParameterFlags(); - } }; } // end namespace constraints diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6c73328216c..63cfe8a6eca 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -728,21 +728,6 @@ matchCallArguments(ArrayRef args, return listener.relabelArguments(actualArgNames); } -static bool hasAppliedSelf(ConstraintSystem &cs, const OverloadChoice &choice) { - auto *decl = choice.getDeclOrNull(); - if (!decl) - return false; - - auto baseType = choice.getBaseType(); - if (baseType) - baseType = cs.getFixedTypeRecursive(baseType, /*wantRValue=*/true); - - // In most cases where we reference a declaration with a curried self - // parameter, it gets dropped from the type of the reference. - return decl->hasCurriedSelf() && - doesMemberRefApplyCurriedSelf(baseType, decl); -} - /// Find the callee declaration and uncurry level for a given call /// locator. static std::tuple, bool, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index f5a1fd2d749..a0978b51419 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -3043,6 +3043,22 @@ bool constraints::isAutoClosureArgument(Expr *argExpr) { return false; } +bool constraints::hasAppliedSelf(ConstraintSystem &cs, + const OverloadChoice &choice) { + auto *decl = choice.getDeclOrNull(); + if (!decl) + return false; + + auto baseType = choice.getBaseType(); + if (baseType) + baseType = cs.getFixedTypeRecursive(baseType, /*wantRValue=*/true); + + // In most cases where we reference a declaration with a curried self + // parameter, it gets dropped from the type of the reference. + return decl->hasCurriedSelf() && + doesMemberRefApplyCurriedSelf(baseType, decl); +} + bool constraints::conformsToKnownProtocol(ConstraintSystem &cs, Type type, KnownProtocolKind protocol) { if (auto *proto = cs.TC.getProtocol(SourceLoc(), protocol)) diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 3c4dfec2c35..55709d9c4d1 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -4014,6 +4014,11 @@ Optional getOperatorName(Expr *expr); // } bool isAutoClosureArgument(Expr *argExpr); +/// Checks whether referencing the given overload choice results in the self +/// parameter being applied, meaning that it's dropped from the type of the +/// reference. +bool hasAppliedSelf(ConstraintSystem &cs, const OverloadChoice &choice); + /// Check whether type conforms to a given known protocol. bool conformsToKnownProtocol(ConstraintSystem &cs, Type type, KnownProtocolKind protocol); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index bd01a73fc09..6729acf0c5a 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1238,6 +1238,25 @@ IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { return false; } +llvm::Expected +IsStaticRequest::evaluate(Evaluator &evaluator, FuncDecl *decl) const { + bool result = (decl->getStaticLoc().isValid() || + decl->getStaticSpelling() != StaticSpellingKind::None); + auto *dc = decl->getDeclContext(); + if (!result && + decl->isOperator() && + dc->isTypeContext()) { + auto operatorName = decl->getFullName().getBaseIdentifier(); + decl->diagnose(diag::nonstatic_operator_in_type, + operatorName, dc->getDeclaredInterfaceType()) + .fixItInsert(decl->getAttributeInsertionLoc(/*forModifier=*/true), + "static "); + result = true; + } + + return result; +} + llvm::Expected IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { // If we can't infer dynamic here, don't. @@ -3064,7 +3083,9 @@ public: } void visitFuncDecl(FuncDecl *FD) { - (void)FD->getInterfaceType(); + // Force these requests in case they emit diagnostics. + (void) FD->getInterfaceType(); + (void) FD->getOperatorDecl(); if (!FD->isInvalid()) { checkGenericParams(FD->getGenericParams(), FD, TC); @@ -3108,6 +3129,33 @@ public: checkDynamicSelfType(FD, FD->getResultInterfaceType()); checkDefaultArguments(TC, FD->getParameters(), FD); + + // Validate 'static'/'class' on functions in extensions. + auto StaticSpelling = FD->getStaticSpelling(); + if (StaticSpelling != StaticSpellingKind::None && + isa(FD->getDeclContext())) { + if (auto *NTD = FD->getDeclContext()->getSelfNominalTypeDecl()) { + if (!isa(NTD)) { + if (StaticSpelling == StaticSpellingKind::KeywordClass) { + FD->diagnose(diag::class_func_not_in_class, false) + .fixItReplace(FD->getStaticLoc(), "static"); + NTD->diagnose(diag::extended_type_declared_here); + } + } + } + } + + // Member functions need some special validation logic. + if (FD->getDeclContext()->isTypeContext()) { + if (FD->isOperator() && !isMemberOperator(FD, nullptr)) { + auto selfNominal = FD->getDeclContext()->getSelfNominalTypeDecl(); + auto isProtocol = selfNominal && isa(selfNominal); + // We did not find 'Self'. Complain. + FD->diagnose(diag::operator_in_unrelated_type, + FD->getDeclContext()->getDeclaredInterfaceType(), isProtocol, + FD->getFullName()); + } + } } void visitModuleDecl(ModuleDecl *) { } @@ -3178,10 +3226,8 @@ public: return; } - // Validate the nominal type declaration being extended. - (void)nominal->getInterfaceType(); - (void)ED->getGenericSignature(); - ED->setValidationToChecked(); + // Produce any diagnostics for the generic signature. + (void) ED->getGenericSignature(); if (extType && !extType->hasError()) { // The first condition catches syntactic forms like @@ -3598,16 +3644,10 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // Check for static/final/class when we're in a type. auto dc = FD->getDeclContext(); if (dc->isTypeContext()) { - if (!FD->isStatic()) { - FD->diagnose(diag::nonstatic_operator_in_type, - operatorName, dc->getDeclaredInterfaceType()) - .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true), - "static "); - - FD->setStatic(); - } else if (auto classDecl = dc->getSelfClassDecl()) { + if (auto classDecl = dc->getSelfClassDecl()) { // For a class, we also need the function or class to be 'final'. if (!classDecl->isFinal() && !FD->isFinal() && + FD->getStaticLoc().isValid() && FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) { FD->diagnose(diag::nonfinal_operator_in_class, operatorName, dc->getDeclaredInterfaceType()) @@ -3793,22 +3833,24 @@ static Type buildAddressorResultType(TypeChecker &TC, } -static void validateResultType(TypeChecker &TC, - ValueDecl *decl, ParameterList *params, - TypeLoc &resultTyLoc, - TypeResolution resolution) { +static void validateResultType(ValueDecl *decl, + TypeLoc &resultTyLoc) { // Nothing to do if there's no result type loc to set into. if (resultTyLoc.isNull()) return; // Check the result type. It is allowed to be opaque. - if (auto opaqueTy = - dyn_cast_or_null(resultTyLoc.getTypeRepr())) { - // Create the decl and type for it. + if (decl->getOpaqueResultTypeRepr()) { + auto *opaqueDecl = decl->getOpaqueResultTypeDecl(); resultTyLoc.setType( - TC.getOrCreateOpaqueResultType(resolution, decl, opaqueTy)); + opaqueDecl + ? opaqueDecl->getDeclaredInterfaceType() + : ErrorType::get(decl->getASTContext())); } else { - TypeChecker::validateType(TC.Context, resultTyLoc, resolution, + auto *dc = decl->getInnermostDeclContext(); + auto resolution = TypeResolution::forInterface(dc); + TypeChecker::validateType(dc->getASTContext(), + resultTyLoc, resolution, TypeResolverContext::FunctionResult); } } @@ -3821,54 +3863,14 @@ void TypeChecker::validateDecl(ValueDecl *D) { // Handling validation failure due to re-entrancy is left // up to the caller, who must call hasInterfaceType() to // check that validateDecl() returned a fully-formed decl. - if (D->hasValidationStarted() || D->hasInterfaceType()) + if (D->isBeingValidated() || D->hasInterfaceType()) return; - // FIXME: It would be nicer if Sema would always synthesize fully-typechecked - // declarations, but for now, you can make an imported type conform to a - // protocol with property requirements, which requires synthesizing getters - // and setters, etc. - if (!isa(D) && !isa(D)) { - assert(isa(D->getDeclContext()->getModuleScopeContext()) && - "Should not validate imported or deserialized declarations"); - } - PrettyStackTraceDecl StackTrace("validating", D); FrontendStatsTracer StatsTracer(Context.Stats, "validate-decl", D); checkForForbiddenPrefix(D); - // Validate the context. - auto dc = D->getDeclContext(); - if (auto nominal = dyn_cast(dc)) { - if (!nominal->getInterfaceType()) - return; - } else if (auto ext = dyn_cast(dc)) { - // If we're currently validating, or have already validated this extension, - // there's nothing more to do now. - if (!ext->hasValidationStarted()) { - DeclValidationRAII IBV(ext); - - if (auto *nominal = ext->getExtendedNominal()) { - // Validate the nominal type declaration being extended. - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)nominal->getInterfaceType(); - - // Eagerly validate the generic signature of the extension. - (void)ext->getGenericSignature(); - } - } - if (ext->getValidationState() == Decl::ValidationState::Checking) - return; - } - - // Validating the parent may have triggered validation of this declaration, - // so just return if that was the case. - if (D->hasValidationStarted() || D->hasInterfaceType()) { - assert(D->hasInterfaceType()); - return; - } - if (Context.Stats) Context.Stats->getFrontendCounters().NumDeclsValidated++; @@ -3963,12 +3965,6 @@ void TypeChecker::validateDecl(ValueDecl *D) { setBoundVarsTypeError(parentPattern, Context); } - if (VD->getOpaqueResultTypeDecl()) { - if (auto SF = VD->getInnermostDeclContext()->getParentSourceFile()) { - SF->markDeclWithOpaqueResultTypeAsValidated(VD); - } - } - break; } @@ -3985,24 +3981,6 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(FD); - // Force computing the operator decl in case it emits diagnostics. - (void) FD->getOperatorDecl(); - - // Validate 'static'/'class' on functions in extensions. - auto StaticSpelling = FD->getStaticSpelling(); - if (StaticSpelling != StaticSpellingKind::None && - isa(FD->getDeclContext())) { - if (auto *NTD = FD->getDeclContext()->getSelfNominalTypeDecl()) { - if (!isa(NTD)) { - if (StaticSpelling == StaticSpellingKind::KeywordClass) { - diagnose(FD, diag::class_func_not_in_class, false) - .fixItReplace(FD->getStaticLoc(), "static"); - diagnose(NTD, diag::extended_type_declared_here); - } - } - } - } - // Accessors should pick up various parts of their type signatures // directly from the storage declaration instead of re-deriving them. // FIXME: should this include the generic signature? @@ -4077,27 +4055,13 @@ void TypeChecker::validateDecl(ValueDecl *D) { // We want the function to be available for name lookup as soon // as it has a valid interface type. - auto resolution = TypeResolution::forInterface(FD, - FD->getGenericSignature()); + auto resolution = TypeResolution::forInterface(FD); typeCheckParameterList(FD->getParameters(), resolution, TypeResolverContext::AbstractFunctionDecl); - validateResultType(*this, FD, FD->getParameters(), - FD->getBodyResultTypeLoc(), resolution); + validateResultType(FD, FD->getBodyResultTypeLoc()); // FIXME: Roll all of this interface type computation into a request. FD->computeType(); - // Member functions need some special validation logic. - if (FD->getDeclContext()->isTypeContext()) { - if (FD->isOperator() && !isMemberOperator(FD, nullptr)) { - auto selfNominal = FD->getDeclContext()->getSelfNominalTypeDecl(); - auto isProtocol = selfNominal && isa(selfNominal); - // We did not find 'Self'. Complain. - diagnose(FD, diag::operator_in_unrelated_type, - FD->getDeclContext()->getDeclaredInterfaceType(), isProtocol, - FD->getFullName()); - } - } - // If the function is exported to C, it must be representable in (Obj-)C. if (auto CDeclAttr = FD->getAttrs().getAttribute()) { Optional errorConvention; @@ -4109,13 +4073,6 @@ void TypeChecker::validateDecl(ValueDecl *D) { } } } - - // Mark the opaque result type as validated, if there is one. - if (FD->getOpaqueResultTypeDecl()) { - if (auto sf = FD->getDeclContext()->getParentSourceFile()) { - sf->markDeclWithOpaqueResultTypeAsValidated(FD); - } - } break; } @@ -4125,7 +4082,7 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(CD); - auto res = TypeResolution::forInterface(CD, CD->getGenericSignature()); + auto res = TypeResolution::forInterface(CD); typeCheckParameterList(CD->getParameters(), res, TypeResolverContext::AbstractFunctionDecl); CD->computeType(); @@ -4137,7 +4094,7 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(DD); - auto res = TypeResolution::forInterface(DD, DD->getGenericSignature()); + auto res = TypeResolution::forInterface(DD); typeCheckParameterList(DD->getParameters(), res, TypeResolverContext::AbstractFunctionDecl); DD->computeType(); @@ -4149,19 +4106,12 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(SD); - auto res = TypeResolution::forInterface(SD, SD->getGenericSignature()); + auto res = TypeResolution::forInterface(SD); typeCheckParameterList(SD->getIndices(), res, TypeResolverContext::SubscriptDecl); - validateResultType(*this, SD, SD->getIndices(), - SD->getElementTypeLoc(), res); + validateResultType(SD, SD->getElementTypeLoc()); SD->computeType(); - if (SD->getOpaqueResultTypeDecl()) { - if (auto SF = SD->getInnermostDeclContext()->getParentSourceFile()) { - SF->markDeclWithOpaqueResultTypeAsValidated(SD); - } - } - break; } @@ -4172,7 +4122,7 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(EED); if (auto *PL = EED->getParameterList()) { - auto res = TypeResolution::forInterface(ED, ED->getGenericSignature()); + auto res = TypeResolution::forInterface(ED); typeCheckParameterList(PL, res, TypeResolverContext::EnumElementDecl); } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 90596fc0846..112fee62ace 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -83,43 +83,47 @@ TypeChecker::gatherGenericParamBindingsText( /// Get the opaque type representing the return type of a declaration, or /// create it if it does not yet exist. -Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, - ValueDecl *originatingDecl, - OpaqueReturnTypeRepr *repr) { +llvm::Expected +OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, + ValueDecl *originatingDecl) const { + auto *repr = originatingDecl->getOpaqueResultTypeRepr(); + assert(repr && "Declaration does not have an opaque result type"); + auto *dc = originatingDecl->getInnermostDeclContext(); + auto &ctx = dc->getASTContext(); + // Protocol requirements can't have opaque return types. // // TODO: Maybe one day we could treat this as sugar for an associated type. if (isa(originatingDecl->getDeclContext()) && originatingDecl->isProtocolRequirement()) { - + SourceLoc fixitLoc; if (auto vd = dyn_cast(originatingDecl)) { fixitLoc = vd->getParentPatternBinding()->getStartLoc(); } else { fixitLoc = originatingDecl->getStartLoc(); } - - diagnose(repr->getLoc(), diag::opaque_type_in_protocol_requirement) + + ctx.Diags.diagnose(repr->getLoc(), + diag::opaque_type_in_protocol_requirement) .fixItInsert(fixitLoc, "associatedtype <#AssocType#>\n") .fixItReplace(repr->getSourceRange(), "<#AssocType#>"); - return ErrorType::get(Context); - } - - // If the decl already has an opaque type decl for its return type, use it. - if (auto existingDecl = originatingDecl->getOpaqueResultTypeDecl()) { - return existingDecl->getDeclaredInterfaceType(); + return nullptr; } // Check the availability of the opaque type runtime support. - if (!Context.LangOpts.DisableAvailabilityChecking) { - auto runningOS = overApproximateAvailabilityAtLocation(repr->getLoc(), - originatingDecl->getInnermostDeclContext()); - auto availability = Context.getOpaqueTypeAvailability(); + if (!ctx.LangOpts.DisableAvailabilityChecking) { + auto runningOS = + TypeChecker::overApproximateAvailabilityAtLocation( + repr->getLoc(), + originatingDecl->getInnermostDeclContext()); + auto availability = ctx.getOpaqueTypeAvailability(); if (!runningOS.isContainedIn(availability)) { - diagnosePotentialOpaqueTypeUnavailability(repr->getSourceRange(), - originatingDecl->getInnermostDeclContext(), - UnavailabilityReason::requiresVersionRange(availability.getOSVersion())); + TypeChecker::diagnosePotentialOpaqueTypeUnavailability( + repr->getSourceRange(), + originatingDecl->getInnermostDeclContext(), + UnavailabilityReason::requiresVersionRange(availability.getOSVersion())); } } @@ -128,18 +132,20 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, TypeResolutionOptions options(TypeResolverContext::GenericRequirement); TypeLoc constraintTypeLoc(repr->getConstraint()); // Pass along the error type if resolving the repr failed. + auto resolution = TypeResolution::forInterface( + dc, dc->getGenericSignatureOfContext()); bool validationError - = validateType(Context, constraintTypeLoc, resolution, options); + = TypeChecker::validateType(ctx, constraintTypeLoc, resolution, options); auto constraintType = constraintTypeLoc.getType(); if (validationError) - return constraintType; + return nullptr; // Error out if the constraint type isn't a class or existential type. if (!constraintType->getClassOrBoundGenericClass() && !constraintType->isExistentialType()) { - diagnose(repr->getConstraint()->getLoc(), - diag::opaque_type_invalid_constraint); - return constraintTypeLoc.getType(); + ctx.Diags.diagnose(repr->getConstraint()->getLoc(), + diag::opaque_type_invalid_constraint); + return nullptr; } if (constraintType->hasArchetype()) @@ -157,8 +163,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, outerGenericSignature->getGenericParams().back()->getDepth() + 1; } - auto returnTypeParam = GenericTypeParamType::get(returnTypeDepth, 0, - Context); + auto returnTypeParam = GenericTypeParamType::get(returnTypeDepth, 0, ctx); SmallVector genericParamTypes; genericParamTypes.push_back(returnTypeParam); @@ -184,7 +189,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, } auto interfaceSignature = evaluateOrDefault( - Context.evaluator, + ctx.evaluator, AbstractGenericSignatureRequest{ outerGenericSignature.getPointer(), std::move(genericParamTypes), @@ -194,24 +199,21 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, // Create the OpaqueTypeDecl for the result type. // It has the same parent context and generic environment as the originating // decl. - auto dc = originatingDecl->getDeclContext(); - + auto parentDC = originatingDecl->getDeclContext(); auto originatingGenericContext = originatingDecl->getAsGenericContext(); GenericParamList *genericParams = originatingGenericContext ? originatingGenericContext->getGenericParams() : nullptr; - auto opaqueDecl = new (Context) OpaqueTypeDecl(originatingDecl, - genericParams, - dc, - interfaceSignature, - returnTypeParam); + auto opaqueDecl = new (ctx) OpaqueTypeDecl(originatingDecl, + genericParams, + parentDC, + interfaceSignature, + returnTypeParam); opaqueDecl->copyFormalAccessFrom(originatingDecl); if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) { opaqueDecl->setGenericSignature(originatingSig); } - - originatingDecl->setOpaqueResultTypeDecl(opaqueDecl); // The declared interface type is an opaque ArchetypeType. SubstitutionMap subs; @@ -221,7 +223,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution, auto opaqueTy = OpaqueTypeArchetypeType::get(opaqueDecl, subs); auto metatype = MetatypeType::get(opaqueTy); opaqueDecl->setInterfaceType(metatype); - return opaqueTy; + return opaqueDecl; } /// Determine whether the given type is \c Self, an associated type of \c Self, diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index e8f428f696f..4aae584a077 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -504,10 +504,6 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, // member entirely. auto *protocol = cast(assocType->getDeclContext()); - // If we're validating the protocol recursively, bail out. - if (!protocol->hasInterfaceType()) - continue; - auto conformance = conformsToProtocol(type, protocol, dc, conformanceOptions); if (!conformance) { diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index c33fce6d02c..cb3eb0e5656 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -695,9 +695,11 @@ static bool validateTypedPattern(TypeChecker &TC, auto named = dyn_cast( TP->getSubPattern()->getSemanticsProvidingPattern()); if (named) { - auto opaqueTy = TC.getOrCreateOpaqueResultType(resolution, - named->getDecl(), - opaqueRepr); + auto *var = named->getDecl(); + auto opaqueDecl = var->getOpaqueResultTypeDecl(); + auto opaqueTy = (opaqueDecl + ? opaqueDecl->getDeclaredInterfaceType() + : ErrorType::get(TC.Context)); TL.setType(named->getDecl()->getDeclContext() ->mapTypeIntoContext(opaqueTy)); hadError = opaqueTy->hasError(); @@ -1133,14 +1135,6 @@ recur: var->getTypeLoc() = tyLoc; var->getTypeLoc().setType(var->getType()); - // FIXME: Copy pasted from validateDecl(). This needs to be converted to - // use requests. - if (var->getOpaqueResultTypeDecl()) { - if (auto sf = var->getInnermostDeclContext()->getParentSourceFile()) { - sf->markDeclWithOpaqueResultTypeAsValidated(var); - } - } - // FIXME: Should probably just remove the forbidden prefix stuff, it no // longer makes a lot of sense in a request-based world. checkForForbiddenPrefix(var); diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index f2e467eb009..27143998d34 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -492,9 +492,12 @@ static Type mapErrorTypeToOriginal(Type type) { static Type getWitnessTypeForMatching(TypeChecker &tc, NormalProtocolConformance *conformance, ValueDecl *witness) { - if (!witness->getInterfaceType()) + if (witness->isRecursiveValidation()) return Type(); + // FIXME: This is here to trigger the isInvalid() computation. + (void) witness->getInterfaceType(); + if (witness->isInvalid()) return Type(); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 85659710e95..1ca8db8c0e6 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -58,16 +58,13 @@ TypeResolution TypeResolution::forStructural(DeclContext *dc) { return TypeResolution(dc, TypeResolutionStage::Structural); } -TypeResolution TypeResolution::forInterface(DeclContext *dc, - LazyResolver *resolver) { - return forInterface(dc, dc->getGenericSignatureOfContext(), resolver); +TypeResolution TypeResolution::forInterface(DeclContext *dc) { + return forInterface(dc, dc->getGenericSignatureOfContext()); } TypeResolution TypeResolution::forInterface(DeclContext *dc, - GenericSignature genericSig, - LazyResolver *resolver) { + GenericSignature genericSig) { TypeResolution result(dc, TypeResolutionStage::Interface); - result.Resolver = resolver; result.complete.genericSig = genericSig; result.complete.builder = nullptr; return result; @@ -2449,7 +2446,6 @@ Type TypeResolver::resolveOpaqueReturnType(TypeRepr *repr, if (definingDeclNode->getKind() == Node::Kind::Global) definingDeclNode = definingDeclNode->getChild(0); ASTBuilder builder(Context); - builder.Resolver = resolution.Resolver; auto opaqueNode = builder.getNodeFactory().createNode(Node::Kind::OpaqueReturnTypeOf); opaqueNode->addChild(definingDeclNode, builder.getNodeFactory()); diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index 2576e77cc25..e9c5c3162ba 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -295,8 +295,6 @@ class TypeResolution { GenericSignatureBuilder *getGenericSignatureBuilder() const; public: - LazyResolver *Resolver = nullptr; - /// 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. @@ -304,14 +302,12 @@ public: /// Form a type resolution for an interface type, which is a complete /// description of the type using generic parameters. - static TypeResolution forInterface(DeclContext *dc, - LazyResolver *resolver = nullptr); + static TypeResolution forInterface(DeclContext *dc); /// 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, - LazyResolver *resolver = nullptr); + GenericSignature genericSig); /// Form a type resolution for a contextual type, which is a complete /// description of the type using the archetypes of the given declaration diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 5ab61019f33..5aa02d2877e 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -618,22 +618,6 @@ swift::handleSILGenericParams(ASTContext &Ctx, GenericParamList *genericParams, return createTypeChecker(Ctx).handleSILGenericParams(genericParams, DC); } -void swift::typeCheckCompletionDecl(Decl *D) { - auto &Ctx = D->getASTContext(); - - DiagnosticSuppression suppression(Ctx.Diags); - (void)createTypeChecker(Ctx); - if (auto ext = dyn_cast(D)) { - if (auto *nominal = ext->computeExtendedNominal()) { - // FIXME(InterfaceTypeRequest): Remove this. - (void)nominal->getInterfaceType(); - } - } else { - // FIXME(InterfaceTypeRequest): Remove this. - (void)cast(D)->getInterfaceType(); - } -} - void swift::typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex) { assert(!PBD->isInitializerChecked(bindingIndex) && diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 394bf03a52c..cc1eb1c9fe9 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1974,10 +1974,6 @@ public: /// Check if the given decl has a @_semantics attribute that gives it /// special case type-checking behavior. DeclTypeCheckingSemantics getDeclTypeCheckingSemantics(ValueDecl *decl); - - Type getOrCreateOpaqueResultType(TypeResolution resolution, - ValueDecl *originatingDecl, - OpaqueReturnTypeRepr *repr); }; /// Temporary on-stack storage and unescaping for encoded diagnostic diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 8c70cb9c36f..5db33582a24 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1288,7 +1288,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { auto name = getIdentifier(DefiningDeclNameID); pathTrace.addOpaqueReturnType(name); - if (auto opaque = baseModule->lookupOpaqueResultType(name.str(), nullptr)) { + if (auto opaque = baseModule->lookupOpaqueResultType(name.str())) { values.push_back(opaque); } break; @@ -1693,8 +1693,7 @@ giveUpFastPath: pathTrace.addOpaqueReturnType(name); auto lookupModule = M ? M : baseModule; - if (auto opaqueTy = lookupModule->lookupOpaqueResultType(name.str(), - nullptr)) { + if (auto opaqueTy = lookupModule->lookupOpaqueResultType(name.str())) { values.push_back(opaqueTy); } break; @@ -2743,8 +2742,9 @@ public: AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true)); if (opaqueReturnTypeID) { - var->setOpaqueResultTypeDecl( - cast(MF.getDecl(opaqueReturnTypeID))); + ctx.evaluator.cacheOutput( + OpaqueResultTypeRequest{var}, + cast(MF.getDecl(opaqueReturnTypeID))); } // If this is a lazy property, record its backing storage. @@ -2853,7 +2853,7 @@ public: DeclID overriddenID; DeclID accessorStorageDeclID; bool needsNewVTableEntry, isTransparent; - DeclID opaqueResultTypeDeclID; + DeclID opaqueReturnTypeID; ArrayRef nameAndDependencyIDs; if (!isAccessor) { @@ -2868,7 +2868,7 @@ public: numNameComponentsBiased, rawAccessLevel, needsNewVTableEntry, - opaqueResultTypeDeclID, + opaqueReturnTypeID, nameAndDependencyIDs); } else { decls_block::AccessorLayout::readRecord(scratch, contextID, isImplicit, @@ -3059,9 +3059,11 @@ public: fn->setForcedStaticDispatch(hasForcedStaticDispatch); fn->setNeedsNewVTableEntry(needsNewVTableEntry); - if (opaqueResultTypeDeclID) - fn->setOpaqueResultTypeDecl( - cast(MF.getDecl(opaqueResultTypeDeclID))); + if (opaqueReturnTypeID) { + ctx.evaluator.cacheOutput( + OpaqueResultTypeRequest{fn}, + cast(MF.getDecl(opaqueReturnTypeID))); + } // Set the interface type. fn->computeType(); @@ -3737,8 +3739,9 @@ public: AddAttribute(new (ctx) OverrideAttr(SourceLoc())); if (opaqueReturnTypeID) { - subscript->setOpaqueResultTypeDecl( - cast(MF.getDecl(opaqueReturnTypeID))); + ctx.evaluator.cacheOutput( + OpaqueResultTypeRequest{subscript}, + cast(MF.getDecl(opaqueReturnTypeID))); } return subscript; diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 5259388d02c..137a0cc5632 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -961,8 +961,7 @@ TypeDecl *SerializedASTFile::lookupLocalType(llvm::StringRef MangledName) const{ } OpaqueTypeDecl * -SerializedASTFile::lookupOpaqueResultType(StringRef MangledName, - LazyResolver *resolver) { +SerializedASTFile::lookupOpaqueResultType(StringRef MangledName) { return File.lookupOpaqueResultType(MangledName); } diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index 7680bab6e13..4c7f011cd58 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -349,8 +349,8 @@ takeVoidVoidFn { () -> Void in } // Swift: Incorrect compile error when calling a function inside a closure -func f19997471(_ x: String) {} // expected-note {{candidate expects value of type 'String' at position #0}} -func f19997471(_ x: Int) {} // expected-note {{candidate expects value of type 'Int' at position #0}} +func f19997471(_ x: String) {} // expected-note {{candidate expects value of type 'String' for parameter #1}} +func f19997471(_ x: Int) {} // expected-note {{candidate expects value of type 'Int' for parameter #1}} func someGeneric19997471(_ x: T) { takeVoidVoidFn { diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index 859c8f92910..af3034af9b7 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -16,9 +16,9 @@ enum Z { init() { self = .none } init(_ c: UnicodeScalar) { self = .char(c) } - // expected-note@-1 2 {{candidate expects value of type 'UnicodeScalar' (aka 'Unicode.Scalar') at position #0}} + // expected-note@-1 2 {{candidate expects value of type 'UnicodeScalar' (aka 'Unicode.Scalar') for parameter #1}} init(_ s: String) { self = .string(s) } - // expected-note@-1 2 {{candidate expects value of type 'String' at position #0}} + // expected-note@-1 2 {{candidate expects value of type 'String' for parameter #1}} init(_ x: Int, _ y: Int) { self = .point(x, y) } } diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index 94dc04cdf66..7a5d54e7169 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -1069,7 +1069,7 @@ func SR_6272_c() { struct SR_6272_D: ExpressibleByIntegerLiteral { typealias IntegerLiteralType = Int init(integerLiteral: Int) {} - static func +(lhs: SR_6272_D, rhs: Int) -> Float { return 42.0 } // expected-note 2 {{candidate expects value of type 'Int' at position #1}} + static func +(lhs: SR_6272_D, rhs: Int) -> Float { return 42.0 } // expected-note 2 {{candidate expects value of type 'Int' for parameter #2}} } func SR_6272_d() { diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift index 28d549333c3..da7dae970f8 100644 --- a/test/Constraints/overload.swift +++ b/test/Constraints/overload.swift @@ -3,9 +3,9 @@ func markUsed(_ t: T) {} func f0(_: Float) -> Float {} -// expected-note@-1 {{candidate expects value of type 'Float' at position #0}} +// expected-note@-1 {{candidate expects value of type 'Float' for parameter #1}} func f0(_: Int) -> Int {} -// expected-note@-1 {{candidate expects value of type 'Int' at position #0}} +// expected-note@-1 {{candidate expects value of type 'Int' for parameter #1}} func f1(_: Int) {} diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index 578d102f771..1ab8677be96 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -74,8 +74,8 @@ protocol Overload { associatedtype B func getA() -> A func getB() -> B - func f1(_: A) -> A // expected-note {{candidate expects value of type 'OtherOvl.A' at position #0}} - func f1(_: B) -> B // expected-note {{candidate expects value of type 'OtherOvl.B' at position #0}} + func f1(_: A) -> A // expected-note {{candidate expects value of type 'OtherOvl.A' for parameter #1}} + func f1(_: B) -> B // expected-note {{candidate expects value of type 'OtherOvl.B' for parameter #1}} func f2(_: Int) -> A // expected-note{{found this candidate}} func f2(_: Int) -> B // expected-note{{found this candidate}} func f3(_: Int) -> Int // expected-note {{found this candidate}} diff --git a/test/Parse/confusables.swift b/test/Parse/confusables.swift index d855ea122d5..e2446708688 100644 --- a/test/Parse/confusables.swift +++ b/test/Parse/confusables.swift @@ -19,4 +19,7 @@ if (true ꝸꝸꝸ false) {} // expected-note {{identifier 'ꝸꝸꝸ' contains // expected-error @+2 {{expected ',' separator}} // expected-error @+1 {{type '(Int, Int)' cannot conform to 'BinaryInteger'; only struct/enum/class types can conform to protocols}} if (5 ‒ 5) == 0 {} // expected-note {{unicode character '‒' looks similar to '-'; did you mean to use '-'?}} {{7-10=-}} -// expected-note @-1 {{required by referencing operator function '==' on 'BinaryInteger' where 'Self' = '(Int, Int)'}} +// expected-note @-1 {{required by referencing operator function '==' on 'BinaryInteger' where}} + +// FIXME: rdar://56002633 +// Above note should read "required by referencing operator function '==' on 'BinaryInteger' where 'Self' = '(Int, Int)'" diff --git a/test/decl/subscript/subscripting.swift b/test/decl/subscript/subscripting.swift index 619edbfd481..1cd4fe9c6ff 100644 --- a/test/decl/subscript/subscripting.swift +++ b/test/decl/subscript/subscripting.swift @@ -393,9 +393,9 @@ func testSubscript1(_ s1 : SubscriptTest1) { } struct SubscriptTest2 { - subscript(a : String, b : Int) -> Int { return 0 } // expected-note {{candidate expects value of type 'Int' at position #1}} + subscript(a : String, b : Int) -> Int { return 0 } // expected-note {{candidate expects value of type 'Int' for parameter #2}} // expected-note@-1 {{declared here}} - subscript(a : String, b : String) -> Int { return 0 } // expected-note {{candidate expects value of type 'String' at position #1}} + subscript(a : String, b : String) -> Int { return 0 } // expected-note {{candidate expects value of type 'String' for parameter #2}} } func testSubscript1(_ s2 : SubscriptTest2) { diff --git a/validation-test/compiler_crashers_2_fixed/0146-rdar38309176.swift b/validation-test/compiler_crashers_2_fixed/0146-rdar38309176.swift index 92e4427c6f1..9eba4bd7dca 100644 --- a/validation-test/compiler_crashers_2_fixed/0146-rdar38309176.swift +++ b/validation-test/compiler_crashers_2_fixed/0146-rdar38309176.swift @@ -1,7 +1,7 @@ // RUN: %target-typecheck-verify-swift -func foo(_ msg: Int) {} // expected-note {{candidate expects value of type 'Int' at position #0}} -func foo(_ msg: Double) {} // expected-note {{candidate expects value of type 'Double' at position #0}} +func foo(_ msg: Int) {} // expected-note {{candidate expects value of type 'Int' for parameter #1}} +func foo(_ msg: Double) {} // expected-note {{candidate expects value of type 'Double' for parameter #1}} func rdar38309176(_ errors: inout [String]) { foo("error: \(errors[0])") // expected-error {{no exact matches in call to global function 'foo'}}