1use crate::{
2 engine_threading::{
3 DebugWithEngines, DisplayWithEngines, EqWithEngines, HashWithEngines, OrdWithEngines,
4 OrdWithEnginesContext, PartialEqWithEngines, PartialEqWithEnginesContext,
5 },
6 parsed::QualifiedPathType,
7 Engines, Ident, Namespace, TypeArgument,
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(), suffix_span.src())
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.root_ref().current_package_root_module().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(&self, engines: &Engines, args: &[TypeArgument]) -> String {
438 let args = args
439 .iter()
440 .map(|type_arg| engines.help_out(type_arg).to_string())
441 .collect::<Vec<_>>()
442 .join(", ");
443
444 format!(
445 "{}{}",
446 &self,
449 if args.is_empty() {
450 String::new()
451 } else {
452 format!("<{args}>")
453 }
454 )
455 }
456}
457
458impl<T: Clone> CallPath<T> {
459 pub fn to_fullpath(&self, engines: &Engines, namespace: &Namespace) -> CallPath<T> {
475 self.to_fullpath_from_mod_path(engines, namespace, namespace.current_mod_path())
476 }
477
478 pub fn to_fullpath_from_mod_path(
495 &self,
496 engines: &Engines,
497 namespace: &Namespace,
498 mod_path: &Vec<Ident>,
499 ) -> CallPath<T> {
500 let mod_path_module = namespace.module_from_absolute_path(mod_path);
501
502 match self.callpath_type {
503 CallPathType::Full => self.clone(),
504 CallPathType::RelativeToPackageRoot => {
505 let mut prefixes = vec![mod_path[0].clone()];
506 for ident in self.prefixes.iter() {
507 prefixes.push(ident.clone());
508 }
509 Self {
510 prefixes,
511 suffix: self.suffix.clone(),
512 callpath_type: CallPathType::Full,
513 }
514 }
515 CallPathType::Ambiguous => {
516 if self.prefixes.is_empty() {
517 CallPath {
521 prefixes: mod_path.clone(),
522 suffix: self.suffix.clone(),
523 callpath_type: CallPathType::Full,
524 }
525 } else if mod_path_module.is_some()
526 && (mod_path_module.unwrap().has_submodule(&self.prefixes[0])
527 || namespace.module_has_binding(engines, mod_path, &self.prefixes[0]))
528 {
529 CallPath {
536 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
537 suffix: self.suffix.clone(),
538 callpath_type: CallPathType::Full,
539 }
540 } else if namespace.package_exists(&self.prefixes[0])
541 && namespace.module_is_external(&self.prefixes)
542 {
543 CallPath {
545 prefixes: self.prefixes.clone(),
546 suffix: self.suffix.clone(),
547 callpath_type: CallPathType::Full,
548 }
549 } else {
550 CallPath {
553 prefixes: mod_path.iter().chain(&self.prefixes).cloned().collect(),
554 suffix: self.suffix.clone(),
555 callpath_type: CallPathType::Full,
556 }
557 }
558 }
559 }
560 }
561}
562
563impl CallPath {
564 pub fn to_canonical_path(&self, engines: &Engines, namespace: &Namespace) -> CallPath {
578 let full_path = self.to_fullpath(engines, namespace);
580
581 match namespace.module_from_absolute_path(&full_path.prefixes) {
582 Some(module) => {
583 match module.resolve_symbol(&Handler::default(), engines, &full_path.suffix) {
585 Ok((decl, decl_path)) => {
586 let name = decl.expect_typed().get_name(engines);
587 let suffix = if name.as_str() != full_path.suffix.as_str() {
588 name
589 } else {
590 full_path.suffix
591 };
592 CallPath {
594 prefixes: decl_path,
595 suffix,
596 callpath_type: full_path.callpath_type,
597 }
598 }
599 Err(_) => {
600 full_path
603 }
604 }
605 }
606 None => {
607 full_path
610 }
611 }
612 }
613}