Files
swift-mirror/include/swift/AST/Effects.h
Doug Gregor 8bb5bbedbc Implement an unsafe expression to cover uses of unsafe constructs
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.
2025-01-10 10:39:14 -08:00

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