Skip to content

Commit 04551c9

Browse files
authored
---
yaml --- r: 293742 b: refs/heads/tensorflow c: 9587a3a h: refs/heads/master
1 parent 299e6d5 commit 04551c9

23 files changed

+367
-64
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ refs/tags/swift-DEVELOPMENT-SNAPSHOT-2018-04-25-a: 22f738a831d43aff2b9c9773bcb65
816816
refs/tags/swift-DEVELOPMENT-SNAPSHOT-2018-05-08-a: 7d98cc16689baba5c8a3b90a9329bdcc1a12b4e9
817817
refs/heads/cherr42: a566ad54b073c2c56ac0a705d0a5bed9743135a5
818818
"refs/heads/codable_test_comment_fix": fc8f6824f7f347e1e8db55bff62db385c5728b5a
819-
refs/heads/tensorflow: d069cc414774464e5c26932f1ef35d0d6604a6a5
819+
refs/heads/tensorflow: 9587a3a1f643065c4ca853bdcb72b95615f551f9
820820
refs/tags/swift-4.1-DEVELOPMENT-SNAPSHOT-2018-05-11-a: 8126fd7a652e2f70ad6d76505239e34fb2ef3e1a
821821
refs/tags/swift-4.1-DEVELOPMENT-SNAPSHOT-2018-05-12-a: b3fd3dd84df6717f2e2e9df58c6d7e99fed57086
822822
refs/tags/swift-4.1-DEVELOPMENT-SNAPSHOT-2018-05-13-a: 71135119579039dc321c5f65d870050fe36efda2

branches/tensorflow/benchmark/single-source/ObjectiveCBridging.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public let ObjectiveCBridging = [
7373
BenchmarkInfo(name: "ObjectiveCBridgeFromNSDateComponents",
7474
runFunction: run_ObjectiveCBridgeFromNSDateComponents, tags: t,
7575
setUpFunction: setup_dateComponents),
76+
BenchmarkInfo(name: "ObjectiveCBridgeASCIIStringFromFile",
77+
runFunction: run_ASCIIStringFromFile, tags: ts,
78+
setUpFunction: setup_ASCIIStringFromFile),
7679
]
7780

7881
#if _runtime(_ObjC)
@@ -709,3 +712,35 @@ public func run_ObjectiveCBridgeFromNSDateComponents(_ N: Int) {
709712
}
710713
#endif
711714
}
715+
716+
var ASCIIStringFromFile:String? = nil
717+
public func setup_ASCIIStringFromFile() {
718+
#if _runtime(_ObjC)
719+
let url:URL
720+
if #available(OSX 10.12, iOS 10.0, *) {
721+
url = FileManager.default.temporaryDirectory.appendingPathComponent(
722+
"sphinx.txt"
723+
)
724+
} else {
725+
url = URL(fileURLWithPath: "/tmp/sphinx.txt")
726+
}
727+
var str = "Sphinx of black quartz judge my vow"
728+
str = Array(repeating: str, count: 100).joined()
729+
try? str.write(
730+
to: url,
731+
atomically: true,
732+
encoding: .ascii
733+
)
734+
ASCIIStringFromFile = try! String(contentsOf: url, encoding: .ascii)
735+
#endif
736+
}
737+
738+
@inline(never)
739+
public func run_ASCIIStringFromFile(_ N: Int) {
740+
#if _runtime(_ObjC)
741+
for _ in 0 ..< N {
742+
blackHole((ASCIIStringFromFile! + "").utf8.count)
743+
}
744+
#endif
745+
}
746+

branches/tensorflow/lib/SILGen/SILGenApply.cpp

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,12 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10191019
if (!ctor->isRequired())
10201020
return false;
10211021

1022+
// @objc dynamic initializers are statically dispatched (we're
1023+
// calling the allocating entry point, which is a thunk that
1024+
// does the dynamic dispatch for us).
1025+
if (ctor->isObjCDynamic())
1026+
return false;
1027+
10221028
// Required constructors are statically dispatched when the 'self'
10231029
// value is statically derived.
10241030
ApplyExpr *thisCallSite = callSites.back();
@@ -1032,64 +1038,32 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10321038
}
10331039

