Skip to content

Commit b01ed59

Browse files
committed
Merge branch 'swift-5.0-branch' of github.com:apple/swift into swift-5.0-branch
2 parents 4aac329 + 50d83d7 commit b01ed59

File tree

18 files changed

+226
-80
lines changed

18 files changed

+226
-80
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,9 @@ class TypeConverter {
857857
GenericEnvironment *env,
858858
bool isMutable);
859859

860+
CanSILBoxType getBoxTypeForEnumElement(SILType enumType,
861+
EnumElementDecl *elt);
862+
860863
private:
861864
CanType getLoweredRValueType(AbstractionPattern origType, CanType substType);
862865

lib/AST/ASTVerifier.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,8 +1069,17 @@ class Verifier : public ASTWalker {
10691069
Type srcObj = checkLValue(E->getSubExpr()->getType(),
10701070
"result of InOutExpr");
10711071
auto DestTy = E->getType()->castTo<InOutType>()->getObjectType();
1072-
1073-
checkSameType(DestTy, srcObj, "object types for InOutExpr");
1072+
1073+
// HACK: Allow differences in optionality of the source and
1074+
// result types. When IUO is gone from the type system we'll no
1075+
// longer need this.
1076+
auto srcOptObjTy = srcObj->getAnyOptionalObjectType();
1077+
auto dstOptObjTy = DestTy->getAnyOptionalObjectType();
1078+
if (srcOptObjTy && dstOptObjTy) {
1079+
checkSameType(srcOptObjTy, dstOptObjTy, "object types for InOutExpr");
1080+
} else {
1081+
checkSameType(DestTy, srcObj, "object types for InOutExpr");
1082+
}
10741083
verifyCheckedBase(E);
10751084
}
10761085

lib/IRGen/IRGenSIL.cpp

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -707,44 +707,31 @@ class IRGenSILFunction :
707707
Storage.getAlignment());
708708
}
709709

710-
void emitShadowCopy(ArrayRef<llvm::Value *> vals, const SILDebugScope *Scope,
710+
void emitShadowCopy(SILValue &SILVal, const SILDebugScope *Scope,
711711
StringRef Name, unsigned ArgNo, bool IsAnonymous,
712712
llvm::SmallVectorImpl<llvm::Value *> &copy) {
713+
Explosion e = getLoweredExplosion(SILVal);
714+
713715
// Only do this at -O0.
714716
if (IGM.IRGen.Opts.shouldOptimize() || IsAnonymous) {
717+
auto vals = e.claimAll();
715718
copy.append(vals.begin(), vals.end());
716719
return;
717720
}
718721

719722
// Single or empty values.
720-
if (vals.size() <= 1) {
723+
if (e.size() <= 1) {
724+
auto vals = e.claimAll();
721725
for (auto val : vals)
722726
copy.push_back(emitShadowCopy(val, Scope, Name, ArgNo, IsAnonymous));
723727
return;
724728
}
725729

726-
// Create a single aggregate alloca for explosions.
727-
// TODO: why are we doing this instead of using the TypeInfo?
728-
llvm::StructType *aggregateType = [&] {
729-
SmallVector<llvm::Type *, 8> eltTypes;
730-
for (auto val : vals)
731-
eltTypes.push_back(val->getType());
732-
return llvm::StructType::get(IGM.LLVMContext, eltTypes);
733-
}();
734-
735-
auto layout = IGM.DataLayout.getStructLayout(aggregateType);
736-
Alignment align(layout->getAlignment());
737-
738-
auto alloca = createAlloca(aggregateType, align, Name + ".debug");
739-
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo, Builder);
740-
size_t i = 0;
741-
for (auto val : vals) {
742-
auto addr = Builder.CreateStructGEP(alloca, i,
743-
Size(layout->getElementOffset(i)));
744-
Builder.CreateStore(val, addr);
745-
i++;
746-
}
747-
copy.push_back(alloca.getAddress());
730+
SILType Type = SILVal->getType();
731+
auto &LTI = cast<LoadableTypeInfo>(IGM.getTypeInfo(Type));
732+
auto Alloca = LTI.allocateStack(*this, Type, "debug.copy");
733+
LTI.initialize(*this, e, Alloca.getAddress(), false /* isOutlined */);
734+
copy.push_back(Alloca.getAddressPointer());
748735
}
749736

750737
/// Determine whether a generic variable has been inlined.
@@ -3474,10 +3461,8 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
34743461

34753462
// Put the value into a stack slot at -Onone.
34763463
llvm::SmallVector<llvm::Value *, 8> Copy;
3477-
Explosion e = getLoweredExplosion(SILVal);
34783464
unsigned ArgNo = i->getVarInfo().ArgNo;
3479-
emitShadowCopy(e.claimAll(), i->getDebugScope(), Name, ArgNo, IsAnonymous,
3480-
Copy);
3465+
emitShadowCopy(SILVal, i->getDebugScope(), Name, ArgNo, IsAnonymous, Copy);
34813466
emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
34823467
i->getDecl(), Name, ArgNo);
34833468
}

