1use std::collections::BTreeSet;
2use std::hash::Hash;
3use std::mem;
4use std::sync::Arc;
5
6use cairo_lang_debug::DebugWithDb;
7use cairo_lang_defs::db::DefsGroup;
8use cairo_lang_defs::ids::{
9 FunctionTitleId, GenericKind, GenericParamId, GenericParamLongId, ImplAliasId,
10 ImplConstantDefId, ImplConstantDefLongId, ImplDefId, ImplFunctionId, ImplFunctionLongId,
11 ImplImplDefId, ImplImplDefLongId, ImplItemId, ImplTypeDefId, ImplTypeDefLongId,
12 LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId,
13 NamedLanguageElementLongId, TopLevelLanguageElementId, TraitConstantId, TraitFunctionId,
14 TraitId, TraitImplId, TraitTypeId, UseId,
15};
16use cairo_lang_diagnostics::{
17 DiagnosticAdded, Diagnostics, Maybe, MaybeAsRef, ToMaybe, skip_diagnostic,
18};
19use cairo_lang_filesystem::db::FilesGroup;
20use cairo_lang_filesystem::ids::{CrateId, CrateLongId, SmolStrId, Tracked, UnstableSalsaId};
21use cairo_lang_proc_macros::{DebugWithDb, HeapSize, SemanticObject};
22use cairo_lang_syntax as syntax;
23use cairo_lang_syntax::node::ast::{
24 OptionTypeClause, OptionWrappedGenericParamList, UnaryOperator,
25};
26use cairo_lang_syntax::node::helpers::GetIdentifier;
27use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
28use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
29use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
30use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
31use cairo_lang_utils::{Intern, define_short_id, extract_matches};
32use itertools::{Itertools, chain, izip};
33use salsa::Database;
34use syntax::attribute::structured::{Attribute, AttributeListStructurize};
35use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
36use syntax::node::helpers::OptionWrappedGenericParamListHelper;
37use syntax::node::ids::SyntaxStablePtrId;
38use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
39
40use super::constant::{
41 ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
42 constant_semantic_data_helper,
43};
44use super::enm::SemanticEnumEx;
45use super::feature_kind::{FeatureKind, HasFeatureKind};
46use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
47use super::functions::{
48 FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
49 forbid_inline_always_with_impl_generic_param,
50};
51use super::generics::{
52 GenericArgumentHead, GenericParamImpl, GenericParamsData, displayable_concrete,
53 generic_params_to_args, semantic_generic_params,
54};
55use super::impl_alias::{
56 ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
57 impl_alias_semantic_data_helper,
58};
59use super::trt::{
60 ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
61 ConcreteTraitImplId,
62};
63use super::type_aliases::{
64 TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
65 type_alias_semantic_data_helper,
66};
67use super::visibility::peek_visible_in;
68use super::{TraitOrImplContext, resolve_trait_path};
69use crate::corelib::{CorelibSemantic, concrete_destruct_trait, concrete_drop_trait, core_crate};
70use crate::db::get_resolver_data_options;
71use crate::diagnostic::SemanticDiagnosticKind::{self, *};
72use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
73use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
74use crate::expr::inference::canonic::ResultNoErrEx;
75use crate::expr::inference::conform::InferenceConform;
76use crate::expr::inference::infers::InferenceEmbeddings;
77use crate::expr::inference::solver::{Ambiguity, SolutionSet, enrich_lookup_context_with_ty};
78use crate::expr::inference::{
79 ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId, NegativeImplVarId,
80};
81use crate::items::function_with_body::get_implicit_precedence;
82use crate::items::functions::ImplicitPrecedence;
83use crate::items::generics::GenericParamSemantic;
84use crate::items::impl_alias::ImplAliasSemantic;
85use crate::items::implization::ImplizationSemantic;
86use crate::items::macro_call::{MacroCallSemantic, module_macro_modules};
87use crate::items::module::ModuleSemantic;
88use crate::items::structure::StructSemantic;
89use crate::items::trt::TraitSemantic;
90use crate::items::us::{SemanticUseEx, UseSemantic};
91use crate::resolve::{
92 AsSegments, ResolutionContext, ResolvedConcreteItem, ResolvedGenericItem, Resolver,
93 ResolverData,
94};
95use crate::substitution::{GenericSubstitution, SemanticRewriter};
96use crate::types::{
97 ImplTypeId, ShallowGenericArg, TypeHead, TypesSemantic, add_type_based_diagnostics,
98 get_impl_at_context, maybe_resolve_shallow_generic_arg_type, resolve_type,
99};
100use crate::{
101 ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
102 GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
103 semantic_object_for_id,
104};
105
106#[cfg(test)]
107#[path = "imp_test.rs"]
108mod test;
109
110#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
111pub struct ConcreteImplLongId<'db> {
112 pub impl_def_id: ImplDefId<'db>,
113 pub generic_args: Vec<GenericArgumentId<'db>>,
114}
115define_short_id!(ConcreteImplId, ConcreteImplLongId<'db>);
116semantic_object_for_id!(ConcreteImplId, ConcreteImplLongId<'a>);
117impl<'db> DebugWithDb<'db> for ConcreteImplLongId<'db> {
118 type Db = dyn Database;
119
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
121 write!(
122 f,
123 "{}",
124 displayable_concrete(db, &self.impl_def_id.full_path(db), &self.generic_args)
125 )
126 }
127}
128impl<'db> ConcreteImplId<'db> {
129 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
130 self.long(db).impl_def_id
131 }
132 pub fn get_impl_function(
133 &self,
134 db: &'db dyn Database,
135 function: TraitFunctionId<'db>,
136 ) -> Maybe<Option<ImplFunctionId<'db>>> {
137 db.impl_function_by_trait_function(self.impl_def_id(db), function)
138 }
139 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
140 self.impl_def_id(db).name(db)
141 }
142 pub fn full_path(&self, db: &dyn Database) -> String {
143 format!("{:?}", self.debug(db))
144 }
145 pub fn substitution(&self, db: &'db dyn Database) -> Maybe<GenericSubstitution<'db>> {
146 Ok(GenericSubstitution::from_impl(ImplLongId::Concrete(*self).intern(db)).concat(
147 GenericSubstitution::new(
148 db.impl_def_generic_params(self.impl_def_id(db))?,
149 &self.long(db).generic_args,
150 ),
151 ))
152 }
153 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
155 self.long(db)
156 .generic_args
157 .iter()
158 .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
159 }
160 pub fn is_var_free(&self, db: &dyn Database) -> bool {
162 self.long(db)
163 .generic_args
164 .iter()
165 .all(|generic_argument_id| generic_argument_id.is_var_free(db))
166 }
167}
168
169#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
172pub enum ImplLongId<'db> {
173 Concrete(ConcreteImplId<'db>),
174 GenericParameter(GenericParamId<'db>),
175 ImplVar(ImplVarId<'db>),
176 ImplImpl(ImplImplId<'db>),
177 SelfImpl(ConcreteTraitId<'db>),
178 GeneratedImpl(GeneratedImplId<'db>),
179}
180impl<'db> ImplLongId<'db> {
181 pub fn head(&self, db: &'db dyn Database) -> Option<ImplHead<'db>> {
183 Some(match self {
184 ImplLongId::Concrete(concrete) => ImplHead::Concrete(concrete.impl_def_id(db)),
185 ImplLongId::GenericParameter(_)
186 | ImplLongId::ImplVar(_)
187 | ImplLongId::ImplImpl(_)
188 | ImplLongId::SelfImpl(_)
189 | ImplLongId::GeneratedImpl(_) => {
190 return None;
191 }
192 })
193 }
194 pub fn name(&self, db: &dyn Database) -> String {
195 match self {
196 ImplLongId::Concrete(concrete_impl) => concrete_impl.name(db).to_string(db),
197 ImplLongId::GenericParameter(generic_param_impl) => {
198 generic_param_impl.name(db).map(|n| n.long(db).as_str()).unwrap_or("_").to_string()
199 }
200 ImplLongId::ImplVar(var) => {
201 format!("ImplVar({})", var.concrete_trait_id(db).full_path(db))
202 }
203 ImplLongId::ImplImpl(impl_impl) => format!(
204 "{}::{}",
205 impl_impl.impl_id().name(db),
206 db.impl_impl_concrete_trait(*impl_impl)
207 .map(|trait_impl| trait_impl.full_path(db))
208 .unwrap_or_else(|_| "_".into())
209 ),
210 ImplLongId::SelfImpl(trait_impl) => trait_impl.name(db).to_string(db),
211 ImplLongId::GeneratedImpl(generated_impl) => {
212 format!("{:?}", generated_impl.debug(db))
213 }
214 }
215 }
216 pub fn format(&self, db: &dyn Database) -> String {
217 format!("{:?}", self.debug(db))
218 }
219
220 pub fn is_var_free(&self, db: &dyn Database) -> bool {
222 match self {
223 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
224 ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id.is_var_free(db),
225 ImplLongId::GenericParameter(_) => true,
226 ImplLongId::ImplVar(_) => false,
227 ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
228 ImplLongId::GeneratedImpl(generated_impl) => {
229 generated_impl.concrete_trait(db).is_var_free(db)
230 && generated_impl
231 .long(db)
232 .impl_items
233 .0
234 .values()
235 .all(|type_id| type_id.is_var_free(db))
236 }
237 }
238 }
239
240 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
242 match self {
243 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
244 ImplLongId::GenericParameter(_) => false,
245 ImplLongId::ImplVar(_) => false,
246 ImplLongId::ImplImpl(_) | ImplLongId::SelfImpl(_) => false,
247 ImplLongId::GeneratedImpl(generated_impl) => {
248 generated_impl.concrete_trait(db).is_fully_concrete(db)
249 && generated_impl
250 .long(db)
251 .impl_items
252 .0
253 .values()
254 .all(|type_id| type_id.is_fully_concrete(db))
255 }
256 }
257 }
258}
259impl<'db> DebugWithDb<'db> for ImplLongId<'db> {
260 type Db = dyn Database;
261
262 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
263 match self {
264 ImplLongId::Concrete(concrete_impl_id) => {
265 write!(f, "{:?}", concrete_impl_id.debug(db))
266 }
267 ImplLongId::GenericParameter(param) => write!(f, "{}", param.format(db).long(db)),
268 ImplLongId::ImplVar(var) => write!(f, "?{}", var.long(db).id.0),
269 ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
270 ImplLongId::SelfImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
271 ImplLongId::GeneratedImpl(generated_impl) => {
272 write!(f, "{:?}", generated_impl.debug(db))
273 }
274 }
275 }
276}
277
278define_short_id!(ImplId, ImplLongId<'db>);
279semantic_object_for_id!(ImplId, ImplLongId<'a>);
280impl<'db> ImplId<'db> {
281 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
282 db.impl_concrete_trait(*self)
283 }
284
285 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
287 impl_is_fully_concrete(db, *self)
288 }
289
290 pub fn is_var_free(&self, db: &dyn Database) -> bool {
292 impl_is_var_free(db, *self)
293 }
294
295 pub fn head(&self, db: &'db dyn Database) -> Option<ImplHead<'db>> {
297 self.long(db).head(db)
298 }
299
300 pub fn name(&self, db: &dyn Database) -> String {
302 self.long(db).name(db)
303 }
304
305 pub fn format(&self, db: &dyn Database) -> String {
306 self.long(db).format(db)
307 }
308}
309
310define_short_id!(GeneratedImplId, GeneratedImplLongId<'db>);
311semantic_object_for_id!(GeneratedImplId, GeneratedImplLongId<'a>);
312
313impl<'db> GeneratedImplId<'db> {
314 pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
315 self.long(db).concrete_trait
316 }
317
318 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
319 self.concrete_trait(db).trait_id(db)
320 }
321}
322
323#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
327pub struct GeneratedImplLongId<'db> {
328 pub concrete_trait: ConcreteTraitId<'db>,
329 pub generic_params: Vec<GenericParam<'db>>,
332 pub impl_items: GeneratedImplItems<'db>,
333}
334#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, SemanticObject, salsa::Update, HeapSize)]
335pub struct GeneratedImplItems<'db>(pub OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>);
336
337pub enum GeneratedImplAssociatedTypes<'db> {
338 Unresolved,
340 Resolved(OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>),
342}
343
344impl<'db> DebugWithDb<'db> for GeneratedImplLongId<'db> {
345 type Db = dyn Database;
346
347 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
348 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
349 }
350}
351
352#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, HeapSize, salsa::Update)]
354pub struct ImplImplId<'db> {
355 impl_id: ImplId<'db>,
357 trait_impl_id: TraitImplId<'db>,
359}
360
361impl<'db> ImplImplId<'db> {
362 pub fn new(impl_id: ImplId<'db>, trait_impl_id: TraitImplId<'db>, db: &dyn Database) -> Self {
365 if let ImplLongId::Concrete(concrete_impl) = impl_id.long(db) {
366 let impl_def_id = concrete_impl.impl_def_id(db);
367 assert_eq!(Ok(trait_impl_id.trait_id(db)), db.impl_def_trait(impl_def_id));
368 }
369
370 ImplImplId { impl_id, trait_impl_id }
371 }
372 pub fn impl_id(&self) -> ImplId<'db> {
373 self.impl_id
374 }
375 pub fn trait_impl_id(&self) -> TraitImplId<'db> {
376 self.trait_impl_id
377 }
378
379 pub fn concrete_trait_impl_id(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitImplId<'db>> {
380 Ok(ConcreteTraitImplId::new_from_data(
381 db,
382 self.impl_id.concrete_trait(db)?,
383 self.trait_impl_id,
384 ))
385 }
386
387 pub fn full_path(&self, db: &dyn Database) -> String {
388 format!("{:?}", self.debug(db))
389 }
390}
391impl<'db> DebugWithDb<'db> for ImplImplId<'db> {
392 type Db = dyn Database;
393
394 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
395 write!(f, "{:?}::{}", self.impl_id.debug(db), self.trait_impl_id.name(db).long(db))
396 }
397}
398
399#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
402pub enum NegativeImplLongId<'db> {
403 Solved(ConcreteTraitId<'db>),
404 GenericParameter(GenericParamId<'db>),
405 NegativeImplVar(NegativeImplVarId<'db>),
406}
407
408impl<'db> NegativeImplLongId<'db> {
409 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
410 match self {
411 NegativeImplLongId::Solved(concrete_trait_id) => Ok(*concrete_trait_id),
412 NegativeImplLongId::GenericParameter(param) => {
413 let param_impl =
414 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::NegImpl);
415 param_impl.concrete_trait
416 }
417 NegativeImplLongId::NegativeImplVar(negative_impl_var_id) => {
418 Ok(negative_impl_var_id.long(db).concrete_trait_id)
419 }
420 }
421 }
422 pub fn is_var_free(&self, db: &dyn Database) -> bool {
423 match self {
424 NegativeImplLongId::Solved(concrete_trait_id) => concrete_trait_id.is_var_free(db),
425 NegativeImplLongId::GenericParameter(_) => true,
426 NegativeImplLongId::NegativeImplVar(_) => false,
427 }
428 }
429 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
430 match self {
431 NegativeImplLongId::Solved(concrete_trait_id) => {
432 concrete_trait_id.is_fully_concrete(db)
433 }
434 NegativeImplLongId::GenericParameter(_) | NegativeImplLongId::NegativeImplVar(_) => {
435 false
436 }
437 }
438 }
439}
440
441define_short_id!(NegativeImplId, NegativeImplLongId<'db>);
442impl<'db> NegativeImplId<'db> {
443 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
444 self.long(db).concrete_trait(db)
445 }
446 pub fn is_var_free(&self, db: &dyn Database) -> bool {
447 self.long(db).is_var_free(db)
448 }
449 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
450 self.long(db).is_fully_concrete(db)
451 }
452}
453semantic_object_for_id!(NegativeImplId, NegativeImplLongId<'a>);
454
455impl<'db> UnstableSalsaId for ImplId<'db> {
456 fn get_internal_id(&self) -> salsa::Id {
457 self.as_intern_id()
458 }
459}
460
461#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
467pub enum ImplHead<'db> {
468 Concrete(ImplDefId<'db>),
469}
470
471#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
474#[debug_db(dyn Database)]
475struct ImplDeclarationData<'db> {
476 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
477 concrete_trait: Maybe<ConcreteTraitId<'db>>,
479 attributes: Vec<Attribute<'db>>,
480 resolver_data: Arc<ResolverData<'db>>,
481}
482
483#[salsa::tracked(returns(ref))]
485fn impl_def_generic_params_data<'db>(
486 db: &'db dyn Database,
487 impl_def_id: ImplDefId<'db>,
488) -> Maybe<GenericParamsData<'db>> {
489 let module_id = impl_def_id.parent_module(db);
490 let mut diagnostics = SemanticDiagnostics::new(module_id);
491
492 let impl_ast = db.module_impl_by_id(impl_def_id)?;
493 let inference_id =
494 InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
495
496 let mut resolver = Resolver::new(db, module_id, inference_id);
497 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
498 let generic_params = semantic_generic_params(
499 db,
500 &mut diagnostics,
501 &mut resolver,
502 module_id,
503 &impl_ast.generic_params(db),
504 );
505 let inference = &mut resolver.inference();
506 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
507 let generic_params = inference.rewrite(generic_params).no_err();
508 let resolver_data = Arc::new(resolver.data);
509 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
510}
511
512#[salsa::tracked(returns(ref))]
514fn impl_def_substitution<'db>(
515 db: &'db dyn Database,
516 impl_def_id: ImplDefId<'db>,
517) -> Maybe<GenericSubstitution<'db>> {
518 let params = db.impl_def_generic_params(impl_def_id)?;
519 let generic_args = generic_params_to_args(params, db);
520 ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)
521}
522
523#[salsa::tracked]
525fn impl_def_trait<'db>(db: &'db dyn Database, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
526 let module_id = impl_def_id.parent_module(db);
527 let mut diagnostics = SemanticDiagnostics::new(module_id);
528
529 let impl_ast = db.module_impl_by_id(impl_def_id)?;
530 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
531
532 let mut resolver = Resolver::new(db, module_id, inference_id);
533 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
534
535 let trait_path_syntax = impl_ast.trait_path(db);
536
537 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path_syntax)
538}
539
540fn impl_def_shallow_trait_generic_args<'db>(
542 db: &'db dyn Database,
543 impl_def_id: ImplDefId<'db>,
544) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
545 Ok(impl_def_shallow_trait_generic_args_helper(db, impl_def_id).maybe_as_ref()?)
546}
547
548#[salsa::tracked(returns(ref))]
551fn impl_def_shallow_trait_generic_args_helper<'db>(
552 db: &'db dyn Database,
553 impl_def_id: ImplDefId<'db>,
554) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
555 let module_id = impl_def_id.parent_module(db);
556 let mut diagnostics = SemanticDiagnostics::new(module_id);
557
558 let impl_ast = db.module_impl_by_id(impl_def_id)?;
559 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
560
561 let mut resolver = Resolver::new(db, module_id, inference_id);
562 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
563
564 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
565 impl_ast.generic_params(db)
566 {
567 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
568 let generic_param_id =
569 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
570 resolver.add_generic_param(generic_param_id);
571 })
572 }
573 let trait_path_syntax = impl_ast.trait_path(db);
574
575 let ResolvedGenericItem::Trait(trait_id) = resolver.resolve_generic_path_with_args(
576 &mut diagnostics,
577 &trait_path_syntax,
578 NotFoundItemType::Trait,
579 ResolutionContext::Default,
580 )?
581 else {
582 return Err(skip_diagnostic());
583 };
584 let generic_params = db
585 .trait_generic_params_ids(trait_id)?
586 .iter()
587 .map(|param_syntax| {
588 GenericParamLongId(trait_id.parent_module(db), param_syntax.stable_ptr(db)).intern(db)
589 })
590 .collect::<Vec<_>>();
591
592 let elements = trait_path_syntax.segments(db).elements(db);
593 let Some(last) = elements.last() else {
594 return Ok(Vec::new());
595 };
596 match last {
597 ast::PathSegment::Simple(_) => Ok(Vec::new()),
598 ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
599 let generic_args =
600 path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
601
602 let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
603 &mut diagnostics,
604 &generic_params,
605 &generic_args,
606 )?;
607 Ok(generic_params
608 .iter()
609 .filter_map(|generic_param| {
610 let expr = arg_syntax_per_param.get(generic_param)?;
611 let arg_ty = maybe_resolve_shallow_generic_arg_type(
612 db,
613 &mut diagnostics,
614 &mut resolver,
615 expr,
616 )?;
617 Some((*generic_param, arg_ty))
618 })
619 .collect::<Vec<_>>())
620 }
621 ast::PathSegment::Missing(_) => Ok(Vec::new()),
622 }
623}
624
625fn impl_alias_trait_generic_args<'db>(
627 db: &'db dyn Database,
628 impl_alias_id: ImplAliasId<'db>,
629) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
630 Ok(impl_alias_trait_generic_args_helper(db, impl_alias_id).maybe_as_ref()?)
631}
632
633#[salsa::tracked(returns(ref))]
634fn impl_alias_trait_generic_args_helper<'db>(
635 db: &'db dyn Database,
636 impl_alias_id: ImplAliasId<'db>,
637) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
638 let module_id = impl_alias_id.parent_module(db);
639 let mut diagnostics = SemanticDiagnostics::new(module_id);
640
641 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?;
642 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
643
644 let mut resolver = Resolver::new(db, module_id, inference_id);
645 resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
646
647 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
648 impl_alias_ast.generic_params(db)
649 {
650 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
651 let generic_param_id =
652 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
653 resolver.add_generic_param(generic_param_id);
654 })
655 }
656 let rhs_syntax = impl_alias_ast.impl_path(db);
657 let (shallow_args, rhs_generic_params) = match resolver.resolve_generic_path_with_args(
658 &mut diagnostics,
659 &rhs_syntax,
660 NotFoundItemType::Impl,
661 ResolutionContext::Default,
662 ) {
663 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
664 let shallow_args = db.impl_def_shallow_trait_generic_args(impl_def_id)?.to_vec();
665 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
666 db.module_impl_by_id(impl_def_id)?.generic_params(db)
667 else {
668 return Ok(shallow_args);
669 };
670 (
671 shallow_args,
672 params
673 .generic_params(db)
674 .elements(db)
675 .map(|param_syntax| {
676 GenericParamLongId(
677 impl_def_id.parent_module(db),
678 param_syntax.stable_ptr(db),
679 )
680 .intern(db)
681 })
682 .collect::<Vec<_>>(),
683 )
684 }
685 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => {
686 let shallow_args = db.impl_alias_trait_generic_args(impl_alias)?.to_vec();
687 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
688 db.module_impl_alias_by_id(impl_alias)?.generic_params(db)
689 else {
690 return Ok(shallow_args);
691 };
692 (
693 shallow_args,
694 params
695 .generic_params(db)
696 .elements(db)
697 .map(|param_syntax| {
698 GenericParamLongId(
699 impl_alias.parent_module(db),
700 param_syntax.stable_ptr(db),
701 )
702 .intern(db)
703 })
704 .collect::<Vec<_>>(),
705 )
706 }
707 _ => return Ok(Vec::new()),
708 };
709
710 let elements = rhs_syntax.segments(db).elements(db);
711 let Some(last) = elements.last() else {
712 return Ok(Vec::new());
713 };
714
715 match last {
716 ast::PathSegment::Simple(_) => Ok(shallow_args),
717 ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
718 let generic_args =
719 path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
720 let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
721 &mut diagnostics,
722 &rhs_generic_params,
723 &generic_args,
724 )?;
725
726 Ok(shallow_args
727 .iter()
728 .filter_map(|(trait_param, arg)| {
729 let ShallowGenericArg::GenericParameter(arg) = arg else {
730 return Some((*trait_param, arg.clone()));
731 };
732
733 arg_syntax_per_param.get(arg).and_then(|expr| {
734 let arg_ty = maybe_resolve_shallow_generic_arg_type(
735 db,
736 &mut diagnostics,
737 &mut resolver,
738 expr,
739 )?;
740 Some((*trait_param, arg_ty))
741 })
742 })
743 .collect::<Vec<_>>())
744 }
745 ast::PathSegment::Missing(_) => Ok(shallow_args),
746 }
747}
748
749fn impl_concrete_trait<'db>(
751 db: &'db dyn Database,
752 impl_id: ImplId<'db>,
753) -> Maybe<ConcreteTraitId<'db>> {
754 match impl_id.long(db) {
755 ImplLongId::Concrete(concrete_impl_id) => {
756 let long_impl = concrete_impl_id.long(db);
757 let substitution = GenericSubstitution::new(
758 db.impl_def_generic_params(long_impl.impl_def_id)?,
759 &long_impl.generic_args,
760 );
761
762 let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
763 substitution.substitute(db, impl_concrete_trait_id)
764 }
765 ImplLongId::GenericParameter(param) => {
766 let param_impl =
767 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
768 param_impl.concrete_trait
769 }
770 ImplLongId::ImplVar(var) => Ok(var.long(db).concrete_trait_id),
771 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl),
772 ImplLongId::SelfImpl(concrete_trait_id) => Ok(*concrete_trait_id),
773 ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
774 }
775}
776
777#[salsa::tracked]
779fn impl_concrete_trait_tracked<'db>(
780 db: &'db dyn Database,
781 impl_id: ImplId<'db>,
782) -> Maybe<ConcreteTraitId<'db>> {
783 impl_concrete_trait(db, impl_id)
784}
785
786fn impl_declaration_data_cycle<'db>(
790 db: &'db dyn Database,
791 _id: salsa::Id,
792 impl_def_id: ImplDefId<'db>,
793) -> Maybe<ImplDeclarationData<'db>> {
794 impl_declaration_data_inner(db, impl_def_id, false)
795}
796
797#[salsa::tracked(cycle_result=impl_declaration_data_cycle, returns(ref))]
799fn impl_declaration_data<'db>(
800 db: &'db dyn Database,
801 impl_def_id: ImplDefId<'db>,
802) -> Maybe<ImplDeclarationData<'db>> {
803 impl_declaration_data_inner(db, impl_def_id, true)
804}
805
806fn impl_declaration_data_inner<'db>(
809 db: &'db dyn Database,
810 impl_def_id: ImplDefId<'db>,
811 resolve_trait: bool,
812) -> Maybe<ImplDeclarationData<'db>> {
813 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
814
815 let impl_ast = db.module_impl_by_id(impl_def_id)?;
819 let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
820 ModuleItemId::Impl(impl_def_id),
821 ));
822
823 let generic_params_data = impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?;
825 let mut resolver = Resolver::with_data(
826 db,
827 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
828 );
829 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
830 diagnostics.extend(generic_params_data.diagnostics.clone());
831 let trait_path_syntax = impl_ast.trait_path(db);
832
833 let concrete_trait = if resolve_trait {
834 resolver
835 .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
836 .and_then(|resolved_item| match resolved_item {
837 ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
838 _ => Err(diagnostics
839 .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
840 })
841 } else {
842 Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
843 };
844
845 let info = db.core_info();
846
847 if let Ok(concrete_trait) = concrete_trait
849 && [
850 info.type_eq_trt,
851 info.fn_trt,
852 info.fn_once_trt,
853 info.felt252_dict_value_trt,
854 info.numeric_literal_trt,
855 info.string_literal_trt,
856 ]
857 .contains(&concrete_trait.trait_id(db))
858 && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
859 {
860 diagnostics.report(
861 trait_path_syntax.stable_ptr(db),
862 CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
863 );
864 }
865
866 let inference = &mut resolver.inference();
868 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
869
870 let concrete_trait: Result<ConcreteTraitId<'_>, DiagnosticAdded> =
871 inference.rewrite(concrete_trait).no_err();
872
873 let attributes = impl_ast.attributes(db).structurize(db);
874 let mut resolver_data = resolver.data;
875 resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
876 Ok(ImplDeclarationData {
877 diagnostics: diagnostics.build(),
878 concrete_trait,
879 attributes,
880 resolver_data: Arc::new(resolver_data),
881 })
882}
883
884#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
887#[debug_db(dyn Database)]
888struct ImplDefinitionData<'db> {
889 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
894
895 function_asts: OrderedHashMap<ImplFunctionId<'db>, ast::FunctionWithBody<'db>>,
897 item_type_asts: OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>,
898 item_constant_asts: OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>,
899 item_impl_asts: OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>,
900
901 item_id_by_name: OrderedHashMap<SmolStrId<'db>, ImplItemInfo<'db>>,
904
905 implicit_impls_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>,
907}
908
909impl<'db> ImplDefinitionData<'db> {
910 pub fn get_impl_item_info(&self, item_name: SmolStrId<'db>) -> Option<ImplItemInfo<'db>> {
912 self.item_id_by_name.get(&item_name).cloned()
913 }
914}
915#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
917pub struct ImplItemInfo<'db> {
918 pub id: ImplItemId<'db>,
920 pub feature_kind: FeatureKind<'db>,
922}
923
924impl<'db> HasFeatureKind<'db> for ImplItemInfo<'db> {
925 fn feature_kind(&self) -> &FeatureKind<'db> {
927 &self.feature_kind
928 }
929}
930
931fn impl_semantic_definition_diagnostics<'db>(
935 db: &'db dyn Database,
936 impl_def_id: ImplDefId<'db>,
937) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
938 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
939
940 let Ok(data) = impl_definition_data(db, impl_def_id) else {
941 return Diagnostics::default();
942 };
943
944 diagnostics.extend(data.diagnostics.clone());
947 for impl_function_id in data.function_asts.keys() {
948 diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
949 diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
950 }
951 for impl_item_type_id in data.item_type_asts.keys() {
952 diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
953 if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
954 add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
955 }
956 }
957 for impl_item_constant_id in data.item_constant_asts.keys() {
958 diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
959 }
960 for impl_item_impl_id in data.item_impl_asts.keys() {
961 diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
962 }
963 for implicit_impl_id in data.implicit_impls_id_by_name.values() {
964 diagnostics
965 .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
966 }
967 if diagnostics.error_count == 0 {
969 let concrete_trait =
970 impl_declaration_data(db, impl_def_id).as_ref().unwrap().concrete_trait.unwrap();
971
972 let trait_id = concrete_trait.trait_id(db);
973 if trait_id == db.core_info().deref_trt {
974 deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
975 }
976 }
977 diagnostics.build()
978}
979
980#[salsa::tracked]
982fn impl_semantic_definition_diagnostics_tracked<'db>(
983 db: &'db dyn Database,
984 impl_def_id: ImplDefId<'db>,
985) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
986 impl_semantic_definition_diagnostics(db, impl_def_id)
987}
988
989#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
991pub struct DerefChain<'db> {
992 pub derefs: Arc<Vec<DerefInfo<'db>>>,
993}
994
995#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
997pub struct DerefInfo<'db> {
998 pub function_id: FunctionId<'db>,
1000 pub self_mutability: Mutability,
1002 pub target_ty: TypeId<'db>,
1004}
1005
1006fn deref_chain_cycle<'db>(
1008 _db: &dyn Database,
1009 _id: salsa::Id,
1010 _ty: TypeId<'db>,
1011 _crate_id: CrateId<'db>,
1012 _try_deref_mut: bool,
1013) -> Maybe<DerefChain<'db>> {
1014 Maybe::Err(skip_diagnostic())
1016}
1017
1018#[salsa::tracked(cycle_result=deref_chain_cycle, returns(ref))]
1020fn deref_chain<'db>(
1021 db: &'db dyn Database,
1022 ty: TypeId<'db>,
1023 crate_id: CrateId<'db>,
1024 try_deref_mut: bool,
1025) -> Maybe<DerefChain<'db>> {
1026 let mut opt_deref = None;
1027 if try_deref_mut {
1028 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, true)?;
1029 }
1030 let self_mutability = if opt_deref.is_some() {
1031 Mutability::Reference
1032 } else {
1033 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, false)?;
1034 Mutability::Immutable
1035 };
1036
1037 let Some((function_id, target_ty)) = opt_deref else {
1038 return Ok(DerefChain { derefs: Arc::new(vec![]) });
1039 };
1040
1041 let inner_chain = db.deref_chain(target_ty, crate_id, false)?;
1042
1043 Ok(DerefChain {
1044 derefs: Arc::new(
1045 chain!(
1046 [DerefInfo { function_id, target_ty, self_mutability }],
1047 inner_chain.derefs.iter().cloned()
1048 )
1049 .collect(),
1050 ),
1051 })
1052}
1053
1054fn try_get_deref_func_and_target<'db>(
1056 db: &'db dyn Database,
1057 ty: TypeId<'db>,
1058 crate_id: CrateId<'db>,
1059 is_mut_deref: bool,
1060) -> Result<Option<(FunctionId<'db>, TypeId<'db>)>, DiagnosticAdded> {
1061 let info = db.core_info();
1062 let (deref_trait_id, deref_method) = if is_mut_deref {
1063 (info.deref_mut_trt, info.deref_mut_fn)
1064 } else {
1065 (info.deref_trt, info.deref_fn)
1066 };
1067
1068 let mut lookup_context = ImplLookupContext::new_from_crate(crate_id);
1069 enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
1070 let concrete_trait = ConcreteTraitLongId {
1071 trait_id: deref_trait_id,
1072 generic_args: vec![GenericArgumentId::Type(ty)],
1073 }
1074 .intern(db);
1075 let Ok(deref_impl) = get_impl_at_context(db, lookup_context.intern(db), concrete_trait, None)
1076 else {
1077 return Ok(None);
1078 };
1079 let concrete_impl_id: ConcreteImplId<'db> = match deref_impl.long(db) {
1080 ImplLongId::Concrete(concrete_impl_id) => *concrete_impl_id,
1081 _ => panic!("Expected concrete impl"),
1082 };
1083
1084 let function_id: FunctionId<'db> = FunctionLongId {
1085 function: ConcreteFunction {
1086 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
1087 impl_id: deref_impl,
1088 function: deref_method,
1089 }),
1090 generic_args: vec![],
1091 },
1092 }
1093 .intern(db);
1094
1095 let data = impl_definition_data(db, concrete_impl_id.impl_def_id(db)).clone().unwrap();
1096 let mut types_iter = data.item_type_asts.iter();
1097 let (impl_item_type_id, _) = types_iter.next().unwrap();
1098 if types_iter.next().is_some() {
1099 panic!(
1100 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1101 );
1102 }
1103 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1104 let substitution: GenericSubstitution<'db> = concrete_impl_id.substitution(db)?;
1105 let ty: TypeId<'db> = substitution.substitute(db, ty).unwrap();
1106
1107 Ok(Some((function_id, ty)))
1108}
1109
1110fn deref_impl_diagnostics<'db>(
1112 db: &'db dyn Database,
1113 mut impl_def_id: ImplDefId<'db>,
1114 concrete_trait: ConcreteTraitId<'db>,
1115 diagnostics: &mut SemanticDiagnostics<'db>,
1116) {
1117 let mut visited_impls: OrderedHashSet<ImplDefId<'_>> = OrderedHashSet::default();
1118 let deref_trait_id = concrete_trait.trait_id(db);
1119
1120 let impl_module = impl_def_id.parent_module(db);
1121
1122 let mut impl_in_valid_location = false;
1123 if impl_module == deref_trait_id.parent_module(db) {
1124 impl_in_valid_location = true;
1125 }
1126
1127 let gargs = concrete_trait.generic_args(db);
1128 let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
1129 if let Some(module_id) = deref_ty.long(db).module_id(db)
1130 && module_id == impl_module
1131 {
1132 impl_in_valid_location = true;
1133 }
1134
1135 if !impl_in_valid_location {
1136 diagnostics.report(
1137 impl_def_id.stable_ptr(db),
1138 SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
1139 );
1140 return;
1141 }
1142
1143 loop {
1144 let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
1145 ConcreteTraitLongId {
1146 trait_id: deref_trait_id,
1147 generic_args: vec![GenericArgumentId::Type(ty)],
1148 }
1149 .intern(db)
1150 }) else {
1151 return;
1154 };
1155
1156 impl_def_id = match impl_id.long(db) {
1157 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
1158 _ => return,
1159 };
1160
1161 if !visited_impls.insert(impl_def_id) {
1162 let deref_chain = visited_impls
1163 .iter()
1164 .map(|visited_impl| {
1165 format!("{:?}", db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db))
1166 })
1167 .join(" -> ");
1168 diagnostics.report(
1169 impl_def_id.stable_ptr(db),
1170 SemanticDiagnosticKind::DerefCycle { deref_chain },
1171 );
1172 return;
1173 }
1174 }
1175}
1176
1177fn get_impl_based_on_single_impl_type<'db>(
1181 db: &'db dyn Database,
1182 impl_def_id: ImplDefId<'db>,
1183 concrete_trait_id: impl FnOnce(TypeId<'db>) -> ConcreteTraitId<'db>,
1184) -> Result<ImplId<'db>, (InferenceError<'db>, ImplTypeDefId<'db>)> {
1185 let data = impl_definition_data(db, impl_def_id).clone().unwrap();
1186 let mut types_iter = data.item_type_asts.iter();
1187 let (impl_item_type_id, _) = types_iter.next().unwrap();
1188 if types_iter.next().is_some() {
1189 panic!(
1190 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1191 );
1192 }
1193 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1194
1195 let module_id = impl_def_id.parent_module(db);
1196 let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
1197 let generic_params_ids =
1198 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1199 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db);
1200 get_impl_at_context(db, lookup_context.intern(db), concrete_trait_id(ty), None)
1201 .map_err(|err| (err, *impl_item_type_id))
1202}
1203
1204#[salsa::tracked(returns(ref))]
1206fn impl_functions<'db>(
1207 db: &'db dyn Database,
1208 impl_def_id: ImplDefId<'db>,
1209) -> Maybe<OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
1210 Ok(impl_definition_data(db, impl_def_id)
1211 .maybe_as_ref()?
1212 .function_asts
1213 .keys()
1214 .map(|function_id| {
1215 let function_long_id = function_id.long(db);
1216 (function_long_id.name(db), *function_id)
1217 })
1218 .collect())
1219}
1220
1221#[salsa::tracked]
1223fn impl_function_by_trait_function<'db>(
1224 db: &'db dyn Database,
1225 impl_def_id: ImplDefId<'db>,
1226 trait_function_id: TraitFunctionId<'db>,
1227) -> Maybe<Option<ImplFunctionId<'db>>> {
1228 let name = trait_function_id.name(db);
1229 for impl_function_id in
1230 impl_definition_data(db, impl_def_id).maybe_as_ref()?.function_asts.keys()
1231 {
1232 if impl_function_id.long(db).name(db) == name {
1233 return Ok(Some(*impl_function_id));
1234 }
1235 }
1236 Ok(None)
1237}
1238
1239fn impl_item_info_by_name<'db>(
1241 db: &'db dyn Database,
1242 impl_def_id: ImplDefId<'db>,
1243 name: SmolStrId<'db>,
1244) -> Maybe<Option<ImplItemInfo<'db>>> {
1245 let impl_definition_data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1246 Ok(impl_definition_data.get_impl_item_info(name))
1247}
1248
1249#[salsa::tracked]
1251fn impl_item_info_by_name_tracked<'db>(
1252 db: &'db dyn Database,
1253 impl_def_id: ImplDefId<'db>,
1254 name: SmolStrId<'db>,
1255) -> Maybe<Option<ImplItemInfo<'db>>> {
1256 impl_item_info_by_name(db, impl_def_id, name)
1257}
1258
1259#[salsa::tracked(returns(ref))]
1261fn impl_all_used_uses<'db>(
1262 db: &'db dyn Database,
1263 impl_def_id: ImplDefId<'db>,
1264) -> Maybe<OrderedHashSet<UseId<'db>>> {
1265 let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1266 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1267 for item in data.item_id_by_name.values() {
1268 for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1269 all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1270 }
1271 }
1272 Ok(all_used_uses)
1273}
1274
1275#[salsa::tracked]
1277fn impl_type_by_id<'db>(
1278 db: &'db dyn Database,
1279 impl_type_id: ImplTypeDefId<'db>,
1280) -> Maybe<ast::ItemTypeAlias<'db>> {
1281 let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1282 impl_types.get(&impl_type_id).cloned().ok_or_else(skip_diagnostic)
1283}
1284
1285fn impl_type_by_trait_type<'db>(
1287 db: &'db dyn Database,
1288 impl_def_id: ImplDefId<'db>,
1289 trait_type_id: TraitTypeId<'db>,
1290) -> Maybe<ImplTypeDefId<'db>> {
1291 if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1292 unreachable!(
1293 "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1294 trait"
1295 )
1296 }
1297
1298 let name = trait_type_id.name(db);
1299 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1301 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
1302 None => Err(skip_diagnostic()),
1303 })
1304}
1305
1306#[salsa::tracked]
1308fn impl_type_by_trait_type_tracked<'db>(
1309 db: &'db dyn Database,
1310 impl_def_id: ImplDefId<'db>,
1311 trait_type_id: TraitTypeId<'db>,
1312) -> Maybe<ImplTypeDefId<'db>> {
1313 impl_type_by_trait_type(db, impl_def_id, trait_type_id)
1314}
1315
1316#[salsa::tracked]
1318fn impl_constant_by_trait_constant<'db>(
1319 db: &'db dyn Database,
1320 impl_def_id: ImplDefId<'db>,
1321 trait_constant_id: TraitConstantId<'db>,
1322) -> Maybe<ImplConstantDefId<'db>> {
1323 if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1324 unreachable!(
1325 "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1326 the impl's trait"
1327 )
1328 }
1329
1330 let name = trait_constant_id.name(db);
1331 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1333 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
1334 None => Err(skip_diagnostic()),
1335 })
1336}
1337
1338#[salsa::tracked]
1340fn impl_impl_by_id<'db>(
1341 db: &'db dyn Database,
1342 impl_impl_id: ImplImplDefId<'db>,
1343) -> Maybe<ast::ItemImplAlias<'db>> {
1344 let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1345 impl_impls.get(&impl_impl_id).cloned().ok_or_else(skip_diagnostic)
1346}
1347
1348#[salsa::tracked]
1350fn impl_impl_by_trait_impl<'db>(
1351 db: &'db dyn Database,
1352 impl_def_id: ImplDefId<'db>,
1353 trait_impl_id: TraitImplId<'db>,
1354) -> Maybe<ImplImplDefId<'db>> {
1355 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1356 unreachable!(
1357 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1358 trait"
1359 )
1360 }
1361
1362 let name = trait_impl_id.name(db);
1363 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1365 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1366 None => Err(skip_diagnostic()),
1367 })
1368}
1369
1370#[salsa::tracked]
1372fn is_implicit_impl_impl<'db>(
1373 db: &'db dyn Database,
1374 impl_def_id: ImplDefId<'db>,
1375 trait_impl_id: TraitImplId<'db>,
1376) -> Maybe<bool> {
1377 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1378 unreachable!(
1379 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1380 trait"
1381 )
1382 }
1383
1384 let name = trait_impl_id.name(db);
1385 Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1387}
1388
1389#[salsa::tracked(returns(ref))]
1393fn impl_definition_data<'db>(
1394 db: &'db dyn Database,
1395 impl_def_id: ImplDefId<'db>,
1396) -> Maybe<ImplDefinitionData<'db>> {
1397 let module_id = impl_def_id.parent_module(db);
1398 let mut diagnostics = SemanticDiagnostics::new(module_id);
1399
1400 let generic_params =
1401 impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?.generic_params.clone();
1402 let concrete_trait = impl_declaration_data(db, impl_def_id).maybe_as_ref()?.concrete_trait?;
1403
1404 let impl_ast = db.module_impl_by_id(impl_def_id)?;
1405
1406 let generic_params_ids =
1407 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1408 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db).intern(db);
1409 check_special_impls(
1410 db,
1411 &mut diagnostics,
1412 lookup_context,
1413 concrete_trait,
1414 impl_ast.stable_ptr(db).untyped(),
1415 )
1416 .ok();
1418
1419 let mut function_asts = OrderedHashMap::default();
1420 let mut item_type_asts = OrderedHashMap::default();
1421 let mut item_constant_asts = OrderedHashMap::default();
1422 let mut item_impl_asts = OrderedHashMap::default();
1423 let mut item_id_by_name = OrderedHashMap::default();
1424
1425 if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1426 for item in body.items(db).elements(db) {
1427 match item {
1428 ImplItem::Module(module) => {
1429 report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1430 }
1431
1432 ImplItem::Use(use_item) => {
1433 report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1434 }
1435 ImplItem::ExternFunction(extern_func) => {
1436 report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1437 }
1438 ImplItem::ExternType(extern_type) => {
1439 report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1440 }
1441 ImplItem::Trait(trt) => {
1442 report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1443 }
1444 ImplItem::Struct(structure) => {
1445 report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1446 }
1447 ImplItem::Enum(enm) => {
1448 report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1449 }
1450 ImplItem::Function(func) => {
1451 let impl_function_id =
1452 ImplFunctionLongId(module_id, func.stable_ptr(db)).intern(db);
1453 let name_node = func.declaration(db).name(db);
1454 let name = name_node.text(db);
1455 let feature_kind =
1456 FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1457 if item_id_by_name
1458 .insert(
1459 name,
1460 ImplItemInfo {
1461 id: ImplItemId::Function(impl_function_id),
1462 feature_kind,
1463 },
1464 )
1465 .is_some()
1466 {
1467 diagnostics
1468 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1469 }
1470 function_asts.insert(impl_function_id, func);
1471 }
1472 ImplItem::Type(ty) => {
1473 let impl_type_id = ImplTypeDefLongId(module_id, ty.stable_ptr(db)).intern(db);
1474 let name_node = ty.name(db);
1475 let name = name_node.text(db);
1476 let feature_kind =
1477 FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1478 if item_id_by_name
1479 .insert(
1480 name,
1481 ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1482 )
1483 .is_some()
1484 {
1485 diagnostics
1486 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1487 }
1488 item_type_asts.insert(impl_type_id, ty);
1489 }
1490 ImplItem::Constant(constant) => {
1491 let impl_constant_id =
1492 ImplConstantDefLongId(module_id, constant.stable_ptr(db)).intern(db);
1493 let name_node = constant.name(db);
1494 let name = name_node.text(db);
1495 let feature_kind =
1496 FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1497 if item_id_by_name
1498 .insert(
1499 name,
1500 ImplItemInfo {
1501 id: ImplItemId::Constant(impl_constant_id),
1502 feature_kind,
1503 },
1504 )
1505 .is_some()
1506 {
1507 diagnostics.report(
1508 name_node.stable_ptr(db),
1509 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1510 );
1511 }
1512 item_constant_asts.insert(impl_constant_id, constant);
1513 }
1514 ImplItem::Impl(imp) => {
1515 let impl_impl_id = ImplImplDefLongId(module_id, imp.stable_ptr(db)).intern(db);
1516 let name_node = imp.name(db);
1517 let name = name_node.text(db);
1518 let feature_kind =
1519 FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1520 if item_id_by_name
1521 .insert(
1522 name,
1523 ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1524 )
1525 .is_some()
1526 {
1527 diagnostics.report(
1528 name_node.stable_ptr(db),
1529 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1530 );
1531 }
1532 item_impl_asts.insert(impl_impl_id, imp);
1533 }
1534 ImplItem::Missing(_) => {}
1536 }
1537 }
1538 }
1539
1540 let mut implicit_impls_id_by_name = OrderedHashMap::default();
1541
1542 let trait_id = concrete_trait.long(db).trait_id;
1543 for (name, trait_impl_id) in db.trait_impls(trait_id)?.iter() {
1544 if item_id_by_name.contains_key(name) {
1545 continue;
1546 }
1547 implicit_impls_id_by_name.insert(*name, *trait_impl_id);
1548 }
1549
1550 let impl_item_names: OrderedHashSet<SmolStrId<'db>> = item_id_by_name.keys().copied().collect();
1554
1555 let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1556 let missing_items_in_impl =
1557 trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1558 if !missing_items_in_impl.is_empty() {
1559 diagnostics.report(
1560 impl_ast.name(db).stable_ptr(db),
1565 SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1566 );
1567 }
1568
1569 Ok(ImplDefinitionData {
1570 diagnostics: diagnostics.build(),
1571 function_asts,
1572 item_type_asts,
1573 item_id_by_name,
1574 item_constant_asts,
1575 item_impl_asts,
1576 implicit_impls_id_by_name,
1577 })
1578}
1579
1580fn report_invalid_impl_item<'db, Terminal: syntax::node::Terminal<'db>>(
1583 db: &'db dyn Database,
1584 diagnostics: &mut SemanticDiagnostics<'db>,
1585 kw_terminal: Terminal,
1586) {
1587 diagnostics
1588 .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1589}
1590
1591fn check_special_impls<'db>(
1593 db: &'db dyn Database,
1594 diagnostics: &mut SemanticDiagnostics<'db>,
1595 lookup_context: ImplLookupContextId<'db>,
1596 concrete_trait: ConcreteTraitId<'db>,
1597 stable_ptr: SyntaxStablePtrId<'db>,
1598) -> Maybe<()> {
1599 let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.long(db);
1600 let info = db.core_info();
1601 let copy = info.copy_trt;
1602 let drop = info.drop_trt;
1603
1604 if *trait_id == copy {
1605 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1606 for inference_error in tys
1607 .into_iter()
1608 .map(|ty| db.type_info(lookup_context, ty))
1609 .flat_map(|info| info.copyable.err())
1610 {
1611 if matches!(
1612 inference_error,
1613 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1614 ) {
1615 continue;
1617 }
1618 return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1619 }
1620 }
1621 if *trait_id == drop {
1622 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1623 for inference_error in tys
1624 .into_iter()
1625 .map(|ty| db.type_info(lookup_context, ty))
1626 .flat_map(|info| info.droppable.err())
1627 {
1628 if matches!(
1629 inference_error,
1630 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1631 ) {
1632 continue;
1634 }
1635 return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1636 }
1637 }
1638
1639 Ok(())
1640}
1641
1642fn get_inner_types<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> Maybe<Vec<TypeId<'db>>> {
1649 Ok(match ty.long(db) {
1650 TypeLongId::Concrete(concrete_type_id) => {
1651 match concrete_type_id {
1653 crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1654 .concrete_struct_members(*concrete_struct_id)?
1655 .values()
1656 .map(|member| member.ty)
1657 .collect(),
1658 crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1659 .concrete_enum_variants(*concrete_enum_id)?
1660 .into_iter()
1661 .map(|variant| variant.ty)
1662 .collect(),
1663 crate::ConcreteTypeId::Extern(_) => vec![],
1664 }
1665 }
1666 TypeLongId::Tuple(tys) => tys.to_vec(),
1667 TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1668 TypeLongId::GenericParameter(_) => {
1669 return Err(skip_diagnostic());
1670 }
1671 TypeLongId::Var(_) | TypeLongId::NumericLiteral(_) | TypeLongId::ImplType(_) => {
1672 panic!("Types should be fully resolved at this point.")
1673 }
1674 TypeLongId::Coupon(_) => vec![],
1675 TypeLongId::FixedSizeArray { type_id, .. } => vec![*type_id],
1676 TypeLongId::Missing(diag_added) => {
1677 return Err(*diag_added);
1678 }
1679 })
1680}
1681
1682#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1687pub struct TraitFilter<'db> {
1688 pub trait_id: TraitId<'db>,
1689 pub generics_filter: GenericsHeadFilter<'db>,
1691}
1692
1693#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
1696pub enum GenericsHeadFilter<'db> {
1697 NoFilter,
1700 FirstGenericFilter(GenericArgumentHead<'db>),
1703 NoGenerics,
1705}
1706
1707#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HeapSize, salsa::Update)]
1708pub struct UninferredImplById<'db>(pub UninferredImpl<'db>);
1709impl<'db> Ord for UninferredImplById<'db> {
1710 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1711 match (&self.0, &other.0) {
1712 (UninferredImpl::Def(impl_def_id), UninferredImpl::Def(other_impl_def_id)) => {
1713 impl_def_id.get_internal_id().cmp(&other_impl_def_id.get_internal_id())
1714 }
1715 (
1716 UninferredImpl::ImplAlias(impl_alias_id),
1717 UninferredImpl::ImplAlias(other_impl_alias_id),
1718 ) => impl_alias_id.get_internal_id().cmp(&other_impl_alias_id.get_internal_id()),
1719 (UninferredImpl::GenericParam(param), UninferredImpl::GenericParam(other_param)) => {
1720 param.get_internal_id().cmp(&other_param.get_internal_id())
1721 }
1722 (
1723 UninferredImpl::ImplImpl(impl_impl_id),
1724 UninferredImpl::ImplImpl(other_impl_impl_id),
1725 ) => {
1726 if impl_impl_id.impl_id() == other_impl_impl_id.impl_id() {
1727 impl_impl_id
1728 .trait_impl_id()
1729 .get_internal_id()
1730 .cmp(&other_impl_impl_id.trait_impl_id().get_internal_id())
1731 } else {
1732 impl_impl_id
1733 .impl_id()
1734 .get_internal_id()
1735 .cmp(&other_impl_impl_id.impl_id().get_internal_id())
1736 }
1737 }
1738 (
1739 UninferredImpl::GeneratedImpl(generated_impl),
1740 UninferredImpl::GeneratedImpl(other_generated_impl),
1741 ) => generated_impl.get_internal_id().cmp(&other_generated_impl.get_internal_id()),
1742 (UninferredImpl::Def(_), _) => std::cmp::Ordering::Less,
1743 (_, UninferredImpl::Def(_)) => std::cmp::Ordering::Greater,
1744 (UninferredImpl::ImplAlias(_), _) => std::cmp::Ordering::Less,
1745 (_, UninferredImpl::ImplAlias(_)) => std::cmp::Ordering::Greater,
1746 (UninferredImpl::GenericParam(_), _) => std::cmp::Ordering::Less,
1747 (_, UninferredImpl::GenericParam(_)) => std::cmp::Ordering::Greater,
1748 (UninferredImpl::ImplImpl(_), _) => std::cmp::Ordering::Less,
1749 (_, UninferredImpl::ImplImpl(_)) => std::cmp::Ordering::Greater,
1750 }
1751 }
1752}
1753impl<'db> PartialOrd for UninferredImplById<'db> {
1754 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1755 Some(self.cmp(other))
1756 }
1757}
1758impl<'db> From<UninferredImpl<'db>> for UninferredImplById<'db> {
1759 fn from(uninferred_impl: UninferredImpl<'db>) -> Self {
1760 UninferredImplById(uninferred_impl)
1761 }
1762}
1763
1764#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, salsa::Update, HeapSize)]
1765#[debug_db(dyn Database)]
1766pub struct ImplLookupContext<'db> {
1767 pub crate_id: CrateId<'db>,
1768 pub generic_params: Vec<GenericParamId<'db>>,
1769 pub inner_impls: BTreeSet<UninferredImplById<'db>>,
1770 pub negative_impls: Vec<GenericParamId<'db>>,
1771}
1772
1773define_short_id!(ImplLookupContextId, ImplLookupContext<'db>);
1774
1775impl<'db> ImplLookupContext<'db> {
1776 pub fn new_from_crate(crate_id: CrateId<'db>) -> Self {
1778 Self {
1779 crate_id,
1780 generic_params: Default::default(),
1781 inner_impls: Default::default(),
1782 negative_impls: Default::default(),
1783 }
1784 }
1785 pub fn new_from_type(ty: TypeId<'db>, db: &'db dyn Database) -> Self {
1788 Self::new_from_crate(
1789 ty.long(db)
1790 .module_id(db)
1791 .map(|m| m.owning_crate(db))
1792 .unwrap_or_else(|| db.core_crate()),
1793 )
1794 }
1795 pub fn new(
1797 module_id: ModuleId<'db>,
1798 generic_params: Vec<GenericParamId<'db>>,
1799 db: &'db dyn Database,
1800 ) -> ImplLookupContext<'db> {
1801 let crate_id = module_id.owning_crate(db);
1802 let negative_impls = generic_params
1803 .iter()
1804 .filter(|generic_param_id| matches!(generic_param_id.kind(db), GenericKind::NegImpl))
1805 .copied()
1806 .collect_vec();
1807 let generic_params = generic_params
1808 .iter()
1809 .filter(|generic_param_id| {
1810 if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1811 return false;
1812 }
1813
1814 let uninferred_impl = UninferredImpl::GenericParam(**generic_param_id);
1815
1816 let Ok(trait_id) = uninferred_impl.trait_id(db) else {
1817 return true;
1818 };
1819 let Some(set) = db.crate_global_impls(crate_id).get(&trait_id) else {
1820 return true;
1821 };
1822 let uninferred_impl: UninferredImplById<'db> = uninferred_impl.into();
1823 if set.contains(&uninferred_impl) {
1824 return false;
1825 };
1826 true
1827 })
1828 .copied()
1829 .collect_vec();
1830 let mut res = Self {
1831 crate_id,
1832 generic_params: generic_params
1833 .clone()
1834 .into_iter()
1835 .filter(|id| id.long(db).has_type_constraints_syntax(db))
1836 .collect_vec(),
1837 inner_impls: BTreeSet::from_iter(
1838 generic_params.into_iter().map(|id| UninferredImpl::GenericParam(id).into()),
1839 ),
1840 negative_impls,
1841 };
1842 res.insert_module(module_id, db);
1843 res
1844 }
1845 pub fn insert_lookup_scope(&mut self, db: &'db dyn Database, imp: &UninferredImpl<'db>) {
1846 match imp {
1847 UninferredImpl::Def(impl_def_id) => {
1848 self.insert_module(impl_def_id.parent_module(db), db)
1849 }
1850 UninferredImpl::ImplAlias(impl_alias_id) => {
1851 self.insert_module(impl_alias_id.parent_module(db), db)
1852 }
1853 UninferredImpl::GenericParam(param) => self.insert_module(param.parent_module(db), db),
1854 UninferredImpl::ImplImpl(impl_impl_id) => self.insert_impl(impl_impl_id.impl_id, db),
1855 UninferredImpl::GeneratedImpl(_) => {
1856 }
1858 };
1859 }
1860 pub fn insert_module(&mut self, module_id: ModuleId<'db>, db: &'db dyn Database) {
1863 let module_id = db.module_perceived_module(module_id);
1865 let crate_global_impls = db.crate_global_impls(self.crate_id);
1866 if let Ok(module_impls) = db.module_global_impls((), module_id) {
1867 module_impls.locals.iter().for_each(|imp| {
1868 if let Ok(trait_id) = imp.0.trait_id(db)
1869 && let Some(set) = crate_global_impls.get(&trait_id)
1870 && set.contains(imp)
1871 {
1872 return;
1873 }
1874
1875 self.inner_impls.insert(*imp);
1876 });
1877 if !crate_dependencies(db, self.crate_id).contains(&module_id.owning_crate(db)) {
1879 module_impls.globals_by_trait.iter().for_each(|(_, imps)| {
1880 imps.iter().for_each(|imp| {
1881 if let Ok(trait_id) = imp.0.trait_id(db)
1882 && let Some(set) = crate_global_impls.get(&trait_id)
1883 && set.contains(imp)
1884 {
1885 return;
1886 }
1887
1888 self.inner_impls.insert(*imp);
1889 });
1890 });
1891 }
1892 }
1893 }
1894
1895 pub fn insert_impl(&mut self, impl_id: ImplId<'db>, db: &'db dyn Database) {
1898 let mut uninferred_impls = Vec::new();
1899 let Ok(concrete_trait) = impl_id.concrete_trait(db) else {
1900 return;
1901 };
1902 let Ok(trait_impls) = db.trait_impls(concrete_trait.trait_id(db)) else {
1903 return;
1904 };
1905 for (_, trait_impl_id) in trait_impls.iter() {
1906 uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1907 impl_id,
1908 *trait_impl_id,
1909 db,
1910 )));
1911 }
1912 for uninferred_impl in uninferred_impls {
1913 self.inner_impls.insert(uninferred_impl.into());
1914 }
1915 }
1916
1917 pub fn strip_for_trait_id(&mut self, db: &dyn Database, trait_id: TraitId<'db>) {
1920 let deps = db.reachable_trait_dependencies(trait_id, self.crate_id);
1921 let type_eq_trt = db.core_info().type_eq_trt;
1922 self.inner_impls.retain(|impl_by_id| {
1923 if let Ok(impl_trait_id) = impl_by_id.0.trait_id(db) {
1924 return trait_id == impl_trait_id
1925 || trait_id == type_eq_trt
1926 || deps.contains(&impl_trait_id);
1927 }
1928
1929 false
1930 });
1931 }
1932}
1933
1934#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, HeapSize, salsa::Update)]
1936pub enum UninferredImpl<'db> {
1937 Def(ImplDefId<'db>),
1938 ImplAlias(ImplAliasId<'db>),
1939 GenericParam(GenericParamId<'db>),
1940 ImplImpl(ImplImplId<'db>),
1941 GeneratedImpl(UninferredGeneratedImplId<'db>),
1942}
1943impl<'db> UninferredImpl<'db> {
1944 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
1945 match self {
1946 UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1947 UninferredImpl::ImplAlias(impl_alias_id) => {
1948 let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1949 impl_id.concrete_trait(db)
1950 }
1951 UninferredImpl::GenericParam(param) => {
1952 let param =
1953 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1954 param.concrete_trait
1955 }
1956 UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1957 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1958 }
1959 }
1960
1961 fn trait_id(&self, db: &'db dyn Database) -> Maybe<TraitId<'db>> {
1962 match self {
1963 UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1964 UninferredImpl::ImplAlias(impl_alias_id) => {
1965 let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1966 db.impl_def_trait(impl_def_id)
1967 }
1968 UninferredImpl::GenericParam(param) => db.generic_impl_param_trait(*param),
1969 UninferredImpl::ImplImpl(impl_impl_id) => db
1970 .impl_impl_concrete_trait(*impl_impl_id)
1971 .map(|concrete_trait| concrete_trait.trait_id(db)),
1972 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1973 }
1974 }
1975
1976 fn trait_shallow_generic_args(
1978 &self,
1979 db: &'db dyn Database,
1980 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
1981 match self {
1982 UninferredImpl::Def(impl_def_id) => {
1983 db.impl_def_shallow_trait_generic_args(*impl_def_id)
1984 }
1985
1986 UninferredImpl::ImplAlias(impl_alias_id) => {
1987 db.impl_alias_trait_generic_args(*impl_alias_id)
1988 }
1989 UninferredImpl::GenericParam(param) => {
1990 db.generic_impl_param_shallow_trait_generic_args(*param)
1991 }
1992 UninferredImpl::ImplImpl(_impl_impl_id) => Ok(&[]),
1994 UninferredImpl::GeneratedImpl(_generated_impl) => Ok(&[]),
1995 }
1996 }
1997}
1998
1999impl<'db> DebugWithDb<'db> for UninferredImpl<'db> {
2000 type Db = dyn Database;
2001
2002 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2003 match self {
2004 UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
2005 UninferredImpl::ImplAlias(impl_alias) => {
2006 write!(f, "{:?}", impl_alias.full_path(db))
2007 }
2008 UninferredImpl::GenericParam(param) => {
2009 write!(
2010 f,
2011 "generic param {}",
2012 param.name(db).map(|name| name.long(db).as_str()).unwrap_or("_")
2013 )
2014 }
2015 UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db),
2016 UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db),
2017 }
2018 }
2019}
2020
2021define_short_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'db>);
2022impl<'db> UnstableSalsaId for UninferredGeneratedImplId<'db> {
2023 fn get_internal_id(&self) -> salsa::Id {
2024 self.0
2025 }
2026}
2027semantic_object_for_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'a>);
2028
2029impl<'db> UninferredGeneratedImplId<'db> {
2030 pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
2031 self.long(db).concrete_trait
2032 }
2033
2034 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
2035 self.concrete_trait(db).trait_id(db)
2036 }
2037}
2038
2039#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
2041pub struct UninferredGeneratedImplLongId<'db> {
2042 pub concrete_trait: ConcreteTraitId<'db>,
2043 pub generic_params: Vec<GenericParam<'db>>,
2044 pub impl_items: GeneratedImplItems<'db>,
2045}
2046
2047impl<'db> DebugWithDb<'db> for UninferredGeneratedImplLongId<'db> {
2048 type Db = dyn Database;
2049
2050 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2051 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
2052 }
2053}
2054
2055#[salsa::tracked(returns(ref))]
2057fn trait_candidate_by_head<'db>(
2058 db: &'db dyn Database,
2059 crate_id: CrateId<'db>,
2060 trait_id: TraitId<'db>,
2061) -> OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
2062 let mut res: OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> =
2063 OrderedHashMap::default();
2064
2065 if let Some(candidates) = db.crate_global_impls(crate_id).get(&trait_id) {
2066 for candidate in candidates.iter() {
2067 let Ok(shallow_generic_args) = candidate.0.trait_shallow_generic_args(db) else {
2068 continue;
2069 };
2070 let Ok(trait_params) = db.trait_generic_params(trait_id) else {
2071 continue;
2072 };
2073 let Some(first_param) = trait_params.first() else {
2074 res.entry(GenericsHeadFilter::NoGenerics).or_default().insert(*candidate);
2075 continue;
2076 };
2077
2078 let shallow_arg =
2080 shallow_generic_args.iter().find(|(param, _)| *param == first_param.id());
2081 if let Some(first_generic_head) = shallow_arg.map(|(_, arg)| arg.head()) {
2082 if !matches!(candidate.0, UninferredImpl::GenericParam(_)) {
2083 let mut type_head = first_generic_head.clone();
2084 while let TypeHead::Snapshot(inner) = type_head {
2085 type_head = *inner;
2086 }
2087 if matches!(type_head, TypeHead::Generic(_)) {
2088 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2089 continue;
2090 }
2091 }
2092 res.entry(GenericsHeadFilter::FirstGenericFilter(GenericArgumentHead::Type(
2093 first_generic_head,
2094 )))
2095 .or_default()
2096 .insert(*candidate);
2097 } else {
2098 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2099 }
2100 }
2101 }
2102 res
2103}
2104
2105pub fn find_candidates_at_context<'db>(
2107 db: &'db dyn Database,
2108 lookup_context: ImplLookupContextId<'db>,
2109 filter: TraitFilter<'db>,
2110) -> Maybe<OrderedHashSet<UninferredImplById<'db>>> {
2111 let mut res = OrderedHashSet::default();
2112 let lookup = lookup_context.long(db);
2113 let crate_id = lookup.crate_id;
2114 let locals = lookup
2115 .inner_impls
2116 .iter()
2117 .filter(|uninferred_impl| {
2118 let Ok(trait_id) = uninferred_impl.0.trait_id(db) else { return false };
2119 trait_id == filter.trait_id
2120 })
2121 .cloned();
2122 match filter.generics_filter {
2123 GenericsHeadFilter::NoFilter => {
2124 let globals = db.crate_global_impls(crate_id);
2125 let globals = globals.get(&filter.trait_id);
2126 res.extend(locals);
2127 res.extend(globals.into_iter().flat_map(|s| s.iter().cloned()))
2128 }
2129 _ => {
2130 let candidates_by_head = db.trait_candidate_by_head(crate_id, filter.trait_id);
2131 let filtered = candidates_by_head.get(&filter.generics_filter).cloned();
2132 let no_filtered = candidates_by_head.get(&GenericsHeadFilter::NoFilter).cloned();
2133 res.extend(filtered.into_iter().flat_map(|s| s.into_iter()));
2134 res.extend(no_filtered.into_iter().flat_map(|s| s.into_iter()));
2135 res.extend(locals.filter(|uninferred_impl| {
2136 let Ok(_) = uninferred_impl.0.concrete_trait(db) else {
2137 return false;
2138 };
2139 true
2142 }));
2143 }
2144 }
2145 Ok(res)
2146}
2147
2148pub fn find_closure_generated_candidate<'db>(
2150 db: &'db dyn Database,
2151 concrete_trait_id: ConcreteTraitId<'db>,
2152) -> Option<UninferredImpl<'db>> {
2153 let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
2154 return None;
2155 };
2156 let TypeLongId::Closure(closure_type_long) = closure_type.long(db) else {
2157 return None;
2158 };
2159
2160 let info = db.core_info();
2161
2162 let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
2164 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2165 chain!(
2166 closure_type_long.captured_types.iter().unique().map(|ty| {
2167 GenericParam::Impl(GenericParamImpl {
2168 id,
2169 concrete_trait: Maybe::Ok(ConcreteTraitId::new(
2170 db,
2171 ConcreteTraitLongId {
2172 trait_id,
2173 generic_args: vec![GenericArgumentId::Type(*ty)],
2174 },
2175 )),
2176 type_constraints: Default::default(),
2177 })
2178 }),
2179 neg_impl_trait.map(|neg_impl_trait| {
2180 GenericParam::NegImpl(GenericParamImpl {
2181 id,
2182 concrete_trait: Maybe::Ok(neg_impl_trait),
2183 type_constraints: Default::default(),
2184 })
2185 })
2186 )
2187 .collect()
2188 };
2189 let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
2190 (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
2191 };
2192 let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
2193 trait_id if trait_id == info.fn_once_trt => {
2194 let concrete_trait = ConcreteTraitLongId {
2195 trait_id,
2196 generic_args: vec![
2197 GenericArgumentId::Type(closure_type),
2198 GenericArgumentId::Type(
2199 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2200 ),
2201 ],
2202 }
2203 .intern(db);
2204 let ret_ty =
2205 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2206
2207 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2208 let param: GenericParam<'_> = GenericParam::NegImpl(GenericParamImpl {
2210 id,
2211 concrete_trait: Maybe::Ok(
2212 ConcreteTraitLongId {
2213 trait_id: info.fn_trt,
2214 generic_args: vec![
2215 GenericArgumentId::Type(closure_type),
2216 GenericArgumentId::Type(
2217 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2218 ),
2219 ],
2220 }
2221 .intern(db),
2222 ),
2223 type_constraints: Default::default(),
2224 });
2225 (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
2226 }
2227 trait_id if trait_id == info.fn_trt => {
2228 let concrete_trait = ConcreteTraitLongId {
2229 trait_id,
2230 generic_args: vec![
2231 GenericArgumentId::Type(closure_type),
2232 GenericArgumentId::Type(
2233 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2234 ),
2235 ],
2236 }
2237 .intern(db);
2238 let ret_ty =
2239 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2240
2241 (
2242 concrete_trait,
2243 mem_trait_generic_params(info.copy_trt, None),
2245 [(ret_ty, closure_type_long.ret_ty)].into(),
2246 )
2247 }
2248 trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2249 trait_id if trait_id == info.destruct_trt => {
2250 handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2251 }
2252 trait_id if trait_id == info.panic_destruct_trt => {
2253 handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2254 }
2255 trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2256 _ => return None,
2257 };
2258 Some(UninferredImpl::GeneratedImpl(
2259 UninferredGeneratedImplLongId {
2260 concrete_trait,
2261 generic_params,
2262 impl_items: GeneratedImplItems(impl_items),
2263 }
2264 .intern(db),
2265 ))
2266}
2267
2268pub fn find_integer_literal_generated_candidate<'db>(
2275 db: &'db dyn Database,
2276 concrete_trait_id: ConcreteTraitId<'db>,
2277) -> Option<UninferredImpl<'db>> {
2278 let GenericArgumentId::Type(ty) = *concrete_trait_id.generic_args(db).first()? else {
2279 return None;
2280 };
2281 if !matches!(ty.long(db), TypeLongId::NumericLiteral(_)) {
2282 return None;
2283 }
2284 let info = db.core_info();
2285 let trait_id = concrete_trait_id.trait_id(db);
2286 if ![info.drop_trt, info.copy_trt, info.destruct_trt, info.panic_destruct_trt]
2287 .contains(&trait_id)
2288 {
2289 return None;
2290 }
2291 Some(UninferredImpl::GeneratedImpl(
2292 UninferredGeneratedImplLongId {
2293 concrete_trait: concrete_trait_id,
2294 generic_params: vec![],
2295 impl_items: GeneratedImplItems(Default::default()),
2296 }
2297 .intern(db),
2298 ))
2299}
2300
2301pub fn can_infer_impl_by_self<'db>(
2307 ctx: &ComputationContext<'db, '_>,
2308 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2309 trait_function_id: TraitFunctionId<'db>,
2310 self_ty: TypeId<'db>,
2311 stable_ptr: SyntaxStablePtrId<'db>,
2312) -> bool {
2313 let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2314 let mut temp_inference = temp_inference_data.inference(ctx.db);
2315 let lookup_context = ctx.resolver.impl_lookup_context();
2316
2317 let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2318 trait_function_id,
2319 self_ty,
2320 lookup_context,
2321 Some(stable_ptr),
2322 inference_errors,
2323 ) else {
2324 return false;
2325 };
2326 if let Err(err_set) = temp_inference.solve() {
2328 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2330 inference_errors.push((trait_function_id, err));
2331 }
2332 }
2333 match temp_inference.trait_solution_set(
2334 concrete_trait_id,
2335 ImplVarTraitItemMappings::default(),
2336 lookup_context,
2337 ) {
2338 Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2339 Ok(SolutionSet::None) => {
2340 inference_errors
2341 .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2342 false
2343 }
2344 Err(err_set) => {
2345 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2347 inference_errors.push((trait_function_id, err));
2348 }
2349 false
2350 }
2351 }
2352}
2353
2354pub fn infer_impl_by_self<'db>(
2357 ctx: &mut ComputationContext<'db, '_>,
2358 trait_function_id: TraitFunctionId<'db>,
2359 self_ty: TypeId<'db>,
2360 stable_ptr: SyntaxStablePtrId<'db>,
2361 generic_args_syntax: Option<Vec<GenericArg<'db>>>,
2362) -> Maybe<(FunctionId<'db>, usize)> {
2363 let lookup_context = ctx.resolver.impl_lookup_context();
2364 let (concrete_trait_id, n_snapshots) = ctx
2365 .resolver
2366 .inference()
2367 .infer_concrete_trait_by_self_without_errors(
2368 trait_function_id,
2369 self_ty,
2370 lookup_context,
2371 Some(stable_ptr),
2372 )
2373 .ok_or_else(skip_diagnostic)?;
2374
2375 let concrete_trait_function_id =
2376 ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2377 .intern(ctx.db);
2378 let trait_func_generic_params =
2379 ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2380
2381 let impl_lookup_context = ctx.resolver.impl_lookup_context();
2382 let inference = &mut ctx.resolver.inference();
2383 let generic_function = inference.infer_trait_generic_function(
2384 concrete_trait_function_id,
2385 impl_lookup_context,
2386 Some(stable_ptr),
2387 );
2388 let generic_args = ctx.resolver.resolve_generic_args(
2389 ctx.diagnostics,
2390 GenericSubstitution::from_impl(generic_function.impl_id),
2391 trait_func_generic_params,
2392 &generic_args_syntax.unwrap_or_default(),
2393 stable_ptr,
2394 )?;
2395
2396 Ok((
2397 FunctionLongId {
2398 function: ConcreteFunction {
2399 generic_function: GenericFunctionId::Impl(generic_function),
2400 generic_args,
2401 },
2402 }
2403 .intern(ctx.db),
2404 n_snapshots,
2405 ))
2406}
2407
2408pub fn filter_candidate_traits<'db>(
2414 ctx: &mut ComputationContext<'db, '_>,
2415 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2416 self_ty: TypeId<'db>,
2417 candidate_traits: &[TraitId<'db>],
2418 function_name: SmolStrId<'db>,
2419 stable_ptr: SyntaxStablePtrId<'db>,
2420) -> Vec<TraitFunctionId<'db>> {
2421 let mut candidates = Vec::new();
2422 for trait_id in candidate_traits.iter().copied() {
2423 let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2424 continue;
2425 };
2426 for (&name, &trait_function) in trait_functions.iter() {
2427 if name == function_name
2428 && can_infer_impl_by_self(
2429 ctx,
2430 inference_errors,
2431 trait_function,
2432 self_ty,
2433 stable_ptr,
2434 )
2435 {
2436 candidates.push(trait_function);
2437 }
2438 }
2439 }
2440 candidates
2441}
2442
2443#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2446#[debug_db(dyn Database)]
2447struct ImplItemTypeData<'db> {
2448 type_alias_data: TypeAliasData<'db>,
2449 trait_type_id: Maybe<TraitTypeId<'db>>,
2450 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2452}
2453
2454#[salsa::tracked(cycle_result=impl_type_semantic_data_cycle, returns(ref))]
2460fn impl_type_semantic_data<'db>(
2461 db: &'db dyn Database,
2462 impl_type_def_id: ImplTypeDefId<'db>,
2463 in_cycle: bool,
2464) -> Maybe<ImplItemTypeData<'db>> {
2465 let mut diagnostics =
2466 SemanticDiagnostics::new(impl_type_def_id.impl_def_id(db).parent_module(db));
2467 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2468 let generic_params_data =
2469 impl_type_def_generic_params_data(db, impl_type_def_id).maybe_as_ref()?.clone();
2470 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2471
2472 let trait_type_id =
2473 validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, &impl_type_def_ast);
2474
2475 if in_cycle {
2476 Ok(ImplItemTypeData {
2477 type_alias_data: type_alias_semantic_data_cycle_helper(
2478 db,
2479 &mut diagnostics,
2480 &impl_type_def_ast,
2481 lookup_item_id,
2482 generic_params_data,
2483 )?,
2484 trait_type_id,
2485 diagnostics: diagnostics.build(),
2486 })
2487 } else {
2488 Ok(ImplItemTypeData {
2491 type_alias_data: type_alias_semantic_data_helper(
2492 db,
2493 &mut diagnostics,
2494 &impl_type_def_ast,
2495 lookup_item_id,
2496 generic_params_data,
2497 )?,
2498 trait_type_id,
2499 diagnostics: diagnostics.build(),
2500 })
2501 }
2502}
2503
2504fn impl_type_semantic_data_cycle<'db>(
2505 db: &'db dyn Database,
2506 _id: salsa::Id,
2507 impl_type_def_id: ImplTypeDefId<'db>,
2508 _in_cycle: bool,
2509) -> Maybe<ImplItemTypeData<'db>> {
2510 impl_type_semantic_data(db, impl_type_def_id, true).clone()
2511}
2512
2513#[salsa::tracked(returns(ref))]
2515fn impl_type_def_generic_params_data<'db>(
2516 db: &'db dyn Database,
2517 impl_type_def_id: ImplTypeDefId<'db>,
2518) -> Maybe<GenericParamsData<'db>> {
2519 let module_id = impl_type_def_id.parent_module(db);
2520 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2521 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2522
2523 let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2524 type_alias_generic_params_data_helper(
2525 db,
2526 module_id,
2527 &impl_type_def_ast,
2528 lookup_item_id,
2529 Some(impl_resolver_data),
2530 )
2531}
2532
2533fn validate_impl_item_type<'db>(
2535 db: &'db dyn Database,
2536 diagnostics: &mut SemanticDiagnostics<'db>,
2537 impl_type_def_id: ImplTypeDefId<'db>,
2538 impl_type_ast: &ast::ItemTypeAlias<'db>,
2539) -> Maybe<TraitTypeId<'db>> {
2540 let impl_def_id = impl_type_def_id.impl_def_id(db);
2541 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2542 let trait_id = concrete_trait_id.trait_id(db);
2543 let type_name = impl_type_def_id.name(db);
2544 let trait_type_id = db.trait_type_by_name(trait_id, type_name)?.ok_or_else(|| {
2545 diagnostics.report(
2546 impl_type_ast.stable_ptr(db),
2547 ImplItemNotInTrait {
2548 impl_def_id,
2549 impl_item_name: type_name,
2550 trait_id,
2551 item_kind: "type".into(),
2552 },
2553 )
2554 })?;
2555
2556 let generic_params_node = impl_type_ast.generic_params(db);
2559 if !generic_params_node.is_empty(db) {
2560 diagnostics.report(
2561 generic_params_node.stable_ptr(db),
2562 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2563 );
2564 }
2565
2566 Ok(trait_type_id)
2567}
2568
2569fn impl_type_concrete_implized<'db>(
2573 db: &'db dyn Database,
2574 impl_type_id: ImplTypeId<'db>,
2575) -> Maybe<TypeId<'db>> {
2576 let concrete_impl = match impl_type_id.impl_id().long(db) {
2577 ImplLongId::Concrete(concrete_impl) => concrete_impl,
2578 ImplLongId::ImplImpl(imp_impl_id) => {
2579 let ImplLongId::Concrete(concrete_impl) =
2580 db.impl_impl_concrete_implized(*imp_impl_id)?.long(db)
2581 else {
2582 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2583 };
2584 concrete_impl
2585 }
2586 ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2587 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2588 }
2589 ImplLongId::GeneratedImpl(generated) => {
2590 return Ok(*generated.long(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2591 }
2592 };
2593
2594 let impl_def_id = concrete_impl.impl_def_id(db);
2595 let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id)?;
2596 concrete_impl.substitution(db)?.substitute(db, ty)
2597}
2598
2599#[salsa::tracked(cycle_result=impl_type_concrete_implized_cycle)]
2600fn impl_type_concrete_implized_helper<'db>(
2601 db: &'db dyn Database,
2602 _tracked: Tracked,
2603 impl_type_id: ImplTypeId<'db>,
2604) -> Maybe<TypeId<'db>> {
2605 impl_type_concrete_implized(db, impl_type_id)
2606}
2607
2608fn impl_type_concrete_implized_tracked<'db>(
2610 db: &'db dyn Database,
2611 impl_type_id: ImplTypeId<'db>,
2612) -> Maybe<TypeId<'db>> {
2613 impl_type_concrete_implized_helper(db, (), impl_type_id)
2614}
2615
2616fn impl_type_concrete_implized_cycle<'db>(
2618 db: &'db dyn Database,
2619 _id: salsa::Id,
2620 _tracked: Tracked,
2621 impl_type_id: ImplTypeId<'db>,
2622) -> Maybe<TypeId<'db>> {
2623 impl_type_concrete_implized(db, impl_type_id)
2625}
2626
2627#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2630#[debug_db(dyn Database)]
2631struct ImplItemConstantData<'db> {
2632 constant_data: ConstantData<'db>,
2633 trait_constant_id: Maybe<TraitConstantId<'db>>,
2634 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2636}
2637
2638#[salsa::tracked(cycle_result=impl_constant_semantic_data_cycle, returns(ref))]
2640fn impl_constant_semantic_data<'db>(
2641 db: &'db dyn Database,
2642 impl_constant_def_id: ImplConstantDefId<'db>,
2643 in_cycle: bool,
2644) -> Maybe<ImplItemConstantData<'db>> {
2645 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2646 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2647 let impl_constant_defs = db.impl_constants(impl_def_id)?;
2648 let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2649 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2650
2651 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2652 ImplItemId::Constant(impl_constant_def_id),
2653 ));
2654 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2655 let mut resolver =
2656 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2657
2658 let trait_constant_id = validate_impl_item_constant(
2659 db,
2660 &mut diagnostics,
2661 impl_constant_def_id,
2662 impl_constant_def_ast,
2663 &mut resolver,
2664 );
2665 let mut constant_data = if in_cycle {
2666 constant_semantic_data_cycle_helper(
2667 db,
2668 impl_constant_def_ast,
2669 lookup_item_id,
2670 Some(Arc::new(resolver.data)),
2671 &impl_def_id,
2672 )?
2673 } else {
2674 constant_semantic_data_helper(
2675 db,
2676 impl_constant_def_ast,
2677 lookup_item_id,
2678 Some(Arc::new(resolver.data)),
2679 &impl_def_id,
2680 )?
2681 };
2682 diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2683 Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2684}
2685
2686fn impl_constant_semantic_data_cycle<'db>(
2687 db: &'db dyn Database,
2688 _id: salsa::Id,
2689 impl_constant_def_id: ImplConstantDefId<'db>,
2690 _in_cycle: bool,
2691) -> Maybe<ImplItemConstantData<'db>> {
2692 impl_constant_semantic_data(db, impl_constant_def_id, true).clone()
2693}
2694
2695fn validate_impl_item_constant<'db>(
2697 db: &'db dyn Database,
2698 diagnostics: &mut SemanticDiagnostics<'db>,
2699 impl_constant_def_id: ImplConstantDefId<'db>,
2700 impl_constant_ast: &ast::ItemConstant<'db>,
2701 resolver: &mut Resolver<'db>,
2702) -> Maybe<TraitConstantId<'db>> {
2703 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2704 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2705 let trait_id = concrete_trait_id.trait_id(db);
2706 let constant_name = impl_constant_def_id.name(db);
2707
2708 let trait_constant_id =
2709 db.trait_constant_by_name(trait_id, constant_name)?.ok_or_else(|| {
2710 diagnostics.report(
2711 impl_constant_ast.stable_ptr(db),
2712 ImplItemNotInTrait {
2713 impl_def_id,
2714 impl_item_name: constant_name,
2715 trait_id,
2716 item_kind: "const".into(),
2717 },
2718 )
2719 })?;
2720 let concrete_trait_constant =
2721 ConcreteTraitConstantId::new_from_data(db, concrete_trait_id, trait_constant_id);
2722 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2723 let concrete_trait_constant_ty = impl_def_substitution
2724 .substitute(db, db.concrete_trait_constant_type(concrete_trait_constant)?)?;
2725
2726 let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2727
2728 let constant_ty =
2729 resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2730
2731 let inference = &mut resolver.inference();
2732
2733 let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2734 let actual_ty = inference.rewrite(constant_ty).no_err();
2735 if expected_ty != actual_ty {
2736 diagnostics.report(
2737 impl_constant_type_clause_ast.ty(db).stable_ptr(db),
2738 WrongType { expected_ty, actual_ty },
2739 );
2740 }
2741 Ok(trait_constant_id)
2742}
2743
2744fn impl_constant_implized_by_context<'db>(
2748 db: &'db dyn Database,
2749 impl_constant_id: ImplConstantId<'db>,
2750 impl_def_id: ImplDefId<'db>,
2751) -> Maybe<ConstValueId<'db>> {
2752 let impl_constant_def_id: ImplConstantDefId<'_> =
2753 db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2754
2755 db.impl_constant_def_value(impl_constant_def_id)
2756}
2757
2758#[salsa::tracked(cycle_result=impl_constant_implized_by_context_cycle)]
2760fn impl_constant_implized_by_context_tracked<'db>(
2761 db: &'db dyn Database,
2762 impl_constant_id: ImplConstantId<'db>,
2763 impl_def_id: ImplDefId<'db>,
2764) -> Maybe<ConstValueId<'db>> {
2765 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2766}
2767
2768fn impl_constant_implized_by_context_cycle<'db>(
2770 db: &'db dyn Database,
2771 _id: salsa::Id,
2772 impl_constant_id: ImplConstantId<'db>,
2773 impl_def_id: ImplDefId<'db>,
2774) -> Maybe<ConstValueId<'db>> {
2775 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2777}
2778
2779fn impl_constant_concrete_implized_value<'db>(
2781 db: &'db dyn Database,
2782 impl_constant_id: ImplConstantId<'db>,
2783) -> Maybe<ConstValueId<'db>> {
2784 if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().long(db) {
2785 let impl_def_id = concrete_impl.impl_def_id(db);
2786 let constant: ConstValueId<'db> =
2787 db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2788 return concrete_impl.substitution(db)?.substitute(db, constant);
2789 }
2790 let substitution: GenericSubstitution<'db> =
2791 GenericSubstitution::from_impl(impl_constant_id.impl_id());
2792 let substitution_id = substitution.substitute(db, impl_constant_id)?;
2793 let const_val: ConstValue<'db> = ConstValue::ImplConstant(substitution_id);
2794 Ok(const_val.intern(db))
2795}
2796
2797fn impl_constant_concrete_implized_value_tracked<'db>(
2799 db: &'db dyn Database,
2800 impl_constant_id: ImplConstantId<'db>,
2801) -> Maybe<ConstValueId<'db>> {
2802 impl_constant_concrete_implized_value_helper(db, (), impl_constant_id)
2803}
2804
2805#[salsa::tracked(cycle_result=impl_constant_concrete_implized_value_cycle)]
2808fn impl_constant_concrete_implized_value_helper<'db>(
2809 db: &'db dyn Database,
2810 _tracked: Tracked,
2811 impl_constant_id: ImplConstantId<'db>,
2812) -> Maybe<ConstValueId<'db>> {
2813 impl_constant_concrete_implized_value(db, impl_constant_id)
2814}
2815
2816fn impl_constant_concrete_implized_value_cycle<'db>(
2818 db: &'db dyn Database,
2819 _id: salsa::Id,
2820 _tracked: Tracked,
2821 impl_constant_id: ImplConstantId<'db>,
2822) -> Maybe<ConstValueId<'db>> {
2823 impl_constant_concrete_implized_value(db, impl_constant_id)
2825}
2826
2827fn impl_constant_concrete_implized_type<'db>(
2829 db: &'db dyn Database,
2830 impl_constant_id: ImplConstantId<'db>,
2831) -> Maybe<TypeId<'db>> {
2832 let concrete_trait_id = match impl_constant_id.impl_id().long(db) {
2833 ImplLongId::Concrete(concrete_impl) => {
2834 let impl_def_id = concrete_impl.impl_def_id(db);
2835 let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2836 return concrete_impl.substitution(db)?.substitute(db, ty);
2837 }
2838 ImplLongId::GenericParameter(param) => {
2839 let param_impl =
2840 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
2841 param_impl.concrete_trait?
2842 }
2843 ImplLongId::ImplVar(var) => var.long(db).concrete_trait_id,
2844 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl)?,
2845 ImplLongId::SelfImpl(concrete_trait_id) => *concrete_trait_id,
2846 ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2847 };
2848
2849 let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new_from_data(
2850 db,
2851 concrete_trait_id,
2852 impl_constant_id.trait_constant_id(),
2853 ))?;
2854 GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2855}
2856
2857fn impl_constant_concrete_implized_type_tracked<'db>(
2859 db: &'db dyn Database,
2860 impl_constant_id: ImplConstantId<'db>,
2861) -> Maybe<TypeId<'db>> {
2862 impl_constant_concrete_implized_type_helper(db, (), impl_constant_id)
2863}
2864
2865#[salsa::tracked(cycle_result=impl_constant_concrete_implized_type_cycle)]
2866fn impl_constant_concrete_implized_type_helper<'db>(
2867 db: &'db dyn Database,
2868 _tracked: Tracked,
2869 impl_constant_id: ImplConstantId<'db>,
2870) -> Maybe<TypeId<'db>> {
2871 impl_constant_concrete_implized_type(db, impl_constant_id)
2872}
2873
2874fn impl_constant_concrete_implized_type_cycle<'db>(
2876 db: &'db dyn Database,
2877 _id: salsa::Id,
2878 _tracked: Tracked,
2879 impl_constant_id: ImplConstantId<'db>,
2880) -> Maybe<TypeId<'db>> {
2881 impl_constant_concrete_implized_type(db, impl_constant_id)
2883}
2884
2885#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2888#[debug_db(dyn Database)]
2889struct ImplItemImplData<'db> {
2890 impl_data: ImplAliasData<'db>,
2891 trait_impl_id: Maybe<TraitImplId<'db>>,
2892 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2894}
2895
2896#[salsa::tracked(cycle_result=impl_impl_semantic_data_cycle, returns(ref))]
2898fn impl_impl_semantic_data<'db>(
2899 db: &'db dyn Database,
2900 impl_impl_def_id: ImplImplDefId<'db>,
2901 in_cycle: bool,
2902) -> Maybe<ImplItemImplData<'db>> {
2903 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2904 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2905 let impl_impl_defs = db.impl_impls(impl_def_id)?;
2906 let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2907 let generic_params_data =
2908 impl_impl_def_generic_params_data(db, impl_impl_def_id).maybe_as_ref()?.clone();
2909 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2910
2911 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2912 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2913 let mut resolver =
2914 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2915
2916 let mut impl_data = if in_cycle {
2917 impl_alias_semantic_data_cycle_helper(
2918 db,
2919 impl_impl_def_ast,
2920 lookup_item_id,
2921 generic_params_data,
2922 )?
2923 } else {
2924 impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2925 };
2926
2927 diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2928
2929 let trait_impl_id = validate_impl_item_impl(
2930 db,
2931 &mut diagnostics,
2932 impl_impl_def_id,
2933 impl_impl_def_ast,
2934 &impl_data,
2935 &mut resolver,
2936 );
2937
2938 Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2939}
2940
2941fn impl_impl_semantic_data_cycle<'db>(
2942 db: &'db dyn Database,
2943 _id: salsa::Id,
2944 impl_impl_def_id: ImplImplDefId<'db>,
2945 _in_cycle: bool,
2946) -> Maybe<ImplItemImplData<'db>> {
2947 impl_impl_semantic_data(db, impl_impl_def_id, true).clone()
2948}
2949
2950#[salsa::tracked(returns(ref))]
2952fn impl_impl_def_generic_params_data<'db>(
2953 db: &'db dyn Database,
2954 impl_impl_def_id: ImplImplDefId<'db>,
2955) -> Maybe<GenericParamsData<'db>> {
2956 let module_id = impl_impl_def_id.parent_module(db);
2957 let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?;
2958 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2959
2960 let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2961 impl_alias_generic_params_data_helper(
2962 db,
2963 module_id,
2964 &impl_impl_def_ast,
2965 lookup_item_id,
2966 Some(impl_resolver_data),
2967 )
2968}
2969
2970fn validate_impl_item_impl<'db>(
2972 db: &'db dyn Database,
2973 diagnostics: &mut SemanticDiagnostics<'db>,
2974 impl_impl_def_id: ImplImplDefId<'db>,
2975 impl_impl_ast: &ast::ItemImplAlias<'db>,
2976 impl_data: &ImplAliasData<'db>,
2977 resolver: &mut Resolver<'db>,
2978) -> Maybe<TraitImplId<'db>> {
2979 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2980 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2981 let trait_id = concrete_trait_id.trait_id(db);
2982 let impl_item_name = impl_impl_def_id.name(db);
2983 let trait_impl_id = db.trait_impl_by_name(trait_id, impl_item_name)?.ok_or_else(|| {
2984 diagnostics.report(
2985 impl_impl_ast.stable_ptr(db),
2986 ImplItemNotInTrait { impl_def_id, impl_item_name, trait_id, item_kind: "impl".into() },
2987 )
2988 })?;
2989
2990 let generic_params_node = impl_impl_ast.generic_params(db);
2993 if !generic_params_node.is_empty(db) {
2994 diagnostics.report(
2995 generic_params_node.stable_ptr(db),
2996 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2997 );
2998 }
2999
3000 let concrete_trait_impl =
3001 ConcreteTraitImplId::new_from_data(db, concrete_trait_id, trait_impl_id);
3002 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3003
3004 let concrete_trait_impl_concrete_trait = db
3005 .concrete_trait_impl_concrete_trait(concrete_trait_impl)
3006 .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
3007
3008 let resolved_impl_concrete_trait =
3009 impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
3010 let _ = (|| -> Result<(), DiagnosticAdded> {
3012 if resolver
3013 .inference()
3014 .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
3015 .is_err()
3016 {
3017 diagnostics.report(
3018 impl_impl_ast.stable_ptr(db),
3019 TraitMismatch {
3020 expected_trt: concrete_trait_impl_concrete_trait?,
3021 actual_trt: resolved_impl_concrete_trait?,
3022 },
3023 );
3024 }
3025 Ok(())
3026 })();
3027
3028 Ok(trait_impl_id)
3029}
3030
3031#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3032#[debug_db(dyn Database)]
3033struct ImplicitImplImplData<'db> {
3034 resolved_impl: Maybe<ImplId<'db>>,
3035 trait_impl_id: TraitImplId<'db>,
3036 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
3037}
3038
3039fn implicit_impl_impl_semantic_data<'db>(
3041 db: &'db dyn Database,
3042 impl_def_id: ImplDefId<'db>,
3043 trait_impl_id: TraitImplId<'db>,
3044 in_cycle: bool,
3045) -> Maybe<ImplicitImplImplData<'db>> {
3046 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3047 if in_cycle {
3048 let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
3049 return Ok(ImplicitImplImplData {
3050 resolved_impl: err,
3051 trait_impl_id,
3052 diagnostics: diagnostics.build(),
3053 });
3054 }
3055 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
3056
3057 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3058 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3059
3060 let mut resolver =
3061 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3062 resolver.trait_or_impl_ctx = TraitOrImplContext::None;
3064
3065 let concrete_trait_impl_concrete_trait = db
3066 .impl_def_concrete_trait(impl_def_id)
3067 .and_then(|concrete_trait_id| {
3068 db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new_from_data(
3069 db,
3070 concrete_trait_id,
3071 trait_impl_id,
3072 ))
3073 })
3074 .and_then(|concrete_trait_id| {
3075 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3076 impl_def_substitution.substitute(db, concrete_trait_id)
3077 });
3078 let impl_lookup_context = resolver.impl_lookup_context();
3079 let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
3080 let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
3081 resolver.inference().finalize_without_reporting().map_err(|err_set| {
3082 diagnostics.report(
3083 impl_def_id.stable_ptr(db).untyped(),
3084 ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
3085 );
3086 resolver.inference().report_on_pending_error(
3087 err_set,
3088 &mut diagnostics,
3089 impl_def_id.stable_ptr(db).untyped(),
3090 )
3091 })?;
3092 resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
3093 });
3094
3095 Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
3096}
3097
3098#[salsa::tracked(cycle_result=implicit_impl_impl_semantic_data_cycle, returns(ref))]
3100fn implicit_impl_impl_semantic_data_tracked<'db>(
3101 db: &'db dyn Database,
3102 impl_def_id: ImplDefId<'db>,
3103 trait_impl_id: TraitImplId<'db>,
3104 in_cycle: bool,
3105) -> Maybe<ImplicitImplImplData<'db>> {
3106 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, in_cycle)
3107}
3108
3109fn implicit_impl_impl_semantic_data_cycle<'db>(
3111 db: &'db dyn Database,
3112 _id: salsa::Id,
3113 impl_def_id: ImplDefId<'db>,
3114 trait_impl_id: TraitImplId<'db>,
3115 _in_cycle: bool,
3116) -> Maybe<ImplicitImplImplData<'db>> {
3117 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, true)
3119}
3120
3121fn impl_impl_implized_by_context<'db>(
3125 db: &'db dyn Database,
3126 impl_impl_id: ImplImplId<'db>,
3127 impl_def_id: ImplDefId<'db>,
3128 in_cycle: bool,
3129) -> Maybe<ImplId<'db>> {
3130 if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
3131 return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
3132 }
3133
3134 let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
3135
3136 db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
3137}
3138
3139#[salsa::tracked(cycle_result=impl_impl_implized_by_context_cycle)]
3141fn impl_impl_implized_by_context_tracked<'db>(
3142 db: &'db dyn Database,
3143 impl_impl_id: ImplImplId<'db>,
3144 impl_def_id: ImplDefId<'db>,
3145 in_cycle: bool,
3146) -> Maybe<ImplId<'db>> {
3147 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, in_cycle)
3148}
3149
3150fn impl_impl_implized_by_context_cycle<'db>(
3152 db: &'db dyn Database,
3153 _id: salsa::Id,
3154 impl_impl_id: ImplImplId<'db>,
3155 impl_def_id: ImplDefId<'db>,
3156 _in_cycle: bool,
3157) -> Maybe<ImplId<'db>> {
3158 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, true)
3160}
3161
3162fn impl_impl_concrete_implized<'db>(
3164 db: &'db dyn Database,
3165 impl_impl_id: ImplImplId<'db>,
3166) -> Maybe<ImplId<'db>> {
3167 impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3168}
3169
3170fn impl_impl_concrete_implized_tracked<'db>(
3172 db: &'db dyn Database,
3173 impl_impl_id: ImplImplId<'db>,
3174) -> Maybe<ImplId<'db>> {
3175 impl_impl_concrete_implized_helper(db, (), impl_impl_id)
3176}
3177
3178#[salsa::tracked(cycle_result=impl_impl_concrete_implized_cycle)]
3179fn impl_impl_concrete_implized_helper<'db>(
3180 db: &'db dyn Database,
3181 _tracked: Tracked,
3182 impl_impl_id: ImplImplId<'db>,
3183) -> Maybe<ImplId<'db>> {
3184 impl_impl_concrete_implized(db, impl_impl_id)
3185}
3186
3187fn impl_impl_concrete_implized_cycle<'db>(
3189 db: &'db dyn Database,
3190 _id: salsa::Id,
3191 _tracked: Tracked,
3192 impl_impl_id: ImplImplId<'db>,
3193) -> Maybe<ImplId<'db>> {
3194 impl_impl_concrete_implized_ex(db, impl_impl_id, true)
3195}
3196
3197fn impl_impl_concrete_implized_ex<'db>(
3198 db: &'db dyn Database,
3199 impl_impl_id: ImplImplId<'db>,
3200 in_cycle: bool,
3201) -> Maybe<ImplId<'db>> {
3202 if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().long(db) {
3203 let impl_def_id = concrete_impl.impl_def_id(db);
3204 let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
3205 return concrete_impl.substitution(db)?.substitute(db, imp);
3206 }
3207
3208 Ok(ImplLongId::ImplImpl(
3209 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, impl_impl_id)?,
3210 )
3211 .intern(db))
3212}
3213
3214fn impl_impl_concrete_trait<'db>(
3216 db: &'db dyn Database,
3217 impl_impl_id: ImplImplId<'db>,
3218) -> Maybe<ConcreteTraitId<'db>> {
3219 let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
3220 db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
3221 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, concrete_trait_id)
3222 })
3223}
3224
3225fn impl_impl_concrete_trait_tracked<'db>(
3227 db: &'db dyn Database,
3228 impl_impl_id: ImplImplId<'db>,
3229) -> Maybe<ConcreteTraitId<'db>> {
3230 impl_impl_concrete_trait_helper(db, (), impl_impl_id)
3231}
3232
3233#[salsa::tracked]
3234fn impl_impl_concrete_trait_helper<'db>(
3235 db: &'db dyn Database,
3236 _tracked: Tracked,
3237 impl_impl_id: ImplImplId<'db>,
3238) -> Maybe<ConcreteTraitId<'db>> {
3239 impl_impl_concrete_trait(db, impl_impl_id)
3240}
3241
3242#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3245#[debug_db(dyn Database)]
3246struct ImplFunctionDeclarationData<'db> {
3247 function_declaration_data: FunctionDeclarationData<'db>,
3248 trait_function_id: Maybe<TraitFunctionId<'db>>,
3249}
3250
3251#[salsa::tracked(returns(ref))]
3253fn impl_function_generic_params_data<'db>(
3254 db: &'db dyn Database,
3255 impl_function_id: ImplFunctionId<'db>,
3256) -> Maybe<GenericParamsData<'db>> {
3257 let module_id = impl_function_id.parent_module(db);
3258 let mut diagnostics = SemanticDiagnostics::new(module_id);
3259 let impl_def_id = impl_function_id.impl_def_id(db);
3260 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3261 let function_syntax = &data.function_asts[&impl_function_id];
3262 let declaration = function_syntax.declaration(db);
3263 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
3264 ImplItemId::Function(impl_function_id),
3265 ));
3266 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3267 let mut resolver =
3268 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3269 let generic_params = semantic_generic_params(
3270 db,
3271 &mut diagnostics,
3272 &mut resolver,
3273 module_id,
3274 &declaration.generic_params(db),
3275 );
3276 let inference = &mut resolver.inference();
3277 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3278
3279 let generic_params = inference.rewrite(generic_params).no_err();
3280 let resolver_data = Arc::new(resolver.data);
3281 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
3282}
3283
3284#[salsa::tracked(returns(ref))]
3286fn impl_function_declaration_data<'db>(
3287 db: &'db dyn Database,
3288 impl_function_id: ImplFunctionId<'db>,
3289) -> Maybe<ImplFunctionDeclarationData<'db>> {
3290 let impl_def_id = impl_function_id.impl_def_id(db);
3291 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3292 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3293 let function_syntax = &data.function_asts[&impl_function_id];
3294 let declaration = function_syntax.declaration(db);
3295
3296 let generic_params_data =
3297 impl_function_generic_params_data(db, impl_function_id).maybe_as_ref()?.clone();
3298 let generic_params = generic_params_data.generic_params;
3299 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3300 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3301 let mut resolver = Resolver::with_data(
3302 db,
3303 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3304 );
3305 diagnostics.extend(generic_params_data.diagnostics);
3306 resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3307
3308 let mut environment = Environment::empty();
3309 let signature = semantic::Signature::from_ast(
3310 &mut diagnostics,
3311 db,
3312 &mut resolver,
3313 &declaration,
3314 FunctionTitleId::Impl(impl_function_id),
3315 &mut environment,
3316 );
3317
3318 let attributes = function_syntax.attributes(db).structurize(db);
3319 let (implicit_precedence, _) =
3320 get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
3321
3322 let inference = &mut resolver.inference();
3323 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3325 let signature_syntax = declaration.signature(db);
3326 let trait_function_id = validate_impl_function_signature(
3327 db,
3328 &mut diagnostics,
3329 inference,
3330 ValidateImplFunctionSignatureParams {
3331 impl_function_id,
3332 signature_syntax: &signature_syntax,
3333 signature: &signature,
3334 impl_function_syntax: function_syntax,
3335 impl_func_generics: &generic_params,
3336 },
3337 );
3338
3339 let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3340
3341 forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3342
3343 let signature = inference.rewrite(signature).no_err();
3344
3345 let resolver_data = Arc::new(resolver.data);
3346 Ok(ImplFunctionDeclarationData {
3347 function_declaration_data: FunctionDeclarationData {
3348 diagnostics: diagnostics.build(),
3349 signature,
3350 environment,
3351 attributes,
3352 resolver_data,
3353 inline_config,
3354 implicit_precedence,
3355 },
3356 trait_function_id,
3357 })
3358}
3359
3360struct ValidateImplFunctionSignatureParams<'a, 'r> {
3362 impl_function_id: ImplFunctionId<'a>,
3364 signature_syntax: &'r ast::FunctionSignature<'a>,
3366 signature: &'r semantic::Signature<'a>,
3368 impl_function_syntax: &'r ast::FunctionWithBody<'a>,
3370 impl_func_generics: &'r [GenericParam<'a>],
3372}
3373
3374fn validate_impl_function_signature<'db>(
3376 db: &'db dyn Database,
3377 diagnostics: &mut SemanticDiagnostics<'db>,
3378 inference: &mut Inference<'db, '_>,
3379 ValidateImplFunctionSignatureParams {
3380 impl_function_id,
3381 signature_syntax,
3382 signature,
3383 impl_function_syntax,
3384 impl_func_generics,
3385 }: ValidateImplFunctionSignatureParams<'db, '_>,
3386) -> Maybe<TraitFunctionId<'db>> {
3387 let impl_def_id = impl_function_id.impl_def_id(db);
3388 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3389 let trait_id = concrete_trait_id.trait_id(db);
3390 let function_name = impl_function_id.name(db);
3391 let trait_function_id =
3392 db.trait_function_by_name(trait_id, function_name)?.ok_or_else(|| {
3393 diagnostics.report(
3394 impl_function_syntax.stable_ptr(db),
3395 ImplItemNotInTrait {
3396 impl_def_id,
3397 impl_item_name: function_name,
3398 trait_id,
3399 item_kind: "function".into(),
3400 },
3401 )
3402 })?;
3403 let concrete_trait_function =
3404 ConcreteTraitGenericFunctionId::new_from_data(db, concrete_trait_id, trait_function_id);
3405 let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3406
3407 let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3411 if impl_func_generics.len() != func_generics.len() {
3412 diagnostics.report(
3413 impl_function_syntax.declaration(db).name(db).stable_ptr(db),
3414 WrongNumberOfGenericParamsForImplFunction {
3415 expected: func_generics.len(),
3416 actual: impl_func_generics.len(),
3417 },
3418 );
3419 return Ok(trait_function_id);
3420 }
3421 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3422 let func_generics: Vec<GenericParam<'_>> =
3423 impl_def_substitution.substitute(db, func_generics.to_vec())?;
3424
3425 let function_substitution =
3426 GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3427
3428 for (trait_generic_param, generic_param) in izip!(func_generics, impl_func_generics.iter()) {
3429 if let Some(name) = trait_generic_param.id().name(db)
3430 && Some(name) != generic_param.id().name(db)
3431 {
3432 diagnostics.report(
3433 generic_param.stable_ptr(db),
3434 WrongParameterName { impl_def_id, impl_function_id, trait_id, expected_name: name },
3435 );
3436 }
3437 match (generic_param, trait_generic_param) {
3438 (GenericParam::Type(_), GenericParam::Type(_)) => {}
3439 (GenericParam::Impl(generic_param), GenericParam::Impl(trait_generic_param))
3440 | (GenericParam::NegImpl(generic_param), GenericParam::NegImpl(trait_generic_param)) => {
3441 let rewritten_trait_param_trait =
3442 function_substitution.substitute(db, trait_generic_param.concrete_trait)?;
3443 let rewritten_trait_param_type_constraints =
3444 function_substitution.substitute(db, trait_generic_param.type_constraints)?;
3445 generic_param
3446 .concrete_trait
3447 .map(|actual_trait| {
3448 rewritten_trait_param_trait
3449 .map(|expected_trait| {
3450 if actual_trait != expected_trait
3451 || generic_param.type_constraints
3452 != rewritten_trait_param_type_constraints
3453 {
3454 diagnostics.report(
3455 generic_param.id.stable_ptr(db),
3456 WrongGenericParamTraitForImplFunction {
3457 impl_def_id,
3458 impl_function_id,
3459 trait_id,
3460 expected_trait,
3461 actual_trait,
3462 },
3463 );
3464 }
3465 })
3466 .ok();
3467 })
3468 .ok();
3469 }
3470 (GenericParam::Const(generic_param), GenericParam::Const(trait_generic_param)) => {
3471 let expected_ty = function_substitution.substitute(db, trait_generic_param.ty)?;
3472 if generic_param.ty != expected_ty {
3473 diagnostics.report(
3474 generic_param.id.stable_ptr(db),
3475 WrongParameterType {
3476 impl_def_id,
3477 impl_function_id,
3478 trait_id,
3479 expected_ty,
3480 actual_ty: generic_param.ty,
3481 },
3482 );
3483 }
3484 }
3485 (generic_param, trait_generic_param) => {
3486 diagnostics.report(
3487 generic_param.stable_ptr(db),
3488 WrongGenericParamKindForImplFunction {
3489 impl_def_id,
3490 impl_function_id,
3491 trait_id,
3492 expected_kind: trait_generic_param.kind(),
3493 actual_kind: generic_param.kind(),
3494 },
3495 );
3496 }
3497 }
3498 }
3499
3500 let concrete_trait_signature =
3501 function_substitution.substitute(db, concrete_trait_signature.clone())?;
3502
3503 if signature.params.len() != concrete_trait_signature.params.len() {
3504 diagnostics.report(
3505 signature_syntax.parameters(db).stable_ptr(db),
3506 WrongNumberOfParameters {
3507 impl_def_id,
3508 impl_function_id,
3509 trait_id,
3510 expected: concrete_trait_signature.params.len(),
3511 actual: signature.params.len(),
3512 },
3513 );
3514 }
3515 let concrete_trait_signature =
3516 impl_def_substitution.substitute(db, concrete_trait_signature)?;
3517 for (param, trait_param) in
3518 izip!(signature.params.iter(), concrete_trait_signature.params.iter())
3519 {
3520 let expected_ty = inference.rewrite(trait_param.ty).no_err();
3521 let actual_ty = inference.rewrite(param.ty).no_err();
3522
3523 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3524 diagnostics.report(
3525 extract_matches!(
3526 param.stable_ptr(db).lookup(db).type_clause(db),
3527 OptionTypeClause::TypeClause
3528 )
3529 .ty(db)
3530 .stable_ptr(db),
3531 WrongParameterType {
3532 impl_def_id,
3533 impl_function_id,
3534 trait_id,
3535 expected_ty,
3536 actual_ty,
3537 },
3538 );
3539 }
3540
3541 if trait_param.mutability != param.mutability {
3542 if trait_param.mutability == Mutability::Reference {
3543 diagnostics.report(
3544 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3545 ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3546 );
3547 }
3548
3549 if param.mutability == Mutability::Reference {
3550 diagnostics.report(
3551 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3552 ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3553 );
3554 }
3555 }
3556
3557 if trait_param.name != param.name {
3558 diagnostics.report(
3559 param.stable_ptr(db).lookup(db).name(db).stable_ptr(db),
3560 WrongParameterName {
3561 impl_def_id,
3562 impl_function_id,
3563 trait_id,
3564 expected_name: trait_param.name,
3565 },
3566 );
3567 }
3568 }
3569
3570 if !concrete_trait_signature.panicable && signature.panicable {
3571 diagnostics.report(
3572 signature_syntax.stable_ptr(db),
3573 PassPanicAsNopanic { impl_function_id, trait_id },
3574 );
3575 }
3576
3577 if concrete_trait_signature.is_const && !signature.is_const {
3578 diagnostics.report(
3579 signature_syntax.stable_ptr(db),
3580 PassConstAsNonConst { impl_function_id, trait_id },
3581 );
3582 }
3583
3584 let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3585 let actual_ty = inference.rewrite(signature.return_type).no_err();
3586
3587 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3588 let location_ptr = match signature_syntax.ret_ty(db) {
3589 OptionReturnTypeClause::ReturnTypeClause(ret_ty) => ret_ty.ty(db).as_syntax_node(),
3590 OptionReturnTypeClause::Empty(_) => {
3591 impl_function_syntax.body(db).lbrace(db).as_syntax_node()
3592 }
3593 }
3594 .stable_ptr(db);
3595 diagnostics.report(
3596 location_ptr,
3597 WrongReturnTypeForImpl {
3598 impl_def_id,
3599 impl_function_id,
3600 trait_id,
3601 expected_ty,
3602 actual_ty,
3603 },
3604 );
3605 }
3606 Ok(trait_function_id)
3607}
3608
3609fn priv_impl_function_body_data<'db>(
3611 db: &'db dyn Database,
3612 impl_function_id: ImplFunctionId<'db>,
3613) -> Maybe<FunctionBodyData<'db>> {
3614 let impl_def_id = impl_function_id.impl_def_id(db);
3615 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3616 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3617 let function_syntax = &data.function_asts[&impl_function_id];
3618 let declaration = impl_function_declaration_data(db, impl_function_id).maybe_as_ref()?;
3620 let parent_resolver_data = declaration.function_declaration_data.resolver_data.clone();
3621 let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3622 ImplItemId::Function(impl_function_id),
3623 ));
3624 let mut resolver =
3625 Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3626 let environment: Environment<'_> = declaration.function_declaration_data.environment.clone();
3627
3628 let function_id = (|| {
3629 let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3630 let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3631
3632 let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3633 impl_id: ImplLongId::Concrete(
3634 ConcreteImplLongId {
3635 impl_def_id,
3636 generic_args: generic_params_to_args(generic_parameters, db),
3637 }
3638 .intern(db),
3639 )
3640 .intern(db),
3641 function: trait_function_id,
3642 });
3643
3644 Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3645 })();
3646 let mut ctx = ComputationContext::new(
3648 db,
3649 &mut diagnostics,
3650 &mut resolver,
3651 Some(&declaration.function_declaration_data.signature),
3652 environment,
3653 ContextFunction::Function(function_id),
3654 );
3655 let function_body = function_syntax.body(db);
3656 let return_type = declaration.function_declaration_data.signature.return_type;
3657 let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3658 let ComputationContext { arenas, .. } = ctx;
3659
3660 let expr_lookup: UnorderedHashMap<_, _> =
3661 arenas.exprs.iter().map(|(id, expr)| (expr.stable_ptr(), id)).collect();
3662 let pattern_lookup: UnorderedHashMap<_, _> =
3663 arenas.patterns.iter().map(|(id, pattern)| (pattern.stable_ptr(), id)).collect();
3664 let resolver_data = Arc::new(resolver.data);
3665 Ok(FunctionBodyData {
3666 diagnostics: diagnostics.build(),
3667 expr_lookup,
3668 pattern_lookup,
3669 resolver_data,
3670 body: FunctionBody { arenas, body_expr },
3671 })
3672}
3673
3674#[salsa::tracked(returns(ref))]
3676fn priv_impl_function_body_data_tracked<'db>(
3677 db: &'db dyn Database,
3678 impl_function_id: ImplFunctionId<'db>,
3679) -> Maybe<FunctionBodyData<'db>> {
3680 priv_impl_function_body_data(db, impl_function_id)
3681}
3682
3683#[salsa::tracked]
3684fn impl_is_fully_concrete<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3685 impl_id.long(db).is_fully_concrete(db)
3686}
3687
3688#[salsa::tracked]
3689fn impl_is_var_free<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3690 impl_id.long(db).is_var_free(db)
3691}
3692
3693#[salsa::tracked(returns(ref))]
3695fn crate_dependencies<'db>(
3696 db: &'db dyn Database,
3697 crate_id: CrateId<'db>,
3698) -> OrderedHashSet<CrateId<'db>> {
3699 let mut crates = [crate_id, db.core_crate()].into_iter().unique().collect_vec();
3700 let mut crates_set: OrderedHashSet<CrateId<'db>, _> = OrderedHashSet::<
3701 CrateId<'db>,
3702 std::collections::hash_map::RandomState,
3703 >::from_iter(crates.iter().copied());
3704 while let Some(crate_id) = crates.pop() {
3705 let default_settings = Default::default();
3706 let settings =
3707 db.crate_config(crate_id).as_ref().map(|c| &c.settings).unwrap_or(&default_settings);
3708
3709 for (ident, dep) in &settings.dependencies {
3710 let dep_crate_id = CrateLongId::Real {
3711 name: SmolStrId::from(db, ident.clone()),
3712 discriminator: dep.discriminator.clone(),
3713 }
3714 .intern(db);
3715 if !crates_set.contains(&dep_crate_id) {
3716 crates.push(dep_crate_id);
3717 crates_set.insert(dep_crate_id);
3718 }
3719 }
3720 }
3721 crates_set
3722}
3723
3724#[salsa::tracked(returns(ref))]
3725fn crate_global_impls<'db>(
3727 db: &'db dyn Database,
3728 crate_id: CrateId<'db>,
3729) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
3730 let mut crate_global_impls: UnorderedHashMap<
3731 TraitId<'db>,
3732 OrderedHashSet<UninferredImplById<'db>>,
3733 > = UnorderedHashMap::default();
3734 for crate_id in crate_dependencies(db, crate_id).iter() {
3735 let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3736 while let Some(module_id) = modules.pop() {
3737 if let Ok(module_impls) = db.module_global_impls((), module_id) {
3738 for (trait_id, impls) in module_impls.globals_by_trait.iter() {
3739 crate_global_impls.entry(*trait_id).or_default().extend(impls.clone());
3740 }
3741 }
3742 if let Ok(x) = db.module_submodules_ids(module_id) {
3743 modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3744 }
3745 if let Ok(macro_call_ids) = db.module_macro_calls_ids(module_id) {
3746 modules.extend(
3747 macro_call_ids
3748 .iter()
3749 .map(|id| db.macro_call_module_id(*id))
3750 .filter_map(|x| x.ok()),
3751 )
3752 }
3753 }
3754 }
3755 crate_global_impls
3756}
3757
3758#[salsa::tracked(returns(ref))]
3760fn crate_traits_dependencies<'db>(
3761 db: &'db dyn Database,
3762 crate_id: CrateId<'db>,
3763) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
3764 let mut dependencies: UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> =
3765 UnorderedHashMap::default();
3766 for crate_id in crate_dependencies(db, crate_id).iter() {
3767 let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3768 while let Some(module_id) = modules.pop() {
3769 if let Ok(module_impls) = db.module_global_impls((), module_id) {
3770 for (trait_id, impls) in module_impls.trait_deps.iter() {
3771 dependencies.entry(*trait_id).or_default().extend(impls.clone());
3772 }
3773 }
3774 if let Ok(x) = db.module_submodules_ids(module_id) {
3775 modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3776 }
3777 }
3778 }
3779
3780 dependencies
3781}
3782
3783#[salsa::tracked(returns(ref))]
3785fn reachable_trait_dependencies<'db>(
3786 db: &'db dyn Database,
3787 trait_id: TraitId<'db>,
3788 crate_id: CrateId<'db>,
3789) -> OrderedHashSet<TraitId<'db>> {
3790 let dependencies = db.crate_traits_dependencies(crate_id);
3791 let mut reachable_deps = OrderedHashSet::default();
3792 let mut to_visit = vec![trait_id];
3793 let mut visited: UnorderedHashSet<TraitId<'db>> = UnorderedHashSet::default();
3794 while let Some(current_trait) = to_visit.pop() {
3795 if visited.contains(¤t_trait) {
3796 continue;
3797 }
3798 visited.insert(current_trait);
3799 if let Some(deps) = dependencies.get(¤t_trait) {
3800 for dep in deps.iter() {
3801 reachable_deps.insert(*dep);
3802 if !visited.contains(dep) {
3803 to_visit.push(*dep);
3804 }
3805 }
3806 }
3807 }
3808 reachable_deps
3809}
3810
3811fn uninferred_impl_trait_dependency<'db>(
3813 db: &'db dyn Database,
3814 impl_id: UninferredImpl<'db>,
3815 trait_deps: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3816) -> Maybe<()> {
3817 if let Ok(imp_trait_id) = impl_id.trait_id(db) {
3818 let (mut resolver, module_id, generic_params, mut diagnostics) = match impl_id {
3819 UninferredImpl::Def(impl_def_id) => {
3820 let module_id = impl_def_id.parent_module(db);
3821 let mut diagnostics = SemanticDiagnostics::new(module_id);
3822
3823 let impl_ast = db.module_impl_by_id(impl_def_id)?;
3824 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
3825
3826 let mut resolver = Resolver::new(db, module_id, inference_id);
3827 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
3828 (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3829 }
3830 UninferredImpl::ImplAlias(impl_alias_id) => {
3831 let module_id = impl_alias_id.parent_module(db);
3832 let mut diagnostics = SemanticDiagnostics::new(module_id);
3833
3834 let impl_ast = db.module_impl_alias_by_id(impl_alias_id)?;
3835 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
3836
3837 let mut resolver = Resolver::new(db, module_id, inference_id);
3838 resolver.set_feature_config(&impl_alias_id, &impl_ast, &mut diagnostics);
3839 (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3840 }
3841 _ => {
3842 return Ok(());
3843 }
3844 };
3845 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) = generic_params
3846 {
3847 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
3848 let generic_param_id =
3849 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
3850 resolver.add_generic_param(generic_param_id);
3851 let trait_path = match param_syntax {
3852 ast::GenericParam::ImplNamed(param) => param.trait_path(db),
3853 ast::GenericParam::ImplAnonymous(param) => param.trait_path(db),
3854 ast::GenericParam::NegativeImpl(param) => param.trait_path(db),
3855
3856 _ => return,
3857 };
3858 let dependant_trait_id =
3859 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path);
3860
3861 let Ok(dependant_trait_id) = dependant_trait_id else {
3862 return;
3863 };
3864 trait_deps.entry(imp_trait_id).or_default().insert(dependant_trait_id);
3865 })
3866 };
3867 };
3868 Ok(())
3869}
3870
3871#[derive(Default, Debug, Eq, PartialEq, salsa::Update)]
3872struct ModuleImpls<'db> {
3873 globals_by_trait: OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3874 trait_deps: OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3875 globals_by_type: OrderedHashMap<TypeId<'db>, Vec<UninferredImpl<'db>>>,
3876
3877 locals: BTreeSet<UninferredImplById<'db>>,
3878}
3879
3880#[salsa::tracked(returns(ref))]
3881fn module_global_impls<'db>(
3882 db: &'db dyn Database,
3883 _tracked: Tracked,
3884 module_id: ModuleId<'db>,
3885) -> Maybe<ModuleImpls<'db>> {
3886 let mut module_impls = ModuleImpls::default();
3887 for (containing_module, info) in db.module_imported_modules((), module_id).iter() {
3888 for defined_module in module_macro_modules(db, true, *containing_module) {
3889 let Ok(module_semantic_data) = db.priv_module_semantic_data(*defined_module) else {
3890 continue;
3891 };
3892 for item in module_semantic_data.items.values().filter(|item| {
3893 info.user_modules.iter().any(|user_module| {
3894 peek_visible_in(db, item.visibility, *containing_module, *user_module)
3895 })
3896 }) {
3897 let imp = match item.item_id {
3898 ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
3899 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
3900 UninferredImpl::Def(impl_def_id)
3901 }
3902 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
3903 UninferredImpl::ImplAlias(impl_alias_id)
3904 }
3905 _ => continue,
3906 },
3907 ModuleItemId::Impl(impl_def_id) => {
3908 if let Ok(impl_ast) = db.module_impl_by_id(impl_def_id) {
3909 global_impls_insert_generic_impls(
3910 db,
3911 &impl_ast.generic_params(db),
3912 impl_def_id.parent_module(db),
3913 &mut module_impls.globals_by_trait,
3914 );
3915 }
3916
3917 UninferredImpl::Def(impl_def_id)
3920 }
3921 ModuleItemId::ImplAlias(impl_alias_id) => {
3923 UninferredImpl::ImplAlias(impl_alias_id)
3924 }
3925 ModuleItemId::FreeFunction(free_function_id) => {
3926 if let Ok(function_ast) = db.module_free_function_by_id(free_function_id) {
3927 let declaration = function_ast.declaration(db);
3928 global_impls_insert_generic_impls(
3929 db,
3930 &declaration.generic_params(db),
3931 free_function_id.parent_module(db),
3932 &mut module_impls.globals_by_trait,
3933 );
3934 }
3935 continue;
3936 }
3937 _ => continue,
3938 };
3939
3940 uninferred_impl_trait_dependency(db, imp, &mut module_impls.trait_deps)?;
3941
3942 if let Ok(true) = is_global_impl(db, imp, module_id) {
3943 let trait_id = imp.trait_id(db)?;
3944 module_impls.globals_by_trait.entry(trait_id).or_default().insert(imp.into());
3945 } else {
3946 module_impls.locals.insert(imp.into());
3947 }
3948 }
3949 }
3950 }
3951
3952 Ok(module_impls)
3953}
3954
3955fn is_global_impl<'db>(
3959 db: &'db dyn Database,
3960 impl_id: UninferredImpl<'db>,
3961 impl_module: ModuleId<'db>,
3962) -> Maybe<bool> {
3963 let trait_id = impl_id.trait_id(db)?;
3964 if trait_id.parent_module(db) == impl_module {
3965 return Ok(true);
3966 }
3967
3968 Ok(impl_id
3969 .trait_shallow_generic_args(db)?
3970 .iter()
3971 .any(|(_, arg)| arg.module_id(db) == Some(impl_module)))
3972}
3973
3974fn global_impls_insert_generic_impls<'db>(
3978 db: &'db dyn Database,
3979 generic_params: &ast::OptionWrappedGenericParamList<'db>,
3980 module_id: ModuleId<'db>,
3981 globals_by_trait: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3982) {
3983 let ast::OptionWrappedGenericParamList::WrappedGenericParamList(generic_params) =
3984 generic_params
3985 else {
3986 return;
3987 };
3988 let mut generic_types = OrderedHashMap::<_, GenericParamId<'db>, _>::default();
3989 for param in generic_params.generic_params(db).elements(db) {
3990 let (trait_path, type_constraints) = match ¶m {
3991 ast::GenericParam::Type(_) => {
3992 let param_id = GenericParamLongId(module_id, param.stable_ptr(db)).intern(db);
3993 if let Some(name) = param_id.name(db) {
3994 generic_types.insert(name, param_id);
3995 }
3996 continue;
3997 }
3998 ast::GenericParam::ImplNamed(impl_param) => {
3999 (impl_param.trait_path(db), impl_param.type_constrains(db))
4000 }
4001 ast::GenericParam::ImplAnonymous(impl_param) => {
4002 (impl_param.trait_path(db), impl_param.type_constrains(db))
4003 }
4004 _ => continue,
4005 };
4006 if is_global_impl_generic_param(db, &generic_types, &trait_path) {
4007 let uninferred_impl = UninferredImpl::GenericParam(
4008 GenericParamLongId(module_id, param.stable_ptr(db)).intern(db),
4009 );
4010 if let Ok(trait_id) = uninferred_impl.trait_id(db) {
4011 if trait_id == db.core_info().type_eq_trt {
4012 continue;
4013 }
4014 if matches!(
4015 type_constraints,
4016 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
4017 ) {
4018 continue;
4019 }
4020 globals_by_trait.entry(trait_id).or_default().insert(uninferred_impl.into());
4021 }
4022 }
4023 }
4024}
4025
4026fn is_global_impl_generic_param<'db>(
4028 db: &'db dyn Database,
4029 generic_types: &OrderedHashMap<SmolStrId<'db>, GenericParamId<'db>>,
4030 trait_syntax: &ast::ExprPath<'db>,
4031) -> bool {
4032 let trait_segments = trait_syntax.to_segments(db);
4033 let ast::PathSegment::WithGenericArgs(trait_segment) = trait_segments.last().unwrap() else {
4034 return false;
4035 };
4036
4037 let generic_args = trait_segment.generic_args(db);
4038
4039 for arg in generic_args.generic_args(db).elements(db) {
4040 let mut expr = match arg {
4041 ast::GenericArg::Unnamed(arg) => arg.value(db),
4042 ast::GenericArg::Named(arg) => arg.value(db),
4043 };
4044
4045 while let ast::Expr::Unary(unary_expr) = &expr {
4046 if !matches!(unary_expr.op(db), UnaryOperator::At(_)) {
4047 break;
4048 }
4049
4050 expr = unary_expr.expr(db);
4051 }
4052
4053 let ast::Expr::Path(path) = expr else {
4054 continue;
4055 };
4056 let path_segments = path.to_segments(db);
4057 let [segment] = path_segments.as_slice() else {
4058 continue;
4059 };
4060
4061 let ast::PathSegment::Simple(simple_segment) = segment else {
4062 continue;
4063 };
4064 if generic_types.contains_key(&simple_segment.identifier(db)) {
4065 return true;
4066 }
4067 }
4068
4069 false
4070}
4071
4072pub trait ImplSemantic<'db>: Database {
4074 fn impl_semantic_declaration_diagnostics(
4076 &'db self,
4077 impl_def_id: ImplDefId<'db>,
4078 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4079 impl_declaration_data(self.as_dyn_database(), impl_def_id)
4080 .as_ref()
4081 .map(|data| data.diagnostics.clone())
4082 .unwrap_or_default()
4083 }
4084 fn impl_def_generic_params(
4086 &'db self,
4087 impl_def_id: ImplDefId<'db>,
4088 ) -> Maybe<&'db [GenericParam<'db>]> {
4089 Ok(&impl_def_generic_params_data(self.as_dyn_database(), impl_def_id)
4090 .maybe_as_ref()?
4091 .generic_params)
4092 }
4093 fn impl_def_resolver_data(
4095 &'db self,
4096 impl_def_id: ImplDefId<'db>,
4097 ) -> Maybe<Arc<ResolverData<'db>>> {
4098 Ok(impl_declaration_data(self.as_dyn_database(), impl_def_id)
4099 .maybe_as_ref()?
4100 .resolver_data
4101 .clone())
4102 }
4103 fn impl_def_concrete_trait(
4105 &'db self,
4106 impl_def_id: ImplDefId<'db>,
4107 ) -> Maybe<ConcreteTraitId<'db>> {
4108 impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.concrete_trait
4109 }
4110 fn impl_def_attributes(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4112 Ok(&impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.attributes)
4113 }
4114 fn impl_concrete_trait(&'db self, impl_id: ImplId<'db>) -> Maybe<ConcreteTraitId<'db>> {
4116 impl_concrete_trait_tracked(self.as_dyn_database(), impl_id)
4117 }
4118 fn impl_def_trait(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
4121 impl_def_trait(self.as_dyn_database(), impl_def_id)
4122 }
4123 fn impl_semantic_definition_diagnostics(
4125 &'db self,
4126 impl_def_id: ImplDefId<'db>,
4127 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4128 impl_semantic_definition_diagnostics_tracked(self.as_dyn_database(), impl_def_id)
4129 }
4130 fn impl_item_info_by_name(
4132 &'db self,
4133 impl_def_id: ImplDefId<'db>,
4134 name: SmolStrId<'db>,
4135 ) -> Maybe<Option<ImplItemInfo<'db>>> {
4136 impl_item_info_by_name_tracked(self.as_dyn_database(), impl_def_id, name)
4137 }
4138 fn impl_all_used_uses(
4140 &'db self,
4141 impl_def_id: ImplDefId<'db>,
4142 ) -> Maybe<&'db OrderedHashSet<UseId<'db>>> {
4143 impl_all_used_uses(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4144 }
4145 fn impl_types(
4147 &'db self,
4148 impl_def_id: ImplDefId<'db>,
4149 ) -> Maybe<&'db OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>> {
4150 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4151 .maybe_as_ref()?
4152 .item_type_asts)
4153 }
4154 fn impl_type_by_trait_type(
4156 &'db self,
4157 impl_def_id: ImplDefId<'db>,
4158 trait_type_id: TraitTypeId<'db>,
4159 ) -> Maybe<ImplTypeDefId<'db>> {
4160 impl_type_by_trait_type_tracked(self.as_dyn_database(), impl_def_id, trait_type_id)
4161 }
4162 fn impl_constants(
4164 &'db self,
4165 impl_def_id: ImplDefId<'db>,
4166 ) -> Maybe<&'db OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>> {
4167 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4168 .maybe_as_ref()?
4169 .item_constant_asts)
4170 }
4171 fn impl_functions(
4173 &'db self,
4174 impl_def_id: ImplDefId<'db>,
4175 ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
4176 impl_functions(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4177 }
4178
4179 fn impl_type_def_resolved_type(&'db self, id: ImplTypeDefId<'db>) -> Maybe<TypeId<'db>> {
4183 impl_type_semantic_data(self.as_dyn_database(), id, false)
4184 .maybe_as_ref()?
4185 .type_alias_data
4186 .resolved_type
4187 }
4188 fn impl_type_def_generic_params(
4190 &'db self,
4191 id: ImplTypeDefId<'db>,
4192 ) -> Maybe<Vec<GenericParam<'db>>> {
4193 Ok(impl_type_def_generic_params_data(self.as_dyn_database(), id)
4194 .maybe_as_ref()?
4195 .generic_params
4196 .clone())
4197 }
4198 fn impl_type_def_attributes(&'db self, id: ImplTypeDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4200 Ok(&impl_type_semantic_data(self.as_dyn_database(), id, false)
4201 .maybe_as_ref()?
4202 .type_alias_data
4203 .attributes)
4204 }
4205 fn impl_type_def_resolver_data(
4207 &'db self,
4208 id: ImplTypeDefId<'db>,
4209 ) -> Maybe<Arc<ResolverData<'db>>> {
4210 Ok(impl_type_semantic_data(self.as_dyn_database(), id, false)
4211 .maybe_as_ref()?
4212 .type_alias_data
4213 .resolver_data
4214 .clone())
4215 }
4216 fn deref_chain(
4218 &'db self,
4219 ty: TypeId<'db>,
4220 crate_id: CrateId<'db>,
4221 try_deref_mut: bool,
4222 ) -> Maybe<&'db DerefChain<'db>> {
4223 deref_chain(self.as_dyn_database(), ty, crate_id, try_deref_mut).maybe_as_ref()
4224 }
4225
4226 fn impl_type_concrete_implized(
4232 &'db self,
4233 impl_type_def_id: ImplTypeId<'db>,
4234 ) -> Maybe<TypeId<'db>> {
4235 impl_type_concrete_implized_tracked(self.as_dyn_database(), impl_type_def_id)
4236 }
4237
4238 fn impl_constant_def_value(&'db self, id: ImplConstantDefId<'db>) -> Maybe<ConstValueId<'db>> {
4242 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4243 .maybe_as_ref()?
4244 .constant_data
4245 .const_value)
4246 }
4247 fn impl_constant_def_resolver_data(
4249 &'db self,
4250 id: ImplConstantDefId<'db>,
4251 ) -> Maybe<Arc<ResolverData<'db>>> {
4252 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4253 .maybe_as_ref()?
4254 .constant_data
4255 .resolver_data
4256 .clone())
4257 }
4258
4259 fn impl_constant_concrete_implized_value(
4264 &'db self,
4265 impl_constant_id: ImplConstantId<'db>,
4266 ) -> Maybe<ConstValueId<'db>> {
4267 impl_constant_concrete_implized_value_tracked(self.as_dyn_database(), impl_constant_id)
4268 }
4269 fn impl_constant_concrete_implized_type(
4272 &'db self,
4273 impl_constant_id: ImplConstantId<'db>,
4274 ) -> Maybe<TypeId<'db>> {
4275 impl_constant_concrete_implized_type_tracked(self.as_dyn_database(), impl_constant_id)
4276 }
4277
4278 fn impl_impl_def_resolver_data(
4282 &'db self,
4283 id: ImplImplDefId<'db>,
4284 ) -> Maybe<Arc<ResolverData<'db>>> {
4285 Ok(impl_impl_semantic_data(self.as_dyn_database(), id, false)
4286 .maybe_as_ref()?
4287 .impl_data
4288 .resolver_data
4289 .clone())
4290 }
4291
4292 fn impl_impl_concrete_implized(&'db self, impl_impl_id: ImplImplId<'db>) -> Maybe<ImplId<'db>> {
4296 impl_impl_concrete_implized_tracked(self.as_dyn_database(), impl_impl_id)
4297 }
4298
4299 fn impl_function_declaration_diagnostics(
4303 &'db self,
4304 id: ImplFunctionId<'db>,
4305 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4306 impl_function_declaration_data(self.as_dyn_database(), id)
4307 .as_ref()
4308 .map(|data| data.function_declaration_data.diagnostics.clone())
4309 .unwrap_or_default()
4310 }
4311 fn impl_function_signature(
4313 &'db self,
4314 id: ImplFunctionId<'db>,
4315 ) -> Maybe<&'db semantic::Signature<'db>> {
4316 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4317 .maybe_as_ref()?
4318 .function_declaration_data
4319 .signature)
4320 }
4321 fn impl_function_generic_params(
4323 &'db self,
4324 id: ImplFunctionId<'db>,
4325 ) -> Maybe<&'db [GenericParam<'db>]> {
4326 Ok(&impl_function_generic_params_data(self.as_dyn_database(), id)
4327 .maybe_as_ref()?
4328 .generic_params)
4329 }
4330 fn impl_function_attributes(
4332 &'db self,
4333 id: ImplFunctionId<'db>,
4334 ) -> Maybe<&'db [Attribute<'db>]> {
4335 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4336 .maybe_as_ref()?
4337 .function_declaration_data
4338 .attributes)
4339 }
4340 fn impl_function_resolver_data(
4342 &'db self,
4343 id: ImplFunctionId<'db>,
4344 ) -> Maybe<Arc<ResolverData<'db>>> {
4345 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4346 .maybe_as_ref()?
4347 .function_declaration_data
4348 .resolver_data
4349 .clone())
4350 }
4351 fn impl_function_declaration_inline_config(
4353 &'db self,
4354 id: ImplFunctionId<'db>,
4355 ) -> Maybe<InlineConfiguration<'db>> {
4356 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4357 .maybe_as_ref()?
4358 .function_declaration_data
4359 .inline_config
4360 .clone())
4361 }
4362 fn impl_function_declaration_implicit_precedence(
4364 &'db self,
4365 id: ImplFunctionId<'db>,
4366 ) -> Maybe<&'db ImplicitPrecedence<'db>> {
4367 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4368 .maybe_as_ref()?
4369 .function_declaration_data
4370 .implicit_precedence)
4371 }
4372 fn impl_function_trait_function(
4374 &'db self,
4375 id: ImplFunctionId<'db>,
4376 ) -> Maybe<TraitFunctionId<'db>> {
4377 impl_function_declaration_data(self.as_dyn_database(), id).maybe_as_ref()?.trait_function_id
4378 }
4379 fn impl_function_body_diagnostics(
4381 &'db self,
4382 impl_function_id: ImplFunctionId<'db>,
4383 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4384 self.priv_impl_function_body_data(impl_function_id)
4385 .map(|data| data.diagnostics.clone())
4386 .unwrap_or_default()
4387 }
4388 fn impl_function_body(
4390 &'db self,
4391 impl_function_id: ImplFunctionId<'db>,
4392 ) -> Maybe<&'db FunctionBody<'db>> {
4393 Ok(&self.priv_impl_function_body_data(impl_function_id)?.body)
4394 }
4395 fn impl_function_body_resolver_data(
4397 &'db self,
4398 impl_function_id: ImplFunctionId<'db>,
4399 ) -> Maybe<Arc<ResolverData<'db>>> {
4400 Ok(self.priv_impl_function_body_data(impl_function_id)?.resolver_data.clone())
4401 }
4402 fn priv_impl_function_body_data(
4404 &'db self,
4405 impl_function_id: ImplFunctionId<'db>,
4406 ) -> Maybe<&'db FunctionBodyData<'db>> {
4407 priv_impl_function_body_data_tracked(self.as_dyn_database(), impl_function_id)
4408 .maybe_as_ref()
4409 }
4410}
4411impl<'db, T: Database + ?Sized> ImplSemantic<'db> for T {}
4412
4413trait PrivImplSemantic<'db>: Database {
4415 fn impl_def_substitution(
4417 &'db self,
4418 impl_def_id: ImplDefId<'db>,
4419 ) -> Maybe<&'db GenericSubstitution<'db>> {
4420 impl_def_substitution(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4421 }
4422 fn impl_def_shallow_trait_generic_args(
4424 &'db self,
4425 impl_def_id: ImplDefId<'db>,
4426 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4427 impl_def_shallow_trait_generic_args(self.as_dyn_database(), impl_def_id)
4428 }
4429 fn impl_alias_trait_generic_args(
4431 &'db self,
4432 impl_def_id: ImplAliasId<'db>,
4433 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4434 impl_alias_trait_generic_args(self.as_dyn_database(), impl_def_id)
4435 }
4436 fn impl_item_by_name(
4438 &'db self,
4439 impl_def_id: ImplDefId<'db>,
4440 name: SmolStrId<'db>,
4441 ) -> Maybe<Option<ImplItemId<'db>>> {
4442 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4443 .maybe_as_ref()?
4444 .item_id_by_name
4445 .get(&name)
4446 .map(|info| info.id))
4447 }
4448 fn impl_implicit_impl_by_name(
4450 &'db self,
4451 impl_def_id: ImplDefId<'db>,
4452 name: SmolStrId<'db>,
4453 ) -> Maybe<Option<TraitImplId<'db>>> {
4454 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4455 .maybe_as_ref()?
4456 .implicit_impls_id_by_name
4457 .get(&name)
4458 .copied())
4459 }
4460 fn impl_type_by_id(
4462 &'db self,
4463 impl_type_id: ImplTypeDefId<'db>,
4464 ) -> Maybe<ast::ItemTypeAlias<'db>> {
4465 impl_type_by_id(self.as_dyn_database(), impl_type_id)
4466 }
4467 fn impl_impls(
4469 &'db self,
4470 impl_def_id: ImplDefId<'db>,
4471 ) -> Maybe<&'db OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>> {
4472 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4473 .maybe_as_ref()?
4474 .item_impl_asts)
4475 }
4476 fn impl_impl_by_id(
4478 &'db self,
4479 impl_impl_id: ImplImplDefId<'db>,
4480 ) -> Maybe<ast::ItemImplAlias<'db>> {
4481 impl_impl_by_id(self.as_dyn_database(), impl_impl_id)
4482 }
4483 fn impl_impl_by_trait_impl(
4485 &'db self,
4486 impl_def_id: ImplDefId<'db>,
4487 trait_impl_id: TraitImplId<'db>,
4488 ) -> Maybe<ImplImplDefId<'db>> {
4489 impl_impl_by_trait_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4490 }
4491 fn is_implicit_impl_impl(
4493 &self,
4494 impl_def_id: ImplDefId<'db>,
4495 trait_impl_id: TraitImplId<'db>,
4496 ) -> Maybe<bool> {
4497 is_implicit_impl_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4498 }
4499 fn impl_constant_by_trait_constant(
4501 &'db self,
4502 impl_def_id: ImplDefId<'db>,
4503 trait_constant_id: TraitConstantId<'db>,
4504 ) -> Maybe<ImplConstantDefId<'db>> {
4505 impl_constant_by_trait_constant(self.as_dyn_database(), impl_def_id, trait_constant_id)
4506 }
4507 fn impl_function_by_trait_function(
4512 &'db self,
4513 impl_def_id: ImplDefId<'db>,
4514 trait_function_id: TraitFunctionId<'db>,
4515 ) -> Maybe<Option<ImplFunctionId<'db>>> {
4516 impl_function_by_trait_function(self.as_dyn_database(), impl_def_id, trait_function_id)
4517 }
4518 fn impl_type_def_semantic_diagnostics(
4520 &'db self,
4521 id: ImplTypeDefId<'db>,
4522 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4523 impl_type_semantic_data(self.as_dyn_database(), id, false)
4524 .as_ref()
4525 .map(|data| data.diagnostics.clone())
4526 .unwrap_or_default()
4527 }
4528 fn impl_constant_def_semantic_diagnostics(
4530 &'db self,
4531 id: ImplConstantDefId<'db>,
4532 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4533 impl_constant_semantic_data(self.as_dyn_database(), id, false)
4534 .as_ref()
4535 .map(|data| data.diagnostics.clone())
4536 .unwrap_or_default()
4537 }
4538 fn impl_constant_implized_by_context(
4540 &'db self,
4541 impl_constant_id: ImplConstantId<'db>,
4542 impl_def_id: ImplDefId<'db>,
4543 ) -> Maybe<ConstValueId<'db>> {
4544 impl_constant_implized_by_context_tracked(
4545 self.as_dyn_database(),
4546 impl_constant_id,
4547 impl_def_id,
4548 )
4549 }
4550 fn impl_impl_def_semantic_diagnostics(
4552 &'db self,
4553 id: ImplImplDefId<'db>,
4554 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4555 impl_impl_semantic_data(self.as_dyn_database(), id, false)
4556 .as_ref()
4557 .map(|data| data.diagnostics.clone())
4558 .unwrap_or_default()
4559 }
4560 fn impl_impl_def_impl(
4562 &'db self,
4563 impl_impl_def_id: ImplImplDefId<'db>,
4564 in_cycle: bool,
4565 ) -> Maybe<ImplId<'db>> {
4566 impl_impl_semantic_data(self.as_dyn_database(), impl_impl_def_id, in_cycle)
4567 .maybe_as_ref()?
4568 .impl_data
4569 .resolved_impl
4570 }
4571 fn implicit_impl_impl_semantic_diagnostics(
4573 &'db self,
4574 impl_def_id: ImplDefId<'db>,
4575 trait_impl_id: TraitImplId<'db>,
4576 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4577 implicit_impl_impl_semantic_data_tracked(
4578 self.as_dyn_database(),
4579 impl_def_id,
4580 trait_impl_id,
4581 false,
4582 )
4583 .as_ref()
4584 .map(|data| data.diagnostics.clone())
4585 .unwrap_or_default()
4586 }
4587 fn implicit_impl_impl_impl(
4589 &'db self,
4590 impl_def_id: ImplDefId<'db>,
4591 trait_impl_id: TraitImplId<'db>,
4592 in_cycle: bool,
4593 ) -> Maybe<ImplId<'db>> {
4594 implicit_impl_impl_semantic_data_tracked(
4595 self.as_dyn_database(),
4596 impl_def_id,
4597 trait_impl_id,
4598 in_cycle,
4599 )
4600 .maybe_as_ref()?
4601 .resolved_impl
4602 }
4603 fn impl_impl_implized_by_context(
4605 &'db self,
4606 impl_impl_id: ImplImplId<'db>,
4607 impl_def_id: ImplDefId<'db>,
4608 in_cycle: bool,
4609 ) -> Maybe<ImplId<'db>> {
4610 impl_impl_implized_by_context_tracked(
4611 self.as_dyn_database(),
4612 impl_impl_id,
4613 impl_def_id,
4614 in_cycle,
4615 )
4616 }
4617 fn impl_impl_concrete_trait(
4619 &'db self,
4620 impl_impl_id: ImplImplId<'db>,
4621 ) -> Maybe<ConcreteTraitId<'db>> {
4622 impl_impl_concrete_trait_tracked(self.as_dyn_database(), impl_impl_id)
4623 }
4624 fn crate_global_impls(
4628 &'db self,
4629 crate_id: CrateId<'db>,
4630 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4631 crate_global_impls(self.as_dyn_database(), crate_id)
4632 }
4633 fn crate_traits_dependencies(
4635 &'db self,
4636 crate_id: CrateId<'db>,
4637 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
4638 crate_traits_dependencies(self.as_dyn_database(), crate_id)
4639 }
4640 fn reachable_trait_dependencies(
4642 &'db self,
4643 trait_id: TraitId<'db>,
4644 crate_id: CrateId<'db>,
4645 ) -> &'db OrderedHashSet<TraitId<'db>> {
4646 reachable_trait_dependencies(self.as_dyn_database(), trait_id, crate_id)
4647 }
4648 fn module_global_impls(
4650 &'db self,
4651 _tracked: Tracked,
4652 module_id: ModuleId<'db>,
4653 ) -> &'db Maybe<ModuleImpls<'db>> {
4654 module_global_impls(self.as_dyn_database(), _tracked, module_id)
4655 }
4656 fn trait_candidate_by_head(
4658 &'db self,
4659 crate_id: CrateId<'db>,
4660 trait_id: TraitId<'db>,
4661 ) -> &'db OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4662 trait_candidate_by_head(self.as_dyn_database(), crate_id, trait_id)
4663 }
4664}
4665impl<'db, T: Database + ?Sized> PrivImplSemantic<'db> for T {}