Skip to content

Commit 225d87a

Browse files
committed
[CSBindings] NFC: Simplify TypeVariableBinding::attempt but extracting fix computation
Add a separate method `fixForHole` on `TypeVariableBinding` responsible for determining whether fix is required and if so, what kind of fix to apply when a particular type variable is resolved to a hole.
1 parent 4d0ab13 commit 225d87a

File tree

2 files changed

+78
-48
lines changed

2 files changed

+78
-48
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 73 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,77 @@ bool TypeVarBindingProducer::computeNext() {
12171217
return true;
12181218
}
12191219

1220+
Optional<std::pair<ConstraintFix *, unsigned>>
1221+
TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
1222+
auto *dstLocator = TypeVar->getImpl().getLocator();
1223+
auto *srcLocator = Binding.getLocator();
1224+
1225+
unsigned defaultImpact = 1;
1226+
1227+
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
1228+
// If it is represetative for a key path root, let's emit a more
1229+
// specific diagnostic.
1230+
auto *keyPathRoot =
1231+
cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot);
1232+
if (keyPathRoot) {
1233+
ConstraintFix *fix = SpecifyKeyPathRootType::create(
1234+
cs, keyPathRoot->getImpl().getLocator());
1235+
return std::make_pair(fix, defaultImpact);
1236+
} else {
1237+
auto path = dstLocator->getPath();
1238+
// Drop `generic parameter` locator element so that all missing
1239+
// generic parameters related to the same path can be coalesced later.
1240+
ConstraintFix *fix = DefaultGenericArgument::create(
1241+
cs, GP,
1242+
cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back()));
1243+
return std::make_pair(fix, defaultImpact);
1244+
}
1245+
}
1246+
1247+
if (TypeVar->getImpl().isClosureParameterType()) {
1248+
ConstraintFix *fix = SpecifyClosureParameterType::create(cs, dstLocator);
1249+
return std::make_pair(fix, defaultImpact);
1250+
}
1251+
1252+
if (TypeVar->getImpl().isClosureResultType()) {
1253+
auto *closure = castToExpr<ClosureExpr>(dstLocator->getAnchor());
1254+
// If the whole body is being ignored due to a pre-check failure,
1255+
// let's not record a fix about result type since there is
1256+
// just not enough context to infer it without a body.
1257+
if (cs.hasFixFor(cs.getConstraintLocator(closure->getBody()),
1258+
FixKind::IgnoreInvalidFunctionBuilderBody))
1259+
return None;
1260+
1261+
ConstraintFix *fix = SpecifyClosureReturnType::create(cs, dstLocator);
1262+
return std::make_pair(fix, defaultImpact);
1263+
}
1264+
1265+
if (srcLocator->directlyAt<ObjectLiteralExpr>()) {
1266+
ConstraintFix *fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator);
1267+
return std::make_pair(fix, defaultImpact);
1268+
}
1269+
1270+
if (srcLocator->isKeyPathRoot()) {
1271+
// If we recorded an invalid key path fix, let's skip this specify root
1272+
// type fix because it wouldn't produce a useful diagnostic.
1273+
auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor());
1274+
if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents))
1275+
return None;
1276+
1277+
ConstraintFix *fix = SpecifyKeyPathRootType::create(cs, dstLocator);
1278+
return std::make_pair(fix, defaultImpact);
1279+
}
1280+
1281+
if (dstLocator->directlyAt<NilLiteralExpr>()) {
1282+
// This is a dramatic event, it means that there is absolutely
1283+
// no contextual information to resolve type of `nil`.
1284+
ConstraintFix *fix = SpecifyContextualTypeForNil::create(cs, dstLocator);
1285+
return std::make_pair(fix, /*impact=*/(unsigned)10);
1286+
}
1287+
1288+
return None;
1289+
}
1290+
12201291
bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
12211292
auto type = Binding.BindingType;
12221293
auto *srcLocator = Binding.getLocator();
@@ -1238,56 +1309,10 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
12381309
// resolved and had to be bound to a placeholder "hole" type.
12391310
cs.increaseScore(SK_Hole);
12401311

1241-
ConstraintFix *fix = nullptr;
1242-
unsigned fixImpact = 1;
1243-
1244-
if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
1245-
// If it is represetative for a key path root, let's emit a more
1246-
// specific diagnostic.
1247-
auto *keyPathRoot =
1248-
cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot);
1249-
if (keyPathRoot) {
1250-
fix = SpecifyKeyPathRootType::create(
1251-
cs, keyPathRoot->getImpl().getLocator());
1252-
} else {
1253-
auto path = dstLocator->getPath();
1254-
// Drop `generic parameter` locator element so that all missing
1255-
// generic parameters related to the same path can be coalesced later.
1256-
fix = DefaultGenericArgument::create(
1257-
cs, GP,
1258-
cs.getConstraintLocator(dstLocator->getAnchor(),
1259-
path.drop_back()));
1260-
}
1261-
} else if (TypeVar->getImpl().isClosureParameterType()) {
1262-
fix = SpecifyClosureParameterType::create(cs, dstLocator);
1263-
} else if (TypeVar->getImpl().isClosureResultType()) {
1264-
auto *locator = TypeVar->getImpl().getLocator();
1265-
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());
1266-
// If the whole body is being ignored due to a pre-check failure,
1267-
// let's not record a fix about result type since there is
1268-
// just not enough context to infer it without a body.
1269-
if (!cs.hasFixFor(cs.getConstraintLocator(closure->getBody()),
1270-
FixKind::IgnoreInvalidFunctionBuilderBody))
1271-
fix = SpecifyClosureReturnType::create(cs, dstLocator);
1272-
} else if (srcLocator->directlyAt<ObjectLiteralExpr>()) {
1273-
fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator);
1274-
} else if (srcLocator->isKeyPathRoot()) {
1275-
// If we recorded an invalid key path fix, let's skip this specify root
1276-
// type fix because it wouldn't produce a useful diagnostic.
1277-
auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor());
1278-
if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents))
1312+
if (auto fix = fixForHole(cs)) {
1313+
if (cs.recordFix(/*fix=*/fix->first, /*impact=*/fix->second))
12791314
return true;
1280-
1281-
fix = SpecifyKeyPathRootType::create(cs, dstLocator);
1282-
} else if (dstLocator->directlyAt<NilLiteralExpr>()) {
1283-
fix = SpecifyContextualTypeForNil::create(cs, dstLocator);
1284-
// This is a dramatic event, it means that there is absolutely
1285-
// no contextual information to resolve type of `nil`.
1286-
fixImpact = 10;
12871315
}
1288-
1289-
if (fix && cs.recordFix(fix, fixImpact))
1290-
return true;
12911316
}
12921317
}
12931318

lib/Sema/ConstraintSystem.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5632,6 +5632,11 @@ class TypeVariableBinding {
56325632

56335633
bool attempt(ConstraintSystem &cs) const;
56345634

5635+
/// Determine what fix (if any) needs to be introduced into a
5636+
/// constraint system as part of resolving type variable as a hole.
5637+
Optional<std::pair<ConstraintFix *, unsigned>>
5638+
fixForHole(ConstraintSystem &cs) const;
5639+
56355640
void print(llvm::raw_ostream &Out, SourceManager *) const {
56365641
PrintOptions PO;
56375642
PO.PrintTypesForDebugging = true;

0 commit comments

Comments
 (0)