mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
NCGenerics: enforce same-source conformance rule
SE-427 says the conformance to Copyable must appear in the same source file as the nominal type. resolves rdar://131486561
This commit is contained in:
@@ -7820,6 +7820,9 @@ WARNING(suppress_already_suppressed_protocol,none,
|
||||
ERROR(extension_conforms_to_invertible_and_others, none,
|
||||
"conformance to '%0' must be declared in a separate extension",
|
||||
(StringRef))
|
||||
ERROR(invertible_conformance_other_source_file,none,
|
||||
"conformance to '%0' must occur in the same source file as %kind1",
|
||||
(StringRef, const ValueDecl *))
|
||||
|
||||
// -- older ones below --
|
||||
ERROR(noncopyable_parameter_requires_ownership, none,
|
||||
|
||||
@@ -144,6 +144,16 @@ static void checkInvertibleConformanceCommon(DeclContext *dc,
|
||||
conformanceLoc = normalConf->getLoc();
|
||||
assert(conformanceLoc);
|
||||
|
||||
// Conformance must be defined in the same source file as the nominal.
|
||||
auto conformanceDC = concrete->getDeclContext();
|
||||
if (auto *sourceFile = conformanceDC->getOutermostParentSourceFile()) {
|
||||
if (sourceFile != nominalDecl->getOutermostParentSourceFile()) {
|
||||
ctx.Diags.diagnose(conformanceLoc,
|
||||
diag::invertible_conformance_other_source_file,
|
||||
getInvertibleProtocolKindName(ip), nominalDecl);
|
||||
}
|
||||
}
|
||||
|
||||
auto condReqs = normalConf->getConditionalRequirements();
|
||||
hasUnconditionalConformance = condReqs.empty();
|
||||
auto *thisProto = normalConf->getProtocol();
|
||||
|
||||
32
test/Sema/copyable_conformance_diff_module.swift
Normal file
32
test/Sema/copyable_conformance_diff_module.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
|
||||
//// Ensure we cannot add the conformance in a different module.
|
||||
|
||||
// RUN: %target-build-swift \
|
||||
// RUN: -swift-version 5 \
|
||||
// RUN: -emit-module \
|
||||
// RUN: -emit-module-path %t/GardenKit.swiftmodule \
|
||||
// RUN: -emit-module-interface-path %t/GardenKit.swiftinterface \
|
||||
// RUN: -enable-library-evolution \
|
||||
// RUN: -module-name=GardenKit \
|
||||
// RUN: %t/GardenKit.swift
|
||||
|
||||
// RUN: %target-swift-frontend \
|
||||
// RUN: -typecheck -verify \
|
||||
// RUN: -I %t \
|
||||
// RUN: %t/Visitor.swift
|
||||
|
||||
//--- GardenKit.swift
|
||||
|
||||
public struct Garden<Plant: ~Copyable>: ~Copyable {
|
||||
public let plant: Plant
|
||||
public init(_ p: consuming Plant) { plant = p }
|
||||
}
|
||||
|
||||
//--- Visitor.swift
|
||||
|
||||
import GardenKit
|
||||
|
||||
// expected-error@+1 {{conformance to 'Copyable' must occur in the same source file as generic struct 'Garden'}}
|
||||
extension Garden: @retroactive Copyable where Plant: Copyable {}
|
||||
20
test/Sema/copyable_conformance_diff_source_file.swift
Normal file
20
test/Sema/copyable_conformance_diff_source_file.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
|
||||
//// Ensure we cannot add the conformance in a different source file.
|
||||
|
||||
// RUN: %target-swift-frontend \
|
||||
// RUN: -typecheck -verify \
|
||||
// RUN: %t/Visitor.swift %t/GardenKit.swift
|
||||
|
||||
//--- GardenKit.swift
|
||||
|
||||
public struct Garden<Plant: ~Copyable>: ~Copyable {
|
||||
public let plant: Plant
|
||||
public init(_ p: consuming Plant) { plant = p }
|
||||
}
|
||||
|
||||
//--- Visitor.swift
|
||||
|
||||
// expected-error@+1 {{conformance to 'Copyable' must occur in the same source file as generic struct 'Garden'}}
|
||||
extension Garden: Copyable where Plant: Copyable {}
|
||||
Reference in New Issue
Block a user