Skip to content

Commit ffa4996

Browse files
committed
[ConstraintSystem] Mark generic parameter bindings as potentially incomplete by default
This helps to postpone attempting bindings related to generic parameters with all else being equal. Consider situation when function has class requirement on its generic parameter. Without such requirement solver would infer sub-class for `T`. But currently when requirement is present base class is inferred instead, because when bindings for such generic parameter are attempted early single available binding at that point comes from the requirement. ```swift class BaseClass {} class SubClass: BaseClass {} struct Box<T> { init(_: T.Type) {} } func test<T: BaseClass>(box: Box<T>) -> T.Type { return T.self } test(box: .init(SubClass.self)) // `T` expected to be `SubClass` ``` Resolves: [SR-9626](https://bugs.swift.org/browse/SR-9626) Resolves: rdar://problem/47324309
1 parent 5b6c008 commit ffa4996

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lib/Sema/ConstraintSystem.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2871,7 +2871,8 @@ class ConstraintSystem {
28712871
/// A set of all constraints which contribute to pontential bindings.
28722872
llvm::SmallPtrSet<Constraint *, 8> Sources;
28732873

2874-
PotentialBindings(TypeVariableType *typeVar) : TypeVar(typeVar) {}
2874+
PotentialBindings(TypeVariableType *typeVar)
2875+
: TypeVar(typeVar), PotentiallyIncomplete(isGenericParameter()) {}
28752876

28762877
/// Determine whether the set of bindings is non-empty.
28772878
explicit operator bool() const { return !Bindings.empty(); }
@@ -2937,6 +2938,16 @@ class ConstraintSystem {
29372938
/// Check if this binding is viable for inclusion in the set.
29382939
bool isViable(PotentialBinding &binding) const;
29392940

2941+
bool isGenericParameter() const {
2942+
if (auto *locator = TypeVar->getImpl().getLocator()) {
2943+
auto path = locator->getPath();
2944+
return path.empty() ? false
2945+
: path.back().getKind() ==
2946+
ConstraintLocator::GenericParameter;
2947+
}
2948+
return false;
2949+
}
2950+
29402951
void dump(llvm::raw_ostream &out,
29412952
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
29422953
out.indent(indent);

test/Constraints/sr9626.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
2+
3+
class BaseClass {}
4+
class SubClass: BaseClass {}
5+
struct Box<T> { init(_: T.Type) {} }
6+
7+
8+
func test1<T>(box: Box<T>) -> T.Type {
9+
return T.self
10+
}
11+
12+
func test2<T: BaseClass>(box: Box<T>) -> T.Type {
13+
return T.self
14+
}
15+
16+
// CHECK: [[F1:%.*]] = function_ref @$s6sr96263BoxVyACyxGxmcfC
17+
// CHECK-NEXT: apply [[F1]]<SubClass>({{.*}}, {{.*}})
18+
_ = test1(box: .init(SubClass.self))
19+
20+
// CHECK: [[F2:%.*]] = function_ref @$s6sr96265test23boxxmAA3BoxVyxG_tAA9BaseClassCRbzlF
21+
// CHECK-NEXT: apply [[F2]]<SubClass>({{.*}})
22+
_ = test2(box: .init(SubClass.self))

0 commit comments

Comments
 (0)