cairo_lang_semantic/
substitution.rs

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