Skip to content

Commit d05ba66

Browse files
committed
[wip] Copyable as a Requirement Against the Machine
1 parent 3113e83 commit d05ba66

File tree

4 files changed

+69
-15
lines changed

4 files changed

+69
-15
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,20 @@ void swift::rewriting::realizeInheritedRequirements(
759759

760760
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
761761
}
762+
763+
// All associated types or generic type params are Copyable by default.
764+
// TODO: if we saw ~Copyable in the inherited types list earlier, skip this!
765+
if (auto *copyable = ctx.getProtocol(KnownProtocolKind::Copyable)) {
766+
SourceLoc loc = decl->getLoc();
767+
Type copyableType = copyable->getDeclaredInterfaceType();
768+
769+
// Add Copyable as an "inferred" requirement.
770+
SmallVector<Requirement, 2> reqs;
771+
Requirement sugaredReq(RequirementKind::Conformance, type, copyableType);
772+
desugarRequirement(sugaredReq, loc, reqs, errors);
773+
for (const auto &req : reqs)
774+
result.push_back({req, loc, /*wasInferred=*/true});
775+
}
762776
}
763777

764778
/// StructuralRequirementsRequest realizes all the user-written requirements

lib/Sema/CSDiagnostics.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,20 @@ bool MissingConformanceFailure::diagnoseAsError() {
616616
if (diagnoseAsAmbiguousOperatorRef())
617617
return true;
618618

619+
// Use tailored diagnostics for failure to conform to Copyable.
620+
if (auto asProtoType = protocolType->getAs<ProtocolType>()) {
621+
if (auto *protoDecl = asProtoType->getDecl()) {
622+
if (protoDecl->isSpecificProtocol(KnownProtocolKind::Copyable)) {
623+
NotCopyableFailure failure(getSolution(),
624+
nonConformingType,
625+
NoncopyableMatchFailure::forCopyableConstraint(),
626+
getLocator());
627+
if (failure.diagnoseAsError())
628+
return true;
629+
}
630+
}
631+
}
632+
619633
if (nonConformingType->isObjCExistentialType()) {
620634
emitDiagnostic(diag::protocol_does_not_conform_static, nonConformingType,
621635
protocolType);
@@ -6158,6 +6172,7 @@ bool NotCopyableFailure::diagnoseAsError() {
61586172

61596173
case NoncopyableMatchFailure::CopyableConstraint: {
61606174
auto *loc = getLocator();
6175+
auto path = loc->getPath();
61616176

61626177
if (loc->isLastElement<LocatorPathElt::AnyTupleElement>()) {
61636178
assert(!noncopyableTy->is<TupleType>() && "will use poor wording");
@@ -6171,9 +6186,11 @@ bool NotCopyableFailure::diagnoseAsError() {
61716186
return true;
61726187
}
61736188

6174-
// a bit paranoid of nulls and such...
6175-
if (auto *genericParam = loc->getGenericParameter()) {
6176-
if (auto *paramDecl = genericParam->getDecl()) {
6189+
auto diagnoseGenericTypeParamType = [&](GenericTypeParamType *typeParam) {
6190+
if (!typeParam)
6191+
return false;
6192+
6193+
if (auto *paramDecl = typeParam->getDecl()) {
61776194
if (auto *owningDecl =
61786195
dyn_cast_or_null<ValueDecl>(paramDecl->getDeclContext()->getAsDecl())) {
61796196

@@ -6182,27 +6199,45 @@ bool NotCopyableFailure::diagnoseAsError() {
61826199
emitDiagnostic(diag::noncopyable_generics_generic_param_metatype,
61836200
noncopyableTy->getMetatypeInstanceType(),
61846201
paramDecl->getDescriptiveKind(),
6185-
genericParam,
6202+
typeParam,
61866203
owningDecl->getName(),
61876204
noncopyableTy);
61886205
else
61896206
emitDiagnostic(diag::noncopyable_generics_generic_param,
61906207
noncopyableTy,
61916208
paramDecl->getDescriptiveKind(),
6192-
genericParam,
6209+
typeParam,
61936210
owningDecl->getName());
61946211

61956212
// If we have a location for the parameter, point it out in a note.
61966213
if (auto loc = paramDecl->getNameLoc()) {
61976214
emitDiagnosticAt(loc,
61986215
diag::noncopyable_generics_implicit_copyable,
61996216
paramDecl->getDescriptiveKind(),
6200-
genericParam);
6217+
typeParam);
62016218
}
62026219

62036220
return true;
62046221
}
62056222
}
6223+
return false;
6224+
};
6225+
6226+
// NOTE: a non-requirement constraint locator might now be impossible after
6227+
// having made Copyable be added as a Requirement.
6228+
if (diagnoseGenericTypeParamType(loc->getGenericParameter()))
6229+
return true;
6230+
6231+
if (auto tpr =
6232+
loc->getLastElementAs<LocatorPathElt::TypeParameterRequirement>()) {
6233+
auto signature = path[path.size() - 2]
6234+
.castTo<LocatorPathElt::OpenedGeneric>()
6235+
.getSignature();
6236+
auto requirement = signature.getRequirements()[tpr->getIndex()];
6237+
auto subject = requirement.getFirstType();
6238+
6239+
if (diagnoseGenericTypeParamType(subject->getAs<GenericTypeParamType>()))
6240+
return true;
62066241
}
62076242
break;
62086243
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,15 +1932,15 @@ TypeVariableType *ConstraintSystem::openGenericParameter(
19321932
// This lookup only can fail if the stdlib (i.e. the Swift module) has not
19331933
// been loaded because you've passed `-parse-stdlib` and are not building the
19341934
// stdlib itself (which would have `-module-name Swift` too).
1935-
if (!outerDC->getParentModule()->isBuiltinModule()) {
1936-
if (auto *copyable = TypeChecker::getProtocol(getASTContext(), SourceLoc(),
1937-
KnownProtocolKind::Copyable)) {
1938-
addConstraint(
1939-
ConstraintKind::ConformsTo, typeVar,
1940-
copyable->getDeclaredInterfaceType(),
1941-
locator.withPathElement(LocatorPathElt::GenericParameter(parameter)));
1942-
}
1943-
}
1935+
// if (!outerDC->getParentModule()->isBuiltinModule()) {
1936+
// if (auto *copyable = TypeChecker::getProtocol(getASTContext(), SourceLoc(),
1937+
// KnownProtocolKind::Copyable)) {
1938+
// addConstraint(
1939+
// ConstraintKind::ConformsTo, typeVar,
1940+
// copyable->getDeclaredInterfaceType(),
1941+
// locator.withPathElement(LocatorPathElt::GenericParameter(parameter)));
1942+
// }
1943+
// }
19441944

19451945
return typeVar;
19461946
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,11 @@ static void checkProtocolRefinementRequirements(ProtocolDecl *proto) {
18201820
if (otherProto == proto)
18211821
continue;
18221822

1823+
// For any protocol 'P', there is an implied requirement 'Self: Copyable',
1824+
// unless it was suppressed via `Self: ~Copyable`; so skip if present.
1825+
if (otherProto->isSpecificProtocol(KnownProtocolKind::Copyable))
1826+
continue;
1827+
18231828
// GenericSignature::getRequiredProtocols() canonicalizes the protocol
18241829
// list by dropping protocols that are inherited by other protocols in
18251830
// the list. Any protocols that remain in the list other than 'proto'

0 commit comments

Comments
 (0)