Skip to content

Commit c48a676

Browse files
authored
Merge pull request #31679 from Jumhyn/implicit-member-chains-different-types
[SE-0287] [Sema] Implementation for implicit member chains
2 parents a6c3e6f + 8905f97 commit c48a676

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+976
-560
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ ERROR(expected_argument_in_contextual_member,none,
112112
"member %0 expects argument of type %1", (DeclName, Type))
113113
ERROR(expected_parens_in_contextual_member,none,
114114
"member %0 is a function; did you mean to call it?", (DeclName))
115+
ERROR(expected_parens_in_contextual_member_type,none,
116+
"member %0 is a function that produces expected type %1; did you mean to "
117+
"call it?", (DeclName, Type))
115118

116119
ERROR(expected_result_in_contextual_member,none,
117120
"member %0 in %2 produces result of type %1, but context expects %2",
@@ -453,6 +456,10 @@ ERROR(cannot_convert_closure_result_nil,none,
453456
ERROR(cannot_convert_parent_type,none,
454457
"cannot convert parent type %0 to expected type %1",
455458
(Type, Type))
459+
ERROR(cannot_convert_chain_result_type,none,
460+
"member chain produces result of type %0 but contextual base was "
461+
"inferred as %1",
462+
(Type, Type))
456463

457464
NOTE(generic_argument_mismatch,none,
458465
"arguments to generic parameter %0 (%1 and %2) are expected to be equal",

include/swift/AST/Expr.h

Lines changed: 56 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -249,17 +249,8 @@ class alignas(8) Expr {
249249
NumArgLabels : 16
250250
);
251251

252-
SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 1+1+1+16,
253-
/// Whether the UnresolvedMemberExpr has arguments.
254-
HasArguments : 1,
255-
/// Whether the UnresolvedMemberExpr also has source locations for the
256-
/// argument label.
257-
HasArgLabelLocs : 1,
258-
/// Whether the last argument is a trailing closure.
259-
HasTrailingClosure : 1,
260-
: NumPadBits,
261-
/// # of argument labels stored after the UnresolvedMemberExpr.
262-
NumArgLabels : 16
252+
SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 2,
253+
FunctionRefKind : 2
263254
);
264255

265256
SWIFT_INLINE_BITFIELD(OverloadSetRefExpr, Expr, 2,
@@ -1841,71 +1832,49 @@ class DynamicSubscriptExpr final
18411832
/// member, which is to be resolved with context sensitive type information into
18421833
/// bar.foo. These always have unresolved type.
18431834
class UnresolvedMemberExpr final
1844-
: public Expr,
1845-
public TrailingCallArguments<UnresolvedMemberExpr> {
1835+
: public Expr {
18461836
SourceLoc DotLoc;
18471837
DeclNameLoc NameLoc;
18481838
DeclNameRef Name;
1849-
Expr *Argument;
1850-
1851-
UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc,
1852-
DeclNameRef name, Expr *argument,
1853-
ArrayRef<Identifier> argLabels,
1854-
ArrayRef<SourceLoc> argLabelLocs,
1855-
bool hasTrailingClosure,
1856-
bool implicit);
18571839

18581840
public:
1859-
/// Create a new unresolved member expression with no arguments.
1860-
static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc,
1861-
DeclNameLoc nameLoc, DeclNameRef name,
1862-
bool implicit);
1863-
1864-
/// Create a new unresolved member expression.
1865-
static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc,
1866-
DeclNameLoc nameLoc, DeclNameRef name,
1867-
SourceLoc lParenLoc,
1868-
ArrayRef<Expr *> args,
1869-
ArrayRef<Identifier> argLabels,
1870-
ArrayRef<SourceLoc> argLabelLocs,
1871-
SourceLoc rParenLoc,
1872-
ArrayRef<TrailingClosure> trailingClosures,
1873-
bool implicit);
1841+
UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, DeclNameRef name,
1842+
bool implicit)
1843+
: Expr(ExprKind::UnresolvedMember, implicit), DotLoc(dotLoc),
1844+
NameLoc(nameLoc), Name(name) {
1845+
// FIXME: Really, we should be setting this to `FunctionRefKind::Compound`
1846+
// if `NameLoc` is compound, but this would be a source break for cases like
1847+
// ```
1848+
// struct S {
1849+
// static func makeS(_: Int) -> S! { S() }
1850+
// }
1851+
//
1852+
// let s: S = .makeS(_:)(0)
1853+
// ```
1854+
// Instead, we should store compound-ness as a separate bit from applied/
1855+
// unapplied.
1856+
Bits.UnresolvedMemberExpr.FunctionRefKind =
1857+
static_cast<unsigned>(FunctionRefKind::Unapplied);
1858+
}
18741859

18751860
DeclNameRef getName() const { return Name; }
18761861
DeclNameLoc getNameLoc() const { return NameLoc; }
18771862
SourceLoc getDotLoc() const { return DotLoc; }
1878-
Expr *getArgument() const { return Argument; }
1879-
void setArgument(Expr *argument) { Argument = argument; }
18801863

1881-
/// Whether this reference has arguments.
1882-
bool hasArguments() const {
1883-
return Bits.UnresolvedMemberExpr.HasArguments;
1884-
}
1885-
1886-
unsigned getNumArguments() const {
1887-
return Bits.UnresolvedMemberExpr.NumArgLabels;
1888-
}
1889-
1890-
bool hasArgumentLabelLocs() const {
1891-
return Bits.UnresolvedMemberExpr.HasArgLabelLocs;
1892-
}
1864+
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
18931865

1894-
/// Whether this call with written with a trailing closure.
1895-
bool hasTrailingClosure() const {
1896-
return Bits.UnresolvedMemberExpr.HasTrailingClosure;
1897-
}
1866+
SourceLoc getStartLoc() const { return DotLoc; }
1867+
SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; }
18981868

