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(TupleConformances, false)
|
||||||
EXPERIMENTAL_FEATURE(FullTypedThrows, false)
|
EXPERIMENTAL_FEATURE(FullTypedThrows, false)
|
||||||
EXPERIMENTAL_FEATURE(SameElementRequirements, false)
|
EXPERIMENTAL_FEATURE(SameElementRequirements, false)
|
||||||
|
EXPERIMENTAL_FEATURE(KeyPathWithMethodMembers, false)
|
||||||
|
|
||||||
// Whether to enable @_used and @_section attributes
|
// Whether to enable @_used and @_section attributes
|
||||||
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
|
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
|
||||||
|
|||||||
@@ -2009,6 +2009,11 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix {
|
|||||||
// a key path component.
|
// a key path component.
|
||||||
MutatingGetter,
|
MutatingGetter,
|
||||||
// Allow a reference to a mutating method.
|
// 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,
|
MutatingMethod,
|
||||||
// Allow a reference to an async or throwing method.
|
// Allow a reference to an async or throwing method.
|
||||||
AsyncOrThrowsMethod,
|
AsyncOrThrowsMethod,
|
||||||
@@ -2035,6 +2040,10 @@ public:
|
|||||||
case RefKind::MutatingGetter:
|
case RefKind::MutatingGetter:
|
||||||
return "allow reference to a member with mutating getter as a key "
|
return "allow reference to a member with mutating getter as a key "
|
||||||
"path component";
|
"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:
|
case RefKind::EnumCase:
|
||||||
return "allow reference to an enum case as a key path component";
|
return "allow reference to an enum case as a key path component";
|
||||||
case RefKind::MutatingMethod:
|
case RefKind::MutatingMethod:
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ UNINTERESTING_FEATURE(StructLetDestructuring)
|
|||||||
UNINTERESTING_FEATURE(MacrosOnImports)
|
UNINTERESTING_FEATURE(MacrosOnImports)
|
||||||
UNINTERESTING_FEATURE(AsyncCallerExecution)
|
UNINTERESTING_FEATURE(AsyncCallerExecution)
|
||||||
UNINTERESTING_FEATURE(ExtensibleEnums)
|
UNINTERESTING_FEATURE(ExtensibleEnums)
|
||||||
|
UNINTERESTING_FEATURE(KeyPathWithMethodMembers)
|
||||||
|
|
||||||
static bool usesFeatureNonescapableTypes(Decl *decl) {
|
static bool usesFeatureNonescapableTypes(Decl *decl) {
|
||||||
auto containsNonEscapable =
|
auto containsNonEscapable =
|
||||||
|
|||||||
@@ -6418,6 +6418,12 @@ bool InvalidMemberWithMutatingGetterInKeyPath::diagnoseAsError() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UnsupportedMethodRefInKeyPath::diagnoseAsError() {
|
||||||
|
emitDiagnostic(diag::expr_keypath_not_property, getMember(),
|
||||||
|
isForKeyPathDynamicMemberLookup());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool InvalidMutatingMethodRefInKeyPath::diagnoseAsError() {
|
bool InvalidMutatingMethodRefInKeyPath::diagnoseAsError() {
|
||||||
emitDiagnostic(diag::expr_keypath_mutating_method, getMember(),
|
emitDiagnostic(diag::expr_keypath_mutating_method, getMember(),
|
||||||
isForKeyPathDynamicMemberLookup());
|
isForKeyPathDynamicMemberLookup());
|
||||||
|
|||||||
@@ -1807,6 +1807,33 @@ public:
|
|||||||
bool diagnoseAsError() override;
|
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
|
/// Diagnose an attempt to reference a mutating method as a key path component
|
||||||
/// e.g.
|
/// e.g.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1251,6 +1251,11 @@ bool AllowInvalidRefInKeyPath::diagnose(const Solution &solution,
|
|||||||
getLocator());
|
getLocator());
|
||||||
return failure.diagnose(asNote);
|
return failure.diagnose(asNote);
|
||||||
}
|
}
|
||||||
|
case RefKind::Method:
|
||||||
|
case RefKind::Initializer: {
|
||||||
|
UnsupportedMethodRefInKeyPath failure(solution, Member, getLocator());
|
||||||
|
return failure.diagnose(asNote);
|
||||||
|
}
|
||||||
case RefKind::MutatingMethod: {
|
case RefKind::MutatingMethod: {
|
||||||
InvalidMutatingMethodRefInKeyPath failure(solution, Member, getLocator());
|
InvalidMutatingMethodRefInKeyPath failure(solution, Member, getLocator());
|
||||||
return failure.diagnose(asNote);
|
return failure.diagnose(asNote);
|
||||||
@@ -1323,22 +1328,41 @@ AllowInvalidRefInKeyPath::forRef(ConstraintSystem &cs, Type baseType,
|
|||||||
cs, baseType, RefKind::MutatingGetter, member, locator);
|
cs, baseType, RefKind::MutatingGetter, member, locator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Referencing mutating, throws or async method members is not currently
|
if (cs.getASTContext().LangOpts.hasFeature(
|
||||||
// allowed.
|
Feature::KeyPathWithMethodMembers)) {
|
||||||
if (auto method = dyn_cast<FuncDecl>(member)) {
|
// Referencing mutating, throws or async method members is not currently
|
||||||
if (method->isAsyncContext())
|
// allowed.
|
||||||
return AllowInvalidRefInKeyPath::create(
|
if (auto method = dyn_cast<FuncDecl>(member)) {
|
||||||
cs, baseType, RefKind::AsyncOrThrowsMethod, member, locator);
|
if (method->isAsyncContext())
|
||||||
if (auto methodType = method->getInterfaceType()->getAs<AnyFunctionType>()) {
|
|
||||||
if (methodType->getResult()->getAs<AnyFunctionType>()->isThrowing())
|
|
||||||
return AllowInvalidRefInKeyPath::create(
|
return AllowInvalidRefInKeyPath::create(
|
||||||
cs, baseType, RefKind::AsyncOrThrowsMethod, member, locator);
|
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(
|
if (isa<ConstructorDecl>(member))
|
||||||
cs, baseType, RefKind::MutatingMethod, member, locator);
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10826,6 +10826,9 @@ static ConstraintFix *validateInitializerRef(ConstraintSystem &cs,
|
|||||||
// which means MetatypeType has to be added after finding a type variable.
|
// which means MetatypeType has to be added after finding a type variable.
|
||||||
if (baseLocator->isLastElement<LocatorPathElt::MemberRefBase>())
|
if (baseLocator->isLastElement<LocatorPathElt::MemberRefBase>())
|
||||||
baseType = MetatypeType::get(baseType);
|
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)
|
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 {
|
struct S {
|
||||||
let i: Int
|
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: objc_interop
|
||||||
|
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||||
|
|
||||||
import Foundation
|
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: executable_test
|
||||||
|
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||||
|
|
||||||
// UNSUPPORTED: use_os_stdlib
|
// UNSUPPORTED: use_os_stdlib
|
||||||
// UNSUPPORTED: back_deployment_runtime
|
// UNSUPPORTED: back_deployment_runtime
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
// RUN: split-file %s %t/src
|
// RUN: split-file %s %t/src
|
||||||
|
|
||||||
/// Build LibA
|
/// 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
|
// 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
|
// 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
|
// 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
|
// 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: executable_test
|
||||||
// REQUIRES: OS=macosx
|
// REQUIRES: OS=macosx
|
||||||
|
// REQUIRES: swift_feature_KeyPathWithMethodMembers
|
||||||
|
|
||||||
// UNSUPPORTED: use_os_stdlib
|
// UNSUPPORTED: use_os_stdlib
|
||||||
// UNSUPPORTED: back_deployment_runtime
|
// 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
|
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
|
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 {
|
struct Sub: Hashable {
|
||||||
static func ==(_: Sub, _: Sub) -> Bool { return true }
|
static func ==(_: Sub, _: Sub) -> Bool { return true }
|
||||||
|
|||||||
Reference in New Issue
Block a user