Skip to content

[ConstraintSystem] Print constraint simplification in type inference debug output #60828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 17, 2022
Merged
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
19 changes: 18 additions & 1 deletion include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -4421,7 +4421,7 @@ class ConstraintSystem {

if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState ? solverState->getCurrentIndent() : 0)
log.indent(solverState ? solverState->getCurrentIndent() + 4 : 0)
<< "(failed constraint ";
constraint->print(log, &getASTContext().SourceMgr);
log << ")\n";
Expand All @@ -4444,6 +4444,14 @@ class ConstraintSystem {
// Add this constraint to the constraint graph.
CG.addConstraint(constraint);

if (isDebugMode() && getPhase() == ConstraintSystemPhase::Solving) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent() + 4) << "(added constraint: ";
constraint->print(log, &getASTContext().SourceMgr,
solverState->getCurrentIndent() + 4);
log << ")\n";
}

// Record this as a newly-generated constraint.
if (solverState)
solverState->addGeneratedConstraint(constraint);
Expand All @@ -4454,6 +4462,15 @@ class ConstraintSystem {
CG.removeConstraint(constraint);
InactiveConstraints.erase(constraint);

if (isDebugMode() && getPhase() == ConstraintSystemPhase::Solving) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent() + 4)
<< "(removed constraint: ";
constraint->print(log, &getASTContext().SourceMgr,
solverState->getCurrentIndent() + 4);
log << ")\n";
}

if (solverState)
solverState->retireConstraint(constraint);
}
Expand Down
38 changes: 38 additions & 0 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,24 +345,62 @@ bool ConstraintSystem::simplify() {
auto *constraint = &ActiveConstraints.front();
deactivateConstraint(constraint);

if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent());
log << "(considering -> ";
constraint->print(log, &getASTContext().SourceMgr);
log << "\n";

// {Dis, Con}junction are returned unsolved in \c simplifyConstraint() and
// handled separately by solver steps.
if (constraint->getKind() != ConstraintKind::Disjunction &&
constraint->getKind() != ConstraintKind::Conjunction) {
log.indent(solverState->getCurrentIndent() + 2)
<< "(simplification result:\n";
}
}

// Simplify this constraint.
switch (simplifyConstraint(*constraint)) {
case SolutionKind::Error:
retireFailedConstraint(constraint);
if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent() + 2) << ")\n";
log.indent(solverState->getCurrentIndent() + 2) << "(outcome: error)\n";
}
break;

case SolutionKind::Solved:
if (solverState)
++solverState->NumSimplifiedConstraints;
retireConstraint(constraint);
if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent() + 2) << ")\n";
log.indent(solverState->getCurrentIndent() + 2)
<< "(outcome: simplified)\n";
}
break;

case SolutionKind::Unsolved:
if (solverState)
++solverState->NumUnsimplifiedConstraints;
if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent() + 2) << ")\n";
log.indent(solverState->getCurrentIndent() + 2)
<< "(outcome: unsolved)\n";
}
break;
}

if (isDebugMode()) {
auto &log = llvm::errs();
log.indent(solverState->getCurrentIndent()) << ")\n";
}

