Merge pull request #13351 from slavapestov/invalid-use-of-polymorphic-init
Diagnose an invalid use of non-polymorphic constructors
diff --git a/docs/DebuggingTheCompiler.rst b/docs/DebuggingTheCompiler.rst
index 9d75f29..d0736e0 100644
--- a/docs/DebuggingTheCompiler.rst
+++ b/docs/DebuggingTheCompiler.rst
@@ -2,6 +2,7 @@
.. highlight:: none
+============================
Debugging the Swift Compiler
============================
@@ -67,12 +68,85 @@
The output of all these dump options (except ``-dump-ast``) can be redirected
with an additional ``-o <file>`` option.
+Debugging the Type Checker
+--------------------------
+
+Enabling Logging
+~~~~~~~~~~~~~~~~
+
+To enable logging in the type checker, use the following argument: ``-Xfrontend -debug-constraints``.
+This will cause the typechecker to log its internal state as it solves
+constraints and present the final type checked solution, e.g.::
+
+ ---Constraint solving for the expression at [test.swift:3:10 - line:3:10]---
+ ---Initial constraints for the given expression---
+ (integer_literal_expr type='$T0' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] value=0)
+ Score: 0 0 0 0 0 0 0 0 0 0 0 0 0
+ Contextual Type: Int
+ Type Variables:
+ #0 = $T0 [inout allowed]
+
+ Active Constraints:
+
+ Inactive Constraints:
+ $T0 literal conforms to ExpressibleByIntegerLiteral [[locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]]];
+ $T0 conv Int [[locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]]];
+ ($T0 literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+ Active bindings: $T0 := Int
+ (trying $T0 := Int
+ (found solution 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ )
+ ---Solution---
+ Fixed score: 0 0 0 0 0 0 0 0 0 0 0 0 0
+ Type variables:
+ $T0 as Int
+
+ Overload choices:
+
+ Constraint restrictions:
+
+ Disjunction choices:
+
+ Conformances:
+ At locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]
+ (normal_conformance type=Int protocol=ExpressibleByIntegerLiteral lazy
+ (normal_conformance type=Int protocol=_ExpressibleByBuiltinIntegerLiteral lazy))
+ (found solution 0 0 0 0 0 0 0 0 0 0 0 0 0)
+ ---Type-checked expression---
+ (call_expr implicit type='Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] arg_labels=_builtinIntegerLiteral:
+ (constructor_ref_call_expr implicit type='(_MaxBuiltinIntegerType) -> Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10]
+ (declref_expr implicit type='(Int.Type) -> (_MaxBuiltinIntegerType) -> Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) function_ref=single)
+ (type_expr implicit type='Int.Type' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] typerepr='Int'))
+ (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] names=_builtinIntegerLiteral
+ (integer_literal_expr type='Int2048' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] value=0)))
+
+When using the integrated swift-repl, one can dump the same output for each
+expression as one evaluates the expression by enabling constraints debugging by
+typing ``:constraints debug on``::
+
+ $ swift -frontend -repl -enable-objc-interop -module-name REPL
+ *** You are running Swift's integrated REPL, ***
+ *** intended for compiler and stdlib ***
+ *** development and testing purposes only. ***
+ *** The full REPL is built as part of LLDB. ***
+ *** Type ':help' for assistance. ***
+ (swift) :constraints debug on
+
+Asserting on First Error
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When changing the typechecker, one can cause a series of cascading errors. Since
+Swift doesn't assert on such errors, one has to know more about the typechecker
+to know where to stop in the debugger. Rather than doing that, one can use the
+option ``-Xllvm -swift-diagnostics-assert-on-error=1`` to cause the
+DiagnosticsEngine to assert upon the first error, providing the signal that the
+debugger needs to know that it should attach.
Debugging on SIL Level
-~~~~~~~~~~~~~~~~~~~~~~
+----------------------
Options for Dumping the SIL
-```````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
Often it is not sufficient to dump the SIL at the beginning or end of the
optimization pipeline.
@@ -92,7 +166,7 @@
For details see ``PassManager.cpp``.
Dumping the SIL and other Data in LLDB
-``````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When debugging the Swift compiler with LLDB (or Xcode, of course), there is
even a more powerful way to examine the data in the compiler, e.g. the SIL.
@@ -125,7 +199,7 @@
environment setting contains the path to the dot tool.
Debugging and Profiling on SIL level
-````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The compiler provides a way to debug and profile on SIL level. To enable SIL
debugging add the front-end option -gsil together with -g. Example::
@@ -141,7 +215,7 @@
the build-script-impl option ``--build-sil-debugging-stdlib``.
ViewCFG: Regex based CFG Printer
-````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ViewCFG (``./utils/viewcfg``) is a script that parses a textual CFG (e.g. a llvm
or sil function) and displays a .dot file of the CFG. Since the parsing is done
@@ -178,7 +252,7 @@
**NOTE** Since we use open, .dot files should be associated with the Graphviz app for viewcfg to work.
Using Breakpoints
-`````````````````
+~~~~~~~~~~~~~~~~~
LLDB has very powerful breakpoints, which can be utilized in many ways to debug
the compiler and Swift executables. The examples in this section show the LLDB
@@ -255,7 +329,7 @@
(lldb) br set -i 84 -n GlobalARCOpts::run
LLDB Scripts
-````````````
+~~~~~~~~~~~~
LLDB has powerful capabilities of scripting in Python among other languages. An
often overlooked, but very useful technique is the -s command to lldb. This
@@ -294,7 +368,7 @@
needing to retype the various commands perfectly every time.
Reducing SIL test cases using bug_reducer
-`````````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is functionality provided in ./swift/utils/bug_reducer/bug_reducer.py for
reducing SIL test cases by:
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index 11362ef..1aaf6ca 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -24,12 +24,13 @@
#include "swift/AST/PrintOptions.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/SourceManager.h"
-#include "swift/Parse/Lexer.h" // bad dependency
#include "swift/Config.h"
+#include "swift/Parse/Lexer.h" // bad dependency
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
using namespace swift;
@@ -588,6 +589,11 @@
llvm_unreachable("Unhandled DiagnosticKind in switch.");
}
+/// A special option only for compiler writers that causes Diagnostics to assert
+/// when a failure diagnostic is emitted. Intended for use in the debugger.
+llvm::cl::opt<bool> AssertOnError("swift-diagnostics-assert-on-error",
+ llvm::cl::init(false));
+
DiagnosticState::Behavior DiagnosticState::determineBehavior(DiagID id) {
auto set = [this](DiagnosticState::Behavior lvl) {
if (lvl == Behavior::Fatal) {
@@ -597,6 +603,7 @@
anyErrorOccurred = true;
}
+ assert((!AssertOnError || !anyErrorOccurred) && "We emitted an error?!");
previousBehavior = lvl;
return lvl;
};