Skip to content

Commit 6410e58

Browse files
committed
[NFC] Sema/TypeCheckPattern: Refactor for recursive MemberTypeRepr representation
1 parent 6818207 commit 6410e58

File tree

3 files changed

+90
-100
lines changed

3 files changed

+90
-100
lines changed

include/swift/AST/TypeRepr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ class DeclRefTypeRepr : public TypeRepr {
344344
ArrayRef<TypeRepr *> GenericArgs,
345345
SourceRange AngleBrackets);
346346

347+
/// Returns the qualifier or base type representation. For example, `A.B`
348+
/// for `A.B.C`. The base of a `IdentTypeRepr` is null.
349+
TypeRepr *getBase() const;
350+
347351
/// Returns the root qualifier. For example, `A` for `A.B.C`. The root
348352
/// qualifier of a `IdentTypeRepr` is itself.
349353
TypeRepr *getRoot();

lib/AST/TypeRepr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ DeclRefTypeRepr *DeclRefTypeRepr::create(const ASTContext &C, TypeRepr *Base,
191191
}
192192
}
193193

194+
TypeRepr *DeclRefTypeRepr::getBase() const {
195+
if (isa<IdentTypeRepr>(this)) {
196+
return nullptr;
197+
}
198+
199+
return cast<MemberTypeRepr>(this)->getBase();
200+
}
201+
194202
TypeRepr *DeclRefTypeRepr::getRoot() {
195203
return const_cast<TypeRepr *>(
196204
const_cast<const DeclRefTypeRepr *>(this)->getRoot());

lib/Sema/TypeCheckPattern.cpp

Lines changed: 78 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -171,83 +171,67 @@ static bool hasEnumElementOrStaticVarMember(DeclContext *DC, Type ty,
171171
});
172172
}
173173

