Skip to content

Commit 47a2fe8

Browse files
committed
NCGenerics: simplify isInterfaceTypeNoncopyable
We can greatly simplify our noncopyable checks if we skip running these diagnostic checks while in SIL mode, where it's not really needed. The challenge with doing the checks in SIL mode is that there is sometimes no generic environment when doing these queries. Whether that itself is simply a bug or fundamental limitation, I haven't investigated.
1 parent b454ded commit 47a2fe8

File tree

3 files changed

+18
-26
lines changed

3 files changed

+18
-26
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,12 @@ static Type containsParameterizedProtocolType(Type inheritedTy) {
8888
}
8989

9090
bool swift::isInterfaceTypeNoncopyable(Type type, GenericEnvironment *env) {
91-
// Turn any type parameters into archetypes.
92-
if (env)
93-
type = GenericEnvironment::mapTypeIntoContext(env, type);
94-
95-
if (auto sugar = dyn_cast<SugarType>(type))
96-
type = sugar->getDesugaredType();
91+
assert(!type->hasTypeParameter() || env && "must have a generic environment");
9792

98-
if (!type->hasTypeParameter())
99-
return type->isNoncopyable();
100-
101-
// Handle types containing unbound generic parameters.
102-
if (auto *generic = type->getAnyGeneric())
103-
return generic->canBeCopyable() != swift::TypeDecl::CanBeInvertible::Always;
104-
else if (auto gtpt = type->getAs<GenericTypeParamType>())
105-
if (auto *gtpd = gtpt->getDecl())
106-
return gtpd->canBeCopyable() != swift::TypeDecl::CanBeInvertible::Always;
93+
if (env)
94+
type = env->mapTypeIntoContext(type);
10795

108-
#ifndef NDEBUG
109-
type->dump();
110-
#endif
111-
llvm_unreachable("unhandled type kind");
96+
return type->isNoncopyable();
11297
}
11398

11499
/// Check the inheritance clause of a type declaration or extension thereof.
@@ -2796,7 +2781,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
27962781
// Reject noncopyable typed subscripts with read/set accessors since we
27972782
// cannot define modify operations upon them without copying the read.
27982783
if (isInterfaceTypeNoncopyable(SD->getElementInterfaceType(),
2799-
DC->getGenericEnvironmentOfContext())) {
2784+
SD->getGenericEnvironment())) {
28002785
if (auto *read = SD->getAccessor(AccessorKind::Read)) {
28012786
if (!read->isImplicit()) {
28022787
if (auto *set = SD->getAccessor(AccessorKind::Set)) {

lib/Sema/TypeCheckStorage.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,12 @@ OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator,
784784
if (storage->getAttrs().hasAttribute<BorrowedAttr>())
785785
return usesBorrowed(DiagKind::BorrowedAttr);
786786

787-
auto *env = storage->getDeclContext()->getGenericEnvironmentOfContext();
787+
GenericEnvironment *env = nullptr;
788+
if (auto *gc = storage->getAsGenericContext())
789+
env = gc->getGenericEnvironment();
790+
else
791+
env = storage->getDeclContext()->getGenericEnvironmentOfContext();
792+
788793
if (isInterfaceTypeNoncopyable(storage->getValueInterfaceType(), env))
789794
return usesBorrowed(DiagKind::NoncopyableType);
790795

lib/Sema/TypeCheckType.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3593,7 +3593,8 @@ TypeResolver::resolveASTFunctionTypeParams(TupleTypeRepr *inputRepr,
35933593
}
35943594

35953595
// Validate the presence of ownership for a noncopyable parameter.
3596-
if (inStage(TypeResolutionStage::Interface)) {
3596+
if (inStage(TypeResolutionStage::Interface)
3597+
&& !options.contains(TypeResolutionFlags::SILMode)) {
35973598
diagnoseMissingOwnership(getASTContext(), dc, ownership,
35983599
eltTypeRepr, ty, options);
35993600

@@ -4776,6 +4777,7 @@ NeverNullType TypeResolver::resolveVarargType(VarargTypeRepr *repr,
47764777
// do not allow move-only types as the element of a vararg
47774778
if (!element->hasError()
47784779
&& inStage(TypeResolutionStage::Interface)
4780+
&& !options.contains(TypeResolutionFlags::SILMode)
47794781
&& isInterfaceTypeNoncopyable(
47804782
element, getDeclContext()->getGenericEnvironmentOfContext())) {
47814783
diagnoseInvalid(repr, repr->getLoc(), diag::noncopyable_generics_variadic,
@@ -4954,11 +4956,13 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
49544956
hadError = true;
49554957
}
49564958
// Tuples with move-only elements aren't yet supported.
4957-
// Track the presence of a noncopyable field for diagnostic purposes.
4959+
// Track the presence of a noncopyable field for diagnostic purposes only.
49584960
// We don't need to re-diagnose if a tuple contains another tuple, though,
49594961
// since we should've diagnosed the inner tuple already.
49604962
if (inStage(TypeResolutionStage::Interface)
4963+
&& !options.contains(TypeResolutionFlags::SILMode)
49614964
&& isInterfaceTypeNoncopyable(ty, dc->getGenericEnvironmentOfContext())
4965+
&& !ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)
49624966
&& !moveOnlyElementIndex.has_value() && !isa<TupleTypeRepr>(tyR)) {
49634967
moveOnlyElementIndex = i;
49644968
}
@@ -5011,9 +5015,7 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
50115015
return ParenType::get(ctx, elements[0].getType());
50125016
}
50135017

5014-
if (moveOnlyElementIndex.has_value()
5015-
&& !options.contains(TypeResolutionFlags::SILType)
5016-
&& !ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)) {
5018+
if (moveOnlyElementIndex.has_value()) {
50175019
auto noncopyableTy = elements[*moveOnlyElementIndex].getType();
50185020
auto loc = repr->getElementType(*moveOnlyElementIndex)->getLoc();
50195021
assert(!noncopyableTy->is<TupleType>() && "will use poor wording");

0 commit comments

Comments
 (0)