Skip to content

Commit 112eeff

Browse files
committed
snapshot
1 parent 3b1da2f commit 112eeff

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
@@ -6734,6 +6734,11 @@ ERROR(availability_isolated_any_only_version_newer, none,
67346734
"%0 %1 or newer",
67356735
(StringRef, llvm::VersionTuple))
67366736

6737+
ERROR(availability_noncopyable_generics_only_version_newer, none,
6738+
"runtime support for '~' suppressions on generic parameters is only available in "
6739+
"%0 %1 or newer",
6740+
(StringRef, llvm::VersionTuple))
6741+
67376742
ERROR(availability_variadic_type_only_version_newer, none,
67386743
"parameter packs in generic types are only available in %0 %1 or newer",
67396744
(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, (5, 11))
7171
// Metadata support for @isolated(any) function types
7272
FEATURE(IsolatedAny, (5, 11))
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
@@ -25,6 +25,7 @@
2525
#include "swift/IRGen/Linking.h"
2626
#include "swift/RemoteInspection/MetadataSourceBuilder.h"
2727
#include "swift/RemoteInspection/Records.h"
28+
#include "swift/Sema/CheckAvailability.h"
2829
#include "swift/SIL/SILModule.h"
2930

3031
#include "ConstantBuilder.h"
@@ -226,17 +227,11 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
226227
}
227228

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

242237
return false;

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/Parse/Lexer.h"
3838
#include "swift/Parse/Parser.h"
3939
#include "swift/Sema/IDETypeChecking.h"
40+
#include "swift/Sema/CheckAvailability.h"
4041
#include "llvm/ADT/MapVector.h"
4142
#include "llvm/ADT/StringSwitch.h"
4243
#include "llvm/Support/SaveAndRestore.h"
@@ -3034,6 +3035,60 @@ static bool diagnoseIsolatedAnyAvailability(
30343035
ReferenceDC);
30353036
}
30363037

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

0 commit comments

Comments
 (0)