Introduce a LangOptions class to capture various type-checker-tweaking flags. For now, introduce bits to enable the constraint solver and to enable debugging of the constraint solver, and use those to eliminate the "useConstraintSolver" bit that was threaded through too much of the type checker.

Swift SVN r2836
This commit is contained in:
Doug Gregor
2012-09-12 20:19:33 +00:00
parent 693318642d
commit 42b1ab6fbd
12 changed files with 96 additions and 40 deletions

View File

@@ -19,6 +19,7 @@
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "swift/AST/Type.h" #include "swift/AST/Type.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Optional.h" #include "swift/Basic/Optional.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
@@ -82,9 +83,13 @@ public:
Implementation &Impl; Implementation &Impl;
public: public:
ASTContext(llvm::SourceMgr &SourceMgr, DiagnosticEngine &Diags); ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr,
DiagnosticEngine &Diags);
~ASTContext(); ~ASTContext();
/// \brief The language options used for translation.
LangOptions &LangOpts;
/// SourceMgr - The source manager object. /// SourceMgr - The source manager object.
llvm::SourceMgr &SourceMgr; llvm::SourceMgr &SourceMgr;

View File

@@ -0,0 +1,47 @@
//===--- LangOptions.h - Language & configuration options -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the LangOptions class, which provides various
// language and configuration flags.
//
//===----------------------------------------------------------------------===//
//
// LangOptions.h
// Swift
//
// Created by Doug Gregor on 9/12/12.
//
//
#ifndef SWIFT_LANGOPTIONS_H
#define SWIFT_LANGOPTIONS_H
namespace swift {
/// \brief A collection of options that affect the language dialect and
/// provide compiler debugging facilities.
class LangOptions {
public:
/// \brief Whether to use the constraint solver for type checking.
///
/// FIXME: This option is temporary, and will be removed once the constraint
/// solver is the only type checker.
bool UseConstraintSolver = false;
/// \brief Whether we are debugging the constraint solver.
///
/// This option enables verbose debugging output from the constraint
/// solver.
bool DebugConstraintSolver = false;
};
}
#endif

View File

@@ -53,11 +53,7 @@ namespace swift {
/// walks the AST to resolve types and diagnose problems therein. StartElem /// walks the AST to resolve types and diagnose problems therein. StartElem
/// indicates where to start for incremental type checking in the /// indicates where to start for incremental type checking in the
/// main module. /// main module.
/// void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0);
/// \param dumpConstraints Dump the constraints of any expressions in
/// top-level code declarations.
void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0,
bool dumpConstraints = false);
/// performCaptureAnalysis - Analyse the AST and mark local declarations /// performCaptureAnalysis - Analyse the AST and mark local declarations
/// and expressions which can capture them so they can be emitted more /// and expressions which can capture them so they can be emitted more

View File

@@ -58,8 +58,10 @@ ASTContext::Implementation::Implementation()
: IdentifierTable(Allocator) {} : IdentifierTable(Allocator) {}
ASTContext::Implementation::~Implementation() {} ASTContext::Implementation::~Implementation() {}
ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags) ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr,
DiagnosticEngine &Diags)
: Impl(*new Implementation()), : Impl(*new Implementation()),
LangOpts(langOpts),
SourceMgr(sourcemgr), SourceMgr(sourcemgr),
Diags(Diags), Diags(Diags),
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)), TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)),

View File