lib/SIL/SILType.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,19 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M) const {
336336
return SILType(objectType, getCategory());
337337
}
338338

339+
// If the case is indirect, then the payload is boxed.
340+
if (elt->isIndirect() || elt->getParentEnum()->isIndirect()) {
341+
auto box = M.Types.getBoxTypeForEnumElement(*this, elt);
342+
return SILType(SILType::getPrimitiveObjectType(box).getSwiftRValueType(),
343+
getCategory());
344+
}
345+
339346
auto substEltTy =
340347
getSwiftRValueType()->getTypeOfMember(M.getSwiftModule(), elt,
341348
elt->getArgumentInterfaceType());
342349
auto loweredTy =
343350
M.Types.getLoweredType(M.Types.getAbstractionPattern(elt), substEltTy);
344351

345-
// If the case is indirect, then the payload is boxed.
346-
if (elt->isIndirect() || elt->getParentEnum()->isIndirect())
347-
loweredTy = SILType::getPrimitiveObjectType(
348-
SILBoxType::get(loweredTy.getSwiftRValueType()));
349-
350352
return SILType(loweredTy.getSwiftRValueType(), getCategory());
351353
}
352354

lib/SIL/TypeLowering.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,45 @@ TypeConverter::getContextBoxTypeForCapture(ValueDecl *captured,
25232523
return boxType;
25242524
}
25252525

