@@ -55,6 +55,36 @@ namespace {
55
55
// / source, or it may represent a cross-import overlay that has been found and
56
56
// / needs to be loaded.
57
57
struct UnboundImport {
58
+ // / The source location to use when diagnosing errors for this import.
59
+ SourceLoc importLoc;
60
+
61
+ // / The options for this import, such as "exported" or
62
+ // / "implementation-only". Use this field, not \c attrs, to determine the
63
+ // / behavior expected for this import.
64
+ ImportOptions options;
65
+
66
+ // / If \c options includes \c PrivateImport, the filename we should import
67
+ // / private declarations from.
68
+ StringRef privateImportFileName;
69
+
70
+ // / The kind of declaration expected for a scoped import, or \c Module if
71
+ // / the import is not scoped.
72
+ Located<ImportKind> importKind;
73
+
74
+ // / The module names being imported. There will usually be just one for the
75
+ // / top-level module, but a submodule import will have more.
76
+ ModuleDecl::AccessPathTy modulePath;
77
+
78
+ // / If this is a scoped import, the names of the declaration being imported;
79
+ // / otherwise empty. (Currently the compiler doesn't support nested scoped
80
+ // / imports, so there should always be zero or one elements, but
81
+ // / \c AccessPathTy is the common currency type for this.)
82
+ ModuleDecl::AccessPathTy declPath;
83
+
84
+ //
85
+ // Set only on UnboundImports that represent physical ImportDecls:
86
+ //
87
+
58
88
// / If this UnboundImport directly represents an ImportDecl, the ImportDecl
59
89
// / it represents.
60
90
// /
@@ -63,14 +93,19 @@ namespace {
63
93
// / the other member variables.
64
94
NullablePtr<ImportDecl> ID;
65
95
66
- SourceLoc importLoc;
67
- ImportOptions options;
68
- StringRef privateImportFileName;
69
- Located<ImportKind> importKind;
70
- ModuleDecl::AccessPathTy modulePath;
71
- ModuleDecl::AccessPathTy declPath;
72
-
96
+ // / If this UnboundImport directly represents an ImportDecl, the attributes
97
+ // / of that ImportDecl.
98
+ // /
99
+ // / This property should only be used to improve diagnostics. Don't pull
100
+ // / information about the import's attributes from this property; use
101
+ // / \c options instead.
73
102
NullablePtr<DeclAttributes> attrs;
103
+
104
+ //
105
+ // Set only on UnboundImports that represent cross-import overlays:
106
+ //
107
+
108
+ // / The module this cross-import overlay is overlaying.
74
109
NullablePtr<ModuleDecl> underlyingModule;
75
110
76
111
// / Create an UnboundImport for a user-written import declaration.
@@ -82,16 +117,27 @@ namespace {
82
117
const ImportedModuleDesc &declaringImport,
83
118
const ImportedModuleDesc &bystandingImport);
84
119
85
- // / Make sure the import is not a self-import.
120
+ // / Diagnoses if the import would simply load the module \p SF already
121
+ // / belongs to, with no actual effect.
122
+ // /
123
+ // / Some apparent self-imports do actually load a different module; this
124
+ // / method allows them.
86
125
bool checkNotTautological (const SourceFile &SF);
87
126
88
127
// / Make sure the module actually loaded, and diagnose if it didn't.
89
128
bool checkModuleLoaded (ModuleDecl *M, SourceFile &SF);
90
129
91
- // / Find the top-level module for this module. If \p M is not a submodule,
92
- // / returns \p M. If it is a submodule, returns either the parent module of
93
- // / \p M or \c nullptr if the current module is the parent (which can happen
94
- // / in a mixed-language framework).
130
+ // / Find the top-level module for this module; that is, if \p M is the
131
+ // / module \c Foo.Bar.Baz, this finds \c Foo.
132
+ // /
133
+ // / Specifically, this method returns:
134
+ // /
135
+ // / \li \p M if \p M is a top-level module.
136
+ // / \li \c nullptr if \p M is a submodule of \c SF's parent module. (This
137
+ // / corner case can occur in mixed-source frameworks, where Swift code
138
+ // / can import a Clang submodule of itself.)
139
+ // / \li The top-level parent (i.e. ancestor with no parent) module above
140
+ // / \p M otherwise.
95
141
NullablePtr<ModuleDecl> getTopLevelModule (ModuleDecl *M, SourceFile &SF);
96
142
97
143
// / Diagnose any errors concerning the \c @_exported, \c @_implementationOnly,
@@ -121,21 +167,44 @@ namespace {
121
167
};
122
168
123
169
// / Represents an import whose options have been checked and module has been
124
- // / loaded, but its scope (if any) has not been validated.
170
+ // / loaded, but its scope (if it's a scoped import) has not been validated
171
+ // / and it has not been added to \c SF.
125
172
struct BoundImport {
173
+ // / The \c UnboundImport we bound to produce this import. Used to avoid
174
+ // / duplicating its fields.
126
175
UnboundImport unbound;
176
+
177
+ // / The \c ImportedModuleDesc that should be added to the source file for
178
+ // / this import.
127
179
ImportedModuleDesc desc;
180
+
181
+ // / The module we bound \c unbound to.
128
182
ModuleDecl *module ;
129
- bool needsScopeValidation = false ;
183
+
184
+ // / If \c true, another, more specific \c BoundImport will validate the same
185
+ // / scope as this import, so validating this one is not necessary.
186
+ bool scopeValidatedElsewhere = true ;
130
187
131
188
BoundImport (UnboundImport unbound, ImportedModuleDesc desc,
132
- ModuleDecl *module , bool needsScopeValidation );
189
+ ModuleDecl *module , bool scopeValidatedElsewhere );
133
190
134
191
// / Validate the scope of the import, if needed.
192
+ // /
193
+ // / A "scoped import" is an import which only covers one particular
194
+ // / declaration, such as:
195
+ // /
196
+ // / import class Foundation.NSString
197
+ // /
198
+ // / We validate the scope by making sure that the named declaration exists
199
+ // / and is of the kind indicated by the keyword. This can't be done until we
200
+ // / have bound all cross-import overlays, since a cross-import overlay could
201
+ // / provide the declaration.
135
202
void validateScope (SourceFile &SF);
136
203
};
137
204
138
- class NameBinder : public DeclVisitor <NameBinder> {
205
+ class NameBinder final : public DeclVisitor<NameBinder> {
206
+ friend DeclVisitor<NameBinder>;
207
+
139
208
SourceFile &SF;
140
209
ASTContext &ctx;
141
210
@@ -146,15 +215,15 @@ namespace {
146
215
// / Imports which still need their scoped imports validated.
147
216
SmallVector<BoundImport, 16 > unvalidatedImports;
148
217
149
- // crossImportableModules is usually relatively small (~hundreds max) and
150
- // keeping it in order is convenient, so we use a SmallSetVector for it.
151
- // visibleModules is much larger and we don't care about its order, so we
152
- // use a DenseSet instead.
153
-
154
218
// / All imported modules, including by re-exports, and including submodules.
155
219
llvm::DenseSet<ImportedModuleDesc> visibleModules;
156
220
157
- // / visibleModules but without the submoduless.
221
+ // / \c visibleModules but without the submodules.
222
+ // /
223
+ // / We use a \c SmallSetVector here because this doubles as the worklist for
224
+ // / cross-importing, so we want to keep it in order; this is feasible
225
+ // / because this set is usually fairly small, while \c visibleModules is
226
+ // / often enormous.
158
227
SmallSetVector<ImportedModuleDesc, 64 > crossImportableModules;
159
228
160
229
// / The index of the next module in \c visibleModules that should be
@@ -166,6 +235,11 @@ namespace {
166
235
: SF(SF), ctx(SF.getASTContext())
167
236
{ }
168
237
238
+ // / Postprocess the imports this NameBinder has bound and collect them into
239
+ // / \p imports.
240
+ void finishImports (SmallVectorImpl<ImportedModuleDesc> &imports);
241
+
242
+ private:
169
243
// Special behavior for these decls:
170
244
void visitImportDecl (ImportDecl *ID);
171
245
void visitPrecedenceGroupDecl (PrecedenceGroupDecl *group);
@@ -176,11 +250,6 @@ namespace {
176
250
// Ignore other decls.
177
251
void visitDecl (Decl *D) {}
178
252
179
- // / Postprocess the imports this NameBinder has bound and collect them into
180
- // / a vector.
181
- void finishImports (SmallVectorImpl<ImportedModuleDesc> &imports);
182
-
183
- protected:
184
253
template <typename ...ArgTypes>
185
254
InFlightDiagnostic diagnose (ArgTypes &&...Args) {
186
255
return ctx.Diags .diagnose (std::forward<ArgTypes>(Args)...);
@@ -230,10 +299,14 @@ namespace {
230
299
// / performNameBinding - Once parsing is complete, this walks the AST to
231
300
// / resolve names and do other top-level validation.
232
301
// /
233
- // / At this point parsing has been performed, but we still have
234
- // / UnresolvedDeclRefExpr nodes for unresolved value names, and we may have
235
- // / unresolved type names as well. This handles import directives and forward
236
- // / references.
302
+ // / Most names are actually bound by the type checker, but before we can
303
+ // / type-check a source file, we need to make declarations imported from other
304
+ // / modules available and build tables of the operators and precedecence groups
305
+ // / declared in that file. Name binding processes top-level \c ImportDecl,
306
+ // / \c OperatorDecl, and \c PrecedenceGroupDecl nodes to perform these tasks,
307
+ // / along with related validation.
308
+ // /
309
+ // / Name binding operates on a parsed but otherwise unvalidated AST.
237
310
void swift::performNameBinding (SourceFile &SF) {
238
311
FrontendStatsTracer tracer (SF.getASTContext ().Stats , " Name binding" );
239
312
@@ -343,12 +416,12 @@ void NameBinder::bindImport(UnboundImport &&I) {
343
416
if (topLevelModule && topLevelModule != M) {
344
417
// If we have distinct submodule and top-level module, add both, disabling
345
418
// the top-level module's scoped import validation.
346
- addImport (I, M, false );
347
- addImport (I, topLevelModule.get (), true );
419
+ addImport (I, M, true );
420
+ addImport (I, topLevelModule.get (), false );
348
421
}
349
422
else {
350
423
// Add only the import itself.
351
- addImport (I, M, true );
424
+ addImport (I, M, false );
352
425
}
353
426
354
427
crossImport (M, I);
@@ -358,11 +431,11 @@ void NameBinder::bindImport(UnboundImport &&I) {
358
431
}
359
432
360
433
void NameBinder::addImport (const UnboundImport &I, ModuleDecl *M,
361
- bool needsScopeValidation ) {
434
+ bool scopeValidatedElsewhere ) {
362
435
auto importDesc = I.makeDesc (M);
363
436
364
437
addVisibleModules (importDesc);
365
- unvalidatedImports.emplace_back (I, importDesc, M, needsScopeValidation );
438
+ unvalidatedImports.emplace_back (I, importDesc, M, scopeValidatedElsewhere );
366
439
}
367
440
368
441
// ===----------------------------------------------------------------------===//
@@ -426,10 +499,10 @@ UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) {
426
499
427
500
// / Create an UnboundImport for a user-written import declaration.
428
501
UnboundImport::UnboundImport (ImportDecl *ID)
429
- : ID(ID), importLoc(ID->getLoc ()), options(), privateImportFileName(),
502
+ : importLoc(ID->getLoc ()), options(), privateImportFileName(),
430
503
importKind(ID->getImportKind (), ID->getKindLoc()),
431
504
modulePath(ID->getModulePath ()), declPath(ID->getDeclPath ()),
432
- attrs(&ID->getAttrs ()), underlyingModule()
505
+ ID(ID), attrs(&ID->getAttrs ()), underlyingModule()
433
506
{
434
507
if (ID->isExported ())
435
508
options |= ImportFlags::Exported;
@@ -600,9 +673,9 @@ void UnboundImport::diagnoseInvalidAttr(DeclAttrKind attrKind,
600
673
// ===----------------------------------------------------------------------===//
601
674
602
675
BoundImport::BoundImport (UnboundImport unbound, ImportedModuleDesc desc,
603
- ModuleDecl *module , bool needsScopeValidation )
676
+ ModuleDecl *module , bool scopeValidatedElsewhere )
604
677
: unbound(unbound), desc(desc), module(module ),
605
- needsScopeValidation(needsScopeValidation ) {
678
+ scopeValidatedElsewhere(scopeValidatedElsewhere ) {
606
679
assert (module && " Can't have an import bound to nothing" );
607
680
}
608
681
@@ -680,7 +753,7 @@ static const char *getImportKindString(ImportKind kind) {
680
753
}
681
754
682
755
void BoundImport::validateScope (SourceFile &SF) {
683
- if (unbound.importKind .Item == ImportKind::Module || !needsScopeValidation )
756
+ if (unbound.importKind .Item == ImportKind::Module || scopeValidatedElsewhere )
684
757
return ;
685
758
686
759
ASTContext &ctx = SF.getASTContext ();
@@ -767,15 +840,14 @@ UnboundImport::UnboundImport(ASTContext &ctx,
767
840
const UnboundImport &base, Identifier overlayName,
768
841
const ImportedModuleDesc &declaringImport,
769
842
const ImportedModuleDesc &bystandingImport)
770
- : ID(nullptr ), importLoc(base.importLoc), options(),
771
- privateImportFileName(), importKind({ ImportKind::Module, SourceLoc () }),
772
- modulePath(),
843
+ : importLoc(base.importLoc), options(), privateImportFileName(),
844
+ importKind({ ImportKind::Module, SourceLoc () }), modulePath(),
773
845
// If the declaring import was scoped, inherit that scope in the
774
846
// overlay's import. Note that we do *not* set importKind; this keeps
775
847
// BoundImport::validateScope() from unnecessarily revalidating the
776
848
// scope.
777
849
declPath(declaringImport.module .first),
778
- attrs(nullptr ), underlyingModule(declaringImport.module .second)
850
+ ID( nullptr ), attrs(nullptr ), underlyingModule(declaringImport.module .second)
779
851
{
780
852
modulePath = ctx.AllocateCopy (
781
853
ModuleDecl::AccessPathTy ( { overlayName, base.modulePath [0 ].Loc }));
0 commit comments