// Check whether a constraint failed. If so, we're done.
if (failedConstraint) {
return true;
Expand Down
5 changes: 3 additions & 2 deletions test/Concurrency/async_overload_filtering.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ var a: String? = nil

// CHECK: attempting disjunction choice $T0 bound to decl async_overload_filtering.(file).filter_async(fn2:)
// CHECK-NEXT: overload set choice binding $T0 := {{.*}}
// CHECK-NEXT: increasing 'sync-in-asynchronous' score by 1
// CHECK-NEXT: solution is worse than the best solution
// CHECK-NEXT: (considering -> ({{.*}}) -> {{.*}} applicable fn {{.*}}
// CHECK: increasing 'sync-in-asynchronous' score by 1
// CHECK: solution is worse than the best solution
filter_async {
Obj()
}.op("" + (a ?? "a"))
6 changes: 4 additions & 2 deletions test/Constraints/common_type.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ func f(_: Double) -> Y { return Y() }

func testCallCommonType() {
// CHECK: overload set choice binding $T{{[0-9]+}} := (Int) -> X
// CHECK-NEXT: (common result type for $T{{[0-9]+}} is Int)
// CHECK: (considering -> $T{{[0-9]+}}[.g: value] == [[G:\$T[0-9]+]]
// CHECK: (common result type for [[G]] is Int)
// CHECK: (overload set choice binding $T{{[0-9]+}} := (Double) -> Y)
// CHECK-NEXT: (common result type for $T{{[0-9]+}} is Double)
// CHECK: (considering -> $T{{[0-9]+}}[.g: value] == [[F:\$T[0-9]+]]
// CHECK: (common result type for [[F]] is Double)
_ = f(0).g(0)
}

Expand Down
29 changes: 16 additions & 13 deletions test/Constraints/one_way_solve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ func takeDoubleAndBool(_: Double, _: Bool) { }

func testTernaryOneWay(b: Bool, b2: Bool) {
// CHECK: ---Connected components---
// CHECK-NEXT: 3: $T10 depends on 1
// CHECK-NEXT: 1: $T5 $T8 $T9 depends on 0, 2
// CHECK-NEXT: 2: $T7
// CHECK-NEXT: 0: $T4
// CHECK-NEXT: 4: $T11 $T13 $T14
// CHECK-NEXT: 3: $T{{[0-9]+}} depends on 1
// CHECK-NEXT: 1: $T{{[0-9]+}} $T{{[0-9]+}} $T{{[0-9]+}} depends on 0, 2
// CHECK-NEXT: 2: $T{{[0-9]+}}
// CHECK-NEXT: 0: $T{{[0-9]+}}
// CHECK-NEXT: 4: $T{{[0-9]+}} $T{{[0-9]+}} $T{{[0-9]+}}
takeDoubleAndBool(
Builtin.one_way(
b ? Builtin.one_way(3.14159) : Builtin.one_way(2.71828)),
Expand All @@ -23,22 +23,25 @@ func int8Or16(_ x: Int16) -> Int16 { return x }

func testTernaryOneWayOverload(b: Bool) {
// CHECK: ---Connected components---
// CHECK: 1: $T5 $T10 $T11 depends on 0, 2
// CHECK: 2: $T7 $T8 $T9
// CHECK: 0: $T2 $T3 $T4
// CHECK: 1: [[A:\$T[0-9]+]] [[B:\$T[0-9]+]] [[C:\$T[0-9]+]] depends on 0, 2
// CHECK: 2: $T{{[0-9]+}} $T{{[0-9]+}} $T{{[0-9]+}}
// CHECK: 0: $T{{[0-9]+}} $T{{[0-9]+}} $T{{[0-9]+}}

// CHECK: solving component #1
// CHECK: (attempting type variable $T11 := Int8
// CHECK: (attempting type variable [[C]] := Int8

// CHECK: solving component #1
// CHECK: (attempting type variable $T11 := Int8
// CHECK: (attempting type variable [[C]] := Int8

// CHECK: solving component #1
// CHECK: (attempting type variable $T11 := Int8
// CHECK: (attempting type variable [[C]] := Int8

// CHECK: solving component #1
// CHECK: (attempting type variable $T11 := Int8
// CHECK: (found solution: [component: non-default literal(s), value: 2] [component: use of overloaded unapplied function(s), value: 2])
// CHECK: (attempting type variable [[C]] := Int8
// CHECK: (considering -> $T{{[0-9]+}} conv [[C]]
// CHECK: (considering -> $T{{[0-9]+}} conv [[C]]
// CHECK: (considering -> [[C]] conv Int8
// CHECK: (found solution: [component: non-default literal(s), value: 2] [component: use of overloaded unapplied function(s), value: 2])

// CHECK: (composed solution: [component: non-default literal(s), value: 2] [component: use of overloaded unapplied function(s), value: 2])
// CHECK-NOT: (composed solution: [component: non-default literal(s), value: 2] [component: use of overloaded unapplied function(s), value: 2])
Expand Down
8 changes: 8 additions & 0 deletions test/Constraints/overload_filtering.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func testSubscript(x: X, i: Int) {
func testUnresolvedMember(i: Int) -> X {
// CHECK: disabled disjunction term {{.*}} bound to decl overload_filtering.(file).X.init(_:)
// CHECK-NEXT: disabled disjunction term {{.*}} bound to decl overload_filtering.(file).X.init(_:_:_:)
// CHECK-NEXT: (removed constraint: disjunction
// CHECK-NEXT: > [[A:\$T[0-9]+]] bound to decl overload_filtering
// CHECK-NEXT: > [disabled] [[A]] bound to decl overload_filtering
// CHECK-NEXT: > [disabled] [[A]] bound to decl overload_filtering
// CHECK-NEXT: introducing single enabled disjunction term {{.*}} bound to decl overload_filtering.(file).X.init(_:_:)
return .init(i, i)
}
Expand All @@ -56,6 +60,10 @@ func test_member_filtering() {
func test(s: S) {
// CHECK: disabled disjunction term {{.*}} bound to decl overload_filtering.(file).test_member_filtering().S.bar(v:)
// CHECK-NEXT: disabled disjunction term {{.*}} bound to decl overload_filtering.(file).test_member_filtering().S.bar(a:b:)
// CHECK-NEXT: (removed constraint: disjunction
// CHECK-NEXT: > [[B:\$T[0-9]+]] bound to decl overload_filtering
// CHECK-NEXT: > [disabled] [[B]] bound to decl overload_filtering
// CHECK-NEXT: > [disabled] [[B]] bound to decl overload_filtering
// CHECK-NEXT: introducing single enabled disjunction term {{.*}} bound to decl overload_filtering.(file).test_member_filtering().S.bar
s.foo(42).bar(42)
}
Expand Down