Skip to content

Commit 61b7eff

Browse files
committed
Sema: Always model nested types as member accesses
When an unqualified reference is overloaded, we would walk the list of overload candidates and check if they are all member accesses. If they are, we would form an UnresolvedMemberRefExpr with the right base. Otherwise, we would form an UnresolvedDeclRefExpr. Now, consider forming an UnresolvedMemberRefExpr even if some of the members are types. This forces all nested type lookups to go through getTypeOfMemberReference(), not getTypeOfReference(). As a result, we no longer pass nested types to the resolveTypeInContext() function from expression checking. This will allow resolveTypeInContext() to take the base declaration on which the nested type was found as a parameter, instead of walking parent DeclContexts to try to guess what the right base was.
1 parent 773d7b3 commit 61b7eff

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,28 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) {
498498

499499
// FIXME: Need to refactor the way we build an AST node from a lookup result!
500500

501+
// If we have an unambiguous reference to a type decl, form a TypeExpr.
502+
if (Lookup.size() == 1 && UDRE->getRefKind() == DeclRefKind::Ordinary &&
503+
isa<TypeDecl>(Lookup[0].Decl)) {
504+
auto *D = cast<TypeDecl>(Lookup[0].Decl);
505+
// FIXME: This is odd.
506+
if (isa<ModuleDecl>(D)) {
507+
return new (Context) DeclRefExpr(D, UDRE->getNameLoc(),
508+
/*Implicit=*/false,
509+
AccessSemantics::Ordinary,
510+
D->getInterfaceType());
511+
}
512+
513+
return TypeExpr::createForDecl(Loc, D,
514+
UDRE->isImplicit());
515+
}
516+
501517
bool AllDeclRefs = true;
502518
SmallVector<ValueDecl*, 4> ResultValues;
503519
for (auto Result : Lookup) {
504520
// If we find a member, then all of the results aren't non-members.
505521
bool IsMember = Result.Base && !isa<ModuleDecl>(Result.Base);
506-
if (IsMember && !isa<TypeDecl>(Result.Decl)) {
522+
if (IsMember) {
507523
AllDeclRefs = false;
508524
break;
509525
}
@@ -532,21 +548,6 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) {
532548
if (matchesDeclRefKind(D, UDRE->getRefKind()))
533549
ResultValues.push_back(D);
534550
}
535-
536-
// If we have an unambiguous reference to a type decl, form a TypeExpr.
537-
if (ResultValues.size() == 1 && UDRE->getRefKind() == DeclRefKind::Ordinary &&
538-
isa<TypeDecl>(ResultValues[0])) {
539-
// FIXME: This is odd.
540-
if (isa<ModuleDecl>(ResultValues[0])) {
541-
return new (Context) DeclRefExpr(ResultValues[0], UDRE->getNameLoc(),
542-
/*Implicit=*/false,
543-
AccessSemantics::Ordinary,
544-
ResultValues[0]->getInterfaceType());
545-
}
546-
547-
return TypeExpr::createForDecl(Loc, cast<TypeDecl>(ResultValues[0]),
548-
UDRE->isImplicit());
549-
}
550551

551552
if (AllDeclRefs) {
552553
// Diagnose uses of operators that found no matching candidates.
@@ -607,7 +608,11 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) {
607608

608609
if (AllMemberRefs) {
609610
Expr *BaseExpr;
610-
if (auto NTD = dyn_cast<NominalTypeDecl>(Base)) {
611+
if (auto PD = dyn_cast<ProtocolDecl>(Base)) {
612+
BaseExpr = TypeExpr::createForDecl(Loc,
613+
PD->getGenericParams()->getParams().front(),
614+
/*isImplicit=*/true);
615+
} else if (auto NTD = dyn_cast<NominalTypeDecl>(Base)) {
611616
BaseExpr = TypeExpr::createForDecl(Loc, NTD, /*isImplicit=*/true);
612617
} else {
613618
BaseExpr = new (Context) DeclRefExpr(Base, UDRE->getNameLoc(),

0 commit comments

Comments
 (0)