174-
namespace {
175-
/// Build up an \c DeclRefTypeRepr and see what it resolves to.
176-
/// FIXME: Support DeclRefTypeRepr nodes with non-identifier base components.
177-
struct ExprToDeclRefTypeRepr : public ASTVisitor<ExprToDeclRefTypeRepr, bool> {
178-
SmallVectorImpl<IdentTypeRepr *> &components;
179-
ASTContext &C;
174+
static DeclRefTypeRepr *translateExprToDeclRefTypeRepr(Expr *E, ASTContext &C) {
175+
// FIXME: Support MemberTypeRepr nodes with non-DeclRefTypeRepr bases.
176+
/// Translates an expression to a \c DeclRefTypeRepr.
177+
class ExprToDeclRefTypeRepr
178+
: public ExprVisitor<ExprToDeclRefTypeRepr, DeclRefTypeRepr *> {
179+
ASTContext &C;
180180

181-
ExprToDeclRefTypeRepr(decltype(components) &components, ASTContext &C)
182-
: components(components), C(C) {}
181+
public:
182+
ExprToDeclRefTypeRepr(ASTContext &C) : C(C) {}
183183

184-
bool visitExpr(Expr *e) {
185-
return false;
186-
}
187-
188-
bool visitTypeExpr(TypeExpr *te) {
189-
if (auto *TR = te->getTypeRepr())
190-
if (auto *ITR = dyn_cast<IdentTypeRepr>(TR)) {
191-
components.push_back(ITR);
192-
return true;
184+
DeclRefTypeRepr *visitExpr(Expr *e) { return nullptr; }
185+
186+
DeclRefTypeRepr *visitTypeExpr(TypeExpr *te) {
187+
return dyn_cast_or_null<IdentTypeRepr>(te->getTypeRepr());
188+
}
189+
190+
DeclRefTypeRepr *visitDeclRefExpr(DeclRefExpr *dre) {
191+
// Get the declared type.
192+
auto *td = dyn_cast<TypeDecl>(dre->getDecl());
193+
if (!td) {
194+
return nullptr;
193195
}
194-
return false;
195-
}
196196

197-
bool visitDeclRefExpr(DeclRefExpr *dre) {
198-
assert(components.empty() && "decl ref should be root element of expr");
199-
200-
// Get the declared type.
201-
if (auto *td = dyn_cast<TypeDecl>(dre->getDecl())) {
202-
components.push_back(
203-
new (C) SimpleIdentTypeRepr(dre->getNameLoc(), td->createNameRef()));
204-
components.back()->setValue(td, nullptr);
205-
return true;
197+
auto *repr =
198+
new (C) SimpleIdentTypeRepr(dre->getNameLoc(), td->createNameRef());
199+
repr->setValue(td, nullptr);
200+
201+
return repr;
206202
}
207-
return false;
208-
}
209-
210-
bool visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *udre) {
211-
assert(components.empty() && "decl ref should be root element of expr");
212-
// Track the AST location of the component.
213-
components.push_back(
214-
new (C) SimpleIdentTypeRepr(udre->getNameLoc(),
215-
udre->getName()));
216-
return true;
217-
}
218-
219-
bool visitUnresolvedDotExpr(UnresolvedDotExpr *ude) {
220-
if (!visit(ude->getBase()))
221-
return false;
222-
223-
assert(!components.empty() && "no components before dot expr?!");
224203

225-
// Track the AST location of the new component.
226-
components.push_back(
227-
new (C) SimpleIdentTypeRepr(ude->getNameLoc(),
228-
ude->getName()));
229-
return true;
230-
}
231-
232-
bool visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *use) {
233-
if (!visit(use->getSubExpr()))
234-
return false;
235-
236-
assert(!components.empty() && "no components before generic args?!");
237-
238-
// Track the AST location of the generic arguments.
239-
auto origComponent = components.back();
240-
components.back() =
241-
GenericIdentTypeRepr::create(C, origComponent->getNameLoc(),
242-
origComponent->getNameRef(),
243-
use->getUnresolvedParams(),
244-
SourceRange(use->getLAngleLoc(),
245-
use->getRAngleLoc()));
246-
247-
return true;
248-
}
249-
};
250-
} // end anonymous namespace
204+
DeclRefTypeRepr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *udre) {
205+
return new (C) SimpleIdentTypeRepr(udre->getNameLoc(), udre->getName());
206+
}
207+
208+
DeclRefTypeRepr *visitUnresolvedDotExpr(UnresolvedDotExpr *ude) {
209+
auto *base = visit(ude->getBase());
210+
if (!base) {
211+
return nullptr;
212+
}
213+
214+
return MemberTypeRepr::create(C, base, ude->getNameLoc(), ude->getName());
215+
}
216+
217+
DeclRefTypeRepr *
218+
visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *use) {
219+
auto *base = visit(use->getSubExpr());
220+
if (!base) {
221+
return nullptr;
222+
}
223+
224+
assert(!base->hasGenericArgList() && "Already has generic arguments");
225+
226+
return DeclRefTypeRepr::create(
227+
C, base->getBase(), base->getNameLoc(), base->getNameRef(),
228+
use->getUnresolvedParams(),
229+
SourceRange(use->getLAngleLoc(), use->getRAngleLoc()));
230+
}
231+
} translator(C);
232+
233+
return translator.visit(E);
234+
}
251235