2526+
CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType,
2527+
EnumElementDecl *elt) {
2528+
2529+
auto *enumDecl = enumType.getEnumOrBoundGenericEnum();
2530+
2531+
assert(elt->getDeclContext() == enumDecl);
2532+
assert(elt->isIndirect() || elt->getParentEnum()->isIndirect());
2533+
2534+
auto &C = M.getASTContext();
2535+
2536+
auto boxSignature = getEffectiveGenericSignature(enumDecl);
2537+
2538+
if (boxSignature == CanGenericSignature()) {
2539+
auto eltIntfTy = elt->getArgumentInterfaceType();
2540+
auto boxVarTy = getLoweredType(eltIntfTy).getSwiftRValueType();
2541+
auto layout = SILLayout::get(C, nullptr, SILField(boxVarTy, true));
2542+
return SILBoxType::get(C, layout, {});
2543+
}
2544+
2545+
// Use the enum's signature for the box type.
2546+
auto boundEnum = enumType.getSwiftRValueType();
2547+
2548+
// Lower the enum element's argument in the box's context.
2549+
auto eltIntfTy = elt->getArgumentInterfaceType();
2550+
GenericContextScope scope(*this, boxSignature);
2551+
auto boxVarTy = getLoweredType(getAbstractionPattern(elt), eltIntfTy)
2552+
.getSwiftRValueType();
2553+
auto layout = SILLayout::get(C, boxSignature, SILField(boxVarTy, true));
2554+
2555+
// Instantiate the layout with enum's substitution list.
2556+
auto subMap = boundEnum->getContextSubstitutionMap(
2557+
M.getSwiftModule(), enumDecl, enumDecl->getGenericEnvironment());
2558+
SmallVector<Substitution, 4> genericArgs;
2559+
boxSignature->getSubstitutions(subMap, genericArgs);
2560+
2561+
auto boxTy = SILBoxType::get(C, layout, genericArgs);
2562+
return boxTy;
2563+
}
2564+
25262565
static void countNumberOfInnerFields(unsigned &fieldsCount, SILModule &Module,
25272566
SILType Ty) {
25282567
if (auto *structDecl = Ty.getStructOrBoundGenericStruct()) {

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3541,7 +3541,7 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc,
35413541
// throws, we know to deallocate the uninitialized box.
35423542
if (element->isIndirect() ||
35433543
element->getParentEnum()->isIndirect()) {
3544-
auto boxTy = SILBoxType::get(payloadTL.getLoweredType().getSwiftRValueType());
3544+
auto boxTy = SGM.M.Types.getBoxTypeForEnumElement(enumTy, element);
35453545
auto *box = B.createAllocBox(loc, boxTy);
35463546
auto *addr = B.createProjectBox(loc, box, 0);
35473547

lib/Sema/CSApply.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5448,6 +5448,38 @@ static unsigned computeCallLevel(ConstraintSystem &cs, ConcreteDeclRef callee,
54485448
return 0;
54495449
}
54505450

5451+
// HACK: Support calling functions with inouts of differing kinds of
5452+
// optionality so that we can warn about overloading by IUO vs. plain
5453+
// Optional and allow users to correct the issue by removing an
5454+
// overload and passing the differently-optional value to the
5455+
// remaining overload.
5456+
bool inOutOptionalityDifferenceHack(Expr *arg, Type paramType,
5457+
ConstraintSystem &cs) {
5458+
auto *inOutArgTy = cs.getType(arg)->getAs<InOutType>();
5459+
if (!inOutArgTy)
5460+
return false;
5461+
5462+
auto *inOutParamTy = paramType->getAs<InOutType>();
5463+
if (!inOutParamTy)
5464+
return false;
5465+
5466+
OptionalTypeKind argOTK;
5467+
OptionalTypeKind paramOTK;
5468+
auto argObjTy = inOutArgTy->getObjectType()->getAnyOptionalObjectType(argOTK);
5469+
auto paramObjTy =
5470+
inOutParamTy->getObjectType()->getAnyOptionalObjectType(paramOTK);
5471+
5472+
if (argOTK == paramOTK || argOTK == OTK_None || paramOTK == OTK_None)
5473+
return false;
5474+
5475+
if (!argObjTy->isEqual(paramObjTy))
5476+
return false;
5477+
5478+
// Hammer over the argument type with the expected parameter type.
5479+
cs.setType(arg, paramType);
5480+
return true;
5481+
}
5482+
54515483
Expr *ExprRewriter::coerceCallArguments(
54525484
Expr *arg, AnyFunctionType *funcType,
54535485
ApplyExpr *apply,
@@ -5678,11 +5710,16 @@ Expr *ExprRewriter::coerceCallArguments(
56785710
continue;
56795711
}
56805712

5681-
// Convert the argument.
5682-
auto convertedArg = coerceToType(arg, paramType,
5683-
getArgLocator(argIdx, paramIdx));
5684-
if (!convertedArg)
5685-
return nullptr;
5713+
Expr *convertedArg;
5714+
if (inOutOptionalityDifferenceHack(arg, paramType, cs)) {
5715+
convertedArg = arg;
5716+
} else {
5717+
// Convert the argument.
5718+
convertedArg =
5719+
coerceToType(arg, paramType, getArgLocator(argIdx, paramIdx));
5720+
if (!convertedArg)
5721+
return nullptr;
5722+
}
56865723

56875724
// Add the converted argument.
56885725
fromTupleExpr[argIdx] = convertedArg;

lib/Sema/CSRanking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
8080
case SK_ValueToPointerConversion:
8181
log << "value-to-pointer conversion";
8282
break;
83+
case SK_InOutOptionalityConversion:
84+
log << "inout optionality conversion";
8385
}
8486
log << ")\n";
8587
}

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,16 +1899,32 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
18991899
locator.withPathElement(
19001900
ConstraintLocator::ArrayElementType));
19011901

1902-
case TypeKind::InOut:
1902+
case TypeKind::InOut: {
19031903
// If the RHS is an inout type, the LHS must be an @lvalue type.
19041904
if (kind == ConstraintKind::BindParam ||
19051905
kind >= ConstraintKind::OperatorArgumentConversion)
19061906
return SolutionKind::Error;
1907-
1908-
return matchTypes(cast<InOutType>(desugar1)->getObjectType(),
1909-
cast<InOutType>(desugar2)->getObjectType(),
1910-
ConstraintKind::Equal, subflags,
1911-
locator.withPathElement(ConstraintLocator::ArrayElementType));
1907+
1908+
auto inoutObjTy1 = cast<InOutType>(desugar1)->getObjectType();
1909+
auto inoutObjTy2 = cast<InOutType>(desugar2)->getObjectType();
1910+
1911+
OptionalTypeKind OTK1;
1912+
OptionalTypeKind OTK2;
1913+
auto optionalObjTy1 = inoutObjTy1->getAnyOptionalObjectType(OTK1);
1914+
auto optionalObjTy2 = inoutObjTy2->getAnyOptionalObjectType(OTK2);
1915+
if (OTK1 != OTK2 && optionalObjTy1 && optionalObjTy2) {
1916+
increaseScore(ScoreKind::SK_InOutOptionalityConversion);
1917+
return matchTypes(inoutObjTy1,
1918+
inoutObjTy2,
1919+
ConstraintKind::ArgumentConversion, subflags,
1920+
locator.withPathElement(ConstraintLocator::ArrayElementType));
1921+
} else {
1922+
return matchTypes(inoutObjTy1,
1923+
inoutObjTy2,
1924+
ConstraintKind::Equal, subflags,
1925+
locator.withPathElement(ConstraintLocator::ArrayElementType));
1926+
}
1927+
}
19121928

19131929
case TypeKind::UnboundGeneric:
19141930
llvm_unreachable("Unbound generic type should have been opened");

lib/Sema/ConstraintSystem.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,12 @@ enum ScoreKind {
462462
SK_KeyPathSubscript,
463463
/// A conversion from a string, array, or inout to a pointer.
464464
SK_ValueToPointerConversion,
465+
/// A conversion from 'inout Optional<T>' to 'inout
466+
/// ImplicitlyUnwrappedOptional<T>' or vice-versa.
467+
/// FIXME: This goes away when IUO-as-a-type goes away.
468+
SK_InOutOptionalityConversion,
465469

466-
SK_LastScoreKind = SK_ValueToPointerConversion,
470+
SK_LastScoreKind = SK_InOutOptionalityConversion,
467471
};
468472

469473
/// The number of score kinds.

test/Constraints/iuo.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,27 @@ func cast<T : P>(_ t: T) {
159159
let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?)
160160
let _: T! = id(T.iuoResultStatic(true))
161161
}
162+
163+
func takesInOutIUO(_ i: inout Int!) {}
164+
func takesInOutOpt(_ o: inout Int?) {}
165+
166+
func overloadedByOptionality(_ a: inout Int!) {}
167+
// expected-note@-1 {{'overloadedByOptionality' previously declared here}}
168+
// expected-note@-2 {{'overloadedByOptionality' previously declared here}}
169+
func overloadedByOptionality(_ a: inout Int?) {}
170+
// expected-warning@-1 {{invalid redeclaration of 'overloadedByOptionality' which differs only by the kind of optional passed as an inout argument ('Int?' vs. 'Int!')}}
171+
// expected-warning@-2 {{invalid redeclaration of 'overloadedByOptionality' which differs only by the kind of optional passed as an inout argument ('Int?' vs. 'Int!')}}
172+
// expected-note@-3 {{overloading by kind of optional is deprecated and will be removed in a future release}}
173+
// expected-note@-4 {{overloading by kind of optional is deprecated and will be removed in a future release}}
174+
175+
func testInOutOptionality() {
176+
var i: Int! = 1
177+
var o: Int? = 2
178+
179+
takesInOutIUO(&i)
180+
takesInOutOpt(&i)
181+
takesInOutIUO(&o)
182+
takesInOutOpt(&o)
183+
184+
overloadedByOptionality(&o)
185+
}

