mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
31f99c2f55
Normally, an unbound reference to a generic type within its own context is automatically bound to the identity generic arguments:
```
struct G<T> {
typealias TA = G // as if you wrote G<T>
}
```
Module selectors normally disable this kind of contextual behavior; make sure that this is not an exception.
To pipe the information needed to do this through the constraint solver, we extend FunctionRefInfo to remember whether a module selector was used.
183 lines
6.6 KiB
C++
183 lines
6.6 KiB
C++
//===--- FunctionRefInfo.h - Function reference info ------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2024 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 the FunctionRefInfo class, which describes how a function
|
|
// is referenced in an expression.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_AST_FUNCTION_REF_INFO_H
|
|
#define SWIFT_AST_FUNCTION_REF_INFO_H
|
|
|
|
#include "swift/Basic/Debug.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
|
|
#include <cstdint>
|
|
|
|
namespace swift {
|
|
|
|
class DeclNameLoc;
|
|
class DeclNameRef;
|
|
|
|
/// Describes how a function is referenced within an expression node.
|
|
///
|
|
/// This dictates things like:
|
|
/// - Whether argument labels are part of the resulting function type or not.
|
|
/// - Whether the result can produce an implicitly unwrapped optional.
|
|
/// - Whether the function type needs adjustment for concurrency.
|
|
///
|
|
/// How a function is referenced comes down to how it was spelled in
|
|
/// the source code, e.g., was it called in the source code and was it
|
|
/// spelled as a compound name.
|
|
class FunctionRefInfo final {
|
|
public:
|
|
/// Whether the function reference is part of a call, and if so how many
|
|
/// applications were used.
|
|
enum class ApplyLevel : uint8_t {
|
|
/// The function is not directly called.
|
|
Unapplied,
|
|
/// The function is directly applied once, e.g., "f(a: 1, b: 2)".
|
|
SingleApply,
|
|
/// The function is directly applied two or more times, e.g., "g(x)(y)".
|
|
DoubleApply,
|
|
};
|
|
|
|
private:
|
|
/// The application level of the function reference.
|
|
uint8_t ApplyLevelKind : 2;
|
|
|
|
/// Whether the function was referenced using a compound function name,
|
|
/// e.g., "f(a:b:)".
|
|
uint8_t IsCompoundName : 1;
|
|
|
|
/// Whether the function was referenced using a module selector,
|
|
/// e.g. "main::f".
|
|
uint8_t HasModuleSelector : 1;
|
|
|
|
FunctionRefInfo(ApplyLevel applyLevel, bool isCompoundName,
|
|
bool hasModuleSelector)
|
|
: ApplyLevelKind(static_cast<uint8_t>(applyLevel)),
|
|
IsCompoundName(isCompoundName), HasModuleSelector(hasModuleSelector) {}
|
|
|
|
public:
|
|
/// An unapplied function reference for a given DeclNameLoc.
|
|
static FunctionRefInfo unapplied(DeclNameLoc nameLoc);
|
|
|
|
/// An unapplied function reference for a given DeclNameRef.
|
|
static FunctionRefInfo unapplied(DeclNameRef nameRef);
|
|
|
|
/// An unapplied function reference using a base name, e.g `let x = fn`.
|
|
static FunctionRefInfo unappliedBaseName(bool hasModuleSelector = false) {
|
|
return FunctionRefInfo(ApplyLevel::Unapplied, /*isCompoundName*/ false,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// An unapplied function reference using a compound name,
|
|
/// e.g `let x = fn(x:)`.
|
|
static FunctionRefInfo unappliedCompoundName(bool hasModuleSelector = false) {
|
|
return FunctionRefInfo(ApplyLevel::Unapplied, /*isCompoundName*/ true,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// A single application using a base name, e.g `fn(x: 0)`.
|
|
static FunctionRefInfo singleBaseNameApply(bool hasModuleSelector = false) {
|
|
return FunctionRefInfo(ApplyLevel::SingleApply, /*isCompoundName*/ false,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// A single application using a compound name, e.g `fn(x:)(0)`.
|
|
static FunctionRefInfo singleCompoundNameApply(bool hasModuleSelector=false) {
|
|
return FunctionRefInfo(ApplyLevel::SingleApply, /*isCompoundName*/ true,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// A double application using a base name, e.g `S.fn(S())(x: 0)`.
|
|
static FunctionRefInfo doubleBaseNameApply(bool hasModuleSelector = false) {
|
|
return FunctionRefInfo(ApplyLevel::DoubleApply, /*isCompoundName*/ false,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// A double application using a compound name, e.g `S.fn(x:)(S())(0)`.
|
|
static FunctionRefInfo doubleCompoundNameApply(bool hasModuleSelector=false) {
|
|
return FunctionRefInfo(ApplyLevel::DoubleApply, /*isCompoundName*/ true,
|
|
hasModuleSelector);
|
|
}
|
|
|
|
/// Reconstructs a FunctionRefInfo from its \c getOpaqueValue().
|
|
static FunctionRefInfo fromOpaque(uint8_t bits) {
|
|
return FunctionRefInfo(static_cast<ApplyLevel>(bits >> 2), bits & 0x2,
|
|
bits & 0x1);
|
|
}
|
|
|
|
/// Retrieves an opaque value that can be stored in e.g a bitfield.
|
|
uint8_t getOpaqueValue() const {
|
|
return (static_cast<uint8_t>(ApplyLevelKind) << 2) |
|
|
(!!IsCompoundName << 1) | !!HasModuleSelector;
|
|
}
|
|
|
|
/// Whether the function reference is part of a call, and if so how many
|
|
/// applications were used.
|
|
ApplyLevel getApplyLevel() const {
|
|
return static_cast<ApplyLevel>(ApplyLevelKind);
|
|
}
|
|
|
|
/// Whether the function was referenced using a compound name,
|
|
/// e.g `fn(x:)(0)`.
|
|
bool isCompoundName() const { return IsCompoundName; }
|
|
|
|
/// Whether the function was referenced using a module selector,
|
|
/// e.g. `main::f`.
|
|
bool hasModuleSelector() const { return HasModuleSelector; }
|
|
|
|
/// Whether the function reference is not part of a call.
|
|
bool isUnapplied() const {
|
|
return getApplyLevel() == ApplyLevel::Unapplied;
|
|
}
|
|
|
|
/// Whether the function reference is both not part of a call, and is
|
|
/// not using a compound name.
|
|
bool isUnappliedBaseName() const {
|
|
return getApplyLevel() == ApplyLevel::Unapplied && !isCompoundName();
|
|
}
|
|
|
|
/// Whether the function reference has been applied a single time.
|
|
bool isSingleApply() const {
|
|
return getApplyLevel() == ApplyLevel::SingleApply;
|
|
}
|
|
|
|
/// Whether the function reference has been applied twice.
|
|
bool isDoubleApply() const {
|
|
return getApplyLevel() == ApplyLevel::DoubleApply;
|
|
}
|
|
|
|
/// Returns the FunctionRefInfo with an additional level of function
|
|
/// application added.
|
|
FunctionRefInfo addingApplicationLevel() const;
|
|
|
|
friend bool operator==(const FunctionRefInfo &lhs,
|
|
const FunctionRefInfo &rhs) {
|
|
return lhs.getApplyLevel() == rhs.getApplyLevel() &&
|
|
lhs.isCompoundName() == rhs.isCompoundName() &&
|
|
lhs.hasModuleSelector() == rhs.hasModuleSelector();
|
|
}
|
|
friend bool operator!=(const FunctionRefInfo &lhs,
|
|
const FunctionRefInfo &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
void dump(raw_ostream &os) const;
|
|
SWIFT_DEBUG_DUMP;
|
|
};
|
|
}
|
|
|
|
#endif // SWIFT_AST_FUNCTION_REF_INFO_H
|