Skip to content

Commit 3e03c67

Browse files
committed
[NCGenerics] remove arg from isNoncopyable(DC)
It should be the responsibility of callers to map the type to a contextual type, as needed. When it's not possible or repetitive to do so, there is a special-purpose function `isInterfaceTypeNoncopyable` for Sema.
1 parent 931f47d commit 3e03c67

14 files changed

+80
-57
lines changed

include/swift/AST/Types.h

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -650,21 +650,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
650650

651651
bool isPlaceholder();
652652

653-
/// Returns true if this type lacks conformance to Copyable in the context,
654-
/// if provided.
655-
bool isNoncopyable(GenericEnvironment *env = nullptr);
656-
bool isNoncopyable(const DeclContext *dc) {
657-
assert(dc);
658-
return isNoncopyable(dc->getGenericEnvironmentOfContext());
659-
};
653+
/// Returns true if this contextual type does not satisfy a conformance to
654+
/// Copyable.
655+
bool isNoncopyable();
660656

661-
/// Returns true if this type conforms to Escapable in the context,
662-
/// if provided.
663-
bool isEscapable(GenericEnvironment *env = nullptr);
664-
bool isEscapable(const DeclContext *dc) {
665-
assert(dc);
666-
return isEscapable(dc->getGenericEnvironmentOfContext());
667-
};
657+
/// Returns true if this contextual type satisfies a conformance to Escapable.
658+
bool isEscapable();
668659

669660
/// Does the type have outer parenthesis?
670661
bool hasParenSugar() const { return getKind() == TypeKind::Paren; }

lib/AST/Type.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ static bool alwaysNoncopyable(Type ty) {
178178
}
179179

