wit_parser/resolve/
error.rs1use 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
14#[non_exhaustive]
16#[derive(Debug, PartialEq, Eq)]
17pub enum ResolveErrorKind {
18 PackageNotFound {
20 span: Span,
21 requested: PackageName,
22 known: Vec<PackageName>,
23 },
24 InvalidTransitiveDependency { span: Span, name: String },
27 DuplicatePackage {
29 name: PackageName,
30 span1: Span,
31 span2: Span,
32 },
33 PackageCycle { package: PackageName, span: Span },
35 ItemShadowing {
37 span: Span,
38 item_type: String,
39 name: String,
40 },
41 StabilityMismatch {
43 span: Span,
44 from: Stability,
45 into: Stability,
46 },
47 Semantic { span: Span, message: String },
49}
50
51impl ResolveErrorKind {
52 pub fn span(&self) -> Span {
54 match self {
55 ResolveErrorKind::PackageNotFound { span, .. }
56 | ResolveErrorKind::InvalidTransitiveDependency { span, .. }
57 | ResolveErrorKind::PackageCycle { span, .. }
58 | ResolveErrorKind::ItemShadowing { span, .. }
59 | ResolveErrorKind::StabilityMismatch { span, .. }
60 | ResolveErrorKind::Semantic { span, .. } => *span,
61 ResolveErrorKind::DuplicatePackage { span1, .. } => *span1,
62 }
63 }
64}
65
66impl fmt::Display for ResolveErrorKind {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 match self {
69 ResolveErrorKind::PackageNotFound {
70 requested, known, ..
71 } => {
72 if known.is_empty() {
73 write!(f, "package '{requested}' not found")
74 } else {
75 write!(f, "package '{requested}' not found. known packages:")?;
76 for k in known {
77 write!(f, "\n {k}")?;
78 }
79 Ok(())
80 }
81 }
82 ResolveErrorKind::InvalidTransitiveDependency { name, .. } => write!(
83 f,
84 "interface `{name}` transitively depends on an interface in incompatible ways",
85 ),
86 ResolveErrorKind::DuplicatePackage { name, .. } => {
87 write!(f, "package `{name}` is defined in two different locations",)
88 }
89 ResolveErrorKind::PackageCycle { package, .. } => {
90 write!(f, "package `{package}` creates a dependency cycle")
91 }
92 ResolveErrorKind::ItemShadowing {
93 item_type, name, ..
94 } => {
95 write!(
96 f,
97 "{item_type} of `{name}` shadows previously {item_type}ed items"
98 )
99 }
100 ResolveErrorKind::StabilityMismatch { from, into, .. } => {
101 write!(f, "mismatch in stability from '{from:?}' to '{into:?}'")
102 }
103 ResolveErrorKind::Semantic { message, .. } => message.fmt(f),
104 }
105 }
106}
107
108#[derive(Debug, PartialEq, Eq)]
110pub struct ResolveError(Box<ResolveErrorKind>);
111
112impl ResolveError {
113 pub fn new_semantic(span: Span, message: impl Into<String>) -> Self {
115 ResolveErrorKind::Semantic {
116 span,
117 message: message.into(),
118 }
119 .into()
120 }
121
122 pub fn kind(&self) -> &ResolveErrorKind {
124 &self.0
125 }
126
127 pub fn kind_mut(&mut self) -> &mut ResolveErrorKind {
129 &mut self.0
130 }
131
132 pub fn highlight(&self, source_map: &SourceMap) -> String {
134 let e = self.kind();
135 let msg = e.to_string();
136 match e {
137 ResolveErrorKind::DuplicatePackage { name, span1, span2 } => {
138 let loc1 = source_map.render_location(*span1);
139 let loc2 = source_map.render_location(*span2);
140 format!(
141 "package `{name}` is defined in two different locations:\n * {loc1}\n * {loc2}"
142 )
143 }
144 _ => source_map.highlight_span(e.span(), &msg).unwrap_or(msg),
145 }
146 }
147}
148
149impl fmt::Display for ResolveError {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 fmt::Display::fmt(self.kind(), f)
152 }
153}
154
155impl core::error::Error for ResolveError {}
156
157impl From<ResolveErrorKind> for ResolveError {
158 fn from(kind: ResolveErrorKind) -> Self {
159 ResolveError(Box::new(kind))
160 }
161}