1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
use crate::{
ast::{expr::ConstExpr, ty::TyKind, TraitRef},
common::{SpanId, SymbolId},
context::with_cx,
span::Span,
};
use super::Lifetime;
/// The syntactic representation of a generic argument, like this:
///
/// ```
/// let _bar: Vec<String> = vec![];
/// // ^^^^^^
/// ```
#[repr(C)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub struct LifetimeArg<'ast> {
lifetime: Lifetime<'ast>,
}
impl<'ast> LifetimeArg<'ast> {
pub fn lifetime(&self) -> &Lifetime<'ast> {
&self.lifetime
}
/// The [`Span`] of the type argument.
pub fn span(&self) -> &Span<'ast> {
self.lifetime
.span()
.expect("every lifetime inside syntactic `SynLifetimeArg` should have a span")
}
}
#[cfg(feature = "driver-api")]
impl<'ast> LifetimeArg<'ast> {
pub fn new(lifetime: Lifetime<'ast>) -> Self {
Self { lifetime }
}
}
/// The syntactic representation of a generic argument, like this:
///
/// ```
/// let _bar: Vec<String> = vec![];
/// // ^^^^^^
/// ```
#[repr(C)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub struct TyArg<'ast> {
ty: TyKind<'ast>,
}
impl<'ast> TyArg<'ast> {
pub fn ty(&self) -> TyKind<'_> {
self.ty
}
/// The [`Span`] of the type argument.
pub fn span(&self) -> &Span<'ast> {
self.ty.span()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> TyArg<'ast> {
pub fn new(ty: TyKind<'ast>) -> Self {
Self { ty }
}
}
/// A generic bound in form `<identifier=type>`. For example, `Item=i32` would be
/// the generic binding here:
///
/// ```ignore
/// let _baz: &dyn Iterator<Item=i32> = todo!();
/// // ^^^^^^^^
/// ```
///
/// The corresponding instance would provide the name (`Item`), the defined type
/// (`i32`) and potentially the [`Span`] if this bound originates from source code.
///
/// See [paths in expressions](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
/// for more information.
#[repr(C)]
#[derive(Debug)]
pub struct BindingArg<'ast> {
span: SpanId,
ident: SymbolId,
ty: TyKind<'ast>,
}
impl<'ast> BindingArg<'ast> {
/// The name of the identifier used in the binding. For example:
///
/// ```ignore
/// let _baz: &dyn Iterator<Item=i32> = todo!();
/// // ^^^^
/// ```
///
/// Would return `Item` as the identifier.
pub fn ident(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.ident))
}
/// The type that the identifier is set to. For example:
///
/// ```ignore
/// let _baz: &dyn Iterator<Item=i32> = todo!();
/// // ^^^
/// ```
///
/// Would return `i32` as the type.
pub fn ty(&self) -> TyKind<'ast> {
self.ty
}
/// The [`Span`] of the binding.
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
#[cfg(feature = "driver-api")]
impl<'ast> BindingArg<'ast> {
pub fn new(span: SpanId, ident: SymbolId, ty: TyKind<'ast>) -> Self {
Self { span, ident, ty }
}
}
/// A constant expression as an argument for a constant generic.
///
/// ```
/// struct Vec<const N: usize> {
/// data: [f32; N],
/// }
///
/// // An integer literal as a const generic argument
/// // v
/// fn vec3() -> Vec<3> {
/// // [...]
/// # todo!()
/// }
///
/// // A const generic parameter as an const generic argument
/// // v
/// impl<const N: usize> Vec<N> {
/// // ...
/// }
/// ```
#[derive(Debug)]
pub struct ConstArg<'ast> {
span: SpanId,
expr: ConstExpr<'ast>,
}
impl<'ast> ConstArg<'ast> {
/// The [`ConstExpr`] that is used as an argument.
pub fn expr(&self) -> &ConstExpr<'ast> {
&self.expr
}
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
#[cfg(feature = "driver-api")]
impl<'ast> ConstArg<'ast> {
pub fn new(span: SpanId, expr: ConstExpr<'ast>) -> Self {
Self { span, expr }
}
}
#[repr(C)]
#[derive(Debug)]
#[non_exhaustive]
pub enum TyParamBound<'ast> {
Lifetime(&'ast Lifetime<'ast>),
TraitBound(&'ast TraitBound<'ast>),
}
#[repr(C)]
#[derive(Debug)]
pub struct TraitBound<'ast> {
/// This is used for relaxed type bounds like `?Size`. This is probably not
/// the best representation. Rustc uses a `TraitBoundModifier` enum which
/// is interesting, but would only have two states right now.
is_relaxed: bool,
trait_ref: TraitRef<'ast>,
span: SpanId,
}
impl<'ast> TraitBound<'ast> {
pub fn trait_ref(&self) -> &TraitRef<'ast> {
&self.trait_ref
}
/// This returns true, when the bound is relaxed. This is currently only
/// possible for the `Sized` trait by writing `?Sized`.
// FIXME: I don't like the name of this function, but can't think of a
// better name/representation for it.
pub fn is_relaxed(&self) -> bool {
self.is_relaxed
}
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
#[cfg(feature = "driver-api")]
impl<'ast> TraitBound<'ast> {
pub fn new(is_relaxed: bool, trait_ref: TraitRef<'ast>, span: SpanId) -> Self {
Self {
is_relaxed,
trait_ref,
span,
}
}
}