Skip to content

Commit 9c263ea

Browse files
committed
Convert @qualified Module in an expr to a DeclRefExpr
This allows us to handle both @qualified Module.TypeName and @qualified Module.funcName non-invasively with the same code paths.
1 parent 1c695c6 commit 9c263ea

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,10 @@ namespace {
939939
/// The expressions that are direct arguments of call expressions.
940940
llvm::SmallPtrSet<Expr *, 4> CallArgs;
941941

942+
/// Simplify TypeExprs which represent a fully-qualified module name only
943+
/// into a DeclRefExpr.
944+
DeclRefExpr *simplifyQualifiedModuleRef(Expr *TE);
945+
942946
/// Simplify expressions which are type sugar productions that got parsed
943947
/// as expressions due to the parser not knowing which identifiers are
944948
/// type names.
@@ -1329,6 +1333,11 @@ namespace {
13291333
return DAE;
13301334
}
13311335

1336+
// Turn qualified references to modules into DeclRefExprs.
1337+
if (auto DRE = simplifyQualifiedModuleRef(expr)) {
1338+
return DRE;
1339+
}
1340+
13321341
// If this is a sugared type that needs to be folded into a single
13331342
// TypeExpr, do it.
13341343
if (auto *simplified = simplifyTypeExpr(expr))
@@ -1397,6 +1406,36 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) {
13971406
return true;
13981407
}
13991408

1409+
static TypeRepr *skipParens(TypeRepr *TR) {
1410+
assert(TR);
1411+
while (isa<TupleTypeRepr>(TR) && cast<TupleTypeRepr>(TR)->isParenType())
1412+
TR = cast<TupleTypeRepr>(TR)->getElement(0).Type;
1413+
return TR;
1414+
}
1415+
1416+
DeclRefExpr *PreCheckExpression::simplifyQualifiedModuleRef(Expr *E) {
1417+
auto TE = dyn_cast<TypeExpr>(E);
1418+
if (!TE || !TE->getTypeRepr()) return nullptr;
1419+
1420+
TypeRepr * Repr = skipParens(TE->getTypeRepr());
1421+
1422+
auto ATR = dyn_cast<AttributedTypeRepr>(Repr);
1423+
if (!ATR || !ATR->getAttrs().has(TAK_qualified)) return nullptr;
1424+
1425+
Repr = skipParens(ATR->getTypeRepr());
1426+
1427+
auto SITR = dyn_cast<SimpleIdentTypeRepr>(Repr);
1428+
if (!SITR) return nullptr;
1429+
1430+
auto modules = TC.lookupUnqualified(DC, SITR->getIdentifier(), SITR->getLoc(),
1431+
NameLookupFlags::IncludeOnlyModules);
1432+
if (modules.size() != 1) return nullptr;
1433+
1434+
ConcreteDeclRef concreteRef(modules.front().getValueDecl());
1435+
return new (TC.Context) DeclRefExpr(concreteRef, DeclNameLoc(TE->getLoc()),
1436+
/*Implicit=*/false);
1437+
}
1438+
14001439
TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) {
14011440
if (!UDE->getName().isSimpleName() ||
14021441
UDE->getName().isSpecial())

test/attr/attr_qualified.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ func uglyInit() -> Int { (@qualified Swift.Int)(bitPattern: 0) } // no-error
1414

1515
func badRef() { Swift.print("hello") } // expected-error {{type 'Swift' has no member 'print'}}
1616
func goodRef() { @qualified Swift.print("hello") } // no-error
17-
func uglyRef() { (@qualified Swift).print("hello") } // no-error
17+
func uglyRef() { (@qualified Swift.print)("hello") } // no-error

0 commit comments

Comments
 (0)