Skip to content

[NFC] Rework types and terms for imports' access paths #33716

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
Sep 11, 2020
Merged
22 changes: 22 additions & 0 deletions docs/Lexicon.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ introduces [reabstraction](#reabstraction) conversions when a value is used with
different abstraction pattern. (This is where the infamous "reabstraction
thunk helpers" sometimes seen in Swift backtraces come from.)

## access path

Broadly, an "access path" is a list of "accesses" which must be chained together
to compute some output from an input. For instance, the generics system has a
type called a `ConformanceAccessPath` which explains how to, for example,
walk from `T: Collection` to `T: Sequence` to `T.Iterator: IteratorProtocol`.
There are several different kinds of "access path" in different parts of the compiler,
but they all follow this basic theme.

In the specific context of imports, an "access path" is the `Bar` portion of a scoped
import like `import class Foo.Bar`. Theoretically, it could have several identifiers
to designate a nested type, although the compiler doesn't currently support this. It can
also be empty, matching all top-level declarations in the module.

Note, however, that there has historically been some confusion about the meaning of
"access path" with regards to imports. You might see some code use "access path"
to include the `Foo` part or even to describe a chain of submodule names where a
declaration is not valid at all. (Strictly, the chain of module names is a "module path"
and the combination of module path + access path is an "import path".)

See `ImportPath` and the types nested inside it for more on this.

## archetype

A placeholder for a generic parameter or an associated type within a
Expand Down
9 changes: 6 additions & 3 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/Evaluator.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Import.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
Expand Down Expand Up @@ -859,12 +860,12 @@ class ASTContext final {
///
/// Note that even if this check succeeds, errors may still occur if the
/// module is loaded in full.
bool canImportModule(Located<Identifier> ModulePath);
bool canImportModule(ImportPath::Element ModulePath);

/// \returns a module with a given name that was already loaded. If the
/// module was not loaded, returns nullptr.
ModuleDecl *getLoadedModule(
ArrayRef<Located<Identifier>> ModulePath) const;
ImportPath::Module ModulePath) const;

ModuleDecl *getLoadedModule(Identifier ModuleName) const;

Expand All @@ -874,10 +875,12 @@ class ASTContext final {
/// be returned.
///
/// \returns The requested module, or NULL if the module cannot be found.
ModuleDecl *getModule(ArrayRef<Located<Identifier>> ModulePath);
ModuleDecl *getModule(ImportPath::Module ModulePath);

ModuleDecl *getModuleByName(StringRef ModuleName);

ModuleDecl *getModuleByIdentifier(Identifier ModuleID);

/// Returns the standard library module, or null if the library isn't present.
///
/// If \p loadIfAbsent is true, the ASTContext will attempt to load the module
Expand Down
53 changes: 16 additions & 37 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1457,46 +1457,28 @@ class GenericContext : private _GenericContext, public DeclContext {
static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
sizeof(GenericContext), "Please add fields to _GenericContext");

/// Describes what kind of name is being imported.
///
/// If the enumerators here are changed, make sure to update all diagnostics
/// using ImportKind as a select index.
enum class ImportKind : uint8_t {
Module = 0,
Type,
Struct,
Class,
Enum,
Protocol,
Var,
Func
};

/// ImportDecl - This represents a single import declaration, e.g.:
/// import Swift
/// import typealias Swift.Int
class ImportDecl final : public Decl,
private llvm::TrailingObjects<ImportDecl, Located<Identifier>> {
private llvm::TrailingObjects<ImportDecl, ImportPath::Element> {
friend TrailingObjects;
friend class Decl;
public:
typedef Located<Identifier> AccessPathElement;

private:
SourceLoc ImportLoc;
SourceLoc KindLoc;

/// The resolved module.
ModuleDecl *Mod = nullptr;

ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);
SourceLoc KindLoc, ImportPath Path);

public:
static ImportDecl *create(ASTContext &C, DeclContext *DC,
SourceLoc ImportLoc, ImportKind Kind,
SourceLoc KindLoc,
ArrayRef<AccessPathElement> Path,
ImportPath Path,
ClangNode ClangN = ClangNode());

/// Returns the import kind that is most appropriate for \p VD.
Expand All @@ -1511,26 +1493,21 @@ class ImportDecl final : public Decl,
/// cannot be overloaded, returns None.
static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);

ArrayRef<AccessPathElement> getFullAccessPath() const {
return {getTrailingObjects<AccessPathElement>(),
static_cast<size_t>(Bits.ImportDecl.NumPathElements)};
ImportKind getImportKind() const {
return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
}

ArrayRef<AccessPathElement> getModulePath() const {
auto result = getFullAccessPath();
if (getImportKind() != ImportKind::Module)
result = result.slice(0, result.size()-1);
return result;
ImportPath getImportPath() const {
return ImportPath({ getTrailingObjects<ImportPath::Element>(),
static_cast<size_t>(Bits.ImportDecl.NumPathElements) });
}

ArrayRef<AccessPathElement> getDeclPath() const {
if (getImportKind() == ImportKind::Module)
return {};
return getFullAccessPath().back();
ImportPath::Module getModulePath() const {
return getImportPath().getModulePath(getImportKind());
}

ImportKind getImportKind() const {
return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
ImportPath::Access getAccessPath() const {
return getImportPath().getAccessPath(getImportKind());
}

bool isExported() const {
Expand All @@ -1549,9 +1526,11 @@ class ImportDecl final : public Decl,
}

SourceLoc getStartLoc() const { return ImportLoc; }
SourceLoc getLocFromSource() const { return getFullAccessPath().front().Loc; }
SourceLoc getLocFromSource() const {
return getImportPath().getSourceRange().Start;
}
SourceRange getSourceRange() const {
return SourceRange(ImportLoc, getFullAccessPath().back().Loc);
return SourceRange(ImportLoc, getImportPath().getSourceRange().End);
}
SourceLoc getKindLoc() const { return KindLoc; }

Expand Down
6 changes: 3 additions & 3 deletions include/swift/AST/FileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,20 @@ class FileUnit : public DeclContext {
/// Find ValueDecls in the module and pass them to the given consumer object.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
virtual void lookupVisibleDecls(ImportPath::Access accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) const {}

/// Finds all class members defined in this file.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupClassMembers(ModuleDecl::AccessPathTy accessPath,
virtual void lookupClassMembers(ImportPath::Access accessPath,
VisibleDeclConsumer &consumer) const {}

/// Finds class members defined in this file with the given name.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupClassMember(ModuleDecl::AccessPathTy accessPath,
virtual void lookupClassMember(ImportPath::Access accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results) const {}

Expand Down
Loading