Skip to content

Commit ef6c79c

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 (cherry picked from commit 8899d3b)
1 parent 76e21ad commit ef6c79c

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7111,6 +7111,11 @@ ERROR(moveonly_parameter_missing_ownership, none,
71117111
"noncopyable parameter must specify its ownership", ())
71127112
NOTE(moveonly_parameter_ownership_suggestion, none,
71137113
"add '%0' %1", (StringRef, StringRef))
7114+
ERROR(ownership_specifier_copyable,none,
7115+
"Copyable types cannot be 'consuming' or 'borrowing' yet", ())
7116+
ERROR(self_ownership_specifier_copyable,none,
7117+
"%0 is not yet valid on %1s in a Copyable type",
7118+
(SelfAccessKind, DescriptiveDeclKind))
71147119

71157120
//------------------------------------------------------------------------------
71167121
// 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
@@ -4279,7 +4279,33 @@ TypeResolver::resolveOwnershipTypeRepr(OwnershipTypeRepr *repr,
42794279
// Remember that we've seen an ownership specifier for this base type.
42804280
options |= TypeResolutionFlags::HasOwnership;
42814281

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

42854311
NeverNullType

0 commit comments

Comments
 (0)