Skip to content

Commit 43b90e8

Browse files
committed
[noimplicitcopy] Error if a noimplicitcopy vardecl or paramdecl is of move only type.
rdar://104934156
1 parent d909c89 commit 43b90e8

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6648,6 +6648,8 @@ ERROR(noimplicitcopy_attr_valid_only_on_local_let_params,
66486648
none, "'@_noImplicitCopy' attribute can only be applied to local lets and params", ())
66496649
ERROR(noimplicitcopy_attr_invalid_in_generic_context,
66506650
none, "'@_noImplicitCopy' attribute cannot be applied to entities in generic contexts", ())
6651+
ERROR(noimplicitcopy_attr_not_allowed_on_moveonlytype,none,
6652+
"'@_noImplicitCopy' has no effect when applied to a move only type", ())
66516653

66526654
//------------------------------------------------------------------------------
66536655
// MARK: Type inference from default expressions

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/AST/ASTWalker.h"
3333
#include "swift/AST/AccessNotes.h"
3434
#include "swift/AST/AccessScope.h"
35+
#include "swift/AST/Attr.h"
3536
#include "swift/AST/Decl.h"
3637
#include "swift/AST/DeclContext.h"
3738
#include "swift/AST/DiagnosticsSema.h"
@@ -2184,6 +2185,21 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
21842185
VD->visitEmittedAccessors([&](AccessorDecl *accessor) {
21852186
visit(accessor);
21862187
});
2188+
2189+
// If this var decl is a no implicit copy varDecl, error if its type is a
2190+
// move only type. No implicit copy is redundant.
2191+
//
2192+
// NOTE: We do this here instead of TypeCheckAttr since types are not
2193+
// completely type checked at that point.
2194+
if (auto attr = VD->getAttrs().getAttribute<NoImplicitCopyAttr>()) {
2195+
if (auto *nom = VD->getType()->getCanonicalType()->getNominalOrBoundGenericNominal()) {
2196+
if (nom->isMoveOnly()) {
2197+
DE.diagnose(attr->getLocation(),
2198+
diag::noimplicitcopy_attr_not_allowed_on_moveonlytype)
2199+
.fixItRemove(attr->getRange());
2200+
}
2201+
}
2202+
}
21872203
}
21882204

21892205
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
@@ -3657,6 +3673,17 @@ void TypeChecker::checkParameterList(ParameterList *params,
36573673
DeclChecker(param->getASTContext(), SF).visitBoundVariable(auxiliaryDecl);
36583674
});
36593675
}
3676+
3677+
// If we have a noimplicitcopy parameter, make sure that the underlying type
3678+
// is not move only. It is redundant.
3679+
if (auto attr = param->getAttrs().getAttribute<NoImplicitCopyAttr>()) {
3680+
if (auto *nom = param->getType()->getCanonicalType()->getNominalOrBoundGenericNominal()) {
3681+
if (nom->isMoveOnly()) {
3682+
param->diagnose(diag::noimplicitcopy_attr_not_allowed_on_moveonlytype)
3683+
.fixItRemove(attr->getRange());
3684+
}
3685+
}
3686+
}
36603687
}
36613688

36623689
// For source compatibility, allow duplicate internal parameter names

test/Sema/noimplicitcopy_attr.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,17 @@ func useGeneric<T>(_ x: T) {
138138
let z = y
139139
print(z)
140140
}
141+
142+
@_moveOnly
143+
struct MoveOnly {
144+
var k = Klass()
145+
}
146+
147+
func useMoveOnly(@_noImplicitCopy _ x: MoveOnly) -> MoveOnly { // expected-error {{'@_noImplicitCopy' has no effect when applied to a move only type}}
148+
return x
149+
}
150+
151+
func useMoveOnly2(_ x: MoveOnly) {
152+
@_noImplicitCopy let y = x // expected-error {{'@_noImplicitCopy' has no effect when applied to a move only type}}
153+
let _ = y
154+
}

0 commit comments

Comments
 (0)