10341040
void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
1035-
SILDeclRef::Kind kind;
1036-
bool requiresAllocRefDynamic = false;
1037-
1038-
if (isa<FuncDecl>(afd)) {
1039-
kind = SILDeclRef::Kind::Func;
1040-
} else {
1041-
if (requiresForeignEntryPoint(afd)) {
1042-
// When we're performing Objective-C dispatch, we don't have an
1043-
// allocating constructor to call. So, perform an alloc_ref_dynamic
1044-
// and pass that along to the initializer.
1045-
requiresAllocRefDynamic = true;
1046-
kind = SILDeclRef::Kind::Initializer;
1047-
} else {
1048-
kind = SILDeclRef::Kind::Allocator;
1049-
}
1050-
}
1051-
10521041
ApplyExpr *thisCallSite = callSites.back();
10531042
callSites.pop_back();
10541043

1055-
// If we require a dynamic allocation of the object here, do so now.
1056-
if (requiresAllocRefDynamic) {
1057-
SILLocation loc = thisCallSite->getArg();
1058-
RValue selfMetatype = SGF.emitRValue(thisCallSite->getArg());
1059-
auto selfValue =
1060-
allocateObject(std::move(selfMetatype).getAsSingleValue(SGF, loc),
1061-
loc, /*objc*/ true);
1062-
RValue self = RValue(SGF, loc, selfValue.getType().getASTType(),
1063-
selfValue);
1064-
ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
1065-
setSelfParam(std::move(selfArgSource), thisCallSite);
1066-
} else {
1067-
ArgumentSource selfArgSource(thisCallSite->getArg());
1068-
setSelfParam(std::move(selfArgSource), thisCallSite);
1069-
}
1044+
ArgumentSource selfArgSource(thisCallSite->getArg());
1045+
setSelfParam(std::move(selfArgSource), thisCallSite);
10701046

10711047
// Directly dispatch to calls of the replaced function inside of
10721048
// '@_dynamicReplacement(for:)' methods.
10731049
bool isObjCReplacementCall = false;
10741050
if (isCallToReplacedInDynamicReplacement(SGF, afd, isObjCReplacementCall) &&
10751051
thisCallSite->getArg()->isSelfExprOf(
10761052
cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()), false)) {
1077-
auto constant = SILDeclRef(afd, kind).asForeign(
1053+
auto constant = SILDeclRef(afd).asForeign(
10781054
!isObjCReplacementCall && requiresForeignEntryPoint(e->getDecl()));
10791055
auto subs = e->getDeclRef().getSubstitutions();
10801056
if (isObjCReplacementCall)
10811057
setCallee(Callee::forDirect(SGF, constant, subs, e));
10821058
else
10831059
setCallee(Callee::forDirect(
10841060
SGF,
1085-
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()),
1086-
kind),
1061+
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl())),
10871062
subs, e, true));
10881063
return;
10891064
}
10901065

1091-
auto constant = SILDeclRef(afd, kind)
1092-
.asForeign(requiresForeignEntryPoint(afd));
1066+
auto constant = SILDeclRef(afd).asForeign(requiresForeignEntryPoint(afd));
10931067

10941068
auto subs = e->getDeclRef().getSubstitutions();
10951069
setCallee(Callee::forClassMethod(SGF, constant, subs, e));

branches/tensorflow/lib/SILGen/SILGenBuilder.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,21 @@ void SILGenBuilder::emitDestructureValueOperation(
820820
SILLocation loc, ManagedValue value,
821821
llvm::function_ref<void(unsigned, ManagedValue)> func) {
822822
CleanupCloner cloner(*this, value);
823-
emitDestructureValueOperation(loc, value.forward(SGF),
824-
[&](unsigned index, SILValue subValue) {
825-
return func(index, cloner.clone(subValue));
826-
});
823+
824+
// NOTE: We can not directly use SILBuilder::emitDestructureValueOperation()
825+
// here since we need to create all of our cleanups before invoking \p
826+
// func. This is necessary since our func may want to emit conditional code
827+
// with an early exit, emitting unused cleanups from the current scope via the
828+
// function emitBranchAndCleanups(). If we have not yet created those
829+
// cleanups, we will introduce a leak along that path.
830+
SmallVector<ManagedValue, 8> destructuredValues;
831+
emitDestructureValueOperation(
832+
loc, value.forward(SGF), [&](unsigned index, SILValue subValue) {
833+
destructuredValues.push_back(cloner.clone(subValue));
834+
});
835+
for (auto p : llvm::enumerate(destructuredValues)) {
836+
func(p.index(), p.value());
837+
}
827838
}
828839

