Skip to content

[NFC] Name Binding -> Import Resolution #27998

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

Closed
wants to merge 4 commits into from
Closed
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
2 changes: 1 addition & 1 deletion docs/CompilerPerformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ compilers on hand while you're working.
Total Execution Time: 0.0876 seconds (0.0877 wall clock)

---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
0.0241 ( 53.9%) 0.0394 ( 92.0%) 0.0635 ( 72.5%) 0.0635 ( 72.5%) Name binding
0.0241 ( 53.9%) 0.0394 ( 92.0%) 0.0635 ( 72.5%) 0.0635 ( 72.5%) Import resolution
0.0170 ( 38.0%) 0.0025 ( 5.8%) 0.0195 ( 22.3%) 0.0195 ( 22.2%) Type checking / Semantic analysis
0.0013 ( 3.0%) 0.0004 ( 0.8%) 0.0017 ( 1.9%) 0.0017 ( 1.9%) LLVM output
0.0010 ( 2.3%) 0.0003 ( 0.7%) 0.0013 ( 1.5%) 0.0013 ( 1.5%) SILGen
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ ERROR(cannot_return_value_from_void_func,none,
"unexpected non-void return value in void function", ())

//------------------------------------------------------------------------------
// MARK: Name Binding
// MARK: Import Resolution
//------------------------------------------------------------------------------

ERROR(sema_no_import,Fatal,
Expand Down
8 changes: 4 additions & 4 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1319,9 +1319,9 @@ class SuperRefExpr : public Expr {
}
};

