Skip to content

Commit e117dd9

Browse files
committed
[Sema] SE-0213: Fix LinkedExprAnalyzer to not record types for literal init
Literal initialization via coercion makes current incorrect logic slightly more eager still, which leads to more chained arithmetic operator expressions to be recognized as "symmetric" and their type variables merged. Although literal init via coercion does provide more type information, let's treat it as regular initializer calls and don't record the types. Resolves: rdar://problem/42750089
1 parent d2cc353 commit e117dd9

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

lib/Sema/CSGen.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,12 @@ namespace {
304304

305305
// Coercion exprs have a rigid type, so there's no use in gathering info
306306
// about them.
307-
if (isa<CoerceExpr>(expr)) {
308-
LTI.collectedTypes.insert(CS.getType(expr).getPointer());
309-
307+
if (auto *coercion = dyn_cast<CoerceExpr>(expr)) {
308+
// Let's not collect information about types initialized by
309+
// coercions just like we don't for regular initializer calls,
310+
// because that might lead to overly eager type variable merging.
311+
if (!coercion->isLiteralInit())
312+
LTI.collectedTypes.insert(CS.getType(expr).getPointer());
310313
return { false, expr };
311314
}
312315

test/Constraints/rdar42750089.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P : Equatable {
4+
associatedtype T = String
5+
}
6+
7+
struct S : Hashable {
8+
var key: String
9+
10+
init(_ key: String) {
11+
self.key = key
12+
}
13+
}
14+
15+
extension S : ExpressibleByStringLiteral {
16+
public init(stringLiteral value: String) {
17+
self.init(value)
18+
}
19+
}
20+
21+
extension S : _ExpressibleByStringInterpolation {
22+
init(stringInterpolation strings: S...) {
23+
self.key = "foo"
24+
}
25+
26+
init<T>(stringInterpolationSegment expr: T) {
27+
self.init(String(describing: expr))
28+
}
29+
}
30+
31+
extension S : P {}
32+
33+
struct ConcP<F: P, S: P> : P where F.T == S.T {
34+
var lhs: F
35+
var rhs: S
36+
}
37+
38+
struct Z : P {
39+
}
40+
41+
extension P {
42+
func bar() -> Z { fatalError() }
43+
44+
static func +<T : P>(lhs: Self, rhs: T) -> ConcP<Self, T> {
45+
return ConcP(lhs: lhs, rhs: rhs)
46+
}
47+
}
48+
49+
class Container<V> {
50+
var value: V
51+
init(_ value: V) {
52+
self.value = value
53+
}
54+
}
55+
56+
struct A {
57+
enum Value : CustomStringConvertible {
58+
case foo, bar
59+
60+
var description: String {
61+
switch self {
62+
case .foo: return "foo"
63+
case .bar: return "bar"
64+
}
65+
}
66+
}
67+
68+
var value: Container<Value>
69+
70+
func foo() {
71+
let value = self.value.value
72+
_ = S("A") + S("\(value)").bar() + S("B") // Ok
73+
}
74+
}

0 commit comments

Comments
 (0)