1use alloc::boxed::Box;
4use alloc::format;
5use alloc::string::{String, ToString};
6use alloc::vec::Vec;
7use core::fmt::{self};
8
9use crate::{PackageName, SourceMap, Span, Stability};
10
11pub type ResolveResult<T, E = ResolveError> = Result<T, E>;
13
14pub(crate) type WorldName = String;
16pub(crate) type InterfaceName = String;
17
18#[non_exhaustive]
20#[derive(Debug, PartialEq, Eq)]
21pub enum ResolveErrorKind {
22 PackageNotFound {
24 span: Span,
25 requested: PackageName,
26 known: Vec<PackageName>,
27 },
28
29 WorldNotFound {
31 span: Span,
32 requested: WorldName,
33 package: PackageName,
34 },
35
36 InterfaceNotFound {
38 span: Span,
39 requested: InterfaceName,
40 package: PackageName,
41 },
42 InvalidTransitiveDependency { span: Span, name: String },
45 DuplicatePackage {
47 name: PackageName,
48 span1: Span,
49 span2: Span,
50 },
51 PackageCycle { package: PackageName, span: Span },
53 ItemShadowing {
55 span: Span,
56 item_type: String,
57 name: String,
58 },
59 StabilityMismatch {
61 span: Span,
62 from: Stability,
63 into: Stability,
64 },
65 Semantic { span: Span, message: String },
67}
68
69impl ResolveErrorKind {
70 pub fn span(&self) -> Span {
72 match self {
73 ResolveErrorKind::PackageNotFound { span, .. }
74 | ResolveErrorKind::WorldNotFound { span, .. }
75 | ResolveErrorKind::InterfaceNotFound { span, .. }
76 | ResolveErrorKind::InvalidTransitiveDependency { span, .. }
77 | ResolveErrorKind::PackageCycle { span, .. }
78 | ResolveErrorKind::ItemShadowing { span, .. }
79 | ResolveErrorKind::StabilityMismatch { span, .. }
80 | ResolveErrorKind::Semantic { span, .. } => *span,
81 ResolveErrorKind::DuplicatePackage { span1, .. } => *span1,
82 }
83 }
84}
85
86impl fmt::Display for ResolveErrorKind {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match self {
89 ResolveErrorKind::PackageNotFound {
90 requested, known, ..
91 } => {
92 if known.is_empty() {
93 write!(f, "package '{requested}' not found")
94 } else {
95 write!(f, "package '{requested}' not found. known packages:")?;
96 for k in known {
97 write!(f, "\n {k}")?;
98 }
99 Ok(())
100 }
101 }
102 ResolveErrorKind::WorldNotFound {
103 requested, package, ..
104 } => write!(f, "world '{requested}' not found in package '{package}'"),
105 ResolveErrorKind::InterfaceNotFound {
106 requested, package, ..
107 } => write!(
108 f,
109 "interface '{requested}' not found in package '{package}'"
110 ),
111 ResolveErrorKind::InvalidTransitiveDependency { name, .. } => write!(
112 f,
113 "interface `{name}` transitively depends on an interface in incompatible ways",
114 ),
115 ResolveErrorKind::DuplicatePackage { name, .. } => {
116 write!(f, "package `{name}` is defined in two different locations",)
117 }
118 ResolveErrorKind::PackageCycle { package, .. } => {
119 write!(f, "package `{package}` creates a dependency cycle")
120 }
121 ResolveErrorKind::ItemShadowing {
122 item_type, name, ..
123 } => {
124 write!(
125 f,
126 "{item_type} of `{name}` shadows previously {item_type}ed items"
127 )
128 }
129 ResolveErrorKind::StabilityMismatch { from, into, .. } => {
130 write!(f, "mismatch in stability from '{from:?}' to '{into:?}'")
131 }
132 ResolveErrorKind::Semantic { message, .. } => message.fmt(f),
133 }
134 }
135}
136
137#[derive(Debug, PartialEq, Eq)]
139pub struct ResolveError(Box<ResolveErrorKind>);
140
141impl ResolveError {
142 pub fn new_semantic(span: Span, message: impl Into<String>) -> Self {
144 ResolveErrorKind::Semantic {
145 span,
146 message: message.into(),
147 }
148 .into()
149 }
150
151 pub fn kind(&self) -> &ResolveErrorKind {
153 &self.0
154 }
155
156 pub fn kind_mut(&mut self) -> &mut ResolveErrorKind {
158 &mut self.0
159 }
160
161 pub fn render(&self, source_map: &SourceMap) -> String {
165 let e = self.kind();
166 let msg = e.to_string();
167 match e {
168 ResolveErrorKind::DuplicatePackage { name, span1, span2 } => {
169 let loc1 = source_map.render_location(*span1);
170 let loc2 = source_map.render_location(*span2);
171 format!(
172 "package `{name}` is defined in two different locations:\n * {loc1}\n * {loc2}"
173 )
174 }
175 _ => source_map.highlight_span(e.span(), &msg).unwrap_or(msg),
176 }
177 }
178}
179
180impl fmt::Display for ResolveError {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 fmt::Display::fmt(self.kind(), f)
183 }
184}
185
186impl core::error::Error for ResolveError {}
187
188impl From<ResolveErrorKind> for ResolveError {
189 fn from(kind: ResolveErrorKind) -> Self {
190 ResolveError(Box::new(kind))
191 }
192}