Skip to content

Commit 962c25f

Browse files
committed
Begin refactoring type variable binding code.
Move all the code specific to dealing with relational constraints out into a separate function. I expect to do more refactoring here so this is likely not the final form for this code - just one step in the direction of breaking things down into smaller logical pieces.
1 parent 2608726 commit 962c25f

File tree

2 files changed

+159
-131
lines changed

2 files changed

+159
-131
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 149 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,135 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
197197
Bindings.push_back(std::move(binding));
198198
}
199199

200+
Optional<ConstraintSystem::PotentialBinding>
201+
ConstraintSystem::getPotentialBindingForRelationalConstraint(
202+
PotentialBindings &result, Constraint *constraint,
203+
bool &hasDependentMemberRelationalConstraints,
204+
bool &hasNonDependentMemberRelationalConstraints,
205+
bool &addOptionalSupertypeBindings) {
206+
assert(constraint->getClassification() ==
207+
ConstraintClassification::Relational &&
208+
"only relational constraints handled here");
209+
210+
auto *typeVar = result.TypeVar;
211+
212+
// Record constraint which contributes to the
213+
// finding of potential bindings.
214+
result.Sources.insert(constraint);
215+
216+
auto first = simplifyType(constraint->getFirstType());
217+
auto second = simplifyType(constraint->getSecondType());
218+
219+
if (first->is<TypeVariableType>() && first->isEqual(second))
220+
return None;
221+
222+
Type type;
223+
AllowedBindingKind kind;
224+
if (first->getAs<TypeVariableType>() == typeVar) {
225+
// Upper bound for this type variable.
226+
type = second;
227+
kind = AllowedBindingKind::Subtypes;
228+
} else if (second->getAs<TypeVariableType>() == typeVar) {
229+
// Lower bound for this type variable.
230+
type = first;
231+
kind = AllowedBindingKind::Supertypes;
232+
} else {
233+
// Can't infer anything.
234+
if (result.InvolvesTypeVariables)
235+
return None;
236+
237+
// Check whether both this type and another type variable are
238+
// inferable.
239+
SmallPtrSet<TypeVariableType *, 4> typeVars;
240+
findInferableTypeVars(first, typeVars);
241+
findInferableTypeVars(second, typeVars);
242+
if (typeVars.size() > 1 && typeVars.count(typeVar))
243+
result.InvolvesTypeVariables = true;
244+
return None;
245+
}
246+
247+
// Do not attempt to bind to ErrorType.
248+
if (type->hasError())
249+
return None;
250+
251+
// If the source of the binding is 'OptionalObject' constraint
252+
// and type variable is on the left-hand side, that means
253+
// that it _has_ to be of optional type, since the right-hand
254+
// side of the constraint is object type of the optional.
255+
if (constraint->getKind() == ConstraintKind::OptionalObject &&
256+
kind == AllowedBindingKind::Subtypes) {
257+
type = OptionalType::get(type);
258+
}
259+
260+
// If the type we'd be binding to is a dependent member, don't try to
261+
// resolve this type variable yet.
262+
if (type->is<DependentMemberType>()) {
263+
if (!ConstraintSystem::typeVarOccursInType(typeVar, type,
264+
&result.InvolvesTypeVariables)) {
265+
hasDependentMemberRelationalConstraints = true;
266+
}
267+
return None;
268+
}
269+
hasNonDependentMemberRelationalConstraints = true;
270+
271+
// Check whether we can perform this binding.
272+
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
273+
bool isNilLiteral = false;
274+
bool *isNilLiteralPtr = nullptr;
275+
if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes)
276+
isNilLiteralPtr = &isNilLiteral;
277+
if (auto boundType = checkTypeOfBinding(typeVar, type, isNilLiteralPtr)) {
278+
type = *boundType;
279+
if (type->hasTypeVariable())
280+
result.InvolvesTypeVariables = true;
281+
} else {
282+
// If the bound is a 'nil' literal type, add optional supertype bindings.
283+
if (isNilLiteral) {
284+
addOptionalSupertypeBindings = true;
285+
return None;
286+
}
287+
288+
result.InvolvesTypeVariables = true;
289+
return None;
290+
}
291+
292+
// Don't deduce autoclosure types or single-element, non-variadic
293+
// tuples.
294+
if (shouldBindToValueType(constraint)) {
295+
if (auto funcTy = type->getAs<FunctionType>()) {
296+
if (funcTy->isAutoClosure())
297+
type = funcTy->getResult();
298+
}
299+
300+
type = type->getWithoutImmediateLabel();
301+
}
302+
303+
// Make sure we aren't trying to equate type variables with different
304+
// lvalue-binding rules.
305+
if (auto otherTypeVar =
306+
type->lookThroughAllOptionalTypes()->getAs<TypeVariableType>()) {
307+
if (typeVar->getImpl().canBindToLValue() !=
308+
otherTypeVar->getImpl().canBindToLValue())
309+
return None;
310+
}
311+
312+
// BindParam constraints are not reflexive and must be treated specially.
313+
if (constraint->getKind() == ConstraintKind::BindParam) {
314+
if (kind == AllowedBindingKind::Subtypes) {
315+
if (auto *lvt = type->getAs<LValueType>()) {
316+
type = InOutType::get(lvt->getObjectType());
317+
}
318+
} else if (kind == AllowedBindingKind::Supertypes) {
319+
if (auto *iot = type->getAs<InOutType>()) {
320+
type = LValueType::get(iot->getObjectType());
321+
}
322+
}
323+
kind = AllowedBindingKind::Exact;
324+
}
325+
326+
return PotentialBinding{type, kind, constraint->getKind()};
327+
}
328+
200329
/// \brief Retrieve the set of potential type bindings for the given
201330
/// representative type variable, along with flags indicating whether
202331
/// those types should be opened.
@@ -238,9 +367,19 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
238367
case ConstraintKind::ArgumentTupleConversion:
239368
case ConstraintKind::OperatorArgumentTupleConversion:
240369
case ConstraintKind::OperatorArgumentConversion:
241-
case ConstraintKind::OptionalObject:
242-
// Relational constraints: break out to look for types above/below.
370+
case ConstraintKind::OptionalObject: {
371+
auto binding = getPotentialBindingForRelationalConstraint(
372+
result, constraint, hasDependentMemberRelationalConstraints,
373+
hasNonDependentMemberRelationalConstraints,
374+
addOptionalSupertypeBindings);
375+
if (!binding)
376+
break;
377+
378+
auto type = binding->BindingType;
379+
if (exactTypes.insert(type->getCanonicalType()).second)
380+
result.addPotentialBinding(*binding);
243381
break;
382+
}
244383

