Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions include/swift/Sema/BindingProducer.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ class ConjunctionElement {

class TypeVariableBinding {
TypeVariableType *TypeVar;
PotentialBinding Binding;
inference::PotentialBinding Binding;

public:
TypeVariableBinding(TypeVariableType *typeVar, PotentialBinding &binding)
TypeVariableBinding(TypeVariableType *typeVar,
inference::PotentialBinding &binding)
: TypeVar(typeVar), Binding(binding) {}

TypeVariableType *getTypeVariable() const { return TypeVar; }
Expand Down Expand Up @@ -183,8 +184,8 @@ class BindingProducer {
};

class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
using BindingKind = AllowedBindingKind;
using Binding = PotentialBinding;
using BindingKind = inference::AllowedBindingKind;
using Binding = inference::PotentialBinding;

TypeVariableType *TypeVar;
llvm::SmallVector<Binding, 8> Bindings;
Expand Down Expand Up @@ -213,7 +214,7 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {

TypeVarBindingProducer(ConstraintSystem &cs,
TypeVariableType *typeVar,
const BindingSet &bindings);
const inference::BindingSet &bindings);

/// Retrieve a set of bindings available in the current state.
ArrayRef<Binding> getCurrentBindings() const { return Bindings; }
Expand Down
31 changes: 0 additions & 31 deletions include/swift/Sema/CSBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,6 @@ class BindingSet {
});
}

/// Check if this binding is viable for inclusion in the set.
///
/// \param binding The binding to validate.
/// \param isTransitive Indicates whether this binding has been
/// acquired through transitive inference and requires extra
/// checking.
bool isViable(PotentialBinding &binding);

/// Determine whether this set has any "viable" (or non-hole) bindings.
///
/// A viable binding could be - a direct or transitive binding
Expand Down Expand Up @@ -662,29 +654,6 @@ class BindingSet {
}
};

enum class ConversionBehavior : unsigned {
None,
Class,
AnyHashable,
Double,
Pointer,
Array,
Dictionary,
Set,
Optional,
Structural,
Unknown
};

/// Classify the possible conversions having this type as result type.
ConversionBehavior getConversionBehavior(Type type);

/// Check whether there exists a type that could be implicitly converted
/// to a given type i.e. is the given type is Double or Optional<..> this
/// function is going to return true because CGFloat could be converted
/// to a Double and non-optional value could be injected into an optional.
bool hasConversions(Type type);

/// Check whether the given type can be used as a binding for the given
/// type variable.
///
Expand Down
6 changes: 2 additions & 4 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@
#include <cstddef>
#include <functional>

using namespace swift::constraints::inference;

namespace swift {

class Expr;
Expand Down Expand Up @@ -4697,13 +4695,13 @@ class ConstraintSystem {

/// Determine whether given type variable with its set of bindings is viable
/// to be attempted on the next step of the solver.
const BindingSet *determineBestBindings();
const inference::BindingSet *determineBestBindings();

/// Get bindings for the given type variable based on current
/// state of the constraint system.
///
/// FIXME: Remove this.
BindingSet getBindingsFor(TypeVariableType *typeVar);
inference::BindingSet getBindingsFor(TypeVariableType *typeVar);

private:
/// Add a constraint to the constraint system.
Expand Down
98 changes: 98 additions & 0 deletions include/swift/Sema/Subtyping.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//===--- Subtyping.h - Swift subtyping and conversion rules -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements various utilities for reasoning about the Swift
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_SUBTYPING_H
#define SWIFT_SEMA_SUBTYPING_H

#include "swift/Basic/OptionSet.h"

namespace swift {

class GenericSignature;
class Type;

namespace constraints {

class ConstraintSystem;

/// Checks if two types can unify if we record a bind constraint between them.
///
/// Returns:
/// - true if there is some indication that the bind may succeed.
/// - false if the bind will definitely fail.
/// - std::nullopt if unknown.
std::optional<bool> isLikelyExactMatch(Type first, Type second);

enum class ConversionBehavior : unsigned {
None,
Class,
AnyHashable,
Double,
Pointer,
Array,
Dictionary,
Set,
Optional,
Structural,
Unknown
};

/// Classify the possible conversions having this type as result type.
ConversionBehavior getConversionBehavior(Type type);

/// Check whether there exists a type that could be implicitly converted
/// to a given type i.e. is the given type is Double or Optional<..> this
/// function is going to return true because CGFloat could be converted
/// to a Double and non-optional value could be injected into an optional.
bool hasConversions(Type type);

enum ConflictFlag : unsigned {
Category = 1 << 0,
Exact = 1 << 1,
Class = 1 << 2,
Structural = 1 << 3,
Array = 1 << 4,
Dictionary = 1 << 5,
Set = 1 << 6,
Optional = 1 << 7,
Double = 1 << 8,
Conformance = 1 << 9,
Mutability = 1 << 10
};
using ConflictReason = OptionSet<ConflictFlag>;

/// Check whether lhs, as a type with type variables or unopened type
/// parameters, might be a subtype of rhs, which again is a type with
/// type variables or unopened type parameters.
///
/// The type parameters are interpreted with respect to sig, whereas
/// type variables are just assumed opaque.
///
/// The answer is conservative, so we err on the side of saying that
/// a convesion _can_ happen. We only return a non-empty ConflictReason
/// if the conversion will definitely fail.
///
/// Even if the types do not contain type variables or type parameters,
/// this does not give a completely accurate answer, yet.
ConflictReason canPossiblyConvertTo(
ConstraintSystem &cs,
Type lhs, Type rhs,
GenericSignature sig);

} // end namespace constraints

} // end namespace swift

#endif // SWIFT_SEMA_SUBTYPING_H
3 changes: 2 additions & 1 deletion lib/Sema/BindingProducer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

using namespace swift;
using namespace constraints;
using namespace inference;

// Given a possibly-Optional type, return the direct superclass of the
// (underlying) type wrapped in the same number of optional levels as
Expand Down Expand Up @@ -389,7 +390,7 @@ bool TypeVarBindingProducer::computeNext() {

for (auto supertype : enumerateDirectSupertypes(type)) {
// If we're not allowed to try this binding, skip it.
if (inference::checkTypeOfBinding(TypeVar, supertype)) {
if (checkTypeOfBinding(TypeVar, supertype)) {
// A key path type cannot be bound to type-erased key path variants.
if (TypeVar->getImpl().isKeyPathType() &&
isTypeErasedKeyPathType(supertype))
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ add_swift_host_library(swiftSema STATIC
ResilienceDiagnostics.cpp
SourceLoader.cpp
SyntacticElementTarget.cpp
Subtyping.cpp
TypeOfReference.cpp
TypeCheckAccess.cpp
TypeCheckAccessNotes.cpp
Expand Down
Loading