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#[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 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 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#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, salsa::Update)]
77pub struct CanonicalImpl<'db>(pub ImplId<'db>);
78impl<'db> CanonicalImpl<'db> {
79 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 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#[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#[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#[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
191struct 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
343struct 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#[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}