829840
ManagedValue SILGenBuilder::createProjectBox(SILLocation loc, ManagedValue mv,

branches/tensorflow/lib/SILGen/SILGenConstructor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,9 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
530530
// Allocate the 'self' value.
531531
bool useObjCAllocation = usesObjCAllocator(selfClassDecl);
532532

533-
if (ctor->hasClangNode() || ctor->isConvenienceInit()) {
533+
if (ctor->hasClangNode() ||
534+
ctor->isObjCDynamic() ||
535+
ctor->isConvenienceInit()) {
534536
assert(ctor->hasClangNode() || ctor->isObjC());
535537
// For an allocator thunk synthesized for an @objc convenience initializer
536538
// or imported Objective-C init method, allocate using the metatype.

branches/tensorflow/lib/Sema/CSDiagnostics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,14 @@ bool ContextualFailure::diagnoseAsError() {
13711371
break;
13721372
}
13731373

1374+
case ConstraintLocator::ContextualType: {
1375+
if (isKnownKeyPathType(FromType) && isKnownKeyPathType(ToType)) {
1376+
diagnostic = diag::cannot_convert_initializer_value;
1377+
break;
1378+
}
1379+
1380+
LLVM_FALLTHROUGH;
1381+
}
13741382
default:
13751383
return false;
13761384
}

branches/tensorflow/lib/Sema/CSFix.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,10 @@ AllowInvalidRefInKeyPath::create(ConstraintSystem &cs, RefKind kind,
477477
return new (cs.getAllocator())
478478
AllowInvalidRefInKeyPath(cs, kind, member, locator);
479479
}
480+
481+
KeyPathContextualMismatch *
482+
KeyPathContextualMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs,
483+
ConstraintLocator *locator) {
484+
return new (cs.getAllocator())
485+
KeyPathContextualMismatch(cs, lhs, rhs, locator);
486+
}

branches/tensorflow/lib/Sema/CSFix.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,31 @@ class ContextualMismatch : public ConstraintFix {
458458
ConstraintLocator *locator);
459459
};
460460

461+
/// Detect situations where key path doesn't have capability required
462+
/// by the context e.g. read-only vs. writable, or either root or value
463+
/// types are incorrect e.g.
464+
///
465+
/// ```swift
466+
/// struct S { let foo: Int }
467+
/// let _: WritableKeyPath<S, Int> = \.foo
468+
/// ```
469+
///
470+
/// Here context requires a writable key path but `foo` property is
471+
/// read-only.
472+
class KeyPathContextualMismatch final : public ContextualMismatch {
473+
KeyPathContextualMismatch(ConstraintSystem &cs, Type lhs, Type rhs,
474+
ConstraintLocator *locator)
475+
: ContextualMismatch(cs, lhs, rhs, locator) {}
476+
477+
public:
478+
std::string getName() const override {
479+
return "fix key path contextual mismatch";
480+
}
481+
482+
static KeyPathContextualMismatch *
483+
create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator);
484+
};
485+
461486
/// Detect situations when argument of the @autoclosure parameter is itself
462487
/// marked as @autoclosure and is not applied. Form a fix which suggests a
463488
/// proper way to forward such arguments, e.g.:

branches/tensorflow/lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,14 @@ repairFailures(ConstraintSystem &cs, Type lhs, Type rhs,
20662066
}
20672067

20682068
case ConstraintLocator::ContextualType: {
2069+
// If both types are key path, the only differences
2070+
// between them are mutability and/or root, value type mismatch.
2071+
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
2072+
auto *fix = KeyPathContextualMismatch::create(
2073+
cs, lhs, rhs, cs.getConstraintLocator(locator));
2074+
conversionsOrFixes.push_back(fix);
2075+
}
2076+
20692077
if (lhs->is<FunctionType>() && !rhs->is<AnyFunctionType>() &&
20702078
isa<ClosureExpr>(anchor)) {
20712079
auto *fix = ContextualMismatch::create(cs, lhs, rhs,
@@ -5230,8 +5238,10 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
52305238

52315239
auto resolvedKPTy = BoundGenericType::get(kpDecl, nullptr,
52325240
{rootTy, valueTy});
5233-
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind,
5234-
subflags, locator);
5241+
// Let's check whether deduced key path type would match
5242+
// expected contextual one.
5243+
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
5244+
locator.withPathElement(ConstraintLocator::ContextualType));
52355245
}
52365246

52375247
ConstraintSystem::SolutionKind

