Skip to content

[5.0][ConstraintSystem] Erase InOutExpr from member base #21222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,20 +1190,6 @@ ConstraintSystem::getTypeOfMemberReference(
// Figure out the instance type used for the base.
Type baseObjTy = getFixedTypeRecursive(baseTy, /*wantRValue=*/true);

ParameterTypeFlags baseFlags;
// FIXME(diagnostics): `InOutType` could appear here as a result
// of successful re-typecheck of the one of the sub-expressions e.g.
// `let _: Int = { (s: inout S) in s.bar() }`. On the first
// attempt to type-check whole expression `s.bar()` - is going
// to have a base which points directly to declaration of `S`.
// But when diagnostics attempts to type-check `s.bar()` standalone
// its base would be tranformed into `InOutExpr -> DeclRefExr`,
// and `InOutType` is going to be recorded in constraint system.
if (auto objType = baseObjTy->getInOutObjectType()) {
baseObjTy = objType;
baseFlags = baseFlags.withInOut(true);
}

bool isInstance = true;
if (auto baseMeta = baseObjTy->getAs<AnyMetatypeType>()) {
baseObjTy = baseMeta->getInstanceType();
Expand All @@ -1215,7 +1201,7 @@ ConstraintSystem::getTypeOfMemberReference(
return getTypeOfReference(value, functionRefKind, locator, useDC, base);
}

FunctionType::Param baseObjParam(baseObjTy, Identifier(), baseFlags);
FunctionType::Param baseObjParam(baseObjTy);

// Don't open existentials when accessing typealias members of
// protocols.
Expand Down
24 changes: 24 additions & 0 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,30 @@ namespace {
CallArgs.insert(arg);
}

// FIXME(diagnostics): `InOutType` could appear here as a result
// of successful re-typecheck of the one of the sub-expressions e.g.
// `let _: Int = { (s: inout S) in s.bar() }`. On the first
// attempt to type-check whole expression `s.bar()` - is going
// to have a base which points directly to declaration of `S`.
// But when diagnostics attempts to type-check `s.bar()` standalone
// its base would be tranformed into `InOutExpr -> DeclRefExr`,
// and `InOutType` is going to be recorded in constraint system.
// One possible way to fix this (if diagnostics still use typecheck)
// might be to make it so self is not wrapped into `InOutExpr`
// but instead used as @lvalue type in some case of mutable members.
if (!expr->isImplicit()) {
if (isa<MemberRefExpr>(expr) || isa<DynamicMemberRefExpr>(expr)) {
auto *LE = cast<LookupExpr>(expr);
if (auto *IOE = dyn_cast<InOutExpr>(LE->getBase()))
LE->setBase(IOE->getSubExpr());
}

if (auto *DSCE = dyn_cast<DotSyntaxCallExpr>(expr)) {
if (auto *IOE = dyn_cast<InOutExpr>(DSCE->getBase()))
DSCE->setBase(IOE->getSubExpr());
}
}

// Local function used to finish up processing before returning. Every
// return site should call through here.
auto finish = [&](bool recursive, Expr *expr) {
Expand Down
16 changes: 16 additions & 0 deletions test/Constraints/operator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,19 @@ func ??= <T>(lhs: inout T?, rhs: T?) {}
var c: Int = 0
c ??= 5 // expected-error{{binary operator '??=' cannot be applied to two 'Int' operands}}
// expected-note@-1{{expected an argument list of type '(inout T?, T?)'}}

func rdar46459603() {
enum E {
case foo(value: String)
}

let e = E.foo(value: "String")
var arr = ["key": e]

_ = arr.values == [e]
// expected-error@-1 {{binary operator '==' cannot be applied to operands of type 'Dictionary<String, E>.Values' and '[E]'}}
// expected-note@-2 {{expected an argument list of type '(Self, Self)'}}
_ = [arr.values] == [[e]]
// expected-error@-1 {{binary operator '==' cannot be applied to operands of type '[Dictionary<String, E>.Values]' and '[[E]]'}}
// expected-note@-2 {{expected an argument list of type '(Self, Self)'}}
}