Skip to content

Commit 13bdd7b

Browse files
committed
Revert "Diagnose inout uses of 'lets' in constructors in the type checker."
This reverts commit 80d949e.
1 parent 8459a9d commit 13bdd7b

15 files changed

+86
-214
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,14 +2092,6 @@ struct ClosureIsolatedByPreconcurrency {
20922092
bool operator()(const ClosureExpr *expr) const;
20932093
};
20942094

2095-
/// Determine whether the given expression is part of the left-hand side
2096-
/// of an assignment expression.
2097-
struct IsInLeftHandSideOfAssignment {
2098-
ConstraintSystem &cs;
2099-
2100-
bool operator()(Expr *expr) const;
2101-
};
2102-
21032095
/// Describes the type produced when referencing a declaration.
21042096
struct DeclReferenceType {
21052097
/// The "opened" type, which is the type of the declaration where any
@@ -4412,7 +4404,7 @@ class ConstraintSystem {
44124404
/// \param wantInterfaceType Whether we want the interface type, if available.
44134405
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
44144406
DeclContext *UseDC,
4415-
ConstraintLocator *locator,
4407+
ConstraintLocator *memberLocator = nullptr,
44164408
bool wantInterfaceType = false,
44174409
bool adjustForPreconcurrency = true);
44184410

@@ -4434,7 +4426,7 @@ class ConstraintSystem {
44344426
getUnopenedTypeOfReference(
44354427
VarDecl *value, Type baseType, DeclContext *UseDC,
44364428
llvm::function_ref<Type(VarDecl *)> getType,
4437-
ConstraintLocator *locator,
4429+
ConstraintLocator *memberLocator = nullptr,
44384430
bool wantInterfaceType = false,
44394431
bool adjustForPreconcurrency = true,
44404432
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
@@ -4444,10 +4436,7 @@ class ConstraintSystem {
44444436
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency =
44454437
[](const ClosureExpr *closure) {
44464438
return closure->isIsolatedByPreconcurrency();
4447-
},
4448-
llvm::function_ref<bool(Expr *)> isAssignTarget = [](Expr *) {
4449-
return false;
4450-
});
4439+
});
44514440

44524441
/// Given the opened type and a pile of information about a member reference,
44534442
/// determine the reference type of the member reference.

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,7 @@ bool SILGenFunction::unsafelyInheritsExecutor() {
648648

649649
void ExecutorBreadcrumb::emit(SILGenFunction &SGF, SILLocation loc) {
650650
if (mustReturnToExecutor) {
651-
assert(SGF.ExpectedExecutor || SGF.unsafelyInheritsExecutor() ||
652-
SGF.isCtorWithHopsInjectedByDefiniteInit());
651+
assert(SGF.ExpectedExecutor || SGF.unsafelyInheritsExecutor());
653652
if (auto executor = SGF.ExpectedExecutor)
654653
SGF.B.createHopToExecutor(
655654
RegularLocation::getDebugOnlyLocation(loc, SGF.getModule()), executor,

lib/SILGen/SILGenConstructor.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -618,19 +618,6 @@ static bool ctorHopsInjectedByDefiniteInit(ConstructorDecl *ctor,
618618
}
619619
}
620620

621-
bool SILGenFunction::isCtorWithHopsInjectedByDefiniteInit() {
622-
auto declRef = F.getDeclRef();
623-
if (!declRef || !declRef.isConstructor())
624-
return false;
625-
626-
auto ctor = dyn_cast_or_null<ConstructorDecl>(declRef.getDecl());
627-
if (!ctor)
628-
return false;
629-
630-
auto isolation = getActorIsolation(ctor);
631-
return ctorHopsInjectedByDefiniteInit(ctor, isolation);
632-
}
633-
634621
void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
635622
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);
636623

lib/SILGen/SILGenFunction.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
820820
/// the fields.
821821
void emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd);
822822

823-
/// Whether we are inside a constructor whose hops are injected by
824-
/// definite initialization.
825-
bool isCtorWithHopsInjectedByDefiniteInit();
826-
827823
/// Generates code for a struct constructor.
828824
/// This allocates the new 'self' value, emits the
829825
/// body code, then returns the final initialized 'self'.

lib/Sema/CSApply.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -655,33 +655,12 @@ namespace {
655655
}
656656

657657
auto ref = resolveConcreteDeclRef(decl, locator);
658-
659-
// If we have a variable that's treated as an rvalue but allows
660-
// assignment (for initialization) in the current context,
661-
// treat it as an rvalue that we immediately load. This is
662-
// the AST that's expected by SILGen.
663-
bool loadImmediately = false;
664-
if (auto var = dyn_cast_or_null<VarDecl>(ref.getDecl())) {
665-
if (!fullType->hasLValueType()) {
666-
if (var->mutability(dc) == StorageMutability::Initializable) {
667-
fullType = LValueType::get(fullType);
668-
adjustedFullType = LValueType::get(adjustedFullType);
669-
loadImmediately = true;
670-
}
671-
}
672-
}
673-
674-
675658
auto declRefExpr =
676659
new (ctx) DeclRefExpr(ref, loc, implicit, semantics, fullType);
677660
cs.cacheType(declRefExpr);
678661
declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
679662
Expr *result = adjustTypeForDeclReference(
680663
declRefExpr, fullType, adjustedFullType, locator);
681-
// If we have to load, do so now.
682-
if (loadImmediately)
683-
result = cs.addImplicitLoadExpr(result);
684-
685664
result = forceUnwrapIfExpected(result, locator);
686665

687666
if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(decl)) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 18 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,14 +1426,12 @@ ConstraintSystem::getWrappedPropertyInformation(
14261426
/// is being accessed; must be null if and only if this is not
14271427
/// a type member
14281428
static bool
1429-
doesStorageProduceLValue(
1430-
AbstractStorageDecl *storage, Type baseType,
1431-
DeclContext *useDC,
1432-
llvm::function_ref<bool(Expr *)> isAssignTarget,
1433-
ConstraintLocator *locator) {
1429+
doesStorageProduceLValue(AbstractStorageDecl *storage, Type baseType,
1430+
DeclContext *useDC,
1431+
ConstraintLocator *memberLocator = nullptr) {
14341432
const DeclRefExpr *base = nullptr;
1435-
if (locator) {
1436-
if (auto *const E = getAsExpr(locator->getAnchor())) {
1433+
if (memberLocator) {
1434+
if (auto *const E = getAsExpr(memberLocator->getAnchor())) {
14371435
if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
14381436
base = dyn_cast<DeclRefExpr>(MRE->getBase());
14391437
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(E)) {
@@ -1442,33 +1440,9 @@ doesStorageProduceLValue(
14421440
}
14431441
}
14441442

1445-
switch (storage->mutabilityInSwift(useDC, base)) {
1446-
case StorageMutability::Immutable:
1447-
// Immutable storage decls always produce rvalues.
1448-
return false;
1449-
1450-
case StorageMutability::Mutable:
1451-
break;
1452-
1453-
case StorageMutability::Initializable: {
1454-
// If the member is not known to be on the left-hand side of
1455-
// an assignment, treat it as an rvalue so we can't pass it
1456-
// inout.
1457-
if (!locator)
1458-
return false;
1459-
1460-
auto *anchor = getAsExpr(simplifyLocatorToAnchor(locator));
1461-
if (!anchor)
1462-
return false;
1463-
1464-
// If the anchor isn't known to be the target of an assignment,
1465-
// treat as immutable.
1466-
if (!isAssignTarget(anchor))
1467-
return false;
1468-
1469-
break;
1470-
}
1471-
}
1443+
// Unsettable storage decls always produce rvalues.
1444+
if (!storage->isSettableInSwift(useDC, base))
1445+
return false;
14721446

14731447
if (!storage->isSetterAccessibleFrom(useDC))
14741448
return false;
@@ -1508,7 +1482,7 @@ ClosureIsolatedByPreconcurrency::operator()(const ClosureExpr *expr) const {
15081482

15091483
Type ConstraintSystem::getUnopenedTypeOfReference(
15101484
VarDecl *value, Type baseType, DeclContext *UseDC,
1511-
ConstraintLocator *locator, bool wantInterfaceType,
1485+
ConstraintLocator *memberLocator, bool wantInterfaceType,
15121486
bool adjustForPreconcurrency) {
15131487
return ConstraintSystem::getUnopenedTypeOfReference(
15141488
value, baseType, UseDC,
@@ -1522,20 +1496,18 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
15221496

15231497
return wantInterfaceType ? var->getInterfaceType() : var->getTypeInContext();
15241498
},
1525-
locator, wantInterfaceType, adjustForPreconcurrency,
1499+
memberLocator, wantInterfaceType, adjustForPreconcurrency,
15261500
GetClosureType{*this},
1527-
ClosureIsolatedByPreconcurrency{*this},
1528-
IsInLeftHandSideOfAssignment{*this});
1501+
ClosureIsolatedByPreconcurrency{*this});
15291502
}
15301503

15311504
Type ConstraintSystem::getUnopenedTypeOfReference(
15321505
VarDecl *value, Type baseType, DeclContext *UseDC,
15331506
llvm::function_ref<Type(VarDecl *)> getType,
1534-
ConstraintLocator *locator,
1507+
ConstraintLocator *memberLocator,
15351508
bool wantInterfaceType, bool adjustForPreconcurrency,
15361509
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType,
1537-
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency,
1538-
llvm::function_ref<bool(Expr *)> isAssignTarget) {
1510+
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency) {
15391511
Type requestedType =
15401512
getType(value)->getWithoutSpecifierType()->getReferenceStorageReferent();
15411513

@@ -1560,8 +1532,7 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
15601532

15611533
// Qualify storage declarations with an lvalue when appropriate.
15621534
// Otherwise, they yield rvalues (and the access must be a load).
1563-
if (doesStorageProduceLValue(value, baseType, UseDC, isAssignTarget,
1564-
locator) &&
1535+
if (doesStorageProduceLValue(value, baseType, UseDC, memberLocator) &&
15651536
!requestedType->hasError()) {
15661537
return LValueType::get(requestedType);
15671538
}
@@ -1934,8 +1905,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
19341905
// FIXME: @preconcurrency
19351906
bool wantInterfaceType = !varDecl->getDeclContext()->isLocalContext();
19361907
Type valueType =
1937-
getUnopenedTypeOfReference(varDecl, Type(), useDC,
1938-
getConstraintLocator(locator),
1908+
getUnopenedTypeOfReference(varDecl, Type(), useDC, /*base=*/nullptr,
19391909
wantInterfaceType);
19401910

19411911
Type thrownErrorType;
@@ -2609,48 +2579,6 @@ bool ConstraintSystem::isPartialApplication(ConstraintLocator *locator) {
26092579
return level < (baseTy->is<MetatypeType>() ? 1 : 2);
26102580
}
26112581

2612-
bool IsInLeftHandSideOfAssignment::operator()(Expr *expr) const {
2613-
// Walk up the parent tree.
2614-
auto parent = cs.getParentExpr(expr);
2615-
if (!parent)
2616-
return false;
2617-
2618-
// If the parent is an assignment expression, check whether we are
2619-
// the left-hand side.
2620-
if (auto assignParent = dyn_cast<AssignExpr>(parent)) {
2621-
return expr == assignParent->getDest();
2622-
}
2623-
2624-
// Always look up through these parent kinds.
2625-
if (isa<TupleExpr>(parent) || isa<IdentityExpr>(parent) ||
2626-
isa<AnyTryExpr>(parent) || isa<BindOptionalExpr>(parent)) {
2627-
return (*this)(parent);
2628-
}
2629-
2630-
// If the parent is a lookup expression, only follow from the base.
2631-
if (auto lookupParent = dyn_cast<LookupExpr>(parent)) {
2632-
if (lookupParent->getBase() == expr)
2633-
return (*this)(parent);
2634-
2635-
// The expression wasn't in the base, so this isn't part of the
2636-
// left-hand side.
2637-
return false;
2638-
}
2639-
2640-
// If the parent is an unresolved member reference a.b, only follow
2641-
// from the base.
2642-
if (auto dotParent = dyn_cast<UnresolvedDotExpr>(parent)) {
2643-
if (dotParent->getBase() == expr)
2644-
return (*this)(parent);
2645-
2646-
// The expression wasn't in the base, so this isn't part of the
2647-
// left-hand side.
2648-
return false;
2649-
}
2650-
2651-
return false;
2652-
}
2653-
26542582
DeclReferenceType
26552583
ConstraintSystem::getTypeOfMemberReference(
26562584
Type baseTy, ValueDecl *value, DeclContext *useDC,
@@ -2756,9 +2684,7 @@ ConstraintSystem::getTypeOfMemberReference(
27562684
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
27572685
auto elementTy = subscript->getElementInterfaceType();
27582686

2759-
if (doesStorageProduceLValue(
2760-
subscript, baseTy, useDC,
2761-
IsInLeftHandSideOfAssignment{*this}, locator))
2687+
if (doesStorageProduceLValue(subscript, baseTy, useDC, locator))
27622688
elementTy = LValueType::get(elementTy);
27632689

27642690
auto indices = subscript->getInterfaceType()
@@ -3013,10 +2939,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
30132939
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
30142940
auto elementTy = subscript->getElementInterfaceType();
30152941

3016-
if (doesStorageProduceLValue(subscript, overload.getBaseType(),
3017-
useDC,
3018-
IsInLeftHandSideOfAssignment{*this},
3019-
locator))
2942+
if (doesStorageProduceLValue(subscript, overload.getBaseType(), useDC))
30202943
elementTy = LValueType::get(elementTy);
30212944
else if (elementTy->hasDynamicSelfType()) {
30222945
elementTy = withDynamicSelfResultReplaced(elementTy,
@@ -3040,9 +2963,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
30402963
locator);
30412964
} else if (auto var = dyn_cast<VarDecl>(decl)) {
30422965
type = var->getValueInterfaceType();
3043-
if (doesStorageProduceLValue(
3044-
var, overload.getBaseType(), useDC,
3045-
IsInLeftHandSideOfAssignment{*this}, locator)) {
2966+
if (doesStorageProduceLValue(var, overload.getBaseType(), useDC)) {
30462967
type = LValueType::get(type);
30472968
} else if (type->hasDynamicSelfType()) {
30482969
type = withDynamicSelfResultReplaced(type, /*uncurryLevel=*/0);

lib/Sema/TypeCheckExpr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,17 @@ bool TypeChecker::requireArrayLiteralIntrinsics(ASTContext &ctx,
581581
return true;
582582
}
583583

584+
Expr *TypeChecker::buildCheckedRefExpr(VarDecl *value, DeclContext *UseDC,
585+
DeclNameLoc loc, bool Implicit) {
586+
auto type = constraints::ConstraintSystem::getUnopenedTypeOfReference(
587+
value, Type(), UseDC,
588+
[&](VarDecl *var) -> Type { return value->getTypeInContext(); });
589+
auto semantics = value->getAccessSemanticsFromContext(UseDC,
590+
/*isAccessOnSelf*/false);
591+
return new (value->getASTContext())
592+
DeclRefExpr(value, loc, Implicit, semantics, type);
593+
}
594+
584595
Expr *TypeChecker::buildRefExpr(ArrayRef<ValueDecl *> Decls,
585596
DeclContext *UseDC, DeclNameLoc NameLoc,
586597
bool Implicit, FunctionRefKind functionRefKind) {

lib/Sema/TypeChecker.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,10 @@ Comparison compareDeclarations(DeclContext *dc, ValueDecl *decl1,
944944
/// of the first one and the expression will still type check.
945945
bool isDeclRefinementOf(ValueDecl *declA, ValueDecl *declB);
946946

947+
/// Build a type-checked reference to the given value.
948+
Expr *buildCheckedRefExpr(VarDecl *D, DeclContext *UseDC, DeclNameLoc nameLoc,
949+
bool Implicit);
950+
947951
/// Build a reference to a declaration, where name lookup returned
948952
/// the given set of declarations.
949953
Expr *buildRefExpr(ArrayRef<ValueDecl *> Decls, DeclContext *UseDC,

test/Constraints/diagnostics.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,9 +1396,7 @@ do {
13961396
func generic<T>(_ value: inout T, _ closure: (S<T>) -> Void) {}
13971397

13981398
let arg: Int
1399-
// expected-note@-1{{change 'let' to 'var' to make it mutable}}
14001399
generic(&arg) { (g: S<Double>) -> Void in } // expected-error {{cannot convert value of type '(S<Double>) -> Void' to expected argument type '(S<Int>) -> Void'}}
1401-
// expected-error@-1{{cannot pass immutable value as inout argument: 'arg' is a 'let' constant}}
14021400
}
14031401

14041402
// rdar://problem/62428353 - bad error message for passing `T` where `inout T` was expected
@@ -1558,17 +1556,18 @@ func testNilCoalescingOperatorRemoveFix() {
15581556
let _ = "" /* This is a comment */ ?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{13-43=}}
15591557

15601558
let _ = "" // This is a comment
1561-
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1560:13-1561:10=}}
1559+
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1558:13-1559:10=}}
15621560

15631561
let _ = "" // This is a comment
15641562
/*
15651563
* The blank line below is part of the test case, do not delete it
15661564
*/
1567-
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1563:13-1567:10=}}
15681565

1569-
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1570:9=}}
1566+
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1561:13-1566:10=}}
1567+
1568+
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1569:9=}}
15701569
"").isEmpty {}
15711570

15721571
if ("" // This is a comment
1573-
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1572:9-1573:12=}}
1572+
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1571:9-1572:12=}}
15741573
}

0 commit comments

Comments
 (0)