branches/tensorflow/lib/Sema/CSSolver.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,8 @@ ConstraintSystem::solveImpl(Expr *&expr,
11561156
if (convertType) {
11571157
auto constraintKind = ConstraintKind::Conversion;
11581158

1159-
if (getContextualTypePurpose() == CTP_ReturnStmt
1159+
if ((getContextualTypePurpose() == CTP_ReturnStmt ||
1160+
getContextualTypePurpose() == CTP_ReturnSingleExpr)
11601161
&& Options.contains(ConstraintSystemFlags::UnderlyingTypeForOpaqueReturnType))
11611162
constraintKind = ConstraintKind::OpaqueUnderlyingType;
11621163

branches/tensorflow/lib/Sema/ConstraintSystem.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,12 @@ void ConstraintSystem::generateConstraints(
27092709
}
27102710
}
27112711

2712+
bool constraints::isKnownKeyPathType(Type type) {
2713+
if (auto *BGT = type->getAs<BoundGenericType>())
2714+
return isKnownKeyPathDecl(type->getASTContext(), BGT->getDecl());
2715+
return false;
2716+
}
2717+
27122718
bool constraints::isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl) {
27132719
return decl == ctx.getKeyPathDecl() || decl == ctx.getWritableKeyPathDecl() ||
27142720
decl == ctx.getReferenceWritableKeyPathDecl() ||

branches/tensorflow/lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4011,6 +4011,10 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
40114011
}
40124012
};
40134013

4014+
/// Determine whether given type is a known one
4015+
/// for a key path `{Writable, ReferenceWritable}KeyPath`.
4016+
bool isKnownKeyPathType(Type type);
4017+
40144018
/// Determine whether given declaration is one for a key path
40154019
/// `{Writable, ReferenceWritable}KeyPath`.
40164020
bool isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl);

branches/tensorflow/lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,20 @@ static bool checkObjCInExtensionContext(const ValueDecl *value,
413413
return false;
414414
}
415415

416-
/// Determines whether the given type is bridged to an Objective-C class type.
417-
static bool isBridgedToObjectiveCClass(DeclContext *dc, Type type) {
416+
/// Determines whether the given type is a valid Objective-C class type that
417+
/// can be returned as a result of a throwing function.
418+
static bool isValidObjectiveCErrorResultType(DeclContext *dc, Type type) {
418419
switch (type->getForeignRepresentableIn(ForeignLanguage::ObjectiveC, dc)
419420
.first) {
420421
case ForeignRepresentableKind::Trivial:
421422
case ForeignRepresentableKind::None:
423+
// Special case: If the type is Unmanaged<T>, then return true, because
424+
// Unmanaged<T> can be represented in Objective-C (if T can be).
425+
if (auto BGT = type->getAs<BoundGenericType>()) {
426+
if (BGT->getDecl() == dc->getASTContext().getUnmanagedDecl()) {
427+
return true;
428+
}
429+
}
422430
return false;
423431

424432
case ForeignRepresentableKind::Object:
@@ -604,12 +612,12 @@ bool swift::isRepresentableInObjC(
604612

605613
errorResultType = boolDecl->getDeclaredType()->getCanonicalType();
606614
} else if (!resultType->getOptionalObjectType() &&
607-
isBridgedToObjectiveCClass(dc, resultType)) {
615+
isValidObjectiveCErrorResultType(dc, resultType)) {
608616
// Functions that return a (non-optional) type bridged to Objective-C
609617
// can be throwing; they indicate failure with a nil result.
610618
kind = ForeignErrorConvention::NilResult;
611619
} else if ((optOptionalType = resultType->getOptionalObjectType()) &&
612-
isBridgedToObjectiveCClass(dc, optOptionalType)) {
620+
isValidObjectiveCErrorResultType(dc, optOptionalType)) {
613621
// Cannot return an optional bridged type, because 'nil' is reserved
614622
// to indicate failure. Call this out in a separate diagnostic.
615623
if (Diagnose) {

branches/tensorflow/test/Constraints/keypath_swift_5.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ struct S {
44
let i: Int
55

66
init() {
7-
let _: WritableKeyPath<S, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
7+
let _: WritableKeyPath<S, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<S, Int>' to specified type 'WritableKeyPath<S, Int>'}}
88

99
S()[keyPath: \.i] = 1
1010
// expected-error@-1 {{cannot assign through subscript: immutable key path}}
1111
}
1212
}
1313

1414
func test() {
15-
let _: WritableKeyPath<C, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
15+
let _: WritableKeyPath<C, Int> = \.i // expected-error {{cannot convert value of type 'KeyPath<C, Int>' to specified type 'WritableKeyPath<C, Int>'}}
1616

1717
C()[keyPath: \.i] = 1
1818
// expected-error@-1 {{cannot assign through subscript: immutable key path}}

0 commit comments

Comments
 (0)