Skip to content

Commit 5fba3d7

Browse files
committed
xxx
1 parent a972094 commit 5fba3d7

File tree

9 files changed

+76
-22
lines changed

9 files changed

+76
-22
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,11 @@ class alignas(1 << TypeAlignInBits) TypeBase
455455
NumProtocols : 16
456456
);
457457

458-
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+28,
458+
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 8+26,
459459
/// Type variable options.
460-
Options : 7,
460+
Options : 8,
461461
/// The unique number assigned to this type variable.
462-
ID : 27
462+
ID : 26
463463
);
464464

465465
SWIFT_INLINE_BITFIELD_FULL(ErrorUnionType, TypeBase, 32,

include/swift/Sema/ConstraintLocator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
238238
/// e.g. `foo[0]` or `\Foo.[0]`
239239
bool isSubscriptMemberRef() const;
240240

241+
bool isClosureParameterType() const;
242+
bool isClosureResultType() const;
243+
241244
/// Determine whether give locator points to the type of the
242245
/// key path expression.
243246
bool isKeyPathType() const;

include/swift/Sema/ConstraintSystem.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ enum TypeVariableOptions {
318318

319319
/// Whether the type variable can be bound only to a pack expansion type.
320320
TVO_PackExpansion = 0x40,
321+
322+
/// Whether the hole for this type variable origates from a different
323+
/// type variable in the equivalence class.
324+
TVO_NonRepresentativeHole = 0x80,
321325
};
322326

323327
enum class KeyPathMutability : uint8_t {
@@ -397,6 +401,8 @@ class TypeVariableType::Implementation {
397401
/// Whether this type variable can bind only to PackExpansionType.
398402
bool isPackExpansion() const { return getRawOptions() & TVO_PackExpansion; }
399403

404+
bool isNonRepresentativeHole() const { return getRawOptions() & TVO_NonRepresentativeHole; }
405+
400406
/// Whether this type variable prefers a subtype binding over a supertype
401407
/// binding.
402408
bool prefersSubtypeBinding() const {
@@ -588,6 +594,12 @@ class TypeVariableType::Implementation {
588594
recordBinding(*trail);
589595
getTypeVariable()->Bits.TypeVariableType.Options &= ~TVO_CanBindToPack;
590596
}
597+
598+
if (!canBindToHole() && otherRep->getImpl().canBindToHole()) {
599+
if (trail)
600+
recordBinding(*trail);
601+
getTypeVariable()->Bits.TypeVariableType.Options |= (TVO_CanBindToHole | TVO_NonRepresentativeHole);
602+
}
591603
}
592604

593605
/// Retrieve the fixed type that corresponds to this type variable,
@@ -701,6 +713,7 @@ class TypeVariableType::Implementation {
701713
ENTRY(TVO_PrefersSubtypeBinding, "");
702714
ENTRY(TVO_CanBindToPack, "pack");
703715
ENTRY(TVO_PackExpansion, "pack expansion");
716+
ENTRY(TVO_NonRepresentativeHole, "non-rep hole");
704717
}
705718
#undef ENTRY
706719
}
@@ -3485,6 +3498,8 @@ class ConstraintSystem {
34853498
getImplicitValueConversionLocator(ConstraintLocatorBuilder root,
34863499
ConversionRestrictionKind restriction);
34873500

3501+
ConstraintLocator *getHoleLocator(TypeVariableType *tv);
3502+
34883503
/// Lookup and return parent associated with given expression.
34893504
Expr *getParentExpr(Expr *expr) {
34903505
if (auto result = getExprDepthAndParent(expr))

lib/Sema/CSBindings.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ bool BindingSet::isDelayed() const {
170170
return true;
171171

172172
if (isHole()) {
173-
auto *locator = TypeVar->getImpl().getLocator();
173+
auto *locator = CS.getHoleLocator(TypeVar);
174174
assert(locator && "a hole without locator?");
175175

176176
// Delay resolution of the code completion expression until
@@ -2735,7 +2735,7 @@ bool TypeVarBindingProducer::computeNext() {
27352735

27362736
std::optional<std::pair<ConstraintFix *, unsigned>>
27372737
TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
2738-
auto *dstLocator = TypeVar->getImpl().getLocator();
2738+
auto *dstLocator = cs.getHoleLocator(TypeVar);
27392739
auto *srcLocator = Binding.getLocator();
27402740

27412741
// FIXME: This check could be turned into an assert once
@@ -2756,7 +2756,7 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
27562756

27572757
unsigned defaultImpact = 1;
27582758

2759-
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
2759+
if (auto *GP = dstLocator->getGenericParameter()) {
27602760
// If it is representative for a key path root, let's emit a more
27612761
// specific diagnostic.
27622762
auto *keyPathRoot =
@@ -2776,12 +2776,12 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
27762776
}
27772777
}
27782778

2779-
if (TypeVar->getImpl().isClosureParameterType()) {
2779+
if (dstLocator->isClosureParameterType()) {
27802780
ConstraintFix *fix = SpecifyClosureParameterType::create(cs, dstLocator);
27812781
return std::make_pair(fix, defaultImpact);
27822782
}
27832783

2784-
if (TypeVar->getImpl().isClosureResultType()) {
2784+
if (dstLocator->isClosureResultType()) {
27852785
auto *closure = castToExpr<ClosureExpr>(dstLocator->getAnchor());
27862786
// If the whole body is being ignored due to a pre-check failure,
27872787
// let's not record a fix about result type since there is

lib/Sema/ConstraintLocator.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,22 @@ bool ConstraintLocator::isSubscriptMemberRef() const {
561561
return path.back().getKind() == ConstraintLocator::SubscriptMember;
562562
}
563563

564+
bool ConstraintLocator::isClosureParameterType() const {
565+
if (!getAnchor())
566+
return false;
567+
568+
return isExpr<ClosureExpr>(getAnchor()) &&
569+
isLastElement<LocatorPathElt::TupleElement>();
570+
}
571+
572+
bool ConstraintLocator::isClosureResultType() const {
573+
if (!getAnchor())
574+
return false;
575+
576+
return isExpr<ClosureExpr>(getAnchor()) &&
577+
isLastElement<LocatorPathElt::ClosureResult>();
578+
}
579+
564580
bool ConstraintLocator::isKeyPathType() const {
565581
auto anchor = getAnchor();
566582
auto path = getPath();

lib/Sema/ConstraintSystem.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,26 @@ ConstraintLocator *ConstraintSystem::getOpenOpaqueLocator(
904904
{ LocatorPathElt::OpenedOpaqueArchetype(opaqueDecl) }, 0);
905905
}
906906

907+
ConstraintLocator *ConstraintSystem::getHoleLocator(TypeVariableType *tv) {
908+
if (!tv->getImpl().isNonRepresentativeHole())
909+
return tv->getImpl().getLocator();
910+
911+
// If we have a non-representative hole, the actual locator is given by
912+
// a member of its equivalence class. Pick the the one with the lowest ID to
913+
// ensure consistency.
914+
TypeVariableType *candidate = nullptr;
915+
for (auto equiv : CG[tv].getEquivalenceClass()) {
916+
if (equiv == tv || !equiv->getImpl().canBindToHole())
917+
continue;
918+
919+
if (!candidate || candidate->getID() > equiv->getID())
920+
candidate = equiv;
921+
}
922+
ASSERT(candidate &&
923+
"Non-representative hole ought to have hole in its equivalence class");
924+
return candidate->getImpl().getLocator();
925+
}
926+
907927
std::pair<Type, ExistentialArchetypeType *>
908928
ConstraintSystem::openAnyExistentialType(Type type,
909929
ConstraintLocator *locator) {
@@ -5284,7 +5304,7 @@ TypeVarBindingProducer::TypeVarBindingProducer(BindingSet &bindings)
52845304
bindings.getTypeVariable()->getImpl().getLocator()),
52855305
TypeVar(bindings.getTypeVariable()), CanBeNil(bindings.canBeNil()) {
52865306
if (bindings.isDirectHole()) {
5287-
auto *locator = getLocator();
5307+
auto *locator = CS.getHoleLocator(TypeVar);
52885308
// If this type variable is associated with a code completion token
52895309
// and it failed to infer any bindings let's adjust holes's locator
52905310
// to point to a code completion token to avoid attempting to "fix"

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,11 @@ bool TypeVariableType::Implementation::isTapType() const {
119119
}
120120

121121
bool TypeVariableType::Implementation::isClosureParameterType() const {
122-
if (!(locator && locator->getAnchor()))
123-
return false;
124-
125-
return isExpr<ClosureExpr>(locator->getAnchor()) &&
126-
locator->isLastElement<LocatorPathElt::TupleElement>();
122+
return locator && locator->isClosureParameterType();
127123
}
128124

129125
bool TypeVariableType::Implementation::isClosureResultType() const {
130-
if (!(locator && locator->getAnchor()))
131-
return false;
132-
133-
return isExpr<ClosureExpr>(locator->getAnchor()) &&
134-
locator->isLastElement<LocatorPathElt::ClosureResult>();
126+
return locator && locator->isClosureResultType();
135127
}
136128

137129
bool TypeVariableType::Implementation::isKeyPathType() const {

test/Constraints/diagnostics.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,3 +1578,13 @@ func testAddMemberVsRemoveCall() {
15781578
let b = Foo_74617()
15791579
let c = (a + b).bar() // expected-error {{cannot call value of non-function type 'Float'}} {{22-24=}}
15801580
}
1581+
1582+
func testArrayLiteralMetatypeMismatch() {
1583+
// Make sure we can correctly turn 'T' into a hole here.
1584+
func foo<T>(_ xs: T.Type, _: Int) -> T {} // expected-note {{in call to function 'foo'}}
1585+
func foo(_ i: Int) {}
1586+
let x = foo([], i)
1587+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
1588+
// expected-error@-2 {{cannot convert value of type '[Any]' to expected argument type '_.Type'}}
1589+
// FIXME: The above should say `T.Type` not `_.Type` ^
1590+
}

test/Constraints/rdar45511837.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ class Foo<Bar: NSObject> {
1818

1919
lazy var foo: () -> Void = {
2020
// TODO: improve diagnostic message
21-
_ = self.foobar + nil // expected-error {{'Bar' is not convertible to 'String'}}
22-
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
23-
// expected-error@-2 {{'nil' is not compatible with expected argument type 'String'}}
21+
_ = self.foobar + nil // expected-error {{generic parameter 'Self' could not be inferred}}
2422
}
2523
}

0 commit comments

Comments
 (0)