245384
case ConstraintKind::BridgingConversion:
246385
case ConstraintKind::CheckedCast:
@@ -249,7 +388,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
249388
case ConstraintKind::KeyPath:
250389
case ConstraintKind::KeyPathApplication:
251390
// Constraints from which we can't do anything.
252-
continue;
391+
break;
253392

254393
case ConstraintKind::DynamicTypeOf: {
255394
// Direct binding of the left-hand side could result
@@ -264,7 +403,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
264403
}
265404

266405
// This is right-hand side, let's continue.
267-
continue;
406+
break;
268407
}
269408

270409
case ConstraintKind::Defaultable:
@@ -274,13 +413,13 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
274413
defaultableConstraints.push_back(constraint);
275414
hasNonDependentMemberRelationalConstraints = true;
276415
}
277-
continue;
416+
break;
278417

279418
case ConstraintKind::Disjunction:
280419
// FIXME: Recurse into these constraints to see whether this
281420
// type variable is fully bound by any of them.
282421
result.InvolvesTypeVariables = true;
283-
continue;
422+
break;
284423

285424
case ConstraintKind::ConformsTo:
286425
case ConstraintKind::SelfObjectOfProtocol:
@@ -350,7 +489,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
350489
constraint->getProtocol()});
351490
}
352491

353-
continue;
492+
break;
354493
}
355494

356495
case ConstraintKind::ApplicableFunction:
@@ -373,7 +512,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
373512
typeVars);
374513
if (typeVars.size() > 1 && typeVars.count(typeVar))
375514
result.InvolvesTypeVariables = true;
376-
continue;
515+
516+
break;
377517
}
378518

