Skip to content

Commit bcb98fa

Browse files
authored
Merge pull request #16623 from rudkx/rdar31538995
Disallow some implicit pointer conversions in autoclosures.
2 parents b90692a + 43775e8 commit bcb98fa

File tree

8 files changed

+153
-48
lines changed

8 files changed

+153
-48
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,8 +673,9 @@ class alignas(1 << TypeAlignInBits) TypeBase {
673673
/// Break an existential down into a set of constraints.
674674
ExistentialLayout getExistentialLayout();
675675

676-
/// Determines the element type of a known *UnsafeMutablePointer
677-
/// variant, or returns null if the type is not a pointer.
676+
/// Determines the element type of a known
677+
/// [Autoreleasing]Unsafe[Mutable][Raw]Pointer variant, or returns null if the
678+
/// type is not a pointer.
678679
Type getAnyPointerElementType(PointerTypeKind &PTK);
679680
Type getAnyPointerElementType() {
680681
PointerTypeKind Ignore;

lib/Sema/CSApply.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -6900,8 +6900,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69006900
->castTo<FunctionType>();
69016901

69026902
// Convert the value to the expected result type of the function.
6903-
expr = coerceToType(expr, toFunc->getResult(),
6904-
locator.withPathElement(ConstraintLocator::Load));
6903+
expr = coerceToType(
6904+
expr, toFunc->getResult(),
6905+
locator.withPathElement(ConstraintLocator::AutoclosureResult));
69056906

69066907
// We'll set discriminator values on all the autoclosures in a
69076908
// later pass.

lib/Sema/CSDiag.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -194,11 +194,13 @@ void constraints::simplifyLocator(Expr *&anchor,
194194

195195
break;
196196

197-
case ConstraintLocator::Load:
197+
case ConstraintLocator::AutoclosureResult:
198198
case ConstraintLocator::RvalueAdjustment:
199199
case ConstraintLocator::ScalarToTuple:
200200
case ConstraintLocator::UnresolvedMember:
201-
// Loads, rvalue adjustment, and scalar-to-tuple conversions are implicit.
201+
// Arguments in autoclosure positions, rvalue adjustments, and
202+
// scalar-to-tuple conversions, and unresolved members are
203+
// implicit.
202204
path = path.slice(1);
203205
continue;
204206

lib/Sema/CSSimplify.cpp

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,10 +2161,18 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
21612161
// an implicit closure.
21622162
if (auto function2 = type2->getAs<FunctionType>()) {
21632163
if (function2->isAutoClosure())
2164-
return matchTypes(type1, function2->getResult(), kind, subflags,
2165-
locator.withPathElement(ConstraintLocator::Load));
2164+
return matchTypes(
2165+
type1, function2->getResult(), kind, subflags,
2166+
locator.withPathElement(ConstraintLocator::AutoclosureResult));
21662167
}
21672168

2169+
// It is never legal to form an autoclosure that results in these
2170+
// implicit conversions to pointer types.
2171+
bool isAutoClosureArgument = false;
2172+
if (auto last = locator.last())
2173+
if (last->getKind() == ConstraintLocator::AutoclosureResult)
2174+
isAutoClosureArgument = true;
2175+
21682176
// Pointer arguments can be converted from pointer-compatible types.
21692177
if (kind >= ConstraintKind::ArgumentConversion) {
21702178
Type unwrappedType2 = type2;
@@ -2183,23 +2191,24 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
21832191
case PTK_UnsafeMutablePointer:
21842192
// UnsafeMutablePointer can be converted from an inout reference to a
21852193
// scalar or array.
2186-
if (auto inoutType1 = dyn_cast<InOutType>(desugar1)) {
2187-
auto inoutBaseType = inoutType1->getInOutObjectType();
2188-
2189-
Type simplifiedInoutBaseType =
2190-
getFixedTypeRecursive(inoutBaseType,
2191-
kind == ConstraintKind::Equal,
2192-
isArgumentTupleConversion);
2193-
2194-
// FIXME: If the base is still a type variable, we can't tell
2195-
// what to do here. Might have to try \c ArrayToPointer and make it
2196-
// more robust.
2197-
if (isArrayType(simplifiedInoutBaseType)) {
2194+
if (!isAutoClosureArgument) {
2195+
if (auto inoutType1 = dyn_cast<InOutType>(desugar1)) {
2196+
auto inoutBaseType = inoutType1->getInOutObjectType();
2197+
2198+
Type simplifiedInoutBaseType = getFixedTypeRecursive(
2199+
inoutBaseType, kind == ConstraintKind::Equal,
2200+
isArgumentTupleConversion);
2201+
2202+
// FIXME: If the base is still a type variable, we can't tell
2203+
// what to do here. Might have to try \c ArrayToPointer and make
2204+
// it more robust.
2205+
if (isArrayType(simplifiedInoutBaseType)) {
2206+
conversionsOrFixes.push_back(
2207+
ConversionRestrictionKind::ArrayToPointer);
2208+
}
21982209
conversionsOrFixes.push_back(
2199-
ConversionRestrictionKind::ArrayToPointer);
2210+
ConversionRestrictionKind::InoutToPointer);
22002211
}
2201-
conversionsOrFixes.push_back(
2202-
ConversionRestrictionKind::InoutToPointer);
22032212
}
22042213

22052214
if (!flags.contains(TMF_ApplyingOperatorParameter) &&
@@ -2247,20 +2256,22 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
22472256
// AutoreleasingUnsafeMutablePointer.
22482257
if (pointerKind == PTK_UnsafePointer
22492258
|| pointerKind == PTK_UnsafeRawPointer) {
2250-
if (isArrayType(type1)) {
2251-
conversionsOrFixes.push_back(
2252-
ConversionRestrictionKind::ArrayToPointer);
2253-
}
2254-
2255-
// The pointer can be converted from a string, if the element type
2256-
// is compatible.
2257-
if (type1->isEqual(TC.getStringType(DC))) {
2258-
auto baseTy = getFixedTypeRecursive(pointeeTy, false);
2259-
2260-
if (baseTy->isTypeVariableOrMember() ||
2261-
isStringCompatiblePointerBaseType(TC, DC, baseTy))
2259+
if (!isAutoClosureArgument) {
2260+
if (isArrayType(type1)) {
22622261
conversionsOrFixes.push_back(
2263-
ConversionRestrictionKind::StringToPointer);
2262+
ConversionRestrictionKind::ArrayToPointer);
2263+
}
2264+
2265+
// The pointer can be converted from a string, if the element
2266+
// type is compatible.
2267+
if (type1->isEqual(TC.getStringType(DC))) {
2268+
auto baseTy = getFixedTypeRecursive(pointeeTy, false);
2269+
2270+
if (baseTy->isTypeVariableOrMember() ||
2271+
isStringCompatiblePointerBaseType(TC, DC, baseTy))
2272+
conversionsOrFixes.push_back(
2273+
ConversionRestrictionKind::StringToPointer);
2274+
}
22642275
}
22652276

22662277
if (type1IsPointer && optionalityMatches &&
@@ -2276,7 +2287,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
22762287
case PTK_AutoreleasingUnsafeMutablePointer:
22772288
// PTK_AutoreleasingUnsafeMutablePointer can be converted from an
22782289
// inout reference to a scalar.
2279-
if (type1->is<InOutType>()) {
2290+
if (!isAutoClosureArgument && type1->is<InOutType>()) {
22802291
conversionsOrFixes.push_back(
22812292
ConversionRestrictionKind::InoutToPointer);
22822293
}

lib/Sema/ConstraintLocator.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -69,7 +69,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
6969
case GeneratorElementType:
7070
case ArrayElementType:
7171
case ScalarToTuple:
72-
case Load:
72+
case AutoclosureResult:
7373
case GenericArgument:
7474
case NamedTupleElement:
7575
case TupleElement:
@@ -173,8 +173,8 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
173173
out << "instance type";
174174
break;
175175

176-
case Load:
177-
out << "load";
176+
case AutoclosureResult:
177+
out << "@autoclosure result";
178178
break;
179179

180180
case Member:

lib/Sema/ConstraintLocator.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -111,8 +111,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
111111
ArrayElementType,
112112
/// \brief The scalar type of a tuple type.
113113
ScalarToTuple,
114-
/// \brief The load of an lvalue.
115-
Load,
114+
/// \brief An argument passed in an autoclosure parameter
115+
/// position, which must match the autoclosure return type.
116+
AutoclosureResult,
116117
/// The requirement that we're matching during protocol conformance
117118
/// checking.
118119
Requirement,
@@ -159,7 +160,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
159160
case GeneratorElementType:
160161
case ArrayElementType:
161162
case ScalarToTuple:
162-
case Load:
163+
case AutoclosureResult:
163164
case Requirement:
164165
case Witness:
165166
case OpenedGeneric:
@@ -205,7 +206,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
205206
case ClosureResult:
206207
case ConstructorMember:
207208
case InstanceType:
208-
case Load:
209+
case AutoclosureResult:
209210
case OptionalPayload:
210211
case Member:
211212
case MemberRefBase:
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
func takesAutoclosure<T>(_ lhs: T, _ rhs: @autoclosure () throws -> T) {}
4+
5+
func test(
6+
_ rawPtr: UnsafeRawPointer,
7+
_ mutRawPtr: UnsafeMutableRawPointer,
8+
_ mutPtr: UnsafeMutablePointer<Int>,
9+
_ ptr: UnsafePointer<Int>,
10+
_ ptrI8: UnsafePointer<Int8>,
11+
_ ptrU8: UnsafePointer<UInt8>,
12+
_ ptrVoid: UnsafePointer<Void> // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
13+
) {
14+
var i: Int = 0
15+
var a: [Int] = [0]
16+
let s = "string"
17+
18+
takesAutoclosure(rawPtr, &i) // expected-error {{'&' used with non-inout argument of type 'Int'}}
19+
takesAutoclosure(mutRawPtr, &i) // expected-error {{'&' used with non-inout argument of type 'Int'}}
20+
takesAutoclosure(mutPtr, &i) // expected-error {{'&' used with non-inout argument of type 'Int'}}
21+
takesAutoclosure(ptr, &i) // expected-error {{'&' used with non-inout argument of type 'Int'}}
22+
takesAutoclosure(rawPtr, &a) // expected-error {{'&' used with non-inout argument of type '[Int]'}}
23+
takesAutoclosure(mutRawPtr, &a) // expected-error {{'&' used with non-inout argument of type '[Int]'}}
24+
takesAutoclosure(mutPtr, &a) // expected-error {{'&' used with non-inout argument of type '[Int]'}}
25+
takesAutoclosure(ptr, &a) // expected-error {{'&' used with non-inout argument of type '[Int]'}}
26+
27+
takesAutoclosure(rawPtr, a) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafeRawPointer, [Int])'}}
28+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
29+
takesAutoclosure(ptr, a) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Int>, [Int])'}}
30+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
31+
32+
takesAutoclosure(rawPtr, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafeRawPointer, String)'}}
33+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
34+
takesAutoclosure(ptrI8, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Int8>, String)'}}
35+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
36+
takesAutoclosure(ptrU8, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<UInt8>, String)'}}
37+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
38+
takesAutoclosure(ptrVoid, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Void>, String)'}}
39+
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
40+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
func takesAutoclosure<T>(_ lhs: T, _ rhs: @autoclosure () throws -> T) {}
4+
func takesUnsafeRawPointer(_ ptr: UnsafeRawPointer) {}
5+
func takesUnsafeMutableRawPointer(_ ptr: UnsafeMutableRawPointer) {}
6+
func takesUnsafePointer<T>(_ ptr: UnsafePointer<T>) {}
7+
func takesUnsafeMutablePointer<T>(_ ptr: UnsafeMutablePointer<T>) {}
8+
func takesUnsafePointerInt8(_ ptr: UnsafePointer<Int8>) {}
9+
func takesUnsafePointerUInt8(_ ptr: UnsafePointer<UInt8>) {}
10+
func takesUnsafePointerVoid(_ ptr: UnsafePointer<Void>) {} // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
11+
12+
func test(
13+
_ rawPtr: UnsafeRawPointer,
14+
_ mutRawPtr: UnsafeMutableRawPointer,
15+
_ mutPtr: UnsafeMutablePointer<Int>,
16+
_ ptr: UnsafePointer<Int>
17+
) {
18+
var i: Int = 0
19+
var a: [Int] = [0]
20+
let s = "string"
21+
22+
takesUnsafeRawPointer(&i)
23+
takesUnsafeMutableRawPointer(&i)
24+
takesUnsafeMutablePointer(&i)
25+
takesUnsafePointer(&i)
26+
takesUnsafeRawPointer(&a)
27+
takesUnsafeMutableRawPointer(&a)
28+
takesUnsafeMutablePointer(&a)
29+
takesUnsafePointer(&a)
30+
31+
takesUnsafeRawPointer(mutPtr)
32+
takesUnsafeMutableRawPointer(mutPtr)
33+
takesUnsafePointer(mutPtr)
34+
35+
takesUnsafeRawPointer(mutRawPtr)
36+
37+
takesUnsafeRawPointer(a)
38+
takesUnsafePointer(a)
39+
40+
takesAutoclosure(rawPtr, mutPtr)
41+
takesAutoclosure(mutRawPtr, mutPtr)
42+
takesAutoclosure(ptr, mutPtr)
43+
takesAutoclosure(rawPtr, mutRawPtr)
44+
45+
takesUnsafeRawPointer(s)
46+
takesUnsafePointerInt8(s)
47+
takesUnsafePointerUInt8(s)
48+
takesUnsafePointerVoid(s)
49+
}

0 commit comments

Comments
 (0)