Skip to content

Commit 335baef

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 f926a5b commit 335baef

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
@@ -249,6 +249,24 @@ static void recordShadowedDeclsAfterSignatureMatch(
249249
break;
250250
}
251251

252+
// Prefer declarations in the any module over those in the standard
253+
// library module.
254+
if (auto swiftModule = ctx.getStdlibModule()) {
255+
if ((firstModule == swiftModule) != (secondModule == swiftModule)) {
256+
// If the second module is the standard library module, the second
257+
// declaration is shadowed by the first.
258+
if (secondModule == swiftModule) {
259+
shadowed.insert(secondDecl);
260+
continue;
261+
}
262+
263+
// Otherwise, the first declaration is shadowed by the second. There is
264+
// no point in continuing to compare the first declaration to others.
265+
shadowed.insert(firstDecl);
266+
break;
267+
}
268+
}
269+
252270
// Prefer declarations in an overlay to similar declarations in
253271
// the Clang module it customizes.
254272
if (firstDecl->hasClangNode() != secondDecl->hasClangNode()) {
@@ -331,26 +349,30 @@ static void recordShadowedDecls(ArrayRef<ValueDecl *> decls,
331349
}
332350
}
333351

334-
// We need an interface type here.
335-
if (typeResolver)
336-
typeResolver->resolveDeclSignature(decl);
352+
CanType signature;
337353

338-
// If the decl is currently being validated, this is likely a recursive
339-
// reference and we'll want to skip ahead so as to avoid having its type
340-
// attempt to desugar itself.
341-
if (!decl->hasValidSignature())
342-
continue;
354+
if (!isa<TypeDecl>(decl)) {
355+
// We need an interface type here.
356+
if (typeResolver)
357+
typeResolver->resolveDeclSignature(decl);
343358

344-
// FIXME: the canonical type makes a poor signature, because we don't
345-
// canonicalize away default arguments.
346-
auto signature = decl->getInterfaceType()->getCanonicalType();
359+
// If the decl is currently being validated, this is likely a recursive
360+
// reference and we'll want to skip ahead so as to avoid having its type
361+
// attempt to desugar itself.
362+
if (!decl->hasValidSignature())
363+
continue;
347364

348-
// FIXME: The type of a variable or subscript doesn't include
349-
// enough context to distinguish entities from different
350-
// constrained extensions, so use the overload signature's
351-
// type. This is layering a partial fix upon a total hack.
352-
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
353-
signature = asd->getOverloadSignatureType();
365+
// FIXME: the canonical type makes a poor signature, because we don't
366+
// canonicalize away default arguments.
367+
signature = decl->getInterfaceType()->getCanonicalType();
368+
369+
// FIXME: The type of a variable or subscript doesn't include
370+
// enough context to distinguish entities from different
371+
// constrained extensions, so use the overload signature's
372+
// type. This is layering a partial fix upon a total hack.
373+
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
374+
signature = asd->getOverloadSignatureType();
375+
}
354376

355377
// Record this declaration based on its signature.
356378
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)