@@ -25,6 +25,7 @@
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h" #include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
#include <iterator> #include <iterator>
#include <memory> #include <memory>
#include <utility> #include <utility>
@@ -3303,11 +3304,11 @@ bool ConstraintSystem::solve(SmallVectorImpl<ConstraintSystem *> &viable) {
assert(&getTopConstraintSystem() == this &&"Can only solve at the top level"); assert(&getTopConstraintSystem() == this &&"Can only solve at the top level");
// Simplify this constraint system. // Simplify this constraint system.
if (TC.DebugConstraintSolver) { if (TC.getLangOpts().DebugConstraintSolver) {
llvm::errs() << "---Simplified constraints---\n"; llvm::errs() << "---Simplified constraints---\n";
} }
bool error = simplify(); bool error = simplify();
if (TC.DebugConstraintSolver) { if (TC.getLangOpts().DebugConstraintSolver) {
dump(); dump();
} }
if (error) if (error)
@@ -3580,6 +3581,10 @@ Expr *ConstraintSystem::applySolution(Expr *expr) {
assert(freeVariables.empty() && "Solution has free variables"); assert(freeVariables.empty() && "Solution has free variables");
#endif #endif
// FIXME: Disable the constraint-based type checker here, because we depend
// heavily on the existing type checker.
llvm::SaveAndRestore<bool> savedUseCS(TC.getLangOpts().UseConstraintSolver,
false);
ExprRewriter rewriter(*this); ExprRewriter rewriter(*this);
ExprWalker walker(rewriter); ExprWalker walker(rewriter);
return expr->walk(walker); return expr->walk(walker);
@@ -3618,6 +3623,9 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
// Type check the type in an array new expression. // Type check the type in an array new expression.
if (auto newArray = dyn_cast<NewArrayExpr>(expr)) { if (auto newArray = dyn_cast<NewArrayExpr>(expr)) {
llvm::SaveAndRestore<bool> savedUseCS(
TC.getLangOpts().UseConstraintSolver,
false);
if (TC.validateType(newArray->getElementTypeLoc(), if (TC.validateType(newArray->getElementTypeLoc(),
/*isFirstPass=*/false)) /*isFirstPass=*/false))
return nullptr; return nullptr;
@@ -3677,7 +3685,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
cs.addConstraint(ConstraintKind::Conversion, expr->getType(), convertType); cs.addConstraint(ConstraintKind::Conversion, expr->getType(), convertType);
} }
if (DebugConstraintSolver) { if (getLangOpts().DebugConstraintSolver) {
log << "---Initial constraints for the given expression---\n"; log << "---Initial constraints for the given expression---\n";
expr->dump(); expr->dump();
log << "\n"; log << "\n";
@@ -3687,7 +3695,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
// Attempt to solve the constraint system. // Attempt to solve the constraint system.
SmallVector<ConstraintSystem *, 4> viable; SmallVector<ConstraintSystem *, 4> viable;
if (cs.solve(viable)) { if (cs.solve(viable)) {
if (DebugConstraintSolver) { if (getLangOpts().DebugConstraintSolver) {
llvm::errs() << "---Solved constraints---\n"; llvm::errs() << "---Solved constraints---\n";
cs.dump(); cs.dump();
@@ -3721,7 +3729,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
} }
auto solution = viable[0]; auto solution = viable[0];
if (DebugConstraintSolver) { if (getLangOpts().DebugConstraintSolver) {
log << "---Solution---\n"; log << "---Solution---\n";
solution->dump(); solution->dump();
} }
@@ -3741,7 +3749,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
return nullptr; return nullptr;
} }
if (DebugConstraintSolver) { if (getLangOpts().DebugConstraintSolver) {
log << "---Type-checked expression---\n"; log << "---Type-checked expression---\n";
result->dump(); result->dump();
} }

View File

@@ -1664,12 +1664,16 @@ Expr *TypeChecker::typeCheckNewReferenceExpr(NewReferenceExpr *expr) {
return SemaExpressionTree(*this).visitNewReferenceExpr(expr); return SemaExpressionTree(*this).visitNewReferenceExpr(expr);
} }
bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType, bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType) {
bool useConstraintSolver) {
// If we're using the constraint solver, we take a different path through // If we're using the constraint solver, we take a different path through
// the type checker. Handle it here. // the type checker. Handle it here.
if (useConstraintSolver) { if (getLangOpts().UseConstraintSolver) {
llvm::SaveAndRestore<bool> debug(DebugConstraintSolver, true); // If this expression has already been type-checked, we're done.
if (E->getType())
return E->getType()->is<ErrorType>();
llvm::SaveAndRestore<bool> debug(getLangOpts().DebugConstraintSolver,
true);
E = typeCheckExpressionConstraints(E, ConvertType); E = typeCheckExpressionConstraints(E, ConvertType);
return E == nullptr; return E == nullptr;
} }

View File

@@ -519,11 +519,10 @@ void TypeChecker::typeCheckDestructorBody(DestructorDecl *DD) {
StmtChecker(*this, DD).typeCheckStmt(Body); StmtChecker(*this, DD).typeCheckStmt(Body);
} }
void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD, void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) {
bool useConstraintSolver) {
auto Elem = TLCD->getBody(); auto Elem = TLCD->getBody();
if (Expr *E = Elem.dyn_cast<Expr*>()) { if (Expr *E = Elem.dyn_cast<Expr*>()) {
if (typeCheckExpression(E, Type(), useConstraintSolver)) if (typeCheckExpression(E, Type()))
return; return;
if (TU.Kind == TranslationUnit::Repl) if (TU.Kind == TranslationUnit::Repl)
typeCheckTopLevelReplExpr(E, TLCD); typeCheckTopLevelReplExpr(E, TLCD);

View File

@@ -401,8 +401,7 @@ static void checkClassOverrides(TypeChecker &TC, ClassDecl *CD) {
/// walks the AST to resolve types and diagnose problems therein. /// walks the AST to resolve types and diagnose problems therein.
/// ///
/// FIXME: This should be moved out to somewhere else. /// FIXME: This should be moved out to somewhere else.
void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem, void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) {
bool useConstraintSolver) {
TypeChecker TC(*TU); TypeChecker TC(*TU);
struct ExprPrePassWalker : private ASTWalker { struct ExprPrePassWalker : private ASTWalker {
@@ -684,7 +683,7 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem,
if (TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(D)) { if (TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
// Immediately perform global name-binding etc. // Immediately perform global name-binding etc.
prePass.doWalk(TLCD); prePass.doWalk(TLCD);
TC.typeCheckTopLevelCodeDecl(TLCD, useConstraintSolver); TC.typeCheckTopLevelCodeDecl(TLCD);
} else { } else {
prePass.doWalk(D); prePass.doWalk(D);
TC.typeCheckDecl(D, /*isFirstPass*/false); TC.typeCheckDecl(D, /*isFirstPass*/false);

View File

@@ -278,9 +278,6 @@ public:
TranslationUnit &TU; TranslationUnit &TU;
ASTContext &Context; ASTContext &Context;
bool UseConstraintSolver = false;
bool DebugConstraintSolver = false;
private: private:
/// \brief The 'Enumerable' protocol, used by the for-each loop. /// \brief The 'Enumerable' protocol, used by the for-each loop.
ProtocolDecl *EnumerableProto; ProtocolDecl *EnumerableProto;
@@ -296,6 +293,8 @@ private:
public: public:
TypeChecker(TranslationUnit &TU) TypeChecker(TranslationUnit &TU)
: TU(TU), Context(TU.Ctx), EnumerableProto(0), RangeProto(0) {} : TU(TU), Context(TU.Ctx), EnumerableProto(0), RangeProto(0) {}
LangOptions &getLangOpts() const { return Context.LangOpts; }
template<typename ...ArgTypes> template<typename ...ArgTypes>
InFlightDiagnostic diagnose(ArgTypes... Args) { InFlightDiagnostic diagnose(ArgTypes... Args) {
@@ -368,8 +367,7 @@ public:
void typeCheckFunctionBody(FuncExpr *FE); void typeCheckFunctionBody(FuncExpr *FE);
void typeCheckConstructorBody(ConstructorDecl *CD); void typeCheckConstructorBody(ConstructorDecl *CD);
void typeCheckDestructorBody(DestructorDecl *DD); void typeCheckDestructorBody(DestructorDecl *DD);
void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD, void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);
bool useConstraintSolver);
void typeCheckTopLevelReplExpr(Expr *&E, TopLevelCodeDecl *TLCD); void typeCheckTopLevelReplExpr(Expr *&E, TopLevelCodeDecl *TLCD);
void REPLCheckPatternBinding(PatternBindingDecl *D); void REPLCheckPatternBinding(PatternBindingDecl *D);
@@ -395,8 +393,7 @@ public:
/// solver's application. /// solver's application.
Expr *typeCheckNewReferenceExpr(NewReferenceExpr *expr); Expr *typeCheckNewReferenceExpr(NewReferenceExpr *expr);
bool typeCheckExpression(Expr *&E, Type ConvertType = Type(), bool typeCheckExpression(Expr *&E, Type ConvertType = Type());
bool useConstraintSolver = false);
Expr *typeCheckExpressionConstraints(Expr *expr, Type convertType = Type()); Expr *typeCheckExpressionConstraints(Expr *expr, Type convertType = Type());
bool typeCheckPattern(Pattern *P, bool isFirstPass, bool allowUnknownTypes); bool typeCheckPattern(Pattern *P, bool isFirstPass, bool allowUnknownTypes);

View File

@@ -77,15 +77,14 @@ swift::buildSingleTranslationUnit(ASTContext &Context, unsigned BufferID,
bool swift::appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID, bool swift::appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID,
unsigned CurTUElem, unsigned CurTUElem,
unsigned &BufferOffset, unsigned &BufferOffset,
unsigned BufferEndOffset, unsigned BufferEndOffset) {
bool useConstraintSolver) {
bool FoundAnySideEffects = false; bool FoundAnySideEffects = false;
do { do {
FoundAnySideEffects |= parseIntoTranslationUnit(TU, BufferID, FoundAnySideEffects |= parseIntoTranslationUnit(TU, BufferID,
&BufferOffset, &BufferOffset,
BufferEndOffset); BufferEndOffset);
performNameBinding(TU, CurTUElem); performNameBinding(TU, CurTUElem);
performTypeChecking(TU, CurTUElem, useConstraintSolver); performTypeChecking(TU, CurTUElem);
CurTUElem = TU->Decls.size(); CurTUElem = TU->Decls.size();
} while (BufferOffset != BufferEndOffset); } while (BufferOffset != BufferEndOffset);
return FoundAnySideEffects; return FoundAnySideEffects;

View File

@@ -27,6 +27,5 @@ namespace swift {
bool appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID, bool appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID,
unsigned CurTUElem, unsigned CurTUElem,
unsigned &BufferOffset, unsigned &BufferOffset,
unsigned BufferEndOffset, unsigned BufferEndOffset);
bool useConstraintSolver);
} }

View File

@@ -34,6 +34,7 @@
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Process.h" #include "llvm/Support/Process.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Signals.h" #include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h" #include "llvm/Support/system_error.h"
@@ -305,8 +306,7 @@ void swift::REPL(ASTContext &Context) {
swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem, swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
CurBufferOffset, CurBufferOffset,
CurBufferEndOffset, CurBufferEndOffset);
/*useConstraintSolver=*/false);
if (Context.hadError()) if (Context.hadError())
return; return;
@@ -418,11 +418,12 @@ void swift::REPL(ASTContext &Context) {
continue; continue;
// Parse the current line(s). // Parse the current line(s).
llvm::SaveAndRestore<bool> setUseConstraintSolver(
TU->getASTContext().LangOpts.UseConstraintSolver, useConstraintSolver);
bool ShouldRun = bool ShouldRun =
swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem, swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
CurBufferOffset, CurBufferOffset,
CurBufferEndOffset, CurBufferEndOffset);
useConstraintSolver);
if (useConstraintSolver) { if (useConstraintSolver) {
useConstraintSolver = false; useConstraintSolver = false;
ShouldRun = false; ShouldRun = false;