1use crate::{
2 engine_threading::{
3 DebugWithEngines, DisplayWithEngines, EqWithEngines, HashWithEngines, OrdWithEngines,
4 OrdWithEnginesContext, PartialEqWithEngines, PartialEqWithEnginesContext,
5 },
6 parsed::QualifiedPathType,
7 Engines, GenericArgument, Ident, Namespace,
8};
9use serde::{Deserialize, Serialize};
10use std::{
11 cmp::Ordering,
12 fmt,
13 hash::{Hash, Hasher},
14 sync::Arc,
15};
16use sway_error::{
17 error::CompileError,
18 handler::{ErrorEmitted, Handler},
19};
20use sway_types::{span::Span, Spanned};
21
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub struct CallPathTree {
24 pub qualified_call_path: QualifiedCallPath,
25 pub children: Vec<CallPathTree>,
26}
27
28impl HashWithEngines for CallPathTree {
29 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
30 let CallPathTree {
31 qualified_call_path,
32 children,
33 } = self;
34 qualified_call_path.hash(state, engines);
35 children.hash(state, engines);
36 }
37}
38
39impl EqWithEngines for CallPathTree {}
40impl PartialEqWithEngines for CallPathTree {
41 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
42 let CallPathTree {
43 qualified_call_path,
44 children,
45 } = self;
46 qualified_call_path.eq(&other.qualified_call_path, ctx) && children.eq(&other.children, ctx)
47 }
48}
49
50impl<T: PartialEqWithEngines> EqWithEngines for Vec<T> {}
51impl<T: PartialEqWithEngines> PartialEqWithEngines for Vec<T> {
52 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
53 if self.len() != other.len() {
54 return false;
55 }
56 self.iter().zip(other.iter()).all(|(a, b)| a.eq(b, ctx))
57 }
58}
59
60impl OrdWithEngines for CallPathTree {
61 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
62 let CallPathTree {
63 qualified_call_path: l_call_path,
64 children: l_children,
65 } = self;
66 let CallPathTree {
67 qualified_call_path: r_call_path,
68 children: r_children,
69 } = other;
70 l_call_path
71 .cmp(r_call_path, ctx)
72 .then_with(|| l_children.cmp(r_children, ctx))
73 }
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize)]
77
78pub struct QualifiedCallPath {
79 pub call_path: CallPath,
80 pub qualified_path_root: Option<Box<QualifiedPathType>>,
81}
82
83impl std::convert::From<Ident> for QualifiedCallPath {
84 fn from(other: Ident) -> Self {
85 QualifiedCallPath {
86 call_path: CallPath {
87 prefixes: vec![],
88 suffix: other,
89 callpath_type: CallPathType::Ambiguous,
90 },
91 qualified_path_root: None,
92 }
93 }
94}
95
96impl std::convert::From<CallPath> for QualifiedCallPath {
97 fn from(other: CallPath) -> Self {
98 QualifiedCallPath {
99 call_path: other,
100 qualified_path_root: None,
101 }
102 }
103}
104
105impl QualifiedCallPath {
106 pub fn to_call_path(self, handler: &Handler) -> Result<CallPath, ErrorEmitted> {
107 if let Some(qualified_path_root) = self.qualified_path_root {
108 Err(handler.emit_err(CompileError::Internal(
109 "Unexpected qualified path.",
110 qualified_path_root.as_trait_span,
111 )))
112 } else {
113 Ok(self.call_path)
114 }
115 }
116}
117
118impl HashWithEngines for QualifiedCallPath {
119 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
120 let QualifiedCallPath {
121 call_path,
122 qualified_path_root,
123 } = self;
124 call_path.hash(state);
125 qualified_path_root.hash(state, engines);
126 }
127}
128
129impl EqWithEngines for QualifiedCallPath {}
130impl PartialEqWithEngines for QualifiedCallPath {
131 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
132 let QualifiedCallPath {
133 call_path,
134 qualified_path_root,
135 } = self;
136 PartialEqWithEngines::eq(call_path, &other.call_path, ctx)
137 && qualified_path_root.eq(&other.qualified_path_root, ctx)
138 }
139}
140
141impl OrdWithEngines for QualifiedCallPath {
142 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
143 let QualifiedCallPath {
144 call_path: l_call_path,
145 qualified_path_root: l_qualified_path_root,
146 } = self;
147 let QualifiedCallPath {
148 call_path: r_call_path,
149 qualified_path_root: r_qualified_path_root,
150 } = other;
151 l_call_path
152 .cmp(r_call_path)
153 .then_with(|| l_qualified_path_root.cmp(r_qualified_path_root, ctx))
154 }
155}
156
157impl DisplayWithEngines for QualifiedCallPath {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
159 if let Some(qualified_path_root) = &self.qualified_path_root {
160 write!(
161 f,
162 "{}::{}",
163 engines.help_out(qualified_path_root),
164 &self.call_path
165 )
166 } else {
167 write!(f, "{}", &self.call_path)
168 }
169 }
170}
171
172impl DebugWithEngines for QualifiedCallPath {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
174 write!(f, "{}", engines.help_out(self))
175 }
176}
177
178#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
179pub enum CallPathType {
180 RelativeToPackageRoot,
185 Ambiguous,
192 Full,
198}
199
200#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
203pub struct CallPath<T = Ident> {
204 pub prefixes: Vec<Ident>,
205 pub suffix: T,
206 pub callpath_type: CallPathType,
207}
208
209impl EqWithEngines for CallPath {}
210impl PartialEqWithEngines for CallPath {
211 fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool {
212 self.prefixes == other.prefixes
213 && self.suffix == other.suffix
214 && self.callpath_type == other.callpath_type
215 }
216}
217
218impl<T: EqWithEngines> EqWithEngines for CallPath<T> {}
219impl<T: PartialEqWithEngines> PartialEqWithEngines for CallPath<T> {
220 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
221 self.prefixes == other.prefixes
222 && self.suffix.eq(&other.suffix, ctx)
223 && self.callpath_type == other.callpath_type
224 }
225}
226
227impl<T: OrdWithEngines> OrdWithEngines for CallPath<T> {
228 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
229 self.prefixes
230 .cmp(&other.prefixes)
231 .then_with(|| self.suffix.cmp(&other.suffix, ctx))
232 .then_with(|| self.callpath_type.cmp(&other.callpath_type))
233 }
234}
235
236#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
237pub struct ResolvedCallPath<T, U = Ident> {
238 pub decl: T,
239 pub unresolved_call_path: CallPath<U>,
240}
241
242impl std::convert::From<Ident> for CallPath {
243 fn from(other: Ident) -> Self {
244 CallPath {
245 prefixes: vec![],
246 suffix: other,
247 callpath_type: CallPathType::Ambiguous,
248 }
249 }
250}
251
252impl<T> fmt::Display for CallPath<T>
253where
254 T: fmt::Display,
255{
256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
257 for prefix in self.prefixes.iter() {
258 write!(f, "{}::", prefix.as_str())?;
259 }
260 write!(f, "{}", &self.suffix)
261 }
262}
263
264impl<T: DisplayWithEngines> DisplayWithEngines for CallPath<T> {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
266 for prefix in self.prefixes.iter() {
267 write!(f, "{}::", prefix.as_str())?;
268 }
269 write!(f, "{}", engines.help_out(&self.suffix))
270 }
271}
272
273impl<T: DisplayWithEngines> DebugWithEngines for CallPath<T> {
274 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
275 for prefix in self.prefixes.iter() {
276 write!(f, "{}::", prefix.as_str())?;
277 }
278 write!(f, "{}", engines.help_out(&self.suffix))
279 }
280}
281
282impl<T: Spanned> Spanned for CallPath<T> {
283 fn span(&self) -> Span {
284 if self.prefixes.is_empty() {
285 self.suffix.span()
286 } else {
287 let suffix_span = self.suffix.span();
288 let mut prefixes_spans = self
289 .prefixes
290 .iter()
291 .map(|x| x.span())
292 .filter(|x| {
299 Arc::ptr_eq(&x.src().text, &suffix_span.src().text)
300 && x.source_id() == suffix_span.source_id()
301 })
302 .peekable();
303 if prefixes_spans.peek().is_some() {
304 Span::join(Span::join_all(prefixes_spans), &suffix_span)
305 } else {
306 suffix_span
307 }
308 }
309 }
310}
311
312pub enum CallPathDisplayType {
314 Regular,
316 StripPackagePrefix,
318}
319
320impl CallPath {
321 pub fn fullpath(path: &[&str]) -> Self {
322 assert!(!path.is_empty());
323
324 CallPath {
325 prefixes: path
326 .iter()
327 .take(path.len() - 1)
328 .map(|&x| Ident::new_no_span(x.into()))
329 .collect(),
330 suffix: path.last().map(|&x| Ident::new_no_span(x.into())).unwrap(),
331 callpath_type: CallPathType::Full,
332 }
333 }
334
335 pub fn rshift(&self) -> CallPath {
338 if self.prefixes.is_empty()
339 || (matches!(self.callpath_type, CallPathType::Full) && self.prefixes.len() == 1)
340 {
341 self.clone()
342 } else {
343 CallPath {
344 prefixes: self.prefixes[0..self.prefixes.len() - 1].to_vec(),
345 suffix: self.prefixes.last().unwrap().clone(),
346 callpath_type: self.callpath_type,
347 }
348 }
349 }
350
351 pub fn lshift(&self) -> CallPath {
353 if self.prefixes.is_empty() {
354 self.clone()
355 } else {
356 let new_callpath_type = match self.callpath_type {
357 CallPathType::RelativeToPackageRoot | CallPathType::Ambiguous => {
358 CallPathType::Ambiguous
359 }
360 CallPathType::Full => CallPathType::RelativeToPackageRoot,
361 };
362 CallPath {
363 prefixes: self.prefixes[1..self.prefixes.len()].to_vec(),
364 suffix: self.suffix.clone(),
365 callpath_type: new_callpath_type,
366 }
367 }
368 }
369
370 pub fn as_vec_string(&self) -> Vec<String> {
371 self.prefixes
372 .iter()
373 .map(|p| p.to_string())
374 .chain(std::iter::once(self.suffix.to_string()))
375 .collect::<Vec<_>>()
376 }
377
378 pub fn ident_to_fullpath(suffix: Ident, namespace: &Namespace) -> CallPath {
384 let mut res: Self = suffix.clone().into();
385 for mod_path in namespace.current_mod_path() {
386 res.prefixes.push(mod_path.clone())
387 }
388 res.callpath_type = CallPathType::Full;
389 res
390 }
391
392 pub fn to_import_path(&self, engines: &Engines, namespace: &Namespace) -> CallPath {
399 let converted = self.to_fullpath(engines, namespace);
400
401 if let Some(first) = converted.prefixes.first() {
402 if namespace.current_package_name() == first {
403 return converted.lshift();
404 }
405 }
406 converted
407 }
408
409 pub fn to_display_path(
410 &self,
411 display_type: CallPathDisplayType,
412 namespace: &Namespace,
413 ) -> CallPath {
414 let mut display_path = self.clone();
415
416 match display_type {
417 CallPathDisplayType::Regular => {}
418 CallPathDisplayType::StripPackagePrefix => {
419 if let Some(first) = self.prefixes.first() {
420 if namespace.current_package_name() == first {
421 display_path = display_path.lshift();
422 }
423 }
424 }
425 };
426
427 display_path
428 }
429
430 pub(crate) fn to_string_with_args(
438 &self,
439 engines: &Engines,
440 args: &[GenericArgument],
441 ) -> String {
442 let args = args
443 .iter()
444 .map(|type_arg| engines.help_out(type_arg).to_string())
445 .collect::<Vec<_>>()
446 .join(", ");
447
448 format!(
449 "{}{}",
450 &self,
453 if args.is_empty() {
454 String::new()
455 } else {
456 format!("<{args}>")
457 }
458 )
459 }
460}
461
462impl<T: Clone> CallPath<T> {
463 pub fn to_fullpath(&self, engines: &Engines, namespace: &Namespace) -> CallPath<T> {
479 self.to_fullpath_from_mod_path(engines, namespace, namespace.current_mod_path())
480 }
481
482 pub fn to_fullpath_from_mod_path(
499 &self,
500 engines: &Engines,
501 namespace: &Namespace,
502 mod_path: &Vec<Ident>,
503 ) -> CallPath<T> {
504 let mod_path_module = namespace.module_from_absolute_path(mod_path);
505
506 match self.callpath_type {
507 CallPathType::Full => self.clone(),
508 CallPathType::RelativeToPackageRoot => {
509 let mut prefixes = vec![mod_path[0].clone()];
510 for ident in self.prefixes.iter() {
511 prefixes.push(ident.clone());
512 }
513 Self {
514 prefixes,
515 suffix: self.suffix.clone(),
516 callpath_type: CallPathType::Full,
517 }
518 }
519 CallPathType::Ambiguous => {
520 if self.prefixes.is_empty() {
521 CallPath {
525 prefixes: mod_path.clone(),
526 suffix: self.suffix.clone(),
527 callpath_type: CallPathType::Full,
528 }
529 } else if mod_path_module.is_some()
530 && (mod_path_module.unwrap().has_submodule(&self.prefixes[0])
531 || namespace.module_has_binding(engines, mod_path, &self.prefixes[0]))
532 {
533 CallPath {
540 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
541 suffix: self.suffix.clone(),
542 callpath_type: CallPathType::Full,
543 }
544 } else if namespace.package_exists(&self.prefixes[0])
545 && namespace.module_is_external(&self.prefixes)
546 {
547 CallPath {
549 prefixes: self.prefixes.clone(),
550 suffix: self.suffix.clone(),
551 callpath_type: CallPathType::Full,
552 }
553 } else {
554 CallPath {
557 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
558 suffix: self.suffix.clone(),
559 callpath_type: CallPathType::Full,
560 }
561 }
562 }
563 }
564 }
565}
566
567impl CallPath {
568 pub fn to_canonical_path(&self, engines: &Engines, namespace: &Namespace) -> CallPath {
582 let full_path = self.to_fullpath(engines, namespace);
584
585 match namespace.module_from_absolute_path(&full_path.prefixes) {
586 Some(module) => {
587 match module.resolve_symbol(&Handler::default(), engines, &full_path.suffix) {
589 Ok((decl, decl_path)) => {
590 let name = decl.expect_typed().get_name(engines);
591 let suffix = if name.as_str() != full_path.suffix.as_str() {
592 name
593 } else {
594 full_path.suffix
595 };
596 CallPath {
598 prefixes: decl_path,
599 suffix,
600 callpath_type: full_path.callpath_type,
601 }
602 }
603 Err(_) => {
604 full_path
607 }
608 }
609 }
610 None => {
611 full_path
614 }
615 }
616 }
617}