diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index a95c933bc91..dd1fac83b4e 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -19,6 +19,7 @@ #include "llvm/Support/DataTypes.h" #include "swift/AST/Type.h" +#include "swift/Basic/LangOptions.h" #include "swift/Basic/Optional.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" @@ -82,9 +83,13 @@ public: Implementation &Impl; public: - ASTContext(llvm::SourceMgr &SourceMgr, DiagnosticEngine &Diags); + ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr, + DiagnosticEngine &Diags); ~ASTContext(); - + + /// \brief The language options used for translation. + LangOptions &LangOpts; + /// SourceMgr - The source manager object. llvm::SourceMgr &SourceMgr; diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h new file mode 100644 index 00000000000..45b4cc0c0f6 --- /dev/null +++ b/include/swift/Basic/LangOptions.h @@ -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 diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 2b338c9afdb..8240b4d570d 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -53,11 +53,7 @@ namespace swift { /// walks the AST to resolve types and diagnose problems therein. StartElem /// indicates where to start for incremental type checking in the /// main module. - /// - /// \param dumpConstraints Dump the constraints of any expressions in - /// top-level code declarations. - void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0, - bool dumpConstraints = false); + void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0); /// performCaptureAnalysis - Analyse the AST and mark local declarations /// and expressions which can capture them so they can be emitted more diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7854b734435..39b828578f8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -58,8 +58,10 @@ ASTContext::Implementation::Implementation() : IdentifierTable(Allocator) {} ASTContext::Implementation::~Implementation() {} -ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags) +ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr, + DiagnosticEngine &Diags) : Impl(*new Implementation()), + LangOpts(langOpts), SourceMgr(sourcemgr), Diags(Diags), TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)), diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 23140eff4c0..5cb17199e04 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SaveAndRestore.h" #include #include #include @@ -3303,11 +3304,11 @@ bool ConstraintSystem::solve(SmallVectorImpl &viable) { assert(&getTopConstraintSystem() == this &&"Can only solve at the top level"); // Simplify this constraint system. - if (TC.DebugConstraintSolver) { + if (TC.getLangOpts().DebugConstraintSolver) { llvm::errs() << "---Simplified constraints---\n"; } bool error = simplify(); - if (TC.DebugConstraintSolver) { + if (TC.getLangOpts().DebugConstraintSolver) { dump(); } if (error) @@ -3580,6 +3581,10 @@ Expr *ConstraintSystem::applySolution(Expr *expr) { assert(freeVariables.empty() && "Solution has free variables"); #endif + // FIXME: Disable the constraint-based type checker here, because we depend + // heavily on the existing type checker. + llvm::SaveAndRestore savedUseCS(TC.getLangOpts().UseConstraintSolver, + false); ExprRewriter rewriter(*this); ExprWalker walker(rewriter); return expr->walk(walker); @@ -3618,6 +3623,9 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){ // Type check the type in an array new expression. if (auto newArray = dyn_cast(expr)) { + llvm::SaveAndRestore savedUseCS( + TC.getLangOpts().UseConstraintSolver, + false); if (TC.validateType(newArray->getElementTypeLoc(), /*isFirstPass=*/false)) return nullptr; @@ -3677,7 +3685,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){ cs.addConstraint(ConstraintKind::Conversion, expr->getType(), convertType); } - if (DebugConstraintSolver) { + if (getLangOpts().DebugConstraintSolver) { log << "---Initial constraints for the given expression---\n"; expr->dump(); log << "\n"; @@ -3687,7 +3695,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){ // Attempt to solve the constraint system. SmallVector viable; if (cs.solve(viable)) { - if (DebugConstraintSolver) { + if (getLangOpts().DebugConstraintSolver) { llvm::errs() << "---Solved constraints---\n"; cs.dump(); @@ -3721,7 +3729,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){ } auto solution = viable[0]; - if (DebugConstraintSolver) { + if (getLangOpts().DebugConstraintSolver) { log << "---Solution---\n"; solution->dump(); } @@ -3741,7 +3749,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){ return nullptr; } - if (DebugConstraintSolver) { + if (getLangOpts().DebugConstraintSolver) { log << "---Type-checked expression---\n"; result->dump(); } diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index 254bca3f344..a78dddd8d15 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -1664,12 +1664,16 @@ Expr *TypeChecker::typeCheckNewReferenceExpr(NewReferenceExpr *expr) { return SemaExpressionTree(*this).visitNewReferenceExpr(expr); } -bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType, - bool useConstraintSolver) { +bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType) { // If we're using the constraint solver, we take a different path through // the type checker. Handle it here. - if (useConstraintSolver) { - llvm::SaveAndRestore debug(DebugConstraintSolver, true); + if (getLangOpts().UseConstraintSolver) { + // If this expression has already been type-checked, we're done. + if (E->getType()) + return E->getType()->is(); + + llvm::SaveAndRestore debug(getLangOpts().DebugConstraintSolver, + true); E = typeCheckExpressionConstraints(E, ConvertType); return E == nullptr; } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index ad36552bdb9..bc2fe700be2 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -519,11 +519,10 @@ void TypeChecker::typeCheckDestructorBody(DestructorDecl *DD) { StmtChecker(*this, DD).typeCheckStmt(Body); } -void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD, - bool useConstraintSolver) { +void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { auto Elem = TLCD->getBody(); if (Expr *E = Elem.dyn_cast()) { - if (typeCheckExpression(E, Type(), useConstraintSolver)) + if (typeCheckExpression(E, Type())) return; if (TU.Kind == TranslationUnit::Repl) typeCheckTopLevelReplExpr(E, TLCD); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 747d92b1667..4733f650aa9 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -401,8 +401,7 @@ static void checkClassOverrides(TypeChecker &TC, ClassDecl *CD) { /// walks the AST to resolve types and diagnose problems therein. /// /// FIXME: This should be moved out to somewhere else. -void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem, - bool useConstraintSolver) { +void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) { TypeChecker TC(*TU); struct ExprPrePassWalker : private ASTWalker { @@ -684,7 +683,7 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem, if (TopLevelCodeDecl *TLCD = dyn_cast(D)) { // Immediately perform global name-binding etc. prePass.doWalk(TLCD); - TC.typeCheckTopLevelCodeDecl(TLCD, useConstraintSolver); + TC.typeCheckTopLevelCodeDecl(TLCD); } else { prePass.doWalk(D); TC.typeCheckDecl(D, /*isFirstPass*/false); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index d3887b68bb7..1bafec5c121 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -278,9 +278,6 @@ public: TranslationUnit &TU; ASTContext &Context; - bool UseConstraintSolver = false; - bool DebugConstraintSolver = false; - private: /// \brief The 'Enumerable' protocol, used by the for-each loop. ProtocolDecl *EnumerableProto; @@ -296,6 +293,8 @@ private: public: TypeChecker(TranslationUnit &TU) : TU(TU), Context(TU.Ctx), EnumerableProto(0), RangeProto(0) {} + + LangOptions &getLangOpts() const { return Context.LangOpts; } template InFlightDiagnostic diagnose(ArgTypes... Args) { @@ -368,8 +367,7 @@ public: void typeCheckFunctionBody(FuncExpr *FE); void typeCheckConstructorBody(ConstructorDecl *CD); void typeCheckDestructorBody(DestructorDecl *DD); - void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD, - bool useConstraintSolver); + void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD); void typeCheckTopLevelReplExpr(Expr *&E, TopLevelCodeDecl *TLCD); void REPLCheckPatternBinding(PatternBindingDecl *D); @@ -395,8 +393,7 @@ public: /// solver's application. Expr *typeCheckNewReferenceExpr(NewReferenceExpr *expr); - bool typeCheckExpression(Expr *&E, Type ConvertType = Type(), - bool useConstraintSolver = false); + bool typeCheckExpression(Expr *&E, Type ConvertType = Type()); Expr *typeCheckExpressionConstraints(Expr *expr, Type convertType = Type()); bool typeCheckPattern(Pattern *P, bool isFirstPass, bool allowUnknownTypes); diff --git a/tools/swift/Frontend.cpp b/tools/swift/Frontend.cpp index 473160c5553..b11605d1066 100644 --- a/tools/swift/Frontend.cpp +++ b/tools/swift/Frontend.cpp @@ -77,15 +77,14 @@ swift::buildSingleTranslationUnit(ASTContext &Context, unsigned BufferID, bool swift::appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID, unsigned CurTUElem, unsigned &BufferOffset, - unsigned BufferEndOffset, - bool useConstraintSolver) { + unsigned BufferEndOffset) { bool FoundAnySideEffects = false; do { FoundAnySideEffects |= parseIntoTranslationUnit(TU, BufferID, &BufferOffset, BufferEndOffset); performNameBinding(TU, CurTUElem); - performTypeChecking(TU, CurTUElem, useConstraintSolver); + performTypeChecking(TU, CurTUElem); CurTUElem = TU->Decls.size(); } while (BufferOffset != BufferEndOffset); return FoundAnySideEffects; diff --git a/tools/swift/Frontend.h b/tools/swift/Frontend.h index f46088bfaf0..25577e3e320 100644 --- a/tools/swift/Frontend.h +++ b/tools/swift/Frontend.h @@ -27,6 +27,5 @@ namespace swift { bool appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID, unsigned CurTUElem, unsigned &BufferOffset, - unsigned BufferEndOffset, - bool useConstraintSolver); + unsigned BufferEndOffset); } diff --git a/tools/swift/Immediate.cpp b/tools/swift/Immediate.cpp index 706af0ca0f3..72e23c3caf8 100644 --- a/tools/swift/Immediate.cpp +++ b/tools/swift/Immediate.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Process.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/system_error.h" @@ -305,8 +306,7 @@ void swift::REPL(ASTContext &Context) { swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem, CurBufferOffset, - CurBufferEndOffset, - /*useConstraintSolver=*/false); + CurBufferEndOffset); if (Context.hadError()) return; @@ -418,11 +418,12 @@ void swift::REPL(ASTContext &Context) { continue; // Parse the current line(s). + llvm::SaveAndRestore setUseConstraintSolver( + TU->getASTContext().LangOpts.UseConstraintSolver, useConstraintSolver); bool ShouldRun = swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem, CurBufferOffset, - CurBufferEndOffset, - useConstraintSolver); + CurBufferEndOffset); if (useConstraintSolver) { useConstraintSolver = false; ShouldRun = false;