Skip to content

Commit 5770b18

Browse files
authored
Merge pull request #3682 from swiftwasm/main
2 parents a416b11 + dec61de commit 5770b18

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1629
-484
lines changed

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,53 @@ _**Note:** This is in reverse chronological order, so newer entries are added to
66
Swift 5.6
77
---------
88

9+
* References to `Self` or so-called "`Self` requirements" in the type signatures
10+
of protocol members are now correctly detected in the parent of a nested type.
11+
As a result, protocol members that fall under this overlooked case are no longer
12+
available on values of protocol type:
13+
14+
```swift
15+
struct Outer<T> {
16+
struct Inner {}
17+
}
18+
19+
protocol P {}
20+
extension P {
21+
func method(arg: Outer<Self>.Inner) {}
22+
}
23+
24+
func test(p: P) {
25+
// error: 'method' has a 'Self' requirement and cannot be used on a value of
26+
// protocol type (use a generic constraint instead).
27+
_ = p.method
28+
}
29+
```
30+
31+
* [SE-0324][]:
32+
33+
Relax diagnostics for pointer arguments to C functions. The Swift
34+
compiler now accepts limited pointer type mismatches when directly
35+
calling functions imported from C as long as the C language allows
36+
those pointer types to alias. Consequently, any Swift
37+
`Unsafe[Mutable]Pointer<T>` or `Unsafe[Mutable]RawPointer` may be
38+
passed to C function arguments declared as `[signed|unsigned] char
39+
*`. Swift `Unsafe[Mutable]Pointer<T>` can also be passed to C
40+
function arguments with an integer type that differs from `T` only
41+
in its signedness.
42+
43+
For example, after importing a C function declaration:
44+
```c
45+
long long decode_int64(const char *ptr_to_int64);
46+
```
47+
Swift can now directly pass a raw pointer as the function argument:
48+
```swift
49+
func decodeAsInt64(data: Data) -> Int64 {
50+
data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
51+
decode_int64(bytes.baseAddress!)
52+
}
53+
}
54+
```
55+
956
* [SE-0315][]:
1057

1158
Type expressions and annotations can now include "type placeholders" which
@@ -8697,6 +8744,7 @@ Swift 1.0
86978744
[SE-0313]: <https://github.com/apple/swift-evolution/blob/main/proposals/0313-actor-isolation-control.md>
86988745
[SE-0315]: <https://github.com/apple/swift-evolution/blob/main/proposals/0315-placeholder-types.md>
86998746
[SE-0316]: <https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md>
8747+
[SE-0324]: <https://github.com/apple/swift-evolution/blob/main/proposals/0324-c-lang-pointer-arg-conversion.md>
87008748

