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 #[allow(unreachable_patterns)]
188 Err(err) => match err {},
189 }
190 }
191}
192
193struct Canonicalizer<'db> {
196 db: &'db dyn Database,
197 to_canonic: VarMapping<'db>,
198}
199impl<'db> Canonicalizer<'db> {
200 fn canonicalize<T>(
201 db: &'db dyn Database,
202 source_inference_id: InferenceId<'db>,
203 value: T,
204 ) -> (T, CanonicalMapping<'db>)
205 where
206 Self: SemanticRewriter<T, NoError>,
207 {
208 let mut canonicalizer =
209 Self { db, to_canonic: VarMapping::new_to_canonic(source_inference_id) };
210 let value = canonicalizer.rewrite(value).no_err();
211 let mapping = CanonicalMapping::from_to_canonic(canonicalizer.to_canonic);
212 (value, mapping)
213 }
214}
215impl<'a> HasDb<&'a dyn Database> for Canonicalizer<'a> {
216 fn get_db(&self) -> &'a dyn Database {
217 self.db
218 }
219}
220
221add_basic_rewrites!(
222 <'a>,
223 Canonicalizer<'a>,
224 NoError,
225 @exclude TypeLongId TypeId ImplLongId ImplId ConstValue NegativeImplLongId NegativeImplId
226);
227
228impl<'db> SemanticRewriter<TypeId<'db>, NoError> for Canonicalizer<'db> {
229 fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, NoError> {
230 if value.is_var_free(self.db) {
231 return Ok(RewriteResult::NoChange);
232 }
233 value.default_rewrite(self)
234 }
235}
236impl<'db> SemanticRewriter<TypeLongId<'db>, NoError> for Canonicalizer<'db> {
237 fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Result<RewriteResult, NoError> {
238 let TypeLongId::Var(var) = value else {
239 return value.default_rewrite(self);
240 };
241 if var.inference_id != self.to_canonic.source_inference_id {
242 return value.default_rewrite(self);
243 }
244 let next_id = LocalTypeVarId(self.to_canonic.type_var_mapping.len());
245 *value = TypeLongId::Var(TypeVar {
246 id: *self.to_canonic.type_var_mapping.entry(var.id).or_insert(next_id),
247 inference_id: InferenceId::Canonical,
248 });
249 Ok(RewriteResult::Modified)
250 }
251}
252impl<'db> SemanticRewriter<ConstValue<'db>, NoError> for Canonicalizer<'db> {
253 fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Result<RewriteResult, NoError> {
254 let ConstValue::Var(var, ty) = value else {
255 return value.default_rewrite(self);
256 };
257 if var.inference_id != self.to_canonic.source_inference_id {
258 return value.default_rewrite(self);
259 }
260 let next_id = LocalConstVarId(self.to_canonic.const_var_mapping.len());
261 ty.default_rewrite(self)?;
262 *value = ConstValue::Var(
263 ConstVar {
264 id: *self.to_canonic.const_var_mapping.entry(var.id).or_insert(next_id),
265 inference_id: InferenceId::Canonical,
266 },
267 *ty,
268 );
269 Ok(RewriteResult::Modified)
270 }
271}
272impl<'db> SemanticRewriter<ImplId<'db>, NoError> for Canonicalizer<'db> {
273 fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, NoError> {
274 if value.is_var_free(self.db) {
275 return Ok(RewriteResult::NoChange);
276 }
277 value.default_rewrite(self)
278 }
279}
280impl<'db> SemanticRewriter<ImplLongId<'db>, NoError> for Canonicalizer<'db> {
281 fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Result<RewriteResult, NoError> {
282 let ImplLongId::ImplVar(var_id) = value else {
283 if value.is_var_free(self.db) {
284 return Ok(RewriteResult::NoChange);
285 }
286 return value.default_rewrite(self);
287 };
288 let var = var_id.long(self.db);
289 if var.inference_id != self.to_canonic.source_inference_id {
290 return value.default_rewrite(self);
291 }
292 let next_id = LocalImplVarId(self.to_canonic.impl_var_mapping.len());
293
294 let mut var = ImplVar {
295 id: *self.to_canonic.impl_var_mapping.entry(var.id).or_insert(next_id),
296 inference_id: InferenceId::Canonical,
297 lookup_context: var.lookup_context,
298 concrete_trait_id: var.concrete_trait_id,
299 };
300 var.concrete_trait_id.default_rewrite(self)?;
301 *value = ImplLongId::ImplVar(var.intern(self.db));
302 Ok(RewriteResult::Modified)
303 }
304}
305impl<'db> SemanticRewriter<NegativeImplId<'db>, NoError> for Canonicalizer<'db> {
306 fn internal_rewrite(
307 &mut self,
308 value: &mut NegativeImplId<'db>,
309 ) -> Result<RewriteResult, NoError> {
310 if value.is_var_free(self.db) {
311 return Ok(RewriteResult::NoChange);
312 }
313 value.default_rewrite(self)
314 }
315}
316impl<'db> SemanticRewriter<NegativeImplLongId<'db>, NoError> for Canonicalizer<'db> {
317 fn internal_rewrite(
318 &mut self,
319 value: &mut NegativeImplLongId<'db>,
320 ) -> Result<RewriteResult, NoError> {
321 let NegativeImplLongId::NegativeImplVar(var_id) = value else {
322 if value.is_var_free(self.db) {
323 return Ok(RewriteResult::NoChange);
324 }
325 return value.default_rewrite(self);
326 };
327 let var = var_id.long(self.db);
328 if var.inference_id != self.to_canonic.source_inference_id {
329 return value.default_rewrite(self);
330 }
331 let next_id = LocalNegativeImplVarId(self.to_canonic.negative_impl_var_mapping.len());
332
333 let mut var = NegativeImplVar {
334 id: *self.to_canonic.negative_impl_var_mapping.entry(var.id).or_insert(next_id),
335 inference_id: InferenceId::Canonical,
336 lookup_context: var.lookup_context,
337 concrete_trait_id: var.concrete_trait_id,
338 };
339 var.concrete_trait_id.default_rewrite(self)?;
340 *value = NegativeImplLongId::NegativeImplVar(var.intern(self.db));
341 Ok(RewriteResult::Modified)
342 }
343}
344
345struct Embedder<'db, 'id, 'mt> {
347 inference: &'mt mut Inference<'db, 'id>,
348 from_canonic: VarMapping<'db>,
349}
350impl<'db, 'id, 'mt> Embedder<'db, 'id, 'mt> {
351 fn embed<T>(inference: &'mt mut Inference<'db, 'id>, value: T) -> (T, CanonicalMapping<'db>)
352 where
353 Self: SemanticRewriter<T, NoError>,
354 {
355 let from_canonic = VarMapping::new_from_canonic(inference.inference_id);
356 let mut embedder = Self { inference, from_canonic };
357 let value = embedder.rewrite(value).no_err();
358 let mapping = CanonicalMapping::from_from_canonic(embedder.from_canonic);
359 (value, mapping)
360 }
361}
362
363impl<'db> HasDb<&'db dyn Database> for Embedder<'db, '_, '_> {
364 fn get_db(&self) -> &'db dyn Database {
365 self.inference.db
366 }
367}
368
369add_basic_rewrites!(
370 <'a, 'id, 'mt>,
371 Embedder<'a, 'id, 'mt>,
372 NoError,
373 @exclude TypeLongId TypeId ConstValue ImplLongId ImplId NegativeImplLongId NegativeImplId
374);
375
376impl<'db> SemanticRewriter<TypeId<'db>, NoError> for Embedder<'db, '_, '_> {
377 fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, NoError> {
378 if value.is_var_free(self.get_db()) {
379 return Ok(RewriteResult::NoChange);
380 }
381 value.default_rewrite(self)
382 }
383}
384impl<'db> SemanticRewriter<TypeLongId<'db>, NoError> for Embedder<'db, '_, '_> {
385 fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Result<RewriteResult, NoError> {
386 let TypeLongId::Var(var) = value else {
387 return value.default_rewrite(self);
388 };
389 if var.inference_id != InferenceId::Canonical {
390 return value.default_rewrite(self);
391 }
392 let new_id = self
393 .from_canonic
394 .type_var_mapping
395 .entry(var.id)
396 .or_insert_with(|| self.inference.new_type_var_raw(None).id);
397 *value = TypeLongId::Var(self.inference.type_vars[new_id.0]);
398 Ok(RewriteResult::Modified)
399 }
400}
401impl<'db> SemanticRewriter<ConstValue<'db>, NoError> for Embedder<'db, '_, '_> {
402 fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Result<RewriteResult, NoError> {
403 let ConstValue::Var(var, ty) = value else {
404 return value.default_rewrite(self);
405 };
406 if var.inference_id != InferenceId::Canonical {
407 return value.default_rewrite(self);
408 }
409 ty.default_rewrite(self)?;
410 let new_id = self
411 .from_canonic
412 .const_var_mapping
413 .entry(var.id)
414 .or_insert_with(|| self.inference.new_const_var_raw(None).id);
415 *value = ConstValue::Var(self.inference.const_vars[new_id.0], *ty);
416 Ok(RewriteResult::Modified)
417 }
418}
419impl<'db> SemanticRewriter<ImplId<'db>, NoError> for Embedder<'db, '_, '_> {
420 fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, NoError> {
421 if value.is_var_free(self.get_db()) {
422 return Ok(RewriteResult::NoChange);
423 }
424 value.default_rewrite(self)
425 }
426}
427impl<'db> SemanticRewriter<ImplLongId<'db>, NoError> for Embedder<'db, '_, '_> {
428 fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Result<RewriteResult, NoError> {
429 let ImplLongId::ImplVar(var_id) = value else {
430 if value.is_var_free(self.get_db()) {
431 return Ok(RewriteResult::NoChange);
432 }
433 return value.default_rewrite(self);
434 };
435 let var = var_id.long(self.get_db());
436 if var.inference_id != InferenceId::Canonical {
437 return value.default_rewrite(self);
438 }
439 let concrete_trait_id = self.rewrite(var.concrete_trait_id)?;
440 let new_id = self.from_canonic.impl_var_mapping.entry(var.id).or_insert_with(|| {
441 self.inference.new_impl_var_raw(var.lookup_context, concrete_trait_id, None)
442 });
443 *value =
444 ImplLongId::ImplVar(self.inference.impl_vars[new_id.0].clone().intern(self.get_db()));
445 Ok(RewriteResult::Modified)
446 }
447}
448impl<'db> SemanticRewriter<NegativeImplId<'db>, NoError> for Embedder<'db, '_, '_> {
449 fn internal_rewrite(
450 &mut self,
451 value: &mut NegativeImplId<'db>,
452 ) -> Result<RewriteResult, NoError> {
453 if value.is_var_free(self.get_db()) {
454 return Ok(RewriteResult::NoChange);
455 }
456 value.default_rewrite(self)
457 }
458}
459impl<'db> SemanticRewriter<NegativeImplLongId<'db>, NoError> for Embedder<'db, '_, '_> {
460 fn internal_rewrite(
461 &mut self,
462 value: &mut NegativeImplLongId<'db>,
463 ) -> Result<RewriteResult, NoError> {
464 let NegativeImplLongId::NegativeImplVar(var_id) = value else {
465 if value.is_var_free(self.get_db()) {
466 return Ok(RewriteResult::NoChange);
467 }
468 return value.default_rewrite(self);
469 };
470 let var = var_id.long(self.get_db());
471 if var.inference_id != InferenceId::Canonical {
472 return value.default_rewrite(self);
473 }
474 let concrete_trait_id = self.rewrite(var.concrete_trait_id)?;
475 let new_id =
476 self.from_canonic.negative_impl_var_mapping.entry(var.id).or_insert_with(|| {
477 self.inference.new_negative_impl_var_raw(
478 var.lookup_context,
479 concrete_trait_id,
480 None,
481 )
482 });
483 *value = NegativeImplLongId::NegativeImplVar(
484 self.inference.negative_impl_vars[new_id.0].clone().intern(self.get_db()),
485 );
486 Ok(RewriteResult::Modified)
487 }
488}
489
490#[derive(Clone, Debug)]
492pub struct MapperError(pub InferenceVar);
493struct Mapper<'db, 'v> {
494 db: &'db dyn Database,
495 mapping: &'v VarMapping<'db>,
496}
497impl<'db, 'v> Mapper<'db, 'v> {
498 fn map<T>(
499 db: &'db dyn Database,
500 value: T,
501 mapping: &'v VarMapping<'db>,
502 ) -> Result<T, MapperError>
503 where
504 Self: SemanticRewriter<T, MapperError>,
505 {
506 let mut mapper = Self { db, mapping };
507 mapper.rewrite(value)
508 }
509}
510
511impl<'db> HasDb<&'db dyn Database> for Mapper<'db, '_> {
512 fn get_db(&self) -> &'db dyn Database {
513 self.db
514 }
515}
516
517add_basic_rewrites!(
518 <'a>,
519 Mapper<'a, '_>,
520 MapperError,
521 @exclude TypeLongId TypeId ImplLongId ImplId ConstValue NegativeImplLongId NegativeImplId
522);
523
524impl<'db> SemanticRewriter<TypeId<'db>, MapperError> for Mapper<'db, '_> {
525 fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, MapperError> {
526 if value.is_var_free(self.db) {
527 return Ok(RewriteResult::NoChange);
528 }
529 value.default_rewrite(self)
530 }
531}
532impl<'db> SemanticRewriter<TypeLongId<'db>, MapperError> for Mapper<'db, '_> {
533 fn internal_rewrite(
534 &mut self,
535 value: &mut TypeLongId<'db>,
536 ) -> Result<RewriteResult, MapperError> {
537 let TypeLongId::Var(var) = value else {
538 return value.default_rewrite(self);
539 };
540 let id = self
541 .mapping
542 .type_var_mapping
543 .get(&var.id)
544 .copied()
545 .ok_or(MapperError(InferenceVar::Type(var.id)))?;
546 *value = TypeLongId::Var(TypeVar { id, inference_id: self.mapping.target_inference_id });
547 Ok(RewriteResult::Modified)
548 }
549}
550impl<'db> SemanticRewriter<ConstValue<'db>, MapperError> for Mapper<'db, '_> {
551 fn internal_rewrite(
552 &mut self,
553 value: &mut ConstValue<'db>,
554 ) -> Result<RewriteResult, MapperError> {
555 let ConstValue::Var(var, ty) = value else {
556 return value.default_rewrite(self);
557 };
558 let id = self
559 .mapping
560 .const_var_mapping
561 .get(&var.id)
562 .copied()
563 .ok_or(MapperError(InferenceVar::Const(var.id)))?;
564 ty.default_rewrite(self)?;
565 *value =
566 ConstValue::Var(ConstVar { id, inference_id: self.mapping.target_inference_id }, *ty);
567 Ok(RewriteResult::Modified)
568 }
569}
570impl<'db> SemanticRewriter<ImplId<'db>, MapperError> for Mapper<'db, '_> {
571 fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, MapperError> {
572 if value.is_var_free(self.db) {
573 return Ok(RewriteResult::NoChange);
574 }
575 value.default_rewrite(self)
576 }
577}
578impl<'db> SemanticRewriter<ImplLongId<'db>, MapperError> for Mapper<'db, '_> {
579 fn internal_rewrite(
580 &mut self,
581 value: &mut ImplLongId<'db>,
582 ) -> Result<RewriteResult, MapperError> {
583 let ImplLongId::ImplVar(var_id) = value else {
584 return value.default_rewrite(self);
585 };
586 let var = var_id.long(self.get_db());
587 let id = self
588 .mapping
589 .impl_var_mapping
590 .get(&var.id)
591 .copied()
592 .ok_or(MapperError(InferenceVar::Impl(var.id)))?;
593 let var = ImplVar { id, inference_id: self.mapping.target_inference_id, ..var.clone() };
594
595 *value = ImplLongId::ImplVar(var.intern(self.get_db()));
596 Ok(RewriteResult::Modified)
597 }
598}
599impl<'db> SemanticRewriter<NegativeImplId<'db>, MapperError> for Mapper<'db, '_> {
600 fn internal_rewrite(
601 &mut self,
602 value: &mut NegativeImplId<'db>,
603 ) -> Result<RewriteResult, MapperError> {
604 if value.is_var_free(self.db) {
605 return Ok(RewriteResult::NoChange);
606 }
607 value.default_rewrite(self)
608 }
609}
610impl<'db> SemanticRewriter<NegativeImplLongId<'db>, MapperError> for Mapper<'db, '_> {
611 fn internal_rewrite(
612 &mut self,
613 value: &mut NegativeImplLongId<'db>,
614 ) -> Result<RewriteResult, MapperError> {
615 let NegativeImplLongId::NegativeImplVar(var_id) = value else {
616 return value.default_rewrite(self);
617 };
618 let var = var_id.long(self.get_db());
619 let id = self
620 .mapping
621 .negative_impl_var_mapping
622 .get(&var.id)
623 .copied()
624 .ok_or(MapperError(InferenceVar::NegativeImpl(var.id)))?;
625 let var =
626 NegativeImplVar { id, inference_id: self.mapping.target_inference_id, ..var.clone() };
627
628 *value = NegativeImplLongId::NegativeImplVar(var.intern(self.get_db()));
629 Ok(RewriteResult::Modified)
630 }
631}