Skip to content

[Type checker] Use the request-evaluator in the type checker. #16963

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 10 commits into from
Jun 16, 2018
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
4 changes: 4 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "llvm/Support/DataTypes.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/Evaluator.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/Type.h"
Expand Down Expand Up @@ -218,6 +219,9 @@ class ASTContext final {
/// Diags - The diagnostics engine.
DiagnosticEngine &Diags;

/// The request-evaluator that is used to process various requests.
Evaluator evaluator;

/// The set of top-level modules we have loaded.
/// This map is used for iteration, therefore it's a MapVector and not a
/// DenseMap.
Expand Down
21 changes: 14 additions & 7 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,9 @@ class ExtensionDecl final : public GenericContext, public Decl,

void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }

/// Retrieve one of the types listed in the "inherited" clause.
Type getInheritedType(unsigned index) const;

/// Whether we have fully checked the extension.
bool hasValidSignature() const {
return hasValidationStarted() && !isBeingValidated();
Expand Down Expand Up @@ -2496,6 +2499,9 @@ class TypeDecl : public ValueDecl {
MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
ArrayRef<TypeLoc> getInherited() const { return Inherited; }

/// Retrieve one of the types listed in the "inherited" clause.
Type getInheritedType(unsigned index) const;

/// Whether we already type-checked the inheritance clause.
bool checkedInheritanceClause() const {
return Bits.TypeDecl.CheckedInheritanceClause;
Expand Down Expand Up @@ -3162,6 +3168,8 @@ class EnumDecl final : public NominalTypeDecl {
} LazySemanticInfo;

friend class IterativeTypeChecker;
friend class EnumRawTypeRequest;
friend class TypeChecker;

public:
EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc,
Expand Down Expand Up @@ -3278,14 +3286,11 @@ class EnumDecl final : public NominalTypeDecl {
}

/// Determine whether this enum declares a raw type in its inheritance clause.
bool hasRawType() const {
return (bool)LazySemanticInfo.RawType.getPointer();
}
bool hasRawType() const { return (bool)getRawType(); }

/// Retrieve the declared raw type of the enum from its inheritance clause,
/// or null if it has none.
Type getRawType() const {
return LazySemanticInfo.RawType.getPointer();
}
Type getRawType() const;

/// Set the raw type of the enum from its inheritance clause.
void setRawType(Type rawType) {
Expand Down Expand Up @@ -3413,6 +3418,8 @@ class ClassDecl final : public NominalTypeDecl {
} LazySemanticInfo;

friend class IterativeTypeChecker;
friend class SuperclassTypeRequest;
friend class TypeChecker;

public:
ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
Expand All @@ -3428,7 +3435,7 @@ class ClassDecl final : public NominalTypeDecl {
bool hasSuperclass() const { return (bool)getSuperclass(); }

/// Retrieve the superclass of this class, or null if there is no superclass.
Type getSuperclass() const { return LazySemanticInfo.Superclass.getPointer(); }
Type getSuperclass() const;

/// Retrieve the ClassDecl for the superclass of this class, or null if there
/// is no superclass.
Expand Down
5 changes: 4 additions & 1 deletion include/swift/AST/Evaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ class Evaluator {
/// diagnostics will be emitted.
DiagnosticEngine &diags;

/// Whether to diagnose cycles or ignore them completely.
bool shouldDiagnoseCycles;

/// A vector containing all of the active evaluation requests, which
/// is treated as a stack and is used to detect cycles.
llvm::SetVector<AnyRequest> activeRequests;
Expand All @@ -128,7 +131,7 @@ class Evaluator {
public:
/// Construct a new evaluator that can emit cyclic-dependency
/// diagnostics through the given diagnostics engine.
Evaluator(DiagnosticEngine &diags);
Evaluator(DiagnosticEngine &diags, bool shouldDiagnoseCycles);

/// Evaluate the given request and produce its result,
/// consulting/populating the cache as required.
Expand Down
21 changes: 10 additions & 11 deletions include/swift/AST/LazyResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,19 @@ class LazyResolver {
/// Resolve the "is Objective-C" bit for the given declaration.
virtual void resolveIsObjC(ValueDecl *VD) = 0;

/// Resolve the types in the inheritance clause of the given
/// declaration context, which will be a type declaration or
/// extension declaration.
virtual void resolveInheritanceClause(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl) = 0;

/// Resolve the superclass of the given class.
virtual void resolveSuperclass(ClassDecl *classDecl) = 0;
/// Retrieve the superclass of the given class.
virtual Type getSuperclass(const ClassDecl *classDecl) = 0;

/// Resolve the raw type of the given enum.
virtual void resolveRawType(EnumDecl *enumDecl) = 0;
virtual Type getRawType(EnumDecl *enumDecl) = 0;

/// Get a specific inherited type from the given declaration.
virtual Type getInheritedType(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) = 0;

/// Resolve the inherited protocols of a given protocol.
virtual void resolveInheritedProtocols(ProtocolDecl *protocol) = 0;
/// Resolve the trailing where clause of the given protocol in-place.
virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;

/// Bind an extension to its extended type.
virtual void bindExtension(ExtensionDecl *ext) = 0;
Expand Down
16 changes: 7 additions & 9 deletions include/swift/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,24 @@ class TypeRepr;
/// A TypeLoc is stored in AST nodes which use an explicitly written type.
struct TypeLoc {
private:
/// \brief The resolved type and a bit indicating if it was validated, which
/// means it went through possible generic substitutions.
llvm::PointerIntPair<Type, 1, bool> TAndValidBit;
Type Ty;
TypeRepr *TyR = nullptr;

TypeLoc(Type T, TypeRepr *TyR) : TAndValidBit(T, false), TyR(TyR) {}

public:
TypeLoc() {}
TypeLoc(TypeRepr *TyR) : TyR(TyR) {}
TypeLoc(TypeRepr *TyR, Type Ty) : TyR(TyR) {
setType(Ty);
}

bool wasValidated() const { return TAndValidBit.getInt(); }
bool wasValidated() const { return !Ty.isNull(); }
bool isError() const;

// FIXME: We generally shouldn't need to build TypeLocs without a location.
static TypeLoc withoutLoc(Type T) {
return TypeLoc(T, nullptr);
TypeLoc result;
result.Ty = T;
return result;
}

/// Get the representative location of this type, for diagnostic
Expand All @@ -60,12 +58,12 @@ struct TypeLoc {

bool hasLocation() const { return TyR != nullptr; }
TypeRepr *getTypeRepr() const { return TyR; }
Type getType() const { return TAndValidBit.getPointer(); }
Type getType() const { return Ty; }

bool isNull() const { return getType().isNull() && TyR == nullptr; }

void setInvalidType(ASTContext &C);
void setType(Type Ty, bool validated = false);
void setType(Type Ty);

TypeLoc clone(ASTContext &ctx) const;
};
Expand Down
132 changes: 132 additions & 0 deletions include/swift/Sema/TypeCheckRequests.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//===--- TypeCheckRequests.h - Type Checking Requests -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 defines type checking requests.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_REQUESTS_H
#define SWIFT_SEMA_REQUESTS_H

#include "swift/AST/Type.h"
#include "swift/AST/Evaluator.h"
#include "swift/AST/SimpleRequest.h"
#include "llvm/ADT/Hashing.h"

namespace swift {

struct TypeLoc;

/// Display a nominal type or extension thereof.
void simple_display(
llvm::raw_ostream &out,
const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value);

/// Request the type from the ith entry in the inheritance clause for the
/// given declaration.
class InheritedTypeRequest :
public SimpleRequest<InheritedTypeRequest,
CacheKind::SeparatelyCached,
Type,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>,
unsigned>
{
/// Retrieve the TypeLoc for this inherited type.
TypeLoc &getTypeLoc(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) const;

public:
using SimpleRequest::SimpleRequest;
using SimpleRequest::operator();

private:
friend class SimpleRequest;

// Evaluation.
Type operator()(Evaluator &evaluator,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
unsigned index) const;

public:
// Cycle handling
Type breakCycle() const { return Type(); }
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;

// Caching
bool isCached() const { return true; }
Optional<Type> getCachedResult() const;
void cacheResult(Type value) const;
};

/// Request the superclass type for the given class.
class SuperclassTypeRequest :
public SimpleRequest<SuperclassTypeRequest,
CacheKind::SeparatelyCached,
Type,
ClassDecl *> {
public:
using SimpleRequest::SimpleRequest;
using SimpleRequest::operator();

private:
friend class SimpleRequest;

// Evaluation.
Type operator()(Evaluator &evaluator, ClassDecl *classDecl) const;

public:
// Cycle handling
Type breakCycle() const { return Type(); }
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;

// Separate caching.
bool isCached() const { return true; }
Optional<Type> getCachedResult() const;
void cacheResult(Type value) const;
};

/// Request the raw type of the given enum.
class EnumRawTypeRequest :
public SimpleRequest<EnumRawTypeRequest,
CacheKind::SeparatelyCached,
Type,
EnumDecl *> {
public:
using SimpleRequest::SimpleRequest;
using SimpleRequest::operator();

private:
friend class SimpleRequest;

// Evaluation.
Type operator()(Evaluator &evaluator, EnumDecl *enumDecl) const;

public:
// Cycle handling
Type breakCycle() const { return Type(); }
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;

// Separate caching.
bool isCached() const { return true; }
Optional<Type> getCachedResult() const;
void cacheResult(Type value) const;
};

#define SWIFT_TYPEID_ZONE 10
#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"

} // end namespace swift

#endif // SWIFT_SEMA_REQUESTS_H
19 changes: 19 additions & 0 deletions include/swift/Sema/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===--- ArithmeticEvaluatorTypeIDZone.def - --------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 definition file describes the types in the type checker's
// TypeID zone, for use with the TypeID template.
//
//===----------------------------------------------------------------------===//
SWIFT_TYPEID(InheritedTypeRequest)
SWIFT_TYPEID(SuperclassTypeRequest)
SWIFT_TYPEID(EnumRawTypeRequest)
1 change: 1 addition & 0 deletions include/swift/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ModuleFile
friend class SerializedASTFile;
friend class SILDeserializer;
using Status = serialization::Status;
using TypeID = serialization::TypeID;

/// A reference back to the AST representation of the file.
FileUnit *FileContext = nullptr;
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ ASTContext::ASTContext(LangOptions &langOpts, SearchPathOptions &SearchPathOpts,
SearchPathOpts(SearchPathOpts),
SourceMgr(SourceMgr),
Diags(Diags),
evaluator(Diags, /*shouldDiagnoseCycles=*/false),
TheBuiltinModule(createBuiltinModule(*this)),
StdlibModuleName(getIdentifier(STDLIB_NAME)),
SwiftShimsModuleName(getIdentifier(SWIFT_SHIMS_NAME)),
Expand Down Expand Up @@ -4246,7 +4247,7 @@ CanType ArchetypeType::getAnyOpened(Type existential) {
}

void TypeLoc::setInvalidType(ASTContext &C) {
TAndValidBit.setPointerAndInt(ErrorType::get(C), true);
Ty = ErrorType::get(C);
}

namespace {
Expand Down
Loading