Skip to content

Commit 9a1e92e

Browse files
committed
[AST] Add getDecl parameter to Expr::isTypeRerefence
So it could be extended to support not yet fully type-checked AST when used by constraint system solver.
1 parent e8c8c0b commit 9a1e92e

File tree

4 files changed

+35
-47
lines changed

4 files changed

+35
-47
lines changed

include/swift/AST/Expr.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,11 @@ class alignas(8) Expr {
466466
/// This distinguishes static references to types, like Int, from metatype
467467
/// values, "someTy: Any.Type".
468468
bool isTypeReference(llvm::function_ref<Type(const Expr *)> getType =
469-
[](const Expr *E) -> Type {
470-
return E->getType();
471-
}) const;
469+
[](const Expr *E) -> Type { return E->getType(); },
470+
llvm::function_ref<Decl *(const Expr *)> getDecl =
471+
[](const Expr *E) -> Decl * {
472+
return nullptr;
473+
}) const;
472474

473475
/// Determine whether this expression refers to a statically-derived metatype.
474476
///

lib/AST/Expr.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,8 @@ void Expr::forEachChildExpr(llvm::function_ref<Expr *(Expr *)> callback) {
440440
}
441441

442442
bool Expr::isTypeReference(
443-
llvm::function_ref<Type(const Expr *)> getType) const {
443+
llvm::function_ref<Type(const Expr *)> getType,
444+
llvm::function_ref<Decl *(const Expr *)> getDecl) const {
444445
// If the result isn't a metatype, there's nothing else to do.
445446
if (!getType(this)->is<AnyMetatypeType>())
446447
return false;
@@ -461,6 +462,12 @@ bool Expr::isTypeReference(
461462
if (auto memberRef = dyn_cast<MemberRefExpr>(expr))
462463
return isa<TypeDecl>(memberRef->getMember().getDecl());
463464

465+
// Any other expressions which might be referencing
466+
// a declaration e.g. not yet type-checked ones like
467+
// `UnresolvedDotExpr`.
468+
if (auto *decl = getDecl(expr))
469+
return isa<TypeDecl>(decl);
470+
464471
// When the base of a "." expression is ignored, look at the member.
465472
if (auto ignoredDot = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr)) {
466473
expr = ignoredDot->getRHS();
@@ -470,7 +477,6 @@ bool Expr::isTypeReference(
470477
// Anything else is not statically derived.
471478
return false;
472479
} while (true);
473-
474480
}
475481

476482
bool Expr::isStaticallyDerivedMetatype(

lib/Sema/CSApply.cpp

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -227,51 +227,25 @@ getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member,
227227
return member->getAccessSemanticsFromContext(DC, isAccessOnSelf);
228228
}
229229

230-
/// This effectively duplicates logic of `Expr::isTypeReference` with
231-
/// one significant difference - support for `UnresolvedDotExpr` and
232-
/// `UnresolvedMemberExpr`. This method could be used on not yet
233-
/// fully type-checked AST.
230+
/// This extends functionality of `Expr::isTypeReference` with
231+
/// support for `UnresolvedDotExpr` and `UnresolvedMemberExpr`.
232+
/// This method could be used on not yet fully type-checked AST.
234233
bool ConstraintSystem::isTypeReference(const Expr *E) {
235-
// If the result isn't a metatype, there's nothing else to do.
236-
if (!getType(E)->is<AnyMetatypeType>())
237-
return false;
238-
239-
Expr *expr = const_cast<Expr *>(E);
240-
do {
241-
// Skip syntax.
242-
expr = expr->getSemanticsProvidingExpr();
243-
244-
// Direct reference to a type.
245-
if (auto declRef = dyn_cast<DeclRefExpr>(expr))
246-
if (isa<TypeDecl>(declRef->getDecl()))
247-
return true;
248-
249-
if (isa<TypeExpr>(expr))
250-
return true;
251-
252-
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
253-
return isa<TypeDecl>(findResolvedMemberRef(
254-
getConstraintLocator(UDE, ConstraintLocator::Member)));
255-
}
256-
257-
if (auto *UME = dyn_cast<UnresolvedMemberExpr>(expr)) {
258-
return isa<TypeDecl>(findResolvedMemberRef(
259-
getConstraintLocator(UME, ConstraintLocator::UnresolvedMember)));
260-
}
261-
262-
// A "." expression that refers to a member.
263-
if (auto memberRef = dyn_cast<MemberRefExpr>(expr))
264-
return isa<TypeDecl>(memberRef->getMember().getDecl());
234+
return E->isTypeReference(
235+
[&](const Expr *E) -> Type { return getType(E); },
236+
[&](const Expr *E) -> Decl * {
237+
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(E)) {
238+
return findResolvedMemberRef(
239+
getConstraintLocator(UDE, ConstraintLocator::Member));
240+
}
265241

266-
// When the base of a "." expression is ignored, look at the member.
267-
if (auto ignoredDot = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr)) {
268-
expr = ignoredDot->getRHS();
269-
continue;
270-
}
242+
if (auto *UME = dyn_cast<UnresolvedMemberExpr>(E)) {
243+
return findResolvedMemberRef(
244+
getConstraintLocator(UME, ConstraintLocator::UnresolvedMember));
245+
}
271246

272-
// Anything else is not statically derived.
273-
return false;
274-
} while (true);
247+
return nullptr;
248+
});
275249
}
276250

277251
bool ConstraintSystem::isStaticallyDerivedMetatype(const Expr *E) {

lib/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,12 @@ class ConstraintSystem {
17621762
pathElt.getNewSummaryFlags());
17631763
}
17641764

1765+
ConstraintLocator *
1766+
getConstraintLocator(const Expr *anchor,
1767+
ConstraintLocator::PathElement pathElt) {
1768+
return getConstraintLocator(const_cast<Expr *>(anchor), pathElt);
1769+
}
1770+
17651771
/// Extend the given constraint locator with a path element.
17661772
ConstraintLocator *
17671773
getConstraintLocator(ConstraintLocator *locator,

0 commit comments

Comments
 (0)