1use std::iter;
4
5use crate::{
6 lang_item::LangItemTarget,
7 type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRefId},
8};
9use hir_expand::{
10 mod_path::{ModPath, PathKind},
11 name::Name,
12};
13use intern::Interned;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub enum Path {
17 BarePath(Interned<ModPath>),
22 Normal(Box<NormalPath>),
24 LangItem(LangItemTarget, Option<Name>),
27}
28
29#[cfg(target_arch = "x86_64")]
31const _: () = {
32 assert!(size_of::<Path>() == 16);
33 assert!(size_of::<Option<Path>>() == 16);
34};
35
36#[derive(Debug, Clone, PartialEq, Eq, Hash)]
37pub struct NormalPath {
38 pub generic_args: Box<[Option<GenericArgs>]>,
39 pub type_anchor: Option<TypeRefId>,
40 pub mod_path: Interned<ModPath>,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44pub enum GenericArgsParentheses {
45 No,
46 ReturnTypeNotation,
49 ParenSugar,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub struct GenericArgs {
60 pub args: Box<[GenericArg]>,
61 pub has_self_type: bool,
67 pub bindings: Box<[AssociatedTypeBinding]>,
69 pub parenthesized: GenericArgsParentheses,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Hash)]
75pub struct AssociatedTypeBinding {
76 pub name: Name,
78 pub args: Option<GenericArgs>,
81 pub type_ref: Option<TypeRefId>,
84 pub bounds: Box<[TypeBound]>,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub enum GenericArg {
93 Type(TypeRefId),
94 Lifetime(LifetimeRef),
95 Const(ConstRef),
96}
97
98impl Path {
99 pub fn from_known_path(path: ModPath, generic_args: Vec<Option<GenericArgs>>) -> Path {
101 Path::Normal(Box::new(NormalPath {
102 generic_args: generic_args.into_boxed_slice(),
103 type_anchor: None,
104 mod_path: Interned::new(path),
105 }))
106 }
107
108 pub fn from_known_path_with_no_generic(path: ModPath) -> Path {
110 Path::BarePath(Interned::new(path))
111 }
112
113 #[inline]
114 pub fn kind(&self) -> &PathKind {
115 match self {
116 Path::BarePath(mod_path) => &mod_path.kind,
117 Path::Normal(path) => &path.mod_path.kind,
118 Path::LangItem(..) => &PathKind::Abs,
119 }
120 }
121
122 #[inline]
123 pub fn type_anchor(&self) -> Option<TypeRefId> {
124 match self {
125 Path::Normal(path) => path.type_anchor,
126 Path::LangItem(..) | Path::BarePath(_) => None,
127 }
128 }
129
130 #[inline]
131 pub fn generic_args(&self) -> Option<&[Option<GenericArgs>]> {
132 match self {
133 Path::Normal(path) => Some(&path.generic_args),
134 Path::LangItem(..) | Path::BarePath(_) => None,
135 }
136 }
137
138 pub fn segments(&self) -> PathSegments<'_> {
139 match self {
140 Path::BarePath(mod_path) => {
141 PathSegments { segments: mod_path.segments(), generic_args: None }
142 }
143 Path::Normal(path) => PathSegments {
144 segments: path.mod_path.segments(),
145 generic_args: Some(&path.generic_args),
146 },
147 Path::LangItem(_, seg) => PathSegments { segments: seg.as_slice(), generic_args: None },
148 }
149 }
150
151 pub fn mod_path(&self) -> Option<&ModPath> {
152 match self {
153 Path::BarePath(mod_path) => Some(mod_path),
154 Path::Normal(path) => Some(&path.mod_path),
155 Path::LangItem(..) => None,
156 }
157 }
158
159 pub fn qualifier(&self) -> Option<Path> {
160 match self {
161 Path::BarePath(mod_path) => {
162 if mod_path.is_ident() {
163 return None;
164 }
165 Some(Path::BarePath(Interned::new(ModPath::from_segments(
166 mod_path.kind,
167 mod_path.segments()[..mod_path.segments().len() - 1].iter().cloned(),
168 ))))
169 }
170 Path::Normal(path) => {
171 let mod_path = &path.mod_path;
172 if mod_path.is_ident() {
173 return None;
174 }
175 let type_anchor = path.type_anchor;
176 let generic_args = &path.generic_args;
177 let qualifier_mod_path = Interned::new(ModPath::from_segments(
178 mod_path.kind,
179 mod_path.segments()[..mod_path.segments().len() - 1].iter().cloned(),
180 ));
181 let qualifier_generic_args = &generic_args[..generic_args.len() - 1];
182 if type_anchor.is_none() && qualifier_generic_args.iter().all(|it| it.is_none()) {
183 Some(Path::BarePath(qualifier_mod_path))
184 } else {
185 Some(Path::Normal(Box::new(NormalPath {
186 type_anchor,
187 mod_path: qualifier_mod_path,
188 generic_args: qualifier_generic_args.iter().cloned().collect(),
189 })))
190 }
191 }
192 Path::LangItem(..) => None,
193 }
194 }
195
196 pub fn is_self_type(&self) -> bool {
197 match self {
198 Path::BarePath(mod_path) => mod_path.is_Self(),
199 Path::Normal(path) => {
200 path.type_anchor.is_none()
201 && path.mod_path.is_Self()
202 && path.generic_args.iter().all(|args| args.is_none())
203 }
204 Path::LangItem(..) => false,
205 }
206 }
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
210pub struct PathSegment<'a> {
211 pub name: &'a Name,
212 pub args_and_bindings: Option<&'a GenericArgs>,
213}
214
215impl PathSegment<'_> {
216 pub const MISSING: PathSegment<'static> =
217 PathSegment { name: &Name::missing(), args_and_bindings: None };
218}
219
220#[derive(Debug, Clone, Copy)]
221pub struct PathSegments<'a> {
222 segments: &'a [Name],
223 generic_args: Option<&'a [Option<GenericArgs>]>,
224}
225
226impl<'a> PathSegments<'a> {
227 pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: None };
228 pub fn is_empty(&self) -> bool {
229 self.len() == 0
230 }
231 pub fn len(&self) -> usize {
232 self.segments.len()
233 }
234 pub fn first(&self) -> Option<PathSegment<'a>> {
235 self.get(0)
236 }
237 pub fn last(&self) -> Option<PathSegment<'a>> {
238 self.get(self.len().checked_sub(1)?)
239 }
240
241 pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
242 let res = PathSegment {
243 name: self.segments.get(idx)?,
244 args_and_bindings: self.generic_args.and_then(|it| it.get(idx)?.as_ref()),
245 };
246 Some(res)
247 }
248
249 pub fn skip(&self, len: usize) -> PathSegments<'a> {
250 PathSegments {
251 segments: self.segments.get(len..).unwrap_or(&[]),
252 generic_args: self.generic_args.and_then(|it| it.get(len..)),
253 }
254 }
255
256 pub fn take(&self, len: usize) -> PathSegments<'a> {
257 PathSegments {
258 segments: self.segments.get(..len).unwrap_or(self.segments),
259 generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
260 }
261 }
262
263 pub fn strip_last(&self) -> PathSegments<'a> {
264 PathSegments {
265 segments: self.segments.split_last().map_or(&[], |it| it.1),
266 generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
267 }
268 }
269
270 pub fn strip_last_two(&self) -> PathSegments<'a> {
271 PathSegments {
272 segments: self.segments.get(..self.segments.len().saturating_sub(2)).unwrap_or(&[]),
273 generic_args: self
274 .generic_args
275 .map(|it| it.get(..it.len().saturating_sub(2)).unwrap_or(&[])),
276 }
277 }
278
279 pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
280 self.segments
281 .iter()
282 .zip(self.generic_args.into_iter().flatten().chain(iter::repeat(&None)))
283 .map(|(name, args)| PathSegment { name, args_and_bindings: args.as_ref() })
284 }
285}
286
287impl GenericArgs {
288 pub(crate) fn empty() -> GenericArgs {
289 GenericArgs {
290 args: Box::default(),
291 has_self_type: false,
292 bindings: Box::default(),
293 parenthesized: GenericArgsParentheses::No,
294 }
295 }
296
297 pub(crate) fn return_type_notation() -> GenericArgs {
298 GenericArgs {
299 args: Box::default(),
300 has_self_type: false,
301 bindings: Box::default(),
302 parenthesized: GenericArgsParentheses::ReturnTypeNotation,
303 }
304 }
305}
306
307impl From<Name> for Path {
308 fn from(name: Name) -> Path {
309 Path::BarePath(Interned::new(ModPath::from_segments(PathKind::Plain, iter::once(name))))
310 }
311}