1899-
/// Return the index of the unlabeled trailing closure argument.
1900-
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
1901-
return getArgument()->getUnlabeledTrailingClosureIndexOfPackedArgument();
1869+
/// Retrieve the kind of function reference.
1870+
FunctionRefKind getFunctionRefKind() const {
1871+
return static_cast<FunctionRefKind>(
1872+
Bits.UnresolvedMemberExpr.FunctionRefKind);
19021873
}
19031874

1904-
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
1905-
1906-
SourceLoc getStartLoc() const { return DotLoc; }
1907-
SourceLoc getEndLoc() const {
1908-
return (Argument ? Argument->getEndLoc() : NameLoc.getSourceRange().End);
1875+
/// Set the kind of function reference.
1876+
void setFunctionRefKind(FunctionRefKind refKind) {
1877+
Bits.UnresolvedMemberExpr.FunctionRefKind = static_cast<unsigned>(refKind);
19091878
}
19101879

19111880
static bool classof(const Expr *E) {
@@ -2088,6 +2057,31 @@ class ParenExpr : public IdentityExpr {
20882057

20892058
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; }
20902059
};
2060+
2061+
/// Represents the result of a chain of accesses or calls hanging off of an
2062+
/// \c UnresolvedMemberExpr at the root. This is only used during type checking
2063+
/// to give the result type of such a chain representation in the AST. This
2064+
/// expression type is always implicit.
2065+
class UnresolvedMemberChainResultExpr : public IdentityExpr {
2066+
/// The base of this chain of member accesses.
2067+
UnresolvedMemberExpr *ChainBase;
2068+
public:
2069+
UnresolvedMemberChainResultExpr(Expr *subExpr, UnresolvedMemberExpr *base,
2070+
Type ty = Type())
2071+
: IdentityExpr(ExprKind::UnresolvedMemberChainResult, subExpr, ty,
2072+
/*isImplicit=*/true),
2073+
ChainBase(base) {
2074+
assert(base);
2075+
}
2076+
2077+
UnresolvedMemberExpr *getChainBase() const { return ChainBase; }
2078+
2079+
SWIFT_FORWARD_SOURCE_LOCS_TO(getSubExpr())
2080+
2081+
static bool classof(const Expr *E) {
2082+
return E->getKind() == ExprKind::UnresolvedMemberChainResult;
2083+
}
2084+
};
20912085

20922086
/// AwaitExpr - An 'await' surrounding an expression, marking that the
20932087
/// expression contains code which is a coroutine that may block.

include/swift/AST/ExprNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ ABSTRACT_EXPR(Identity, Expr)
104104
EXPR(Paren, IdentityExpr)
105105
EXPR(DotSelf, IdentityExpr)
106106
EXPR(Await, IdentityExpr)
107-
EXPR_RANGE(Identity, Paren, Await)
107+
EXPR(UnresolvedMemberChainResult, IdentityExpr)
108+
EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult)
108109
ABSTRACT_EXPR(AnyTry, Expr)
109110
EXPR(Try, AnyTryExpr)
110111
EXPR(ForceTry, AnyTryExpr)