379519
case ConstraintKind::ValueMember:
@@ -395,130 +535,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
395535
&result.InvolvesTypeVariables)) {
396536
result.FullyBound = true;
397537
}
398-
continue;
399-
}
400-
401-
// Handle relational constraints.
402-
assert(constraint->getClassification() ==
403-
ConstraintClassification::Relational &&
404-
"only relational constraints handled here");
405-
406-
// Record constraint which contributes to the
407-
// finding of pontential bindings.
408-
result.Sources.insert(constraint);
409-
410-
auto first = simplifyType(constraint->getFirstType());
411-
auto second = simplifyType(constraint->getSecondType());
412-
413-
if (first->is<TypeVariableType>() && first->isEqual(second))
414-
continue;
415-
416-
Type type;
417-
AllowedBindingKind kind;
418-
if (first->getAs<TypeVariableType>() == typeVar) {
419-
// Upper bound for this type variable.
420-
type = second;
421-
kind = AllowedBindingKind::Subtypes;
422-
} else if (second->getAs<TypeVariableType>() == typeVar) {
423-
// Lower bound for this type variable.
424-
type = first;
425-
kind = AllowedBindingKind::Supertypes;
426-
} else {
427-
// Can't infer anything.
428-
if (result.InvolvesTypeVariables)
429-
continue;
430-
431-
// Check whether both this type and another type variable are
432-
// inferable.
433-
SmallPtrSet<TypeVariableType *, 4> typeVars;
434-
findInferableTypeVars(first, typeVars);
435-
findInferableTypeVars(second, typeVars);
436-
if (typeVars.size() > 1 && typeVars.count(typeVar))
437-
result.InvolvesTypeVariables = true;
438-
continue;
439-
}
440-
441-
// Do not attempt to bind to ErrorType.
442-
if (type->hasError())
443-
continue;
444-
445-
// If the source of the binding is 'OptionalObject' constraint
446-
// and type variable is on the left-hand side, that means
447-
// that it _has_ to be of optional type, since the right-hand
448-
// side of the constraint is object type of the optional.
449-
if (constraint->getKind() == ConstraintKind::OptionalObject &&
450-
kind == AllowedBindingKind::Subtypes) {
451-
type = OptionalType::get(type);
452-
}
453-
454-
// If the type we'd be binding to is a dependent member, don't try to
455-
// resolve this type variable yet.
456-
if (type->is<DependentMemberType>()) {
457-
if (!ConstraintSystem::typeVarOccursInType(
458-
typeVar, type, &result.InvolvesTypeVariables)) {
459-
hasDependentMemberRelationalConstraints = true;
460-
}
461-
continue;
462-
}
463-
hasNonDependentMemberRelationalConstraints = true;
464-
465-
// Check whether we can perform this binding.
466-
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
467-
bool isNilLiteral = false;
468-
bool *isNilLiteralPtr = nullptr;
469-
if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes)
470-
isNilLiteralPtr = &isNilLiteral;
471-
if (auto boundType = checkTypeOfBinding(typeVar, type, isNilLiteralPtr)) {
472-
type = *boundType;
473-
if (type->hasTypeVariable())
474-
result.InvolvesTypeVariables = true;
475-
} else {
476-
// If the bound is a 'nil' literal type, add optional supertype bindings.
477-
if (isNilLiteral) {
478-
addOptionalSupertypeBindings = true;
479-
continue;
480-
}
481-
482-
result.InvolvesTypeVariables = true;
483-
continue;
484-
}
485-
486-
// Don't deduce autoclosure types or single-element, non-variadic
487-
// tuples.
488-
if (shouldBindToValueType(constraint)) {
489-
if (auto funcTy = type->getAs<FunctionType>()) {
490-
if (funcTy->isAutoClosure())
491-
type = funcTy->getResult();
492-
}
493-
494-
type = type->getWithoutImmediateLabel();
495-
}
496-
497-
// Make sure we aren't trying to equate type variables with different
498-
// lvalue-binding rules.
499-
if (auto otherTypeVar =
500-
type->lookThroughAllOptionalTypes()->getAs<TypeVariableType>()) {
501-
if (typeVar->getImpl().canBindToLValue() !=
502-
otherTypeVar->getImpl().canBindToLValue())
503-
continue;
504-
}
505-
506-
// BindParam constraints are not reflexive and must be treated specially.
507-
if (constraint->getKind() == ConstraintKind::BindParam) {
508-
if (kind == AllowedBindingKind::Subtypes) {
509-
if (auto *lvt = type->getAs<LValueType>()) {
510-
type = InOutType::get(lvt->getObjectType());
511-
}
512-
} else if (kind == AllowedBindingKind::Supertypes) {
513-
if (auto *iot = type->getAs<InOutType>()) {
514-
type = LValueType::get(iot->getObjectType());
515-
}
516-
}
517-
kind = AllowedBindingKind::Exact;
538+
break;
518539
}
519-
520-
if (exactTypes.insert(type->getCanonicalType()).second)
521-
result.addPotentialBinding({type, kind, constraint->getKind()});
522540
}
523541

524542
// If we have any literal constraints, check whether there is already a

lib/Sema/ConstraintSystem.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2866,6 +2866,16 @@ class ConstraintSystem {
28662866
Optional<Type> checkTypeOfBinding(TypeVariableType *typeVar, Type type,
28672867
bool *isNilLiteral = nullptr);
28682868
Optional<PotentialBindings> determineBestBindings();
2869+
Optional<ConstraintSystem::PotentialBinding>
2870+
getPotentialBindingForRelationalConstraint(
2871+
PotentialBindings &result, Constraint *constraint,
2872+
bool &hasDependentMemberRelationalConstraints,
2873+
bool &hasNonDependentMemberRelationalConstraints,
2874+
bool &addOptionalSupertypeBindings);
2875+
2876+
Optional<PotentialBinding>
2877+
getPotentialBindingForRelationalConstraint(PotentialBindings &result,
2878+
Constraint *constraint);
28692879
PotentialBindings getPotentialBindings(TypeVariableType *typeVar);
28702880

28712881
bool

0 commit comments

Comments
 (0)