Skip to content

Commit 5e399b9

Browse files
authored
Merge pull request swiftlang#34118 from xedin/no-fix-for-code-completion
[CSBindings] If hole originates from code completion token avoid "fixing" it
2 parents a73a808 + a6c44bf commit 5e399b9

File tree

3 files changed

+49
-12
lines changed

3 files changed

+49
-12
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ using namespace swift;
2222
using namespace constraints;
2323

2424
void ConstraintSystem::PotentialBindings::inferTransitiveBindings(
25-
const ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &existingTypes,
25+
ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &existingTypes,
2626
const llvm::SmallDenseMap<TypeVariableType *,
2727
ConstraintSystem::PotentialBindings>
2828
&inferredBindings) {
@@ -144,7 +144,7 @@ isUnviableDefaultType(Type defaultType,
144144
}
145145

146146
void ConstraintSystem::PotentialBindings::inferDefaultTypes(
147-
const ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &existingTypes) {
147+
ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &existingTypes) {
148148
auto isDirectRequirement = [&](Constraint *constraint) -> bool {
149149
if (auto *typeVar = constraint->getFirstType()->getAs<TypeVariableType>()) {
150150
auto *repr = cs.getRepresentative(typeVar);
@@ -300,7 +300,7 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
300300
}
301301

302302
void ConstraintSystem::PotentialBindings::finalize(
303-
const ConstraintSystem &cs,
303+
ConstraintSystem &cs,
304304
const llvm::SmallDenseMap<TypeVariableType *,
305305
ConstraintSystem::PotentialBindings>
306306
&inferredBindings) {
@@ -377,6 +377,15 @@ void ConstraintSystem::PotentialBindings::finalize(
377377
PotentiallyIncomplete = true;
378378
}
379379

380+
// If this type variable is associated with a code completion token
381+
// and it failed to infer any bindings let's adjust hole's locator
382+
// to point to a code completion token to avoid attempting to "fix"
383+
// this problem since its rooted in the fact that constraint system
384+
// is under-constrained.
385+
if (AssociatedCodeCompletionToken) {
386+
locator = cs.getConstraintLocator(AssociatedCodeCompletionToken);
387+
}
388+
380389
addPotentialBinding(PotentialBinding::forHole(TypeVar, locator));
381390
}
382391

@@ -620,8 +629,7 @@ bool ConstraintSystem::PotentialBindings::favoredOverDisjunction(
620629
}
621630

622631
ConstraintSystem::PotentialBindings
623-
ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar,
624-
bool finalize) const {
632+
ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar, bool finalize) {
625633
assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar &&
626634
"not a representative");
627635
assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type");
@@ -769,6 +777,18 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
769777

770778
result.InvolvesTypeVariables = true;
771779

780+
// If current type variable is associated with a code completion token
781+
// it's possible that it doesn't have enough contextual information
782+
// to be resolved to anything, so let's note that fact in the potential
783+
// bindings and use it when forming a hole if there are no other bindings
784+
// available.
785+
if (auto *locator = bindingTypeVar->getImpl().getLocator()) {
786+
if (locator->directlyAt<CodeCompletionExpr>()) {
787+
result.AssociatedCodeCompletionToken = locator->getAnchor();
788+
result.PotentiallyIncomplete = true;
789+
}
790+
}
791+
772792
if (constraint->getKind() == ConstraintKind::Subtype &&
773793
kind == AllowedBindingKind::Subtypes) {
774794
result.SubtypeOf.insert(bindingTypeVar);
@@ -829,7 +849,7 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
829849
/// representative type variable, along with flags indicating whether
830850
/// those types should be opened.
831851
bool ConstraintSystem::PotentialBindings::infer(
832-
const ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &exactTypes,
852+
ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &exactTypes,
833853
Constraint *constraint) {
834854
switch (constraint->getKind()) {
835855
case ConstraintKind::Bind:
@@ -1222,6 +1242,21 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
12221242
auto *dstLocator = TypeVar->getImpl().getLocator();
12231243
auto *srcLocator = Binding.getLocator();
12241244

1245+
// FIXME: This check could be turned into an assert once
1246+
// all code completion kinds are ported to use
1247+
// `TypeChecker::typeCheckForCodeCompletion` API.
1248+
if (cs.isForCodeCompletion()) {
1249+
// If the hole is originated from code completion expression
1250+
// let's not try to fix this, anything connected to a
1251+
// code completion is allowed to be a hole because presence
1252+
// of a code completion token makes constraint system
1253+
// under-constrained due to e.g. lack of expressions on the
1254+
// right-hand side of the token, which are required for a
1255+
// regular type-check.
1256+
if (dstLocator->directlyAt<CodeCompletionExpr>())
1257+
return None;
1258+
}
1259+
12251260
unsigned defaultImpact = 1;
12261261

12271262
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {

lib/Sema/ConstraintSystem.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4644,6 +4644,8 @@ class ConstraintSystem {
46444644
/// `bind param` are present in the system.
46454645
bool PotentiallyIncomplete = false;
46464646

4647+
ASTNode AssociatedCodeCompletionToken = ASTNode();
4648+
46474649
/// Whether this type variable has literal bindings.
46484650
LiteralBindingKind LiteralBinding = LiteralBindingKind::None;
46494651

@@ -4775,25 +4777,25 @@ class ConstraintSystem {
47754777
/// \param inferredBindings The set of all bindings inferred for type
47764778
/// variables in the workset.
47774779
void inferTransitiveBindings(
4778-
const ConstraintSystem &cs,
4780+
ConstraintSystem &cs,
47794781
llvm::SmallPtrSetImpl<CanType> &existingTypes,
47804782
const llvm::SmallDenseMap<TypeVariableType *,
47814783
ConstraintSystem::PotentialBindings>
47824784
&inferredBindings);
47834785

47844786
/// Infer bindings based on any protocol conformances that have default
47854787
/// types.
4786-
void inferDefaultTypes(const ConstraintSystem &cs,
4788+
void inferDefaultTypes(ConstraintSystem &cs,
47874789
llvm::SmallPtrSetImpl<CanType> &existingTypes);
47884790

47894791
public:
4790-
bool infer(const ConstraintSystem &cs,
4792+
bool infer(ConstraintSystem &cs,
47914793
llvm::SmallPtrSetImpl<CanType> &exactTypes,
47924794
Constraint *constraint);
47934795

47944796
/// Finalize binding computation for this type variable by
47954797
/// inferring bindings from context e.g. transitive bindings.
4796-
void finalize(const ConstraintSystem &cs,
4798+
void finalize(ConstraintSystem &cs,
47974799
const llvm::SmallDenseMap<TypeVariableType *,
47984800
ConstraintSystem::PotentialBindings>
47994801
&inferredBindings);
@@ -4862,7 +4864,7 @@ class ConstraintSystem {
48624864
/// Infer bindings for the given type variable based on current
48634865
/// state of the constraint system.
48644866
PotentialBindings inferBindingsFor(TypeVariableType *typeVar,
4865-
bool finalize = true) const;
4867+
bool finalize = true);
48664868

48674869
private:
48684870
Optional<ConstraintSystem::PotentialBinding>

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2991,7 +2991,7 @@ void ConstraintSystem::print(raw_ostream &out) const {
29912991
out << " as ";
29922992
Type(fixed).print(out, PO);
29932993
} else {
2994-
inferBindingsFor(tv).dump(out, 1);
2994+
const_cast<ConstraintSystem *>(this)->inferBindingsFor(tv).dump(out, 1);
29952995
}
29962996
} else {
29972997
out << " equivalent to ";

0 commit comments

Comments
 (0)