cairo_lang_semantic/expr/inference/
canonic.rs

1use cairo_lang_defs::ids::{
2    EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericParamId, ImplAliasId, ImplDefId,
3    ImplFunctionId, ImplImplDefId, LocalVarId, MemberId, ParamId, StructId, TraitConstantId,
4    TraitFunctionId, TraitId, TraitImplId, TraitTypeId, VarId, VariantId,
5};
6use cairo_lang_proc_macros::SemanticObject;
7use cairo_lang_utils::Intern;
8use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
9use salsa::Database;
10
11use super::{
12    ConstVar, ImplVar, ImplVarId, ImplVarTraitItemMappings, Inference, InferenceId, InferenceVar,
13    LocalConstVarId, LocalImplVarId, LocalNegativeImplVarId, LocalTypeVarId, NegativeImplVar,
14    NegativeImplVarId, TypeVar,
15};
16use crate::items::constant::{ConstValue, ConstValueId, ImplConstantId};
17use crate::items::functions::{
18    ConcreteFunctionWithBody, ConcreteFunctionWithBodyId, GenericFunctionId,
19    GenericFunctionWithBodyId, ImplFunctionBodyId, ImplGenericFunctionId,
20    ImplGenericFunctionWithBodyId,
21};
22use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
23use crate::items::imp::{
24    GeneratedImplId, GeneratedImplItems, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
25    NegativeImplId, NegativeImplLongId, UninferredGeneratedImplId, UninferredGeneratedImplLongId,
26    UninferredImpl,
27};
28use crate::items::trt::{
29    ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId, ConcreteTraitTypeId,
30    ConcreteTraitTypeLongId,
31};
32use crate::substitution::{HasDb, RewriteResult, SemanticObject, SemanticRewriter};
33use crate::types::{
34    ClosureTypeLongId, ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId,
35    ImplTypeId,
36};
37use crate::{
38    ConcreteEnumId, ConcreteExternTypeId, ConcreteFunction, ConcreteImplId, ConcreteImplLongId,
39    ConcreteStructId, ConcreteTraitId, ConcreteTraitLongId, ConcreteTypeId, ConcreteVariant,
40    ExprId, ExprVar, ExprVarMemberPath, FunctionId, FunctionLongId, GenericArgumentId,
41    GenericParam, MatchArmSelector, Parameter, Signature, TypeId, TypeLongId, ValueSelectorArm,
42    add_basic_rewrites,
43};
44
45/// A canonical representation of a concrete trait that needs to be solved.
46#[derive(Clone, PartialEq, Hash, Eq, Debug, SemanticObject)]
47pub struct CanonicalTrait<'db> {
48    pub id: ConcreteTraitId<'db>,
49    pub mappings: ImplVarTraitItemMappings<'db>,
50}
51
52impl<'db> CanonicalTrait<'db> {
53    /// Canonicalizes a concrete trait that is part of an [Inference].
54    pub fn canonicalize(
55        db: &'db dyn Database,
56        source_inference_id: InferenceId<'db>,
57        trait_id: ConcreteTraitId<'db>,
58        impl_var_mappings: ImplVarTraitItemMappings<'db>,
59    ) -> (Self, CanonicalMapping<'db>) {
60        Canonicalizer::canonicalize(
61            db,
62            source_inference_id,
63            Self { id: trait_id, mappings: impl_var_mappings },
64        )
65    }
66    /// Embeds a canonical trait into an [Inference].
67    pub fn embed(
68        &self,
69        inference: &mut Inference<'db, '_>,
70    ) -> (CanonicalTrait<'db>, CanonicalMapping<'db>) {
71        Embedder::embed(inference, self.clone())
72    }
73}
74
75/// A solution for a [CanonicalTrait].
76#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, salsa::Update)]
77pub struct CanonicalImpl<'db>(pub ImplId<'db>);
78impl<'db> CanonicalImpl<'db> {
79    /// Canonicalizes a concrete impl that is part of an [Inference].
80    /// Uses the same canonicalization of the trait, to be consistent.
81    pub fn canonicalize(
82        db: &'db dyn Database,
83        impl_id: ImplId<'db>,
84        mapping: &CanonicalMapping<'db>,
85    ) -> Result<Self, MapperError> {
86        Ok(Self(Mapper::map(db, impl_id, &mapping.to_canonic)?))
87    }
88    /// Embeds a canonical impl into an [Inference].
89    /// Uses the same embedding of the trait, to be consistent.
90    pub fn embed(
91        &self,
92        inference: &Inference<'db, '_>,
93        mapping: &CanonicalMapping<'db>,
94    ) -> ImplId<'db> {
95        Mapper::map(inference.db, self.0, &mapping.from_canonic)
96            .expect("Tried to embed a non canonical impl")
97    }
98}
99
100/// Mapping between canonical space and inference space.
101/// Created by either canonicalizing or embedding a trait.
102#[derive(Debug)]
103pub struct CanonicalMapping<'db> {
104    to_canonic: VarMapping<'db>,
105    from_canonic: VarMapping<'db>,
106}
107impl<'db> CanonicalMapping<'db> {
108    fn from_to_canonic(to_canonic: VarMapping<'db>) -> CanonicalMapping<'db> {
109        let from_canonic = VarMapping {
110            type_var_mapping: to_canonic.type_var_mapping.iter().map(|(k, v)| (*v, *k)).collect(),
111            const_var_mapping: to_canonic.const_var_mapping.iter().map(|(k, v)| (*v, *k)).collect(),
112            impl_var_mapping: to_canonic.impl_var_mapping.iter().map(|(k, v)| (*v, *k)).collect(),
113            negative_impl_var_mapping: to_canonic
114                .negative_impl_var_mapping
115                .iter()
116                .map(|(k, v)| (*v, *k))
117                .collect(),
118            source_inference_id: to_canonic.target_inference_id,
119            target_inference_id: to_canonic.source_inference_id,
120        };
121        Self { to_canonic, from_canonic }
122    }
123    fn from_from_canonic(from_canonic: VarMapping<'db>) -> CanonicalMapping<'db> {
124        let to_canonic = VarMapping {
125            type_var_mapping: from_canonic.type_var_mapping.iter().map(|(k, v)| (*v, *k)).collect(),
126            const_var_mapping: from_canonic
127                .const_var_mapping
128                .iter()
129                .map(|(k, v)| (*v, *k))
130                .collect(),
131            impl_var_mapping: from_canonic.impl_var_mapping.iter().map(|(k, v)| (*v, *k)).collect(),
132            negative_impl_var_mapping: from_canonic
133                .negative_impl_var_mapping
134                .iter()
135                .map(|(k, v)| (*v, *k))
136                .collect(),
137            source_inference_id: from_canonic.target_inference_id,
138            target_inference_id: from_canonic.source_inference_id,
139        };
140        Self { to_canonic, from_canonic }
141    }
142}
143
144// Mappings.
145#[derive(Debug)]
146pub struct VarMapping<'db> {
147    type_var_mapping: OrderedHashMap<LocalTypeVarId, LocalTypeVarId>,
148    const_var_mapping: OrderedHashMap<LocalConstVarId, LocalConstVarId>,
149    impl_var_mapping: OrderedHashMap<LocalImplVarId, LocalImplVarId>,
150    negative_impl_var_mapping: OrderedHashMap<LocalNegativeImplVarId, LocalNegativeImplVarId>,
151    source_inference_id: InferenceId<'db>,
152    target_inference_id: InferenceId<'db>,
153}
154impl<'db> VarMapping<'db> {
155    fn new_to_canonic(source_inference_id: InferenceId<'db>) -> Self {
156        Self {
157            type_var_mapping: OrderedHashMap::default(),
158            const_var_mapping: OrderedHashMap::default(),
159            impl_var_mapping: OrderedHashMap::default(),
160            negative_impl_var_mapping: OrderedHashMap::default(),
161            source_inference_id,
162            target_inference_id: InferenceId::Canonical,
163        }
164    }
165    fn new_from_canonic(target_inference_id: InferenceId<'db>) -> Self {
166        Self {
167            type_var_mapping: OrderedHashMap::default(),
168            const_var_mapping: OrderedHashMap::default(),
169            impl_var_mapping: OrderedHashMap::default(),
170            negative_impl_var_mapping: OrderedHashMap::default(),
171            source_inference_id: InferenceId::Canonical,
172            target_inference_id,
173        }
174    }
175}
176
177/// A 'never' error.
178#[derive(Debug)]
179pub enum NoError {}
180pub trait ResultNoErrEx<T> {
181    fn no_err(self) -> T;
182}
183impl<T> ResultNoErrEx<T> for Result<T, NoError> {
184    fn no_err(self) -> T {
185        match self {
186            Ok(v) => v,
187        }
188    }
189}
190
191/// Canonicalization rewriter. Each encountered variable is mapped to a new free variable,
192/// in pre-order.
193struct Canonicalizer<'db> {
194    db: &'db dyn Database,
195    to_canonic: VarMapping<'db>,
196}
197impl<'db> Canonicalizer<'db> {
198    fn canonicalize<T>(
199        db: &'db dyn Database,
200        source_inference_id: InferenceId<'db>,
201        value: T,
202    ) -> (T, CanonicalMapping<'db>)
203    where
204        Self: SemanticRewriter<T, NoError>,
205    {
206        let mut canonicalizer =
207            Self { db, to_canonic: VarMapping::new_to_canonic(source_inference_id) };
208        let value = canonicalizer.rewrite(value).no_err();
209        let mapping = CanonicalMapping::from_to_canonic(canonicalizer.to_canonic);
210        (value, mapping)
211    }
212}
213impl<'a> HasDb<&'a dyn Database> for Canonicalizer<'a> {
214    fn get_db(&self) -> &'a dyn Database {
215        self.db
216    }
217}
218
219add_basic_rewrites!(
220    <'a>,
221    Canonicalizer<'a>,
222    NoError,
223    @exclude TypeLongId TypeId ImplLongId ImplId ConstValue NegativeImplLongId NegativeImplId
224);
225
226impl<'db> SemanticRewriter<TypeId<'db>, NoError> for Canonicalizer<'db> {
227    fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, NoError> {
228        if value.is_var_free(self.db) {
229            return Ok(RewriteResult::NoChange);
230        }
231        value.default_rewrite(self)
232    }
233}
234impl<'db> SemanticRewriter<TypeLongId<'db>, NoError> for Canonicalizer<'db> {
235    fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Result<RewriteResult, NoError> {
236        let TypeLongId::Var(var) = value else {
237            return value.default_rewrite(self);
238        };
239        if var.inference_id != self.to_canonic.source_inference_id {
240            return value.default_rewrite(self);
241        }
242        let next_id = LocalTypeVarId(self.to_canonic.type_var_mapping.len());
243        *value = TypeLongId::Var(TypeVar {
244            id: *self.to_canonic.type_var_mapping.entry(var.id).or_insert(next_id),
245            inference_id: InferenceId::Canonical,
246        });
247        Ok(RewriteResult::Modified)
248    }
249}
250impl<'db> SemanticRewriter<ConstValue<'db>, NoError> for Canonicalizer<'db> {
251    fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Result<RewriteResult, NoError> {
252        let ConstValue::Var(var, ty) = value else {
253            return value.default_rewrite(self);
254        };
255        if var.inference_id != self.to_canonic.source_inference_id {
256            return value.default_rewrite(self);
257        }
258        let next_id = LocalConstVarId(self.to_canonic.const_var_mapping.len());
259        ty.default_rewrite(self)?;
260        *value = ConstValue::Var(
261            ConstVar {
262                id: *self.to_canonic.const_var_mapping.entry(var.id).or_insert(next_id),
263                inference_id: InferenceId::Canonical,
264            },
265            *ty,
266        );
267        Ok(RewriteResult::Modified)
268    }
269}
270impl<'db> SemanticRewriter<ImplId<'db>, NoError> for Canonicalizer<'db> {
271    fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, NoError> {
272        if value.is_var_free(self.db) {
273            return Ok(RewriteResult::NoChange);
274        }
275        value.default_rewrite(self)
276    }
277}
278impl<'db> SemanticRewriter<ImplLongId<'db>, NoError> for Canonicalizer<'db> {
279    fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Result<RewriteResult, NoError> {
280        let ImplLongId::ImplVar(var_id) = value else {
281            if value.is_var_free(self.db) {
282                return Ok(RewriteResult::NoChange);
283            }
284            return value.default_rewrite(self);
285        };
286        let var = var_id.long(self.db);
287        if var.inference_id != self.to_canonic.source_inference_id {
288            return value.default_rewrite(self);
289        }
290        let next_id = LocalImplVarId(self.to_canonic.impl_var_mapping.len());
291
292        let mut var = ImplVar {
293            id: *self.to_canonic.impl_var_mapping.entry(var.id).or_insert(next_id),
294            inference_id: InferenceId::Canonical,
295            lookup_context: var.lookup_context,
296            concrete_trait_id: var.concrete_trait_id,
297        };
298        var.concrete_trait_id.default_rewrite(self)?;
299        *value = ImplLongId::ImplVar(var.intern(self.db));
300        Ok(RewriteResult::Modified)
301    }
302}
303impl<'db> SemanticRewriter<NegativeImplId<'db>, NoError> for Canonicalizer<'db> {
304    fn internal_rewrite(
305        &mut self,
306        value: &mut NegativeImplId<'db>,
307    ) -> Result<RewriteResult, NoError> {
308        if value.is_var_free(self.db) {
309            return Ok(RewriteResult::NoChange);
310        }
311        value.default_rewrite(self)
312    }
313}
314impl<'db> SemanticRewriter<NegativeImplLongId<'db>, NoError> for Canonicalizer<'db> {
315    fn internal_rewrite(
316        &mut self,
317        value: &mut NegativeImplLongId<'db>,
318    ) -> Result<RewriteResult, NoError> {
319        let NegativeImplLongId::NegativeImplVar(var_id) = value else {
320            if value.is_var_free(self.db) {
321                return Ok(RewriteResult::NoChange);
322            }
323            return value.default_rewrite(self);
324        };
325        let var = var_id.long(self.db);
326        if var.inference_id != self.to_canonic.source_inference_id {
327            return value.default_rewrite(self);
328        }
329        let next_id = LocalNegativeImplVarId(self.to_canonic.negative_impl_var_mapping.len());
330
331        let mut var = NegativeImplVar {
332            id: *self.to_canonic.negative_impl_var_mapping.entry(var.id).or_insert(next_id),
333            inference_id: InferenceId::Canonical,
334            lookup_context: var.lookup_context,
335            concrete_trait_id: var.concrete_trait_id,
336        };
337        var.concrete_trait_id.default_rewrite(self)?;
338        *value = NegativeImplLongId::NegativeImplVar(var.intern(self.db));
339        Ok(RewriteResult::Modified)
340    }
341}
342
343/// Embedder rewriter. Each canonical variable is mapped to a new inference variable.
344struct Embedder<'db, 'id, 'mt> {
345    inference: &'mt mut Inference<'db, 'id>,
346    from_canonic: VarMapping<'db>,
347}
348impl<'db, 'id, 'mt> Embedder<'db, 'id, 'mt> {
349    fn embed<T>(inference: &'mt mut Inference<'db, 'id>, value: T) -> (T, CanonicalMapping<'db>)
350    where
351        Self: SemanticRewriter<T, NoError>,
352    {
353        let from_canonic = VarMapping::new_from_canonic(inference.inference_id);
354        let mut embedder = Self { inference, from_canonic };
355        let value = embedder.rewrite(value).no_err();
356        let mapping = CanonicalMapping::from_from_canonic(embedder.from_canonic);
357        (value, mapping)
358    }
359}
360
361impl<'db> HasDb<&'db dyn Database> for Embedder<'db, '_, '_> {
362    fn get_db(&self) -> &'db dyn Database {
363        self.inference.db
364    }
365}
366
367add_basic_rewrites!(
368    <'a, 'id, 'mt>,
369    Embedder<'a, 'id, 'mt>,
370    NoError,
371    @exclude TypeLongId TypeId ConstValue ImplLongId ImplId NegativeImplLongId NegativeImplId
372);
373
374impl<'db> SemanticRewriter<TypeId<'db>, NoError> for Embedder<'db, '_, '_> {
375    fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, NoError> {
376        if value.is_var_free(self.get_db()) {
377            return Ok(RewriteResult::NoChange);
378        }
379        value.default_rewrite(self)
380    }
381}
382impl<'db> SemanticRewriter<TypeLongId<'db>, NoError> for Embedder<'db, '_, '_> {
383    fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Result<RewriteResult, NoError> {
384        let TypeLongId::Var(var) = value else {
385            return value.default_rewrite(self);
386        };
387        if var.inference_id != InferenceId::Canonical {
388            return value.default_rewrite(self);
389        }
390        let new_id = self
391            .from_canonic
392            .type_var_mapping
393            .entry(var.id)
394            .or_insert_with(|| self.inference.new_type_var_raw(None).id);
395        *value = TypeLongId::Var(self.inference.type_vars[new_id.0]);
396        Ok(RewriteResult::Modified)
397    }
398}
399impl<'db> SemanticRewriter<ConstValue<'db>, NoError> for Embedder<'db, '_, '_> {
400    fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Result<RewriteResult, NoError> {
401        let ConstValue::Var(var, ty) = value else {
402            return value.default_rewrite(self);
403        };
404        if var.inference_id != InferenceId::Canonical {
405            return value.default_rewrite(self);
406        }
407        ty.default_rewrite(self)?;
408        let new_id = self
409            .from_canonic
410            .const_var_mapping
411            .entry(var.id)
412            .or_insert_with(|| self.inference.new_const_var_raw(None).id);
413        *value = ConstValue::Var(self.inference.const_vars[new_id.0], *ty);
414        Ok(RewriteResult::Modified)
415    }
416}
417impl<'db> SemanticRewriter<ImplId<'db>, NoError> for Embedder<'db, '_, '_> {
418    fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, NoError> {
419        if value.is_var_free(self.get_db()) {
420            return Ok(RewriteResult::NoChange);
421        }
422        value.default_rewrite(self)
423    }
424}
425impl<'db> SemanticRewriter<ImplLongId<'db>, NoError> for Embedder<'db, '_, '_> {
426    fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Result<RewriteResult, NoError> {
427        let ImplLongId::ImplVar(var_id) = value else {
428            if value.is_var_free(self.get_db()) {
429                return Ok(RewriteResult::NoChange);
430            }
431            return value.default_rewrite(self);
432        };
433        let var = var_id.long(self.get_db());
434        if var.inference_id != InferenceId::Canonical {
435            return value.default_rewrite(self);
436        }
437        let concrete_trait_id = self.rewrite(var.concrete_trait_id)?;
438        let new_id = self.from_canonic.impl_var_mapping.entry(var.id).or_insert_with(|| {
439            self.inference.new_impl_var_raw(var.lookup_context, concrete_trait_id, None)
440        });
441        *value =
442            ImplLongId::ImplVar(self.inference.impl_vars[new_id.0].clone().intern(self.get_db()));
443        Ok(RewriteResult::Modified)
444    }
445}
446impl<'db> SemanticRewriter<NegativeImplId<'db>, NoError> for Embedder<'db, '_, '_> {
447    fn internal_rewrite(
448        &mut self,
449        value: &mut NegativeImplId<'db>,
450    ) -> Result<RewriteResult, NoError> {
451        if value.is_var_free(self.get_db()) {
452            return Ok(RewriteResult::NoChange);
453        }
454        value.default_rewrite(self)
455    }
456}
457impl<'db> SemanticRewriter<NegativeImplLongId<'db>, NoError> for Embedder<'db, '_, '_> {
458    fn internal_rewrite(
459        &mut self,
460        value: &mut NegativeImplLongId<'db>,
461    ) -> Result<RewriteResult, NoError> {
462        let NegativeImplLongId::NegativeImplVar(var_id) = value else {
463            if value.is_var_free(self.get_db()) {
464                return Ok(RewriteResult::NoChange);
465            }
466            return value.default_rewrite(self);
467        };
468        let var = var_id.long(self.get_db());
469        if var.inference_id != InferenceId::Canonical {
470            return value.default_rewrite(self);
471        }
472        let concrete_trait_id = self.rewrite(var.concrete_trait_id)?;
473        let new_id =
474            self.from_canonic.negative_impl_var_mapping.entry(var.id).or_insert_with(|| {
475                self.inference.new_negative_impl_var_raw(
476                    var.lookup_context,
477                    concrete_trait_id,
478                    None,
479                )
480            });
481        *value = NegativeImplLongId::NegativeImplVar(
482            self.inference.negative_impl_vars[new_id.0].clone().intern(self.get_db()),
483        );
484        Ok(RewriteResult::Modified)
485    }
486}
487
488/// Mapper rewriter. Maps variables according to a given [VarMapping].
489#[derive(Clone, Debug)]
490pub struct MapperError(pub InferenceVar);
491struct Mapper<'db, 'v> {
492    db: &'db dyn Database,
493    mapping: &'v VarMapping<'db>,
494}
495impl<'db, 'v> Mapper<'db, 'v> {
496    fn map<T>(
497        db: &'db dyn Database,
498        value: T,
499        mapping: &'v VarMapping<'db>,
500    ) -> Result<T, MapperError>
501    where
502        Self: SemanticRewriter<T, MapperError>,
503    {
504        let mut mapper = Self { db, mapping };
505        mapper.rewrite(value)
506    }
507}
508
509impl<'db> HasDb<&'db dyn Database> for Mapper<'db, '_> {
510    fn get_db(&self) -> &'db dyn Database {
511        self.db
512    }
513}
514
515add_basic_rewrites!(
516    <'a>,
517    Mapper<'a, '_>,
518    MapperError,
519    @exclude TypeLongId TypeId ImplLongId ImplId ConstValue NegativeImplLongId NegativeImplId
520);
521
522impl<'db> SemanticRewriter<TypeId<'db>, MapperError> for Mapper<'db, '_> {
523    fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, MapperError> {
524        if value.is_var_free(self.db) {
525            return Ok(RewriteResult::NoChange);
526        }
527        value.default_rewrite(self)
528    }
529}
530impl<'db> SemanticRewriter<TypeLongId<'db>, MapperError> for Mapper<'db, '_> {
531    fn internal_rewrite(
532        &mut self,
533        value: &mut TypeLongId<'db>,
534    ) -> Result<RewriteResult, MapperError> {
535        let TypeLongId::Var(var) = value else {
536            return value.default_rewrite(self);
537        };
538        let id = self
539            .mapping
540            .type_var_mapping
541            .get(&var.id)
542            .copied()
543            .ok_or(MapperError(InferenceVar::Type(var.id)))?;
544        *value = TypeLongId::Var(TypeVar { id, inference_id: self.mapping.target_inference_id });
545        Ok(RewriteResult::Modified)
546    }
547}
548impl<'db> SemanticRewriter<ConstValue<'db>, MapperError> for Mapper<'db, '_> {
549    fn internal_rewrite(
550        &mut self,
551        value: &mut ConstValue<'db>,
552    ) -> Result<RewriteResult, MapperError> {
553        let ConstValue::Var(var, ty) = value else {
554            return value.default_rewrite(self);
555        };
556        let id = self
557            .mapping
558            .const_var_mapping
559            .get(&var.id)
560            .copied()
561            .ok_or(MapperError(InferenceVar::Const(var.id)))?;
562        ty.default_rewrite(self)?;
563        *value =
564            ConstValue::Var(ConstVar { id, inference_id: self.mapping.target_inference_id }, *ty);
565        Ok(RewriteResult::Modified)
566    }
567}
568impl<'db> SemanticRewriter<ImplId<'db>, MapperError> for Mapper<'db, '_> {
569    fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, MapperError> {
570        if value.is_var_free(self.db) {
571            return Ok(RewriteResult::NoChange);
572        }
573        value.default_rewrite(self)
574    }
575}
576impl<'db> SemanticRewriter<ImplLongId<'db>, MapperError> for Mapper<'db, '_> {
577    fn internal_rewrite(
578        &mut self,
579        value: &mut ImplLongId<'db>,
580    ) -> Result<RewriteResult, MapperError> {
581        let ImplLongId::ImplVar(var_id) = value else {
582            return value.default_rewrite(self);
583        };
584        let var = var_id.long(self.get_db());
585        let id = self
586            .mapping
587            .impl_var_mapping
588            .get(&var.id)
589            .copied()
590            .ok_or(MapperError(InferenceVar::Impl(var.id)))?;
591        let var = ImplVar { id, inference_id: self.mapping.target_inference_id, ..var.clone() };
592
593        *value = ImplLongId::ImplVar(var.intern(self.get_db()));
594        Ok(RewriteResult::Modified)
595    }
596}
597impl<'db> SemanticRewriter<NegativeImplId<'db>, MapperError> for Mapper<'db, '_> {
598    fn internal_rewrite(
599        &mut self,
600        value: &mut NegativeImplId<'db>,
601    ) -> Result<RewriteResult, MapperError> {
602        if value.is_var_free(self.db) {
603            return Ok(RewriteResult::NoChange);
604        }
605        value.default_rewrite(self)
606    }
607}
608impl<'db> SemanticRewriter<NegativeImplLongId<'db>, MapperError> for Mapper<'db, '_> {
609    fn internal_rewrite(
610        &mut self,
611        value: &mut NegativeImplLongId<'db>,
612    ) -> Result<RewriteResult, MapperError> {
613        let NegativeImplLongId::NegativeImplVar(var_id) = value else {
614            return value.default_rewrite(self);
615        };
616        let var = var_id.long(self.get_db());
617        let id = self
618            .mapping
619            .negative_impl_var_mapping
620            .get(&var.id)
621            .copied()
622            .ok_or(MapperError(InferenceVar::NegativeImpl(var.id)))?;
623        let var =
624            NegativeImplVar { id, inference_id: self.mapping.target_inference_id, ..var.clone() };
625
626        *value = NegativeImplLongId::NegativeImplVar(var.intern(self.get_db()));
627        Ok(RewriteResult::Modified)
628    }
629}