252236
namespace {
253237
class ResolvePattern : public ASTVisitor<ResolvePattern,
@@ -470,15 +454,15 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
470454
// Member syntax 'T.Element' forms a pattern if 'T' is an enum and the
471455
// member name is a member of the enum.
472456
Pattern *visitUnresolvedDotExpr(UnresolvedDotExpr *ude) {
473-
SmallVector<IdentTypeRepr *, 2> components;
474-
if (!ExprToDeclRefTypeRepr(components, Context).visit(ude->getBase()))
457+
DeclRefTypeRepr *repr =
458+
translateExprToDeclRefTypeRepr(ude->getBase(), Context);
459+
if (!repr) {
475460
return nullptr;
461+
}
476462

477463
const auto options =
478464
TypeResolutionOptions(llvm::None) | TypeResolutionFlags::SilenceErrors;
479465

480-
DeclRefTypeRepr *repr = MemberTypeRepr::create(Context, components);
481-
482466
// See if the repr resolves to a type.
483467
const auto ty = TypeResolution::resolveContextualType(
484468
repr, DC, options,
@@ -572,39 +556,36 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
572556
return P;
573557
}
574558

575-
SmallVector<IdentTypeRepr *, 2> components;
576-
if (!ExprToDeclRefTypeRepr(components, Context).visit(ce->getFn()))
577-
return nullptr;
578-
579-
if (components.empty())
559+
DeclRefTypeRepr *repr =
560+
translateExprToDeclRefTypeRepr(ce->getFn(), Context);
561+
if (!repr) {
580562
return nullptr;
563+
}
581564

582-
auto tailComponent = components.pop_back_val();
583565
EnumElementDecl *referencedElement = nullptr;
584566
TypeExpr *baseTE = nullptr;
585567

586-
if (components.empty()) {
587-
// Only one component. Try looking up an enum element in context.
588-
referencedElement
589-
= lookupUnqualifiedEnumMemberElement(DC, tailComponent->getNameRef(),
590-
tailComponent->getLoc());
568+
if (isa<IdentTypeRepr>(repr)) {
569+
// Not qualified. Try looking up an enum element in context.
570+
referencedElement = lookupUnqualifiedEnumMemberElement(
571+
DC, repr->getNameRef(), repr->getLoc());
591572
if (!referencedElement)
592573
return nullptr;
593574

594575
auto *enumDecl = referencedElement->getParentEnum();
595576
baseTE = TypeExpr::createImplicit(enumDecl->getDeclaredTypeInContext(),
596577
Context);
597578
} else {
598-
const auto options = TypeResolutionOptions(llvm::None) |
599-
TypeResolutionFlags::SilenceErrors;
600-
601579
// Otherwise, see whether we had an enum type as the penultimate
602580
// component, and look up an element inside it.
603-
DeclRefTypeRepr *prefixRepr = MemberTypeRepr::create(Context, components);
581+
auto *qualIdentTR = cast<MemberTypeRepr>(repr);
582+
583+
const auto options = TypeResolutionOptions(llvm::None) |
584+
TypeResolutionFlags::SilenceErrors;
604585

605586
// See first if the entire repr resolves to a type.
606587
const Type enumTy = TypeResolution::resolveContextualType(
607-
prefixRepr, DC, options,
588+
qualIdentTR->getBase(), DC, options,
608589
[](auto unboundTy) {
609590
// FIXME: Don't let unbound generic types escape type
610591
// resolution. For now, just return the unbound generic type.
@@ -619,26 +600,23 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
619600
if (!enumDecl)
620601
return nullptr;
621602

622-
referencedElement
623-
= lookupEnumMemberElement(DC, enumTy,
624-
tailComponent->getNameRef(),
625-
tailComponent->getLoc());
603+
referencedElement = lookupEnumMemberElement(
604+
DC, enumTy, qualIdentTR->getNameRef(), qualIdentTR->getLoc());
626605
if (!referencedElement)
627606
return nullptr;
628607

629608
baseTE = TypeExpr::createForMemberDecl(
630-
prefixRepr, tailComponent->getNameLoc(), enumDecl);
609+
qualIdentTR->getBase(), qualIdentTR->getNameLoc(), enumDecl);
631610
baseTE->setType(MetatypeType::get(enumTy));
632611
}
633612

634613
assert(baseTE && baseTE->getType() && "Didn't initialize base expression?");
635-
assert(!isa<GenericIdentTypeRepr>(tailComponent) &&
636-
"should be handled above");
614+
assert(!repr->hasGenericArgList() && "should be handled above");
637615

638616
auto *subPattern = composeTupleOrParenPattern(ce->getArgs());
639617
return new (Context) EnumElementPattern(
640-
baseTE, SourceLoc(), tailComponent->getNameLoc(),
641-
tailComponent->getNameRef(), referencedElement, subPattern, DC);
618+
baseTE, SourceLoc(), repr->getNameLoc(), repr->getNameRef(),
619+
referencedElement, subPattern, DC);
642620
}
643621
};
644622

0 commit comments

Comments
 (0)