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