diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index d74e094b49d4b..7e15eff31f809 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2711,6 +2711,7 @@ class ValueDecl : public Decl { /// Is this declaration marked with 'dynamic'? bool isDynamic() const; +private: bool isObjCDynamic() const { return isObjC() && isDynamic(); } @@ -2719,6 +2720,37 @@ class ValueDecl : public Decl { return !isObjC() && isDynamic(); } + bool isObjCDynamicInGenericClass() const; + +public: + /// Should we use Objective-C method dispatch for this decl. + bool shouldUseObjCDispatch() const { + return isObjCDynamic(); + } + + /// Should we use native dynamic function replacement dispatch for this decl. + bool shouldUseNativeDynamicDispatch() const { + return isNativeDynamic(); + } + + /// Should we use Objective-C category based function replacement for this + /// decl. + /// This is all `@objc dynamic` methods except for such methods in native + /// generic classes. We can't use a category for generic classes so we use + /// native replacement instead (this behavior is only enabled with + /// -enable-implicit-dynamic). + bool shouldUseObjCMethodReplacement() const; + + /// Should we use native dynamic function replacement mechanism for this decl. + /// This is all native dynamic methods except for `@objc dynamic` methods in + /// generic classes (see above). + bool shouldUseNativeMethodReplacement() const; + + /// Is this a native dynamic function replacement based replacement. + /// This is all @_dynamicReplacement(for:) of native functions and @objc + /// dynamic methods on generic classes (see above). + bool isNativeMethodReplacement() const; + bool isEffectiveLinkageMoreVisibleThan(ValueDecl *other) const { return (std::min(getEffectiveAccess(), AccessLevel::Public) > std::min(other->getEffectiveAccess(), AccessLevel::Public)); diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 8eeee999aee01..80a8ddb742bcf 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5054,8 +5054,8 @@ ERROR(function_builder_infer_ambig, none, NOTE(function_builder_infer_add_return, none, "add an explicit 'return' statement to not use a function builder", ()) NOTE(function_builder_infer_pick_specific, none, - "apply function builder %0 (inferred from protocol %1)", - (Type, DeclName)) + "apply function builder %0 (inferred from %select{protocol|dynamic replacement of}1 %2)", + (Type, unsigned, DeclName)) //------------------------------------------------------------------------------ // MARK: Tuple Shuffle Diagnostics diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 9f19c25818d25..923a68fa743cb 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -597,13 +597,23 @@ class ErrorExpr : public Expr { /// CodeCompletionExpr - Represents the code completion token in the AST, this /// can help us preserve the context of the code completion position. class CodeCompletionExpr : public Expr { - SourceRange Range; + Expr *Base; + SourceLoc Loc; public: - CodeCompletionExpr(SourceRange Range, Type Ty = Type()) - : Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Ty), Range(Range) {} + CodeCompletionExpr(Expr *Base, SourceLoc Loc) + : Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Type()), + Base(Base), Loc(Loc) {} - SourceRange getSourceRange() const { return Range; } + CodeCompletionExpr(SourceLoc Loc) + : CodeCompletionExpr(/*Base=*/nullptr, Loc) {} + + Expr *getBase() const { return Base; } + void setBase(Expr *E) { Base = E; } + + SourceLoc getLoc() const { return Loc; } + SourceLoc getStartLoc() const { return Base ? Base->getStartLoc() : Loc; } + SourceLoc getEndLoc() const { return Loc; } static bool classof(const Expr *E) { return E->getKind() == ExprKind::CodeCompletion; diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 961bb25f8e6e6..6516d7baeb234 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -316,13 +316,13 @@ namespace swift { /// Emit the newer, finer-grained swiftdeps file. Eventually will support /// faster rebuilds. - bool EnableFineGrainedDependencies = true; + bool EnableFineGrainedDependencies = false; /// Instead of hashing tokens inside of NominalType and ExtensionBodies into /// the interface hash, hash them into per-iterable-decl-context /// fingerprints. Fine-grained dependency types won't dirty every provides /// in a file when the user adds a member to, e.g., a struct. - bool EnableTypeFingerprints = true; + bool EnableTypeFingerprints = false; /// When using fine-grained dependencies, emit dot files for every swiftdeps /// file. @@ -540,7 +540,10 @@ namespace swift { /// Enable constraint solver support for experimental /// operator protocol designator feature. bool SolverEnableOperatorDesignatedTypes = false; - + + /// Enable experimental support for one-way constraints for the + /// parameters of closures. + bool EnableOneWayClosureParameters = false; }; } // end namespace swift diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c8168fde7d545..496caa77100ea 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -632,6 +632,10 @@ def experimental_print_full_convention : HelpText<"When emitting a module interface, emit additional @convention " "arguments, regardless of whether they were written in the source">; +def experimental_one_way_closure_params : + Flag<["-"], "experimental-one-way-closure-params">, + HelpText<"Enable experimental support for one-way closure parameters">; + def prebuilt_module_cache_path : Separate<["-"], "prebuilt-module-cache-path">, HelpText<"Directory of prebuilt modules for loading module interfaces">; diff --git a/include/swift/Parse/CodeCompletionCallbacks.h b/include/swift/Parse/CodeCompletionCallbacks.h index b8c5fe151fe83..eeee748a4b904 100644 --- a/include/swift/Parse/CodeCompletionCallbacks.h +++ b/include/swift/Parse/CodeCompletionCallbacks.h @@ -198,6 +198,10 @@ class CodeCompletionCallbacks { virtual void completeCallArg(CodeCompletionExpr *E, bool isFirst) {}; + virtual bool canPerformCompleteLabeledTrailingClosure() const { + return false; + } + virtual void completeLabeledTrailingClosure(CodeCompletionExpr *E, bool isAtStartOfLine) {}; diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index 5208ac62ccbc5..c727b198cc0de 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -98,6 +98,7 @@ class ExtendedValidationInfo { unsigned IsSIB : 1; unsigned IsTestable : 1; unsigned ResilienceStrategy : 2; + unsigned IsImplicitDynamicEnabled: 1; } Bits; public: ExtendedValidationInfo() : Bits() {} @@ -123,6 +124,10 @@ class ExtendedValidationInfo { void setPrivateImportsEnabled(bool enabled) { Bits.ArePrivateImportsEnabled = enabled; } + bool isImplicitDynamicEnabled() { return Bits.IsImplicitDynamicEnabled; } + void setImplicitDynamicEnabled(bool val) { + Bits.IsImplicitDynamicEnabled = val; + } bool isTestable() const { return Bits.IsTestable; } void setIsTestable(bool val) { Bits.IsTestable = val; diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index fafd3ac57b47b..704637ccd6d85 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -3111,12 +3111,12 @@ class Verifier : public ASTWalker { storageDecl->getWriteImpl() == WriteImplKind::StoredWithObservers || storageDecl->getWriteImpl() == WriteImplKind::MutableAddress) && - storageDecl->isNativeDynamic()) && + storageDecl->shouldUseNativeDynamicDispatch()) && // We allow a non dynamic getter if there is a dynamic read. !(FD->isGetter() && (storageDecl->getReadImpl() == ReadImplKind::Read || storageDecl->getReadImpl() == ReadImplKind::Address) && - storageDecl->isNativeDynamic())) { + storageDecl->shouldUseNativeDynamicDispatch())) { Out << "Property and accessor do not match for 'dynamic'\n"; abort(); } diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 2e6a946b498e9..bdfd547c07e94 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -476,7 +476,15 @@ class Traversal : public ASTVisitorgetBase()) { + Expr *newBaseExpr = doIt(baseExpr); + if (!newBaseExpr) + return nullptr; + E->setBase(newBaseExpr); + } + return E; + } Expr *visitLiteralExpr(LiteralExpr *E) { return E; } Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *E) { return E; } Expr *visitTypeExpr(TypeExpr *E) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 07fde47f5abdb..deb987e61c2ba 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1950,7 +1950,7 @@ SourceRange IfConfigDecl::getSourceRange() const { } static bool isPolymorphic(const AbstractStorageDecl *storage) { - if (storage->isObjCDynamic()) + if (storage->shouldUseObjCDispatch()) return true; @@ -2083,7 +2083,7 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) { return AccessStrategy::getStorage(); case ReadWriteImplKind::Stored: { // If the storage isDynamic (and not @objc) use the accessors. - if (storage->isNativeDynamic()) + if (storage->shouldUseNativeDynamicDispatch()) return AccessStrategy::getMaterializeToTemporary( getOpaqueReadAccessStrategy(storage, false), getOpaqueWriteAccessStrategy(storage, false)); @@ -2168,7 +2168,7 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics, if (isPolymorphic(this)) return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ true); - if (isNativeDynamic()) + if (shouldUseNativeDynamicDispatch()) return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ false); // If the storage is resilient from the given module and resilience @@ -2926,6 +2926,59 @@ bool ValueDecl::isDynamic() const { getAttrs().hasAttribute()); } +bool ValueDecl::isObjCDynamicInGenericClass() const { + if (!isObjCDynamic()) + return false; + + auto *DC = this->getDeclContext(); + auto *classDecl = DC->getSelfClassDecl(); + if (!classDecl) + return false; + + return classDecl->isGenericContext() && !classDecl->usesObjCGenericsModel(); +} + +bool ValueDecl::shouldUseObjCMethodReplacement() const { + if (isNativeDynamic()) + return false; + + if (getModuleContext()->isImplicitDynamicEnabled() && + isObjCDynamicInGenericClass()) + return false; + + return isObjCDynamic(); +} + +bool ValueDecl::shouldUseNativeMethodReplacement() const { + if (isNativeDynamic()) + return true; + + if (!isObjCDynamicInGenericClass()) + return false; + + auto *replacedDecl = getDynamicallyReplacedDecl(); + if (replacedDecl) + return false; + + return getModuleContext()->isImplicitDynamicEnabled(); +} + +bool ValueDecl::isNativeMethodReplacement() const { + // Is this a @_dynamicReplacement(for:) that use the native dynamic function + // replacement mechanism. + auto *replacedDecl = getDynamicallyReplacedDecl(); + if (!replacedDecl) + return false; + + if (isNativeDynamic()) + return true; + + if (isObjCDynamicInGenericClass()) + return replacedDecl->getModuleContext()->isImplicitDynamicEnabled(); + + return false; +} + void ValueDecl::setIsDynamic(bool value) { assert(!LazySemanticInfo.isDynamicComputed || LazySemanticInfo.isDynamic == value); @@ -5143,7 +5196,7 @@ bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const { bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const { for (auto accessor : getAllAccessors()) { - if (accessor->isNativeDynamic()) + if (accessor->shouldUseNativeDynamicDispatch()) return true; } return false; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index af3443c8292fa..e629322648553 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -690,6 +690,8 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args, Opts.SolverEnableOperatorDesignatedTypes |= Args.hasArg(OPT_solver_enable_operator_designated_types); + Opts.EnableOneWayClosureParameters |= + Args.hasArg(OPT_experimental_one_way_closure_params); Opts.DebugConstraintSolver |= Args.hasArg(OPT_debug_constraints); Opts.DebugGenericSignatures |= Args.hasArg(OPT_debug_generic_signatures); diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index e9d4f5279fbea..bad23e38215bd 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -1687,6 +1687,10 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks { void completeLabeledTrailingClosure(CodeCompletionExpr *E, bool isAtStartOfLine) override; + bool canPerformCompleteLabeledTrailingClosure() const override { + return true; + } + void completeReturnStmt(CodeCompletionExpr *E) override; void completeYieldStmt(CodeCompletionExpr *E, Optional yieldIndex) override; @@ -2762,23 +2766,32 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { const AnyFunctionType *AFT, const SubscriptDecl *SD, const Optional SemanticContext = None) { foundFunction(AFT); - auto genericSig = - SD->getInnermostDeclContext()->getGenericSignatureOfContext(); - AFT = eraseArchetypes(const_cast(AFT), genericSig) - ->castTo(); + if (SD) { + auto genericSig = + SD->getInnermostDeclContext()->getGenericSignatureOfContext(); + AFT = eraseArchetypes(const_cast(AFT), genericSig) + ->castTo(); + } CommandWordsPairs Pairs; CodeCompletionResultBuilder Builder( - Sink, CodeCompletionResult::ResultKind::Declaration, + Sink, + SD ? CodeCompletionResult::ResultKind::Declaration + : CodeCompletionResult::ResultKind::Pattern, SemanticContext ? *SemanticContext : getSemanticContextKind(SD), expectedTypeContext); - Builder.setAssociatedDecl(SD); - setClangDeclKeywords(SD, Pairs, Builder); + if (SD) { + Builder.setAssociatedDecl(SD); + setClangDeclKeywords(SD, Pairs, Builder); + } if (!HaveLParen) Builder.addLeftBracket(); else Builder.addAnnotatedLeftBracket(); - addCallArgumentPatterns(Builder, AFT, SD->getIndices()); + ArrayRef declParams; + if (SD) + declParams = SD->getIndices()->getArray(); + addCallArgumentPatterns(Builder, AFT->getParams(), declParams); if (!HaveLParen) Builder.addRightBracket(); else @@ -4491,6 +4504,51 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { getAttributeDeclParamCompletions(DAK_Available, 0); } + void getSelfTypeCompletionInDeclContext(SourceLoc Loc, bool isForDeclResult) { + const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext(); + if (!typeDC) + return; + + // For protocols, there's a 'Self' generic parameter. + if (typeDC->getSelfProtocolDecl()) + return; + + Type selfType = + CurrDeclContext->mapTypeIntoContext(typeDC->getSelfInterfaceType()); + + if (typeDC->getSelfClassDecl()) { + // In classes, 'Self' can be used in result type of func, subscript and + // computed property, or inside function bodies. + bool canUseDynamicSelf = false; + if (isForDeclResult) { + canUseDynamicSelf = true; + } else { + const auto *checkDC = CurrDeclContext; + if (isa(checkDC)) + checkDC = checkDC->getParent(); + + if (const auto *AFD = checkDC->getInnermostMethodContext()) { + canUseDynamicSelf = Ctx.SourceMgr.rangeContainsTokenLoc( + AFD->getBodySourceRange(), Loc); + } + } + if (!canUseDynamicSelf) + return; + // 'Self' in class is a dynamic type. + selfType = DynamicSelfType::get(selfType, Ctx); + } else { + // In enums and structs, 'Self' is just an alias for the nominal type, + // and can be used anywhere. + } + + CodeCompletionResultBuilder Builder( + Sink, CodeCompletionResult::ResultKind::Keyword, + SemanticContextKind::CurrentNominal, expectedTypeContext); + Builder.addKeyword("Self"); + Builder.setKeywordKind(CodeCompletionKeywordKind::kw_Self); + addTypeAnnotation(Builder, selfType); + } + void getTypeCompletionsInDeclContext(SourceLoc Loc, bool ModuleQualifier = true) { Kind = LookupKind::TypeInDeclContext; @@ -5783,6 +5841,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { auto DoPostfixExprBeginning = [&] (){ SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc(); Lookup.getValueCompletionsInDeclContext(Loc); + Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false); }; switch (Kind) { @@ -5933,8 +5992,10 @@ void CodeCompletionCallbacksImpl::doneParsing() { case CompletionKind::TypeDeclResultBeginning: case CompletionKind::TypeSimpleBeginning: { - Lookup.getTypeCompletionsInDeclContext( - P.Context.SourceMgr.getCodeCompletionLoc()); + auto Loc = Context.SourceMgr.getCodeCompletionLoc(); + Lookup.getTypeCompletionsInDeclContext(Loc); + Lookup.getSelfTypeCompletionInDeclContext( + Loc, Kind == CompletionKind::TypeDeclResultBeginning); break; } @@ -6013,7 +6074,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { Lookup.getUnresolvedMemberCompletions(ContextInfo.getPossibleTypes()); break; } - case CompletionKind::CallArg : { + case CompletionKind::CallArg: { ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr); bool shouldPerformGlobalCompletion = true; @@ -6022,9 +6083,12 @@ void CodeCompletionCallbacksImpl::doneParsing() { !ContextInfo.getPossibleCallees().empty()) { Lookup.setHaveLParen(true); for (auto &typeAndDecl : ContextInfo.getPossibleCallees()) { - if (auto SD = dyn_cast_or_null(typeAndDecl.Decl)) { - Lookup.addSubscriptCallPattern(typeAndDecl.Type, SD, - typeAndDecl.SemanticContext); + auto apply = ContextInfo.getAnalyzedExpr(); + if (apply && isa(apply)) { + Lookup.addSubscriptCallPattern( + typeAndDecl.Type, + dyn_cast_or_null(typeAndDecl.Decl), + typeAndDecl.SemanticContext); } else { Lookup.addFunctionCallPattern( typeAndDecl.Type, diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index ff5034f10f527..22857c51466f2 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -299,8 +299,11 @@ class ExprParentFinder : public ASTWalker { static void collectPossibleCalleesByQualifiedLookup( DeclContext &DC, Type baseTy, DeclNameRef name, SmallVectorImpl &candidates) { - bool isOnMetaType = baseTy->is(); auto baseInstanceTy = baseTy->getMetatypeInstanceType(); + if (!baseInstanceTy->mayHaveMembers()) + return; + + bool isOnMetaType = baseTy->is(); SmallVector decls; if (!DC.lookupQualified(baseInstanceTy, @@ -389,8 +392,6 @@ static void collectPossibleCalleesByQualifiedLookup( baseTy = *baseTyOpt; } baseTy = baseTy->getWithoutSpecifierType(); - if (!baseTy->getMetatypeInstanceType()->mayHaveMembers()) - return; // Use metatype for lookup 'super.init' if it's inside constructors. if (isa(baseExpr) && isa(DC) && @@ -398,6 +399,22 @@ static void collectPossibleCalleesByQualifiedLookup( baseTy = MetatypeType::get(baseTy); collectPossibleCalleesByQualifiedLookup(DC, baseTy, name, candidates); + + // Add virtual 'subscript(keyPath: KeyPath) -> Value'. + if (name.getBaseName() == DeclBaseName::createSubscript() && + (baseTy->getAnyNominal() || baseTy->is() || + baseTy->is())) { + auto &Ctx = DC.getASTContext(); + + auto *kpDecl = Ctx.getKeyPathDecl(); + Type kpTy = kpDecl->mapTypeIntoContext(kpDecl->getDeclaredInterfaceType()); + Type kpValueTy = kpTy->castTo()->getGenericArgs()[1]; + kpTy = BoundGenericType::get(kpDecl, Type(), {baseTy, kpValueTy}); + + Type fnTy = FunctionType::get( + {AnyFunctionType::Param(kpTy, Ctx.Id_keyPath)}, kpValueTy); + candidates.emplace_back(fnTy->castTo(), nullptr); + } } /// For the given \c callExpr, collect possible callee types and declarations. diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index a74f5496f567b..84f9c98b2e55e 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -468,7 +468,7 @@ bool shouldUseOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) { // Don't emit accessors for functions that are not dynamic or dynamic // replacements. - return namingDecl->isNativeDynamic() || + return namingDecl->shouldUseNativeDynamicDispatch() || (bool)namingDecl->getDynamicallyReplacedDecl(); } diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 68a3e88a75739..24ad113408a4a 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2539,7 +2539,7 @@ void IRGenModule::emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) { // Don't emit accessors for functions that are not dynamic or dynamic // replacements. if (!abstractStorage) { - isNativeDynamic = namingDecl->isNativeDynamic(); + isNativeDynamic = namingDecl->shouldUseNativeDynamicDispatch(); if (!isNativeDynamic && !isDynamicReplacement) return; } diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 7eca86628b80c..a66253f6f093d 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -1551,7 +1551,7 @@ namespace { auto flags = getMethodDescriptorFlags(func); // Remember if the declaration was dynamic. - if (func->isObjCDynamic()) + if (func->shouldUseObjCDispatch()) flags = flags.withIsDynamic(true); // Include the pointer-auth discriminator. diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index 4b6c2c08b78cd..f4d28bb08c38d 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -1430,12 +1430,22 @@ void irgen::emitObjCSetterDescriptor(IRGenModule &IGM, emitObjCDescriptor(IGM, descriptors, descriptor); } +static bool isObjCGenericClassExtension(ValueDecl *decl) { + // Don't emit category entries for @objc methods in extensions they would + // normally be disallowed except for @_dynamicReplacement(for:) methods that + // use the native dynamic replacement mechanism instead of objc categories. + auto *DC = decl->getDeclContext(); + if (!isa(DC)) + return false; + return decl->isNativeMethodReplacement(); +} + bool irgen::requiresObjCMethodDescriptor(FuncDecl *method) { // Property accessors should be generated alongside the property. if (isa(method)) return false; - return method->isObjC(); + return method->isObjC() && !isObjCGenericClassExtension(method); } bool irgen::requiresObjCMethodDescriptor(ConstructorDecl *constructor) { @@ -1447,12 +1457,13 @@ bool irgen::requiresObjCPropertyDescriptor(IRGenModule &IGM, // Don't generate a descriptor for a property without any accessors. // This is only possible in SIL files because Sema will normally // implicitly synthesize accessors for @objc properties. - return property->isObjC() && property->requiresOpaqueAccessors(); + return property->isObjC() && property->requiresOpaqueAccessors() && + !isObjCGenericClassExtension(property); } bool irgen::requiresObjCSubscriptDescriptor(IRGenModule &IGM, SubscriptDecl *subscript) { - return subscript->isObjC(); + return subscript->isObjC() && !isObjCGenericClassExtension(subscript); } llvm::Value *IRGenFunction::emitBlockCopyCall(llvm::Value *value) { diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 59ff50b8ecdb2..ed4132c2da5ac 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1054,11 +1054,14 @@ void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs, if (FuncOptMode == OptimizationMode::ForSize) Attrs.addAttribute(llvm::Attribute::MinSize); - auto triple = llvm::Triple(ClangOpts.Triple); - if (triple.getArchName() == "arm64e") { + if (IRGen.Opts.PointerAuth.ReturnAddresses) Attrs.addAttribute("ptrauth-returns"); + if (IRGen.Opts.PointerAuth.FunctionPointers) Attrs.addAttribute("ptrauth-calls"); - } + if (IRGen.Opts.PointerAuth.IndirectGotos) + Attrs.addAttribute("ptrauth-indirect-gotos"); + if (IRGen.Opts.PointerAuth.AuthTraps) + Attrs.addAttribute("ptrauth-auth-traps"); } llvm::AttributeList IRGenModule::constructInitialAttributes() { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index a087b216a9fc4..02775bfd558b8 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1132,10 +1132,9 @@ Parser::parseExprPostfixSuffix(ParserResult Result, bool isExprBasic, if (CodeCompletion) { CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc); } - // Eat the code completion token because we handled it. - consumeToken(tok::code_complete); - Result.setHasCodeCompletion(); - return Result; + auto CCExpr = new (Context) CodeCompletionExpr(Result.get(), + consumeToken(tok::code_complete)); + return makeParserCodeCompletionResult(CCExpr); } DeclNameLoc NameLoc; @@ -3217,6 +3216,13 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange, if (!Tok.is(tok::code_complete)) break; + // If the current completion mode doesn't support trailing closure + // completion, leave the token here and let "postfix completion" to + // handle it. + if (CodeCompletion && + !CodeCompletion->canPerformCompleteLabeledTrailingClosure()) + break; + // foo() {} auto CCExpr = new (Context) CodeCompletionExpr(Tok.getLoc()); if (CodeCompletion) diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 05e19cef63602..42ec4a3476ef7 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -750,7 +750,7 @@ ParserResult Parser::parseStmtReturn(SourceLoc tryLoc) { SourceLoc ReturnLoc = consumeToken(tok::kw_return); if (Tok.is(tok::code_complete)) { - auto CCE = new (Context) CodeCompletionExpr(SourceRange(Tok.getLoc())); + auto CCE = new (Context) CodeCompletionExpr(Tok.getLoc()); auto Result = makeParserResult(new (Context) ReturnStmt(ReturnLoc, CCE)); if (CodeCompletion) { CodeCompletion->completeReturnStmt(CCE); @@ -818,7 +818,7 @@ ParserResult Parser::parseStmtYield(SourceLoc tryLoc) { SourceLoc yieldLoc = consumeToken(tok::kw_yield); if (Tok.is(tok::code_complete)) { - auto cce = new (Context) CodeCompletionExpr(SourceRange(Tok.getLoc())); + auto cce = new (Context) CodeCompletionExpr(Tok.getLoc()); auto result = makeParserResult( YieldStmt::create(Context, yieldLoc, SourceLoc(), cce, SourceLoc())); if (CodeCompletion) { @@ -1500,8 +1500,13 @@ Parser::parseStmtConditionElement(SmallVectorImpl &result, ThePattern = parseOptionalPatternTypeAnnotation(ThePattern, BindingKindStr != "case"); - if (ThePattern.hasCodeCompletion()) + if (ThePattern.hasCodeCompletion()) { Status.setHasCodeCompletion(); + + // Skip to '=' so that the completion can see the expected type of the + // pattern which is determined by the initializer. + skipUntilDeclStmtRBrace(tok::equal, tok::l_brace); + } if (ThePattern.isNull()) { // Recover by creating AnyPattern. diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 0af0f064e60a2..86d75b0d94f52 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -41,7 +41,7 @@ swift::getMethodDispatch(AbstractFunctionDecl *method) { auto dc = method->getDeclContext(); if (dc->getSelfClassDecl()) { - if (method->isObjCDynamic()) { + if (method->shouldUseObjCDispatch()) { return MethodDispatch::Class; } @@ -88,7 +88,7 @@ bool swift::requiresForeignToNativeThunk(ValueDecl *vd) { bool swift::requiresForeignEntryPoint(ValueDecl *vd) { assert(!isa(vd)); - if (vd->isObjCDynamic()) { + if (vd->shouldUseObjCDispatch()) { return true; } @@ -867,15 +867,15 @@ SILDeclRef SILDeclRef::getNextOverriddenVTableEntry() const { } // Overrides of @objc dynamic declarations are not in the vtable. - if (overridden.getDecl()->isObjCDynamic()) { + if (overridden.getDecl()->shouldUseObjCDispatch()) { return SILDeclRef(); } - + if (auto *accessor = dyn_cast(overridden.getDecl())) { auto *asd = accessor->getStorage(); if (asd->hasClangNode()) return SILDeclRef(); - if (asd->isObjCDynamic()) { + if (asd->shouldUseObjCDispatch()) { return SILDeclRef(); } } @@ -1106,6 +1106,10 @@ static bool isDesignatedConstructorForClass(ValueDecl *decl) { } bool SILDeclRef::canBeDynamicReplacement() const { + // The foreign entry of a @dynamicReplacement(for:) of @objc method in a + // generic class can't be a dynamic replacement. + if (isForeign && hasDecl() && getDecl()->isNativeMethodReplacement()) + return false; if (kind == SILDeclRef::Kind::Destroyer || kind == SILDeclRef::Kind::DefaultArgGenerator) return false; @@ -1117,6 +1121,11 @@ bool SILDeclRef::canBeDynamicReplacement() const { } bool SILDeclRef::isDynamicallyReplaceable() const { + // The non-foreign entry of a @dynamicReplacement(for:) of @objc method in a + // generic class can't be a dynamically replaced. + if (!isForeign && hasDecl() && getDecl()->isNativeMethodReplacement()) + return false; + if (kind == SILDeclRef::Kind::DefaultArgGenerator) return false; if (isStoredPropertyInitializer() || isPropertyWrapperBackingInitializer()) @@ -1138,5 +1147,15 @@ bool SILDeclRef::isDynamicallyReplaceable() const { return false; auto decl = getDecl(); - return decl->isNativeDynamic(); + + if (isForeign) + return false; + + // We can't generate categories for generic classes. So the standard mechanism + // for replacing @objc dynamic methods in generic classes does not work. + // Instead we mark the non @objc entry dynamically replaceable and replace + // that. + // For now, we only support this behavior if -enable-implicit-dynamic is + // enabled. + return decl->shouldUseNativeMethodReplacement(); } diff --git a/lib/SIL/IR/SILFunctionBuilder.cpp b/lib/SIL/IR/SILFunctionBuilder.cpp index e30dde44ec358..b56d34ea74d00 100644 --- a/lib/SIL/IR/SILFunctionBuilder.cpp +++ b/lib/SIL/IR/SILFunctionBuilder.cpp @@ -91,7 +91,10 @@ void SILFunctionBuilder::addFunctionAttributes( auto *decl = constant.getDecl(); // Only emit replacements for the objc entry point of objc methods. - if (decl->isObjC() && + // There is one exception: @_dynamicReplacement(for:) of @objc methods in + // generic classes. In this special case we use native replacement instead of + // @objc categories. + if (decl->isObjC() && !decl->isNativeMethodReplacement() && F->getLoweredFunctionType()->getExtInfo().getRepresentation() != SILFunctionTypeRepresentation::ObjCMethod) return; @@ -103,7 +106,10 @@ void SILFunctionBuilder::addFunctionAttributes( if (!replacedDecl) return; - if (decl->isObjC()) { + // For @objc method replacement we normally use categories to perform the + // replacement. Except for methods in generic class where we can't. Instead, + // we special case this and use the native swift replacement mechanism. + if (decl->isObjC() && !decl->isNativeMethodReplacement()) { F->setObjCReplacement(replacedDecl); return; } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 9d4307623df06..b774c781119d8 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1005,7 +1005,7 @@ class SILGenApply : public Lowering::ExprVisitor { // @objc dynamic initializers are statically dispatched (we're // calling the allocating entry point, which is a thunk that // does the dynamic dispatch for us). - if (ctor->isObjCDynamic()) + if (ctor->shouldUseObjCDispatch()) return false; // Required constructors are statically dispatched when the 'self' diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 2430f1df4b3d7..3b3129cf591af 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1466,7 +1466,7 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { // If @objc was inferred based on the Swift 3 @objc inference rules, emit // a call to Builtin.swift3ImplicitObjCEntrypoint() to enable runtime // logging of the uses of such entrypoints. - if (attr->isSwift3Inferred() && !decl->isObjCDynamic()) { + if (attr->isSwift3Inferred() && !decl->shouldUseObjCDispatch()) { // Get the starting source location of the declaration so we can say // exactly where to stick '@objc'. SourceLoc objcInsertionLoc = diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 596c6be33d2db..0efed4f651342 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -571,7 +571,7 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) { bool useObjCAllocation = usesObjCAllocator(selfClassDecl); if (ctor->hasClangNode() || - ctor->isObjCDynamic() || + ctor->shouldUseObjCDispatch() || ctor->isConvenienceInit()) { assert(ctor->hasClangNode() || ctor->isObjC()); // For an allocator thunk synthesized for an @objc convenience initializer diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 247242b1ddc59..ad1a0e0165a0d 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -154,7 +154,7 @@ SILGenFunction::emitSiblingMethodRef(SILLocation loc, // If the method is dynamic, access it through runtime-hookable virtual // dispatch (viz. objc_msgSend for now). if (methodConstant.hasDecl() - && methodConstant.getDecl()->isObjCDynamic()) { + && methodConstant.getDecl()->shouldUseObjCDispatch()) { methodValue = emitDynamicMethodRef( loc, methodConstant, diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 8cd45ba46bed8..4296dd4a14479 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -1463,7 +1463,7 @@ namespace { auto setterInfo = SGF.getConstantInfo(SGF.getTypeExpansionContext(), setter); SILValue setterFRef; - if (setter.hasDecl() && setter.getDecl()->isObjCDynamic()) { + if (setter.hasDecl() && setter.getDecl()->shouldUseObjCDispatch()) { // Emit a thunk we might have to bridge arguments. auto foreignSetterThunk = setter.asForeign(false); setterFRef = diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 41c87507021a9..e970715c6a845 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -4493,7 +4493,7 @@ static WitnessDispatchKind getWitnessDispatchKind(SILDeclRef witness, } // If the witness is dynamic, go through dynamic dispatch. - if (decl->isObjCDynamic()) { + if (decl->shouldUseObjCDispatch()) { // For initializers we still emit a static allocating thunk around // the dynamic initializing entry point. if (witness.kind == SILDeclRef::Kind::Allocator) diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 75c2b1aa662fa..b4356c89bb066 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -83,7 +83,7 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, // it will be redispatched, funneling the method call through the runtime // hook point. bool usesObjCDynamicDispatch = - (derivedDecl->isObjCDynamic() && + (derivedDecl->shouldUseObjCDispatch() && derived.kind != SILDeclRef::Kind::Allocator); if (usesObjCDynamicDispatch) { @@ -216,18 +216,27 @@ bool SILGenModule::requiresObjCMethodEntryPoint(FuncDecl *method) { if (auto accessor = dyn_cast(method)) { if (accessor->isGetterOrSetter()) { auto asd = accessor->getStorage(); - return asd->isObjC() && !asd->getAttrs().hasAttribute(); + return asd->isObjC() && !asd->getAttrs().hasAttribute() && + !method->isNativeMethodReplacement(); } } if (method->getAttrs().hasAttribute()) return false; + if (!method->isObjC()) + return false; - return method->isObjC(); + // Don't emit the objective c entry point of @_dynamicReplacement(for:) + // methods in generic classes. There is no way to call it. + return !method->isNativeMethodReplacement(); } bool SILGenModule::requiresObjCMethodEntryPoint(ConstructorDecl *constructor) { - return constructor->isObjC(); + if (!constructor->isObjC()) + return false; + // Don't emit the objective c entry point of @_dynamicReplacement(for:) + // methods in generic classes. There is no way to call it. + return !constructor->isNativeMethodReplacement(); } namespace { diff --git a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index c40ec0b6a30fb..1b4c5204a70be 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -52,8 +52,23 @@ class LiveRange { /// introducer and not to be forwarding. OwnedValueIntroducer introducer; + /// A vector that we store all of our uses into. + /// + /// Some properties of this array are: + /// + /// 1. It is only mutated in the constructor of LiveRange. + /// + /// 2. destroyingUses, ownershipForwardingUses, and unknownConsumingUses are + /// views into this array. We store the respective uses in the aforementioned + /// order. This is why it is important not to mutate consumingUses after we + /// construct the LiveRange since going from small -> large could invalidate + /// the uses. + SmallVector consumingUses; + /// A list of destroy_values of the live range. - SmallVector destroyingUses; + /// + /// This is just a view into consuming uses. + ArrayRef destroyingUses; /// A list of forwarding instructions that forward owned ownership, but that /// are also able to be converted to guaranteed ownership. If we are able to @@ -61,12 +76,12 @@ class LiveRange { /// flip the ownership of all of these instructions to guaranteed from owned. /// /// Corresponds to isOwnershipForwardingInst(...). - SmallVector ownershipForwardingUses; + ArrayRef ownershipForwardingUses; /// Consuming uses that we were not able to understand as a forwarding /// instruction or a destroy_value. These must be passed a strongly control /// equivalent +1 value. - SmallVector unknownConsumingUses; + ArrayRef unknownConsumingUses; public: LiveRange(SILValue value); @@ -87,6 +102,11 @@ class LiveRange { HasConsumingUse_t hasUnknownConsumingUse(bool assumingFixedPoint = false) const; + /// Return an array ref to /all/ consuming uses. Will include all 3 sorts of + /// consuming uses: destroying uses, forwarding consuming uses, and unknown + /// forwarding instruction. + ArrayRef getAllConsumingUses() const { return consumingUses; } + ArrayRef getDestroyingUses() const { return destroyingUses; } private: @@ -121,7 +141,7 @@ class LiveRange { return ownershipForwardingUses; } - void convertOwnedGeneralForwardingUsesToGuaranteed(); + void convertOwnedGeneralForwardingUsesToGuaranteed() &&; /// A consuming operation that: /// @@ -192,6 +212,10 @@ LiveRange::LiveRange(SILValue value) ownershipForwardingUses(), unknownConsumingUses() { assert(introducer.value.getOwnershipKind() == ValueOwnershipKind::Owned); + SmallVector tmpDestroyingUses; + SmallVector tmpForwardingConsumingUses; + SmallVector tmpUnknownConsumingUses; + // We know that our silvalue produces an @owned value. Look through all of our // uses and classify them as either consuming or not. SmallVector worklist(introducer.value->getUses()); @@ -220,7 +244,7 @@ LiveRange::LiveRange(SILValue value) // Ok, we know now that we have a consuming use. See if we have a destroy // value, quickly up front. If we do have one, stash it and continue. if (isa(user)) { - destroyingUses.push_back(op); + tmpDestroyingUses.push_back(op); continue; } @@ -244,13 +268,13 @@ LiveRange::LiveRange(SILValue value) return v.getOwnershipKind() == ValueOwnershipKind::Owned; })) { - unknownConsumingUses.push_back(op); + tmpUnknownConsumingUses.push_back(op); continue; } // Ok, this is a forwarding instruction whose ownership we can flip from // owned -> guaranteed. - ownershipForwardingUses.push_back(op); + tmpForwardingConsumingUses.push_back(op); // If we have a non-terminator, just visit its users recursively to see if // the the users force the live range to be alive. @@ -284,6 +308,20 @@ LiveRange::LiveRange(SILValue value) } } } + + // The order in which we append these to consumingUses matters since we assume + // their order as an invariant. This is done to ensure that we can pass off + // all of our uses or individual sub-arrays of our users without needing to + // move around memory. + llvm::copy(tmpDestroyingUses, std::back_inserter(consumingUses)); + llvm::copy(tmpForwardingConsumingUses, std::back_inserter(consumingUses)); + llvm::copy(tmpUnknownConsumingUses, std::back_inserter(consumingUses)); + + auto cUseArrayRef = llvm::makeArrayRef(consumingUses); + destroyingUses = cUseArrayRef.take_front(tmpDestroyingUses.size()); + ownershipForwardingUses = cUseArrayRef.slice( + tmpDestroyingUses.size(), tmpForwardingConsumingUses.size()); + unknownConsumingUses = cUseArrayRef.take_back(tmpUnknownConsumingUses.size()); } void LiveRange::insertEndBorrowsAtDestroys( @@ -339,9 +377,10 @@ void LiveRange::insertEndBorrowsAtDestroys( } } -void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() { +void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { while (!ownershipForwardingUses.empty()) { - auto *i = ownershipForwardingUses.pop_back_val()->getUser(); + auto *i = ownershipForwardingUses.back()->getUser(); + ownershipForwardingUses = ownershipForwardingUses.drop_back(); // If this is a term inst, just convert all of its incoming values that are // owned to be guaranteed. @@ -402,7 +441,8 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue, InstModCallbacks callbacks) && { auto *value = cast(introducer.value); while (!destroyingUses.empty()) { - auto *d = destroyingUses.pop_back_val(); + auto *d = destroyingUses.back(); + destroyingUses = destroyingUses.drop_back(); callbacks.deleteInst(d->getUser()); ++NumEliminatedInsts; } @@ -412,7 +452,7 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue, // Then change all of our guaranteed forwarding insts to have guaranteed // ownership kind instead of what ever they previously had (ignoring trivial // results); - convertOwnedGeneralForwardingUsesToGuaranteed(); + std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, @@ -429,7 +469,8 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, // Then eliminate all of the destroys... while (!destroyingUses.empty()) { - auto *d = destroyingUses.pop_back_val(); + auto *d = destroyingUses.back(); + destroyingUses = destroyingUses.drop_back(); callbacks.deleteInst(d->getUser()); ++NumEliminatedInsts; } @@ -437,7 +478,7 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, // and change all of our guaranteed forwarding insts to have guaranteed // ownership kind instead of what ever they previously had (ignoring trivial // results); - convertOwnedGeneralForwardingUsesToGuaranteed(); + std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } LiveRange::HasConsumingUse_t @@ -1297,8 +1338,9 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst SmallVector scratchSpace; SmallPtrSet visitedBlocks; if (llvm::any_of(borrowScopeIntroducers, [&](BorrowedValue borrowScope) { - return !borrowScope.areUsesWithinScope( - destroys, scratchSpace, visitedBlocks, getDeadEndBlocks()); + return !borrowScope.areUsesWithinScope(lr.getAllConsumingUses(), + scratchSpace, visitedBlocks, + getDeadEndBlocks()); })) { return false; } @@ -1330,12 +1372,11 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst return false; } - if (llvm::any_of(borrowScopeIntroducers, - [&](BorrowedValue borrowScope) { - return !borrowScope.areUsesWithinScope( - phiArgLR.getDestroyingUses(), scratchSpace, - visitedBlocks, getDeadEndBlocks()); - })) { + if (llvm::any_of(borrowScopeIntroducers, [&](BorrowedValue borrowScope) { + return !borrowScope.areUsesWithinScope( + phiArgLR.getAllConsumingUses(), scratchSpace, visitedBlocks, + getDeadEndBlocks()); + })) { return false; } } @@ -1641,7 +1682,7 @@ class StorageGuaranteesLoadVisitor SmallPtrSet visitedBlocks; LinearLifetimeChecker checker(visitedBlocks, ARCOpt.getDeadEndBlocks()); if (!checker.validateLifetime(access, endScopeUses, - liveRange.getDestroyingUses())) { + liveRange.getAllConsumingUses())) { // If we fail the linear lifetime check, then just recur: return next(access->getOperand()); } @@ -1738,8 +1779,8 @@ class StorageGuaranteesLoadVisitor LinearLifetimeChecker checker(visitedBlocks, ARCOpt.getDeadEndBlocks()); // Returns true on success. So we invert. - bool foundError = !checker.validateLifetime(baseObject, endScopeInsts, - liveRange.getDestroyingUses()); + bool foundError = !checker.validateLifetime( + baseObject, endScopeInsts, liveRange.getAllConsumingUses()); return answer(foundError); } @@ -1777,7 +1818,7 @@ class StorageGuaranteesLoadVisitor // Returns true on success. So we invert. bool foundError = !checker.validateLifetime( stack, destroyAddrOperands /*consuming users*/, - liveRange.getDestroyingUses() /*non consuming users*/); + liveRange.getAllConsumingUses() /*non consuming users*/); return answer(foundError); } diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index dc780435f7be0..8cb067e112841 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -711,7 +711,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const { } break; - case ConstraintKind::OneWayEqual: { + case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: { // Don't produce any bindings if this type variable is on the left-hand // side of a one-way binding. auto firstType = constraint->getFirstType(); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index ab03b13fbc402..4519e73598dc3 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1175,9 +1175,24 @@ namespace { virtual Type visitCodeCompletionExpr(CodeCompletionExpr *E) { CS.Options |= ConstraintSystemFlags::SuppressDiagnostics; - return CS.createTypeVariable(CS.getConstraintLocator(E), - TVO_CanBindToLValue | - TVO_CanBindToNoEscape); + auto locator = CS.getConstraintLocator(E); + auto ty = CS.createTypeVariable(locator, + TVO_CanBindToLValue | + TVO_CanBindToNoEscape); + + // Defaults to the type of the base expression if we have a base + // expression. + // FIXME: This is just to keep the old behavior where `foo(base.)` + // the argument is type checked to the type of the 'base'. Ideally, code + // completion expression should be defauled to 'UnresolvedType' + // regardless of the existence of the base expression. But the constraint + // system is simply not ready for that. + if (auto base = E->getBase()) { + CS.addConstraint(ConstraintKind::Defaultable, ty, CS.getType(base), + locator); + } + + return ty; } Type visitNilLiteralExpr(NilLiteralExpr *expr) { diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 0088b425b7d41..d274e4117c515 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1322,6 +1322,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, case ConstraintKind::FunctionInput: case ConstraintKind::FunctionResult: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: llvm_unreachable("Not a conversion"); } @@ -1387,6 +1388,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1, case ConstraintKind::FunctionInput: case ConstraintKind::FunctionResult: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: return false; } @@ -1698,6 +1700,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, case ConstraintKind::FunctionInput: case ConstraintKind::FunctionResult: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: llvm_unreachable("Not a relational constraint"); } @@ -4340,6 +4343,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, case ConstraintKind::FunctionInput: case ConstraintKind::FunctionResult: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: llvm_unreachable("Not a relational constraint"); } @@ -7064,9 +7068,16 @@ ConstraintSystem::simplifyOneWayConstraint( return SolutionKind::Solved; } - // Translate this constraint into a one-way binding constraint. - return matchTypes(first, secondSimplified, ConstraintKind::Equal, flags, - locator); + // Translate this constraint into an equality or bind-parameter constraint, + // as appropriate. + if (kind == ConstraintKind::OneWayEqual) { + return matchTypes(first, secondSimplified, ConstraintKind::Equal, flags, + locator); + } + + assert(kind == ConstraintKind::OneWayBindParam); + return matchTypes( + secondSimplified, first, ConstraintKind::BindParam, flags, locator); } static Type getFunctionBuilderTypeFor(ConstraintSystem &cs, unsigned paramIdx, @@ -7104,6 +7115,24 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, auto *closure = cast(closureLocator->getAnchor()); auto *inferredClosureType = getClosureType(closure); + // Determine whether a function builder will be applied. + Type functionBuilderType; + ConstraintLocator *calleeLocator = nullptr; + if (auto last = locator.last()) { + if (auto argToParam = last->getAs()) { + calleeLocator = getCalleeLocator(getConstraintLocator(locator)); + functionBuilderType = getFunctionBuilderTypeFor( + *this, argToParam->getParamIdx(), calleeLocator); + } + } + + // Determine whether to introduce one-way constraints between the parameter's + // type as seen in the body of the closure and the external parameter + // type. + bool oneWayConstraints = + getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters || + functionBuilderType; + auto *paramList = closure->getParameters(); SmallVector parameters; for (unsigned i = 0, n = paramList->size(); i != n; ++i) { @@ -7117,13 +7146,25 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, } Type internalType; - if (paramList->get(i)->getTypeRepr()) { // Internal type is the type used in the body of the closure, // so "external" type translates to it as follows: // - `Int...` -> `[Int]`, // - `inout Int` -> `@lvalue Int`. internalType = param.getParameterType(); + + // When there are type variables in the type and we have enabled + // one-way constraints, create a fresh type variable to handle the + // binding. + if (oneWayConstraints && internalType->hasTypeVariable()) { + auto *paramLoc = + getConstraintLocator(closure, LocatorPathElt::TupleElement(i)); + auto *typeVar = createTypeVariable(paramLoc, TVO_CanBindToLValue | + TVO_CanBindToNoEscape); + addConstraint( + ConstraintKind::OneWayBindParam, typeVar, internalType, paramLoc); + internalType = typeVar; + } } else { auto *paramLoc = getConstraintLocator(closure, LocatorPathElt::TupleElement(i)); @@ -7137,7 +7178,13 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, param.isVariadic() ? ArraySliceType::get(typeVar) : Type(typeVar); auto externalType = param.getOldType(); - addConstraint(ConstraintKind::BindParam, externalType, typeVar, paramLoc); + if (oneWayConstraints) { + addConstraint( + ConstraintKind::OneWayBindParam, typeVar, externalType, paramLoc); + } else { + addConstraint( + ConstraintKind::BindParam, externalType, typeVar, paramLoc); + } } setType(paramList->get(i), internalType); @@ -7149,17 +7196,12 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, inferredClosureType->getExtInfo()); assignFixedType(typeVar, closureType, closureLocator); - if (auto last = locator.last()) { - if (auto argToParam = last->getAs()) { - auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator)); - if (auto functionBuilderType = getFunctionBuilderTypeFor( - *this, argToParam->getParamIdx(), calleeLocator)) { - if (auto result = matchFunctionBuilder( - closure, functionBuilderType, closureType->getResult(), - ConstraintKind::Conversion, calleeLocator, locator)) { - return result->isSuccess(); - } - } + // If there is a function builder to apply, do so now. + if (functionBuilderType) { + if (auto result = matchFunctionBuilder( + closure, functionBuilderType, closureType->getResult(), + ConstraintKind::Conversion, calleeLocator, locator)) { + return result->isSuccess(); } } @@ -9687,6 +9729,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first, subflags, locator); case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: return simplifyOneWayConstraint(kind, first, second, subflags, locator); case ConstraintKind::ValueMember: @@ -10194,6 +10237,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { return SolutionKind::Unsolved; case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: return simplifyOneWayConstraint(constraint.getKind(), constraint.getFirstType(), constraint.getSecondType(), diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 0399da93579b3..b2df207007158 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1703,6 +1703,7 @@ void ConstraintSystem::ArgumentInfoCollector::walk(Type argType) { case ConstraintKind::ConformsTo: case ConstraintKind::Defaultable: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: break; } diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index ad7ab14a32841..0a41ae0c69442 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -66,6 +66,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, case ConstraintKind::FunctionResult: case ConstraintKind::OpaqueUnderlyingType: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: assert(!First.isNull()); assert(!Second.isNull()); break; @@ -138,6 +139,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third, case ConstraintKind::FunctionResult: case ConstraintKind::OpaqueUnderlyingType: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: llvm_unreachable("Wrong constructor"); @@ -265,6 +267,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const { case ConstraintKind::FunctionResult: case ConstraintKind::OpaqueUnderlyingType: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: return create(cs, getKind(), getFirstType(), getSecondType(), getLocator()); @@ -348,6 +351,7 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const { case ConstraintKind::EscapableFunctionOf: Out << " @escaping type of "; break; case ConstraintKind::OpenedExistentialOf: Out << " opened archetype of "; break; case ConstraintKind::OneWayEqual: Out << " one-way bind to "; break; + case ConstraintKind::OneWayBindParam: Out << " one-way bind param to "; break; case ConstraintKind::DefaultClosureType: Out << " closure can default to "; break; @@ -564,6 +568,7 @@ gatherReferencedTypeVars(Constraint *constraint, case ConstraintKind::FunctionResult: case ConstraintKind::OpaqueUnderlyingType: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: constraint->getFirstType()->getTypeVariables(typeVars); constraint->getSecondType()->getTypeVariables(typeVars); diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h index 23e615fed081d..d13a95bb39889 100644 --- a/lib/Sema/Constraint.h +++ b/lib/Sema/Constraint.h @@ -161,6 +161,12 @@ enum class ConstraintKind : char { /// type). At that point, this constraint will be treated like an `Equal` /// constraint. OneWayEqual, + /// The second type is the type of a function parameter, and the first type + /// is the type of a reference to that function parameter within the body. + /// Once the second type has been fully determined (and mapped down to a + /// concrete type), this constraint will be treated like a 'BindParam' + /// constraint. + OneWayBindParam, /// If there is no contextual info e.g. `_ = { 42 }` default first type /// to a second type (inferred closure type). This is effectively a /// `Defaultable` constraint which a couple of differences: @@ -549,6 +555,7 @@ class Constraint final : public llvm::ilist_node, case ConstraintKind::OptionalObject: case ConstraintKind::OpaqueUnderlyingType: case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: case ConstraintKind::DefaultClosureType: return ConstraintClassification::Relational; @@ -669,7 +676,8 @@ class Constraint final : public llvm::ilist_node, /// Whether this is a one-way constraint. bool isOneWayConstraint() const { - return Kind == ConstraintKind::OneWayEqual; + return Kind == ConstraintKind::OneWayEqual || + Kind == ConstraintKind::OneWayBindParam; } /// Retrieve the overload choice for an overload-binding constraint. diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 43dd231aa7204..740382e1d352f 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -3334,6 +3334,13 @@ void constraints::simplifyLocator(Expr *&anchor, if (auto subscriptExpr = dyn_cast(anchor)) { anchor = subscriptExpr->getIndex(); path = path.slice(1); + + // TODO: It would be better if the index expression was always wrapped + // in a ParenExpr (if there is no label). + if (!(isa(anchor) || isa(anchor)) && + !path.empty() && path[0].is()) { + path = path.slice(1); + } continue; } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index a0ea012d0a2fb..cfbfe1f230140 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4286,7 +4286,7 @@ static void maybeDiagnoseCallToKeyValueObserveMethod(const Expr *E, if (!property) return; auto propertyVar = cast(property); - if (propertyVar->isObjCDynamic() || + if (propertyVar->shouldUseObjCDispatch() || (propertyVar->isObjC() && propertyVar->getParsedAccessor(AccessorKind::Set))) return; diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp index 79488edcae34e..ee8cf299ed2dc 100644 --- a/lib/Sema/ResilienceDiagnostics.cpp +++ b/lib/Sema/ResilienceDiagnostics.cpp @@ -81,7 +81,7 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc, // Dynamic declarations were mistakenly not checked in Swift 4.2. // Do enforce the restriction even in pre-Swift-5 modes if the module we're // building is resilient, though. - if (D->isObjCDynamic() && !Context.isSwiftVersionAtLeast(5) && + if (D->shouldUseObjCDispatch() && !Context.isSwiftVersionAtLeast(5) && !DC->getParentModule()->isResilient()) { return false; } diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 6015b60c30cff..5b05de70bd962 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2583,7 +2583,7 @@ void AttributeChecker::visitDynamicReplacementAttr(DynamicReplacementAttr *attr) return; } - if (replacement->isNativeDynamic()) { + if (replacement->shouldUseNativeDynamicDispatch()) { diagnose(attr->getLocation(), diag::dynamic_replacement_must_not_be_dynamic, replacement->getBaseName()); attr->setInvalid(); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 20253af8fd9f2..f1620fb6882b1 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -833,7 +833,7 @@ NeedsNewVTableEntryRequest::evaluate(Evaluator &evaluator, // Final members are always be called directly. // Dynamic methods are always accessed by objc_msgSend(). - if (decl->isFinal() || decl->isObjCDynamic() || decl->hasClangNode()) + if (decl->isFinal() || decl->shouldUseObjCDispatch() || decl->hasClangNode()) return false; auto &ctx = dc->getASTContext(); @@ -863,7 +863,7 @@ NeedsNewVTableEntryRequest::evaluate(Evaluator &evaluator, auto base = decl->getOverriddenDecl(); - if (!base || base->hasClangNode() || base->isObjCDynamic()) + if (!base || base->hasClangNode() || base->shouldUseObjCDispatch()) return true; // As above, convenience initializers are not formally overridable in Swift diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 15642a98193ba..443f10e1936dc 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -437,6 +437,14 @@ static bool checkObjCInExtensionContext(const ValueDecl *value, } if (classDecl->isGenericContext()) { + // We do allow one special case. A @_dynamicReplacement(for:) function. + // Currently, this is only supported if the replaced decl is from a + // module compiled with -enable-implicit-dynamic. + if (value->getDynamicallyReplacedDecl() && + value->getDynamicallyReplacedDecl() + ->getModuleContext() + ->isImplicitDynamicEnabled()) + return false; if (!classDecl->usesObjCGenericsModel()) { if (diagnose) { value->diagnose(diag::objc_in_generic_extension, diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index dc853a680bfaf..6a82bcd6630dd 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1819,7 +1819,7 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) { if (auto *baseDecl = dyn_cast(base->getDeclContext())) { if (!isAccessor && baseDecl->hasKnownSwiftImplementation() && - !base->isObjCDynamic() && + !base->shouldUseObjCDispatch() && isa(override->getDeclContext())) { diags.diagnose(override, diag::override_class_declaration_in_extension); diags.diagnose(base, diag::overridden_here); diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp index 7807a7dd02c14..d1fa6258a7e0e 100644 --- a/lib/Sema/TypeCheckRequestFunctions.cpp +++ b/lib/Sema/TypeCheckRequestFunctions.cpp @@ -210,44 +210,109 @@ static Type inferFunctionBuilderType(ValueDecl *decl) { lookupDecl = accessor->getStorage(); } - // Determine all of the conformances within the same context as - // this declaration. If this declaration is a witness to any - // requirement within one of those protocols that has a function builder - // attached, use that function builder type. - auto conformances = evaluateOrDefault( - dc->getASTContext().evaluator, - LookupAllConformancesInContextRequest{dc}, { }); - // Find all of the potentially inferred function builder types. struct Match { - ProtocolConformance *conformance; - ValueDecl *requirement; + enum Kind { + Conformance, + DynamicReplacement, + } kind; + + union { + struct { + ProtocolConformance *conformance; + ValueDecl *requirement; + } conformanceMatch; + + ValueDecl *dynamicReplacement; + }; + Type functionBuilderType; - }; - SmallVector matches; - for (auto conformance : conformances) { - auto protocol = conformance->getProtocol(); - for (auto found : protocol->lookupDirect(lookupDecl->getName())) { - if (!isa(found->getDeclContext())) - continue; - auto requirement = dyn_cast(found); - if (!requirement) - continue; + static Match forConformance( + ProtocolConformance *conformance, + ValueDecl *requirement, + Type functionBuilderType) { + Match match; + match.kind = Conformance; + match.conformanceMatch.conformance = conformance; + match.conformanceMatch.requirement = requirement; + match.functionBuilderType = functionBuilderType; + return match; + } - Type functionBuilderType = requirement->getFunctionBuilderType(); - if (!functionBuilderType) - continue; + static Match forDynamicReplacement( + ValueDecl *dynamicReplacement, Type functionBuilderType) { + Match match; + match.kind = DynamicReplacement; + match.dynamicReplacement = dynamicReplacement; + match.functionBuilderType = functionBuilderType; + return match; + } - auto witness = conformance->getWitnessDecl(requirement); - if (witness != lookupDecl) - continue; + DeclName getSourceName() const { + switch (kind) { + case Conformance: + return conformanceMatch.conformance->getProtocol()->getName(); - // Substitute into the function builder type. - auto subs = conformance->getSubstitutions(decl->getModuleContext()); - Type subFunctionBuilderType = functionBuilderType.subst(subs); + case DynamicReplacement: + return dynamicReplacement->getName(); + } + } + }; + + // The set of matches from which we can infer function builder types. + SmallVector matches; - matches.push_back({conformance, requirement, subFunctionBuilderType}); + // Determine all of the conformances within the same context as + // this declaration. If this declaration is a witness to any + // requirement within one of those protocols that has a function builder + // attached, use that function builder type. + auto addConformanceMatches = [&matches](ValueDecl *lookupDecl) { + DeclContext *dc = lookupDecl->getDeclContext(); + auto idc = cast(dc->getAsDecl()); + auto conformances = evaluateOrDefault( + dc->getASTContext().evaluator, + LookupAllConformancesInContextRequest{dc}, { }); + + for (auto conformance : conformances) { + auto protocol = conformance->getProtocol(); + for (auto found : protocol->lookupDirect(lookupDecl->getName())) { + if (!isa(found->getDeclContext())) + continue; + + auto requirement = dyn_cast(found); + if (!requirement) + continue; + + Type functionBuilderType = requirement->getFunctionBuilderType(); + if (!functionBuilderType) + continue; + + auto witness = conformance->getWitnessDecl(requirement); + if (witness != lookupDecl) + continue; + + // Substitute into the function builder type. + auto subs = + conformance->getSubstitutions(lookupDecl->getModuleContext()); + Type subFunctionBuilderType = functionBuilderType.subst(subs); + + matches.push_back( + Match::forConformance( + conformance, requirement, subFunctionBuilderType)); + } + } + }; + + addConformanceMatches(lookupDecl); + + // Look for function builder types inferred through dynamic replacements. + if (auto replaced = lookupDecl->getDynamicallyReplacedDecl()) { + if (auto functionBuilderType = replaced->getFunctionBuilderType()) { + matches.push_back( + Match::forDynamicReplacement(replaced, functionBuilderType)); + } else { + addConformanceMatches(replaced); } } @@ -273,7 +338,8 @@ static Type inferFunctionBuilderType(ValueDecl *decl) { decl->diagnose( diag::function_builder_infer_pick_specific, match.functionBuilderType, - match.conformance->getProtocol()->getName()) + static_cast(match.kind), + match.getSourceName()) .fixItInsert( lookupDecl->getAttributeInsertionLoc(false), "@" + match.functionBuilderType.getString() + " "); diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index a3599f481ee1c..e9c2a65b94961 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2083,7 +2083,7 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator, } else if (dc->isModuleScopeContext()) { // Fixed-layout global variables don't require opaque accessors. - if (!var->isResilient() && !var->isNativeDynamic()) + if (!var->isResilient() && !var->shouldUseNativeDynamicDispatch()) return false; // Stored properties imported from Clang don't require opaque accessors. @@ -2128,7 +2128,7 @@ RequiresOpaqueModifyCoroutineRequest::evaluate(Evaluator &evaluator, // Dynamic storage does not have an opaque modify coroutine. if (dc->getSelfClassDecl()) - if (storage->isObjCDynamic()) + if (storage->shouldUseObjCDispatch()) return false; // Requirements of ObjC protocols don't have an opaque modify coroutine. @@ -2684,16 +2684,21 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator, pbd->setInit(0, initializer); pbd->setInitializerChecked(0); wrappedValue = findWrappedValuePlaceholder(initializer); - } else if (!parentPBD->isInitialized(patternNumber) && - wrapperInfo.defaultInit) { - // FIXME: Record this expression somewhere so that DI can perform the - // initialization itself. - auto typeExpr = TypeExpr::createImplicit(storageType, ctx); - Expr *initializer = CallExpr::createImplicit(ctx, typeExpr, {}, { }); - typeCheckSynthesizedWrapperInitializer(pbd, backingVar, parentPBD, - initializer); - pbd->setInit(0, initializer); - pbd->setInitializerChecked(0); + } else { + if (!parentPBD->isInitialized(patternNumber) && wrapperInfo.defaultInit) { + // FIXME: Record this expression somewhere so that DI can perform the + // initialization itself. + auto typeExpr = TypeExpr::createImplicit(storageType, ctx); + Expr *initializer = CallExpr::createImplicit(ctx, typeExpr, {}, { }); + typeCheckSynthesizedWrapperInitializer(pbd, backingVar, parentPBD, + initializer); + pbd->setInit(0, initializer); + pbd->setInitializerChecked(0); + } + + if (var->getOpaqueResultTypeDecl()) { + var->diagnose(diag::opaque_type_var_no_underlying_type); + } } // If there is a projection property (projectedValue) in the wrapper, diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 5c2ed6f52a5dc..22b84ba5410e7 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -152,6 +152,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor, case options_block::ARE_PRIVATE_IMPORTS_ENABLED: extendedInfo.setPrivateImportsEnabled(true); break; + case options_block::IS_IMPLICIT_DYNAMIC_ENABLED: + extendedInfo.setImplicitDynamicEnabled(true); + break; case options_block::RESILIENCE_STRATEGY: unsigned Strategy; options_block::ResilienceStrategyLayout::readRecord(scratch, Strategy); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index ca49bee023b5e..3376baac0fb85 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 555; // add @main attribute +const uint16_t SWIFTMODULE_VERSION_MINOR = 556; // Serialization of -implicit-dynamic /// A standard hash seed used for all string hashes in a serialized module. /// @@ -753,7 +753,8 @@ namespace options_block { IS_SIB, IS_TESTABLE, RESILIENCE_STRATEGY, - ARE_PRIVATE_IMPORTS_ENABLED + ARE_PRIVATE_IMPORTS_ENABLED, + IS_IMPLICIT_DYNAMIC_ENABLED }; using SDKPathLayout = BCRecordLayout< @@ -779,6 +780,10 @@ namespace options_block { ARE_PRIVATE_IMPORTS_ENABLED >; + using IsImplicitDynamicEnabledLayout = BCRecordLayout< + IS_IMPLICIT_DYNAMIC_ENABLED + >; + using ResilienceStrategyLayout = BCRecordLayout< RESILIENCE_STRATEGY, BCFixed<2> diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 13f0ec0d39f9b..322b7be43fd7f 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -903,6 +903,11 @@ void Serializer::writeHeader(const SerializationOptions &options) { PrivateImports.emit(ScratchRecord); } + if (M->isImplicitDynamicEnabled()) { + options_block::IsImplicitDynamicEnabledLayout ImplicitDynamic(Out); + ImplicitDynamic.emit(ScratchRecord); + } + if (M->getResilienceStrategy() != ResilienceStrategy::Default) { options_block::ResilienceStrategyLayout Strategy(Out); Strategy.emit(ScratchRecord, unsigned(M->getResilienceStrategy())); @@ -2795,7 +2800,7 @@ class Serializer::DeclSerializer : public DeclVisitor { // its overrides after they've been compiled: if the declaration is '@objc' // and 'dynamic'. In that case, all accesses to the method or property will // go through the Objective-C method tables anyway. - if (overridden->hasClangNode() || overridden->isObjCDynamic()) + if (overridden->hasClangNode() || overridden->shouldUseObjCDispatch()) return false; return true; } diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 8fe3c2d277b2e..0f6bba4d2532d 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -643,6 +643,8 @@ FileUnit *SerializedModuleLoaderBase::loadAST( M.setTestingEnabled(); if (extendedInfo.arePrivateImportsEnabled()) M.setPrivateImportsEnabled(); + if (extendedInfo.isImplicitDynamicEnabled()) + M.setImplicitDynamicEnabled(); auto diagLocOrInvalid = diagLoc.getValueOr(SourceLoc()); loadInfo.status = diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index d3fbc93980264..47a13619fc14f 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -636,7 +636,7 @@ void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) { addSymbol(SILDeclRef(AFD)); // Add the global function pointer for a dynamically replaceable function. - if (AFD->isNativeDynamic()) { + if (AFD->shouldUseNativeMethodReplacement()) { bool useAllocator = shouldUseAllocatorMangling(AFD); addSymbol(LinkEntity::forDynamicallyReplaceableFunctionVariable( AFD, useAllocator)); @@ -681,7 +681,7 @@ void TBDGenVisitor::visitFuncDecl(FuncDecl *FD) { if (auto opaqueResult = FD->getOpaqueResultTypeDecl()) { addSymbol(LinkEntity::forOpaqueTypeDescriptor(opaqueResult)); assert(opaqueResult->getNamingDecl() == FD); - if (FD->isNativeDynamic()) { + if (FD->shouldUseNativeDynamicDispatch()) { addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessor(opaqueResult)); addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorImpl(opaqueResult)); addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorKey(opaqueResult)); diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb index 8c66a6ef8546e..a0242df85313b 100644 --- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb @@ -616,7 +616,7 @@ extension Unsafe${Mutable}BufferPointer { /// - repeatedValue: The instance to assign this buffer's memory to. /// /// Warning: All buffer elements must be initialized before calling this. - /// Assigning to part of the buffer must be done using the `assign(repeating:count:)`` + /// Assigning to part of the buffer must be done using the `assign(repeating:count:)` /// method on the buffer’s `baseAddress`. @inlinable // unsafe-performance public func assign(repeating repeatedValue: Element) { diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 9d6c7013bb5a0..127fac8653b44 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -4536,8 +4536,8 @@ WitnessTableCacheEntry::allocate( // Find the allocation. void **fullTable = reinterpret_cast(this + 1); - // Zero out the private storage area. - memset(fullTable, 0, privateSizeInWords * sizeof(void*)); + // Zero out the witness table. + memset(fullTable, 0, getWitnessTableSize(conformance)); // Advance the address point; the private storage area is accessed via // negative offsets. diff --git a/test/Constraints/function_builder_diags.swift b/test/Constraints/function_builder_diags.swift index 389ddc5ba6bc1..1a04e05892926 100644 --- a/test/Constraints/function_builder_diags.swift +++ b/test/Constraints/function_builder_diags.swift @@ -558,3 +558,14 @@ func rdar61347993() { func test_closure(_: () -> Result) {} test_closure {} // expected-error {{cannot convert value of type '()' to closure result type 'Result'}} } + +// One-way constraints through parameters. +func wrapperifyInfer(_ cond: Bool, @WrapperBuilder body: (U) -> T) -> T { + fatalError("boom") +} + +let intValue = 17 +wrapperifyInfer(true) { x in // expected-error{{unable to infer type of a closure parameter 'x' in the current context}} + intValue + x +} + diff --git a/test/Constraints/function_builder_infer.swift b/test/Constraints/function_builder_infer.swift index 7444cbb179110..1715352d39424 100644 --- a/test/Constraints/function_builder_infer.swift +++ b/test/Constraints/function_builder_infer.swift @@ -184,3 +184,51 @@ struct TupleMeResolvedExplicit: Tupled, OtherTupled { return "hello" } } + +// Inference through dynamic replacement +struct DynamicTupled: Tupled { + dynamic var tuple: some Any { + return "hello" + } +} + +extension DynamicTupled { + @_dynamicReplacement(for: tuple) + var replacementTuple: some Any { + 1 + 3.14159 + "hello" + } +} + +struct DynamicTupled2: Tupled, OtherTupled { + dynamic var tuple: some Any { + return "hello" + } +} + +extension DynamicTupled2 { + @_dynamicReplacement(for: tuple) + var replacementTuple: some Any { // expected-error{{ambiguous function builder inferred for 'replacementTuple': 'TupleBuilder' or 'OtherTupleBuilder'}} + // expected-note@-1{{add an explicit 'return' statement to not use a function builder}} + // expected-note@-2{{apply function builder 'TupleBuilder' (inferred from protocol 'Tupled')}} + // expected-note@-3{{apply function builder 'OtherTupleBuilder' (inferred from protocol 'OtherTupled')}} + 1 + } +} + +struct DynamicTupled3 { + @TupleBuilder dynamic var dynamicTuple: some Any { + 0 + } +} + +extension DynamicTupled3: OtherTupled { + @_dynamicReplacement(for: dynamicTuple) + var tuple: some Any { // expected-error{{ambiguous function builder inferred for 'tuple': 'OtherTupleBuilder' or 'TupleBuilder'}} + // expected-note@-1{{add an explicit 'return' statement to not use a function builder}} + // expected-note@-2{{apply function builder 'OtherTupleBuilder' (inferred from protocol 'OtherTupled')}} + // expected-note@-3{{apply function builder 'TupleBuilder' (inferred from dynamic replacement of 'dynamicTuple')}} + 0 + } +} diff --git a/test/Constraints/function_builder_one_way.swift b/test/Constraints/function_builder_one_way.swift index d393025c4b01c..e3519800497f1 100644 --- a/test/Constraints/function_builder_one_way.swift +++ b/test/Constraints/function_builder_one_way.swift @@ -49,16 +49,17 @@ func tuplify(_ collection: C, @TupleBuilder body: (C.Element) } // CHECK: ---Connected components--- -// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T10 $T77 $T78 depends on 2 -// CHECK-NEXT: 2: $T12 $T17 $T28 $T42 $T53 $T54 $T55 $T56 $T57 $T58 $T59 $T60 $T61 $T62 $T63 $T64 $T65 $T66 $T68 $T69 $T70 $T71 $T72 $T73 $T74 $T75 $T76 depends on 1, 3, 4, 6, 9 -// CHECK-NEXT: 9: $T48 $T49 $T50 $T51 $T52 depends on 8 -// CHECK-NEXT: 8: $T43 $T44 $T45 $T46 $T47 -// CHECK-NEXT: 6: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 5, 7 -// CHECK-NEXT: 7: $T32 $T33 $T34 -// CHECK-NEXT: 5: $T30 -// CHECK-NEXT: 4: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 -// CHECK-NEXT: 3: $T15 $T16 -// CHECK-NEXT: 1: $T11 +// CHECK-NEXT: 1: $T10 depends on 0 +// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T77 $T78 depends on 3 +// CHECK-NEXT: 3: $T12 $T17 $T28 $T42 $T53 $T54 $T55 $T56 $T57 $T58 $T59 $T60 $T61 $T62 $T63 $T64 $T65 $T66 $T68 $T69 $T70 $T71 $T72 $T73 $T74 $T75 $T76 depends on 2, 4, 5, 7, 10 +// CHECK-NEXT: 10: $T48 $T49 $T50 $T51 $T52 depends on 9 +// CHECK-NEXT: 9: $T43 $T44 $T45 $T46 $T47 +// CHECK-NEXT: 7: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 6, 8 +// CHECK-NEXT: 8: $T32 $T33 $T34 +// CHECK-NEXT: 6: $T30 +// CHECK-NEXT: 5: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 +// CHECK-NEXT: 4: $T15 $T16 +// CHECK-NEXT: 2: $T11 let names = ["Alice", "Bob", "Charlie"] let b = true var number = 17 diff --git a/test/Constraints/one_way_closure_params.swift b/test/Constraints/one_way_closure_params.swift new file mode 100644 index 0000000000000..c62bb7256cb7b --- /dev/null +++ b/test/Constraints/one_way_closure_params.swift @@ -0,0 +1,8 @@ +// RUN: %target-typecheck-verify-swift -swift-version 4 -experimental-one-way-closure-params + +func testBasic() { + let _: (Float) -> Float = { $0 + 1 } + + let _ = { $0 + 1 } // expected-error{{unable to infer type of a closure parameter $0 in the current context}} +} + diff --git a/test/IDE/complete_enum_elements.swift b/test/IDE/complete_enum_elements.swift index 01a5138abee84..7f4097efb0a9c 100644 --- a/test/IDE/complete_enum_elements.swift +++ b/test/IDE/complete_enum_elements.swift @@ -29,7 +29,7 @@ // RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT_ELEMENTS < %t.enum.txt // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_WITH_QUAL_1 > %t.enum.txt -// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT < %t.enum.txt +// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT_CONTEXT < %t.enum.txt // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_EXPR_ERROR_1 > %t.enum.txt // RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT < %t.enum.txt @@ -116,6 +116,17 @@ enum FooEnum: CaseIterable { // FOO_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}} // FOO_ENUM_DOT-NEXT: End completions +// FOO_ENUM_DOT_CONTEXT: Begin completions +// FOO_ENUM_DOT_CONTEXT-NEXT: Keyword[self]/CurrNominal: self[#FooEnum.Type#]; name=self +// FOO_ENUM_DOT_CONTEXT-NEXT: Keyword/CurrNominal: Type[#FooEnum.Type#]; name=Type +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: Foo1[#FooEnum#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: Foo2[#FooEnum#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: alias1[#FooEnum#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[TypeAlias]/CurrNominal: AllCases[#[FooEnum]#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}} +// FOO_ENUM_DOT_CONTEXT-NEXT: End completions + // FOO_ENUM_DOT_INVALID: Begin completions // FOO_ENUM_DOT_INVALID-NEXT: Keyword[self]/CurrNominal: self[#FooEnum.Type#]; name=self // FOO_ENUM_DOT_INVALID-NEXT: Keyword/CurrNominal: Type[#FooEnum.Type#]; name=Type diff --git a/test/IDE/complete_rdar63965160.swift b/test/IDE/complete_rdar63965160.swift new file mode 100644 index 0000000000000..41dd721ffb8d6 --- /dev/null +++ b/test/IDE/complete_rdar63965160.swift @@ -0,0 +1,38 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRINGLITERAL | %FileCheck %s +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=NORMAL | %FileCheck %s + +protocol View {} + +@_functionBuilder +struct Builder { + static func buildBlock(_ c0: C0) -> C0 {} + static func buildBlock(_ c0: C0, _ c1: C1) -> C1 {} + static func buildBlock(_ c0: C0, _ c1: C1, _ c2: C2) -> C1 {} +} + +struct ForEach: View where Data: RandomAccessCollection { + init(_ dat: Data, @Builder content: (Data.Element) -> Content) {} +} + +struct Text: View { + init(_ text: String) {} +} + +struct Value { + var name: String +} + +func test(values: [Value]) { + _ = ForEach(values) { value in + Text("foobar") + Text("value \(value.#^STRINGLITERAL^#)") + } + _ = ForEach(values) { value in + Text("foobar") + Text(value.#^NORMAL^#) + } +} +// CHECK: Begin completions, 2 items +// CHECK-DAG: Keyword[self]/CurrNominal: self[#Value#]; +// CHECK-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[{{Convertible|Identical}}]: name[#String#]; +// CHECK: End completions diff --git a/test/IDE/complete_sself.swift b/test/IDE/complete_sself.swift new file mode 100644 index 0000000000000..93b7f6da4bea7 --- /dev/null +++ b/test/IDE/complete_sself.swift @@ -0,0 +1,223 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_EXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_TYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_VARBODY_EXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=NOSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_TYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_PARAMTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_TYPEALIAS_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF + +// NOSELF: Begin completions +// NOSELF-NOT: name=Self +// NOSELF: End completions + +// GENERICPARAM: Begin completions +// GENERICPARAM: Decl[GenericTypeParam]/Local: Self[#Self#]; + +// STATICSELF: Begin completions +// STATICSELF: Keyword[Self]/CurrNominal: Self[#S#]; + +// DYNAMICSELF: Begin completions +// DYNAMICSELF: Keyword[Self]/CurrNominal: Self[#Self#]; + +func freeFunc() { + #^GLOBAL_BODY_EXPR^# + let _: #^GLOBAL_BODY_TYPE^# +} +var freeVar: String { + "\(#^GLOBAL_VARBODY_EXPR^#)" +} +func freeFunc(x: #^GLOBAL_FUNC_PARAMTYPE^#) {} +func freeFunc(x: Int = #^GLOBAL_FUNC_DEFAULTEXPR^#) {} +func freeFunc(x: Int) -> #^GLOBAL_FUNC_RESULTTYPE^# {} + +var x: ^#GLOBAL_VAR_TYPE^# + +func sync() {} + +protocol P { + func protoMeth(x: #^PROTOCOL_FUNC_PARAMTYPE^#) + func protoMeth(x: Int) -> #^PROTOCOL_FUNC_RESULTTYPE^# + + subscript(x: #^PROTOCOL_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^PROTOCOL_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^PROTOCOL_VAR_TYPE^# +} +extension P { + func method(x: #^PROTOEXT_FUNC_PARAMTYPE^#) { } + func method(x: Int = #^PROTOEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^PROTOEXT_FUNC_RESULTTYPE^# { } + + subscript(x: #^PROTOEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { } + subscript(y: Int) -> #^PROTOEXT_SUBSCRIPT_RESULTTYPE^# { } + + var x: #^PROTOEXT_VAR_TYPE^# { } + + func bodyTest() { + #^PROTOEXT_BODY_EXPR^# + let _: #^PROTOEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^PROTOEXT_VARBODY_EXPR^#)" + } +} + +struct S { + func method(x: #^STRUCT_FUNC_PARAMTYPE^#) + func method(x: Int = #^STRUCT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^STRUCT_FUNC_RESULTTYPE^# + + subscript(x: #^STRUCT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^STRUCT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^STRUCT_VAR_TYPE^# + + func bodyTest() { + #^STRUCT_BODY_EXPR^# + let _: #^STRUCT_BODY_TYPE^# + } + var varTest: String { + "\(#^STRUCT_VARBODY_EXPR^#)" + } +} +extension S { + func method(x: #^STRUCTEXT_FUNC_PARAMTYPE^#) + func method(x: Int = #^STRUCTEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^STRUCTEXT_FUNC_RESULTTYPE^# + + subscript(x: #^STRUCTEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^STRUCTEXT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^STRUCTEXT_VAR_TYPE^# + + func bodyTest() { + #^STRUCTEXT_BODY_EXPR^# + let _: #^STRUCTEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^STRUCTEXT_VARBODY_EXPR^#)" + } +} + +class C { + func method(x: #^CLASS_FUNC_PARAMTYPE^#) + func method(x: Int = #^CLASS_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^CLASS_FUNC_RESULTTYPE^# + + subscript(x: #^CLASS_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^CLASS_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^CLASS_VAR_TYPE^# + + func bodyTest() { + #^CLASS_BODY_EXPR^# + let _: #^CLASS_BODY_TYPE^# + } + var varTest: String { + "\(#^CLASS_VARBODY_EXPR^#)" + } +} +class CC {} +extension CC { + func method(x: #^CLASSEXT_FUNC_PARAMTYPE^#) + func method(x: Int = #^CLASSEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^CLASSEXT_FUNC_RESULTTYPE^# + + subscript(x: #^CLASSEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^CLASSEXT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^CLASSEXT_VAR_TYPE^# + + func bodyTest() { + #^CLASSEXT_BODY_EXPR^# + let _: #^CLASSEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^CLASSEXT_VARBODY_EXPR^#)" + } +} + +class CCC { + func bodyTest() { + func inner() { + #^CLASS_NESTEDBODY_EXPR^# + let _: #^CLASS_NESTEDBODY_TYPE^# + } + + func inner(x: #^CLASS_NESTEDFUNC_PARAMTYPE^#) {} + func inner(y: Int = #^CLASS_NESTEDFUNC_DEFAULTEXPR^#) {} + func inner() -> #^CLASS_NESTEDFUNC_RESULTTYPE^# {} + + typealias A = #^CLASS_TYPEALIAS_TYPE^# + } + class Inner { + func method() { + #^CLASS_NESTEDTYPE_EXPR^# + let _: #^CLASS_NESTEDTYPE_TYPE^# + } + } +} diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift index c2fca5a6aa1fe..b76a9bfad2f14 100644 --- a/test/IDE/complete_stmt_controlling_expr.swift +++ b/test/IDE/complete_stmt_controlling_expr.swift @@ -120,6 +120,9 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_7 | %FileCheck %s -check-prefix=FOOSTRUCT_LOCALVAL // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_8 | %FileCheck %s -check-prefix=FOOSTRUCT_LOCALVAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_CASE_PATTERN_1| %FileCheck %s -check-prefix=OPTIONAL_FOOSTRUCT +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_CASE_PATTERN_2| %FileCheck %s -check-prefix=OPTIONAL_FOOSTRUCT + struct FooStruct { var instanceVar : Int init(_: Int = 0) { } @@ -612,7 +615,12 @@ func testGuardLetBinding7(x: FooStruct?) { func testGuardLetBinding8(_ x: FooStruct?) { guard let boundVal = x, let other = testGuardLetBinding8(#^GUARD_LET_BIND_8^#) else {} } - +func testGuardCase(x:FooStruct?) { + guard case .#^GUARD_CASE_PATTERN_1^# = x {} +} +func testGuardCase(x:FooStruct?) { + guard case .#^GUARD_CASE_PATTERN_2^#some() = x {} +} // FOOSTRUCT_DOT: Begin completions // FOOSTRUCT_DOT-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#]; @@ -635,3 +643,12 @@ func testGuardLetBinding8(_ x: FooStruct?) { // FOOSTRUCT_LOCALVAL: Begin completions // FOOSTRUCT_LOCALVAL-DAG: Decl[LocalVar]/Local{{(/TypeRelation\[Convertible\])?}}: boundVal[#FooStruct#]; // FOOSTRUCT_LOCALVAL: End completions + +// OPTIONAL_FOOSTRUCT: Begin completions, 5 items +// OPTIONAL_FOOSTRUCT-DAG: Keyword[nil]/None/Erase[1]: nil[#FooStruct?#]; name=nil +// OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none +// OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#FooStruct#})[#Optional#]; name=some(FooStruct) +// FIXME: 'FooStruct' members should not be shown. +// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#FooStruct#]; name=init() +// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#Int#})[#FooStruct#]; name=init(Int) +// OPTIONAL_FOOSTRUCT: End completions diff --git a/test/IDE/complete_subscript.swift b/test/IDE/complete_subscript.swift index afd47cb1fb798..dfb74fafc1c0b 100644 --- a/test/IDE/complete_subscript.swift +++ b/test/IDE/complete_subscript.swift @@ -16,6 +16,7 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SUPER_IN_STATICMETHOD | %FileCheck %s -check-prefix=SUPER_IN_STATICMETHOD // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LABELED_SUBSCRIPT | %FileCheck %s -check-prefix=LABELED_SUBSCRIPT +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TUPLE | %FileCheck %s -check-prefix=TUPLE struct MyStruct { static subscript(x: Int, static defValue: T) -> MyStruct { @@ -62,6 +63,7 @@ func test1() { let _ = MyStruct()[#^INSTANCE_INT_BRACKET^# // INSTANCE_INT_BRACKET: Begin completions // INSTANCE_INT_BRACKET-DAG: Decl[Subscript]/CurrNominal: ['[']{#(x): Int#}, {#instance: Int#}[']'][#Int#]; +// INSTANCE_INT_BRACKET-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath, Value>#}[']'][#Value#]; // INSTANCE_INT_BRACKET: End completions } func test2(value: MyStruct) { @@ -87,6 +89,7 @@ func test2(value: MyStruct) { let _ = value[#^INSTANCE_ARCHETYPE_BRACKET^# // INSTANCE_ARCHETYPE_BRACKET: Begin completions // INSTANCE_ARCHETYPE_BRACKET-DAG: Decl[Subscript]/CurrNominal: ['[']{#(x): Int#}, {#instance: U#}[']'][#Int#]; +// INSTANCE_ARCHETYPE_BRACKET-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath, Value>#}[']'][#Value#]; // INSTANCE_ARCHETYPE_BRACKET: End completions let _ = MyStruct[42, #^METATYPE_LABEL^# @@ -110,14 +113,16 @@ class Derived: Base { func testInstance() { let _ = self[#^SELF_IN_INSTANCEMETHOD^#] -// SELF_IN_INSTANCEMETHOD: Begin completions, 2 items +// SELF_IN_INSTANCEMETHOD: Begin completions, 3 items // SELF_IN_INSTANCEMETHOD-DAG: Decl[Subscript]/CurrNominal: ['[']{#derivedInstance: Int#}[']'][#Int#]; // SELF_IN_INSTANCEMETHOD-DAG: Decl[Subscript]/Super: ['[']{#instance: Int#}[']'][#Int#]; +// SELF_IN_INSTANCEMETHOD-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath#}[']'][#Value#]; // SELF_IN_INSTANCEMETHOD: End completions let _ = super[#^SUPER_IN_INSTANCEMETHOD^#] -// SUPER_IN_INSTANCEMETHOD: Begin completions, 1 items -// SUPER_IN_INSTANCEMETHOD-DAG: Decl[Subscript]/CurrNominal: ['[']{#instance: Int#}[']'][#Int#]; +// SUPER_IN_INSTANCEMETHOD: Begin completions, 2 items +// SUPER_IN_INSTANCEMETHOD-DAG: Decl[Subscript]/CurrNominal: ['[']{#instance: Int#}[']'][#Int#]; +// SUPER_IN_INSTANCEMETHOD-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath#}[']'][#Value#]; // SUPER_IN_INSTANCEMETHOD: End completions } @@ -130,7 +135,7 @@ class Derived: Base { let _ = super[#^SUPER_IN_STATICMETHOD^#] // SUPER_IN_STATICMETHOD: Begin completions, 1 items -// SUPER_IN_STATICMETHOD-DAG: Decl[Subscript]/CurrNominal: ['[']{#static: Int#}[']'][#Int#]; +// SUPER_IN_STATICMETHOD-DAG: Decl[Subscript]/CurrNominal: ['[']{#static: Int#}[']'][#Int#]; // SUPER_IN_STATICMETHOD: End completions } } @@ -140,7 +145,15 @@ struct MyStruct1 { } func testSubscriptCallSig(val: MyStruct1) { val[#^LABELED_SUBSCRIPT^# -// LABELED_SUBSCRIPT: Begin completions, 1 items -// LABELED_SUBSCRIPT: Decl[Subscript]/CurrNominal: ['[']{#idx1: Int#}, {#idx2: Comparable#}[']'][#Int!#]; +// LABELED_SUBSCRIPT: Begin completions, 2 items +// LABELED_SUBSCRIPT-DAG: Decl[Subscript]/CurrNominal: ['[']{#idx1: Int#}, {#idx2: Comparable#}[']'][#Int!#]; +// LABELED_SUBSCRIPT-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath, Value>#}[']'][#Value#]; // LABELED_SUBSCRIPT: End completions } + +func testSubcscriptTuple(val: (x: Int, String)) { + val[#^TUPLE^#] +// TUPLE: Begin completions, 1 items +// TUPLE-DAG: Pattern/CurrModule: ['[']{#keyPath: KeyPath<(x: Int, String), Value>#}[']'][#Value#]; +// TUPLE: End completions +} diff --git a/test/IDE/conforming-methods-afterclosure.swift b/test/IDE/conforming-methods-afterclosure.swift new file mode 100644 index 0000000000000..faa168b12761d --- /dev/null +++ b/test/IDE/conforming-methods-afterclosure.swift @@ -0,0 +1,27 @@ +// RUN: %target-swift-ide-test -conforming-methods -source-filename %s -code-completion-token=AFTER_TRAILINGCLOSURE -module-name MyModule -conforming-methods-expected-types 's:8MyModule7TargetPP' | %FileCheck %s -check-prefix=AFTER_TRAILINGCLOSURE + +public protocol TargetP {} +struct ConcreteP: TargetP {} + +public struct MyStruct { + init(arg1: Int = 0, fn: () -> Int) {} + + public func returnSomeP -> some TargetP { ConcreteP() } + public func returnConcreteP -> ConcreteP { ConcreteP() } + public func reutrnInt -> Int { 1 } +} + +func test() { + MyStruct { + 1 + } #^AFTER_TRAILINGCLOSURE^# +} + +//AFTER_TRAILINGCLOSURE: -----BEGIN CONFORMING METHOD LIST----- +//AFTER_TRAILINGCLOSURE-NEXT: - TypeName: MyStruct +//AFTER_TRAILINGCLOSURE-NEXT: - Members: +//AFTER_TRAILINGCLOSURE-NEXT: - Name: returnSomeP() +//AFTER_TRAILINGCLOSURE-NEXT: TypeName: some TargetP +//AFTER_TRAILINGCLOSURE-NEXT: - Name: returnConcreteP() +//AFTER_TRAILINGCLOSURE-NEXT: TypeName: ConcreteP +//AFTER_TRAILINGCLOSURE-NEXT: -----END CONFORMING METHOD LIST----- diff --git a/test/IRGen/c_globals.swift b/test/IRGen/c_globals.swift index 0f55f9bb4d173..5b39f5ddf1580 100644 --- a/test/IRGen/c_globals.swift +++ b/test/IRGen/c_globals.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-cpu-%target-abi import c_layout @@ -31,5 +31,37 @@ public func testCaptureGlobal() { }) // CHECK: {{^}$}} } -// CHECK-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-i386-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-i386-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-i386-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-i386-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" + +// CHECK-x86_64-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-x86_64-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-x86_64-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-x86_64-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" + +// CHECK-armv7-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" + +// CHECK-armv7s-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7s-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7s-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7s-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" + +// CHECK-armv7k-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7k-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7k-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7k-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" + +// CHECK-arm64-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" + +// CHECK-arm64e-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64e-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64e-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64e-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" diff --git a/test/IRGen/ptrauth-functions.sil b/test/IRGen/ptrauth-functions.sil index 9606671228345..80f9e43227584 100644 --- a/test/IRGen/ptrauth-functions.sil +++ b/test/IRGen/ptrauth-functions.sil @@ -87,4 +87,4 @@ bb0(%0 : $T): sil_vtable F { } -// CHECK: #[[ATTRS]] = {{{.*}} "ptrauth-calls" "ptrauth-returns" +// CHECK: #[[ATTRS]] = {{{.*}} "ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns" diff --git a/test/InterfaceHash/added_method-type-fingerprints.swift b/test/InterfaceHash/added_method-type-fingerprints.swift index 7b51e1f67b758..16f0163c59eaf 100644 --- a/test/InterfaceHash/added_method-type-fingerprints.swift +++ b/test/InterfaceHash/added_method-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift index cf3a104cc71b1..0511b470d785d 100644 --- a/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift @@ -5,10 +5,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_class_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_property-type-fingerprints.swift index f4e01619c1b76..336a443b960a6 100644 --- a/test/InterfaceHash/added_private_class_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_class_property-type-fingerprints.swift @@ -5,10 +5,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift index 9ad0b28d56449..e713399da7804 100644 --- a/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift index c8220f6f9a54b..13072b3631653 100644 --- a/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_method-type-fingerprints.swift b/test/InterfaceHash/added_private_method-type-fingerprints.swift index c0c60206d9c92..6b22e390c1919 100644 --- a/test/InterfaceHash/added_private_method-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_method-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift b/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift index 42fee00e31bf0..abb1a4d77d519 100644 --- a/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift index c0ccd54a11771..1b4cdcc8e8574 100644 --- a/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift index c27cee3752b83..480542c32598d 100644 --- a/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift index 47e371aff0901..31cc7e8453001 100644 --- a/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift index bd92b5dfbe37f..9da9ac55bd15c 100644 --- a/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift +++ b/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/edited_method_body-type-fingerprints.swift b/test/InterfaceHash/edited_method_body-type-fingerprints.swift index 10ae3e000c09f..7dedc064b8833 100644 --- a/test/InterfaceHash/edited_method_body-type-fingerprints.swift +++ b/test/InterfaceHash/edited_method_body-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: cmp %t/{a,b}-processed.swiftdeps diff --git a/test/InterfaceHash/edited_property_getter-type-fingerprints.swift b/test/InterfaceHash/edited_property_getter-type-fingerprints.swift index 0a0b5fdaaff54..7bd06798a19de 100644 --- a/test/InterfaceHash/edited_property_getter-type-fingerprints.swift +++ b/test/InterfaceHash/edited_property_getter-type-fingerprints.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -enable-fine-grained-dependencies -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps // RUN: cmp %t/{a,b}-processed.swiftdeps diff --git a/test/SILGen/Inputs/objc_dynamic_replacement_ext.swift b/test/SILGen/Inputs/objc_dynamic_replacement_ext.swift new file mode 100644 index 0000000000000..7823f67597b19 --- /dev/null +++ b/test/SILGen/Inputs/objc_dynamic_replacement_ext.swift @@ -0,0 +1,16 @@ +import Foundation + +public class Generic: NSObject { + @objc public dynamic func foo() {} + + @objc public dynamic var x: Int { + get { + return 0; + } + set { + print("noop") + } + } + + @objc public dynamic var y: Int = 0 +} diff --git a/test/SILGen/objc_dynamic_replacement_ext.swift b/test/SILGen/objc_dynamic_replacement_ext.swift new file mode 100644 index 0000000000000..736ed735c892f --- /dev/null +++ b/test/SILGen/objc_dynamic_replacement_ext.swift @@ -0,0 +1,81 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-emit-silgen -module-name SomeModule %S/Inputs/objc_dynamic_replacement_ext.swift -swift-version 5 -enable-implicit-dynamic | %FileCheck %s --check-prefix=IMPORT +// RUN: %target-swift-emit-silgen -module-name SomeModule %S/Inputs/objc_dynamic_replacement_ext.swift -swift-version 5 | %FileCheck %s --check-prefix=NO +// RUN: %target-swift-frontend -module-name SomeModule -emit-module -emit-module-path=%t/SomeModule.swiftmodule %S/Inputs/objc_dynamic_replacement_ext.swift -swift-version 5 -validate-tbd-against-ir=all +// RUN: %target-swift-frontend -module-name SomeModule -emit-module -emit-module-path=%t/SomeModule.swiftmodule %S/Inputs/objc_dynamic_replacement_ext.swift -swift-version 5 -enable-implicit-dynamic -validate-tbd-against-ir=all +// RUN: %target-swift-emit-silgen -I %t %s -swift-version 5 | %FileCheck %s +// RUN: %target-swift-emit-ir -I %t %s -swift-version 5 -validate-tbd-against-ir=all + +// REQUIRES: objc_interop + +import Foundation +import SomeModule + +// Make sure we support replacing @objc dynamic methods in generic classes. +// Normally we would disallow such methods in extensions because we don't +// support emitting objc categories for native generic classes. We special case +// @_dynamicReplacements for such methods and use the native dynamic replacement +// mechanism instead. + +// In imported file: +// public class Generic: NSObject { +// @objc public dynamic func foo() {} +// @objc public dynamic var x: Int { +// get { +// return 0; +// } +// set { +// print("noop") +// } +// } +// @objc public dynamic var y: Int = 0 +// } + +// IMPORT-DAG: sil [dynamically_replacable] [ossa] @$s10SomeModule7GenericC3fooyyF : $@convention(method) (@guaranteed Generic) -> () +// IMPORT-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC3fooyyFTo : $@convention(objc_method) (Generic) -> () + +// IMPORT-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1xSivgTo : $@convention(objc_method) (Generic) -> Int +// IMPORT-DAG: sil [dynamically_replacable] [ossa] @$s10SomeModule7GenericC1xSivg : $@convention(method) (@guaranteed Generic) -> Int +// IMPORT-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1xSivsTo : $@convention(objc_method) (Int, Generic) -> () +// IMPORT-DAG: sil [dynamically_replacable] [ossa] @$s10SomeModule7GenericC1xSivs : $@convention(method) (Int, @guaranteed Generic) -> () + +// NO-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1xSivgTo : $@convention(objc_method) (Generic) -> Int +// NO-DAG: sil [ossa] @$s10SomeModule7GenericC1xSivg : $@convention(method) (@guaranteed Generic) -> Int +// NO-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1xSivsTo : $@convention(objc_method) (Int, Generic) -> () +// NO-DAG: sil [ossa] @$s10SomeModule7GenericC1xSivs : $@convention(method) (Int, @guaranteed Generic) -> () + +// IMPORT-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1ySivgTo : $@convention(objc_method) (Generic) -> Int +// IMPORT-DAG: sil [dynamically_replacable] [ossa] @$s10SomeModule7GenericC1ySivg : $@convention(method) (@guaranteed Generic) -> Int +// IMPORT-DAG: sil [thunk] [ossa] @$s10SomeModule7GenericC1ySivsTo : $@convention(objc_method) (Int, Generic) -> () +// IMPORT-DAG: sil [dynamically_replacable] [ossa] @$s10SomeModule7GenericC1ySivs : $@convention(method) (Int, @guaranteed Generic) -> () + +extension Generic { + @_dynamicReplacement(for: foo()) public func __replacement__foo() {} +// CHECK-DAG: sil [dynamic_replacement_for "$s10SomeModule7GenericC3fooyyF"] [ossa] @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F5__fooyyF : $@convention(method) (@guaranteed Generic) -> () +// CHECK-NOT: sil {{.*}} @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F5__fooyyFTo : $@convention(objc_method) (Generic) -> () + + @_dynamicReplacement(for: x) public var __replacement_x : Int { + get { + return 0; + } + set { + print("noop") + } + } +// CHECK-NOT: sil {{.*}} @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_xSivgTo : $@convention(objc_method) (Generic) -> Int +// CHECK-DAG: sil [dynamic_replacement_for "$s10SomeModule7GenericC1xSivg"] [ossa] @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_xSivg : $@convention(method) (@guaranteed Generic) -> Int +// CHECK-NOT: sil {{.*}} @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_xSivsTo : $@convention(objc_method) (Int, Generic) -> () +// CHECK-DAG: sil [dynamic_replacement_for "$s10SomeModule7GenericC1xSivs"] [ossa] @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_xSivs : $@convention(method) (Int, @guaranteed Generic) -> () + + @_dynamicReplacement(for: y) public var __replacement_y : Int { + get { + return 7; + } + set { + } + } +// CHECK-NOT: sil {{.*}} @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_ySivgTo : $@convention(objc_method) (Generic) -> Int +// CHECK-DAG: sil [dynamic_replacement_for "$s10SomeModule7GenericC1ySivg"] [ossa] @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_ySivg : $@convention(method) (@guaranteed Generic) -> Int +// CHECK-NOT: sil {{.*}} @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_ySivsTo : $@convention(objc_method) (Int, Generic) -> () +// CHECK-DAG: sil [dynamic_replacement_for "$s10SomeModule7GenericC1ySivs"] [ossa] @$s10SomeModule7GenericC28objc_dynamic_replacement_extE02__F2_ySivs : $@convention(method) (Int, @guaranteed Generic) -> () +} diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil index 93f565b65ef20..30d2ed520f47f 100644 --- a/test/SILOptimizer/semantic-arc-opts.sil +++ b/test/SILOptimizer/semantic-arc-opts.sil @@ -59,6 +59,7 @@ class ClassLet { @_hasStorage let aLet: Klass @_hasStorage var aVar: Klass @_hasStorage let aLetTuple: (Klass, Klass) + @_hasStorage let anOptionalLet: FakeOptional @_hasStorage let anotherLet: ClassLet } @@ -2204,3 +2205,31 @@ bb6: %9999 = tuple() return %9999 : $() } + +// Make sure that we do not promote the load [copy] to a load_borrow since it +// has a use outside of the access scope. +// +// CHECK-LABEL: sil [ossa] @deadEndBlockDoNotPromote : $@convention(method) (@guaranteed ClassLet) -> () { +// CHECK: load_borrow +// CHECK: load [copy] +// CHECK: } // end sil function 'deadEndBlockDoNotPromote' +sil [ossa] @deadEndBlockDoNotPromote : $@convention(method) (@guaranteed ClassLet) -> () { +bb0(%0 : @guaranteed $ClassLet): + %4 = ref_element_addr %0 : $ClassLet, #ClassLet.anotherLet + %5 = load [copy] %4 : $*ClassLet + %6 = begin_borrow %5 : $ClassLet + %7 = ref_element_addr %6 : $ClassLet, #ClassLet.anOptionalLet + %8 = begin_access [read] [dynamic] %7 : $*FakeOptional + %9 = load [copy] %8 : $*FakeOptional + end_access %8 : $*FakeOptional + end_borrow %6 : $ClassLet + destroy_value %5 : $ClassLet + switch_enum %9 : $FakeOptional, case #FakeOptional.none!enumelt: bb1, case #FakeOptional.some!enumelt: bb2 + +bb1: + %107 = tuple () + return %107 : $() + +bb2(%39 : @owned $Klass): + unreachable +} diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 51c06e93ecfcb..313d35685f51a 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -1972,4 +1972,4 @@ public struct NonVisibleImplicitInit { public var wrappedValue: Bool { return false } -} \ No newline at end of file +} diff --git a/test/decl/var/property_wrappers_opaque.swift b/test/decl/var/property_wrappers_opaque.swift new file mode 100644 index 0000000000000..966b259f318c1 --- /dev/null +++ b/test/decl/var/property_wrappers_opaque.swift @@ -0,0 +1,27 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 -disable-availability-checking + +protocol P { } + +@propertyWrapper +struct WrapperWithDefaultInit { + private var stored: T? + + var wrappedValue: T { + get { stored! } + set { stored = newValue } + } + + init() { + self.stored = nil + } +} + +// FB7699647 - crash with opaque result type and property wrappers. +struct FB7699647 { + @WrapperWithDefaultInit var property: some P // expected-error{{property declares an opaque return type, but cannot infer the underlying type from its initializer expression}} + @WrapperWithDefaultInit() var otherProperty: some P // expected-error{{property declares an opaque return type, but cannot infer the underlying type from its initializer expression}} +} + +struct FB7699647b { + @WrapperWithDefaultInit var property: some P // expected-error{{property declares an opaque return type, but cannot infer the underlying type from its initializer expression}} +} diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 9435256f5ab4f..d74159e484fc0 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -1579,13 +1579,16 @@ mixin-preset= mixin_linux_install_components_with_clang libdispatch +libicu foundation xctest +install-libicu install-foundation install-libdispatch install-xctest +skip-test-libicu skip-test-foundation skip-test-libdispatch skip-test-xctest diff --git a/validation-test/compiler_crashers_2_fixed/sr12990.swift b/validation-test/compiler_crashers_2_fixed/sr12990.swift new file mode 100644 index 0000000000000..d3d68daed1bec --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr12990.swift @@ -0,0 +1,11 @@ +// RUN: %target-swift-frontend -typecheck %s -verify + +class ContainerTransition { + var viewControllers: [Int: String]? + func completeTransition() { + viewControllers?[Int//.max + // expected-error@-1 {{no exact matches in call to subscript}} + // expected-note@-2 {{found candidate with type '((Int).Type) -> Dictionary.SubSequence' (aka '(Int.Type) -> Slice>')}} + // expected-note@-3 {{to match this opening '['}} + } // expected-error {{expected ']' in expression list}} +}