1 //! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
11 type_ref
::{ConstScalarOrPath, LifetimeRef}
,
13 use hir_expand
::name
::Name
;
17 use crate::type_ref
::{TypeBound, TypeRef}
;
19 pub use hir_expand
::mod_path
::{path, ModPath, PathKind}
;
21 #[derive(Debug, Clone, PartialEq, Eq)]
22 pub enum ImportAlias
{
23 /// Unnamed alias, as in `use Foo as _;`
29 impl Display
for ImportAlias
{
30 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
32 ImportAlias
::Underscore
=> f
.write_str("_"),
33 ImportAlias
::Alias(name
) => f
.write_str(&name
.to_smol_str()),
38 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
40 /// Type based path like `<T>::foo`.
41 /// Note that paths like `<Type as Trait>::foo` are desugared to `Trait::<Self=Type>::foo`.
42 type_anchor
: Option
<Interned
<TypeRef
>>,
43 mod_path
: Interned
<ModPath
>,
44 /// Invariant: the same len as `self.mod_path.segments` or `None` if all segments are `None`.
45 generic_args
: Option
<Box
<[Option
<Interned
<GenericArgs
>>]>>,
48 /// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
49 /// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
50 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
51 pub struct GenericArgs
{
52 pub args
: Box
<[GenericArg
]>,
53 /// This specifies whether the args contain a Self type as the first
54 /// element. This is the case for path segments like `<T as Trait>`, where
55 /// `T` is actually a type parameter for the path `Trait` specifying the
56 /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
58 pub has_self_type
: bool
,
59 /// Associated type bindings like in `Iterator<Item = T>`.
60 pub bindings
: Box
<[AssociatedTypeBinding
]>,
61 /// Whether these generic args were desugared from `Trait(Arg) -> Output`
62 /// parenthesis notation typically used for the `Fn` traits.
63 pub desugared_from_fn
: bool
,
66 /// An associated type binding like in `Iterator<Item = T>`.
67 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
68 pub struct AssociatedTypeBinding
{
69 /// The name of the associated type.
71 /// The generic arguments to the associated type. e.g. For `Trait<Assoc<'a, T> = &'a T>`, this
72 /// would be `['a, T]`.
73 pub args
: Option
<Interned
<GenericArgs
>>,
74 /// The type bound to this associated type (in `Item = T`, this would be the
75 /// `T`). This can be `None` if there are bounds instead.
76 pub type_ref
: Option
<TypeRef
>,
77 /// Bounds for the associated type, like in `Iterator<Item:
78 /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
80 pub bounds
: Box
<[Interned
<TypeBound
>]>,
83 /// A single generic argument.
84 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
87 Lifetime(LifetimeRef
),
88 Const(ConstScalarOrPath
),
92 /// Converts an `ast::Path` to `Path`. Works with use trees.
93 /// It correctly handles `$crate` based path from macro call.
94 pub fn from_src(path
: ast
::Path
, ctx
: &LowerCtx
<'_
>) -> Option
<Path
> {
95 lower
::lower_path(path
, ctx
)
98 /// Converts a known mod path to `Path`.
99 pub fn from_known_path(
101 generic_args
: impl Into
<Box
<[Option
<Interned
<GenericArgs
>>]>>,
103 let generic_args
= generic_args
.into();
104 assert_eq
!(path
.len(), generic_args
.len());
105 Path { type_anchor: None, mod_path: Interned::new(path), generic_args: Some(generic_args) }
108 pub fn kind(&self) -> &PathKind
{
112 pub fn type_anchor(&self) -> Option
<&TypeRef
> {
113 self.type_anchor
.as_deref()
116 pub fn segments(&self) -> PathSegments
<'_
> {
117 let s
= PathSegments
{
118 segments
: self.mod_path
.segments(),
119 generic_args
: self.generic_args
.as_deref(),
121 if let Some(generic_args
) = s
.generic_args
{
122 assert_eq
!(s
.segments
.len(), generic_args
.len());
127 pub fn mod_path(&self) -> &ModPath
{
131 pub fn qualifier(&self) -> Option
<Path
> {
132 if self.mod_path
.is_ident() {
136 type_anchor
: self.type_anchor
.clone(),
137 mod_path
: Interned
::new(ModPath
::from_segments(
139 self.mod_path
.segments()[..self.mod_path
.segments().len() - 1].iter().cloned(),
141 generic_args
: self.generic_args
.as_ref().map(|it
| it
[..it
.len() - 1].to_vec().into()),
146 pub fn is_self_type(&self) -> bool
{
147 self.type_anchor
.is_none()
148 && self.generic_args
.as_deref().is_none()
149 && self.mod_path
.is_Self()
153 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
154 pub struct PathSegment
<'a
> {
156 pub args_and_bindings
: Option
<&'a GenericArgs
>,
159 pub struct PathSegments
<'a
> {
160 segments
: &'a
[Name
],
161 generic_args
: Option
<&'a
[Option
<Interned
<GenericArgs
>>]>,
164 impl<'a
> PathSegments
<'a
> {
165 pub const EMPTY
: PathSegments
<'
static> = PathSegments { segments: &[], generic_args: None }
;
166 pub fn is_empty(&self) -> bool
{
169 pub fn len(&self) -> usize {
172 pub fn first(&self) -> Option
<PathSegment
<'a
>> {
175 pub fn last(&self) -> Option
<PathSegment
<'a
>> {
176 self.get(self.len().checked_sub(1)?
)
178 pub fn get(&self, idx
: usize) -> Option
<PathSegment
<'a
>> {
179 let res
= PathSegment
{
180 name
: self.segments
.get(idx
)?
,
181 args_and_bindings
: self.generic_args
.and_then(|it
| it
.get(idx
)?
.as_deref()),
185 pub fn skip(&self, len
: usize) -> PathSegments
<'a
> {
187 segments
: &self.segments
.get(len
..).unwrap_or(&[]),
188 generic_args
: self.generic_args
.and_then(|it
| it
.get(len
..)),
191 pub fn take(&self, len
: usize) -> PathSegments
<'a
> {
193 segments
: &self.segments
.get(..len
).unwrap_or(&self.segments
),
194 generic_args
: self.generic_args
.map(|it
| it
.get(..len
).unwrap_or(it
)),
197 pub fn iter(&self) -> impl Iterator
<Item
= PathSegment
<'a
>> {
200 .zip(self.generic_args
.into_iter().flatten().chain(iter
::repeat(&None
)))
201 .map(|(name
, args
)| PathSegment { name, args_and_bindings: args.as_deref() }
)
206 pub(crate) fn from_ast(
207 lower_ctx
: &LowerCtx
<'_
>,
208 node
: ast
::GenericArgList
,
209 ) -> Option
<GenericArgs
> {
210 lower
::lower_generic_args(lower_ctx
, node
)
213 pub(crate) fn empty() -> GenericArgs
{
215 args
: Box
::default(),
216 has_self_type
: false,
217 bindings
: Box
::default(),
218 desugared_from_fn
: false,
223 impl From
<Name
> for Path
{
224 fn from(name
: Name
) -> Path
{
227 mod_path
: Interned
::new(ModPath
::from_segments(PathKind
::Plain
, iter
::once(name
))),
233 impl From
<Name
> for Box
<Path
> {
234 fn from(name
: Name
) -> Box
<Path
> {
235 Box
::new(Path
::from(name
))