include/swift/AST/Pattern.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ class EnumElementPattern : public Pattern {
554554
bool hasUnresolvedOriginalExpr() const {
555555
return ElementDeclOrUnresolvedOriginalExpr.is<Expr*>();
556556
}
557+
void setUnresolvedOriginalExpr(Expr *e) {
558+
ElementDeclOrUnresolvedOriginalExpr = e;
559+
}
557560

558561
DeclNameLoc getNameLoc() const { return NameLoc; }
559562
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,11 +2108,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21082108
void visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
21092109
printCommon(E, "unresolved_member_expr")
21102110
<< " name='" << E->getName() << "'";
2111-
printArgumentLabels(E->getArgumentLabels());
2112-
if (E->getArgument()) {
2113-
OS << '\n';
2114-
printRec(E->getArgument());
2115-
}
2111+
PrintWithColorRAII(OS, ExprModifierColor)
2112+
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
21162113
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21172114
}
21182115
void visitDotSelfExpr(DotSelfExpr *E) {
@@ -2135,7 +2132,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21352132
printRec(E->getSubExpr());
21362133
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21372134
}
2138-
2135+
void visitUnresolvedMemberChainResultExpr(UnresolvedMemberChainResultExpr *E){
2136+
printCommon(E, "unresolved_member_chain_expr");
2137+
OS << '\n';
2138+
printRec(E->getSubExpr());
2139+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2140+
}
21392141
void visitTupleExpr(TupleExpr *E) {
21402142
printCommon(E, "tuple_expr");
21412143
if (E->hasTrailingClosure())

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -504,17 +504,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
504504
Expr *visitOverloadedDeclRefExpr(OverloadedDeclRefExpr *E) { return E; }
505505
Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) { return E; }
506506

507-
Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
508-
if (E->getArgument()) {
509-
if (auto arg = doIt(E->getArgument())) {
510-
E->setArgument(arg);
511-
return E;
512-
}
513-
514-
return nullptr;
515-
}
516-
return E;
517-
}
507+
Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { return E; }
518508

519509
Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) { return E; }
520510

lib/AST/Expr.cpp

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
288288
return cast<ParenExpr>(this)
289289
->getSubExpr()->getReferencedDecl(stopAtParenExpr);
290290

291+
PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr);
291292
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
292293
PASS_THROUGH_REFERENCE(Await, getSubExpr);
293294
PASS_THROUGH_REFERENCE(Try, getSubExpr);
@@ -606,6 +607,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
606607

607608
case ExprKind::Paren:
608609
case ExprKind::DotSelf:
610+
case ExprKind::UnresolvedMemberChainResult:
609611
case ExprKind::Tuple:
610612
case ExprKind::Array:
611613
case ExprKind::Dictionary:
@@ -1606,61 +1608,6 @@ DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, Expr *index,
16061608
hasTrailingClosure, decl, implicit);
16071609
}
16081610

