Skip to content

Commit 5de23f5

Browse files
committed
[Sema] Rebase and address feedback for implicit member chains
1 parent 0055501 commit 5de23f5

File tree

8 files changed

+31
-42
lines changed

8 files changed

+31
-42
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ ERROR(expected_argument_in_contextual_member,none,
113113
ERROR(expected_parens_in_contextual_member,none,
114114
"member %0 is a function; did you mean to call it?", (DeclName))
115115
ERROR(expected_parens_in_contextual_member_type,none,
116-
"member %0 is a function that produces expected type %1; did you mean to call it?", (DeclName, Type))
116+
"member %0 is a function that produces expected type %1; did you mean to "
117+
"call it?", (DeclName, Type))
117118

118119
ERROR(expected_result_in_contextual_member,none,
119120
"member %0 in %2 produces result of type %1, but context expects %2",
@@ -456,7 +457,8 @@ ERROR(cannot_convert_parent_type,none,
456457
"cannot convert parent type %0 to expected type %1",
457458
(Type, Type))
458459
ERROR(cannot_convert_chain_result_type,none,
459-
"member chain produces result of type %0 but contextual base was inferred as %1",
460+
"member chain produces result of type %0 but contextual base was "
461+
"inferred as %1",
460462
(Type, Type))
461463

462464
NOTE(generic_argument_mismatch,none,

include/swift/AST/Expr.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,10 +2094,18 @@ class ParenExpr : public IdentityExpr {
20942094
/// to give the result type of such a chain representation in the AST. This
20952095
/// expression type is always implicit.
20962096
class UnresolvedMemberChainResultExpr : public IdentityExpr {
2097+
/// The base of this chain of member accesses.
2098+
UnresolvedMemberExpr *ChainBase;
20972099
public:
2098-
UnresolvedMemberChainResultExpr(Expr *subExpr, Type ty = Type())
2100+
UnresolvedMemberChainResultExpr(Expr *subExpr, UnresolvedMemberExpr *base,
2101+
Type ty = Type())
20992102
: IdentityExpr(ExprKind::UnresolvedMemberChainResult, subExpr, ty,
2100-
/*isImplicit=*/true) {}
2103+
/*isImplicit=*/true),
2104+
ChainBase(base) {
2105+
assert(base);
2106+
}
2107+
2108+
UnresolvedMemberExpr *getChainBase() const { return ChainBase; }
21012109

21022110
SWIFT_FORWARD_SOURCE_LOCS_TO(getSubExpr())
21032111

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2757,7 +2757,7 @@ namespace {
27572757
// an ambiguity tolerant mode used for diagnostic generation. Just leave
27582758
// this as an unresolved member reference.
27592759
Type resultTy = simplifyType(cs.getType(expr));
2760-
if (resultTy->getRValueType()->is<UnresolvedType>()) {
2760+
if (resultTy->hasUnresolvedType()) {
27612761
cs.setType(expr, resultTy);
27622762
return expr;
27632763
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,17 +2160,9 @@ bool ContextualFailure::diagnoseAsError() {
21602160

21612161
case ConstraintLocator::UnresolvedMemberChainResult: {
21622162
auto &solution = getSolution();
2163-
auto member = anchor;
2164-
if (auto *CE = getAsExpr<CallExpr>(anchor))
2165-
member = CE->getFn();
2166-
2167-
auto kind = ConstraintLocator::Member;
2168-
if (isExpr<UnresolvedMemberExpr>(anchor))
2169-
kind = ConstraintLocator::UnresolvedMember;
2170-
else if (isExpr<SubscriptExpr>(anchor))
2171-
kind = ConstraintLocator::SubscriptMember;
2172-
auto overload = getOverloadChoiceIfAvailable(getConstraintLocator(member,
2173-
kind));
2163+
2164+
auto overload =
2165+
getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor));
21742166
if (!(overload && overload->choice.isDecl()))
21752167
return false;
21762168

lib/Sema/CSGen.cpp

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,32 +1503,20 @@ namespace {
15031503
Type visitUnresolvedMemberChainResultExpr(
15041504
UnresolvedMemberChainResultExpr *expr) {
15051505
auto *tail = expr->getSubExpr();
1506-
assert(isa<UnresolvedMemberExpr>(tail) || isa<UnresolvedDotExpr>(tail) ||
1507-
isa<CallExpr>(tail) || isa<BindOptionalExpr>(tail) ||
1508-
isa<ForceValueExpr>(tail) ||
1509-
isa<SubscriptExpr>(tail) &&
1510-
"Unexpected expression at end of unresolved member chain");
1511-
15121506
auto memberTy = CS.getType(tail);
1513-
auto *base = TypeChecker::getUnresolvedMemberChainBase(tail);
1514-
1515-
// FIXME: This is a workaround for SR-13357, should not be necessary.
1516-
// Copy any type variable options from the result of the tail member to
1517-
// the result of the entire chain.
1518-
unsigned additionalOptions = 0;
1519-
if (auto *tvt = memberTy->getAs<TypeVariableType>())
1520-
additionalOptions = tvt->getImpl().getRawOptions();
1507+
auto *base = expr->getChainBase();
1508+
assert(base == TypeChecker::getUnresolvedMemberChainBase(tail));
15211509

1522-
// The contextual type (represented with a new type variable) must equal
1523-
// the base type.
1510+
// The result type of the chain is is represented by a new type variable.
15241511
auto locator = CS.getConstraintLocator(
15251512
expr, ConstraintLocator::UnresolvedMemberChainResult);
1526-
auto tvo = additionalOptions | TVO_CanBindToHole | TVO_CanBindToNoEscape;
1527-
auto chainResultTy = CS.createTypeVariable(locator, tvo);
1528-
auto chainBaseTy = UnresolvedBaseTypes.find(base)->second;
1513+
auto chainResultTy = CS.createTypeVariable(
1514+
locator,
1515+
TVO_CanBindToLValue | TVO_CanBindToHole | TVO_CanBindToNoEscape);
1516+
auto chainBaseTy = getUnresolvedBaseType(base);
15291517

1530-
// The result of this element of the chain must be convertible to the
1531-
// contextual type, and the contextual type must be equal to the base.
1518+
// The result of the last element of the chain must be convertible to the
1519+
// whole chain, and the type of the whole chain must be equal to the base.
15321520
CS.addConstraint(
15331521
ConstraintKind::Conversion, memberTy, chainBaseTy,
15341522
CS.getConstraintLocator(tail, ConstraintLocator::RValueAdjustment));
@@ -3828,7 +3816,6 @@ namespace {
38283816
}
38293817

38303818
if (auto type = CG.visit(expr)) {
3831-
38323819
auto simplifiedType = CS.simplifyType(type);
38333820

38343821
CS.setType(expr, simplifiedType);

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3860,7 +3860,7 @@ void constraints::simplifyLocator(ASTNode &anchor,
38603860
}
38613861

38623862
case ConstraintLocator::UnresolvedMemberChainResult: {
3863-
auto *resultExpr = getAsExpr<UnresolvedMemberChainResultExpr>(anchor);
3863+
auto *resultExpr = castToExpr<UnresolvedMemberChainResultExpr>(anchor);
38643864
anchor = resultExpr->getSubExpr();
38653865
path = path.slice(1);
38663866
continue;

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ namespace {
13701370
if (isMemberChainTail(expr, parent))
13711371
if (auto *UME = TypeChecker::getUnresolvedMemberChainBase(expr))
13721372
if (!parent || !isa<UnresolvedMemberChainResultExpr>(parent))
1373-
return new (ctx) UnresolvedMemberChainResultExpr(expr);
1373+
return new (ctx) UnresolvedMemberChainResultExpr(expr, UME);
13741374

13751375
return expr;
13761376
}

test/expr/delayed-ident/member_chains.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ let _: ImplicitMembers = .implicit[optional: ()] // expected-error {{value of op
126126
let _: ImplicitMembers = .implicit[funcOptional: ()]() // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{55-55= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{55-55=!}}
127127

128128
// FIXME: Improve these diagnostics (should probably offer unwrapping, as above)
129-
let _: ImplicitMembers = .implicit.anotherOptional?.another // expected-error{{cannot infer contextual base in reference to member 'implicit'}} expected-error{{cannot convert value of type 'Optional<_>' to specified type 'ImplicitMembers'}}
130-
let _: ImplicitMembers = .implicit[optionalFunc: ()]?() // expected-error{{cannot infer contextual base in reference to member 'implicit'}} expected-error{{cannot convert value of type 'Optional<_>' to specified type 'ImplicitMembers'}}
129+
let _: ImplicitMembers = .implicit.anotherOptional?.another // expected-error{{type of expression is ambiguous without more context}}
130+
let _: ImplicitMembers = .implicit[optionalFunc: ()]?() // expected-error{{type of expression is ambiguous without more context}}
131131

132132

133133
let _: ImplicitMembers = .other.implicit

0 commit comments

Comments
 (0)