/// A reference to a type in expression context, spelled out as a TypeLoc. Sema
/// forms this expression as a result of name binding. This always has
/// MetaTypetype.
/// A reference to a type in expression context, spelled out as a TypeLoc.
///
/// The type of this expression is always \c MetaTypeType.
class TypeExpr : public Expr {
TypeLoc Info;
TypeExpr(Type Ty);
Expand Down Expand Up @@ -4675,7 +4675,7 @@ class AssignExpr : public Expr {
};

/// A pattern production that has been parsed but hasn't been resolved
/// into a complete pattern. Name binding converts these into standalone pattern
/// into a complete pattern. Pattern checking converts these into standalone pattern
/// nodes or raises an error if a pattern production appears in an invalid
/// position.
class UnresolvedPatternExpr : public Expr {
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/ImportCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class alignas(ModuleDecl::ImportedModule) ImportCache {
const DeclContext *dc);

/// This is a hack to cope with main file parsing and REPL parsing, where
/// we can add ImportDecls after name binding.
/// we can add ImportDecls after import resolution.
void clear() {
ImportSetForDC.clear();
}
Expand Down
17 changes: 7 additions & 10 deletions include/swift/AST/SourceFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class SourceFile final : public FileUnit {

/// This is the list of modules that are imported by this module.
///
/// This is filled in by the Name Binding phase.
/// This is filled in by the import resolution phase.
ArrayRef<ImportedModuleDesc> Imports;

/// A unique identifier representing this file; used to mark private decls
Expand Down Expand Up @@ -172,13 +172,10 @@ class SourceFile final : public FileUnit {
/// List of Objective-C member conflicts we have found during type checking.
std::vector<ObjCMethodConflict> ObjCMethodConflicts;

template <typename T>
using OperatorMap = llvm::DenseMap<Identifier,llvm::PointerIntPair<T,1,bool>>;

OperatorMap<InfixOperatorDecl*> InfixOperators;
OperatorMap<PostfixOperatorDecl*> PostfixOperators;
OperatorMap<PrefixOperatorDecl*> PrefixOperators;
OperatorMap<PrecedenceGroupDecl*> PrecedenceGroups;
llvm::DenseMap<Identifier, InfixOperatorDecl *> InfixOperators;
llvm::DenseMap<Identifier, PostfixOperatorDecl *> PostfixOperators;
llvm::DenseMap<Identifier, PrefixOperatorDecl *> PrefixOperators;
llvm::DenseMap<Identifier, PrecedenceGroupDecl *> PrecedenceGroups;

/// Describes what kind of file this is, which can affect some type checking
/// and other behavior.
Expand All @@ -189,8 +186,8 @@ class SourceFile final : public FileUnit {
Parsing,
/// Parsing has completed.
Parsed,
/// Name binding has completed.
NameBound,
/// Import resolution has completed.
ImportsResolved,
/// Type checking has completed.
TypeChecked
};
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class ComponentIdentTypeRepr : public IdentTypeRepr {
/// component.
///
/// The initial parsed representation is always an identifier, and
/// name binding will resolve this to a specific declaration.
/// name lookup will resolve this to a specific declaration.
llvm::PointerUnion<Identifier, TypeDecl *> IdOrDecl;

/// The declaration context from which the bound declaration was
Expand Down
13 changes: 7 additions & 6 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1204,10 +1204,11 @@ class NominalOrBoundGenericNominalType : public AnyGenericType {
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)

/// ErrorType - This represents a type that was erroneously constructed. This
/// is produced when parsing types and when name binding type aliases, and is
/// installed in declaration that use these erroneous types. All uses of a
/// declaration of invalid type should be ignored and not re-diagnosed.
/// ErrorType - Represents the type of an erroneously constructed declaration,
/// expression, or type. When creating ErrorTypes, an associated error
/// diagnostic should always be emitted. That way when later stages of compilation
/// encounter an ErrorType installed by earlier phases they do not have to
/// emit further diagnostics to abort compilation.
class ErrorType final : public TypeBase {
friend class ASTContext;
// The Error type is always canonical.
Expand Down Expand Up @@ -5643,11 +5644,11 @@ inline ArrayRef<AnyFunctionType::Param> AnyFunctionType::getParams() const {
llvm_unreachable("Undefined function type");
}
}

/// If this is a method in a type or extension thereof, compute
/// and return a parameter to be used for the 'self' argument. The type of
/// the parameter is the empty Type() if no 'self' argument should exist. This
/// can only be used after name binding has resolved types.
/// can only be used after types have been resolved.
///
/// \param isInitializingCtor Specifies whether we're computing the 'self'
/// type of an initializing constructor, which accepts an instance 'self'
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Frontend/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ class CompilerInstance {
void performParseOnly(bool EvaluateConditionals = false,
bool ParseDelayedBodyOnEnd = false);

/// Parses and performs name binding on all input files.
/// Parses and performs import resolution on all input files.
///
/// Like a parse-only invocation, a single file is required. Unlike a
/// parse-only invocation, module imports will be processed.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Parse/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ inline ValueDecl *ScopeInfo::lookupValueName(DeclName Name) {
assert(CurScope && "no scope");
// If we found nothing, or we found a decl at the top-level, return nothing.
// We ignore results at the top-level because we may have overloading that
// will be resolved properly by name binding.
// will be resolved properly by name lookup and overload resolution.
std::pair<unsigned, ValueDecl *> Res = HT.lookup(CurScope->HTScope, Name);
if (Res.first < ResolvableDepth)
return 0;
Expand Down
10 changes: 5 additions & 5 deletions include/swift/Subsystems.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,23 @@ namespace swift {
/// Once parsing is complete, this walks the AST to resolve imports, record
/// operators, and do other top-level validation.
///
/// \param StartElem Where to start for incremental name binding in the main
/// \param StartElem Where to start for incremental import and operator resolution in the main
/// source file.
void performNameBinding(SourceFile &SF, unsigned StartElem = 0);
void resolveImportsAndOperators(SourceFile &SF, unsigned StartElem = 0);

/// Once type-checking is complete, this instruments code with calls to an
/// intrinsic that record the expected values of local variables so they can
/// be compared against the results from the debugger.
void performDebuggerTestingTransform(SourceFile &SF);

/// Once parsing and name-binding are complete, this optionally transforms the
/// Once parsing and type checking are complete, this optionally transforms the
/// ASTs to add calls to external logging functions.
///
/// \param HighPerformance True if the playground transform should omit
/// instrumentation that has a high runtime performance impact.
void performPlaygroundTransform(SourceFile &SF, bool HighPerformance);

/// Once parsing and name-binding are complete this optionally walks the ASTs
/// Once parsing and type checking are complete this optionally walks the ASTs
/// to add calls to externally provided functions that simulate
/// "program counter"-like debugging events.
void performPCMacro(SourceFile &SF, TopLevelContext &TLC);
Expand Down Expand Up @@ -201,7 +201,7 @@ namespace swift {
/// \returns a reference to the type checker instance.
TypeChecker &createTypeChecker(ASTContext &Ctx);

/// Once parsing and name-binding are complete, this walks the AST to resolve
/// Once parsing and preliminary import resolution are complete, this walks the AST to resolve
/// types and diagnose problems therein.
///
/// \param StartElem Where to start for incremental type-checking in the main
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ class Verifier : public ASTWalker {
verifyParsed(node);

// If we've bound names already, verify as a bound node.
if (!SF || SF->ASTStage >= SourceFile::NameBound)
if (!SF || SF->ASTStage >= SourceFile::ImportsResolved)
verifyBound(node);

// If we've checked types already, do some extra verification.
Expand Down
104 changes: 47 additions & 57 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,7 @@ void ModuleDecl::getPrecedenceGroups(
void SourceFile::getPrecedenceGroups(
SmallVectorImpl<PrecedenceGroupDecl*> &Results) const {
for (auto pair : PrecedenceGroups) {
if (pair.second.getPointer() && pair.second.getInt()) {
Results.push_back(pair.second.getPointer());
}
Results.push_back(pair.second);
}
}

Expand Down Expand Up @@ -891,9 +889,6 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
}

namespace {
template <typename T>
using OperatorMap = SourceFile::OperatorMap<T>;

template <typename T>
struct OperatorLookup {
// Don't fold this into the static_assert: this would trigger an MSVC bug
Expand Down Expand Up @@ -968,10 +963,10 @@ void SourceFile::setSyntaxRoot(syntax::SourceFileSyntax &&Root) {
SyntaxInfo->SyntaxRoot.emplace(Root);
}

template<typename OP_DECL>
static Optional<OP_DECL *>
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name,
OperatorMap<OP_DECL *> SourceFile::*OP_MAP);
template <typename OP_DECL>
static Optional<OP_DECL *> lookupOperatorDeclForName(
ModuleDecl *M, SourceLoc Loc, Identifier Name,
llvm::DenseMap<Identifier, OP_DECL *> SourceFile::*OP_MAP);

template<typename OP_DECL>
using ImportedOperatorsMap = llvm::SmallDenseMap<OP_DECL*, bool, 16>;
Expand Down Expand Up @@ -1019,12 +1014,10 @@ checkOperatorConflicts(const SourceFile &SF, SourceLoc loc,

// Returns None on error, Optional(nullptr) if no operator decl found, or
// Optional(decl) if decl was found.
template<typename OP_DECL>
static Optional<OP_DECL *>
lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc, Identifier Name,
bool includePrivate,
OperatorMap<OP_DECL *> SourceFile::*OP_MAP)
{
template <typename OP_DECL>
static Optional<OP_DECL *> lookupOperatorDeclForName(
FileUnit &File, SourceLoc Loc, Identifier Name, bool includePrivate,
llvm::DenseMap<Identifier, OP_DECL *> SourceFile::*OP_MAP) {
switch (File.getKind()) {
case FileUnitKind::Builtin:
// The Builtin module declares no operators.
Expand All @@ -1038,12 +1031,12 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc, Identifier Name,
}

auto &SF = cast<SourceFile>(File);
assert(SF.ASTStage >= SourceFile::NameBound);
assert(SF.ASTStage >= SourceFile::ImportsResolved);

// Look for an operator declaration in the current module.
auto found = (SF.*OP_MAP).find(Name);
if (found != (SF.*OP_MAP).end() && (includePrivate || found->second.getInt()))
return found->second.getPointer();
if (found != (SF.*OP_MAP).end())
return found->second;

// Look for imported operator decls.
// Record whether they come from re-exported modules.
Expand All @@ -1070,36 +1063,33 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc, Identifier Name,
importedOperators[op] |= isExported;
}

typename OperatorMap<OP_DECL *>::mapped_type result = { nullptr, true };

OP_DECL *result = nullptr;
if (!importedOperators.empty()) {
auto start = checkOperatorConflicts(SF, Loc, importedOperators);
if (start == importedOperators.end())
return None;
result = { start->first, start->second };
result = start->first;
}

if (includePrivate) {
// Cache the mapping so we don't need to troll imports next time.
// It's not safe to cache the non-private results because we didn't search
// private imports there, but in most non-private cases the result will
// be cached in the final lookup.
auto &mutableOpMap = const_cast<OperatorMap<OP_DECL *> &>(SF.*OP_MAP);
mutableOpMap[Name] = result;
(SF.*OP_MAP)[Name] = result;
}

if (includePrivate || result.getInt())
return result.getPointer();
if (includePrivate)
return result;
return nullptr;
}

template<typename OP_DECL>
static Optional<OP_DECL *>
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name,
OperatorMap<OP_DECL *> SourceFile::*OP_MAP)
{
template <typename OP_DECL>
static Optional<OP_DECL *> lookupOperatorDeclForName(
ModuleDecl *M, SourceLoc Loc, Identifier Name,
llvm::DenseMap<Identifier, OP_DECL *> SourceFile::*OP_MAP) {
OP_DECL *result = nullptr;
for (const FileUnit *File : M->getFiles()) {
for (FileUnit *File : M->getFiles()) {
auto next = lookupOperatorDeclForName(*File, Loc, Name, false, OP_MAP);
if (!next.hasValue())
return next;
Expand All @@ -1113,31 +1103,31 @@ lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name,
return result;
}

#define LOOKUP_OPERATOR(Kind) \
Kind##Decl * \
ModuleDecl::lookup##Kind(Identifier name, SourceLoc loc) { \
auto result = lookupOperatorDeclForName(this, loc, name, \
&SourceFile::Kind##s); \
return result ? *result : nullptr; \
} \
Kind##Decl * \
SourceFile::lookup##Kind(Identifier name, bool isCascading, SourceLoc loc) { \
auto result = lookupOperatorDeclForName(*this, loc, name, true, \
&SourceFile::Kind##s); \
if (!result.hasValue()) \
return nullptr; \
if (ReferencedNames) {\
if (!result.getValue() || \
result.getValue()->getDeclContext()->getModuleScopeContext() != this) {\
ReferencedNames->addTopLevelName(name, isCascading); \
} \
} \
if (!result.getValue()) { \
result = lookupOperatorDeclForName(getParentModule(), loc, name, \
&SourceFile::Kind##s); \
} \
return result.hasValue() ? result.getValue() : nullptr; \
}
#define LOOKUP_OPERATOR(Kind) \
Kind##Decl *ModuleDecl::lookup##Kind(Identifier name, SourceLoc loc) { \
auto result = \
lookupOperatorDeclForName(this, loc, name, &SourceFile::Kind##s); \
return result ? *result : nullptr; \
} \
Kind##Decl *SourceFile::lookup##Kind(Identifier name, bool isCascading, \
SourceLoc loc) { \
auto result = lookupOperatorDeclForName(*this, loc, name, true, \
&SourceFile::Kind##s); \
if (!result.hasValue()) \
return nullptr; \
if (ReferencedNames) { \
if (!result.getValue() || \
result.getValue()->getDeclContext()->getModuleScopeContext() != \
this) { \
ReferencedNames->addTopLevelName(name, isCascading); \
} \
} \
if (!result.getValue()) { \
result = lookupOperatorDeclForName(getParentModule(), loc, name, \
&SourceFile::Kind##s); \
} \
return result.hasValue() ? result.getValue() : nullptr; \
}

LOOKUP_OPERATOR(PrefixOperator)
LOOKUP_OPERATOR(InfixOperator)
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/UnqualifiedLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,7 @@ bool UnqualifiedLookupFactory::shouldDiffer() const {
"swift/test/TypeCoercion/overload_noncall.swift",
"swift/test/expr/capture/nested_class.swift",
"swift/test/expr/capture/order.swift",
"swift/test/NameBinding/name-binding.swift"
"swift/test/ImportResolution/name-binding.swift"
};
StringRef fileName = SF->getFilename();
return llvm::any_of(testsThatShouldDiffer, [&](const char *testFile) {
Expand Down
Loading