1609-
UnresolvedMemberExpr::UnresolvedMemberExpr(SourceLoc dotLoc,
1610-
DeclNameLoc nameLoc,
1611-
DeclNameRef name, Expr *argument,
1612-
ArrayRef<Identifier> argLabels,
1613-
ArrayRef<SourceLoc> argLabelLocs,
1614-
bool hasTrailingClosure,
1615-
bool implicit)
1616-
: Expr(ExprKind::UnresolvedMember, implicit),
1617-
DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) {
1618-
Bits.UnresolvedMemberExpr.HasArguments = (argument != nullptr);
1619-
Bits.UnresolvedMemberExpr.NumArgLabels = argLabels.size();
1620-
Bits.UnresolvedMemberExpr.HasArgLabelLocs = !argLabelLocs.empty();
1621-
Bits.UnresolvedMemberExpr.HasTrailingClosure = hasTrailingClosure;
1622-
initializeCallArguments(argLabels, argLabelLocs);
1623-
}
1624-
1625-
UnresolvedMemberExpr *UnresolvedMemberExpr::create(ASTContext &ctx,
1626-
SourceLoc dotLoc,
1627-
DeclNameLoc nameLoc,
1628-
DeclNameRef name,
1629-
bool implicit) {
1630-
size_t size = totalSizeToAlloc({ }, { });
1631-
1632-
void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr));
1633-
return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, nullptr,
1634-
{ }, { },
1635-
/*hasTrailingClosure=*/false,
1636-
implicit);
1637-
}
1638-
1639-
UnresolvedMemberExpr *
1640-
UnresolvedMemberExpr::create(ASTContext &ctx, SourceLoc dotLoc,
1641-
DeclNameLoc nameLoc, DeclNameRef name,
1642-
SourceLoc lParenLoc,
1643-
ArrayRef<Expr *> args,
1644-
ArrayRef<Identifier> argLabels,
1645-
ArrayRef<SourceLoc> argLabelLocs,
1646-
SourceLoc rParenLoc,
1647-
ArrayRef<TrailingClosure> trailingClosures,
1648-
bool implicit) {
1649-
SmallVector<Identifier, 4> argLabelsScratch;
1650-
SmallVector<SourceLoc, 4> argLabelLocsScratch;
1651-
Expr *arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs,
1652-
rParenLoc, trailingClosures, implicit,
1653-
argLabelsScratch, argLabelLocsScratch);
1654-
1655-
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
1656-
1657-
void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr));
1658-
return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, arg,
1659-
argLabels, argLabelLocs,
1660-
trailingClosures.size() == 1,
1661-
implicit);
1662-
}
1663-
16641611
ArrayRef<Identifier> ApplyExpr::getArgumentLabels(
16651612
SmallVectorImpl<Identifier> &scratch) const {
16661613
// Unary operators and 'self' applications have a single, unlabeled argument.

lib/IDE/CodeCompletion.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,14 +4284,18 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
42844284
if (!T->mayHaveMembers())
42854285
return;
42864286

4287-
DeclContext *DC = const_cast<DeclContext *>(CurrDeclContext);
4288-
42894287
// We can only say .foo where foo is a static member of the contextual
42904288
// type and has the same type (or if the member is a function, then the
42914289
// same result type) as the contextual type.
42924290
FilteredDeclConsumer consumer(*this, [=](ValueDecl *VD,
42934291
DeclVisibilityKind Reason) {
4294-
return isReferenceableByImplicitMemberExpr(CurrModule, DC, T, VD);
4292+
if (T->getOptionalObjectType() &&
4293+
VD->getModuleContext()->isStdlibModule()) {
4294+
// In optional context, ignore '.init(<some>)', 'init(nilLiteral:)',
4295+
if (isa<ConstructorDecl>(VD))
4296+
return false;
4297+
}
4298+
return true;
42954299
});
42964300

42974301
auto baseType = MetatypeType::get(T);

0 commit comments

Comments
 (0)