180180
/// Preprocesses a type before querying whether it conforms to an invertible.
181-
static CanType preprocessTypeForInvertibleQuery(GenericEnvironment *env,
182-
Type orig) {
181+
static CanType preprocessTypeForInvertibleQuery(Type orig) {
183182
Type type = orig;
184183

185184
// Strip off any StorageType wrapper.
@@ -189,31 +188,34 @@ static CanType preprocessTypeForInvertibleQuery(GenericEnvironment *env,
189188
if (auto wrapper = type->getAs<SILMoveOnlyWrappedType>())
190189
type = wrapper->getInnerType();
191190

192-
// Turn any type parameters into archetypes.
193-
if (env)
194-
if (!type->hasArchetype() || type->hasOpenedExistential())
195-
type = GenericEnvironment::mapTypeIntoContext(env, type);
191+
// Pack expansions such as `repeat T` themselves do not have conformances,
192+
// so check its pattern type for conformance.
193+
if (auto *pet = type->getAs<PackExpansionType>()) {
194+
type = pet->getPatternType()->getCanonicalType();
195+
}
196196

197197
// Strip @lvalue and canonicalize.
198198
auto canType = type->getRValueType()->getCanonicalType();
199199
return canType;
200200
}
201201

202202
/// \returns true iff this type lacks conformance to Copyable.
203-
bool TypeBase::isNoncopyable(GenericEnvironment *env) {
204-
auto canType = preprocessTypeForInvertibleQuery(env, this);
203+
bool TypeBase::isNoncopyable() {
204+
auto canType = preprocessTypeForInvertibleQuery(this);
205205
auto &ctx = canType->getASTContext();
206206

207207
// for legacy-mode queries that are not dependent on conformances to Copyable
208208
if (!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics))
209209
return alwaysNoncopyable(canType);
210210

211+
assert(!hasTypeParameter()
212+
&& "requires a contextual type; use mapTypeIntoContext");
211213
IsNoncopyableRequest request{canType};
212214
return evaluateOrDefault(ctx.evaluator, request, /*default=*/true);
213215
}
214216

215-
bool TypeBase::isEscapable(GenericEnvironment *env) {
216-
auto canType = preprocessTypeForInvertibleQuery(env, this);
217+
bool TypeBase::isEscapable() {
218+
auto canType = preprocessTypeForInvertibleQuery(this);
217219
auto &ctx = canType->getASTContext();
218220

219221
// for legacy-mode queries that are not dependent on conformances to Escapable
@@ -224,6 +226,8 @@ bool TypeBase::isEscapable(GenericEnvironment *env) {
224226
return true;
225227
}
226228

229+
assert(!hasTypeParameter()
230+
&& "requires a contextual type; use mapTypeIntoContext");
227231
IsEscapableRequest request{canType};
228232
return evaluateOrDefault(ctx.evaluator, request, /*default=*/false);
229233
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5545,10 +5545,11 @@ makeBaseClassMemberAccessors(DeclContext *declContext,
55455545
AbstractStorageDecl *baseClassVar) {
55465546
auto &ctx = declContext->getASTContext();
55475547
auto computedType = computedVar->getInterfaceType();
5548+
auto contextTy = declContext->mapTypeIntoContext(computedType);
55485549

55495550
// Use 'address' or 'mutableAddress' accessors for non-copyable
55505551
// types, unless the base accessor returns it by value.
5551-
bool useAddress = computedType->isNoncopyable(declContext) &&
5552+
bool useAddress = contextTy->isNoncopyable() &&
55525553
(baseClassVar->getReadImpl() == ReadImplKind::Stored ||
55535554
baseClassVar->getAccessor(AccessorKind::Address));
55545555

@@ -5699,9 +5700,11 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
56995700
}
57005701

57015702
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
5703+
auto contextTy =
5704+
newContext->mapTypeIntoContext(subscript->getElementInterfaceType());
57025705
// Subscripts that return non-copyable types are not yet supported.
57035706
// See: https://github.com/apple/swift/issues/70047.
5704-
if (subscript->getElementInterfaceType()->isNoncopyable(newContext))
5707+
if (contextTy->isNoncopyable())
57055708
return nullptr;
57065709
auto out = SubscriptDecl::create(
57075710
subscript->getASTContext(), subscript->getName(), subscript->getStaticLoc(),

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,9 +1756,10 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
17561756
: rawElementTy;
17571757
// Use 'address' or 'mutableAddress' accessors for non-copyable
17581758
// types that are returned indirectly.
1759-
bool isImplicit = !elementTy->isNoncopyable(dc);
1759+
bool isNoncopyable = dc->mapTypeIntoContext(elementTy)->isNoncopyable();
1760+
bool isImplicit = !isNoncopyable;
17601761
bool useAddress =
1761-
rawElementTy->getAnyPointerElementType() && elementTy->isNoncopyable(dc);
1762+
rawElementTy->getAnyPointerElementType() && isNoncopyable;
17621763

17631764
auto result = new (ctx)
17641765
VarDecl(/*isStatic*/ false, VarDecl::Introducer::Var,

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
137137
return CheckTypeWitnessResult::forError();
138138

139139
if (!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)
140-
&& type->isNoncopyable(dc)) {
140+
&& type->isNoncopyable()) {
141141
// No move-only type can witness an associatedtype requirement.
142142
// Pretend the failure is a lack of Copyable conformance.
143143
auto *copyable = ctx.getProtocol(KnownProtocolKind::Copyable);

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,7 +3889,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
38893889
}
38903890

38913891
// move-only types (and their metatypes) cannot match with existential types.
3892-
if (type1->getMetatypeInstanceType()->isNoncopyable(DC)) {
3892+
if (type1->getMetatypeInstanceType()->isNoncopyable()) {
38933893
// tailor error message
38943894
if (shouldAttemptFixes()) {
38953895
auto *fix = MustBeCopyable::create(*this,
@@ -11886,7 +11886,7 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
1188611886

1188711887
// Noncopyable types can't be involved in bridging conversions since a bridged
1188811888
// type assumes the ability to copy.
11889-
if (type1->isNoncopyable(DC)) {
11889+
if (type1->isNoncopyable()) {
1189011890
return SolutionKind::Error;
1189111891
}
1189211892

lib/Sema/MiscDiagnostics.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
325325
tupleExpr->getElementNames());
326326

327327
// Diagnose attempts to form a tuple with any noncopyable elements.
328-
if (E->getType()->isNoncopyable(DC)
328+
if (E->getType()->isNoncopyable()
329329
&& !Ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)) {
330330
auto noncopyableTy = E->getType();
331331
assert(noncopyableTy->is<TupleType>() && "will use poor wording");
@@ -388,7 +388,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
388388
if (!castType)
389389
return;
390390

391-
if (castType->isNoncopyable(DC)) {
391+
if (castType->isNoncopyable()) {
392392
// can't cast anything to move-only; there should be no valid ones.
393393
Ctx.Diags.diagnose(cast->getLoc(), diag::noncopyable_cast);
394394
return;
@@ -398,7 +398,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
398398
// as of now there is no type it could be cast to except itself, so
399399
// there's no reason for it to happen at runtime.
400400
if (auto fromType = cast->getSubExpr()->getType()) {
401-
if (fromType->isNoncopyable(DC)) {
401+
if (fromType->isNoncopyable()) {
402402
// can't cast move-only to anything.
403403
Ctx.Diags.diagnose(cast->getLoc(), diag::noncopyable_cast);
404404
return;
@@ -4103,7 +4103,7 @@ diagnoseMoveOnlyPatternMatchSubject(ASTContext &C,
41034103
auto subjectType = subjectExpr->getType();
41044104
if (!subjectType
41054105
|| subjectType->hasError()
4106-
|| !subjectType->isNoncopyable(DC)) {
4106+
|| !subjectType->isNoncopyable()) {
41074107
return;
41084108
}
41094109

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7319,8 +7319,7 @@ void AttributeChecker::visitStaticExclusiveOnlyAttr(
73197319
// Can only be applied to structs.
73207320
auto structDecl = cast<StructDecl>(D);
73217321

7322-
if (!structDecl->getDeclaredInterfaceType()
7323-
->isNoncopyable(D->getDeclContext())) {
7322+
if (structDecl->canBeCopyable() != TypeDecl::CBI_Never) {
73247323
diagnoseAndRemoveAttr(attr, diag::attr_static_exclusive_only_noncopyable);
73257324
}
73267325
}

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,8 +1726,8 @@ TypeChecker::typeCheckCheckedCast(Type fromType, Type toType,
17261726
//
17271727
// Thus, right now, a move-only type is only a subtype of itself.
17281728
// We also want to prevent conversions of a move-only type's metatype.
1729-
if (fromType->getMetatypeInstanceType()->isNoncopyable(dc)
1730-
|| toType->getMetatypeInstanceType()->isNoncopyable(dc))
1729+
if (fromType->getMetatypeInstanceType()->isNoncopyable()
1730+
|| toType->getMetatypeInstanceType()->isNoncopyable())
17311731
return CheckedCastKind::Unresolved;
17321732

17331733
// Check for a bridging conversion.

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ static Type containsParameterizedProtocolType(Type inheritedTy) {
9090
bool swift::isInterfaceTypeNoncopyable(Type type, GenericEnvironment *env) {
9191
// Turn any type parameters into archetypes.
9292
if (env)
93-
if (!type->hasArchetype() || type->hasOpenedExistential())
94-
type = GenericEnvironment::mapTypeIntoContext(env, type);
93+
type = GenericEnvironment::mapTypeIntoContext(env, type);
94+
95+
if (auto sugar = dyn_cast<SugarType>(type))
96+
type = sugar->getDesugaredType();
9597

9698
if (!type->hasTypeParameter())
9799
return type->isNoncopyable();
@@ -100,8 +102,12 @@ bool swift::isInterfaceTypeNoncopyable(Type type, GenericEnvironment *env) {
100102
if (auto *generic = type->getAnyGeneric())
101103
return generic->canBeCopyable() != swift::TypeDecl::CBI_Always;
102104
else if (auto gtpt = type->getAs<GenericTypeParamType>())
103-
return gtpt->getDecl()->canBeCopyable() != swift::TypeDecl::CBI_Always;
105+
if (auto *gtpd = gtpt->getDecl())
106+
return gtpd->canBeCopyable() != swift::TypeDecl::CBI_Always;
104107

108+
#ifndef NDEBUG
109+
type->dump();
110+
#endif
105111
llvm_unreachable("unhandled type kind");
106112
}
107113

0 commit comments

Comments
 (0)