test/DebugInfo/guard-let.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@ func use<T>(_ t: T) {}
88
public func f(_ i : Int?)
99
{
1010
// CHECK: define {{.*}}@"$S4main1fyySiSgF"
11-
// The shadow copy store should not have a location.
12-
// Note that the store must be in the same scope or else it might defeat
13-
// livedebugvalues.
11+
// CHECK1: %debug.copy = alloca %TSiSg
12+
// CHECK1: @llvm.dbg.declare(metadata %TSiSg* %debug.copy
1413
// CHECK1: @llvm.dbg.declare(metadata {{(i32|i64)}}* %val.addr, {{.*}}, !dbg ![[DBG0:.*]]
15-
// CHECK1: %[[PHI:.*]] = phi
16-
// CHECK1: store {{(i32|i64)}} %[[PHI]], {{(i32|i64)}}* %val.addr, align {{(4|8)}}, !dbg ![[DBG1:.*]]
1714
// CHECK1: ![[F:.*]] = distinct !DISubprogram(name: "f",
1815
// CHECK1: ![[BLK:.*]] = distinct !DILexicalBlock(scope: ![[F]],
1916
// CHECK1: ![[DBG0]] = !DILocation(line: [[@LINE+2]],
@@ -29,10 +26,11 @@ public func f(_ i : Int?)
2926
public func g(_ s : String?)
3027
{
3128
// CHECK2: define {{.*}}@"$S4main1gyySSSgF"
32-
// The shadow copy store should not have a location.
33-
// CHECK2: getelementptr inbounds {{.*}} %s.debug, {{.*}}, !dbg ![[DBG0:.*]]
29+
// CHECK2: %debug.copy = alloca %TSSSg
30+
// CHECK2: @llvm.dbg.declare(metadata %TSSSg*
31+
// CHECK2: %debug.copy1 = alloca %TSS
32+
// CHECK2: @llvm.dbg.declare(metadata %TSS*
3433
// CHECK2: ![[G:.*]] = distinct !DISubprogram(name: "g"
35-
// CHECK2: ![[DBG0]] = !DILocation(line: 0, scope: ![[G]])
3634
guard let val = s else { return }
3735
use(val)
3836
}

test/IRGen/objc_block.sil

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ entry(%b : $@convention(block) Foo -> Foo, %x : $Foo):
1818
}
1919
// CHECK-LABEL: define{{( protected)?}} swiftcc %T10objc_block3FooC* @call_block(%objc_block*, %T10objc_block3FooC*) {{.*}} {
2020
// CHECK: entry:
21-
// CHECK: %2 = getelementptr inbounds %objc_block, %objc_block* %0, i32 0, i32 3
22-
// CHECK: %3 = load i8*, i8** %2
23-
// CHECK: %4 = bitcast i8* %3 to i8* (%objc_block*, i8*)*
24-
// CHECK: %5 = bitcast %T10objc_block3FooC* %1 to i8*
25-
// CHECK: %6 = call i8* %4(%objc_block* %0, i8* %5)
26-
// CHECK: %7 = bitcast i8* %6 to %T10objc_block3FooC*
27-
// CHECK: ret %T10objc_block3FooC* %7
21+
// CHECK: [[T0:%.*]] = getelementptr inbounds %objc_block, %objc_block* %0, i32 0, i32 3
22+
// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]]
23+
// CHECK: [[T2:%.*]] = bitcast i8* [[T1]] to i8* (%objc_block*, i8*)*
24+
// CHECK: [[T3:%.*]] = bitcast %T10objc_block3FooC* %1 to i8*
25+
// CHECK: [[T4:%.*]] = call i8* [[T2]](%objc_block* %0, i8* [[T3]])
26+
// CHECK: [[T5:%.*]] = bitcast i8* [[T4]] to %T10objc_block3FooC*
27+
// CHECK: ret %T10objc_block3FooC* [[T5]]
2828
// CHECK: }
2929

3030
sil @generic : $@convention(thin) <T> (@in T) -> ()

test/Interpreter/enum.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,3 +651,19 @@ func run() {
651651
}
652652

653653
run()
654+
655+
public enum Indirect<T> {
656+
indirect case payload((T, other: T))
657+
case none
658+
}
659+
660+
public func testIndirectEnum<T>(_ payload: T) -> Indirect<T> {
661+
return Indirect.payload((payload, other: payload))
662+
}
663+
664+
public func testCase(_ closure: @escaping (Int) -> ()) -> Indirect<(Int) -> ()> {
665+
return testIndirectEnum(closure)
666+
}
667+
668+
// CHECK: payload((Function), other: (Function))
669+
print(testCase({ _ in }))

0 commit comments

Comments
 (0)