mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Guard feature behind experimental flag.
This commit is contained in:
@@ -294,6 +294,7 @@ EXPERIMENTAL_FEATURE(MacrosOnImports, true)
|
||||
EXPERIMENTAL_FEATURE(TupleConformances, false)
|
||||
EXPERIMENTAL_FEATURE(FullTypedThrows, false)
|
||||
EXPERIMENTAL_FEATURE(SameElementRequirements, false)
|
||||
EXPERIMENTAL_FEATURE(KeyPathWithMethodMembers, false)
|
||||
|
||||
// Whether to enable @_used and @_section attributes
|
||||
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
|
||||
|
||||
@@ -2009,6 +2009,11 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix {
|
||||
// a key path component.
|
||||
MutatingGetter,
|
||||
// Allow a reference to a mutating method.
|
||||
Method,
|
||||
// Allow a reference to a initializer instance as a key path
|
||||
// component.
|
||||
Initializer,
|
||||
// Allow a reference to an enum case as a key path component.
|
||||
MutatingMethod,
|
||||
// Allow a reference to an async or throwing method.
|
||||
AsyncOrThrowsMethod,
|
||||
@@ -2035,6 +2040,10 @@ public:
|
||||
case RefKind::MutatingGetter:
|
||||
return "allow reference to a member with mutating getter as a key "
|
||||
"path component";
|
||||
case RefKind::Method:
|
||||
return "allow reference to a method as a key path component";
|
||||
case RefKind::Initializer:
|
||||
return "allow reference to an init method as a key path component";
|
||||
case RefKind::EnumCase:
|
||||
return "allow reference to an enum case as a key path component";
|
||||
case RefKind::MutatingMethod:
|
||||
|
||||
@@ -125,6 +125,7 @@ UNINTERESTING_FEATURE(StructLetDestructuring)
|
||||
UNINTERESTING_FEATURE(MacrosOnImports)
|
||||
UNINTERESTING_FEATURE(AsyncCallerExecution)
|
||||
UNINTERESTING_FEATURE(ExtensibleEnums)
|
||||
UNINTERESTING_FEATURE(KeyPathWithMethodMembers)
|
||||
|
||||
static bool usesFeatureNonescapableTypes(Decl *decl) {
|
||||
auto containsNonEscapable =
|
||||
|
||||
@@ -6418,6 +6418,12 @@ bool InvalidMemberWithMutatingGetterInKeyPath::diagnoseAsError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnsupportedMethodRefInKeyPath::diagnoseAsError() {
|
||||
emitDiagnostic(diag::expr_keypath_not_property, getMember(),
|
||||
isForKeyPathDynamicMemberLookup());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InvalidMutatingMethodRefInKeyPath::diagnoseAsError() {
|
||||
emitDiagnostic(diag::expr_keypath_mutating_method, getMember(),
|
||||
isForKeyPathDynamicMemberLookup());
|
||||
|
||||
@@ -1807,6 +1807,33 @@ public:
|
||||
bool diagnoseAsError() override;
|
||||
};
|
||||
|
||||
/// Diagnose an attempt to reference a method or initializer as a key path
|
||||
/// component.
|
||||
///
|
||||
/// Only diagnosed if `-KeyPathWithMethodMember` feature flag is not set.
|
||||
///
|
||||
/// ```swift
|
||||
/// struct S {
|
||||
/// init() { }
|
||||
/// func foo() -> Int { return 42 }
|
||||
/// static func bar() -> Int { return 0 }
|
||||
/// }
|
||||
///
|
||||
/// _ = \S.foo
|
||||
/// _ = \S.Type.bar
|
||||
/// _ = \S.init
|
||||
/// ```
|
||||
class UnsupportedMethodRefInKeyPath final : public InvalidMemberRefInKeyPath {
|
||||
public:
|
||||
UnsupportedMethodRefInKeyPath(const Solution &solution, ValueDecl *method,
|
||||
ConstraintLocator *locator)
|
||||
: InvalidMemberRefInKeyPath(solution, method, locator) {
|
||||
assert(isa<FuncDecl>(method) || isa<ConstructorDecl>(method));
|
||||
}
|
||||
|
||||
bool diagnoseAsError() override;
|
||||
};
|
||||
|
||||
/// Diagnose an attempt to reference a mutating method as a key path component
|
||||
/// e.g.
|
||||
///
|
||||
|
||||
@@ -1251,6 +1251,11 @@ bool AllowInvalidRefInKeyPath::diagnose(const Solution &solution,
|
||||
getLocator());
|
||||
return failure.diagnose(asNote);
|
||||
}
|
||||
case RefKind::Method:
|
||||
case RefKind::Initializer: {
|
||||
UnsupportedMethodRefInKeyPath failure(solution, Member, getLocator());
|
||||
return failure.diagnose(asNote);
|
||||
}
|
||||
case RefKind::MutatingMethod: {
|
||||
InvalidMutatingMethodRefInKeyPath failure(solution, Member, getLocator());
|
||||
return failure.diagnose(asNote);
|
||||
@@ -1323,22 +1328,41 @@ AllowInvalidRefInKeyPath::forRef(ConstraintSystem &cs, Type baseType,
|
||||
cs, baseType, RefKind::MutatingGetter, member, locator);
|
||||
}
|
||||
|
||||
// Referencing mutating, throws or async method members is not currently
|
||||
// allowed.
|
||||
if (auto method = dyn_cast<FuncDecl>(member)) {
|
||||
if (method->isAsyncContext())
|
||||
return AllowInvalidRefInKeyPath::create(
|
||||
cs, baseType, RefKind::AsyncOrThrowsMethod, member, locator);
|
||||
if (auto methodType = method->getInterfaceType()->getAs<AnyFunctionType>()) {
|
||||
if (methodType->getResult()->getAs<AnyFunctionType>()->isThrowing())
|
||||
if (cs.getASTContext().LangOpts.hasFeature(
|
||||
Feature::KeyPathWithMethodMembers)) {
|
||||
// Referencing mutating, throws or async method members is not currently
|
||||
// allowed.
|
||||
if (auto method = dyn_cast<FuncDecl>(member)) {
|
||||
if (method->isAsyncContext())
|
||||
return AllowInvalidRefInKeyPath::create(
|
||||
cs, baseType, RefKind::AsyncOrThrowsMethod, member, locator);
|
||||
if (auto methodType =
|
||||
method->getInterfaceType()->getAs<AnyFunctionType>()) {
|
||||
if (methodType->getResult()->getAs<AnyFunctionType>()->isThrowing())
|
||||
return AllowInvalidRefInKeyPath::create(
|
||||
cs, baseType, RefKind::AsyncOrThrowsMethod, member, locator);
|
||||
}
|
||||
if (method->isMutating())
|
||||
return AllowInvalidRefInKeyPath::create(
|
||||
cs, baseType, RefKind::MutatingMethod, member, locator);
|
||||
return nullptr;
|
||||
}
|
||||
if (method->isMutating())
|
||||
return AllowInvalidRefInKeyPath::create(
|
||||
cs, baseType, RefKind::MutatingMethod, member, locator);
|
||||
|
||||
if (isa<ConstructorDecl>(member))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Referencing (instance or static) methods in key path is
|
||||
// not currently allowed.
|
||||
if (isa<FuncDecl>(member))
|
||||
return AllowInvalidRefInKeyPath::create(cs, baseType, RefKind::Method,
|
||||
member, locator);
|
||||
|
||||
// Referencing initializers in key path is not currently allowed.
|
||||
if (isa<ConstructorDecl>(member))
|
||||
return AllowInvalidRefInKeyPath::create(cs, baseType, RefKind::Initializer,
|
||||
member, locator);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -10826,6 +10826,9 @@ static ConstraintFix *validateInitializerRef(ConstraintSystem &cs,
|
||||
// which means MetatypeType has to be added after finding a type variable.
|
||||
if (baseLocator->isLastElement<LocatorPathElt::MemberRefBase>())
|
||||
baseType = MetatypeType::get(baseType);
|
||||
} else if (auto *keyPathExpr = getAsExpr<KeyPathExpr>(anchor)) {
|
||||
// Key path can't refer to initializers e.g. `\Type.init`
|
||||
return AllowInvalidRefInKeyPath::forRef(cs, baseType, init, locator);
|
||||
}
|
||||
|
||||
if (!baseType)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-swift-frontend -typecheck -verify %S/Inputs/keypath.swift -primary-file %s
|
||||
// RUN: %target-swift-frontend -enable-experimental-feature KeyPathWithMethodMembers -typecheck -verify %S/Inputs/keypath.swift -primary-file %s
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
struct S {
|
||||
let i: Int
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature KeyPathWithMethodMembers -typecheck -verify %s
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-run-simple-swift | %FileCheck %s
|
||||
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-feature -Xfrontend KeyPathWithMethodMembers) | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// RUN: split-file %s %t/src
|
||||
|
||||
/// Build LibA
|
||||
// RUN: %host-build-swift %t/src/LibA.swift -swift-version 5 -emit-module -emit-library -enable-library-evolution -module-name LibA -o %t/%target-library-name(LibA) -emit-module-interface-path %t/LibA.swiftinterface
|
||||
// RUN: %host-build-swift %t/src/LibA.swift -swift-version 5 -enable-experimental-feature KeyPathWithMethodMembers -emit-module -emit-library -enable-library-evolution -module-name LibA -o %t/%target-library-name(LibA) -emit-module-interface-path %t/LibA.swiftinterface
|
||||
|
||||
// Build LibB
|
||||
// RUN: %target-build-swift %t/src/LibB.swift -I %t -L %t -l LibA -swift-version 5 -emit-module -emit-library -module-name LibB -o %t/%target-library-name(LibB)
|
||||
// RUN: %target-build-swift %t/src/LibB.swift -I %t -L %t -l LibA -swift-version 5 -enable-experimental-feature KeyPathWithMethodMembers -emit-module -emit-library -module-name LibB -o %t/%target-library-name(LibB)
|
||||
|
||||
// Build LibC
|
||||
// RUN: %target-build-swift %t/src/LibC.swift -I %t -L %t -l LibA -swift-version 5 -emit-module -emit-library -module-name LibC -o %t/%target-library-name(LibC)
|
||||
// RUN: %target-build-swift %t/src/LibC.swift -I %t -L %t -l LibA -swift-version 5 -enable-experimental-feature KeyPathWithMethodMembers -emit-module -emit-library -module-name LibC -o %t/%target-library-name(LibC)
|
||||
|
||||
// Build & run main.swift
|
||||
// RUN: %target-build-swift -I %t -L %t -l LibA -l LibB -l LibC %t/src/main.swift -o %t/a.out
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: OS=macosx
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -target %target-swift-5.1-abi-triple -parse-stdlib -module-name keypaths %s | %FileCheck %s
|
||||
// RUN: %target-swift-emit-silgen -enable-experimental-feature KeyPathWithMethodMembers -Xllvm -sil-print-types -target %target-swift-5.1-abi-triple -parse-stdlib -module-name keypaths %s | %FileCheck %s
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
import Swift
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
// RUN: %target-typecheck-verify-swift -enable-experimental-feature KeyPathWithMethodMembers
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
var global = 42
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-swift-frontend -typecheck -parse-as-library %s -verify
|
||||
// RUN: %target-swift-frontend -enable-experimental-feature KeyPathWithMethodMembers -typecheck -parse-as-library %s -verify
|
||||
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||
|
||||
struct Sub: Hashable {
|
||||
static func ==(_: Sub, _: Sub) -> Bool { return true }
|
||||
|
||||
Reference in New Issue
Block a user