Skip to content

Commit 616f7ac

Browse files
committed
temporarily prevent Copyable types from using consuming and borrowing
There is a strong desire for "no-implicit-copy" semantics to be applied to Copyable values marked with the newer `borrowing` and `consuming` ownership specifiers. If we lock ourselves into what SE-390 specifies now for Copyable types in the implementation, then we'll have to introduce a source break when we want such values to have the desired semantics. Before there's wider adoption, I'm making it an error to use those newer names. If for some reason this is enabling a critical optimization for your use case, please use the old names instead: - `__owned` for `consuming` parameters - `__consuming` for `consuming` methods - `__shared` for `borrowing` parameters NOTE: the older names have their ownership attribute mangled into the name of the function itself, so there's a possibility of ABI breaks in the future if you move from the old name to the new one. There is some consideration being made to allow for a migration to the new names in the future without breaking ABI, so do reach out if this is an issue for you. resolves rdar://108538971
1 parent 964b63d commit 616f7ac

File tree

4 files changed

+96
-2
lines changed

4 files changed

+96
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7119,6 +7119,11 @@ ERROR(moveonly_parameter_missing_ownership, none,
71197119
"noncopyable parameter must specify its ownership", ())
71207120
NOTE(moveonly_parameter_ownership_suggestion, none,
71217121
"add '%0' %1", (StringRef, StringRef))
7122+
ERROR(ownership_specifier_copyable,none,
7123+
"Copyable types cannot be 'consuming' or 'borrowing' yet", ())
7124+
ERROR(self_ownership_specifier_copyable,none,
7125+
"%0 is not yet valid on %1s in a Copyable type",
7126+
(SelfAccessKind, DescriptiveDeclKind))
71227127

71237128
//------------------------------------------------------------------------------
71247129
// MARK: Runtime discoverable attributes (@runtimeMetadata)

lib/Sema/TypeCheckAttr.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
466466
}
467467

468468
auto DC = FD->getDeclContext();
469-
// mutation attributes may only appear in type context.
469+
// self-ownership attributes may only appear in type context.
470470
if (auto contextTy = DC->getDeclaredInterfaceType()) {
471471
// 'mutating' and 'nonmutating' are not valid on types
472472
// with reference semantics.
@@ -487,6 +487,27 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
487487
break;
488488
}
489489
}
490+
491+
// Unless we have the experimental no-implicit-copy feature enabled, Copyable
492+
// types can't use 'consuming' or 'borrowing' ownership specifiers.
493+
if (!Ctx.LangOpts.hasFeature(Feature::NoImplicitCopy)) {
494+
if (!contextTy->isPureMoveOnly()) {
495+
switch (attrModifier) { // check the modifier for the Copyable type.
496+
case SelfAccessKind::NonMutating:
497+
case SelfAccessKind::Mutating:
498+
case SelfAccessKind::LegacyConsuming:
499+
// already checked
500+
break;
501+
502+
case SelfAccessKind::Consuming:
503+
case SelfAccessKind::Borrowing:
504+
diagnoseAndRemoveAttr(attr, diag::self_ownership_specifier_copyable,
505+
attrModifier, FD->getDescriptiveKind());
506+
break;
507+
}
508+
}
509+
}
510+
490511
} else {
491512
diagnoseAndRemoveAttr(attr, diag::mutating_invalid_global_scope,
492513
attrModifier);

lib/Sema/TypeCheckType.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4280,7 +4280,33 @@ TypeResolver::resolveOwnershipTypeRepr(OwnershipTypeRepr *repr,
42804280
// Remember that we've seen an ownership specifier for this base type.
42814281
options |= TypeResolutionFlags::HasOwnership;
42824282

4283-
return resolveType(repr->getBase(), options);
4283+
auto result = resolveType(repr->getBase(), options);
4284+
if (result->hasError())
4285+
return result;
4286+
4287+
// Unless we have the experimental no-implicit-copy feature enabled, Copyable
4288+
// types can't use 'consuming' or 'borrowing' ownership specifiers.
4289+
if (!getASTContext().LangOpts.hasFeature(Feature::NoImplicitCopy)) {
4290+
if (!result->isPureMoveOnly()) {
4291+
// Prevent copyable types from using the non-underscored ownership parameter
4292+
// specifiers, other than 'inout'.
4293+
switch (ownershipRepr->getSpecifier()) {
4294+
case ParamSpecifier::Default:
4295+
case ParamSpecifier::InOut:
4296+
case ParamSpecifier::LegacyShared:
4297+
case ParamSpecifier::LegacyOwned:break;
4298+
4299+
case ParamSpecifier::Borrowing:
4300+
case ParamSpecifier::Consuming:
4301+
diagnoseInvalid(ownershipRepr,
4302+
ownershipRepr->getLoc(),
4303+
diag::ownership_specifier_copyable);
4304+
return ErrorType::get(getASTContext());
4305+
}
4306+
}
4307+
}
4308+
4309+
return result;
42844310
}
42854311

42864312
NeverNullType
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
func chalk(_ a: consuming String, // expected-error{{Copyable types cannot be 'consuming' or 'borrowing' yet}}
4+
_ b: borrowing [Int], // expected-error{{Copyable types cannot be 'consuming' or 'borrowing' yet}}
5+
_ c: __shared [String],
6+
_ d: __owned Int?)
7+
{}
8+
9+
struct Stepping {
10+
consuming func perform() {} // expected-error {{'consuming' is not yet valid on instance methods in a Copyable type}}
11+
borrowing func doIt() {} // expected-error {{'borrowing' is not yet valid on instance methods in a Copyable type}}
12+
mutating func change() {}
13+
var ex: Int {
14+
__consuming get { 0 }
15+
}
16+
}
17+
18+
class Clapping {
19+
consuming func perform() {} // expected-error {{'consuming' is not yet valid on instance methods in a Copyable type}}
20+
borrowing func doIt() {} // expected-error {{'borrowing' is not yet valid on instance methods in a Copyable type}}
21+
var ex: Int {
22+
__consuming get { 0 }
23+
}
24+
}
25+
26+
protocol Popping {
27+
consuming func perform() // expected-error {{'consuming' is not yet valid on instance methods in a Copyable type}}
28+
borrowing func doIt() // expected-error {{'borrowing' is not yet valid on instance methods in a Copyable type}}
29+
mutating func change()
30+
var ex: Int {
31+
__consuming get
32+
}
33+
}
34+
35+
enum Exercising {
36+
consuming func perform() {} // expected-error {{'consuming' is not yet valid on instance methods in a Copyable type}}
37+
borrowing func doIt() {} // expected-error {{'borrowing' is not yet valid on instance methods in a Copyable type}}
38+
mutating func change() {}
39+
var ex: Int {
40+
__consuming get { 0 }
41+
}
42+
}

0 commit comments

Comments
 (0)