Skip to content

Commit 9f61301

Browse files
committed
[Name lookup] Enable shadowing for type lookup and of the Swift module.
Tweak the shadowing rules in two ways: 1) For unqualified type lookup, apply shadowing rules. Without this, we would always get an ambiguity if there were two types with the same name, so this should be a strict improvement. 2) Allow a name introduced in any other module to shadow a name in the Swift standard library. This is (another) weak form of a more sensible, generalized rule that would use the import graph to describe shadowing. Together, these tweaks allow the Result type that was recently introduced in the standard library to exist without breaking source compatibility for Swift code that is already using a Result type. The user Result type will shadow (hide) the Swift one. The latter can be spelled Swift.Result if it is needed by such code. Fixes rdar://problem/46767892.
1 parent aa5dc6c commit 9f61301

File tree

3 files changed

+57
-17
lines changed

3 files changed

+57
-17
lines changed

lib/AST/NameLookup.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,24 @@ static void recordShadowedDeclsAfterSignatureMatch(
254254
break;
255255
}
256256

257+
// Prefer declarations in the any module over those in the standard
258+
// library module.
259+
if (auto swiftModule = ctx.getStdlibModule()) {
260+
if ((firstModule == swiftModule) != (secondModule == swiftModule)) {
261+
// If the second module is the standard library module, the second
262+
// declaration is shadowed by the first.
263+
if (secondModule == swiftModule) {
264+
shadowed.insert(secondDecl);
265+
continue;
266+
}
267+
268+
// Otherwise, the first declaration is shadowed by the second. There is
269+
// no point in continuing to compare the first declaration to others.
270+
shadowed.insert(firstDecl);
271+
break;
272+
}
273+
}
274+
257275
// Prefer declarations in an overlay to similar declarations in
258276
// the Clang module it customizes.
259277
if (firstDecl->hasClangNode() != secondDecl->hasClangNode()) {
@@ -336,26 +354,30 @@ static void recordShadowedDecls(ArrayRef<ValueDecl *> decls,
336354
}
337355
}
338356

339-
// We need an interface type here.
340-
if (typeResolver)
341-
typeResolver->resolveDeclSignature(decl);
357+
CanType signature;
342358

343-
// If the decl is currently being validated, this is likely a recursive
344-
// reference and we'll want to skip ahead so as to avoid having its type
345-
// attempt to desugar itself.
346-
if (!decl->hasValidSignature())
347-
continue;
359+
if (!isa<TypeDecl>(decl)) {
360+
// We need an interface type here.
361+
if (typeResolver)
362+
typeResolver->resolveDeclSignature(decl);
348363

349-
// FIXME: the canonical type makes a poor signature, because we don't
350-
// canonicalize away default arguments.
351-
auto signature = decl->getInterfaceType()->getCanonicalType();
364+
// If the decl is currently being validated, this is likely a recursive
365+
// reference and we'll want to skip ahead so as to avoid having its type
366+
// attempt to desugar itself.
367+
if (!decl->hasValidSignature())
368+
continue;
352369

353-
// FIXME: The type of a variable or subscript doesn't include
354-
// enough context to distinguish entities from different
355-
// constrained extensions, so use the overload signature's
356-
// type. This is layering a partial fix upon a total hack.
357-
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
358-
signature = asd->getOverloadSignatureType();
370+
// FIXME: the canonical type makes a poor signature, because we don't
371+
// canonicalize away default arguments.
372+
signature = decl->getInterfaceType()->getCanonicalType();
373+
374+
// FIXME: The type of a variable or subscript doesn't include
375+
// enough context to distinguish entities from different
376+
// constrained extensions, so use the overload signature's
377+
// type. This is layering a partial fix upon a total hack.
378+
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
379+
signature = asd->getOverloadSignatureType();
380+
}
359381

360382
// Record this declaration based on its signature.
361383
auto &known = collisions[signature];
@@ -1169,6 +1191,11 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
11691191
lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup,
11701192
resolutionKind, TypeResolver, DC, extraImports);
11711193

1194+
// Always perform name shadowing for type lookup.
1195+
if (options.contains(Flags::TypeLookup)) {
1196+
removeShadowedDecls(CurModuleResults, &M);
1197+
}
1198+
11721199
for (auto VD : CurModuleResults)
11731200
Results.push_back(LookupResultEntry(VD));
11741201

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public enum Result<Value, Error> {
2+
case success(Value)
3+
case failure(Error)
4+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/HasResult.swift
3+
// RUN: %target-swift-frontend -typecheck %s -I %t -verify
4+
5+
import HasResult
6+
7+
func foo() -> Result<Int, Error> {
8+
return Result<Int, Error>.success(42)
9+
}

0 commit comments

Comments
 (0)