Skip to content

Commit a243831

Browse files
committed
[unittest/Sema] Add a test-case for a single hop protocol requirement inference
In situations like: `$T0 <convertible> $T1` `$T1 <conforms to> P` `$T0` should know about `P` as a transitive protocol requirement.
1 parent 1aecea1 commit a243831

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

unittests/Sema/BindingInferenceTests.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "SemaFixture.h"
1414
#include "swift/AST/Expr.h"
1515
#include "swift/Sema/ConstraintSystem.h"
16+
#include "llvm/ADT/SmallPtrSet.h"
1617

1718
using namespace swift;
1819
using namespace swift::unittest;
@@ -44,3 +45,44 @@ TEST_F(SemaTest, TestIntLiteralBindingInference) {
4445
ASSERT_TRUE(binding.BindingType->isEqual(getStdlibType("Int")));
4546
ASSERT_TRUE(binding.hasDefaultedLiteralProtocol());
4647
}
48+
49+
TEST_F(SemaTest, TestTransitiveProtocolInference) {
50+
ConstraintSystemOptions options;
51+
ConstraintSystem cs(DC, options);
52+
53+
auto *PD1 =
54+
new (Context) ProtocolDecl(DC, SourceLoc(), SourceLoc(),
55+
Context.getIdentifier("P1"), /*Inherited=*/{},
56+
/*trailingWhere=*/nullptr);
57+
PD1->setImplicit();
58+
59+
auto *protocolTy1 = ProtocolType::get(PD1, Type(), Context);
60+
61+
auto *GPT = cs.createTypeVariable(cs.getConstraintLocator({}),
62+
/*options=*/TVO_CanBindToNoEscape);
63+
64+
cs.addConstraint(
65+
ConstraintKind::ConformsTo, GPT, protocolTy1,
66+
cs.getConstraintLocator({}, LocatorPathElt::TypeParameterRequirement(
67+
0, RequirementKind::Conformance)));
68+
69+
// First, let's try inferring through a single conversion
70+
// relationship.
71+
{
72+
auto *typeVar = cs.createTypeVariable(cs.getConstraintLocator({}),
73+
/*options=*/0);
74+
75+
cs.addConstraint(
76+
ConstraintKind::Conversion, typeVar, GPT,
77+
cs.getConstraintLocator({}, LocatorPathElt::ContextualType()));
78+
79+
auto bindings = inferBindings(cs, typeVar);
80+
ASSERT_TRUE(bindings.Protocols.empty());
81+
82+
const auto &inferredProtocols = bindings.TransitiveProtocols;
83+
ASSERT_TRUE(bool(inferredProtocols));
84+
ASSERT_EQ(inferredProtocols->size(), (unsigned)1);
85+
ASSERT_TRUE(
86+
(*inferredProtocols->begin())->getSecondType()->isEqual(protocolTy1));
87+
}
88+
}

0 commit comments

Comments
 (0)