Skip to content

Commit ce4d210

Browse files
committed
snapshot
1 parent 937430b commit ce4d210

File tree

5 files changed

+97
-10
lines changed

5 files changed

+97
-10
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6735,6 +6735,11 @@ ERROR(availability_isolated_any_only_version_newer, none,
67356735
"%0 %1 or newer",
67366736
(StringRef, llvm::VersionTuple))
67376737

6738+
ERROR(availability_noncopyable_generics_only_version_newer, none,
6739+
"runtime support for '~' suppressions on generic parameters is only available in "
6740+
"%0 %1 or newer",
6741+
(StringRef, llvm::VersionTuple))
6742+
67386743
ERROR(availability_variadic_type_only_version_newer, none,
67396744
"parameter packs in generic types are only available in %0 %1 or newer",
67406745
(StringRef, llvm::VersionTuple))

include/swift/AST/FeatureAvailability.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ FEATURE(SwiftExceptionPersonality, (6, 0))
7171
// Metadata support for @isolated(any) function types
7272
FEATURE(IsolatedAny, (6, 0))
7373

74+
FEATURE(NoncopyableGenerics, (6, 0))
75+
7476
FEATURE(TaskExecutor, FUTURE)
7577
FEATURE(Differentiation, FUTURE)
7678
FEATURE(InitRawStructMetadata, FUTURE)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===--- CheckAvailability.h - CheckAvailability ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SEMA_CHECKAVAILABILITY_H
14+
#define SWIFT_SEMA_CHECKAVAILABILITY_H
15+
16+
namespace swift {
17+
class NominalOrBoundGenericNominalType;
18+
19+
/// NoncopyableGenerics, which is the generics system for inverses, does not
20+
/// always require the runtime metadata that is only availabile in Swift 6.
21+
///
22+
/// \returns true if the given type needs the newer runtime.
23+
bool requiresNoncopyableGenericsAvailabilityCheck(
24+
NominalOrBoundGenericNominalType *type);
25+
}
26+
27+
#endif //SWIFT_SEMA_CheckAVAILABILITY_H

lib/IRGen/GenReflection.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/IRGen/Linking.h"
2727
#include "swift/RemoteInspection/MetadataSourceBuilder.h"
2828
#include "swift/RemoteInspection/Records.h"
29+
#include "swift/Sema/CheckAvailability.h"
2930
#include "swift/SIL/SILModule.h"
3031

3132
#include "ConstantBuilder.h"
@@ -227,17 +228,11 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
227228
}
228229

229230
// Any nominal type that has an inverse requirement in its generic signature
230-
// uses NoncopyableGenerics. Since inverses are mangled into symbols,
231-
// a Swift 6.0+ runtime is needed to demangle them.
231+
// uses NoncopyableGenerics. We can support some cases where the type has
232+
// bound generic arguments that conform to all invertible protocols.
232233
if (auto nominalTy = dyn_cast<NominalOrBoundGenericNominalType>(t)) {
233-
auto *nom = nominalTy->getDecl();
234-
if (auto sig = nom->getGenericSignature()) {
235-
SmallVector<InverseRequirement, 2> inverses;
236-
SmallVector<Requirement, 2> reqs;
237-
sig->getRequirementsWithInverses(reqs, inverses);
238-
if (!inverses.empty())
239-
return addRequirement(Swift_6_0);
240-
}
234+
if (requiresNoncopyableGenericsAvailabilityCheck(nominalTy))
235+
return addRequirement(Swift_6_0);
241236
}
242237

243238
return false;

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "swift/Parse/Lexer.h"
3939
#include "swift/Parse/Parser.h"
4040
#include "swift/Sema/IDETypeChecking.h"
41+
#include "swift/Sema/CheckAvailability.h"
4142
#include "llvm/ADT/MapVector.h"
4243
#include "llvm/ADT/StringSwitch.h"
4344
#include "llvm/Support/SaveAndRestore.h"
@@ -3023,6 +3024,60 @@ static bool diagnoseIsolatedAnyAvailability(
30233024
ReferenceDC);
30243025
}
30253026

3027+
static bool diagnoseNoncopyableGenericsAvailability(
3028+
SourceRange ReferenceRange, const DeclContext *ReferenceDC) {
3029+
return TypeChecker::checkAvailability(
3030+
ReferenceRange,
3031+
ReferenceDC->getASTContext().getNoncopyableGenericsAvailability(),
3032+
diag::availability_noncopyable_generics_only_version_newer,
3033+
ReferenceDC);
3034+
}
3035+
3036+
static bool inverseGenericsOldRuntimeCompatable(BoundGenericType *boundTy) {
3037+
for (auto arg : boundTy->getGenericArgs()) {
3038+
if (arg->hasTypeParameter() || arg->hasUnboundGenericType())
3039+
return false;
3040+
3041+
// Make sure the argument conforms to all known invertible protocols.
3042+
for (auto ip : InvertibleProtocolSet::allKnown()) {
3043+
switch (ip) {
3044+
case InvertibleProtocolKind::Copyable:
3045+
if (arg->isNoncopyable())
3046+
return false;
3047+
case InvertibleProtocolKind::Escapable:
3048+
if (!arg->isEscapable())
3049+
return false;
3050+
}
3051+
}
3052+
}
3053+
return true;
3054+
}
3055+
3056+
bool swift::requiresNoncopyableGenericsAvailabilityCheck(
3057+
NominalOrBoundGenericNominalType *nominalTy) {
3058+
auto *nom = nominalTy->getDecl();
3059+
if (auto sig = nom->getGenericSignature()) {
3060+
SmallVector<InverseRequirement, 2> inverses;
3061+
SmallVector<Requirement, 2> reqs;
3062+
sig->getRequirementsWithInverses(reqs, inverses);
3063+
if (!inverses.empty()) {
3064+
// If the nominal is a bound generic type, and all arguments are
3065+
// conform to all invertible protocols, then older runtimes that will
3066+
// not check for those conformances don't actually need to, since we
3067+
// have already checked it now.
3068+
if (auto boundTy = dyn_cast<BoundGenericType>(nominalTy)) {
3069+
if (!inverseGenericsOldRuntimeCompatable(boundTy))
3070+
return true;
3071+
} else {
3072+
// It's generic, not bound, and has an inverse on a generic
3073+
// parameter, so we need the appropriate runtime.
3074+
return true;
3075+
}
3076+
}
3077+
}
3078+
return false;
3079+
}
3080+
30263081
static bool checkTypeMetadataAvailabilityInternal(CanType type,
30273082
SourceRange refLoc,
30283083
const DeclContext *refDC) {
@@ -3033,6 +3088,9 @@ static bool checkTypeMetadataAvailabilityInternal(CanType type,
30333088
auto isolation = fnType->getIsolation();
30343089
if (isolation.isErased())
30353090
return diagnoseIsolatedAnyAvailability(refLoc, refDC);
3091+
} else if (auto nominalTy = dyn_cast<NominalOrBoundGenericNominalType>(type)) {
3092+
if (requiresNoncopyableGenericsAvailabilityCheck(nominalTy))
3093+
return diagnoseNoncopyableGenericsAvailability(refLoc, refDC);
30363094
}
30373095
return false;
30383096
});

0 commit comments

Comments
 (0)