1use std::hash::Hash;
2use std::ops::{Deref, DerefMut};
3
4use cairo_lang_defs::ids::{
5 EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericParamId, ImplAliasId, ImplDefId,
6 ImplFunctionId, ImplImplDefId, LanguageElementId, LocalVarId, MemberId, ParamId, StructId,
7 TraitConstantId, TraitFunctionId, TraitId, TraitImplId, TraitTypeId, VariantId,
8};
9use cairo_lang_diagnostics::{DiagnosticAdded, Maybe};
10use cairo_lang_utils::deque::Deque;
11use cairo_lang_utils::extract_matches;
12use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
13use itertools::zip_eq;
14use salsa::Database;
15
16use crate::expr::inference::canonic::CanonicalTrait;
17use crate::expr::inference::{
18 ConstVar, ImplVar, ImplVarId, ImplVarTraitItemMappings, InferenceId, InferenceVar,
19 LocalConstVarId, LocalImplVarId, LocalNegativeImplVarId, LocalTypeVarId, NegativeImplVar,
20 NegativeImplVarId, TypeVar,
21};
22use crate::items::constant::{ConstValue, ConstValueId, ImplConstantId};
23use crate::items::functions::{
24 ConcreteFunctionWithBody, ConcreteFunctionWithBodyId, GenericFunctionId,
25 GenericFunctionWithBodyId, ImplFunctionBodyId, ImplGenericFunctionId,
26 ImplGenericFunctionWithBodyId,
27};
28use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
29use crate::items::imp::{
30 GeneratedImplId, GeneratedImplItems, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
31 ImplSemantic, NegativeImplId, NegativeImplLongId, UninferredGeneratedImplId,
32 UninferredGeneratedImplLongId, UninferredImpl,
33};
34use crate::items::trt::{
35 ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId, ConcreteTraitTypeId,
36 ConcreteTraitTypeLongId,
37};
38use crate::types::{
39 ClosureTypeLongId, ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId,
40 ImplTypeId,
41};
42use crate::{
43 ConcreteEnumId, ConcreteExternTypeId, ConcreteFunction, ConcreteImplId, ConcreteImplLongId,
44 ConcreteStructId, ConcreteTraitId, ConcreteTraitLongId, ConcreteTypeId, ConcreteVariant,
45 ExprId, ExprVar, ExprVarMemberPath, FunctionId, FunctionLongId, GenericArgumentId,
46 GenericParam, MatchArmSelector, Parameter, Signature, TypeId, TypeLongId, ValueSelectorArm,
47 VarId,
48};
49
50pub enum RewriteResult {
51 Modified,
52 NoChange,
53}
54
55#[derive(Clone, Debug, Default, PartialEq, Eq, salsa::Update, Hash)]
58pub struct GenericSubstitution<'db> {
59 param_to_arg: OrderedHashMap<GenericParamId<'db>, GenericArgumentId<'db>>,
60 self_impl: Option<ImplId<'db>>,
61}
62impl<'db> GenericSubstitution<'db> {
63 pub fn from_impl(self_impl: ImplId<'db>) -> Self {
64 GenericSubstitution { param_to_arg: OrderedHashMap::default(), self_impl: Some(self_impl) }
65 }
66 pub fn new(
67 generic_params: &[GenericParam<'db>],
68 generic_args: &[GenericArgumentId<'db>],
69 ) -> Self {
70 GenericSubstitution {
71 param_to_arg: zip_eq(generic_params, generic_args)
72 .map(|(param, arg)| (param.id(), *arg))
73 .collect(),
74 self_impl: None,
75 }
76 }
77 pub fn concat(mut self, other: GenericSubstitution<'db>) -> Self {
78 for (key, value) in other.param_to_arg {
79 self.param_to_arg.insert(key, value);
80 }
81 if let Some(self_impl) = other.self_impl {
82 self.self_impl = Some(self_impl);
83 }
84 self
85 }
86 pub fn is_empty(&self) -> bool {
88 self.param_to_arg.is_empty() && self.self_impl.is_none()
89 }
90 pub fn substitute<'a, 'r, Obj>(&'r self, db: &'a dyn Database, obj: Obj) -> Maybe<Obj>
91 where
92 'a: 'r,
93 'db: 'a,
94 SubstitutionRewriter<'a, 'r>: SemanticRewriter<Obj, DiagnosticAdded>,
95 {
96 SubstitutionRewriter { db, substitution: self }.rewrite(obj)
97 }
98}
99impl<'db> Deref for GenericSubstitution<'db> {
100 type Target = OrderedHashMap<GenericParamId<'db>, GenericArgumentId<'db>>;
101
102 fn deref(&self) -> &Self::Target {
103 &self.param_to_arg
104 }
105}
106impl<'db> DerefMut for GenericSubstitution<'db> {
107 fn deref_mut(&mut self) -> &mut Self::Target {
108 &mut self.param_to_arg
109 }
110}
111
112#[macro_export]
113macro_rules! semantic_object_for_id {
114 ($name:ident, $long_ty:path) => {
115 impl<
116 'a,
117 Error,
118 TRewriter: $crate::substitution::HasDb<&'a dyn Database>
119 + $crate::substitution::SemanticRewriter<$long_ty, Error>,
120 > $crate::substitution::SemanticObject<TRewriter, Error> for $name<'a>
121 {
122 fn default_rewrite(
123 &mut self,
124 rewriter: &mut TRewriter,
125 ) -> Result<$crate::substitution::RewriteResult, Error> where {
126 let db = $crate::substitution::HasDb::get_db(rewriter);
127 let mut val = self.long(db).clone();
128 Ok(
129 match $crate::substitution::SemanticRewriter::internal_rewrite(
130 rewriter, &mut val,
131 )? {
132 $crate::substitution::RewriteResult::Modified => {
133 *self = $name::new(db, val);
134 $crate::substitution::RewriteResult::Modified
135 }
136 $crate::substitution::RewriteResult::NoChange => {
137 $crate::substitution::RewriteResult::NoChange
138 }
139 },
140 )
141 }
142 }
143 };
144}
145
146#[macro_export]
147macro_rules! add_rewrite {
148 (<$($generics:lifetime),*>, $self_ty:ty, $err_ty:ty, $ty:path) => {
149 impl <$($generics),*> SemanticRewriter<$ty, $err_ty> for $self_ty {
150 fn internal_rewrite(
151 &mut self,
152 value: &mut $ty
153 ) -> Result<$crate::substitution::RewriteResult, $err_ty> {
154 $crate::substitution::SemanticObject::default_rewrite(value, self)
155 }
156 }
157 };
158}
159
160#[macro_export]
161macro_rules! add_rewrite_identity {
162 (<$($generics:lifetime),*>, $self_ty:ty, $err_ty:ty, $ty:path) => {
163 impl <$($generics),*> SemanticRewriter<$ty, $err_ty> for $self_ty {
164 fn internal_rewrite(
165 &mut self,
166 _value: &mut $ty
167 ) -> Result<$crate::substitution::RewriteResult, $err_ty> {
168 Ok(RewriteResult::NoChange)
169 }
170 }
171 };
172}
173
174pub trait SemanticObject<TRewriter, Error>: Sized {
175 fn default_rewrite(&mut self, rewriter: &mut TRewriter) -> Result<RewriteResult, Error>;
176}
177impl<T: Clone, E, TRewriter: SemanticRewriter<T, E>> SemanticRewriter<Vec<T>, E> for TRewriter {
178 fn internal_rewrite(&mut self, value: &mut Vec<T>) -> Result<RewriteResult, E> {
179 let mut result = RewriteResult::NoChange;
180 for el in value.iter_mut() {
181 match self.internal_rewrite(el)? {
182 RewriteResult::Modified => {
183 result = RewriteResult::Modified;
184 }
185 RewriteResult::NoChange => {}
186 }
187 }
188
189 Ok(result)
190 }
191}
192impl<T, E, TRewriter: SemanticRewriter<T, E>> SemanticRewriter<Deque<T>, E> for TRewriter {
193 fn internal_rewrite(&mut self, value: &mut Deque<T>) -> Result<RewriteResult, E> {
194 let mut result = RewriteResult::NoChange;
195 for el in value.iter_mut() {
196 match self.internal_rewrite(el)? {
197 RewriteResult::Modified => {
198 result = RewriteResult::Modified;
199 }
200 RewriteResult::NoChange => {}
201 }
202 }
203
204 Ok(result)
205 }
206}
207impl<T, E, TRewriter: SemanticRewriter<T, E>> SemanticRewriter<Box<T>, E> for TRewriter {
208 fn internal_rewrite(&mut self, value: &mut Box<T>) -> Result<RewriteResult, E> {
209 self.internal_rewrite(value.as_mut())
210 }
211}
212
213impl<'a, K: Hash + Eq + LanguageElementId<'a>, V: Clone, E, TRewriter: SemanticRewriter<V, E>>
214 SemanticRewriter<OrderedHashMap<K, V>, E> for TRewriter
215{
216 fn internal_rewrite(&mut self, value: &mut OrderedHashMap<K, V>) -> Result<RewriteResult, E> {
217 let mut result = RewriteResult::NoChange;
218 for (_, v) in value.iter_mut() {
219 match self.internal_rewrite(v)? {
220 RewriteResult::Modified => {
221 result = RewriteResult::Modified;
222 }
223 RewriteResult::NoChange => {}
224 }
225 }
226 Ok(result)
227 }
228}
229impl<T0, T1, E, TRewriter: SemanticRewriter<T0, E> + SemanticRewriter<T1, E>>
230 SemanticRewriter<(T0, T1), E> for TRewriter
231{
232 fn internal_rewrite(&mut self, value: &mut (T0, T1)) -> Result<RewriteResult, E> {
233 match (self.internal_rewrite(&mut value.0)?, self.internal_rewrite(&mut value.1)?) {
234 (RewriteResult::NoChange, RewriteResult::NoChange) => Ok(RewriteResult::NoChange),
235 _ => Ok(RewriteResult::Modified),
236 }
237 }
238}
239impl<T, E, TRewriter: SemanticRewriter<T, E>> SemanticRewriter<Option<T>, E> for TRewriter {
240 fn internal_rewrite(&mut self, value: &mut Option<T>) -> Result<RewriteResult, E> {
241 Ok(match value {
242 Some(val) => self.internal_rewrite(val)?,
243 None => RewriteResult::NoChange,
244 })
245 }
246}
247impl<T, E, TRewriter: SemanticRewriter<T, E>, E2> SemanticRewriter<Result<T, E2>, E> for TRewriter {
248 fn internal_rewrite(&mut self, value: &mut Result<T, E2>) -> Result<RewriteResult, E> {
249 Ok(match value {
250 Ok(val) => self.internal_rewrite(val)?,
251 Err(_) => RewriteResult::NoChange,
252 })
253 }
254}
255pub trait HasDb<T> {
256 fn get_db(&self) -> T;
257}
258pub trait SemanticRewriter<T, Error> {
259 fn rewrite(&mut self, mut value: T) -> Result<T, Error> {
260 self.internal_rewrite(&mut value)?;
261 Ok(value)
262 }
263
264 fn internal_rewrite(&mut self, value: &mut T) -> Result<RewriteResult, Error>;
265}
266
267#[macro_export]
268macro_rules! prune_single {
269 ($macro:ident, $item:ident, ) => {$macro!($item);};
270 ($macro:ident, $item:ident, $item0:ident $($item_rest:ident)*) => {
271 macro_rules! __inner_helper {
272 ($item $item) => { };
274 ($item $item0) => { $crate::prune_single!($macro, $item, $($item_rest)*); };
276 }
277 __inner_helper!($item $item0);
278 }
279}
280
281#[macro_export]
282macro_rules! add_basic_rewrites {
283 (<$($generics:lifetime),*>, $self_ty:ty, $err_ty:ty, @exclude $($exclude:ident)*) => {
284 macro_rules! __identity_helper {
286 ($item:ident) => {
287 $crate::add_rewrite_identity!(<$($generics),*>, $self_ty, $err_ty, $item<'a>);
288 }
289 }
290 macro_rules! __identity_helper_no_lifetime {
291 ($item:ident) => {
292 $crate::add_rewrite_identity!(<$($generics),*>, $self_ty, $err_ty, $item);
293 }
294 }
295 macro_rules! __regular_helper {
296 ($item:ident) => { $crate::add_rewrite!(<$($generics),*>, $self_ty, $err_ty, $item<'a>); }
297 }
298 macro_rules! __regular_helper_no_lifetime {
299 ($item:ident) => { $crate::add_rewrite!(<$($generics),*>, $self_ty, $err_ty, $item); }
300 }
301
302 $crate::prune_single!(__identity_helper, InferenceId, $($exclude)*);
303 $crate::prune_single!(__identity_helper, ParamId, $($exclude)*);
304 $crate::prune_single!(__identity_helper, FreeFunctionId, $($exclude)*);
305 $crate::prune_single!(__identity_helper, ExternFunctionId, $($exclude)*);
306 $crate::prune_single!(__identity_helper, ExternTypeId, $($exclude)*);
307 $crate::prune_single!(__identity_helper, ImplDefId, $($exclude)*);
308 $crate::prune_single!(__identity_helper, ImplImplDefId, $($exclude)*);
309 $crate::prune_single!(__identity_helper, ImplAliasId, $($exclude)*);
310 $crate::prune_single!(__identity_helper, TraitId, $($exclude)*);
311 $crate::prune_single!(__identity_helper, TraitFunctionId, $($exclude)*);
312 $crate::prune_single!(__identity_helper, VariantId, $($exclude)*);
313 $crate::prune_single!(__identity_helper, ImplFunctionId, $($exclude)*);
314 $crate::prune_single!(__identity_helper, EnumId, $($exclude)*);
315 $crate::prune_single!(__identity_helper, StructId, $($exclude)*);
316 $crate::prune_single!(__identity_helper, GenericParamId, $($exclude)*);
317 $crate::prune_single!(__identity_helper, TraitTypeId, $($exclude)*);
318 $crate::prune_single!(__identity_helper, TraitImplId, $($exclude)*);
319 $crate::prune_single!(__identity_helper, TraitConstantId, $($exclude)*);
320 $crate::prune_single!(__identity_helper, TypeVar, $($exclude)*);
321 $crate::prune_single!(__identity_helper, ConstVar, $($exclude)*);
322 $crate::prune_single!(__identity_helper, VarId, $($exclude)*);
323 $crate::prune_single!(__identity_helper, MemberId, $($exclude)*);
324 $crate::prune_single!(__identity_helper, LocalVarId, $($exclude)*);
325 $crate::prune_single!(__identity_helper_no_lifetime, LocalImplVarId, $($exclude)*);
326 $crate::prune_single!(__identity_helper_no_lifetime, LocalTypeVarId, $($exclude)*);
327 $crate::prune_single!(__identity_helper_no_lifetime, LocalConstVarId, $($exclude)*);
328 $crate::prune_single!(__identity_helper_no_lifetime, LocalNegativeImplVarId, $($exclude)*);
329 $crate::prune_single!(__identity_helper_no_lifetime, InferenceVar, $($exclude)*);
330 $crate::prune_single!(__identity_helper, ImplFunctionBodyId, $($exclude)*);
331 $crate::prune_single!(__identity_helper_no_lifetime, ExprId, $($exclude)*);
332
333 $crate::prune_single!(__regular_helper, Signature, $($exclude)*);
334 $crate::prune_single!(__regular_helper, GenericFunctionId, $($exclude)*);
335 $crate::prune_single!(__regular_helper, GenericFunctionWithBodyId, $($exclude)*);
336 $crate::prune_single!(__regular_helper, ConcreteFunction, $($exclude)*);
337 $crate::prune_single!(__regular_helper, ConcreteFunctionWithBody, $($exclude)*);
338 $crate::prune_single!(__regular_helper, ConcreteFunctionWithBodyId, $($exclude)*);
339 $crate::prune_single!(__regular_helper, ImplGenericFunctionId, $($exclude)*);
340 $crate::prune_single!(__regular_helper, ImplGenericFunctionWithBodyId, $($exclude)*);
341 $crate::prune_single!(__regular_helper, ImplVar, $($exclude)*);
342 $crate::prune_single!(__regular_helper, ImplVarId, $($exclude)*);
343 $crate::prune_single!(__regular_helper, NegativeImplVar, $($exclude)*);
344 $crate::prune_single!(__regular_helper, NegativeImplVarId, $($exclude)*);
345 $crate::prune_single!(__regular_helper, Parameter, $($exclude)*);
346 $crate::prune_single!(__regular_helper, GenericParam, $($exclude)*);
347 $crate::prune_single!(__regular_helper, GenericParamType, $($exclude)*);
348 $crate::prune_single!(__regular_helper, GenericParamConst, $($exclude)*);
349 $crate::prune_single!(__regular_helper, GenericParamImpl, $($exclude)*);
350 $crate::prune_single!(__regular_helper, GenericArgumentId, $($exclude)*);
351 $crate::prune_single!(__regular_helper, FunctionId, $($exclude)*);
352 $crate::prune_single!(__regular_helper, FunctionLongId, $($exclude)*);
353 $crate::prune_single!(__regular_helper, TypeId, $($exclude)*);
354 $crate::prune_single!(__regular_helper, TypeLongId, $($exclude)*);
355 $crate::prune_single!(__regular_helper, ConstValueId, $($exclude)*);
356 $crate::prune_single!(__regular_helper, ConstValue, $($exclude)*);
357 $crate::prune_single!(__regular_helper, ConcreteVariant, $($exclude)*);
358 $crate::prune_single!(__regular_helper_no_lifetime, ValueSelectorArm, $($exclude)*);
359 $crate::prune_single!(__regular_helper, MatchArmSelector, $($exclude)*);
360 $crate::prune_single!(__regular_helper, ClosureTypeLongId, $($exclude)*);
361 $crate::prune_single!(__regular_helper, ConcreteTypeId, $($exclude)*);
362 $crate::prune_single!(__regular_helper, ConcreteStructId, $($exclude)*);
363 $crate::prune_single!(__regular_helper, ConcreteStructLongId, $($exclude)*);
364 $crate::prune_single!(__regular_helper, ConcreteEnumId, $($exclude)*);
365 $crate::prune_single!(__regular_helper, ConcreteEnumLongId, $($exclude)*);
366 $crate::prune_single!(__regular_helper, ConcreteExternTypeId, $($exclude)*);
367 $crate::prune_single!(__regular_helper, ConcreteExternTypeLongId, $($exclude)*);
368 $crate::prune_single!(__regular_helper, ConcreteTraitId, $($exclude)*);
369 $crate::prune_single!(__regular_helper, ConcreteTraitLongId, $($exclude)*);
370 $crate::prune_single!(__regular_helper, ConcreteTraitTypeId, $($exclude)*);
371 $crate::prune_single!(__regular_helper, ConcreteTraitTypeLongId, $($exclude)*);
372 $crate::prune_single!(__regular_helper, ConcreteImplId, $($exclude)*);
373 $crate::prune_single!(__regular_helper, ConcreteImplLongId, $($exclude)*);
374 $crate::prune_single!(__regular_helper, ConcreteTraitGenericFunctionLongId, $($exclude)*);
375 $crate::prune_single!(__regular_helper, ConcreteTraitGenericFunctionId, $($exclude)*);
376 $crate::prune_single!(__regular_helper, GeneratedImplId, $($exclude)*);
377 $crate::prune_single!(__regular_helper, GeneratedImplLongId, $($exclude)*);
378 $crate::prune_single!(__regular_helper, GeneratedImplItems, $($exclude)*);
379 $crate::prune_single!(__regular_helper, ImplLongId, $($exclude)*);
380 $crate::prune_single!(__regular_helper, ImplId, $($exclude)*);
381 $crate::prune_single!(__regular_helper, NegativeImplLongId, $($exclude)*);
382 $crate::prune_single!(__regular_helper, NegativeImplId, $($exclude)*);
383 $crate::prune_single!(__regular_helper, ImplTypeId, $($exclude)*);
384 $crate::prune_single!(__regular_helper, ImplConstantId, $($exclude)*);
385 $crate::prune_single!(__regular_helper, ImplImplId, $($exclude)*);
386 $crate::prune_single!(__regular_helper, UninferredGeneratedImplId, $($exclude)*);
387 $crate::prune_single!(__regular_helper, UninferredGeneratedImplLongId, $($exclude)*);
388 $crate::prune_single!(__regular_helper, UninferredImpl, $($exclude)*);
389 $crate::prune_single!(__regular_helper, ExprVarMemberPath, $($exclude)*);
390 $crate::prune_single!(__regular_helper, ExprVar, $($exclude)*);
391 $crate::prune_single!(__regular_helper, ImplVarTraitItemMappings, $($exclude)*);
392 $crate::prune_single!(__regular_helper, CanonicalTrait, $($exclude)*);
393 };
394}
395
396#[macro_export]
397macro_rules! add_expr_rewrites {
398 (<$($generics:lifetime),*>, $self_ty:ty, $err_ty:ty, @exclude $($exclude:ident)*) => {
399 macro_rules! __identity_helper {
400 ($item:ident) => {
401 $crate::add_rewrite_identity!(<$($generics),*>, $self_ty, $err_ty, $item<'a>);
402 }
403 }
404 macro_rules! __identity_helper_no_lifetime {
405 ($item:ident) => {
406 $crate::add_rewrite_identity!(<$($generics),*>, $self_ty, $err_ty, $item);
407 }
408 }
409 macro_rules! __regular_helper {
410 ($item:ident) => { $crate::add_rewrite!(<$($generics),*>, $self_ty, $err_ty, $item<'a>); }
411 }
412 macro_rules! __regular_helper_no_lifetime {
413 ($item:ident) => { $crate::add_rewrite!(<$($generics),*>, $self_ty, $err_ty, $item); }
414 }
415
416 $crate::prune_single!(__identity_helper_no_lifetime, PatternId, $($exclude)*);
417 $crate::prune_single!(__identity_helper_no_lifetime, StatementId, $($exclude)*);
418 $crate::prune_single!(__identity_helper, ConstantId, $($exclude)*);
419 $crate::prune_single!(__regular_helper, Expr, $($exclude)*);
420 $crate::prune_single!(__regular_helper, ExprTuple, $($exclude)*);
421 $crate::prune_single!(__regular_helper, ExprSnapshot, $($exclude)*);
422 $crate::prune_single!(__regular_helper, ExprDesnap, $($exclude)*);
423 $crate::prune_single!(__regular_helper, ExprAssignment, $($exclude)*);
424 $crate::prune_single!(__regular_helper, ExprLogicalOperator, $($exclude)*);
425 $crate::prune_single!(__regular_helper, ExprBlock, $($exclude)*);
426 $crate::prune_single!(__regular_helper, ExprFunctionCall, $($exclude)*);
427 $crate::prune_single!(__regular_helper, ExprMatch, $($exclude)*);
428 $crate::prune_single!(__regular_helper, ExprIf, $($exclude)*);
429 $crate::prune_single!(__regular_helper_no_lifetime, Condition, $($exclude)*);
430 $crate::prune_single!(__regular_helper, ExprLoop, $($exclude)*);
431 $crate::prune_single!(__regular_helper, ExprWhile, $($exclude)*);
432 $crate::prune_single!(__regular_helper, ExprFor, $($exclude)*);
433 $crate::prune_single!(__regular_helper, ExprLiteral, $($exclude)*);
434 $crate::prune_single!(__regular_helper, ExprStringLiteral, $($exclude)*);
435 $crate::prune_single!(__regular_helper, ExprMemberAccess, $($exclude)*);
436 $crate::prune_single!(__regular_helper, ExprStructCtor, $($exclude)*);
437 $crate::prune_single!(__regular_helper, ExprEnumVariantCtor, $($exclude)*);
438 $crate::prune_single!(__regular_helper, ExprPropagateError, $($exclude)*);
439 $crate::prune_single!(__regular_helper, ExprConstant, $($exclude)*);
440 $crate::prune_single!(__regular_helper, ExprFixedSizeArray, $($exclude)*);
441 $crate::prune_single!(__regular_helper, ExprClosure, $($exclude)*);
442 $crate::prune_single!(__regular_helper, ExprMissing, $($exclude)*);
443 $crate::prune_single!(__regular_helper, ExprFunctionCallArg, $($exclude)*);
444 $crate::prune_single!(__regular_helper, FixedSizeArrayItems, $($exclude)*);
445 $crate::prune_single!(__regular_helper_no_lifetime, MatchArm, $($exclude)*);
446 $crate::prune_single!(__regular_helper, Statement, $($exclude)*);
447 $crate::prune_single!(__regular_helper, StatementExpr, $($exclude)*);
448 $crate::prune_single!(__regular_helper, StatementLet, $($exclude)*);
449 $crate::prune_single!(__regular_helper, StatementReturn, $($exclude)*);
450 $crate::prune_single!(__regular_helper, StatementContinue, $($exclude)*);
451 $crate::prune_single!(__regular_helper, StatementBreak, $($exclude)*);
452 $crate::prune_single!(__regular_helper, StatementItem, $($exclude)*);
453 $crate::prune_single!(__regular_helper, Pattern, $($exclude)*);
454 $crate::prune_single!(__regular_helper, PatternLiteral, $($exclude)*);
455 $crate::prune_single!(__regular_helper, PatternStringLiteral, $($exclude)*);
456 $crate::prune_single!(__regular_helper, PatternVariable, $($exclude)*);
457 $crate::prune_single!(__regular_helper, PatternStruct, $($exclude)*);
458 $crate::prune_single!(__regular_helper, PatternTuple, $($exclude)*);
459 $crate::prune_single!(__regular_helper, PatternFixedSizeArray, $($exclude)*);
460 $crate::prune_single!(__regular_helper, PatternEnumVariant, $($exclude)*);
461 $crate::prune_single!(__regular_helper, PatternOtherwise, $($exclude)*);
462 $crate::prune_single!(__regular_helper, PatternMissing, $($exclude)*);
463 $crate::prune_single!(__regular_helper, LocalVariable, $($exclude)*);
464 $crate::prune_single!(__regular_helper, Member, $($exclude)*);
465 };
466}
467
468pub struct SubstitutionRewriter<'a, 'r> {
469 db: &'a dyn Database,
470 substitution: &'r GenericSubstitution<'a>,
471}
472impl<'a> HasDb<&'a dyn Database> for SubstitutionRewriter<'a, '_> {
473 fn get_db(&self) -> &'a dyn Database {
474 self.db
475 }
476}
477
478add_basic_rewrites!(
479 <'a, 'r>,
480 SubstitutionRewriter<'a, 'r>,
481 DiagnosticAdded,
482 @exclude TypeId TypeLongId ImplId ImplLongId ConstValue GenericFunctionWithBodyId NegativeImplId NegativeImplLongId
483);
484
485impl<'db> SemanticRewriter<TypeId<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
486 fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Maybe<RewriteResult> {
487 if value.is_fully_concrete(self.db) {
488 return Ok(RewriteResult::NoChange);
489 }
490 value.default_rewrite(self)
491 }
492}
493
494impl<'db> SemanticRewriter<ImplId<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
495 fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Maybe<RewriteResult> {
496 if value.is_fully_concrete(self.db) {
497 return Ok(RewriteResult::NoChange);
498 }
499 value.default_rewrite(self)
500 }
501}
502
503impl<'db> SemanticRewriter<NegativeImplId<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
504 fn internal_rewrite(&mut self, value: &mut NegativeImplId<'db>) -> Maybe<RewriteResult> {
505 if value.is_fully_concrete(self.db) {
506 return Ok(RewriteResult::NoChange);
507 }
508 value.default_rewrite(self)
509 }
510}
511
512impl<'db> SemanticRewriter<TypeLongId<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
513 fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Maybe<RewriteResult> {
514 match value {
515 TypeLongId::GenericParameter(generic_param) => {
516 if let Some(generic_arg) = self.substitution.get(generic_param) {
517 let type_id = *extract_matches!(generic_arg, GenericArgumentId::Type);
518 *value = type_id.long(self.db).clone();
520 return Ok(RewriteResult::Modified);
521 }
522 }
523 TypeLongId::ImplType(impl_type_id) => {
524 let impl_type_id_rewrite_result = self.internal_rewrite(impl_type_id)?;
525 let new_value = self.db.impl_type_concrete_implized(*impl_type_id)?.long(self.db);
526 if *new_value != *value {
527 *value = new_value.clone();
528 return Ok(RewriteResult::Modified);
529 } else {
530 return Ok(impl_type_id_rewrite_result);
531 }
532 }
533 _ => {}
534 }
535 value.default_rewrite(self)
536 }
537}
538impl<'db> SemanticRewriter<ConstValue<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
539 fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Maybe<RewriteResult> {
540 match value {
541 ConstValue::Generic(param_id) => {
542 if let Some(generic_arg) = self.substitution.get(param_id) {
543 let const_value_id = extract_matches!(generic_arg, GenericArgumentId::Constant);
544
545 *value = const_value_id.long(self.db).clone();
546 return Ok(RewriteResult::Modified);
547 }
548 }
549 ConstValue::ImplConstant(impl_constant_id) => {
550 let impl_const_id_rewrite_result = self.internal_rewrite(impl_constant_id)?;
551 let new_value =
552 self.db.impl_constant_concrete_implized_value(*impl_constant_id)?.long(self.db);
553 if *new_value != *value {
554 *value = new_value.clone();
555 return Ok(RewriteResult::Modified);
556 } else {
557 return Ok(impl_const_id_rewrite_result);
558 }
559 }
560 _ => {}
561 }
562
563 value.default_rewrite(self)
564 }
565}
566impl<'db> SemanticRewriter<ImplLongId<'db>, DiagnosticAdded> for SubstitutionRewriter<'db, '_> {
567 fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Maybe<RewriteResult> {
568 match value {
569 ImplLongId::GenericParameter(generic_param) => {
570 if let Some(generic_arg) = self.substitution.get(generic_param) {
571 *value = extract_matches!(generic_arg, GenericArgumentId::Impl)
572 .long(self.db)
573 .clone();
574 return Ok(RewriteResult::Modified);
577 }
578 }
579 ImplLongId::ImplImpl(impl_impl_id) => {
580 let impl_impl_id_rewrite_result = self.internal_rewrite(impl_impl_id)?;
581 let new_value = self.db.impl_impl_concrete_implized(*impl_impl_id)?.long(self.db);
582 if *new_value != *value {
583 *value = new_value.clone();
584 return Ok(RewriteResult::Modified);
585 } else {
586 return Ok(impl_impl_id_rewrite_result);
587 }
588 }
589 ImplLongId::SelfImpl(concrete_trait_id) => {
590 let rewrite_result = self.internal_rewrite(concrete_trait_id)?;
591 if let Some(self_impl) = &self.substitution.self_impl {
592 if *concrete_trait_id == self_impl.concrete_trait(self.db)? {
593 *value = self_impl.long(self.db).clone();
594 return Ok(RewriteResult::Modified);
595 }
596 } else {
597 return Ok(rewrite_result);
598 }
599 }
600 _ => {}
601 }
602 value.default_rewrite(self)
603 }
604}
605
606impl<'db> SemanticRewriter<NegativeImplLongId<'db>, DiagnosticAdded>
607 for SubstitutionRewriter<'db, '_>
608{
609 fn internal_rewrite(&mut self, value: &mut NegativeImplLongId<'db>) -> Maybe<RewriteResult> {
610 if let NegativeImplLongId::GenericParameter(generic_param) = value
611 && let Some(generic_arg) = self.substitution.get(generic_param)
612 {
613 *value =
614 extract_matches!(generic_arg, GenericArgumentId::NegImpl).long(self.db).clone();
615 return Ok(RewriteResult::Modified);
616 }
617
618 value.default_rewrite(self)
619 }
620}
621
622impl<'db> SemanticRewriter<GenericFunctionWithBodyId<'db>, DiagnosticAdded>
623 for SubstitutionRewriter<'db, '_>
624{
625 fn internal_rewrite(
626 &mut self,
627 value: &mut GenericFunctionWithBodyId<'db>,
628 ) -> Maybe<RewriteResult> {
629 if let GenericFunctionWithBodyId::Trait(id) = value
630 && let Some(self_impl) = &self.substitution.self_impl
631 && let ImplLongId::Concrete(concrete_impl_id) = self_impl.long(self.db)
632 && self.rewrite(id.concrete_trait(self.db))? == self_impl.concrete_trait(self.db)?
633 {
634 *value = GenericFunctionWithBodyId::Impl(ImplGenericFunctionWithBodyId {
635 concrete_impl_id: *concrete_impl_id,
636 function_body: ImplFunctionBodyId::Trait(id.trait_function(self.db)),
637 });
638 return Ok(RewriteResult::Modified);
639 }
640 value.default_rewrite(self)
641 }
642}