Skip to content

Commit 041d9f4

Browse files
committed
fix typechecking for discard in generics
Don't use `getDeclaredTypeInContext` it gives the wrong types for generic params. rdar://108975216 (cherry picked from commit da9847a)
1 parent bc1161d commit 041d9f4

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12621262
// check the kind of type this discard statement appears within.
12631263
if (!diagnosed) {
12641264
auto *nominalDecl = fn->getDeclContext()->getSelfNominalTypeDecl();
1265-
Type nominalType = nominalDecl->getDeclaredTypeInContext();
1265+
Type nominalType =
1266+
fn->mapTypeIntoContext(nominalDecl->getDeclaredInterfaceType());
12661267

12671268
// must be noncopyable
12681269
if (!nominalType->isPureMoveOnly()) {
@@ -1288,17 +1289,16 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12881289
// if the modules differ, so that you can discard a @frozen type from a
12891290
// resilient module. But for now the proposal simply says that it has to
12901291
// be the same module, which is probably better for everyone.
1291-
auto *typeDecl = nominalType->getAnyNominal();
12921292
auto *fnModule = fn->getModuleContext();
1293-
auto *typeModule = typeDecl->getModuleContext();
1293+
auto *typeModule = nominalDecl->getModuleContext();
12941294
if (fnModule != typeModule) {
12951295
ctx.Diags.diagnose(DS->getDiscardLoc(), diag::discard_wrong_module,
12961296
nominalType);
12971297
diagnosed = true;
12981298
} else {
12991299
assert(
1300-
!typeDecl->isResilient(fnModule, ResilienceExpansion::Maximal) &&
1301-
"trying to discard a type resilient to us!");
1300+
!nominalDecl->isResilient(fnModule, ResilienceExpansion::Maximal)
1301+
&& "trying to discard a type resilient to us!");
13021302
}
13031303
}
13041304
}

test/Interpreter/moveonly_discard.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ func print_closing_MFD() { print("closing MaybeFileDescriptor") }
99

1010
enum E: Error { case err }
1111

12-
@_moveOnly
13-
struct FileDescriptor {
12+
struct FileDescriptor: ~Copyable {
1413
var fd: Int
1514
static var nextFD: Int = 0
1615

@@ -59,7 +58,7 @@ struct FileDescriptor {
5958
}
6059
}
6160

62-
@_moveOnly enum MaybeFileDescriptor {
61+
enum MaybeFileDescriptor: ~Copyable {
6362
case some(FileDescriptor)
6463
case nothing
6564

@@ -83,6 +82,14 @@ struct FileDescriptor {
8382
}
8483
}
8584

85+
struct SillyEmptyGeneric<T>: ~Copyable {
86+
consuming func identity(_ t: T) -> T {
87+
discard self
88+
return t
89+
}
90+
deinit { fatalError("ran unexpectedly!") }
91+
}
92+
8693
func main() {
8794
let _ = {
8895
let x = FileDescriptor() // 0
@@ -161,6 +168,13 @@ func main() {
161168
// CHECK: closing file descriptor: 13
162169
}()
163170

171+
let _ = {
172+
let x = SillyEmptyGeneric<[Int]>()
173+
let z = [1, 2]
174+
let ans = x.identity(z)
175+
assert(z == ans)
176+
}()
177+
164178
}
165179

166180
main()

test/Sema/discard.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,21 @@ enum NoDeinitEnum: ~Copyable {
162162
}
163163
}
164164

165-
struct HasGenericNotStored<T>: ~Copyable {
165+
struct HasGenericNotStored<T>: ~Copyable { // expected-note 2{{arguments to generic parameter 'T' ('Int' and 'T') are expected to be equal}}
166166
consuming func discard() { discard self }
167+
168+
consuming func bad_discard1() {
169+
discard HasGenericNotStored<Int>()
170+
// expected-error@-1 {{cannot convert value of type 'HasGenericNotStored<Int>' to expected discard type 'HasGenericNotStored<T>'}}
171+
// expected-error@-2 {{you can only discard 'self'}}
172+
}
173+
174+
consuming func bad_discard2() {
175+
let `self` = HasGenericNotStored<Int>()
176+
discard `self`
177+
// expected-error@-1 {{cannot convert value of type 'HasGenericNotStored<Int>' to expected discard type 'HasGenericNotStored<T>'}}
178+
}
179+
167180
func identity(_ t: T) -> T { return t }
168181
deinit{}
169182
}

0 commit comments

Comments
 (0)