mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Introduce an `unsafe` expression akin to `try` and `await` that notes
that there are unsafe constructs in the expression to the right-hand
side. Extend the effects checker to also check for unsafety along with
throwing and async operations. This will result in diagnostics like
the following:
10 | func sum() -> Int {
11 | withUnsafeBufferPointer { buffer in
12 | let value = buffer[0]
| | `- note: reference to unsafe subscript 'subscript(_:)'
| |- warning: expression uses unsafe constructs but is not marked with 'unsafe'
| `- note: reference to parameter 'buffer' involves unsafe type 'UnsafeBufferPointer<Int>'
13 | tryWithP(X())
14 | return fastAdd(buffer.baseAddress, buffer.count)
These will come with a Fix-It that inserts `unsafe` into the proper
place. There's also a warning that appears when `unsafe` doesn't cover
any unsafe code, making it easier to clean up extraneous `unsafe`.
This approach requires that `@unsafe` be present on any declaration
that involves unsafe constructs within its signature. Outside of the
signature, the `unsafe` expression is used to identify unsafe code.
110 lines
3.1 KiB
C++
110 lines
3.1 KiB
C++
//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines some data types used for 'rethrows' and `reasync` checking.
|
|
//
|
|
// We refer to 'throws' and 'async' as "effects". A function might have either or
|
|
// both effects.
|
|
//
|
|
// A function is _effect polymorphic_ if its effect depends on the call site.
|
|
// This can either be unconditional (the usual 'throws' or 'async' case), or it
|
|
// can depend on either its arguments or conformances (these are 'rethrows' and
|
|
// 'reasync' functions).
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_EFFECTS_H
|
|
#define SWIFT_EFFECTS_H
|
|
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/Basic/OptionSet.h"
|
|
|
|
#include <utility>
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
}
|
|
|
|
namespace swift {
|
|
class AbstractFunctionDecl;
|
|
class ProtocolDecl;
|
|
|
|
enum class EffectKind : uint8_t {
|
|
Throws = 1 << 0,
|
|
Async = 1 << 1,
|
|
Unsafe = 1 << 2,
|
|
};
|
|
using PossibleEffects = OptionSet<EffectKind>;
|
|
|
|
void simple_display(llvm::raw_ostream &out, const EffectKind kind);
|
|
|
|
class ValueDecl;
|
|
|
|
class PolymorphicEffectRequirementList {
|
|
using Requirements = ArrayRef<AbstractFunctionDecl *>;
|
|
using Conformances = ArrayRef<std::pair<Type, ProtocolDecl *>>;
|
|
private:
|
|
Requirements requirements;
|
|
Conformances conformances;
|
|
|
|
public:
|
|
PolymorphicEffectRequirementList(Requirements requirements,
|
|
Conformances conformances)
|
|
: requirements(requirements), conformances(conformances) {}
|
|
PolymorphicEffectRequirementList() {}
|
|
|
|
Requirements getRequirements() const {
|
|
return requirements;
|
|
}
|
|
|
|
Conformances getConformances() const {
|
|
return conformances;
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const PolymorphicEffectRequirementList reqs);
|
|
|
|
enum class PolymorphicEffectKind : uint8_t {
|
|
/// The function does not have this effect at all.
|
|
None,
|
|
|
|
/// The function has this effect if at least one closure argument has it.
|
|
///
|
|
/// This is the ordinary 'rethrows' /'reasync' case.
|
|
ByClosure,
|
|
|
|
/// The function has this effect if at least one of its conformances has it.
|
|
///
|
|
/// This is the conformance-based 'rethrows' /'reasync' case.
|
|
ByConformance,
|
|
|
|
/// The function is only permitted to be `rethrows` because it depends
|
|
/// on a conformance to `AsyncSequence` or `AsyncIteratorProtocol`,
|
|
/// which historically were "@rethrows" protocols.
|
|
AsyncSequenceRethrows,
|
|
|
|
/// The function has this effect unconditionally.
|
|
///
|
|
/// This is a plain old 'throws' / 'async' function.
|
|
Always,
|
|
|
|
/// The function declaration was invalid.
|
|
Invalid
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out, PolymorphicEffectKind value);
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|