Skip to main content

cairo_lang_semantic/expr/
inference.rs

1//! Bidirectional type inference.
2
3#![expect(clippy::disallowed_types)]
4
5use std::collections::HashMap;
6use std::hash::Hash;
7use std::ops::{Deref, DerefMut};
8use std::sync::Arc;
9
10use cairo_lang_debug::DebugWithDb;
11use cairo_lang_defs::ids::{
12    ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericKind,
13    GenericParamId, GlobalUseId, ImplAliasId, ImplDefId, ImplFunctionId, ImplImplDefId, LocalVarId,
14    LookupItemId, MacroCallId, MemberId, ModuleId, NamedLanguageElementId, ParamId, StructId,
15    TraitConstantId, TraitFunctionId, TraitId, TraitImplId, TraitTypeId, VarId, VariantId,
16};
17use cairo_lang_diagnostics::{DiagnosticAdded, skip_diagnostic};
18use cairo_lang_proc_macros::{DebugWithDb, HeapSize, SemanticObject};
19use cairo_lang_syntax::node::TypedStablePtr;
20use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
21use cairo_lang_utils::deque::Deque;
22use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
23use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
24use cairo_lang_utils::{Intern, define_short_id, extract_matches};
25use salsa::Database;
26
27use self::canonic::{CanonicalImpl, CanonicalMapping, CanonicalTrait, NoError};
28use self::solver::{Ambiguity, SolutionSet};
29use crate::corelib::{CorelibSemantic, is_valid_literal_type};
30use crate::diagnostic::{SemanticDiagnosticKind, SemanticDiagnostics, SemanticDiagnosticsBuilder};
31use crate::expr::inference::canonic::ResultNoErrEx;
32use crate::expr::inference::conform::InferenceConform;
33use crate::expr::inference::solver::SemanticSolver;
34use crate::expr::objects::*;
35use crate::expr::pattern::*;
36use crate::items::constant::{ConstValue, ConstValueId, ImplConstantId};
37use crate::items::functions::{
38    ConcreteFunctionWithBody, ConcreteFunctionWithBodyId, GenericFunctionId,
39    GenericFunctionWithBodyId, ImplFunctionBodyId, ImplGenericFunctionId,
40    ImplGenericFunctionWithBodyId,
41};
42use crate::items::generics::{
43    GenericParamConst, GenericParamImpl, GenericParamSemantic, GenericParamType,
44};
45use crate::items::imp::{
46    GeneratedImplId, GeneratedImplItems, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
47    ImplLookupContext, ImplLookupContextId, ImplSemantic, NegativeImplId, NegativeImplLongId,
48    UninferredGeneratedImplId, UninferredGeneratedImplLongId, UninferredImpl,
49};
50use crate::items::trt::{
51    ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId, ConcreteTraitTypeId,
52    ConcreteTraitTypeLongId,
53};
54use crate::path::ContextualizePath;
55use crate::substitution::{GenericSubstitution, HasDb, RewriteResult, SemanticRewriter};
56use crate::types::{
57    ClosureTypeLongId, ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId,
58    ImplTypeId, get_impl_at_context,
59};
60use crate::{
61    ConcreteEnumId, ConcreteExternTypeId, ConcreteFunction, ConcreteImplId, ConcreteImplLongId,
62    ConcreteStructId, ConcreteTraitId, ConcreteTraitLongId, ConcreteTypeId, ConcreteVariant,
63    FunctionId, FunctionLongId, GenericArgumentId, GenericParam, LocalVariable, MatchArmSelector,
64    Member, Parameter, SemanticObject, Signature, TypeId, TypeLongId, ValueSelectorArm,
65    add_basic_rewrites, add_expr_rewrites, add_rewrite, semantic_object_for_id,
66};
67
68pub mod canonic;
69pub mod conform;
70pub mod infers;
71pub mod solver;
72
73/// A type variable, created when a generic type argument is not passed, and thus is not known
74/// yet and needs to be inferred.
75#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HeapSize, salsa::SalsaValue)]
76pub struct TypeVar<'db> {
77    pub inference_id: InferenceId<'db>,
78    pub id: LocalTypeVarId,
79}
80
81/// A const variable, created when a generic const argument is not passed, and thus is not known
82/// yet and needs to be inferred.
83#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HeapSize, salsa::SalsaValue)]
84pub struct ConstVar<'db> {
85    pub inference_id: InferenceId<'db>,
86    pub id: LocalConstVarId,
87}
88
89/// An id for an inference context. Each inference variable is associated with an inference id.
90#[derive(
91    Copy,
92    Clone,
93    Debug,
94    PartialEq,
95    Eq,
96    Hash,
97    DebugWithDb,
98    SemanticObject,
99    HeapSize,
100    salsa::SalsaValue,
101)]
102#[debug_db(dyn Database)]
103pub enum InferenceId<'db> {
104    LookupItemDeclaration(LookupItemId<'db>),
105    LookupItemGenerics(LookupItemId<'db>),
106    LookupItemDefinition(LookupItemId<'db>),
107    ImplDefTrait(ImplDefId<'db>),
108    ImplAliasImplDef(ImplAliasId<'db>),
109    GenericParam(GenericParamId<'db>),
110    GenericImplParamTrait(GenericParamId<'db>),
111    GlobalUseStar(GlobalUseId<'db>),
112    MacroCall(MacroCallId<'db>),
113    Canonical,
114    /// For resolving that will not be used anywhere in the semantic model.
115    NoContext,
116}
117
118/// An impl variable, created when a generic type argument is not passed, and thus is not known
119/// yet and needs to be inferred.
120#[derive(
121    Clone, Debug, PartialEq, Eq, Hash, DebugWithDb, SemanticObject, HeapSize, salsa::SalsaValue,
122)]
123#[debug_db(dyn Database)]
124pub struct ImplVar<'db> {
125    pub inference_id: InferenceId<'db>,
126    #[dont_rewrite]
127    pub id: LocalImplVarId,
128    pub concrete_trait_id: ConcreteTraitId<'db>,
129    #[dont_rewrite]
130    pub lookup_context: ImplLookupContextId<'db>,
131}
132impl<'db> ImplVar<'db> {
133    pub fn intern(&self, db: &'db dyn Database) -> ImplVarId<'db> {
134        self.clone().intern(db)
135    }
136}
137
138/// A negative impl variable.
139#[derive(
140    Clone, Debug, PartialEq, Eq, Hash, DebugWithDb, SemanticObject, HeapSize, salsa::SalsaValue,
141)]
142#[debug_db(dyn Database)]
143pub struct NegativeImplVar<'db> {
144    pub inference_id: InferenceId<'db>,
145    #[dont_rewrite]
146    pub id: LocalNegativeImplVarId,
147    pub concrete_trait_id: ConcreteTraitId<'db>,
148    #[dont_rewrite]
149    pub lookup_context: ImplLookupContextId<'db>,
150}
151
152#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, SemanticObject, HeapSize, salsa::SalsaValue)]
153pub struct LocalTypeVarId(pub usize);
154#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, SemanticObject, HeapSize, salsa::SalsaValue)]
155pub struct LocalImplVarId(pub usize);
156
157#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, SemanticObject, HeapSize, salsa::SalsaValue)]
158pub struct LocalNegativeImplVarId(pub usize);
159
160#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, SemanticObject, HeapSize, salsa::SalsaValue)]
161pub struct LocalConstVarId(pub usize);
162
163define_short_id!(ImplVarId, ImplVar<'db>);
164impl<'db> ImplVarId<'db> {
165    pub fn id(&self, db: &dyn Database) -> LocalImplVarId {
166        self.long(db).id
167    }
168    pub fn concrete_trait_id(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
169        self.long(db).concrete_trait_id
170    }
171    pub fn lookup_context(&self, db: &'db dyn Database) -> ImplLookupContextId<'db> {
172        self.long(db).lookup_context
173    }
174}
175semantic_object_for_id!(ImplVarId, ImplVar<'a>);
176
177define_short_id!(NegativeImplVarId, NegativeImplVar<'db>);
178impl<'db> NegativeImplVarId<'db> {
179    pub fn id(&self, db: &dyn Database) -> LocalNegativeImplVarId {
180        self.long(db).id
181    }
182    pub fn concrete_trait_id(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
183        self.long(db).concrete_trait_id
184    }
185    pub fn lookup_context(&self, db: &'db dyn Database) -> ImplLookupContextId<'db> {
186        self.long(db).lookup_context
187    }
188}
189semantic_object_for_id!(NegativeImplVarId, NegativeImplVar<'a>);
190
191#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, SemanticObject, salsa::SalsaValue)]
192pub enum InferenceVar {
193    Type(LocalTypeVarId),
194    Const(LocalConstVarId),
195    Impl(LocalImplVarId),
196    NegativeImpl(LocalNegativeImplVarId),
197}
198
199// TODO(spapini): Add to diagnostics.
200#[derive(Clone, Debug, Eq, Hash, PartialEq, DebugWithDb, salsa::SalsaValue)]
201#[debug_db(dyn Database)]
202pub enum InferenceError<'db> {
203    /// An inference error wrapping a previously reported error.
204    Reported(DiagnosticAdded),
205    Cycle(InferenceVar),
206    TypeKindMismatch {
207        ty0: TypeId<'db>,
208        ty1: TypeId<'db>,
209    },
210    ConstKindMismatch {
211        const0: ConstValueId<'db>,
212        const1: ConstValueId<'db>,
213    },
214    ImplKindMismatch {
215        impl0: ImplId<'db>,
216        impl1: ImplId<'db>,
217    },
218    NegativeImplKindMismatch {
219        impl0: NegativeImplId<'db>,
220        impl1: NegativeImplId<'db>,
221    },
222    GenericArgMismatch {
223        garg0: GenericArgumentId<'db>,
224        garg1: GenericArgumentId<'db>,
225    },
226    TraitMismatch {
227        trt0: TraitId<'db>,
228        trt1: TraitId<'db>,
229    },
230    ImplTypeMismatch {
231        impl_id: ImplId<'db>,
232        trait_type_id: TraitTypeId<'db>,
233        ty0: TypeId<'db>,
234        ty1: TypeId<'db>,
235    },
236    GenericFunctionMismatch {
237        func0: GenericFunctionId<'db>,
238        func1: GenericFunctionId<'db>,
239    },
240    ConstNotInferred,
241    // TODO(spapini): These are only used for external interface. Separate them along with the
242    // finalize() function to a wrapper.
243    NoImplsFound(ConcreteTraitId<'db>),
244    NoNegativeImplsFound(ConcreteTraitId<'db>),
245    Ambiguity(Ambiguity<'db>),
246    TypeNotInferred(TypeId<'db>),
247    /// A numeric literal was bound to a type that does not accept numeric literals.
248    InvalidLiteralType(TypeId<'db>),
249}
250impl<'db> InferenceError<'db> {
251    pub fn format(&self, db: &dyn Database, context_module: ModuleId<'db>) -> String {
252        match self {
253            InferenceError::Reported(_) => "Inference error occurred.".into(),
254            InferenceError::Cycle(_var) => "Inference cycle detected".into(),
255            InferenceError::TypeKindMismatch { ty0, ty1 } => {
256                format!(
257                    "Type mismatch: `{}` and `{}`.",
258                    ty0.contextualized_path(db, context_module),
259                    ty1.contextualized_path(db, context_module)
260                )
261            }
262            InferenceError::ConstKindMismatch { const0, const1 } => {
263                format!(
264                    "Const mismatch: `{}` and `{}`.",
265                    const0.contextualized_path(db, context_module),
266                    const1.contextualized_path(db, context_module)
267                )
268            }
269            InferenceError::ImplKindMismatch { impl0, impl1 } => {
270                format!(
271                    "Impl mismatch: `{}` and `{}`.",
272                    impl0.contextualized_path(db, context_module),
273                    impl1.contextualized_path(db, context_module)
274                )
275            }
276            InferenceError::NegativeImplKindMismatch { impl0, impl1 } => {
277                format!(
278                    "Negative impl mismatch: `{:?}` and `{:?}`.",
279                    impl0.debug(db),
280                    impl1.debug(db)
281                )
282            }
283            InferenceError::GenericArgMismatch { garg0, garg1 } => {
284                format!(
285                    "Generic arg mismatch: `{}` and `{}`.",
286                    garg0.contextualized_path(db, context_module),
287                    garg1.contextualized_path(db, context_module)
288                )
289            }
290            InferenceError::TraitMismatch { trt0, trt1 } => {
291                format!(
292                    "Trait mismatch: `{}` and `{}`.",
293                    trt0.contextualized_path(db, context_module),
294                    trt1.contextualized_path(db, context_module)
295                )
296            }
297            InferenceError::ConstNotInferred => "Failed to infer constant.".into(),
298            InferenceError::NoImplsFound(concrete_trait_id) => {
299                if concrete_trait_id.trait_id(db) == db.core_info().string_literal_trt {
300                    let generic_type = extract_matches!(
301                        concrete_trait_id.generic_args(db)[0],
302                        GenericArgumentId::Type
303                    );
304                    return format!(
305                        "Mismatched types. The type `{}` cannot be created from a string literal.",
306                        generic_type.contextualized_path(db, context_module)
307                    );
308                }
309                format!(
310                    "Trait has no implementation in context: {}.",
311                    concrete_trait_id.contextualized_path(db, context_module)
312                )
313            }
314            InferenceError::NoNegativeImplsFound(concrete_trait_id) => {
315                format!(
316                    "Trait has implementation in context: {}.",
317                    concrete_trait_id.contextualized_path(db, context_module)
318                )
319            }
320            InferenceError::Ambiguity(ambiguity) => ambiguity.format(db, context_module),
321            InferenceError::TypeNotInferred(ty) => {
322                format!(
323                    "Type annotations needed. Failed to infer {}.",
324                    ty.contextualized_path(db, context_module)
325                )
326            }
327            InferenceError::GenericFunctionMismatch { func0, func1 } => {
328                format!(
329                    "Function mismatch: `{}` and `{}`.",
330                    func0.contextualized_path(db, context_module),
331                    func1.contextualized_path(db, context_module)
332                )
333            }
334            InferenceError::ImplTypeMismatch { impl_id, trait_type_id, ty0, ty1 } => {
335                format!(
336                    "`{}::{}` type mismatch: `{}` and `{}`.",
337                    impl_id.contextualized_path(db, context_module),
338                    trait_type_id.name(db).long(db),
339                    ty0.contextualized_path(db, context_module),
340                    ty1.contextualized_path(db, context_module)
341                )
342            }
343            InferenceError::InvalidLiteralType(ty) => format!(
344                "Mismatched types. The type `{}` cannot be created from a numeric literal.",
345                ty.contextualized_path(db, context_module),
346            ),
347        }
348    }
349}
350
351impl<'db> InferenceError<'db> {
352    pub fn report(
353        &self,
354        diagnostics: &mut SemanticDiagnostics<'db>,
355        stable_ptr: SyntaxStablePtrId<'db>,
356    ) -> DiagnosticAdded {
357        match self {
358            InferenceError::Reported(diagnostic_added) => *diagnostic_added,
359            _ => diagnostics
360                .report(stable_ptr, SemanticDiagnosticKind::InternalInferenceError(self.clone())),
361        }
362    }
363}
364
365/// This struct is used to ensure that when an inference error occurs, it is properly set in the
366/// `Inference` object, and then properly consumed.
367///
368/// It must not be constructed directly. Instead, it is returned by [Inference::set_error].
369#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
370pub struct ErrorSet;
371
372pub type InferenceResult<T> = Result<T, ErrorSet>;
373
374#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::SalsaValue)]
375enum InferenceErrorStatus<'db> {
376    /// There is a pending error.
377    Pending(PendingInferenceError<'db>),
378    /// There was an error but it was already consumed.
379    Consumed(DiagnosticAdded),
380}
381
382/// A pending inference error.
383#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::SalsaValue)]
384struct PendingInferenceError<'db> {
385    /// The actual error.
386    err: InferenceError<'db>,
387    /// The optional location of the error.
388    stable_ptr: Option<SyntaxStablePtrId<'db>>,
389}
390
391/// A mapping of an impl var's trait items to concrete items.
392#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, SemanticObject, salsa::SalsaValue)]
393pub struct ImplVarTraitItemMappings<'db> {
394    /// The trait types of the impl var.
395    types: OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>,
396    /// The trait constants of the impl var.
397    constants: OrderedHashMap<TraitConstantId<'db>, ConstValueId<'db>>,
398    /// The trait impls of the impl var.
399    impls: OrderedHashMap<TraitImplId<'db>, ImplId<'db>>,
400}
401
402impl ImplVarTraitItemMappings<'_> {
403    /// Returns `true` if the impl var has no mappings.
404    pub fn is_empty(&self) -> bool {
405        self.types.is_empty() && self.constants.is_empty() && self.impls.is_empty()
406    }
407}
408
409/// State of inference.
410#[derive(Debug, DebugWithDb, PartialEq, Eq, salsa::SalsaValue)]
411#[debug_db(dyn Database)]
412pub struct InferenceData<'db> {
413    pub inference_id: InferenceId<'db>,
414    /// Current inferred assignment for type variables.
415    pub type_assignment: OrderedHashMap<LocalTypeVarId, TypeId<'db>>,
416    /// Current inferred assignment for const variables.
417    pub const_assignment: OrderedHashMap<LocalConstVarId, ConstValueId<'db>>,
418    /// Current inferred assignment for impl variables.
419    pub impl_assignment: OrderedHashMap<LocalImplVarId, ImplId<'db>>,
420    /// Current inferred assignment for negative impl variables.
421    pub negative_impl_assignment: OrderedHashMap<LocalNegativeImplVarId, NegativeImplId<'db>>,
422    /// Unsolved impl variables mapping to a maps of trait items to a corresponding item variable.
423    /// Upon solution of the trait conforms the fully known item to the variable.
424    pub impl_vars_trait_item_mappings: HashMap<LocalImplVarId, ImplVarTraitItemMappings<'db>>,
425    /// Type variables.
426    pub type_vars: Vec<TypeVar<'db>>,
427    /// Type variables that represent deferred concrete integer types from numeric literals
428    /// (`TypeLongId::NumericLiteral`). At finalization, any of these that remain unassigned are
429    /// defaulted to `felt252`.
430    pub integer_literal_vars: Vec<LocalTypeVarId>,
431    /// Const variables.
432    pub const_vars: Vec<ConstVar<'db>>,
433    /// Impl variables.
434    pub impl_vars: Vec<ImplVar<'db>>,
435    /// Negative impl variables.
436    pub negative_impl_vars: Vec<NegativeImplVar<'db>>,
437    /// Mapping from variables to stable pointers, if exist.
438    pub stable_ptrs: HashMap<InferenceVar, SyntaxStablePtrId<'db>>,
439    /// Inference variables that are pending to be solved.
440    pending: Deque<LocalImplVarId>,
441    /// Inference negative variables that are pending to be solved.
442    negative_pending: Deque<LocalNegativeImplVarId>,
443    /// Inference variables that have been refuted - no solutions exist.
444    refuted: Vec<LocalImplVarId>,
445    /// Inference negative variables that have been refuted - no solutions exist.
446    negative_refuted: Vec<LocalNegativeImplVarId>,
447    /// Inference variables that have been solved.
448    solved: Vec<LocalImplVarId>,
449    /// Inference variables that are currently ambiguous. May be solved later.
450    ambiguous: Vec<(LocalImplVarId, Ambiguity<'db>)>,
451    /// Negative impl inference variables that are currently ambiguous. May be solved later.
452    negative_ambiguous: Vec<(LocalNegativeImplVarId, Ambiguity<'db>)>,
453    /// Mapping from impl types to type variables.
454    pub impl_type_bounds: Arc<OrderedHashMap<ImplTypeId<'db>, TypeId<'db>>>,
455
456    /// The current error status.
457    error_status: Result<(), InferenceErrorStatus<'db>>,
458}
459impl<'db> InferenceData<'db> {
460    pub fn new(inference_id: InferenceId<'db>) -> Self {
461        Self {
462            inference_id,
463            type_assignment: OrderedHashMap::default(),
464            impl_assignment: OrderedHashMap::default(),
465            const_assignment: OrderedHashMap::default(),
466            negative_impl_assignment: OrderedHashMap::default(),
467            impl_vars_trait_item_mappings: HashMap::new(),
468            type_vars: Vec::new(),
469            integer_literal_vars: Vec::new(),
470            impl_vars: Vec::new(),
471            const_vars: Vec::new(),
472            negative_impl_vars: Vec::new(),
473            stable_ptrs: HashMap::new(),
474            pending: Deque::new(),
475            negative_pending: Deque::new(),
476            refuted: Vec::new(),
477            negative_refuted: Vec::new(),
478            solved: Vec::new(),
479            ambiguous: Vec::new(),
480            negative_ambiguous: Vec::new(),
481            impl_type_bounds: Default::default(),
482            error_status: Ok(()),
483        }
484    }
485    pub fn inference<'r>(&'r mut self, db: &'db dyn Database) -> Inference<'db, 'r> {
486        Inference::new(db, self)
487    }
488    pub fn clone_with_inference_id(
489        &self,
490        db: &'db dyn Database,
491        inference_id: InferenceId<'db>,
492    ) -> InferenceData<'db> {
493        let mut inference_id_replacer =
494            InferenceIdReplacer::new(db, self.inference_id, inference_id);
495        Self {
496            inference_id,
497            type_assignment: self
498                .type_assignment
499                .iter()
500                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
501                .collect(),
502            const_assignment: self
503                .const_assignment
504                .iter()
505                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
506                .collect(),
507            impl_assignment: self
508                .impl_assignment
509                .iter()
510                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
511                .collect(),
512            negative_impl_assignment: self
513                .negative_impl_assignment
514                .iter()
515                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
516                .collect(),
517            impl_vars_trait_item_mappings: self
518                .impl_vars_trait_item_mappings
519                .iter()
520                .map(|(k, mappings)| {
521                    (
522                        *k,
523                        ImplVarTraitItemMappings {
524                            types: mappings
525                                .types
526                                .iter()
527                                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
528                                .collect(),
529                            constants: mappings
530                                .constants
531                                .iter()
532                                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
533                                .collect(),
534                            impls: mappings
535                                .impls
536                                .iter()
537                                .map(|(k, v)| (*k, inference_id_replacer.rewrite(*v).no_err()))
538                                .collect(),
539                        },
540                    )
541                })
542                .collect(),
543            type_vars: inference_id_replacer.rewrite(self.type_vars.clone()).no_err(),
544            integer_literal_vars: self.integer_literal_vars.clone(),
545            const_vars: inference_id_replacer.rewrite(self.const_vars.clone()).no_err(),
546            impl_vars: inference_id_replacer.rewrite(self.impl_vars.clone()).no_err(),
547            negative_impl_vars: inference_id_replacer
548                .rewrite(self.negative_impl_vars.clone())
549                .no_err(),
550            stable_ptrs: self.stable_ptrs.clone(),
551            pending: inference_id_replacer.rewrite(self.pending.clone()).no_err(),
552            negative_pending: inference_id_replacer.rewrite(self.negative_pending.clone()).no_err(),
553            refuted: inference_id_replacer.rewrite(self.refuted.clone()).no_err(),
554            negative_refuted: inference_id_replacer.rewrite(self.negative_refuted.clone()).no_err(),
555            solved: inference_id_replacer.rewrite(self.solved.clone()).no_err(),
556            ambiguous: inference_id_replacer.rewrite(self.ambiguous.clone()).no_err(),
557            negative_ambiguous: inference_id_replacer
558                .rewrite(self.negative_ambiguous.clone())
559                .no_err(),
560            // we do not need to rewrite the impl type bounds, as they all should be var free.
561            impl_type_bounds: self.impl_type_bounds.clone(),
562
563            error_status: self.error_status.clone(),
564        }
565    }
566    pub fn temporary_clone(&self) -> InferenceData<'db> {
567        Self {
568            inference_id: self.inference_id,
569            type_assignment: self.type_assignment.clone(),
570            const_assignment: self.const_assignment.clone(),
571            impl_assignment: self.impl_assignment.clone(),
572            negative_impl_assignment: self.negative_impl_assignment.clone(),
573            impl_vars_trait_item_mappings: self.impl_vars_trait_item_mappings.clone(),
574            type_vars: self.type_vars.clone(),
575            integer_literal_vars: self.integer_literal_vars.clone(),
576            const_vars: self.const_vars.clone(),
577            impl_vars: self.impl_vars.clone(),
578            negative_impl_vars: self.negative_impl_vars.clone(),
579            stable_ptrs: self.stable_ptrs.clone(),
580            pending: self.pending.clone(),
581            negative_pending: self.negative_pending.clone(),
582            refuted: self.refuted.clone(),
583            negative_refuted: self.negative_refuted.clone(),
584            solved: self.solved.clone(),
585            ambiguous: self.ambiguous.clone(),
586            negative_ambiguous: self.negative_ambiguous.clone(),
587            impl_type_bounds: self.impl_type_bounds.clone(),
588            error_status: self.error_status.clone(),
589        }
590    }
591}
592
593/// State of inference. A system of inference constraints.
594pub struct Inference<'db, 'id> {
595    db: &'db dyn Database,
596    pub data: &'id mut InferenceData<'db>,
597}
598
599impl<'db, 'id> Deref for Inference<'db, 'id> {
600    type Target = InferenceData<'db>;
601
602    fn deref(&self) -> &Self::Target {
603        self.data
604    }
605}
606impl DerefMut for Inference<'_, '_> {
607    fn deref_mut(&mut self) -> &mut Self::Target {
608        self.data
609    }
610}
611
612impl std::fmt::Debug for Inference<'_, '_> {
613    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
614        let x = self.data.debug(self.db);
615        write!(f, "{x:?}")
616    }
617}
618
619impl<'db, 'id> Inference<'db, 'id> {
620    fn new(db: &'db dyn Database, data: &'id mut InferenceData<'db>) -> Self {
621        Self { db, data }
622    }
623
624    /// Getter for an [ImplVar].
625    fn impl_var(&self, var_id: LocalImplVarId) -> &ImplVar<'db> {
626        &self.impl_vars[var_id.0]
627    }
628
629    /// Getter for an impl var assignment.
630    pub fn impl_assignment(&self, var_id: LocalImplVarId) -> Option<ImplId<'db>> {
631        self.impl_assignment.get(&var_id).copied()
632    }
633
634    /// Getter for a [NegativeImplVar].
635    fn negative_impl_var(&self, var_id: LocalNegativeImplVarId) -> &NegativeImplVar<'db> {
636        &self.negative_impl_vars[var_id.0]
637    }
638
639    /// Getter for a negative impl var assignment.
640    pub fn negative_impl_assignment(
641        &self,
642        var_id: LocalNegativeImplVarId,
643    ) -> Option<NegativeImplId<'db>> {
644        self.negative_impl_assignment.get(&var_id).copied()
645    }
646
647    /// Getter for a type var assignment.
648    fn type_assignment(&self, var_id: LocalTypeVarId) -> Option<TypeId<'db>> {
649        self.type_assignment.get(&var_id).copied()
650    }
651
652    /// Allocates a new [TypeVar] for an unknown type that needs to be inferred.
653    /// Returns a wrapping TypeId.
654    pub fn new_type_var(&mut self, stable_ptr: Option<SyntaxStablePtrId<'db>>) -> TypeId<'db> {
655        let var = self.new_type_var_raw(stable_ptr);
656
657        TypeLongId::Var(var).intern(self.db)
658    }
659
660    /// Allocates a new [TypeVar] wrapped in a [`TypeLongId::NumericLiteral`] placeholder for a
661    /// numeric literal whose type is not yet known. The synthetic-impl machinery treats this
662    /// placeholder as satisfying `Drop`/`Copy`/`Destruct`/`PanicDestruct`, and finalization
663    /// defaults any still-unbound variant to `felt252`.
664    pub fn new_integer_literal_type(
665        &mut self,
666        stable_ptr: Option<SyntaxStablePtrId<'db>>,
667    ) -> TypeId<'db> {
668        let var = self.new_type_var_raw(stable_ptr);
669        self.data.integer_literal_vars.push(var.id);
670        TypeLongId::NumericLiteral(var).intern(self.db)
671    }
672
673    /// Allocates a new [TypeVar] for an unknown type that needs to be inferred.
674    /// Returns the variable id.
675    pub fn new_type_var_raw(&mut self, stable_ptr: Option<SyntaxStablePtrId<'db>>) -> TypeVar<'db> {
676        let var =
677            TypeVar { inference_id: self.inference_id, id: LocalTypeVarId(self.type_vars.len()) };
678        if let Some(stable_ptr) = stable_ptr {
679            self.stable_ptrs.insert(InferenceVar::Type(var.id), stable_ptr);
680        }
681        self.type_vars.push(var);
682        var
683    }
684
685    /// Sets the inference's impl type bounds to the given map, and rewrites the types so all the
686    /// types are var free.
687    pub fn set_impl_type_bounds(
688        &mut self,
689        impl_type_bounds: OrderedHashMap<ImplTypeId<'db>, TypeId<'db>>,
690    ) {
691        let impl_type_bounds_finalized = impl_type_bounds
692            .iter()
693            .filter_map(|(impl_type, ty)| {
694                let rewritten_type = self.rewrite(ty.long(self.db).clone()).no_err();
695                if !matches!(rewritten_type, TypeLongId::Var(_) | TypeLongId::NumericLiteral(_)) {
696                    return Some((*impl_type, rewritten_type.intern(self.db)));
697                }
698                // conformed the var type to the original impl type to remove it from the pending
699                // list.
700                self.conform_ty(*ty, TypeLongId::ImplType(*impl_type).intern(self.db)).ok();
701                None
702            })
703            .collect();
704
705        self.data.impl_type_bounds = Arc::new(impl_type_bounds_finalized);
706    }
707
708    /// Allocates a new [ConstVar] for an unknown const that needs to be inferred.
709    /// Returns a wrapping [ConstValueId].
710    pub fn new_const_var(
711        &mut self,
712        stable_ptr: Option<SyntaxStablePtrId<'db>>,
713        ty: TypeId<'db>,
714    ) -> ConstValueId<'db> {
715        let var = self.new_const_var_raw(stable_ptr);
716        ConstValue::Var(var, ty).intern(self.db)
717    }
718
719    /// Allocates a new [ConstVar] for an unknown type that needs to be inferred.
720    /// Returns the variable id.
721    pub fn new_const_var_raw(
722        &mut self,
723        stable_ptr: Option<SyntaxStablePtrId<'db>>,
724    ) -> ConstVar<'db> {
725        let var = ConstVar {
726            inference_id: self.inference_id,
727            id: LocalConstVarId(self.const_vars.len()),
728        };
729        if let Some(stable_ptr) = stable_ptr {
730            self.stable_ptrs.insert(InferenceVar::Const(var.id), stable_ptr);
731        }
732        self.const_vars.push(var);
733        var
734    }
735
736    /// Allocates a new [ImplVar] for an unknown type that needs to be inferred.
737    /// Returns a wrapping ImplId.
738    pub fn new_impl_var(
739        &mut self,
740        concrete_trait_id: ConcreteTraitId<'db>,
741        stable_ptr: Option<SyntaxStablePtrId<'db>>,
742        lookup_context: ImplLookupContextId<'db>,
743    ) -> ImplId<'db> {
744        let var = self.new_impl_var_raw(lookup_context, concrete_trait_id, stable_ptr);
745        ImplLongId::ImplVar(self.impl_var(var).intern(self.db)).intern(self.db)
746    }
747
748    /// Allocates a new [ImplVar] for an unknown impl that needs to be inferred.
749    /// Returns the variable id.
750    fn new_impl_var_raw(
751        &mut self,
752        lookup_context: ImplLookupContextId<'db>,
753        concrete_trait_id: ConcreteTraitId<'db>,
754        stable_ptr: Option<SyntaxStablePtrId<'db>>,
755    ) -> LocalImplVarId {
756        let id = LocalImplVarId(self.impl_vars.len());
757        if let Some(stable_ptr) = stable_ptr {
758            self.stable_ptrs.insert(InferenceVar::Impl(id), stable_ptr);
759        }
760        let var =
761            ImplVar { inference_id: self.inference_id, id, concrete_trait_id, lookup_context };
762        self.impl_vars.push(var);
763        self.pending.push_back(id);
764        id
765    }
766
767    /// Allocates a new [NegativeImplVar] for an unknown negative impl that needs to be inferred.
768    /// Returns a wrapping NegativeImplId.
769    pub fn new_negative_impl_var(
770        &mut self,
771        concrete_trait_id: ConcreteTraitId<'db>,
772        stable_ptr: Option<SyntaxStablePtrId<'db>>,
773        lookup_context: ImplLookupContextId<'db>,
774    ) -> NegativeImplId<'db> {
775        let var = self.new_negative_impl_var_raw(lookup_context, concrete_trait_id, stable_ptr);
776        NegativeImplLongId::NegativeImplVar(self.negative_impl_var(var).clone().intern(self.db))
777            .intern(self.db)
778    }
779
780    /// Allocates a new [NegativeImplVar] for an unknown type that needs to be inferred.
781    /// Returns the variable id.
782    fn new_negative_impl_var_raw(
783        &mut self,
784        lookup_context: ImplLookupContextId<'db>,
785        concrete_trait_id: ConcreteTraitId<'db>,
786        stable_ptr: Option<SyntaxStablePtrId<'db>>,
787    ) -> LocalNegativeImplVarId {
788        let id = LocalNegativeImplVarId(self.negative_impl_vars.len());
789        if let Some(stable_ptr) = stable_ptr {
790            self.stable_ptrs.insert(InferenceVar::NegativeImpl(id), stable_ptr);
791        }
792        let var = NegativeImplVar {
793            inference_id: self.inference_id,
794            id,
795            concrete_trait_id,
796            lookup_context,
797        };
798        self.negative_impl_vars.push(var);
799        self.negative_pending.push_back(id);
800        id
801    }
802
803    /// Solves the inference system. After a successful solve, there are no more pending impl
804    /// inferences.
805    /// Returns whether the inference was successful. If not, the error may be found by
806    /// `.error_state()`.
807    pub fn solve(&mut self) -> InferenceResult<()> {
808        let ambiguous = std::mem::take(&mut self.ambiguous).into_iter();
809        self.pending.extend(ambiguous.map(|(var, _)| var));
810        while let Some(var) = self.pending.pop_front() {
811            // First inference error stops inference.
812            self.solve_single_pending(var).inspect_err(|_err_set| {
813                self.add_error_stable_ptr(InferenceVar::Impl(var));
814            })?;
815        }
816        while let Some(var) = self.negative_pending.pop_front() {
817            // First inference error stops inference.
818            self.solve_single_negative_pending(var).inspect_err(|_err_set| {
819                self.add_error_stable_ptr(InferenceVar::NegativeImpl(var));
820            })?;
821        }
822        Ok(())
823    }
824
825    fn solve_single_pending(&mut self, var: LocalImplVarId) -> InferenceResult<()> {
826        if self.impl_assignment.contains_key(&var) {
827            return Ok(());
828        }
829        let solution = match self.impl_var_solution_set(var)? {
830            SolutionSet::None => {
831                self.refuted.push(var);
832                return Ok(());
833            }
834            SolutionSet::Ambiguous(ambiguity) => {
835                self.ambiguous.push((var, ambiguity));
836                return Ok(());
837            }
838            SolutionSet::Unique(solution) => solution,
839        };
840
841        // Solution found. Assign it.
842        self.assign_local_impl(var, solution)?;
843
844        // Something changed.
845        self.solved.push(var);
846        let ambiguous = std::mem::take(&mut self.ambiguous).into_iter();
847        self.pending.extend(ambiguous.map(|(var, _)| var));
848
849        let negative_ambiguous = std::mem::take(&mut self.negative_ambiguous).into_iter();
850        self.negative_pending.extend(negative_ambiguous.map(|(var, _)| var));
851
852        Ok(())
853    }
854
855    /// Solves a single negative impl pending variable.
856    fn solve_single_negative_pending(
857        &mut self,
858        var: LocalNegativeImplVarId,
859    ) -> InferenceResult<()> {
860        if self.negative_impl_assignment.contains_key(&var) {
861            return Ok(());
862        }
863
864        let solution = match self.negative_impl_var_solution_set(var)? {
865            SolutionSet::None => {
866                self.negative_refuted.push(var);
867                return Ok(());
868            }
869            SolutionSet::Ambiguous(ambiguity) => {
870                self.negative_ambiguous.push((var, ambiguity));
871                return Ok(());
872            }
873            SolutionSet::Unique(solution) => solution,
874        };
875
876        // Solution found. Assign it.
877        self.assign_local_negative_impl(var, solution)?;
878
879        Ok(())
880    }
881
882    /// Returns the solution set status for the inference:
883    /// Whether there is a unique solution, multiple solutions, no solutions or an error.
884    pub fn solution_set(&mut self) -> InferenceResult<SolutionSet<'db, ()>> {
885        self.solve()?;
886        if !self.refuted.is_empty() {
887            return Ok(SolutionSet::None);
888        }
889        if !self.negative_refuted.is_empty() {
890            return Ok(SolutionSet::None);
891        }
892        if let Some((_, ambiguity)) = self.ambiguous.first() {
893            return Ok(SolutionSet::Ambiguous(ambiguity.clone()));
894        }
895        if let Some((_, ambiguity)) = self.negative_ambiguous.first() {
896            return Ok(SolutionSet::Ambiguous(ambiguity.clone()));
897        }
898        assert!(self.pending.is_empty(), "solution() called on an unsolved solver");
899        assert!(self.negative_pending.is_empty(), "solution() called on an unsolved solver");
900        Ok(SolutionSet::Unique(()))
901    }
902
903    /// Finalizes the inference by inferring uninferred numeric literals as felt252.
904    /// Returns an error and does not report it.
905    pub fn finalize_without_reporting(&mut self) -> Result<(), ErrorSet> {
906        if self.error_status.is_err() {
907            return Err(ErrorSet);
908        }
909        let felt_ty = self.db.core_info().felt252;
910
911        // Default any still-unbound `NumericLiteral` type variables to `felt252`. We do this one
912        // var at a time and re-solve between each, mirroring the old behavior for
913        // `NumericLiteral<Var>`: defaulting the first literal can constrain other literals
914        // through trait resolution (e.g., `0.pow(0)` — defaulting the receiver lets `Pow<T, Exp>`
915        // resolve, which then constrains the exponent to `usize`, avoiding a felt252 default for
916        // the second literal).
917        loop {
918            self.solve()?;
919            let mut changed = false;
920            for var_id in self.data.integer_literal_vars.clone() {
921                if self.type_assignment.contains_key(&var_id) {
922                    continue;
923                }
924                let var = self.type_vars[var_id.0];
925                let placeholder = TypeLongId::NumericLiteral(var).intern(self.db);
926                if self.rewrite(placeholder).no_err() == felt_ty {
927                    continue;
928                }
929                self.conform_ty(placeholder, felt_ty).inspect_err(|_err_set| {
930                    self.add_error_stable_ptr(InferenceVar::Type(var_id));
931                })?;
932                changed = true;
933                break;
934            }
935            if !changed {
936                break;
937            }
938        }
939        assert!(
940            self.pending.is_empty(),
941            "pending should all be solved by this point. Guaranteed by solve()."
942        );
943
944        // Defensive backstop: every invalid `IntegerLiteral` binding should already have been
945        // caught at conform-time by `bind_integer_literal`.
946        for var_id in self.data.integer_literal_vars.clone() {
947            let Some(bound) = self.type_assignment.get(&var_id).copied() else {
948                continue;
949            };
950            let bound = self.rewrite(bound).no_err();
951            if !bound.is_var_free(self.db) || is_valid_literal_type(self.db, bound) {
952                continue;
953            }
954            let err = self.set_error(InferenceError::InvalidLiteralType(bound));
955            self.add_error_stable_ptr(InferenceVar::Type(var_id));
956            return Err(err);
957        }
958
959        // Persist rewriter substitutions of synthetic `NumericLiteral`-over-mem-trait
960        // `GeneratedImpl`s into `impl_assignment` so subsequent queries see the natural impl.
961        let assignments: Vec<_> = self.impl_assignment.iter().map(|(k, v)| (*k, *v)).collect();
962        for (var_id, impl_id) in assignments {
963            let rewritten = self.rewrite(impl_id).no_err();
964            if rewritten != impl_id {
965                self.impl_assignment.insert(var_id, rewritten);
966            }
967        }
968
969        let Some((var, err)) = self.first_undetermined_variable() else {
970            return Ok(());
971        };
972        Err(self.set_error_on_var(err, var))
973    }
974
975    /// Finalizes the inference and report diagnostics if there are any errors.
976    /// All the remaining type vars are mapped to the `missing` type, to prevent additional
977    /// diagnostics.
978    pub fn finalize<'m>(
979        &'m mut self,
980        diagnostics: &mut SemanticDiagnostics<'db>,
981        stable_ptr: SyntaxStablePtrId<'db>,
982    ) {
983        if let Err(err_set) = self.finalize_without_reporting() {
984            let diag = self.report_on_pending_error(err_set, diagnostics, stable_ptr);
985
986            let ty_missing = TypeId::missing(self.db, diag);
987            for var in &self.data.type_vars {
988                self.data.type_assignment.entry(var.id).or_insert(ty_missing);
989            }
990        }
991    }
992
993    /// Retrieves the first variable that is still not inferred, or None, if everything is
994    /// inferred.
995    /// Does not set the error but return it, which is ok as this is a private helper function.
996    fn first_undetermined_variable(&mut self) -> Option<(InferenceVar, InferenceError<'db>)> {
997        if let Some(var) = self.refuted.first().copied() {
998            let impl_var = self.impl_var(var).clone();
999            let concrete_trait_id = impl_var.concrete_trait_id;
1000            let concrete_trait_id = self.rewrite(concrete_trait_id).no_err();
1001            return Some((
1002                InferenceVar::Impl(var),
1003                InferenceError::NoImplsFound(concrete_trait_id),
1004            ));
1005        }
1006        if let Some(var) = self.negative_refuted.first().copied() {
1007            let negative_impl_var = self.negative_impl_var(var).clone();
1008            let concrete_trait_id = negative_impl_var.concrete_trait_id;
1009            let concrete_trait_id = self.rewrite(concrete_trait_id).no_err();
1010            return Some((
1011                InferenceVar::NegativeImpl(var),
1012                InferenceError::NoNegativeImplsFound(concrete_trait_id),
1013            ));
1014        }
1015
1016        let mut fallback_ret = None;
1017        if let Some((var, ambiguity)) = self.ambiguous.first() {
1018            // Note: do not rewrite `ambiguity`, since it is expressed in canonical variables.
1019            let ret =
1020                Some((InferenceVar::Impl(*var), InferenceError::Ambiguity(ambiguity.clone())));
1021            if !matches!(ambiguity, Ambiguity::WillNotInfer(_)) {
1022                return ret;
1023            } else {
1024                fallback_ret = ret;
1025            }
1026        }
1027        if let Some((var, ambiguity)) = self.negative_ambiguous.first() {
1028            let ret = Some((
1029                InferenceVar::NegativeImpl(*var),
1030                InferenceError::Ambiguity(ambiguity.clone()),
1031            ));
1032            if !matches!(ambiguity, Ambiguity::WillNotInfer(_)) {
1033                return ret;
1034            } else {
1035                fallback_ret = ret;
1036            }
1037        }
1038        for (id, var) in self.type_vars.iter().enumerate() {
1039            if self.type_assignment(LocalTypeVarId(id)).is_none() {
1040                let ty = TypeLongId::Var(*var).intern(self.db);
1041                return Some((InferenceVar::Type(var.id), InferenceError::TypeNotInferred(ty)));
1042            }
1043        }
1044        for (id, var) in self.const_vars.iter().enumerate() {
1045            if !self.const_assignment.contains_key(&LocalConstVarId(id)) {
1046                let infernence_var = InferenceVar::Const(var.id);
1047                return Some((infernence_var, InferenceError::ConstNotInferred));
1048            }
1049        }
1050        fallback_ret
1051    }
1052
1053    /// Assigns a value to a local impl variable id. See assign_impl().
1054    fn assign_local_impl(
1055        &mut self,
1056        var: LocalImplVarId,
1057        impl_id: ImplId<'db>,
1058    ) -> InferenceResult<ImplId<'db>> {
1059        let concrete_trait = impl_id
1060            .concrete_trait(self.db)
1061            .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1062        self.conform_traits(self.impl_var(var).concrete_trait_id, concrete_trait)?;
1063        if let Some(other_impl) = self.impl_assignment(var) {
1064            return self.conform_impl(impl_id, other_impl);
1065        }
1066        if !impl_id.is_var_free(self.db) && self.impl_contains_var(impl_id, InferenceVar::Impl(var))
1067        {
1068            let inference_var = InferenceVar::Impl(var);
1069            return Err(self.set_error_on_var(InferenceError::Cycle(inference_var), inference_var));
1070        }
1071        self.impl_assignment.insert(var, impl_id);
1072        if let Some(mappings) = self.impl_vars_trait_item_mappings.remove(&var) {
1073            for (trait_type_id, ty) in mappings.types {
1074                let impl_ty = self
1075                    .db
1076                    .impl_type_concrete_implized(ImplTypeId::new(impl_id, trait_type_id, self.db))
1077                    .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1078                if let Err(err_set) = self.conform_ty(ty, impl_ty) {
1079                    // Override the error with ImplTypeMismatch.
1080                    let ty0 = self.rewrite(ty).no_err();
1081                    let ty1 = self.rewrite(impl_ty).no_err();
1082
1083                    let err = InferenceError::ImplTypeMismatch { impl_id, trait_type_id, ty0, ty1 };
1084                    self.error_status = Err(InferenceErrorStatus::Pending(PendingInferenceError {
1085                        err,
1086                        stable_ptr: self.stable_ptrs.get(&InferenceVar::Impl(var)).cloned(),
1087                    }));
1088                    return Err(err_set);
1089                }
1090            }
1091            for (trait_constant, constant_id) in mappings.constants {
1092                let concrete_impl_constant = self
1093                    .db
1094                    .impl_constant_concrete_implized_value(ImplConstantId::new(
1095                        impl_id,
1096                        trait_constant,
1097                        self.db,
1098                    ))
1099                    .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1100                self.conform_const(constant_id, concrete_impl_constant)?;
1101            }
1102            for (trait_impl, inner_impl_id) in mappings.impls {
1103                let concrete_impl_impl = self
1104                    .db
1105                    .impl_impl_concrete_implized(ImplImplId::new(impl_id, trait_impl, self.db))
1106                    .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1107                self.conform_impl(inner_impl_id, concrete_impl_impl)?;
1108            }
1109        }
1110        Ok(impl_id)
1111    }
1112
1113    /// Tries to assigns value to an [ImplVarId]. Return the assigned impl, or an error.
1114    fn assign_impl(
1115        &mut self,
1116        var_id: ImplVarId<'db>,
1117        impl_id: ImplId<'db>,
1118    ) -> InferenceResult<ImplId<'db>> {
1119        let var = var_id.long(self.db);
1120        if var.inference_id != self.inference_id {
1121            return Err(self.set_error(InferenceError::ImplKindMismatch {
1122                impl0: ImplLongId::ImplVar(var_id).intern(self.db),
1123                impl1: impl_id,
1124            }));
1125        }
1126        self.assign_local_impl(var.id, impl_id)
1127    }
1128
1129    /// Assigns a value to a local negative impl variable id. See assign_neg_impl().
1130    fn assign_local_negative_impl(
1131        &mut self,
1132        var: LocalNegativeImplVarId,
1133        neg_impl_id: NegativeImplId<'db>,
1134    ) -> InferenceResult<NegativeImplId<'db>> {
1135        let concrete_trait = neg_impl_id
1136            .concrete_trait(self.db)
1137            .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1138        self.conform_traits(self.negative_impl_var(var).concrete_trait_id, concrete_trait)?;
1139        if let Some(other_impl) = self.negative_impl_assignment(var) {
1140            return self.conform_neg_impl(neg_impl_id, other_impl);
1141        }
1142        if !neg_impl_id.is_var_free(self.db)
1143            && self.negative_impl_contains_var(neg_impl_id, InferenceVar::NegativeImpl(var))
1144        {
1145            return Err(self.set_error(InferenceError::Cycle(InferenceVar::NegativeImpl(var))));
1146        }
1147        self.negative_impl_assignment.insert(var, neg_impl_id);
1148        Ok(neg_impl_id)
1149    }
1150
1151    /// Tries to assigns value to an [NegativeImplVarId]. Return the assigned negative impl, or an
1152    /// error.
1153    fn assign_neg_impl(
1154        &mut self,
1155        var_id: NegativeImplVarId<'db>,
1156        neg_impl_id: NegativeImplId<'db>,
1157    ) -> InferenceResult<NegativeImplId<'db>> {
1158        let var = var_id.long(self.db);
1159        if var.inference_id != self.inference_id {
1160            return Err(self.set_error(InferenceError::NegativeImplKindMismatch {
1161                impl0: NegativeImplLongId::NegativeImplVar(var_id).intern(self.db),
1162                impl1: neg_impl_id,
1163            }));
1164        }
1165        self.assign_local_negative_impl(var.id, neg_impl_id)
1166    }
1167
1168    /// Assigns a value to a [TypeVar]. Return the assigned type, or an error.
1169    /// Assumes the variable is not already assigned.
1170    fn assign_ty(&mut self, var: TypeVar<'db>, ty: TypeId<'db>) -> InferenceResult<TypeId<'db>> {
1171        if var.inference_id != self.inference_id {
1172            return Err(self.set_error(InferenceError::TypeKindMismatch {
1173                ty0: TypeLongId::Var(var).intern(self.db),
1174                ty1: ty,
1175            }));
1176        }
1177        assert!(!self.type_assignment.contains_key(&var.id), "Cannot reassign variable.");
1178        let inference_var = InferenceVar::Type(var.id);
1179        if !ty.is_var_free(self.db) && self.ty_contains_var(ty, inference_var) {
1180            return Err(self.set_error_on_var(InferenceError::Cycle(inference_var), inference_var));
1181        }
1182        // If assigning var to var - making sure assigning to the lower id for proper canonization.
1183        if let TypeLongId::Var(other) = ty.long(self.db)
1184            && other.inference_id == self.inference_id
1185            && other.id.0 > var.id.0
1186        {
1187            let var_ty = TypeLongId::Var(var).intern(self.db);
1188            self.type_assignment.insert(other.id, var_ty);
1189            return Ok(var_ty);
1190        }
1191        self.type_assignment.insert(var.id, ty);
1192        Ok(ty)
1193    }
1194
1195    /// Assigns a value to a [ConstVar]. Return the assigned const, or an error.
1196    /// Assumes the variable is not already assigned.
1197    fn assign_const(
1198        &mut self,
1199        var: ConstVar<'db>,
1200        id: ConstValueId<'db>,
1201    ) -> InferenceResult<ConstValueId<'db>> {
1202        if var.inference_id != self.inference_id {
1203            return Err(self.set_error(InferenceError::ConstKindMismatch {
1204                const0: ConstValue::Var(var, TypeId::missing(self.db, skip_diagnostic()))
1205                    .intern(self.db),
1206                const1: id,
1207            }));
1208        }
1209
1210        self.const_assignment.insert(var.id, id);
1211        Ok(id)
1212    }
1213
1214    /// Computes the solution set for an impl variable with a recursive query.
1215    fn impl_var_solution_set(
1216        &mut self,
1217        var: LocalImplVarId,
1218    ) -> InferenceResult<SolutionSet<'db, ImplId<'db>>> {
1219        let impl_var = self.impl_var(var).clone();
1220        // Update the concrete trait of the impl var.
1221        let concrete_trait_id = self.rewrite(impl_var.concrete_trait_id).no_err();
1222        self.impl_vars[impl_var.id.0].concrete_trait_id = concrete_trait_id;
1223        let impl_var_trait_item_mappings =
1224            self.impl_vars_trait_item_mappings.get(&var).cloned().unwrap_or_default();
1225        let solution_set = self.trait_solution_set(
1226            concrete_trait_id,
1227            impl_var_trait_item_mappings,
1228            impl_var.lookup_context,
1229        )?;
1230        Ok(match solution_set {
1231            SolutionSet::None => SolutionSet::None,
1232            SolutionSet::Unique((canonical_impl, canonicalizer)) => {
1233                SolutionSet::Unique(canonical_impl.embed(self, &canonicalizer))
1234            }
1235            SolutionSet::Ambiguous(ambiguity) => SolutionSet::Ambiguous(ambiguity),
1236        })
1237    }
1238
1239    /// Computes the solution set for a negative impl variable with a recursive query.
1240    fn negative_impl_var_solution_set(
1241        &mut self,
1242        var: LocalNegativeImplVarId,
1243    ) -> InferenceResult<SolutionSet<'db, NegativeImplId<'db>>> {
1244        let negative_impl_var = self.negative_impl_var(var).clone();
1245        let concrete_trait_id = self.rewrite(negative_impl_var.concrete_trait_id).no_err();
1246
1247        let solution_set =
1248            self.validate_no_solution_set(concrete_trait_id, negative_impl_var.lookup_context)?;
1249        Ok(match solution_set {
1250            SolutionSet::Unique(concrete_trait_id) => {
1251                SolutionSet::Unique(NegativeImplLongId::Solved(concrete_trait_id).intern(self.db))
1252            }
1253            SolutionSet::Ambiguous(ambiguity) => SolutionSet::Ambiguous(ambiguity),
1254            SolutionSet::None => SolutionSet::None,
1255        })
1256    }
1257
1258    /// Validates that no solution set is found for the negative impls.
1259    fn validate_no_solution_set(
1260        &mut self,
1261        concrete_trait_id: ConcreteTraitId<'db>,
1262        lookup_context: ImplLookupContextId<'db>,
1263    ) -> InferenceResult<SolutionSet<'db, ConcreteTraitId<'db>>> {
1264        for negative_impl in &lookup_context.long(self.db).negative_impls {
1265            let generic_param = self
1266                .db
1267                .generic_param_semantic(*negative_impl)
1268                .map_err(|diag_added| self.set_error(InferenceError::Reported(diag_added)))?;
1269            if let GenericParam::NegImpl(neg_impl) = generic_param
1270                && Ok(concrete_trait_id) == neg_impl.concrete_trait
1271            {
1272                return Ok(SolutionSet::Unique(concrete_trait_id));
1273            }
1274        }
1275
1276        let generic_args = concrete_trait_id.generic_args(self.db);
1277        // Defer if the generic argument contains inference variables, with special handling for
1278        // closures. Closures can only have one type even if not var-free, so they
1279        // don't cause ambiguity.
1280        if generic_args.iter().any(|garg| {
1281            matches!(
1282                garg,
1283                GenericArgumentId::Type(ty)
1284                if !matches!(
1285                    ty.long(self.db),
1286                    TypeLongId::Closure(_) | TypeLongId::NumericLiteral(_)
1287                )
1288                && !ty.is_var_free(self.db)
1289            )
1290        }) {
1291            return Ok(SolutionSet::Ambiguous(Ambiguity::WillNotInfer(concrete_trait_id)));
1292        }
1293
1294        let mut neg_impl_generic_params = OrderedHashSet::default();
1295        let mut visited_types = OrderedHashSet::default();
1296        for garg in generic_args {
1297            if garg
1298                .extract_generic_params(self.db, &mut neg_impl_generic_params, &mut visited_types)
1299                .is_err()
1300            {
1301                return Ok(SolutionSet::Ambiguous(
1302                    Ambiguity::NegativeImplWithUnsupportedExtractedArgs(*garg),
1303                ));
1304            }
1305        }
1306
1307        let solution_set = if neg_impl_generic_params.is_empty() {
1308            self.trait_solution_set(
1309                concrete_trait_id,
1310                ImplVarTraitItemMappings::default(),
1311                lookup_context,
1312            )?
1313        } else {
1314            let mut substitution: OrderedHashMap<GenericParamId<'db>, GenericArgumentId<'db>> =
1315                Default::default();
1316
1317            for param in neg_impl_generic_params {
1318                let garg = match param.kind(self.db) {
1319                    GenericKind::Type => GenericArgumentId::Type(
1320                        self.new_type_var(Some(param.stable_ptr(self.db).untyped())),
1321                    ),
1322                    GenericKind::Const | GenericKind::Impl | GenericKind::NegImpl => {
1323                        return Ok(SolutionSet::Ambiguous(
1324                            Ambiguity::NegativeImplWithUnsupportedGenericParam(param),
1325                        ));
1326                    }
1327                };
1328
1329                substitution.insert(param, garg);
1330            }
1331            let rewritten_concrete_trait_id =
1332                GenericSubstitution { param_to_arg: substitution.clone(), self_impl: None }
1333                    .substitute(self.db, concrete_trait_id)
1334                    .unwrap();
1335
1336            let solution_set = self.trait_solution_set(
1337                rewritten_concrete_trait_id,
1338                ImplVarTraitItemMappings::default(),
1339                lookup_context,
1340            )?;
1341
1342            // Assign the newly created type variables with their corresponding generic parameters.
1343            // This step prevents leaving type variables unresolved.
1344            let db = self.db;
1345            for (generic_param, garg) in substitution {
1346                let GenericArgumentId::Type(ty) = garg else {
1347                    panic!("Expected a type variable");
1348                };
1349                let (TypeLongId::Var(var) | TypeLongId::NumericLiteral(var)) = ty.long(self.db)
1350                else {
1351                    panic!("Expected a type variable");
1352                };
1353                self.type_assignment
1354                    .entry(var.id)
1355                    .or_insert_with(|| TypeLongId::GenericParameter(generic_param).intern(db));
1356            }
1357
1358            solution_set
1359        };
1360
1361        if !matches!(solution_set, SolutionSet::None) {
1362            return Ok(SolutionSet::None);
1363        }
1364
1365        Ok(SolutionSet::Unique(concrete_trait_id))
1366    }
1367
1368    /// Computes the solution set for a trait with a recursive query.
1369    pub fn trait_solution_set(
1370        &mut self,
1371        concrete_trait_id: ConcreteTraitId<'db>,
1372        impl_var_trait_item_mappings: ImplVarTraitItemMappings<'db>,
1373        lookup_context_id: ImplLookupContextId<'db>,
1374    ) -> InferenceResult<SolutionSet<'db, (CanonicalImpl<'db>, CanonicalMapping<'db>)>> {
1375        let impl_var_trait_item_mappings = self.rewrite(impl_var_trait_item_mappings).no_err();
1376        // TODO(spapini): This is done twice. Consider doing it only here.
1377        let concrete_trait_id = self.rewrite(concrete_trait_id).no_err();
1378        let lookup_context = lookup_context_id.enriched(self.db, concrete_trait_id);
1379
1380        // Don't try to resolve impls if the first generic param is a variable.
1381        let generic_args = concrete_trait_id.generic_args(self.db);
1382        match generic_args.first() {
1383            Some(GenericArgumentId::Type(ty)) => {
1384                if let TypeLongId::Var(_) = ty.long(self.db) {
1385                    // Don't try to infer such impls.
1386                    return Ok(SolutionSet::Ambiguous(Ambiguity::WillNotInfer(concrete_trait_id)));
1387                }
1388            }
1389            Some(GenericArgumentId::Impl(imp)) => {
1390                // Don't try to infer such impls.
1391                if let ImplLongId::ImplVar(_) = imp.long(self.db) {
1392                    return Ok(SolutionSet::Ambiguous(Ambiguity::WillNotInfer(concrete_trait_id)));
1393                }
1394            }
1395            Some(GenericArgumentId::Constant(const_value)) => {
1396                if let ConstValue::Var(_, _) = const_value.long(self.db) {
1397                    // Don't try to infer such impls.
1398                    return Ok(SolutionSet::Ambiguous(Ambiguity::WillNotInfer(concrete_trait_id)));
1399                }
1400            }
1401            _ => {}
1402        };
1403        let (canonical_trait, canonicalizer) = CanonicalTrait::canonicalize(
1404            self.db,
1405            self.inference_id,
1406            concrete_trait_id,
1407            impl_var_trait_item_mappings,
1408        );
1409        // impl_type_bounds order is determined by the generic params of the function and therefore
1410        // is consistent.
1411        let solution_set = match self.db.canonic_trait_solutions(
1412            canonical_trait,
1413            lookup_context,
1414            (*self.data.impl_type_bounds).clone(),
1415        ) {
1416            Ok(solution_set) => solution_set,
1417            Err(err) => return Err(self.set_error(err)),
1418        };
1419        match solution_set {
1420            SolutionSet::None => Ok(SolutionSet::None),
1421            SolutionSet::Unique(canonical_impl) => {
1422                Ok(SolutionSet::Unique((canonical_impl, canonicalizer)))
1423            }
1424            SolutionSet::Ambiguous(ambiguity) => Ok(SolutionSet::Ambiguous(ambiguity)),
1425        }
1426    }
1427
1428    // Error handling methods
1429    // ======================
1430
1431    /// Sets an error in the inference state.
1432    /// Does nothing if an error is already set.
1433    /// Returns an `ErrorSet` that can be used in reporting the error.
1434    pub fn set_error(&mut self, err: InferenceError<'db>) -> ErrorSet {
1435        self.set_error_ex(err, None)
1436    }
1437
1438    /// Sets an error in the inference state, with an optional location for the diagnostics
1439    /// reporting. Does nothing if an error is already set.
1440    /// Returns an `ErrorSet` that can be used in reporting the error.
1441    pub fn set_error_ex(
1442        &mut self,
1443        err: InferenceError<'db>,
1444        stable_ptr: Option<SyntaxStablePtrId<'db>>,
1445    ) -> ErrorSet {
1446        if self.error_status.is_err() {
1447            return ErrorSet;
1448        }
1449        self.error_status = Err(if let InferenceError::Reported(diag_added) = err {
1450            InferenceErrorStatus::Consumed(diag_added)
1451        } else {
1452            InferenceErrorStatus::Pending(PendingInferenceError { err, stable_ptr })
1453        });
1454        ErrorSet
1455    }
1456
1457    /// Sets an error in the inference state, with a var to fetch location for the diagnostics
1458    /// reporting. Does nothing if an error is already set.
1459    /// Returns an `ErrorSet` that can be used in reporting the error.
1460    pub fn set_error_on_var(&mut self, err: InferenceError<'db>, var: InferenceVar) -> ErrorSet {
1461        self.set_error_ex(err, self.stable_ptrs.get(&var).cloned())
1462    }
1463
1464    /// Returns whether an error is set (either pending or consumed).
1465    pub fn is_error_set(&self) -> InferenceResult<()> {
1466        self.error_status.as_ref().copied().map_err(|_| ErrorSet)
1467    }
1468
1469    /// If there is no stable ptr for the pending error, add it by the given var.
1470    fn add_error_stable_ptr(&mut self, var: InferenceVar) {
1471        let var_stable_ptr = self.stable_ptrs.get(&var).copied();
1472        if let Err(InferenceErrorStatus::Pending(PendingInferenceError { err: _, stable_ptr })) =
1473            &mut self.error_status
1474            && stable_ptr.is_none()
1475        {
1476            *stable_ptr = var_stable_ptr;
1477        }
1478    }
1479
1480    /// Consumes the error but doesn't report it. If there is no error, or the error is consumed,
1481    /// returns None. This should be used with caution. Always prefer to use
1482    /// (1) `report_on_pending_error` if possible, or (2) `consume_reported_error` which is safer.
1483    ///
1484    /// Gets an `ErrorSet` to "enforce" it is only called when an error is set.
1485    pub fn consume_error_without_reporting(
1486        &mut self,
1487        err_set: ErrorSet,
1488    ) -> Option<InferenceError<'db>> {
1489        Some(self.consume_error_inner(err_set, skip_diagnostic())?.err)
1490    }
1491
1492    /// Consumes the error that is already reported. If there is no error, or the error is consumed,
1493    /// does nothing. This should be used with caution. Always prefer to use
1494    /// `report_on_pending_error` if possible.
1495    ///
1496    /// Gets an `ErrorSet` to "enforce" it is only called when an error is set.
1497    /// Gets an `DiagnosticAdded` to "enforce" it is only called when a diagnostic was reported.
1498    pub fn consume_reported_error(&mut self, err_set: ErrorSet, diag_added: DiagnosticAdded) {
1499        self.consume_error_inner(err_set, diag_added);
1500    }
1501
1502    /// Consumes the error and returns it, but doesn't report it. If there is no error, or the error
1503    /// is already consumed, returns None. This should be used with caution. Always prefer to use
1504    /// `report_on_pending_error` if possible.
1505    ///
1506    /// Gets an `ErrorSet` to "enforce" it is only called when an error is set.
1507    /// Gets an `DiagnosticAdded` to "enforce" it is only called when a diagnostic was reported.
1508    fn consume_error_inner(
1509        &mut self,
1510        _err_set: ErrorSet,
1511        diag_added: DiagnosticAdded,
1512    ) -> Option<PendingInferenceError<'db>> {
1513        match &mut self.error_status {
1514            Err(InferenceErrorStatus::Pending(error)) => {
1515                let pending_error = std::mem::replace(
1516                    error,
1517                    PendingInferenceError {
1518                        err: InferenceError::Reported(diag_added),
1519                        stable_ptr: None,
1520                    },
1521                );
1522                self.error_status = Err(InferenceErrorStatus::Consumed(diag_added));
1523                Some(pending_error)
1524            }
1525            // TODO(orizi): `panic!("consume_error when there is no pending error")` instead.
1526            _ => None,
1527        }
1528    }
1529
1530    /// Consumes the pending error, if any, and reports it.
1531    /// Should only be called when an error is set, otherwise it panics.
1532    /// Gets an `ErrorSet` to "enforce" it is only called when an error is set.
1533    /// If an error was set but it's already consumed, it doesn't report it again but returns the
1534    /// stored `DiagnosticAdded`.
1535    pub fn report_on_pending_error(
1536        &mut self,
1537        _err_set: ErrorSet,
1538        diagnostics: &mut SemanticDiagnostics<'db>,
1539        stable_ptr: SyntaxStablePtrId<'db>,
1540    ) -> DiagnosticAdded {
1541        let Err(state_error) = &self.error_status else {
1542            panic!("report_on_pending_error should be called only on error");
1543        };
1544        match state_error {
1545            InferenceErrorStatus::Consumed(diag_added) => *diag_added,
1546            InferenceErrorStatus::Pending(pending) => {
1547                let diag_added = match &pending.err {
1548                    InferenceError::TypeNotInferred(_) if diagnostics.error_count > 0 => {
1549                        // If we have other diagnostics, there is no need to TypeNotInferred.
1550
1551                        // Note that `diagnostics` is not empty, so it is safe to return
1552                        // 'DiagnosticAdded' here.
1553                        skip_diagnostic()
1554                    }
1555                    diag => diag.report(diagnostics, pending.stable_ptr.unwrap_or(stable_ptr)),
1556                };
1557                self.error_status = Err(InferenceErrorStatus::Consumed(diag_added));
1558                diag_added
1559            }
1560        }
1561    }
1562
1563    /// If the current status is of a pending error, reports an alternative diagnostic, by calling
1564    /// `report`, and consumes the error. Otherwise, does nothing.
1565    pub fn report_modified_if_pending(
1566        &mut self,
1567        err_set: ErrorSet,
1568        report: impl FnOnce() -> DiagnosticAdded,
1569    ) {
1570        if matches!(self.error_status, Err(InferenceErrorStatus::Pending { .. })) {
1571            self.consume_reported_error(err_set, report());
1572        }
1573    }
1574}
1575
1576impl<'a, 'mt> HasDb<&'a dyn Database> for Inference<'a, 'mt> {
1577    fn get_db(&self) -> &'a dyn Database {
1578        self.db
1579    }
1580}
1581add_basic_rewrites!(<'a, 'mt>, Inference<'a, 'mt>, NoError, @exclude TypeLongId TypeId ImplLongId ImplId ConstValue NegativeImplLongId NegativeImplId);
1582add_expr_rewrites!(<'a, 'mt>, Inference<'a, 'mt>, NoError, @exclude);
1583add_rewrite!(<'a, 'mt>, Inference<'a, 'mt>, NoError, Ambiguity<'a>);
1584impl<'db, 'mt> SemanticRewriter<TypeId<'db>, NoError> for Inference<'db, 'mt> {
1585    fn internal_rewrite(&mut self, value: &mut TypeId<'db>) -> Result<RewriteResult, NoError> {
1586        if value.is_var_free(self.db) {
1587            return Ok(RewriteResult::NoChange);
1588        }
1589        value.default_rewrite(self)
1590    }
1591}
1592impl<'db, 'mt> SemanticRewriter<ImplId<'db>, NoError> for Inference<'db, 'mt> {
1593    fn internal_rewrite(&mut self, value: &mut ImplId<'db>) -> Result<RewriteResult, NoError> {
1594        if value.is_var_free(self.db) {
1595            return Ok(RewriteResult::NoChange);
1596        }
1597        value.default_rewrite(self)
1598    }
1599}
1600impl<'db, 'mt> SemanticRewriter<NegativeImplId<'db>, NoError> for Inference<'db, 'mt> {
1601    fn internal_rewrite(
1602        &mut self,
1603        value: &mut NegativeImplId<'db>,
1604    ) -> Result<RewriteResult, NoError> {
1605        if value.is_var_free(self.db) {
1606            return Ok(RewriteResult::NoChange);
1607        }
1608        value.default_rewrite(self)
1609    }
1610}
1611
1612impl<'db, 'mt> SemanticRewriter<TypeLongId<'db>, NoError> for Inference<'db, 'mt> {
1613    fn internal_rewrite(&mut self, value: &mut TypeLongId<'db>) -> Result<RewriteResult, NoError> {
1614        match value {
1615            TypeLongId::Var(var) | TypeLongId::NumericLiteral(var) => {
1616                if let Some(type_id) = self.type_assignment.get(&var.id) {
1617                    let mut long_type_id = type_id.long(self.db).clone();
1618                    if let RewriteResult::Modified = self.internal_rewrite(&mut long_type_id)? {
1619                        *self.type_assignment.get_mut(&var.id).unwrap() =
1620                            long_type_id.clone().intern(self.db);
1621                    }
1622                    *value = long_type_id;
1623                    return Ok(RewriteResult::Modified);
1624                }
1625            }
1626            TypeLongId::ImplType(impl_type_id) => {
1627                if let Some(type_id) = self.impl_type_bounds.get(impl_type_id) {
1628                    *value = type_id.long(self.db).clone();
1629                    self.internal_rewrite(value)?;
1630                    return Ok(RewriteResult::Modified);
1631                }
1632                let impl_type_id_rewrite_result = self.internal_rewrite(impl_type_id)?;
1633                let impl_id = impl_type_id.impl_id();
1634                let trait_ty = impl_type_id.ty();
1635                return Ok(match impl_id.long(self.db) {
1636                    ImplLongId::GenericParameter(_)
1637                    | ImplLongId::SelfImpl(_)
1638                    | ImplLongId::ImplImpl(_) => impl_type_id_rewrite_result,
1639                    ImplLongId::Concrete(_) => {
1640                        if let Ok(ty) = self.db.impl_type_concrete_implized(ImplTypeId::new(
1641                            impl_id, trait_ty, self.db,
1642                        )) {
1643                            *value = self.rewrite(ty).no_err().long(self.db).clone();
1644                            RewriteResult::Modified
1645                        } else {
1646                            impl_type_id_rewrite_result
1647                        }
1648                    }
1649                    ImplLongId::ImplVar(var) => {
1650                        *value = self.rewritten_impl_type(*var, trait_ty).long(self.db).clone();
1651                        return Ok(RewriteResult::Modified);
1652                    }
1653                    ImplLongId::GeneratedImpl(generated) => {
1654                        *value = self
1655                            .rewrite(
1656                                *generated
1657                                    .long(self.db)
1658                                    .impl_items
1659                                    .0
1660                                    .get(&impl_type_id.ty())
1661                                    .unwrap(),
1662                            )
1663                            .no_err()
1664                            .long(self.db)
1665                            .clone();
1666                        RewriteResult::Modified
1667                    }
1668                });
1669            }
1670            _ => {}
1671        }
1672        value.default_rewrite(self)
1673    }
1674}
1675impl<'db, 'mt> SemanticRewriter<ConstValue<'db>, NoError> for Inference<'db, 'mt> {
1676    fn internal_rewrite(&mut self, value: &mut ConstValue<'db>) -> Result<RewriteResult, NoError> {
1677        match value {
1678            ConstValue::Var(var, _) => {
1679                return Ok(if let Some(const_value_id) = self.const_assignment.get(&var.id) {
1680                    let mut const_value = const_value_id.long(self.db).clone();
1681                    if let RewriteResult::Modified = self.internal_rewrite(&mut const_value)? {
1682                        *self.const_assignment.get_mut(&var.id).unwrap() =
1683                            const_value.clone().intern(self.db);
1684                    }
1685                    *value = const_value;
1686                    RewriteResult::Modified
1687                } else {
1688                    RewriteResult::NoChange
1689                });
1690            }
1691            ConstValue::ImplConstant(impl_constant_id) => {
1692                let impl_constant_id_rewrite_result = self.internal_rewrite(impl_constant_id)?;
1693                let impl_id = impl_constant_id.impl_id();
1694                let trait_constant = impl_constant_id.trait_constant_id();
1695                return Ok(match impl_id.long(self.db) {
1696                    ImplLongId::GenericParameter(_)
1697                    | ImplLongId::SelfImpl(_)
1698                    | ImplLongId::GeneratedImpl(_)
1699                    | ImplLongId::ImplImpl(_) => impl_constant_id_rewrite_result,
1700                    ImplLongId::Concrete(_) => {
1701                        if let Ok(constant) = self.db.impl_constant_concrete_implized_value(
1702                            ImplConstantId::new(impl_id, trait_constant, self.db),
1703                        ) {
1704                            *value = self.rewrite(constant).no_err().long(self.db).clone();
1705                            RewriteResult::Modified
1706                        } else {
1707                            impl_constant_id_rewrite_result
1708                        }
1709                    }
1710                    ImplLongId::ImplVar(var) => {
1711                        *value = self
1712                            .rewritten_impl_constant(*var, trait_constant)
1713                            .long(self.db)
1714                            .clone();
1715                        return Ok(RewriteResult::Modified);
1716                    }
1717                });
1718            }
1719            _ => {}
1720        }
1721        value.default_rewrite(self)
1722    }
1723}
1724impl<'db, 'mt> SemanticRewriter<ImplLongId<'db>, NoError> for Inference<'db, 'mt> {
1725    fn internal_rewrite(&mut self, value: &mut ImplLongId<'db>) -> Result<RewriteResult, NoError> {
1726        match value {
1727            ImplLongId::ImplVar(var) => {
1728                let long_id = var.long(self.db);
1729                // Relax the candidates.
1730                let impl_var_id = long_id.id;
1731                if let Some(impl_id) = self.impl_assignment(impl_var_id) {
1732                    let mut long_impl_id = impl_id.long(self.db).clone();
1733                    if let RewriteResult::Modified = self.internal_rewrite(&mut long_impl_id)? {
1734                        *self.impl_assignment.get_mut(&impl_var_id).unwrap() =
1735                            long_impl_id.clone().intern(self.db);
1736                    }
1737                    *value = long_impl_id;
1738                    return Ok(RewriteResult::Modified);
1739                }
1740            }
1741            ImplLongId::GeneratedImpl(generated) => {
1742                // Recurse into the generated impl's fields first so the inner type is rewritten.
1743                let inner_result = generated.default_rewrite(self)?;
1744                let concrete_trait = generated.concrete_trait(self.db);
1745                if let Some(GenericArgumentId::Type(first_ty)) =
1746                    concrete_trait.generic_args(self.db).first().copied()
1747                    && !matches!(
1748                        first_ty.long(self.db),
1749                        TypeLongId::Closure(_)
1750                            | TypeLongId::Var(_)
1751                            | TypeLongId::NumericLiteral(_)
1752                            | TypeLongId::ImplType(_)
1753                    )
1754                {
1755                    let info = self.db.core_info();
1756                    let trait_id = concrete_trait.trait_id(self.db);
1757                    if [info.drop_trt, info.copy_trt, info.destruct_trt, info.panic_destruct_trt]
1758                        .contains(&trait_id)
1759                    {
1760                        // The synthetic NumericLiteral candidate produced this GeneratedImpl;
1761                        // now that the inner type is concrete, replace it with the natural impl.
1762                        let lookup_context =
1763                            ImplLookupContext::new_from_type(first_ty, self.db).intern(self.db);
1764                        if let Ok(real_impl) =
1765                            get_impl_at_context(self.db, lookup_context, concrete_trait, None)
1766                        {
1767                            *value = real_impl.long(self.db).clone();
1768                            return Ok(RewriteResult::Modified);
1769                        }
1770                    }
1771                }
1772                return Ok(inner_result);
1773            }
1774            ImplLongId::ImplImpl(impl_impl_id) => {
1775                let impl_impl_id_rewrite_result = self.internal_rewrite(impl_impl_id)?;
1776                let impl_id = impl_impl_id.impl_id();
1777                return Ok(match impl_id.long(self.db) {
1778                    ImplLongId::GenericParameter(_)
1779                    | ImplLongId::SelfImpl(_)
1780                    | ImplLongId::GeneratedImpl(_)
1781                    | ImplLongId::ImplImpl(_) => impl_impl_id_rewrite_result,
1782                    ImplLongId::Concrete(_) => {
1783                        if let Ok(imp) = self.db.impl_impl_concrete_implized(*impl_impl_id) {
1784                            *value = self.rewrite(imp).no_err().long(self.db).clone();
1785                            RewriteResult::Modified
1786                        } else {
1787                            impl_impl_id_rewrite_result
1788                        }
1789                    }
1790                    ImplLongId::ImplVar(var) => {
1791                        if let Ok(concrete_trait_impl) =
1792                            impl_impl_id.concrete_trait_impl_id(self.db)
1793                        {
1794                            *value = self
1795                                .rewritten_impl_impl(*var, concrete_trait_impl)
1796                                .long(self.db)
1797                                .clone();
1798                            return Ok(RewriteResult::Modified);
1799                        } else {
1800                            impl_impl_id_rewrite_result
1801                        }
1802                    }
1803                });
1804            }
1805
1806            _ => {}
1807        }
1808        if value.is_var_free(self.db) {
1809            return Ok(RewriteResult::NoChange);
1810        }
1811        value.default_rewrite(self)
1812    }
1813}
1814
1815impl<'db, 'mt> SemanticRewriter<NegativeImplLongId<'db>, NoError> for Inference<'db, 'mt> {
1816    fn internal_rewrite(
1817        &mut self,
1818        value: &mut NegativeImplLongId<'db>,
1819    ) -> Result<RewriteResult, NoError> {
1820        if let NegativeImplLongId::NegativeImplVar(var) = value {
1821            let long_id = var.long(self.db);
1822            // Relax the candidates.
1823            let neg_impl_var_id = long_id.id;
1824            if let Some(impl_id) = self.negative_impl_assignment(neg_impl_var_id) {
1825                let mut long_neg_impl_id = impl_id.long(self.db).clone();
1826                if let RewriteResult::Modified = self.internal_rewrite(&mut long_neg_impl_id)? {
1827                    *self.negative_impl_assignment.get_mut(&neg_impl_var_id).unwrap() =
1828                        long_neg_impl_id.clone().intern(self.db);
1829                }
1830                *value = long_neg_impl_id;
1831                return Ok(RewriteResult::Modified);
1832            }
1833        }
1834
1835        if value.is_var_free(self.db) {
1836            return Ok(RewriteResult::NoChange);
1837        }
1838        value.default_rewrite(self)
1839    }
1840}
1841
1842struct InferenceIdReplacer<'a> {
1843    db: &'a dyn Database,
1844    from_inference_id: InferenceId<'a>,
1845    to_inference_id: InferenceId<'a>,
1846}
1847impl<'a> InferenceIdReplacer<'a> {
1848    fn new(
1849        db: &'a dyn Database,
1850        from_inference_id: InferenceId<'a>,
1851        to_inference_id: InferenceId<'a>,
1852    ) -> Self {
1853        Self { db, from_inference_id, to_inference_id }
1854    }
1855}
1856impl<'a> HasDb<&'a dyn Database> for InferenceIdReplacer<'a> {
1857    fn get_db(&self) -> &'a dyn Database {
1858        self.db
1859    }
1860}
1861add_basic_rewrites!(<'a>, InferenceIdReplacer<'a>, NoError, @exclude InferenceId);
1862add_expr_rewrites!(<'a>, InferenceIdReplacer<'a>, NoError, @exclude);
1863add_rewrite!(<'a>, InferenceIdReplacer<'a>, NoError, Ambiguity<'a>);
1864impl<'a> SemanticRewriter<InferenceId<'a>, NoError> for InferenceIdReplacer<'a> {
1865    fn internal_rewrite(&mut self, value: &mut InferenceId<'a>) -> Result<RewriteResult, NoError> {
1866        if value == &self.from_inference_id {
1867            *value = self.to_inference_id;
1868            Ok(RewriteResult::Modified)
1869        } else {
1870            Ok(RewriteResult::NoChange)
1871        }
1872    }
1873}