87018749
[SR-75]: <https://bugs.swift.org/browse/SR-75>
87028750
[SR-106]: <https://bugs.swift.org/browse/SR-106>

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,6 +1954,15 @@ NOTE(non_sendable_nominal,none,
19541954
NOTE(add_nominal_sendable_conformance,none,
19551955
"consider making %0 %1 conform to the 'Sendable' protocol",
19561956
(DescriptiveDeclKind, DeclName))
1957+
WARNING(public_decl_needs_sendable,none,
1958+
"public %0 %1 does not specify whether it is 'Sendable' or not",
1959+
(DescriptiveDeclKind, DeclName))
1960+
NOTE(explicit_unchecked_sendable,none,
1961+
"add '@unchecked Sendable' conformance to %0 %1 if this type manually implements concurrency safety",
1962+
(DescriptiveDeclKind, DeclName))
1963+
NOTE(explicit_disable_sendable,none,
1964+
"make %0 %1 explicitly non-Sendable to suppress this warning",
1965+
(DescriptiveDeclKind, DeclName))
19571966

19581967
NOTE(required_by_opaque_return,none,
19591968
"required by opaque return type of %0 %1", (DescriptiveDeclKind, DeclName))

include/swift/Basic/LangOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ namespace swift {
147147
/// Disable API availability checking.
148148
bool DisableAvailabilityChecking = false;
149149

150+
/// Only check the availability of the API, ignore function bodies.
151+
bool CheckAPIAvailabilityOnly = false;
152+
150153
/// Should conformance availability violations be diagnosed as errors?
151154
bool EnableConformanceAvailabilityErrors = false;
152155

@@ -176,6 +179,9 @@ namespace swift {
176179
// Availability macros definitions to be expanded at parsing.
177180
SmallVector<std::string, 4> AvailabilityMacros;
178181

182+
/// Require public declarations to declare that they are Sendable (or not).
183+
bool RequireExplicitSendable = false;
184+
179185
/// If false, '#file' evaluates to the full path rather than a
180186
/// human-readable string.
181187
bool EnableConcisePoundFile = false;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,10 @@ def disable_availability_checking : Flag<["-"],
465465
"disable-availability-checking">,
466466
HelpText<"Disable checking for potentially unavailable APIs">;
467467

468+
def check_api_availability_only : Flag<["-"],
469+
"check-api-availability-only">,
470+
HelpText<"Only check the availability of the APIs, ignore function bodies">;
471+
468472
def enable_conformance_availability_errors : Flag<["-"],
469473
"enable-conformance-availability-errors">,
470474
HelpText<"Diagnose conformance availability violations as errors">;

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ def require_explicit_availability_target : Separate<["-"], "require-explicit-ava
413413
HelpText<"Suggest fix-its adding @available(<target>, *) to public declarations without availability">,
414414
MetaVarName<"<target>">;
415415

416+
def require_explicit_sendable : Flag<["-"], "require-explicit-sendable">,
417+
Flags<[FrontendOption, NoInteractiveOption]>,
418+
HelpText<"Require explicit Sendable annotations on public declarations">;
419+
416420
def define_availability : Separate<["-"], "define-availability">,
417421
Flags<[FrontendOption, NoInteractiveOption]>,
418422
HelpText<"Define an availability macro in the format 'macroName : iOS 13.0, macOS 10.15'">,

include/swift/SIL/OwnershipUtils.h

Lines changed: 106 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
#include "swift/Basic/Debug.h"
1717
#include "swift/Basic/LLVM.h"
18+
#include "swift/SIL/MemAccessUtils.h"
1819
#include "swift/SIL/SILArgument.h"
19-
#include "swift/SIL/SILInstruction.h"
2020
#include "swift/SIL/SILBasicBlock.h"
21+
#include "swift/SIL/SILInstruction.h"
2122
#include "swift/SIL/SILValue.h"
2223
#include "llvm/ADT/SmallPtrSet.h"
2324
#include "llvm/ADT/SmallVector.h"
@@ -29,6 +30,7 @@ class SILInstruction;
2930
class SILModule;
3031
class SILValue;
3132
class DeadEndBlocks;
33+
class PrunedLiveness;
3234

3335
/// Returns true if v is an address or trivial.
3436
bool isValueAddressOrTrivial(SILValue v);
@@ -148,7 +150,7 @@ bool findTransitiveGuaranteedUses(SILValue guaranteedValue,
148150
/// 1. If \p guaranteedValue introduces a borrow scope (begin_borrow,
149151
/// load_borrow, or phi), then its only use points are the extended scope-ending
150152
/// uses, and this function returns true. This is, in fact, equivalent to
151-
/// calling BorrowedValue::visitExtendedLocalScopeEndingUses().
153+
/// calling BorrowedValue::visitExtendedScopeEndingUses().
152154
///
153155
/// 2. If \p guaranteedValue does not introduce a borrow scope (it is not a
154156
/// valid BorrowedValue), then its uses are discovered transitively by looking
@@ -172,8 +174,8 @@ class ForwardingOperand {
172174
return use->getOwnershipConstraint();
173175
}
174176

175-
ValueOwnershipKind getOwnershipKind() const;
176-
void setOwnershipKind(ValueOwnershipKind newKind) const;
177+
ValueOwnershipKind getForwardingOwnershipKind() const;
178+
void setForwardingOwnershipKind(ValueOwnershipKind newKind) const;
177179
void replaceOwnershipKind(ValueOwnershipKind oldKind,
178180
ValueOwnershipKind newKind) const;
179181

@@ -304,13 +306,20 @@ struct BorrowingOperand {
304306
/// visits the end of the introduced borrow scope.
305307
bool visitScopeEndingUses(function_ref<bool(Operand *)> func) const;
306308

309+
/// Returns true for borrows that create a local borrow scope but have no
310+
/// scope-ending uses (presumably all paths are dead-end blocks). This does
311+
/// not include instantaneous borrows, which don't require explicit scope
312+
/// ending uses.
313+
///
314+
/// FIXME: Borrow scopes should have scope-ending uses on all paths, even to
315+
/// dead end blocks. When the verifier enforces this, remove this check.
316+
bool hasEmptyRequiredEndingUses() const;
317+
307318
/// Visit the scope ending operands of the extended scope, after transitively
308319
/// searching through reborrows. These uses might not be dominated by this
309320
/// BorrowingOperand.
310321
///
311322
/// Returns false and early exits if the visitor \p func returns false.
312-
///
313-
/// Note: this does not visit the intermediate reborrows.
314323
bool visitExtendedScopeEndingUses(function_ref<bool(Operand *)> func) const;
315324

316325
/// Returns true if this borrow scope operand consumes guaranteed
@@ -493,7 +502,7 @@ struct InteriorPointerOperand;
493502
/// jointly post-dominate this value (see visitLocalScopeEndingUses()). The
494503
/// extended scope, including reborrows has end points that are not dominated by
495504
/// this value but still jointly post-dominate (see
496-
/// visitExtendedLocalScopeEndingUses()).
505+
/// visitExtendedScopeEndingUses()).
497506
struct BorrowedValue {
498507
SILValue value;
499508
BorrowedValueKind kind = BorrowedValueKind::Invalid;
@@ -535,20 +544,25 @@ struct BorrowedValue {
535544

536545
bool isLocalScope() const { return kind.isLocalScope(); }
537546

538-
/// Returns true if the passed in set of uses is completely within
539-
/// the lifetime of this borrow introducer.
547+
/// Add this scopes live blocks into the PrunedLiveness result.
548+
void computeLiveness(PrunedLiveness &liveness) const;
549+
550+
/// Returns true if \p uses are completely within this borrow introducer's
551+
/// local scope.
540552
///
541-
/// NOTE: Scratch space is used internally to this method to store the end
542-
/// borrow scopes if needed.
543-
bool areUsesWithinScope(ArrayRef<Operand *> uses,
544-
SmallVectorImpl<Operand *> &scratchSpace,
545-
DeadEndBlocks &deadEndBlocks) const;
553+
/// Precondition: \p uses are dominated by the local borrow introducer.
554+
///
555+
/// This ignores reborrows. The assumption is that, since \p uses are
556+
/// dominated by this local scope, checking the extended borrow scope should
557+
/// not be necessary to determine they are within the scope.
558+
bool areUsesWithinLocalScope(ArrayRef<Operand *> uses,
559+
DeadEndBlocks &deadEndBlocks) const;
546560

547561
/// Given a local borrow scope introducer, visit all non-forwarding consuming
548562
/// users. This means that this looks through guaranteed block arguments. \p
549563
/// visitor is *not* called on Reborrows, only on final scope ending uses.
550-
bool visitExtendedLocalScopeEndingUses(
551-
function_ref<bool(Operand *)> visitor) const;
564+
bool
565+
visitExtendedScopeEndingUses(function_ref<bool(Operand *)> visitor) const;
552566

553567
void print(llvm::raw_ostream &os) const;
554568
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
@@ -583,6 +597,14 @@ struct BorrowedValue {
583597
func, InteriorPointerOperandVisitorKind::YesNestedYesReborrows);
584598
}
585599

600+
bool hasReborrow() const {
601+
for (auto *op : value->getUses()) {
602+
if (op->getOperandOwnership() == OperandOwnership::Reborrow)
603+
return true;
604+
}
605+
return false;
606+
}
607+
586608
/// Visit all immediate uses of this borrowed value and if any of them are
587609
/// reborrows, place them in BorrowingOperand form into \p
588610
/// foundReborrows. Returns true if we appended any such reborrows to
@@ -591,12 +613,10 @@ struct BorrowedValue {
591613
&foundReborrows) const {
592614
bool foundAnyReborrows = false;
593615
for (auto *op : value->getUses()) {
594-
if (auto borrowingOperand = BorrowingOperand(op)) {
595-
if (borrowingOperand.isReborrow()) {
596-
foundReborrows.push_back(
597-
{value->getParentBlock(), op->getOperandNumber()});
598-
foundAnyReborrows = true;
599-
}
616+
if (op->getOperandOwnership() == OperandOwnership::Reborrow) {
617+
foundReborrows.push_back(
618+
{value->getParentBlock(), op->getOperandNumber()});
619+
foundAnyReborrows = true;
600620
}
601621
}
602622
return foundAnyReborrows;
@@ -642,6 +662,13 @@ bool getAllBorrowIntroducingValues(SILValue value,
642662
/// introducer, then we return a .some(BorrowScopeIntroducingValue).
643663
BorrowedValue getSingleBorrowIntroducingValue(SILValue inputValue);
644664

665+
/// The algorithm that is used to determine what the verifier will consider to
666+
/// be transitive uses of the given address. Used to implement \see
667+
/// findTransitiveUses.
668+
bool findTransitiveUsesForAddress(
669+
SILValue address, SmallVectorImpl<Operand *> &foundUses,
670+
std::function<void(Operand *)> *onError = nullptr);
671+
645672
class InteriorPointerOperandKind {
646673
public:
647674
enum Kind : uint8_t {
@@ -785,7 +812,7 @@ struct InteriorPointerOperand {
785812
}
786813

787814
/// Return the base BorrowedValue of the incoming value's operand.
788-
BorrowedValue getSingleBaseValue() const {
815+
BorrowedValue getSingleBorrowedValue() const {
789816
return getSingleBorrowIntroducingValue(operand->get());
790817
}
791818

@@ -820,14 +847,6 @@ struct InteriorPointerOperand {
820847
onError);
821848
}
822849

823-
/// The algorithm that is used to determine what the verifier will consider to
824-
/// be transitive uses of the given address. Used to implement \see
825-
/// findTransitiveUses.
826-
static bool
827-
findTransitiveUsesForAddress(SILValue address,
828-
SmallVectorImpl<Operand *> &foundUses,
829-
std::function<void(Operand *)> *onError = nullptr);
830-
831850
Operand *operator->() { return operand; }
832851
const Operand *operator->() const { return operand; }
833852
Operand *operator*() { return operand; }
@@ -840,23 +859,70 @@ struct InteriorPointerOperand {
840859
: operand(op), kind(kind) {}
841860
};
842861

843-
/// Utility to check if an address may originate from a borrowed value. If so,
862+
/// Utility to check if an address may originate from an OSSA value. If so,
844863
/// then uses of the address cannot be replaced without ensuring that they are
845-
/// also within the same scope.
864+
/// also within the same owned lifetime or borrow scope.
846865
///
847-
/// If mayBeBorrowed is false, then there is no enclosing borrow scope and
848-
/// interiorPointerOp is irrelevant.
866+
/// If hasOwnership() is false, then there is no enclosing lifetime or borrow
867+
/// scope and interiorPointerOp is irrelevant.
849868
///
850-
/// If mayBeBorrowed is true, then interiorPointerOp refers to the operand that
869+
/// If hasOwnership() is true, then interiorPointerOp refers to the operand that
851870
/// converts a non-address value into the address from which the contructor's
852871
/// address is derived. If the best-effort to find an InteriorPointerOperand
853872
/// fails, then interiorPointerOp remains invalid, and clients must be
854873
/// conservative.
855-
struct BorrowedAddress {
856-
bool mayBeBorrowed = true;
857-
InteriorPointerOperand interiorPointerOp;
874+
///
875+
/// TODO: Handle implicit borrow scopes once they are legal in SIL. The operand
876+
/// of the base will be owned but mayBeBorrowed will remain true.
877+
struct AddressOwnership {
878+
AccessBase base;
879+
880+
AddressOwnership() = default;
881+
882+
AddressOwnership(SILValue address) : base(AccessBase::compute(address)) {
883+
assert(address->getType().isAddress());
884+
}
885+
886+
AddressOwnership(AccessBase base) : base(base) {}
887+
888+
operator bool() const { return bool(base); }
889+
890+
bool operator==(const AddressOwnership &other) const {
891+
return base.hasIdenticalAccessInfo(other.base);
892+
}
893+
894+
bool operator!=(const AddressOwnership &other) const {
895+
return !(*this == other);
896+
}
858897

859-
BorrowedAddress(SILValue address);
898+
/// Return true if this address may be derived from a value with a local OSSA
899+
/// lifetime or borrow scope.
900+
bool hasLocalOwnershipLifetime() const {
901+
return base.hasLocalOwnershipLifetime();
902+
}
903+
904+
/// Return the OSSA value from which this address is derived. This may be
905+
/// invalid even if hasOSSALifetime() is true in cases where the
906+
/// InteriorPointerOperand is unrecognized.
907+
SILValue getOwnershipReferenceRoot() const {
908+
if (base.isReference())
909+
return base.getOwnershipReferenceRoot();
910+
911+
return SILValue();
912+
}
913+
914+
/// Transitively compute uses of this base address.
915+
bool findTransitiveUses(SmallVectorImpl<Operand *> &foundUses) {
916+
return findTransitiveUsesForAddress(base.getBaseAddress(), foundUses);
917+
}
918+
919+
/// Return true of all \p uses occur before the end of the address' lifetime
920+
/// or borrow scope.
921+
///
922+
/// Precondition: all \p uses are dominated by the beginning of the address'
923+
/// lifetime or borrow scope.
924+
bool areUsesWithinLifetime(ArrayRef<Operand *> uses,
925+
DeadEndBlocks &deadEndBlocks) const;
860926
};
861927

862928
class OwnedValueIntroducerKind {

0 commit comments

Comments
 (0)