Skip to content

Commit 6720a7c

Browse files
authored
Merge branch 'master' into artiodactyla
2 parents b3c5a68 + f5ba89d commit 6720a7c

30 files changed

+455
-101
lines changed

benchmark/single-source/ExistentialPerformance.swift

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -264,17 +264,6 @@ func caRef1() { ca(Ref1.self) }
264264
func caRef2() { ca(Ref2.self) }
265265
func caRef3() { ca(Ref3.self) }
266266
func caRef4() { ca(Ref4.self) }
267-
@inline(never)
268-
func grabArray() -> [Existential] { // transfer array ownership to caller
269-
// FIXME: This is causing Illegal Instruction: 4 crash
270-
// defer { array = nil }
271-
// return array
272-
// This doesn't work either:
273-
// let a = array!
274-
// array = nil
275-
// return a
276-
return array!
277-
}
278267

279268
// `setUpFunctions` that determine which existential type will be tested
280269
var existentialType: Existential.Type!
@@ -540,7 +529,7 @@ func run_Array_init(_ N: Int) {
540529
}
541530

542531
func run_Array_method1x(_ N: Int) {
543-
let existentialArray = grabArray()
532+
let existentialArray = array!
544533
for _ in 0 ..< N * 100 {
545534
for elt in existentialArray {
546535
if !elt.doIt() {
@@ -551,7 +540,7 @@ func run_Array_method1x(_ N: Int) {
551540
}
552541

553542
func run_Array_method2x(_ N: Int) {
554-
let existentialArray = grabArray()
543+
let existentialArray = array!
555544
for _ in 0 ..< N * 100 {
556545
for elt in existentialArray {
557546
if !elt.doIt() || !elt.reallyDoIt() {
@@ -562,8 +551,8 @@ func run_Array_method2x(_ N: Int) {
562551
}
563552

564553
func run_ArrayMutating(_ N: Int) {
565-
var existentialArray = grabArray()
566-
for _ in 0 ..< N * 100 {
554+
var existentialArray = array!
555+
for _ in 0 ..< N * 500 {
567556
for i in 0 ..< existentialArray.count {
568557
if !existentialArray[i].mutateIt() {
569558
fatalError("expected true")
@@ -573,7 +562,7 @@ func run_ArrayMutating(_ N: Int) {
573562
}
574563

575564
func run_ArrayShift(_ N: Int) {
576-
var existentialArray = grabArray()
565+
var existentialArray = array!
577566
for _ in 0 ..< N * 25 {
578567
for i in 0 ..< existentialArray.count-1 {
579568
existentialArray.swapAt(i, i+1)
@@ -582,7 +571,7 @@ func run_ArrayShift(_ N: Int) {
582571
}
583572

584573
func run_ArrayConditionalShift(_ N: Int) {
585-
var existentialArray = grabArray()
574+
var existentialArray = array!
586575
for _ in 0 ..< N * 25 {
587576
for i in 0 ..< existentialArray.count-1 {
588577
let curr = existentialArray[i]

benchmark/single-source/ExistentialPerformance.swift.gyb

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ Setup = """
3636
let existential = existentialType.init()
3737
let existential2 = existentialType.init()
3838
var existential = existentialType.init()
39-
let existentialArray = grabArray()
40-
var existentialArray = grabArray()
39+
let existentialArray = array!
40+
var existentialArray = array!
4141
""".splitlines()
4242
Setup = [Setup[0], Setup[1], '\n'.join(Setup[1:3]), Setup[3], Setup[4], Setup[5]]
4343

@@ -90,7 +90,7 @@ Workloads = [
9090
}
9191
}
9292
"""),
93-
('Array.Mutating', Setup[5], '100', """
93+
('Array.Mutating', Setup[5], '500', """
9494
for i in 0 ..< existentialArray.count {
9595
if !existentialArray[i].mutateIt() {
9696
fatalError("expected true")
@@ -151,17 +151,6 @@ func ca<T: Existential>(_: T.Type) {
151151
% for Variant in Vals + Refs:
152152
func ca${Variant}() { ca(${Variant}.self) }
153153
% end
154-
@inline(never)
155-
func grabArray() -> [Existential] { // transfer array ownership to caller
156-
// FIXME: This is causing Illegal Instruction: 4 crash
157-
// defer { array = nil }
158-
// return array
159-
// This doesn't work either:
160-
// let a = array!
161-
// array = nil
162-
// return a
163-
return array!
164-
}
165154

166155
// `setUpFunctions` that determine which existential type will be tested
167156
var existentialType: Existential.Type!

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3075,10 +3075,15 @@ NOTE(silence_debug_description_in_interpolation_segment_call,none,
30753075
NOTE(noescape_parameter,none,
30763076
"parameter %0 is implicitly non-escaping",
30773077
(Identifier))
3078+
NOTE(generic_parameters_always_escaping,none,
3079+
"generic parameters are always considered '@escaping'", ())
30783080

30793081
ERROR(passing_noescape_to_escaping,none,
30803082
"passing non-escaping parameter %0 to function expecting an @escaping closure",
30813083
(Identifier))
3084+
ERROR(converting_noespace_param_to_generic_type,none,
3085+
"converting non-escaping parameter %0 to generic parameter %1 may allow it to escape",
3086+
(Identifier, Type))
30823087
ERROR(assigning_noescape_to_escaping,none,
30833088
"assigning non-escaping parameter %0 to an @escaping closure",
30843089
(Identifier))

include/swift/AST/Evaluator.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ class Evaluator {
285285
(*this)(requests)...);
286286
}
287287

288+
/// Cache a precomputed value for the given request, so that it will not
289+
/// be computed.
290+
template<typename Request,
291+
typename std::enable_if<Request::hasExternalCache>::type* = nullptr>
292+
void cacheOutput(const Request &request,
293+
typename Request::OutputType &&output) {
294+
request.cacheResult(std::move(output));
295+
}
296+
297+
/// Cache a precomputed value for the given request, so that it will not
298+
/// be computed.
299+
template<typename Request,
300+
typename std::enable_if<!Request::hasExternalCache>::type* = nullptr>
301+
void cacheOutput(const Request &request,
302+
typename Request::OutputType &&output) {
303+
cache.insert({getCanonicalRequest(request), std::move(output)});
304+
}
305+
288306
/// Clear the cache stored within this evaluator.
289307
///
290308
/// Note that this does not clear the caches of requests that use external

include/swift/SIL/TypeSubstCloner.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
193193
Helper.getArguments(), Inst->isNonThrowing(),
194194
GenericSpecializationInformation::create(
195195
Inst, getBuilder()));
196+
// Specialization can return noreturn applies that were not identified as
197+
// such before.
198+
if (N->isCalleeNoReturn() &&
199+
!isa<UnreachableInst>(*std::next(SILBasicBlock::iterator(Inst)))) {
200+
noReturnApplies.push_back(N);
201+
}
202+
196203
recordClonedInstruction(Inst, N);
197204
}
198205

@@ -381,6 +388,9 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
381388
SILFunction &Original;
382389
/// True, if used for inlining.
383390
bool Inlining;
391+
// Generic specialization can create noreturn applications that where
392+
// previously not identifiable as such.
393+
SmallVector<ApplyInst *, 16> noReturnApplies;
384394
};
385395

386396
} // end namespace swift

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class GenericCloner
7474
return SC.getCloned();
7575
}
7676

77+
void fixUp(SILFunction *calleeFunction);
78+
7779
protected:
7880
void visitTerminator(SILBasicBlock *BB);
7981

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 489; // dependency directories
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 490; // dependency directories
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1054,7 +1054,8 @@ namespace decls_block {
10541054
AccessLevelField, // access level
10551055
AccessLevelField, // setter access, if applicable
10561056
DeclIDField, // opaque return type decl
1057-
BCArray<TypeIDField> // accessors and dependencies
1057+
BCFixed<2>, // # of property delegate backing properties
1058+
BCArray<TypeIDField> // accessors, backing properties, and dependencies
10581059
>;
10591060

10601061
using ParamLayout = BCRecordLayout<

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,12 @@ const SILDebugScope *GenericCloner::remapScope(const SILDebugScope *DS) {
191191
RemappedScopeCache.insert({DS, RemappedScope});
192192
return RemappedScope;
193193
}
194+
195+
void GenericCloner::fixUp(SILFunction *f) {
196+
for (auto *apply : noReturnApplies) {
197+
auto applyBlock = apply->getParent();
198+
applyBlock->split(std::next(SILBasicBlock::iterator(apply)));
199+
getBuilder().setInsertionPoint(applyBlock);
200+
getBuilder().createUnreachable(apply->getLoc());
201+
}
202+
}

lib/Sema/CSDiag.cpp

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -173,17 +173,26 @@ void constraints::simplifyLocator(Expr *&anchor,
173173
continue;
174174

175175
case ConstraintLocator::NamedTupleElement:
176-
case ConstraintLocator::TupleElement:
176+
case ConstraintLocator::TupleElement: {
177177
// Extract tuple element.
178+
unsigned index = path[0].getValue();
178179
if (auto tupleExpr = dyn_cast<TupleExpr>(anchor)) {
179-
unsigned index = path[0].getValue();
180180
if (index < tupleExpr->getNumElements()) {
181181
anchor = tupleExpr->getElement(index);
182182
path = path.slice(1);
183183
continue;
184184
}
185185
}
186+
187+
if (auto *CE = dyn_cast<CollectionExpr>(anchor)) {
188+
if (index < CE->getNumElements()) {
189+
anchor = CE->getElement(index);
190+
path = path.slice(1);
191+
continue;
192+
}
193+
}
186194
break;
195+
}
187196

188197
case ConstraintLocator::ApplyArgToParam:
189198
// Extract tuple element.
@@ -1994,34 +2003,9 @@ bool FailureDiagnosis::diagnoseNonEscapingParameterToEscaping(
19942003
if (!srcFT || !dstFT || !srcFT->isNoEscape() || dstFT->isNoEscape())
19952004
return false;
19962005

1997-
// Pick a specific diagnostic for the specific use
1998-
auto paramDecl = cast<ParamDecl>(declRef->getDecl());
1999-
switch (dstPurpose) {
2000-
case CTP_CallArgument:
2001-
CS.TC.diagnose(declRef->getLoc(), diag::passing_noescape_to_escaping,
2002-
paramDecl->getName());
2003-
break;
2004-
case CTP_AssignSource:
2005-
CS.TC.diagnose(declRef->getLoc(), diag::assigning_noescape_to_escaping,
2006-
paramDecl->getName());
2007-
break;
2008-
2009-
default:
2010-
CS.TC.diagnose(declRef->getLoc(), diag::general_noescape_to_escaping,
2011-
paramDecl->getName());
2012-
break;
2013-
}
2014-
2015-
// Give a note and fixit
2016-
InFlightDiagnostic note = CS.TC.diagnose(
2017-
paramDecl->getLoc(), diag::noescape_parameter, paramDecl->getName());
2018-
2019-
if (!paramDecl->isAutoClosure()) {
2020-
note.fixItInsert(paramDecl->getTypeLoc().getSourceRange().Start,
2021-
"@escaping ");
2022-
} // TODO: add in a fixit for autoclosure
2023-
2024-
return true;
2006+
NoEscapeFuncToTypeConversionFailure failure(
2007+
expr, CS, CS.getConstraintLocator(expr), dstType);
2008+
return failure.diagnoseAsError();
20252009
}
20262010

20272011
bool FailureDiagnosis::diagnoseContextualConversionError(

0 commit comments

Comments
 (0)