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 as_vec_ident(&self) -> Vec<Ident> {
379 self.as_vec_string()
380 .iter()
381 .map(|s| Ident::new_no_span(s.clone()))
382 .collect::<Vec<_>>()
383 }
384
385 pub fn ident_to_fullpath(suffix: Ident, namespace: &Namespace) -> CallPath {
391 let mut res: Self = suffix.clone().into();
392 for mod_path in namespace.current_mod_path() {
393 res.prefixes.push(mod_path.clone())
394 }
395 res.callpath_type = CallPathType::Full;
396 res
397 }
398
399 pub fn to_import_path(&self, engines: &Engines, namespace: &Namespace) -> CallPath {
406 let converted = self.to_fullpath(engines, namespace);
407
408 if let Some(first) = converted.prefixes.first() {
409 if namespace.current_package_name() == first {
410 return converted.lshift();
411 }
412 }
413 converted
414 }
415
416 pub fn to_display_path(
417 &self,
418 display_type: CallPathDisplayType,
419 namespace: &Namespace,
420 ) -> CallPath {
421 let mut display_path = self.clone();
422
423 match display_type {
424 CallPathDisplayType::Regular => {}
425 CallPathDisplayType::StripPackagePrefix => {
426 if let Some(first) = self.prefixes.first() {
427 if namespace.current_package_name() == first {
428 display_path = display_path.lshift();
429 }
430 }
431 }
432 };
433
434 display_path
435 }
436
437 pub(crate) fn to_string_with_args(
445 &self,
446 engines: &Engines,
447 args: &[GenericArgument],
448 ) -> String {
449 let args = args
450 .iter()
451 .map(|type_arg| engines.help_out(type_arg).to_string())
452 .collect::<Vec<_>>()
453 .join(", ");
454
455 format!(
456 "{}{}",
457 &self,
460 if args.is_empty() {
461 String::new()
462 } else {
463 format!("<{args}>")
464 }
465 )
466 }
467}
468
469impl<T: Clone> CallPath<T> {
470 pub fn to_fullpath(&self, engines: &Engines, namespace: &Namespace) -> CallPath<T> {
486 self.to_fullpath_from_mod_path(engines, namespace, namespace.current_mod_path())
487 }
488
489 pub fn to_fullpath_from_mod_path(
506 &self,
507 engines: &Engines,
508 namespace: &Namespace,
509 mod_path: &Vec<Ident>,
510 ) -> CallPath<T> {
511 let mod_path_module = namespace.module_from_absolute_path(mod_path);
512
513 match self.callpath_type {
514 CallPathType::Full => self.clone(),
515 CallPathType::RelativeToPackageRoot => {
516 let mut prefixes = vec![mod_path[0].clone()];
517 for ident in self.prefixes.iter() {
518 prefixes.push(ident.clone());
519 }
520 Self {
521 prefixes,
522 suffix: self.suffix.clone(),
523 callpath_type: CallPathType::Full,
524 }
525 }
526 CallPathType::Ambiguous => {
527 if self.prefixes.is_empty() {
528 CallPath {
532 prefixes: mod_path.clone(),
533 suffix: self.suffix.clone(),
534 callpath_type: CallPathType::Full,
535 }
536 } else if mod_path_module.is_some()
537 && (mod_path_module.unwrap().has_submodule(&self.prefixes[0])
538 || namespace.module_has_binding(engines, mod_path, &self.prefixes[0]))
539 {
540 CallPath {
547 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
548 suffix: self.suffix.clone(),
549 callpath_type: CallPathType::Full,
550 }
551 } else if namespace.package_exists(&self.prefixes[0])
552 && namespace.module_is_external(&self.prefixes)
553 {
554 CallPath {
556 prefixes: self.prefixes.clone(),
557 suffix: self.suffix.clone(),
558 callpath_type: CallPathType::Full,
559 }
560 } else {
561 CallPath {
564 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
565 suffix: self.suffix.clone(),
566 callpath_type: CallPathType::Full,
567 }
568 }
569 }
570 }
571 }
572}
573
574impl CallPath {
575 pub fn to_canonical_path(&self, engines: &Engines, namespace: &Namespace) -> CallPath {
589 let full_path = self.to_fullpath(engines, namespace);
591
592 match namespace.module_from_absolute_path(&full_path.prefixes) {
593 Some(module) => {
594 match module.resolve_symbol(&Handler::default(), engines, &full_path.suffix) {
596 Ok((decl, decl_path)) => {
597 let name = decl.expect_typed().get_name(engines);
598 let suffix = if name.as_str() != full_path.suffix.as_str() {
599 name
600 } else {
601 full_path.suffix
602 };
603 CallPath {
605 prefixes: decl_path,
606 suffix,
607 callpath_type: full_path.callpath_type,
608 }
609 }
610 Err(_) => {
611 full_path
614 }
615 }
616 }
617 None => {
618 full_path
621 }
622 }
623 }
624}