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, try_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 }
622}
623
624fn impl_alias_trait_generic_args<'db>(
626 db: &'db dyn Database,
627 impl_alias_id: ImplAliasId<'db>,
628) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
629 Ok(impl_alias_trait_generic_args_helper(db, impl_alias_id).maybe_as_ref()?)
630}
631
632#[salsa::tracked(returns(ref))]
633fn impl_alias_trait_generic_args_helper<'db>(
634 db: &'db dyn Database,
635 impl_alias_id: ImplAliasId<'db>,
636) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
637 let module_id = impl_alias_id.parent_module(db);
638 let mut diagnostics = SemanticDiagnostics::new(module_id);
639
640 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?;
641 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
642
643 let mut resolver = Resolver::new(db, module_id, inference_id);
644 resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
645
646 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
647 impl_alias_ast.generic_params(db)
648 {
649 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
650 let generic_param_id =
651 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
652 resolver.add_generic_param(generic_param_id);
653 })
654 }
655 let rhs_syntax = impl_alias_ast.impl_path(db);
656 let (shallow_args, rhs_generic_params) = match resolver.resolve_generic_path_with_args(
657 &mut diagnostics,
658 &rhs_syntax,
659 NotFoundItemType::Impl,
660 ResolutionContext::Default,
661 ) {
662 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
663 let shallow_args = db.impl_def_shallow_trait_generic_args(impl_def_id)?.to_vec();
664 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
665 db.module_impl_by_id(impl_def_id)?.generic_params(db)
666 else {
667 return Ok(shallow_args);
668 };
669 (
670 shallow_args,
671 params
672 .generic_params(db)
673 .elements(db)
674 .map(|param_syntax| {
675 GenericParamLongId(
676 impl_def_id.parent_module(db),
677 param_syntax.stable_ptr(db),
678 )
679 .intern(db)
680 })
681 .collect::<Vec<_>>(),
682 )
683 }
684 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => {
685 let shallow_args = db.impl_alias_trait_generic_args(impl_alias)?.to_vec();
686 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
687 db.module_impl_alias_by_id(impl_alias)?.generic_params(db)
688 else {
689 return Ok(shallow_args);
690 };
691 (
692 shallow_args,
693 params
694 .generic_params(db)
695 .elements(db)
696 .map(|param_syntax| {
697 GenericParamLongId(
698 impl_alias.parent_module(db),
699 param_syntax.stable_ptr(db),
700 )
701 .intern(db)
702 })
703 .collect::<Vec<_>>(),
704 )
705 }
706 _ => return Ok(Vec::new()),
707 };
708
709 let elements = rhs_syntax.segments(db).elements(db);
710 let Some(last) = elements.last() else {
711 return Ok(Vec::new());
712 };
713
714 match last {
715 ast::PathSegment::Simple(_) => Ok(shallow_args),
716 ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
717 let generic_args =
718 path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
719 let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
720 &mut diagnostics,
721 &rhs_generic_params,
722 &generic_args,
723 )?;
724
725 Ok(shallow_args
726 .iter()
727 .filter_map(|(trait_param, arg)| {
728 let ShallowGenericArg::GenericParameter(arg) = arg else {
729 return Some((*trait_param, arg.clone()));
730 };
731
732 arg_syntax_per_param.get(arg).and_then(|expr| {
733 let arg_ty = maybe_resolve_shallow_generic_arg_type(
734 db,
735 &mut diagnostics,
736 &mut resolver,
737 expr,
738 )?;
739 Some((*trait_param, arg_ty))
740 })
741 })
742 .collect::<Vec<_>>())
743 }
744 }
745}
746
747fn impl_concrete_trait<'db>(
749 db: &'db dyn Database,
750 impl_id: ImplId<'db>,
751) -> Maybe<ConcreteTraitId<'db>> {
752 match impl_id.long(db) {
753 ImplLongId::Concrete(concrete_impl_id) => {
754 let long_impl = concrete_impl_id.long(db);
755 let substitution = GenericSubstitution::new(
756 db.impl_def_generic_params(long_impl.impl_def_id)?,
757 &long_impl.generic_args,
758 );
759
760 let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
761 substitution.substitute(db, impl_concrete_trait_id)
762 }
763 ImplLongId::GenericParameter(param) => {
764 let param_impl =
765 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
766 param_impl.concrete_trait
767 }
768 ImplLongId::ImplVar(var) => Ok(var.long(db).concrete_trait_id),
769 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl),
770 ImplLongId::SelfImpl(concrete_trait_id) => Ok(*concrete_trait_id),
771 ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
772 }
773}
774
775#[salsa::tracked]
777fn impl_concrete_trait_tracked<'db>(
778 db: &'db dyn Database,
779 impl_id: ImplId<'db>,
780) -> Maybe<ConcreteTraitId<'db>> {
781 impl_concrete_trait(db, impl_id)
782}
783
784fn impl_declaration_data_cycle<'db>(
788 db: &'db dyn Database,
789 _id: salsa::Id,
790 impl_def_id: ImplDefId<'db>,
791) -> Maybe<ImplDeclarationData<'db>> {
792 impl_declaration_data_inner(db, impl_def_id, false)
793}
794
795#[salsa::tracked(cycle_result=impl_declaration_data_cycle, returns(ref))]
797fn impl_declaration_data<'db>(
798 db: &'db dyn Database,
799 impl_def_id: ImplDefId<'db>,
800) -> Maybe<ImplDeclarationData<'db>> {
801 impl_declaration_data_inner(db, impl_def_id, true)
802}
803
804fn impl_declaration_data_inner<'db>(
807 db: &'db dyn Database,
808 impl_def_id: ImplDefId<'db>,
809 resolve_trait: bool,
810) -> Maybe<ImplDeclarationData<'db>> {
811 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
812
813 let impl_ast = db.module_impl_by_id(impl_def_id)?;
817 let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
818 ModuleItemId::Impl(impl_def_id),
819 ));
820
821 let generic_params_data = impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?;
823 let mut resolver = Resolver::with_data(
824 db,
825 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
826 );
827 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
828 diagnostics.extend(generic_params_data.diagnostics.clone());
829 let trait_path_syntax = impl_ast.trait_path(db);
830
831 let concrete_trait = if resolve_trait {
832 resolver
833 .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
834 .and_then(|resolved_item| match resolved_item {
835 ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
836 _ => Err(diagnostics
837 .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
838 })
839 } else {
840 Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
841 };
842
843 let info = db.core_info();
844
845 if let Ok(concrete_trait) = concrete_trait
847 && [
848 info.type_eq_trt,
849 info.fn_trt,
850 info.fn_once_trt,
851 info.felt252_dict_value_trt,
852 info.numeric_literal_trt,
853 info.string_literal_trt,
854 ]
855 .contains(&concrete_trait.trait_id(db))
856 && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
857 {
858 diagnostics.report(
859 trait_path_syntax.stable_ptr(db),
860 CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
861 );
862 }
863
864 let inference = &mut resolver.inference();
866 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
867
868 let concrete_trait: Result<ConcreteTraitId<'_>, DiagnosticAdded> =
869 inference.rewrite(concrete_trait).no_err();
870
871 let attributes = impl_ast.attributes(db).structurize(db);
872 let mut resolver_data = resolver.data;
873 resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
874 Ok(ImplDeclarationData {
875 diagnostics: diagnostics.build(),
876 concrete_trait,
877 attributes,
878 resolver_data: Arc::new(resolver_data),
879 })
880}
881
882#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
885#[debug_db(dyn Database)]
886struct ImplDefinitionData<'db> {
887 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
892
893 function_asts: OrderedHashMap<ImplFunctionId<'db>, ast::FunctionWithBody<'db>>,
895 item_type_asts: OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>,
896 item_constant_asts: OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>,
897 item_impl_asts: OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>,
898
899 item_id_by_name: OrderedHashMap<SmolStrId<'db>, ImplItemInfo<'db>>,
902
903 implicit_impls_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>,
905}
906
907impl<'db> ImplDefinitionData<'db> {
908 pub fn get_impl_item_info(&self, item_name: SmolStrId<'db>) -> Option<ImplItemInfo<'db>> {
910 self.item_id_by_name.get(&item_name).cloned()
911 }
912}
913#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
915pub struct ImplItemInfo<'db> {
916 pub id: ImplItemId<'db>,
918 pub feature_kind: FeatureKind<'db>,
920}
921
922impl<'db> HasFeatureKind<'db> for ImplItemInfo<'db> {
923 fn feature_kind(&self) -> &FeatureKind<'db> {
925 &self.feature_kind
926 }
927}
928
929fn impl_semantic_definition_diagnostics<'db>(
933 db: &'db dyn Database,
934 impl_def_id: ImplDefId<'db>,
935) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
936 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
937
938 let Ok(data) = impl_definition_data(db, impl_def_id) else {
939 return Diagnostics::default();
940 };
941
942 diagnostics.extend(data.diagnostics.clone());
945 for impl_function_id in data.function_asts.keys() {
946 diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
947 diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
948 }
949 for impl_item_type_id in data.item_type_asts.keys() {
950 diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
951 if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
952 add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
953 }
954 }
955 for impl_item_constant_id in data.item_constant_asts.keys() {
956 diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
957 }
958 for impl_item_impl_id in data.item_impl_asts.keys() {
959 diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
960 }
961 for implicit_impl_id in data.implicit_impls_id_by_name.values() {
962 diagnostics
963 .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
964 }
965 if diagnostics.error_count == 0 {
967 let concrete_trait =
968 impl_declaration_data(db, impl_def_id).as_ref().unwrap().concrete_trait.unwrap();
969
970 let trait_id = concrete_trait.trait_id(db);
971 if trait_id == db.core_info().deref_trt {
972 deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
973 }
974 }
975 diagnostics.build()
976}
977
978#[salsa::tracked]
980fn impl_semantic_definition_diagnostics_tracked<'db>(
981 db: &'db dyn Database,
982 impl_def_id: ImplDefId<'db>,
983) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
984 impl_semantic_definition_diagnostics(db, impl_def_id)
985}
986
987#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
989pub struct DerefChain<'db> {
990 pub derefs: Arc<Vec<DerefInfo<'db>>>,
991}
992
993#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
995pub struct DerefInfo<'db> {
996 pub function_id: FunctionId<'db>,
998 pub self_mutability: Mutability,
1000 pub target_ty: TypeId<'db>,
1002}
1003
1004fn deref_chain_cycle<'db>(
1006 _db: &dyn Database,
1007 _id: salsa::Id,
1008 _ty: TypeId<'db>,
1009 _crate_id: CrateId<'db>,
1010 _try_deref_mut: bool,
1011) -> Maybe<DerefChain<'db>> {
1012 Maybe::Err(skip_diagnostic())
1014}
1015
1016#[salsa::tracked(cycle_result=deref_chain_cycle, returns(ref))]
1018fn deref_chain<'db>(
1019 db: &'db dyn Database,
1020 ty: TypeId<'db>,
1021 crate_id: CrateId<'db>,
1022 try_deref_mut: bool,
1023) -> Maybe<DerefChain<'db>> {
1024 let mut opt_deref = None;
1025 if try_deref_mut {
1026 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, true)?;
1027 }
1028 let self_mutability = if opt_deref.is_some() {
1029 Mutability::Reference
1030 } else {
1031 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, false)?;
1032 Mutability::Immutable
1033 };
1034
1035 let Some((function_id, target_ty)) = opt_deref else {
1036 return Ok(DerefChain { derefs: Arc::new(vec![]) });
1037 };
1038
1039 let inner_chain = db.deref_chain(target_ty, crate_id, false)?;
1040
1041 Ok(DerefChain {
1042 derefs: Arc::new(
1043 chain!(
1044 [DerefInfo { function_id, target_ty, self_mutability }],
1045 inner_chain.derefs.iter().cloned()
1046 )
1047 .collect(),
1048 ),
1049 })
1050}
1051
1052fn try_get_deref_func_and_target<'db>(
1054 db: &'db dyn Database,
1055 ty: TypeId<'db>,
1056 crate_id: CrateId<'db>,
1057 is_mut_deref: bool,
1058) -> Result<Option<(FunctionId<'db>, TypeId<'db>)>, DiagnosticAdded> {
1059 let info = db.core_info();
1060 let (deref_trait_id, deref_method) = if is_mut_deref {
1061 (info.deref_mut_trt, info.deref_mut_fn)
1062 } else {
1063 (info.deref_trt, info.deref_fn)
1064 };
1065
1066 let mut lookup_context = ImplLookupContext::new_from_crate(crate_id);
1067 enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
1068 let concrete_trait = ConcreteTraitLongId {
1069 trait_id: deref_trait_id,
1070 generic_args: vec![GenericArgumentId::Type(ty)],
1071 }
1072 .intern(db);
1073 let Ok(deref_impl) = get_impl_at_context(db, lookup_context.intern(db), concrete_trait, None)
1074 else {
1075 return Ok(None);
1076 };
1077 let concrete_impl_id: ConcreteImplId<'db> = match deref_impl.long(db) {
1078 ImplLongId::Concrete(concrete_impl_id) => *concrete_impl_id,
1079 _ => panic!("Expected concrete impl"),
1080 };
1081
1082 let function_id: FunctionId<'db> = FunctionLongId {
1083 function: ConcreteFunction {
1084 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
1085 impl_id: deref_impl,
1086 function: deref_method,
1087 }),
1088 generic_args: vec![],
1089 },
1090 }
1091 .intern(db);
1092
1093 let data = impl_definition_data(db, concrete_impl_id.impl_def_id(db)).maybe_as_ref()?;
1094 let Ok((impl_item_type_id, _)) = data.item_type_asts.iter().exactly_one() else {
1095 return Ok(None);
1096 };
1097 let ty = db.impl_type_def_resolved_type(*impl_item_type_id)?;
1098 let substitution: GenericSubstitution<'db> = concrete_impl_id.substitution(db)?;
1099 let ty: TypeId<'db> = substitution.substitute(db, ty)?;
1100
1101 Ok(Some((function_id, ty)))
1102}
1103
1104fn deref_impl_diagnostics<'db>(
1106 db: &'db dyn Database,
1107 mut impl_def_id: ImplDefId<'db>,
1108 concrete_trait: ConcreteTraitId<'db>,
1109 diagnostics: &mut SemanticDiagnostics<'db>,
1110) {
1111 let mut visited_impls: OrderedHashSet<ImplDefId<'_>> = OrderedHashSet::default();
1112 let deref_trait_id = concrete_trait.trait_id(db);
1113
1114 let impl_module = impl_def_id.parent_module(db);
1115
1116 let mut impl_in_valid_location = false;
1117 if impl_module == deref_trait_id.parent_module(db) {
1118 impl_in_valid_location = true;
1119 }
1120
1121 let gargs = concrete_trait.generic_args(db);
1122 let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
1123 if let Some(module_id) = deref_ty.long(db).module_id(db)
1124 && module_id == impl_module
1125 {
1126 impl_in_valid_location = true;
1127 }
1128
1129 if !impl_in_valid_location {
1130 diagnostics.report(
1131 impl_def_id.stable_ptr(db),
1132 SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
1133 );
1134 return;
1135 }
1136
1137 loop {
1138 let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
1139 ConcreteTraitLongId {
1140 trait_id: deref_trait_id,
1141 generic_args: vec![GenericArgumentId::Type(ty)],
1142 }
1143 .intern(db)
1144 }) else {
1145 return;
1148 };
1149
1150 impl_def_id = match impl_id.long(db) {
1151 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
1152 _ => return,
1153 };
1154
1155 if !visited_impls.insert(impl_def_id) {
1156 let deref_chain = visited_impls
1157 .iter()
1158 .map(|visited_impl| {
1159 format!("{:?}", db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db))
1160 })
1161 .join(" -> ");
1162 diagnostics.report(
1163 impl_def_id.stable_ptr(db),
1164 SemanticDiagnosticKind::DerefCycle { deref_chain },
1165 );
1166 return;
1167 }
1168 }
1169}
1170
1171fn get_impl_based_on_single_impl_type<'db>(
1175 db: &'db dyn Database,
1176 impl_def_id: ImplDefId<'db>,
1177 concrete_trait_id: impl FnOnce(TypeId<'db>) -> ConcreteTraitId<'db>,
1178) -> Result<ImplId<'db>, (InferenceError<'db>, ImplTypeDefId<'db>)> {
1179 let data = impl_definition_data(db, impl_def_id).clone().unwrap();
1180 let mut types_iter = data.item_type_asts.iter();
1181 let (impl_item_type_id, _) = types_iter.next().unwrap();
1182 if types_iter.next().is_some() {
1183 panic!(
1184 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1185 );
1186 }
1187 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1188
1189 let module_id = impl_def_id.parent_module(db);
1190 let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
1191 let generic_params_ids =
1192 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1193 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db);
1194 get_impl_at_context(db, lookup_context.intern(db), concrete_trait_id(ty), None)
1195 .map_err(|err| (err, *impl_item_type_id))
1196}
1197
1198#[salsa::tracked(returns(ref))]
1200fn impl_functions<'db>(
1201 db: &'db dyn Database,
1202 impl_def_id: ImplDefId<'db>,
1203) -> Maybe<OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
1204 Ok(impl_definition_data(db, impl_def_id)
1205 .maybe_as_ref()?
1206 .function_asts
1207 .keys()
1208 .map(|function_id| {
1209 let function_long_id = function_id.long(db);
1210 (function_long_id.name(db), *function_id)
1211 })
1212 .collect())
1213}
1214
1215#[salsa::tracked]
1217fn impl_function_by_trait_function<'db>(
1218 db: &'db dyn Database,
1219 impl_def_id: ImplDefId<'db>,
1220 trait_function_id: TraitFunctionId<'db>,
1221) -> Maybe<Option<ImplFunctionId<'db>>> {
1222 let name = trait_function_id.name(db);
1223 for impl_function_id in
1224 impl_definition_data(db, impl_def_id).maybe_as_ref()?.function_asts.keys()
1225 {
1226 if impl_function_id.long(db).name(db) == name {
1227 return Ok(Some(*impl_function_id));
1228 }
1229 }
1230 Ok(None)
1231}
1232
1233fn impl_item_info_by_name<'db>(
1235 db: &'db dyn Database,
1236 impl_def_id: ImplDefId<'db>,
1237 name: SmolStrId<'db>,
1238) -> Maybe<Option<ImplItemInfo<'db>>> {
1239 let impl_definition_data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1240 Ok(impl_definition_data.get_impl_item_info(name))
1241}
1242
1243#[salsa::tracked]
1245fn impl_item_info_by_name_tracked<'db>(
1246 db: &'db dyn Database,
1247 impl_def_id: ImplDefId<'db>,
1248 name: SmolStrId<'db>,
1249) -> Maybe<Option<ImplItemInfo<'db>>> {
1250 impl_item_info_by_name(db, impl_def_id, name)
1251}
1252
1253#[salsa::tracked(returns(ref))]
1255fn impl_all_used_uses<'db>(
1256 db: &'db dyn Database,
1257 impl_def_id: ImplDefId<'db>,
1258) -> Maybe<OrderedHashSet<UseId<'db>>> {
1259 let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1260 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1261 for item in data.item_id_by_name.values() {
1262 for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1263 all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1264 }
1265 }
1266 Ok(all_used_uses)
1267}
1268
1269#[salsa::tracked]
1271fn impl_type_by_id<'db>(
1272 db: &'db dyn Database,
1273 impl_type_id: ImplTypeDefId<'db>,
1274) -> Maybe<ast::ItemTypeAlias<'db>> {
1275 let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1276 impl_types.get(&impl_type_id).cloned().ok_or_else(skip_diagnostic)
1277}
1278
1279fn impl_type_by_trait_type<'db>(
1281 db: &'db dyn Database,
1282 impl_def_id: ImplDefId<'db>,
1283 trait_type_id: TraitTypeId<'db>,
1284) -> Maybe<ImplTypeDefId<'db>> {
1285 if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1286 unreachable!(
1287 "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1288 trait"
1289 )
1290 }
1291 db.impl_item_by_name(impl_def_id, trait_type_id.name(db))?
1293 .and_then(|item_id| try_extract_matches!(item_id, ImplItemId::Type))
1294 .ok_or_else(skip_diagnostic)
1295}
1296
1297#[salsa::tracked]
1299fn impl_type_by_trait_type_tracked<'db>(
1300 db: &'db dyn Database,
1301 impl_def_id: ImplDefId<'db>,
1302 trait_type_id: TraitTypeId<'db>,
1303) -> Maybe<ImplTypeDefId<'db>> {
1304 impl_type_by_trait_type(db, impl_def_id, trait_type_id)
1305}
1306
1307#[salsa::tracked]
1309fn impl_constant_by_trait_constant<'db>(
1310 db: &'db dyn Database,
1311 impl_def_id: ImplDefId<'db>,
1312 trait_constant_id: TraitConstantId<'db>,
1313) -> Maybe<ImplConstantDefId<'db>> {
1314 if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1315 unreachable!(
1316 "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1317 the impl's trait"
1318 )
1319 }
1320 db.impl_item_by_name(impl_def_id, trait_constant_id.name(db))?
1322 .and_then(|item_id| try_extract_matches!(item_id, ImplItemId::Constant))
1323 .ok_or_else(skip_diagnostic)
1324}
1325
1326#[salsa::tracked]
1328fn impl_impl_by_id<'db>(
1329 db: &'db dyn Database,
1330 impl_impl_id: ImplImplDefId<'db>,
1331) -> Maybe<ast::ItemImplAlias<'db>> {
1332 let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1333 impl_impls.get(&impl_impl_id).cloned().ok_or_else(skip_diagnostic)
1334}
1335
1336#[salsa::tracked]
1338fn impl_impl_by_trait_impl<'db>(
1339 db: &'db dyn Database,
1340 impl_def_id: ImplDefId<'db>,
1341 trait_impl_id: TraitImplId<'db>,
1342) -> Maybe<ImplImplDefId<'db>> {
1343 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1344 unreachable!(
1345 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1346 trait"
1347 )
1348 }
1349 db.impl_item_by_name(impl_def_id, trait_impl_id.name(db))?
1351 .and_then(|item_id| try_extract_matches!(item_id, ImplItemId::Impl))
1352 .ok_or_else(skip_diagnostic)
1353}
1354
1355#[salsa::tracked]
1357fn is_implicit_impl_impl<'db>(
1358 db: &'db dyn Database,
1359 impl_def_id: ImplDefId<'db>,
1360 trait_impl_id: TraitImplId<'db>,
1361) -> Maybe<bool> {
1362 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1363 unreachable!(
1364 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1365 trait"
1366 )
1367 }
1368
1369 let name = trait_impl_id.name(db);
1370 Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1372}
1373
1374#[salsa::tracked(returns(ref))]
1378fn impl_definition_data<'db>(
1379 db: &'db dyn Database,
1380 impl_def_id: ImplDefId<'db>,
1381) -> Maybe<ImplDefinitionData<'db>> {
1382 let module_id = impl_def_id.parent_module(db);
1383 let mut diagnostics = SemanticDiagnostics::new(module_id);
1384
1385 let generic_params =
1386 impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?.generic_params.clone();
1387 let concrete_trait = impl_declaration_data(db, impl_def_id).maybe_as_ref()?.concrete_trait?;
1388
1389 let impl_ast = db.module_impl_by_id(impl_def_id)?;
1390
1391 let generic_params_ids =
1392 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1393 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db).intern(db);
1394 check_special_impls(
1395 db,
1396 &mut diagnostics,
1397 lookup_context,
1398 concrete_trait,
1399 impl_ast.stable_ptr(db).untyped(),
1400 )
1401 .ok();
1403
1404 let mut function_asts = OrderedHashMap::default();
1405 let mut item_type_asts = OrderedHashMap::default();
1406 let mut item_constant_asts = OrderedHashMap::default();
1407 let mut item_impl_asts = OrderedHashMap::default();
1408 let mut item_id_by_name = OrderedHashMap::default();
1409
1410 if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1411 for item in body.items(db).elements(db) {
1412 match item {
1413 ImplItem::Module(module) => {
1414 report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1415 }
1416
1417 ImplItem::Use(use_item) => {
1418 report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1419 }
1420 ImplItem::ExternFunction(extern_func) => {
1421 report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1422 }
1423 ImplItem::ExternType(extern_type) => {
1424 report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1425 }
1426 ImplItem::Trait(trt) => {
1427 report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1428 }
1429 ImplItem::Struct(structure) => {
1430 report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1431 }
1432 ImplItem::Enum(enm) => {
1433 report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1434 }
1435 ImplItem::Function(func) => {
1436 let impl_function_id =
1437 ImplFunctionLongId(module_id, func.stable_ptr(db)).intern(db);
1438 let name_node = func.declaration(db).name(db);
1439 let name = name_node.text(db);
1440 let feature_kind =
1441 FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1442 if item_id_by_name
1443 .insert(
1444 name,
1445 ImplItemInfo {
1446 id: ImplItemId::Function(impl_function_id),
1447 feature_kind,
1448 },
1449 )
1450 .is_some()
1451 {
1452 diagnostics
1453 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1454 }
1455 function_asts.insert(impl_function_id, func);
1456 }
1457 ImplItem::Type(ty) => {
1458 let impl_type_id = ImplTypeDefLongId(module_id, ty.stable_ptr(db)).intern(db);
1459 let name_node = ty.name(db);
1460 let name = name_node.text(db);
1461 let feature_kind =
1462 FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1463 if item_id_by_name
1464 .insert(
1465 name,
1466 ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1467 )
1468 .is_some()
1469 {
1470 diagnostics
1471 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1472 }
1473 item_type_asts.insert(impl_type_id, ty);
1474 }
1475 ImplItem::Constant(constant) => {
1476 let impl_constant_id =
1477 ImplConstantDefLongId(module_id, constant.stable_ptr(db)).intern(db);
1478 let name_node = constant.name(db);
1479 let name = name_node.text(db);
1480 let feature_kind =
1481 FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1482 if item_id_by_name
1483 .insert(
1484 name,
1485 ImplItemInfo {
1486 id: ImplItemId::Constant(impl_constant_id),
1487 feature_kind,
1488 },
1489 )
1490 .is_some()
1491 {
1492 diagnostics.report(
1493 name_node.stable_ptr(db),
1494 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1495 );
1496 }
1497 item_constant_asts.insert(impl_constant_id, constant);
1498 }
1499 ImplItem::Impl(imp) => {
1500 let impl_impl_id = ImplImplDefLongId(module_id, imp.stable_ptr(db)).intern(db);
1501 let name_node = imp.name(db);
1502 let name = name_node.text(db);
1503 let feature_kind =
1504 FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1505 if item_id_by_name
1506 .insert(
1507 name,
1508 ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1509 )
1510 .is_some()
1511 {
1512 diagnostics.report(
1513 name_node.stable_ptr(db),
1514 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1515 );
1516 }
1517 item_impl_asts.insert(impl_impl_id, imp);
1518 }
1519 ImplItem::Missing(_) => {}
1521 }
1522 }
1523 }
1524
1525 let mut implicit_impls_id_by_name = OrderedHashMap::default();
1526
1527 let trait_id = concrete_trait.long(db).trait_id;
1528 for (name, trait_impl_id) in db.trait_impls(trait_id)?.iter() {
1529 if item_id_by_name.contains_key(name) {
1530 continue;
1531 }
1532 implicit_impls_id_by_name.insert(*name, *trait_impl_id);
1533 }
1534
1535 let impl_item_names: OrderedHashSet<SmolStrId<'db>> = item_id_by_name.keys().copied().collect();
1539
1540 let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1541 let missing_items_in_impl =
1542 trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1543 if !missing_items_in_impl.is_empty() {
1544 diagnostics.report(
1545 impl_ast.name(db).stable_ptr(db),
1550 SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1551 );
1552 }
1553
1554 Ok(ImplDefinitionData {
1555 diagnostics: diagnostics.build(),
1556 function_asts,
1557 item_type_asts,
1558 item_id_by_name,
1559 item_constant_asts,
1560 item_impl_asts,
1561 implicit_impls_id_by_name,
1562 })
1563}
1564
1565fn report_invalid_impl_item<'db, Terminal: syntax::node::Terminal<'db>>(
1568 db: &'db dyn Database,
1569 diagnostics: &mut SemanticDiagnostics<'db>,
1570 kw_terminal: Terminal,
1571) {
1572 diagnostics
1573 .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1574}
1575
1576fn check_special_impls<'db>(
1578 db: &'db dyn Database,
1579 diagnostics: &mut SemanticDiagnostics<'db>,
1580 lookup_context: ImplLookupContextId<'db>,
1581 concrete_trait: ConcreteTraitId<'db>,
1582 stable_ptr: SyntaxStablePtrId<'db>,
1583) -> Maybe<()> {
1584 let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.long(db);
1585 let info = db.core_info();
1586 let copy = info.copy_trt;
1587 let drop = info.drop_trt;
1588
1589 if *trait_id == copy {
1590 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1591 for inference_error in tys
1592 .into_iter()
1593 .map(|ty| db.type_info(lookup_context, ty))
1594 .flat_map(|info| info.copyable.err())
1595 {
1596 if matches!(
1597 inference_error,
1598 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1599 ) {
1600 continue;
1602 }
1603 return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1604 }
1605 }
1606 if *trait_id == drop {
1607 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1608 for inference_error in tys
1609 .into_iter()
1610 .map(|ty| db.type_info(lookup_context, ty))
1611 .flat_map(|info| info.droppable.err())
1612 {
1613 if matches!(
1614 inference_error,
1615 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1616 ) {
1617 continue;
1619 }
1620 return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1621 }
1622 }
1623
1624 Ok(())
1625}
1626
1627fn get_inner_types<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> Maybe<Vec<TypeId<'db>>> {
1634 Ok(match ty.long(db) {
1635 TypeLongId::Concrete(concrete_type_id) => {
1636 match concrete_type_id {
1638 crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1639 .concrete_struct_members(*concrete_struct_id)?
1640 .values()
1641 .map(|member| member.ty)
1642 .collect(),
1643 crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1644 .concrete_enum_variants(*concrete_enum_id)?
1645 .into_iter()
1646 .map(|variant| variant.ty)
1647 .collect(),
1648 crate::ConcreteTypeId::Extern(_) => vec![],
1649 }
1650 }
1651 TypeLongId::Tuple(tys) => tys.to_vec(),
1652 TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1653 TypeLongId::GenericParameter(_) => {
1654 return Err(skip_diagnostic());
1655 }
1656 TypeLongId::Var(_) | TypeLongId::NumericLiteral(_) | TypeLongId::ImplType(_) => {
1657 panic!("Types should be fully resolved at this point.")
1658 }
1659 TypeLongId::Coupon(_) => vec![],
1660 TypeLongId::FixedSizeArray { type_id, .. } => vec![*type_id],
1661 TypeLongId::Missing(diag_added) => {
1662 return Err(*diag_added);
1663 }
1664 })
1665}
1666
1667#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1672pub struct TraitFilter<'db> {
1673 pub trait_id: TraitId<'db>,
1674 pub generics_filter: GenericsHeadFilter<'db>,
1676}
1677
1678#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
1681pub enum GenericsHeadFilter<'db> {
1682 NoFilter,
1685 FirstGenericFilter(GenericArgumentHead<'db>),
1688 NoGenerics,
1690}
1691
1692#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HeapSize, salsa::Update)]
1693pub struct UninferredImplById<'db>(pub UninferredImpl<'db>);
1694impl<'db> Ord for UninferredImplById<'db> {
1695 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1696 match (&self.0, &other.0) {
1697 (UninferredImpl::Def(impl_def_id), UninferredImpl::Def(other_impl_def_id)) => {
1698 impl_def_id.get_internal_id().cmp(&other_impl_def_id.get_internal_id())
1699 }
1700 (
1701 UninferredImpl::ImplAlias(impl_alias_id),
1702 UninferredImpl::ImplAlias(other_impl_alias_id),
1703 ) => impl_alias_id.get_internal_id().cmp(&other_impl_alias_id.get_internal_id()),
1704 (UninferredImpl::GenericParam(param), UninferredImpl::GenericParam(other_param)) => {
1705 param.get_internal_id().cmp(&other_param.get_internal_id())
1706 }
1707 (
1708 UninferredImpl::ImplImpl(impl_impl_id),
1709 UninferredImpl::ImplImpl(other_impl_impl_id),
1710 ) => {
1711 if impl_impl_id.impl_id() == other_impl_impl_id.impl_id() {
1712 impl_impl_id
1713 .trait_impl_id()
1714 .get_internal_id()
1715 .cmp(&other_impl_impl_id.trait_impl_id().get_internal_id())
1716 } else {
1717 impl_impl_id
1718 .impl_id()
1719 .get_internal_id()
1720 .cmp(&other_impl_impl_id.impl_id().get_internal_id())
1721 }
1722 }
1723 (
1724 UninferredImpl::GeneratedImpl(generated_impl),
1725 UninferredImpl::GeneratedImpl(other_generated_impl),
1726 ) => generated_impl.get_internal_id().cmp(&other_generated_impl.get_internal_id()),
1727 (UninferredImpl::Def(_), _) => std::cmp::Ordering::Less,
1728 (_, UninferredImpl::Def(_)) => std::cmp::Ordering::Greater,
1729 (UninferredImpl::ImplAlias(_), _) => std::cmp::Ordering::Less,
1730 (_, UninferredImpl::ImplAlias(_)) => std::cmp::Ordering::Greater,
1731 (UninferredImpl::GenericParam(_), _) => std::cmp::Ordering::Less,
1732 (_, UninferredImpl::GenericParam(_)) => std::cmp::Ordering::Greater,
1733 (UninferredImpl::ImplImpl(_), _) => std::cmp::Ordering::Less,
1734 (_, UninferredImpl::ImplImpl(_)) => std::cmp::Ordering::Greater,
1735 }
1736 }
1737}
1738impl<'db> PartialOrd for UninferredImplById<'db> {
1739 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1740 Some(self.cmp(other))
1741 }
1742}
1743impl<'db> From<UninferredImpl<'db>> for UninferredImplById<'db> {
1744 fn from(uninferred_impl: UninferredImpl<'db>) -> Self {
1745 UninferredImplById(uninferred_impl)
1746 }
1747}
1748
1749#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, salsa::Update, HeapSize)]
1750#[debug_db(dyn Database)]
1751pub struct ImplLookupContext<'db> {
1752 pub crate_id: CrateId<'db>,
1753 pub generic_params: Vec<GenericParamId<'db>>,
1754 pub inner_impls: BTreeSet<UninferredImplById<'db>>,
1755 pub negative_impls: Vec<GenericParamId<'db>>,
1756}
1757
1758define_short_id!(ImplLookupContextId, ImplLookupContext<'db>);
1759
1760impl<'db> ImplLookupContext<'db> {
1761 pub fn new_from_crate(crate_id: CrateId<'db>) -> Self {
1763 Self {
1764 crate_id,
1765 generic_params: Default::default(),
1766 inner_impls: Default::default(),
1767 negative_impls: Default::default(),
1768 }
1769 }
1770 pub fn new_from_type(ty: TypeId<'db>, db: &'db dyn Database) -> Self {
1773 Self::new_from_crate(
1774 ty.long(db)
1775 .module_id(db)
1776 .map(|m| m.owning_crate(db))
1777 .unwrap_or_else(|| db.core_crate()),
1778 )
1779 }
1780 pub fn new(
1782 module_id: ModuleId<'db>,
1783 generic_params: Vec<GenericParamId<'db>>,
1784 db: &'db dyn Database,
1785 ) -> ImplLookupContext<'db> {
1786 let crate_id = module_id.owning_crate(db);
1787 let negative_impls = generic_params
1788 .iter()
1789 .filter(|generic_param_id| matches!(generic_param_id.kind(db), GenericKind::NegImpl))
1790 .copied()
1791 .collect_vec();
1792 let generic_params = generic_params
1793 .iter()
1794 .filter(|generic_param_id| {
1795 if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1796 return false;
1797 }
1798
1799 let uninferred_impl = UninferredImpl::GenericParam(**generic_param_id);
1800
1801 let Ok(trait_id) = uninferred_impl.trait_id(db) else {
1802 return true;
1803 };
1804 let Some(set) = db.crate_global_impls(crate_id).get(&trait_id) else {
1805 return true;
1806 };
1807 let uninferred_impl: UninferredImplById<'db> = uninferred_impl.into();
1808 if set.contains(&uninferred_impl) {
1809 return false;
1810 };
1811 true
1812 })
1813 .copied()
1814 .collect_vec();
1815 let mut res = Self {
1816 crate_id,
1817 generic_params: generic_params
1818 .clone()
1819 .into_iter()
1820 .filter(|id| id.long(db).has_type_constraints_syntax(db))
1821 .collect_vec(),
1822 inner_impls: BTreeSet::from_iter(
1823 generic_params.into_iter().map(|id| UninferredImpl::GenericParam(id).into()),
1824 ),
1825 negative_impls,
1826 };
1827 res.insert_module(module_id, db);
1828 res
1829 }
1830 pub fn insert_lookup_scope(&mut self, db: &'db dyn Database, imp: &UninferredImpl<'db>) {
1831 match imp {
1832 UninferredImpl::Def(impl_def_id) => {
1833 self.insert_module(impl_def_id.parent_module(db), db)
1834 }
1835 UninferredImpl::ImplAlias(impl_alias_id) => {
1836 self.insert_module(impl_alias_id.parent_module(db), db)
1837 }
1838 UninferredImpl::GenericParam(param) => self.insert_module(param.parent_module(db), db),
1839 UninferredImpl::ImplImpl(impl_impl_id) => self.insert_impl(impl_impl_id.impl_id, db),
1840 UninferredImpl::GeneratedImpl(_) => {
1841 }
1843 };
1844 }
1845 pub fn insert_module(&mut self, module_id: ModuleId<'db>, db: &'db dyn Database) {
1848 let module_id = db.module_perceived_module(module_id);
1850 let crate_global_impls = db.crate_global_impls(self.crate_id);
1851 if let Ok(module_impls) = db.module_global_impls((), module_id) {
1852 module_impls.locals.iter().for_each(|imp| {
1853 if let Ok(trait_id) = imp.0.trait_id(db)
1854 && let Some(set) = crate_global_impls.get(&trait_id)
1855 && set.contains(imp)
1856 {
1857 return;
1858 }
1859
1860 self.inner_impls.insert(*imp);
1861 });
1862 if !crate_dependencies(db, self.crate_id).contains(&module_id.owning_crate(db)) {
1864 module_impls.globals_by_trait.iter().for_each(|(_, imps)| {
1865 imps.iter().for_each(|imp| {
1866 if let Ok(trait_id) = imp.0.trait_id(db)
1867 && let Some(set) = crate_global_impls.get(&trait_id)
1868 && set.contains(imp)
1869 {
1870 return;
1871 }
1872
1873 self.inner_impls.insert(*imp);
1874 });
1875 });
1876 }
1877 }
1878 }
1879
1880 pub fn insert_impl(&mut self, impl_id: ImplId<'db>, db: &'db dyn Database) {
1883 let mut uninferred_impls = Vec::new();
1884 let Ok(concrete_trait) = impl_id.concrete_trait(db) else {
1885 return;
1886 };
1887 let Ok(trait_impls) = db.trait_impls(concrete_trait.trait_id(db)) else {
1888 return;
1889 };
1890 for (_, trait_impl_id) in trait_impls.iter() {
1891 uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1892 impl_id,
1893 *trait_impl_id,
1894 db,
1895 )));
1896 }
1897 for uninferred_impl in uninferred_impls {
1898 self.inner_impls.insert(uninferred_impl.into());
1899 }
1900 }
1901
1902 pub fn strip_for_trait_id(&mut self, db: &dyn Database, trait_id: TraitId<'db>) {
1905 let deps = db.reachable_trait_dependencies(trait_id, self.crate_id);
1906 let type_eq_trt = db.core_info().type_eq_trt;
1907 self.inner_impls.retain(|impl_by_id| {
1908 if let Ok(impl_trait_id) = impl_by_id.0.trait_id(db) {
1909 return trait_id == impl_trait_id
1910 || trait_id == type_eq_trt
1911 || deps.contains(&impl_trait_id);
1912 }
1913
1914 false
1915 });
1916 }
1917}
1918
1919#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, HeapSize, salsa::Update)]
1921pub enum UninferredImpl<'db> {
1922 Def(ImplDefId<'db>),
1923 ImplAlias(ImplAliasId<'db>),
1924 GenericParam(GenericParamId<'db>),
1925 ImplImpl(ImplImplId<'db>),
1926 GeneratedImpl(UninferredGeneratedImplId<'db>),
1927}
1928impl<'db> UninferredImpl<'db> {
1929 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
1930 match self {
1931 UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1932 UninferredImpl::ImplAlias(impl_alias_id) => {
1933 let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1934 impl_id.concrete_trait(db)
1935 }
1936 UninferredImpl::GenericParam(param) => {
1937 let param =
1938 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1939 param.concrete_trait
1940 }
1941 UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1942 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1943 }
1944 }
1945
1946 fn trait_id(&self, db: &'db dyn Database) -> Maybe<TraitId<'db>> {
1947 match self {
1948 UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1949 UninferredImpl::ImplAlias(impl_alias_id) => {
1950 let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1951 db.impl_def_trait(impl_def_id)
1952 }
1953 UninferredImpl::GenericParam(param) => db.generic_impl_param_trait(*param),
1954 UninferredImpl::ImplImpl(impl_impl_id) => db
1955 .impl_impl_concrete_trait(*impl_impl_id)
1956 .map(|concrete_trait| concrete_trait.trait_id(db)),
1957 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1958 }
1959 }
1960
1961 fn trait_shallow_generic_args(
1963 &self,
1964 db: &'db dyn Database,
1965 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
1966 match self {
1967 UninferredImpl::Def(impl_def_id) => {
1968 db.impl_def_shallow_trait_generic_args(*impl_def_id)
1969 }
1970
1971 UninferredImpl::ImplAlias(impl_alias_id) => {
1972 db.impl_alias_trait_generic_args(*impl_alias_id)
1973 }
1974 UninferredImpl::GenericParam(param) => {
1975 db.generic_impl_param_shallow_trait_generic_args(*param)
1976 }
1977 UninferredImpl::ImplImpl(_impl_impl_id) => Ok(&[]),
1979 UninferredImpl::GeneratedImpl(_generated_impl) => Ok(&[]),
1980 }
1981 }
1982}
1983
1984impl<'db> DebugWithDb<'db> for UninferredImpl<'db> {
1985 type Db = dyn Database;
1986
1987 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
1988 match self {
1989 UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
1990 UninferredImpl::ImplAlias(impl_alias) => {
1991 write!(f, "{:?}", impl_alias.full_path(db))
1992 }
1993 UninferredImpl::GenericParam(param) => {
1994 write!(
1995 f,
1996 "generic param {}",
1997 param.name(db).map(|name| name.long(db).as_str()).unwrap_or("_")
1998 )
1999 }
2000 UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db),
2001 UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db),
2002 }
2003 }
2004}
2005
2006define_short_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'db>);
2007impl<'db> UnstableSalsaId for UninferredGeneratedImplId<'db> {
2008 fn get_internal_id(&self) -> salsa::Id {
2009 self.0
2010 }
2011}
2012semantic_object_for_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'a>);
2013
2014impl<'db> UninferredGeneratedImplId<'db> {
2015 pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
2016 self.long(db).concrete_trait
2017 }
2018
2019 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
2020 self.concrete_trait(db).trait_id(db)
2021 }
2022}
2023
2024#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
2026pub struct UninferredGeneratedImplLongId<'db> {
2027 pub concrete_trait: ConcreteTraitId<'db>,
2028 pub generic_params: Vec<GenericParam<'db>>,
2029 pub impl_items: GeneratedImplItems<'db>,
2030}
2031
2032impl<'db> DebugWithDb<'db> for UninferredGeneratedImplLongId<'db> {
2033 type Db = dyn Database;
2034
2035 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2036 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
2037 }
2038}
2039
2040#[salsa::tracked(returns(ref))]
2042fn trait_candidate_by_head<'db>(
2043 db: &'db dyn Database,
2044 crate_id: CrateId<'db>,
2045 trait_id: TraitId<'db>,
2046) -> OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
2047 let mut res: OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> =
2048 OrderedHashMap::default();
2049
2050 if let Some(candidates) = db.crate_global_impls(crate_id).get(&trait_id) {
2051 for candidate in candidates.iter() {
2052 let Ok(shallow_generic_args) = candidate.0.trait_shallow_generic_args(db) else {
2053 continue;
2054 };
2055 let Ok(trait_params) = db.trait_generic_params(trait_id) else {
2056 continue;
2057 };
2058 let Some(first_param) = trait_params.first() else {
2059 res.entry(GenericsHeadFilter::NoGenerics).or_default().insert(*candidate);
2060 continue;
2061 };
2062
2063 let shallow_arg =
2065 shallow_generic_args.iter().find(|(param, _)| *param == first_param.id());
2066 if let Some(first_generic_head) = shallow_arg.map(|(_, arg)| arg.head()) {
2067 if !matches!(candidate.0, UninferredImpl::GenericParam(_)) {
2068 let mut type_head = first_generic_head.clone();
2069 while let TypeHead::Snapshot(inner) = type_head {
2070 type_head = *inner;
2071 }
2072 if matches!(type_head, TypeHead::Generic(_)) {
2073 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2074 continue;
2075 }
2076 }
2077 res.entry(GenericsHeadFilter::FirstGenericFilter(GenericArgumentHead::Type(
2078 first_generic_head,
2079 )))
2080 .or_default()
2081 .insert(*candidate);
2082 } else {
2083 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2084 }
2085 }
2086 }
2087 res
2088}
2089
2090pub fn find_candidates_at_context<'db>(
2092 db: &'db dyn Database,
2093 lookup_context: ImplLookupContextId<'db>,
2094 filter: TraitFilter<'db>,
2095) -> Maybe<OrderedHashSet<UninferredImplById<'db>>> {
2096 let mut res = OrderedHashSet::default();
2097 let lookup = lookup_context.long(db);
2098 let crate_id = lookup.crate_id;
2099 let locals = lookup
2100 .inner_impls
2101 .iter()
2102 .filter(|uninferred_impl| {
2103 let Ok(trait_id) = uninferred_impl.0.trait_id(db) else { return false };
2104 trait_id == filter.trait_id
2105 })
2106 .cloned();
2107 match filter.generics_filter {
2108 GenericsHeadFilter::NoFilter => {
2109 let globals = db.crate_global_impls(crate_id);
2110 let globals = globals.get(&filter.trait_id);
2111 res.extend(locals);
2112 res.extend(globals.into_iter().flat_map(|s| s.iter().cloned()))
2113 }
2114 _ => {
2115 let candidates_by_head = db.trait_candidate_by_head(crate_id, filter.trait_id);
2116 let filtered = candidates_by_head.get(&filter.generics_filter).cloned();
2117 let no_filtered = candidates_by_head.get(&GenericsHeadFilter::NoFilter).cloned();
2118 res.extend(filtered.into_iter().flat_map(|s| s.into_iter()));
2119 res.extend(no_filtered.into_iter().flat_map(|s| s.into_iter()));
2120 res.extend(locals.filter(|uninferred_impl| {
2121 let Ok(_) = uninferred_impl.0.concrete_trait(db) else {
2122 return false;
2123 };
2124 true
2127 }));
2128 }
2129 }
2130 Ok(res)
2131}
2132
2133pub fn find_closure_generated_candidate<'db>(
2135 db: &'db dyn Database,
2136 concrete_trait_id: ConcreteTraitId<'db>,
2137) -> Option<UninferredImpl<'db>> {
2138 let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
2139 return None;
2140 };
2141 let TypeLongId::Closure(closure_type_long) = closure_type.long(db) else {
2142 return None;
2143 };
2144
2145 let info = db.core_info();
2146
2147 let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
2149 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2150 chain!(
2151 closure_type_long.captured_types.iter().unique().map(|ty| {
2152 GenericParam::Impl(GenericParamImpl {
2153 id,
2154 concrete_trait: Maybe::Ok(ConcreteTraitId::new(
2155 db,
2156 ConcreteTraitLongId {
2157 trait_id,
2158 generic_args: vec![GenericArgumentId::Type(*ty)],
2159 },
2160 )),
2161 type_constraints: Default::default(),
2162 })
2163 }),
2164 neg_impl_trait.map(|neg_impl_trait| {
2165 GenericParam::NegImpl(GenericParamImpl {
2166 id,
2167 concrete_trait: Maybe::Ok(neg_impl_trait),
2168 type_constraints: Default::default(),
2169 })
2170 })
2171 )
2172 .collect()
2173 };
2174 let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
2175 (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
2176 };
2177 let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
2178 trait_id if trait_id == info.fn_once_trt => {
2179 let concrete_trait = ConcreteTraitLongId {
2180 trait_id,
2181 generic_args: vec![
2182 GenericArgumentId::Type(closure_type),
2183 GenericArgumentId::Type(
2184 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2185 ),
2186 ],
2187 }
2188 .intern(db);
2189 let ret_ty =
2190 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2191
2192 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2193 let param: GenericParam<'_> = GenericParam::NegImpl(GenericParamImpl {
2195 id,
2196 concrete_trait: Maybe::Ok(
2197 ConcreteTraitLongId {
2198 trait_id: info.fn_trt,
2199 generic_args: vec![
2200 GenericArgumentId::Type(closure_type),
2201 GenericArgumentId::Type(
2202 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2203 ),
2204 ],
2205 }
2206 .intern(db),
2207 ),
2208 type_constraints: Default::default(),
2209 });
2210 (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
2211 }
2212 trait_id if trait_id == info.fn_trt => {
2213 let concrete_trait = ConcreteTraitLongId {
2214 trait_id,
2215 generic_args: vec![
2216 GenericArgumentId::Type(closure_type),
2217 GenericArgumentId::Type(
2218 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2219 ),
2220 ],
2221 }
2222 .intern(db);
2223 let ret_ty =
2224 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2225
2226 (
2227 concrete_trait,
2228 mem_trait_generic_params(info.copy_trt, None),
2230 [(ret_ty, closure_type_long.ret_ty)].into(),
2231 )
2232 }
2233 trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2234 trait_id if trait_id == info.destruct_trt => {
2235 handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2236 }
2237 trait_id if trait_id == info.panic_destruct_trt => {
2238 handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2239 }
2240 trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2241 _ => return None,
2242 };
2243 Some(UninferredImpl::GeneratedImpl(
2244 UninferredGeneratedImplLongId {
2245 concrete_trait,
2246 generic_params,
2247 impl_items: GeneratedImplItems(impl_items),
2248 }
2249 .intern(db),
2250 ))
2251}
2252
2253pub fn find_integer_literal_generated_candidate<'db>(
2260 db: &'db dyn Database,
2261 concrete_trait_id: ConcreteTraitId<'db>,
2262) -> Option<UninferredImpl<'db>> {
2263 let GenericArgumentId::Type(ty) = *concrete_trait_id.generic_args(db).first()? else {
2264 return None;
2265 };
2266 if !matches!(ty.long(db), TypeLongId::NumericLiteral(_)) {
2267 return None;
2268 }
2269 let info = db.core_info();
2270 let trait_id = concrete_trait_id.trait_id(db);
2271 if ![info.drop_trt, info.copy_trt, info.destruct_trt, info.panic_destruct_trt]
2272 .contains(&trait_id)
2273 {
2274 return None;
2275 }
2276 Some(UninferredImpl::GeneratedImpl(
2277 UninferredGeneratedImplLongId {
2278 concrete_trait: concrete_trait_id,
2279 generic_params: vec![],
2280 impl_items: GeneratedImplItems(Default::default()),
2281 }
2282 .intern(db),
2283 ))
2284}
2285
2286pub fn can_infer_impl_by_self<'db>(
2292 ctx: &ComputationContext<'db, '_>,
2293 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2294 trait_function_id: TraitFunctionId<'db>,
2295 self_ty: TypeId<'db>,
2296 stable_ptr: SyntaxStablePtrId<'db>,
2297) -> bool {
2298 let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2299 let mut temp_inference = temp_inference_data.inference(ctx.db);
2300 let lookup_context = ctx.resolver.impl_lookup_context();
2301
2302 let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2303 trait_function_id,
2304 self_ty,
2305 lookup_context,
2306 Some(stable_ptr),
2307 inference_errors,
2308 ) else {
2309 return false;
2310 };
2311 if let Err(err_set) = temp_inference.solve() {
2313 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2315 inference_errors.push((trait_function_id, err));
2316 }
2317 }
2318 match temp_inference.trait_solution_set(
2319 concrete_trait_id,
2320 ImplVarTraitItemMappings::default(),
2321 lookup_context,
2322 ) {
2323 Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2324 Ok(SolutionSet::None) => {
2325 inference_errors
2326 .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2327 false
2328 }
2329 Err(err_set) => {
2330 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2332 inference_errors.push((trait_function_id, err));
2333 }
2334 false
2335 }
2336 }
2337}
2338
2339pub fn infer_impl_by_self<'db>(
2342 ctx: &mut ComputationContext<'db, '_>,
2343 trait_function_id: TraitFunctionId<'db>,
2344 self_ty: TypeId<'db>,
2345 stable_ptr: SyntaxStablePtrId<'db>,
2346 generic_args_syntax: Option<Vec<GenericArg<'db>>>,
2347) -> Maybe<(FunctionId<'db>, usize)> {
2348 let lookup_context = ctx.resolver.impl_lookup_context();
2349 let (concrete_trait_id, n_snapshots) = ctx
2350 .resolver
2351 .inference()
2352 .infer_concrete_trait_by_self_without_errors(
2353 trait_function_id,
2354 self_ty,
2355 lookup_context,
2356 Some(stable_ptr),
2357 )
2358 .ok_or_else(skip_diagnostic)?;
2359
2360 let concrete_trait_function_id =
2361 ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2362 .intern(ctx.db);
2363 let trait_func_generic_params =
2364 ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2365
2366 let impl_lookup_context = ctx.resolver.impl_lookup_context();
2367 let inference = &mut ctx.resolver.inference();
2368 let generic_function = inference.infer_trait_generic_function(
2369 concrete_trait_function_id,
2370 impl_lookup_context,
2371 Some(stable_ptr),
2372 );
2373 let generic_args = ctx.resolver.resolve_generic_args(
2374 ctx.diagnostics,
2375 GenericSubstitution::from_impl(generic_function.impl_id),
2376 trait_func_generic_params,
2377 &generic_args_syntax.unwrap_or_default(),
2378 stable_ptr,
2379 )?;
2380
2381 Ok((
2382 FunctionLongId {
2383 function: ConcreteFunction {
2384 generic_function: GenericFunctionId::Impl(generic_function),
2385 generic_args,
2386 },
2387 }
2388 .intern(ctx.db),
2389 n_snapshots,
2390 ))
2391}
2392
2393pub fn filter_candidate_traits<'db>(
2399 ctx: &mut ComputationContext<'db, '_>,
2400 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2401 self_ty: TypeId<'db>,
2402 candidate_traits: &[TraitId<'db>],
2403 function_name: SmolStrId<'db>,
2404 stable_ptr: SyntaxStablePtrId<'db>,
2405) -> Vec<TraitFunctionId<'db>> {
2406 let mut candidates = Vec::new();
2407 for trait_id in candidate_traits.iter().copied() {
2408 let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2409 continue;
2410 };
2411 for (&name, &trait_function) in trait_functions.iter() {
2412 if name == function_name
2413 && can_infer_impl_by_self(
2414 ctx,
2415 inference_errors,
2416 trait_function,
2417 self_ty,
2418 stable_ptr,
2419 )
2420 {
2421 candidates.push(trait_function);
2422 }
2423 }
2424 }
2425 candidates
2426}
2427
2428#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2431#[debug_db(dyn Database)]
2432struct ImplItemTypeData<'db> {
2433 type_alias_data: TypeAliasData<'db>,
2434 trait_type_id: Maybe<TraitTypeId<'db>>,
2435 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2437}
2438
2439#[salsa::tracked(cycle_result=impl_type_semantic_data_cycle, returns(ref))]
2445fn impl_type_semantic_data<'db>(
2446 db: &'db dyn Database,
2447 impl_type_def_id: ImplTypeDefId<'db>,
2448 in_cycle: bool,
2449) -> Maybe<ImplItemTypeData<'db>> {
2450 let mut diagnostics =
2451 SemanticDiagnostics::new(impl_type_def_id.impl_def_id(db).parent_module(db));
2452 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2453 let generic_params_data =
2454 impl_type_def_generic_params_data(db, impl_type_def_id).maybe_as_ref()?.clone();
2455 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2456
2457 let trait_type_id =
2458 validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, &impl_type_def_ast);
2459
2460 if in_cycle {
2461 Ok(ImplItemTypeData {
2462 type_alias_data: type_alias_semantic_data_cycle_helper(
2463 db,
2464 &mut diagnostics,
2465 &impl_type_def_ast,
2466 lookup_item_id,
2467 generic_params_data,
2468 )?,
2469 trait_type_id,
2470 diagnostics: diagnostics.build(),
2471 })
2472 } else {
2473 Ok(ImplItemTypeData {
2476 type_alias_data: type_alias_semantic_data_helper(
2477 db,
2478 &mut diagnostics,
2479 &impl_type_def_ast,
2480 lookup_item_id,
2481 generic_params_data,
2482 )?,
2483 trait_type_id,
2484 diagnostics: diagnostics.build(),
2485 })
2486 }
2487}
2488
2489fn impl_type_semantic_data_cycle<'db>(
2490 db: &'db dyn Database,
2491 _id: salsa::Id,
2492 impl_type_def_id: ImplTypeDefId<'db>,
2493 _in_cycle: bool,
2494) -> Maybe<ImplItemTypeData<'db>> {
2495 impl_type_semantic_data(db, impl_type_def_id, true).clone()
2496}
2497
2498#[salsa::tracked(returns(ref))]
2500fn impl_type_def_generic_params_data<'db>(
2501 db: &'db dyn Database,
2502 impl_type_def_id: ImplTypeDefId<'db>,
2503) -> Maybe<GenericParamsData<'db>> {
2504 let module_id = impl_type_def_id.parent_module(db);
2505 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2506 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2507
2508 let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2509 type_alias_generic_params_data_helper(
2510 db,
2511 module_id,
2512 &impl_type_def_ast,
2513 lookup_item_id,
2514 Some(impl_resolver_data),
2515 )
2516}
2517
2518fn validate_impl_item_type<'db>(
2520 db: &'db dyn Database,
2521 diagnostics: &mut SemanticDiagnostics<'db>,
2522 impl_type_def_id: ImplTypeDefId<'db>,
2523 impl_type_ast: &ast::ItemTypeAlias<'db>,
2524) -> Maybe<TraitTypeId<'db>> {
2525 let impl_def_id = impl_type_def_id.impl_def_id(db);
2526 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2527 let trait_id = concrete_trait_id.trait_id(db);
2528 let type_name = impl_type_def_id.name(db);
2529 let trait_type_id = db.trait_type_by_name(trait_id, type_name)?.ok_or_else(|| {
2530 diagnostics.report(
2531 impl_type_ast.stable_ptr(db),
2532 ImplItemNotInTrait {
2533 impl_def_id,
2534 impl_item_name: type_name,
2535 trait_id,
2536 item_kind: "type".into(),
2537 },
2538 )
2539 })?;
2540
2541 let generic_params_node = impl_type_ast.generic_params(db);
2544 if !generic_params_node.is_empty(db) {
2545 diagnostics.report(
2546 generic_params_node.stable_ptr(db),
2547 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2548 );
2549 }
2550
2551 Ok(trait_type_id)
2552}
2553
2554fn impl_type_concrete_implized<'db>(
2558 db: &'db dyn Database,
2559 impl_type_id: ImplTypeId<'db>,
2560) -> Maybe<TypeId<'db>> {
2561 let concrete_impl = match impl_type_id.impl_id().long(db) {
2562 ImplLongId::Concrete(concrete_impl) => concrete_impl,
2563 ImplLongId::ImplImpl(imp_impl_id) => {
2564 let ImplLongId::Concrete(concrete_impl) =
2565 db.impl_impl_concrete_implized(*imp_impl_id)?.long(db)
2566 else {
2567 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2568 };
2569 concrete_impl
2570 }
2571 ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2572 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2573 }
2574 ImplLongId::GeneratedImpl(generated) => {
2575 return Ok(*generated.long(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2576 }
2577 };
2578
2579 let impl_def_id = concrete_impl.impl_def_id(db);
2580 let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id)?;
2581 concrete_impl.substitution(db)?.substitute(db, ty)
2582}
2583
2584#[salsa::tracked(cycle_result=impl_type_concrete_implized_cycle)]
2585fn impl_type_concrete_implized_helper<'db>(
2586 db: &'db dyn Database,
2587 _tracked: Tracked,
2588 impl_type_id: ImplTypeId<'db>,
2589) -> Maybe<TypeId<'db>> {
2590 impl_type_concrete_implized(db, impl_type_id)
2591}
2592
2593fn impl_type_concrete_implized_tracked<'db>(
2595 db: &'db dyn Database,
2596 impl_type_id: ImplTypeId<'db>,
2597) -> Maybe<TypeId<'db>> {
2598 impl_type_concrete_implized_helper(db, (), impl_type_id)
2599}
2600
2601fn impl_type_concrete_implized_cycle<'db>(
2603 db: &'db dyn Database,
2604 _id: salsa::Id,
2605 _tracked: Tracked,
2606 impl_type_id: ImplTypeId<'db>,
2607) -> Maybe<TypeId<'db>> {
2608 impl_type_concrete_implized(db, impl_type_id)
2610}
2611
2612#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2615#[debug_db(dyn Database)]
2616struct ImplItemConstantData<'db> {
2617 constant_data: ConstantData<'db>,
2618 trait_constant_id: Maybe<TraitConstantId<'db>>,
2619 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2621}
2622
2623#[salsa::tracked(cycle_result=impl_constant_semantic_data_cycle, returns(ref))]
2625fn impl_constant_semantic_data<'db>(
2626 db: &'db dyn Database,
2627 impl_constant_def_id: ImplConstantDefId<'db>,
2628 in_cycle: bool,
2629) -> Maybe<ImplItemConstantData<'db>> {
2630 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2631 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2632 let impl_constant_defs = db.impl_constants(impl_def_id)?;
2633 let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2634 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2635
2636 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2637 ImplItemId::Constant(impl_constant_def_id),
2638 ));
2639 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2640 let mut resolver =
2641 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2642
2643 let trait_constant_id = validate_impl_item_constant(
2644 db,
2645 &mut diagnostics,
2646 impl_constant_def_id,
2647 impl_constant_def_ast,
2648 &mut resolver,
2649 );
2650 let mut constant_data = if in_cycle {
2651 constant_semantic_data_cycle_helper(
2652 db,
2653 impl_constant_def_ast,
2654 lookup_item_id,
2655 Some(Arc::new(resolver.data)),
2656 &impl_def_id,
2657 )?
2658 } else {
2659 constant_semantic_data_helper(
2660 db,
2661 impl_constant_def_ast,
2662 lookup_item_id,
2663 Some(Arc::new(resolver.data)),
2664 &impl_def_id,
2665 )?
2666 };
2667 diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2668 Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2669}
2670
2671fn impl_constant_semantic_data_cycle<'db>(
2672 db: &'db dyn Database,
2673 _id: salsa::Id,
2674 impl_constant_def_id: ImplConstantDefId<'db>,
2675 _in_cycle: bool,
2676) -> Maybe<ImplItemConstantData<'db>> {
2677 impl_constant_semantic_data(db, impl_constant_def_id, true).clone()
2678}
2679
2680fn validate_impl_item_constant<'db>(
2682 db: &'db dyn Database,
2683 diagnostics: &mut SemanticDiagnostics<'db>,
2684 impl_constant_def_id: ImplConstantDefId<'db>,
2685 impl_constant_ast: &ast::ItemConstant<'db>,
2686 resolver: &mut Resolver<'db>,
2687) -> Maybe<TraitConstantId<'db>> {
2688 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2689 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2690 let trait_id = concrete_trait_id.trait_id(db);
2691 let constant_name = impl_constant_def_id.name(db);
2692
2693 let trait_constant_id =
2694 db.trait_constant_by_name(trait_id, constant_name)?.ok_or_else(|| {
2695 diagnostics.report(
2696 impl_constant_ast.stable_ptr(db),
2697 ImplItemNotInTrait {
2698 impl_def_id,
2699 impl_item_name: constant_name,
2700 trait_id,
2701 item_kind: "const".into(),
2702 },
2703 )
2704 })?;
2705 let concrete_trait_constant =
2706 ConcreteTraitConstantId::new_from_data(db, concrete_trait_id, trait_constant_id);
2707 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2708 let concrete_trait_constant_ty = impl_def_substitution
2709 .substitute(db, db.concrete_trait_constant_type(concrete_trait_constant)?)?;
2710
2711 let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2712
2713 let constant_ty =
2714 resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2715
2716 let inference = &mut resolver.inference();
2717
2718 let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2719 let actual_ty = inference.rewrite(constant_ty).no_err();
2720 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
2721 diagnostics.report(
2722 impl_constant_type_clause_ast.ty(db).stable_ptr(db),
2723 WrongType { expected_ty, actual_ty },
2724 );
2725 }
2726 Ok(trait_constant_id)
2727}
2728
2729fn impl_constant_implized_by_context<'db>(
2733 db: &'db dyn Database,
2734 impl_constant_id: ImplConstantId<'db>,
2735 impl_def_id: ImplDefId<'db>,
2736) -> Maybe<ConstValueId<'db>> {
2737 let impl_constant_def_id: ImplConstantDefId<'_> =
2738 db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2739
2740 db.impl_constant_def_value(impl_constant_def_id)
2741}
2742
2743#[salsa::tracked(cycle_result=impl_constant_implized_by_context_cycle)]
2745fn impl_constant_implized_by_context_tracked<'db>(
2746 db: &'db dyn Database,
2747 impl_constant_id: ImplConstantId<'db>,
2748 impl_def_id: ImplDefId<'db>,
2749) -> Maybe<ConstValueId<'db>> {
2750 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2751}
2752
2753fn impl_constant_implized_by_context_cycle<'db>(
2755 db: &'db dyn Database,
2756 _id: salsa::Id,
2757 impl_constant_id: ImplConstantId<'db>,
2758 impl_def_id: ImplDefId<'db>,
2759) -> Maybe<ConstValueId<'db>> {
2760 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2762}
2763
2764fn impl_constant_concrete_implized_value<'db>(
2766 db: &'db dyn Database,
2767 impl_constant_id: ImplConstantId<'db>,
2768) -> Maybe<ConstValueId<'db>> {
2769 if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().long(db) {
2770 let impl_def_id = concrete_impl.impl_def_id(db);
2771 let constant: ConstValueId<'db> =
2772 db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2773 return concrete_impl.substitution(db)?.substitute(db, constant);
2774 }
2775 let substitution: GenericSubstitution<'db> =
2776 GenericSubstitution::from_impl(impl_constant_id.impl_id());
2777 let substitution_id = substitution.substitute(db, impl_constant_id)?;
2778 let const_val: ConstValue<'db> = ConstValue::ImplConstant(substitution_id);
2779 Ok(const_val.intern(db))
2780}
2781
2782fn impl_constant_concrete_implized_value_tracked<'db>(
2784 db: &'db dyn Database,
2785 impl_constant_id: ImplConstantId<'db>,
2786) -> Maybe<ConstValueId<'db>> {
2787 impl_constant_concrete_implized_value_helper(db, (), impl_constant_id)
2788}
2789
2790#[salsa::tracked(cycle_result=impl_constant_concrete_implized_value_cycle)]
2793fn impl_constant_concrete_implized_value_helper<'db>(
2794 db: &'db dyn Database,
2795 _tracked: Tracked,
2796 impl_constant_id: ImplConstantId<'db>,
2797) -> Maybe<ConstValueId<'db>> {
2798 impl_constant_concrete_implized_value(db, impl_constant_id)
2799}
2800
2801fn impl_constant_concrete_implized_value_cycle<'db>(
2803 db: &'db dyn Database,
2804 _id: salsa::Id,
2805 _tracked: Tracked,
2806 impl_constant_id: ImplConstantId<'db>,
2807) -> Maybe<ConstValueId<'db>> {
2808 impl_constant_concrete_implized_value(db, impl_constant_id)
2810}
2811
2812fn impl_constant_concrete_implized_type<'db>(
2814 db: &'db dyn Database,
2815 impl_constant_id: ImplConstantId<'db>,
2816) -> Maybe<TypeId<'db>> {
2817 let concrete_trait_id = match impl_constant_id.impl_id().long(db) {
2818 ImplLongId::Concrete(concrete_impl) => {
2819 let impl_def_id = concrete_impl.impl_def_id(db);
2820 let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2821 return concrete_impl.substitution(db)?.substitute(db, ty);
2822 }
2823 ImplLongId::GenericParameter(param) => {
2824 let param_impl =
2825 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
2826 param_impl.concrete_trait?
2827 }
2828 ImplLongId::ImplVar(var) => var.long(db).concrete_trait_id,
2829 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl)?,
2830 ImplLongId::SelfImpl(concrete_trait_id) => *concrete_trait_id,
2831 ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2832 };
2833
2834 let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new_from_data(
2835 db,
2836 concrete_trait_id,
2837 impl_constant_id.trait_constant_id(),
2838 ))?;
2839 GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2840}
2841
2842fn impl_constant_concrete_implized_type_tracked<'db>(
2844 db: &'db dyn Database,
2845 impl_constant_id: ImplConstantId<'db>,
2846) -> Maybe<TypeId<'db>> {
2847 impl_constant_concrete_implized_type_helper(db, (), impl_constant_id)
2848}
2849
2850#[salsa::tracked(cycle_result=impl_constant_concrete_implized_type_cycle)]
2851fn impl_constant_concrete_implized_type_helper<'db>(
2852 db: &'db dyn Database,
2853 _tracked: Tracked,
2854 impl_constant_id: ImplConstantId<'db>,
2855) -> Maybe<TypeId<'db>> {
2856 impl_constant_concrete_implized_type(db, impl_constant_id)
2857}
2858
2859fn impl_constant_concrete_implized_type_cycle<'db>(
2861 db: &'db dyn Database,
2862 _id: salsa::Id,
2863 _tracked: Tracked,
2864 impl_constant_id: ImplConstantId<'db>,
2865) -> Maybe<TypeId<'db>> {
2866 impl_constant_concrete_implized_type(db, impl_constant_id)
2868}
2869
2870#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2873#[debug_db(dyn Database)]
2874struct ImplItemImplData<'db> {
2875 impl_data: ImplAliasData<'db>,
2876 trait_impl_id: Maybe<TraitImplId<'db>>,
2877 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2879}
2880
2881#[salsa::tracked(cycle_result=impl_impl_semantic_data_cycle, returns(ref))]
2883fn impl_impl_semantic_data<'db>(
2884 db: &'db dyn Database,
2885 impl_impl_def_id: ImplImplDefId<'db>,
2886 in_cycle: bool,
2887) -> Maybe<ImplItemImplData<'db>> {
2888 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2889 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2890 let impl_impl_defs = db.impl_impls(impl_def_id)?;
2891 let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2892 let generic_params_data =
2893 impl_impl_def_generic_params_data(db, impl_impl_def_id).maybe_as_ref()?.clone();
2894 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2895
2896 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2897 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2898 let mut resolver =
2899 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2900
2901 let mut impl_data = if in_cycle {
2902 impl_alias_semantic_data_cycle_helper(
2903 db,
2904 impl_impl_def_ast,
2905 lookup_item_id,
2906 generic_params_data,
2907 )?
2908 } else {
2909 impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2910 };
2911
2912 diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2913
2914 let trait_impl_id = validate_impl_item_impl(
2915 db,
2916 &mut diagnostics,
2917 impl_impl_def_id,
2918 impl_impl_def_ast,
2919 &impl_data,
2920 &mut resolver,
2921 );
2922
2923 Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2924}
2925
2926fn impl_impl_semantic_data_cycle<'db>(
2927 db: &'db dyn Database,
2928 _id: salsa::Id,
2929 impl_impl_def_id: ImplImplDefId<'db>,
2930 _in_cycle: bool,
2931) -> Maybe<ImplItemImplData<'db>> {
2932 impl_impl_semantic_data(db, impl_impl_def_id, true).clone()
2933}
2934
2935#[salsa::tracked(returns(ref))]
2937fn impl_impl_def_generic_params_data<'db>(
2938 db: &'db dyn Database,
2939 impl_impl_def_id: ImplImplDefId<'db>,
2940) -> Maybe<GenericParamsData<'db>> {
2941 let module_id = impl_impl_def_id.parent_module(db);
2942 let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?;
2943 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2944
2945 let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2946 impl_alias_generic_params_data_helper(
2947 db,
2948 module_id,
2949 &impl_impl_def_ast,
2950 lookup_item_id,
2951 Some(impl_resolver_data),
2952 )
2953}
2954
2955fn validate_impl_item_impl<'db>(
2957 db: &'db dyn Database,
2958 diagnostics: &mut SemanticDiagnostics<'db>,
2959 impl_impl_def_id: ImplImplDefId<'db>,
2960 impl_impl_ast: &ast::ItemImplAlias<'db>,
2961 impl_data: &ImplAliasData<'db>,
2962 resolver: &mut Resolver<'db>,
2963) -> Maybe<TraitImplId<'db>> {
2964 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2965 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2966 let trait_id = concrete_trait_id.trait_id(db);
2967 let impl_item_name = impl_impl_def_id.name(db);
2968 let trait_impl_id = db.trait_impl_by_name(trait_id, impl_item_name)?.ok_or_else(|| {
2969 diagnostics.report(
2970 impl_impl_ast.stable_ptr(db),
2971 ImplItemNotInTrait { impl_def_id, impl_item_name, trait_id, item_kind: "impl".into() },
2972 )
2973 })?;
2974
2975 let generic_params_node = impl_impl_ast.generic_params(db);
2978 if !generic_params_node.is_empty(db) {
2979 diagnostics.report(
2980 generic_params_node.stable_ptr(db),
2981 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2982 );
2983 }
2984
2985 let concrete_trait_impl =
2986 ConcreteTraitImplId::new_from_data(db, concrete_trait_id, trait_impl_id);
2987 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2988
2989 let concrete_trait_impl_concrete_trait = db
2990 .concrete_trait_impl_concrete_trait(concrete_trait_impl)
2991 .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
2992
2993 let resolved_impl_concrete_trait =
2994 impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2995 let _ = (|| -> Result<(), DiagnosticAdded> {
2997 if resolver
2998 .inference()
2999 .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
3000 .is_err()
3001 {
3002 diagnostics.report(
3003 impl_impl_ast.stable_ptr(db),
3004 TraitMismatch {
3005 expected_trt: concrete_trait_impl_concrete_trait?,
3006 actual_trt: resolved_impl_concrete_trait?,
3007 },
3008 );
3009 }
3010 Ok(())
3011 })();
3012
3013 Ok(trait_impl_id)
3014}
3015
3016#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3017#[debug_db(dyn Database)]
3018struct ImplicitImplImplData<'db> {
3019 resolved_impl: Maybe<ImplId<'db>>,
3020 trait_impl_id: TraitImplId<'db>,
3021 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
3022}
3023
3024fn implicit_impl_impl_semantic_data<'db>(
3026 db: &'db dyn Database,
3027 impl_def_id: ImplDefId<'db>,
3028 trait_impl_id: TraitImplId<'db>,
3029 in_cycle: bool,
3030) -> Maybe<ImplicitImplImplData<'db>> {
3031 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3032 if in_cycle {
3033 let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
3034 return Ok(ImplicitImplImplData {
3035 resolved_impl: err,
3036 trait_impl_id,
3037 diagnostics: diagnostics.build(),
3038 });
3039 }
3040 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
3041
3042 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3043 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3044
3045 let mut resolver =
3046 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3047 resolver.trait_or_impl_ctx = TraitOrImplContext::None;
3049
3050 let concrete_trait_impl_concrete_trait = db
3051 .impl_def_concrete_trait(impl_def_id)
3052 .and_then(|concrete_trait_id| {
3053 db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new_from_data(
3054 db,
3055 concrete_trait_id,
3056 trait_impl_id,
3057 ))
3058 })
3059 .and_then(|concrete_trait_id| {
3060 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3061 impl_def_substitution.substitute(db, concrete_trait_id)
3062 });
3063 let impl_lookup_context = resolver.impl_lookup_context();
3064 let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
3065 let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
3066 resolver.inference().finalize_without_reporting().map_err(|err_set| {
3067 diagnostics.report(
3068 impl_def_id.stable_ptr(db).untyped(),
3069 ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
3070 );
3071 resolver.inference().report_on_pending_error(
3072 err_set,
3073 &mut diagnostics,
3074 impl_def_id.stable_ptr(db).untyped(),
3075 )
3076 })?;
3077 resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
3078 });
3079
3080 Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
3081}
3082
3083#[salsa::tracked(cycle_result=implicit_impl_impl_semantic_data_cycle, returns(ref))]
3085fn implicit_impl_impl_semantic_data_tracked<'db>(
3086 db: &'db dyn Database,
3087 impl_def_id: ImplDefId<'db>,
3088 trait_impl_id: TraitImplId<'db>,
3089 in_cycle: bool,
3090) -> Maybe<ImplicitImplImplData<'db>> {
3091 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, in_cycle)
3092}
3093
3094fn implicit_impl_impl_semantic_data_cycle<'db>(
3096 db: &'db dyn Database,
3097 _id: salsa::Id,
3098 impl_def_id: ImplDefId<'db>,
3099 trait_impl_id: TraitImplId<'db>,
3100 _in_cycle: bool,
3101) -> Maybe<ImplicitImplImplData<'db>> {
3102 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, true)
3104}
3105
3106fn impl_impl_implized_by_context<'db>(
3110 db: &'db dyn Database,
3111 impl_impl_id: ImplImplId<'db>,
3112 impl_def_id: ImplDefId<'db>,
3113 in_cycle: bool,
3114) -> Maybe<ImplId<'db>> {
3115 if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
3116 return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
3117 }
3118
3119 let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
3120
3121 db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
3122}
3123
3124#[salsa::tracked(cycle_result=impl_impl_implized_by_context_cycle)]
3126fn impl_impl_implized_by_context_tracked<'db>(
3127 db: &'db dyn Database,
3128 impl_impl_id: ImplImplId<'db>,
3129 impl_def_id: ImplDefId<'db>,
3130 in_cycle: bool,
3131) -> Maybe<ImplId<'db>> {
3132 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, in_cycle)
3133}
3134
3135fn impl_impl_implized_by_context_cycle<'db>(
3137 db: &'db dyn Database,
3138 _id: salsa::Id,
3139 impl_impl_id: ImplImplId<'db>,
3140 impl_def_id: ImplDefId<'db>,
3141 _in_cycle: bool,
3142) -> Maybe<ImplId<'db>> {
3143 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, true)
3145}
3146
3147fn impl_impl_concrete_implized<'db>(
3149 db: &'db dyn Database,
3150 impl_impl_id: ImplImplId<'db>,
3151) -> Maybe<ImplId<'db>> {
3152 impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3153}
3154
3155fn impl_impl_concrete_implized_tracked<'db>(
3157 db: &'db dyn Database,
3158 impl_impl_id: ImplImplId<'db>,
3159) -> Maybe<ImplId<'db>> {
3160 impl_impl_concrete_implized_helper(db, (), impl_impl_id)
3161}
3162
3163#[salsa::tracked(cycle_result=impl_impl_concrete_implized_cycle)]
3164fn impl_impl_concrete_implized_helper<'db>(
3165 db: &'db dyn Database,
3166 _tracked: Tracked,
3167 impl_impl_id: ImplImplId<'db>,
3168) -> Maybe<ImplId<'db>> {
3169 impl_impl_concrete_implized(db, impl_impl_id)
3170}
3171
3172fn impl_impl_concrete_implized_cycle<'db>(
3174 db: &'db dyn Database,
3175 _id: salsa::Id,
3176 _tracked: Tracked,
3177 impl_impl_id: ImplImplId<'db>,
3178) -> Maybe<ImplId<'db>> {
3179 impl_impl_concrete_implized_ex(db, impl_impl_id, true)
3180}
3181
3182fn impl_impl_concrete_implized_ex<'db>(
3183 db: &'db dyn Database,
3184 impl_impl_id: ImplImplId<'db>,
3185 in_cycle: bool,
3186) -> Maybe<ImplId<'db>> {
3187 if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().long(db) {
3188 let impl_def_id = concrete_impl.impl_def_id(db);
3189 let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
3190 return concrete_impl.substitution(db)?.substitute(db, imp);
3191 }
3192
3193 Ok(ImplLongId::ImplImpl(
3194 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, impl_impl_id)?,
3195 )
3196 .intern(db))
3197}
3198
3199fn impl_impl_concrete_trait<'db>(
3201 db: &'db dyn Database,
3202 impl_impl_id: ImplImplId<'db>,
3203) -> Maybe<ConcreteTraitId<'db>> {
3204 let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
3205 db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
3206 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, concrete_trait_id)
3207 })
3208}
3209
3210fn impl_impl_concrete_trait_tracked<'db>(
3212 db: &'db dyn Database,
3213 impl_impl_id: ImplImplId<'db>,
3214) -> Maybe<ConcreteTraitId<'db>> {
3215 impl_impl_concrete_trait_helper(db, (), impl_impl_id)
3216}
3217
3218#[salsa::tracked]
3219fn impl_impl_concrete_trait_helper<'db>(
3220 db: &'db dyn Database,
3221 _tracked: Tracked,
3222 impl_impl_id: ImplImplId<'db>,
3223) -> Maybe<ConcreteTraitId<'db>> {
3224 impl_impl_concrete_trait(db, impl_impl_id)
3225}
3226
3227#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3230#[debug_db(dyn Database)]
3231struct ImplFunctionDeclarationData<'db> {
3232 function_declaration_data: FunctionDeclarationData<'db>,
3233 trait_function_id: Maybe<TraitFunctionId<'db>>,
3234}
3235
3236#[salsa::tracked(returns(ref))]
3238fn impl_function_generic_params_data<'db>(
3239 db: &'db dyn Database,
3240 impl_function_id: ImplFunctionId<'db>,
3241) -> Maybe<GenericParamsData<'db>> {
3242 let module_id = impl_function_id.parent_module(db);
3243 let mut diagnostics = SemanticDiagnostics::new(module_id);
3244 let impl_def_id = impl_function_id.impl_def_id(db);
3245 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3246 let function_syntax = &data.function_asts[&impl_function_id];
3247 let declaration = function_syntax.declaration(db);
3248 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
3249 ImplItemId::Function(impl_function_id),
3250 ));
3251 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3252 let mut resolver =
3253 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3254 let generic_params = semantic_generic_params(
3255 db,
3256 &mut diagnostics,
3257 &mut resolver,
3258 module_id,
3259 &declaration.generic_params(db),
3260 );
3261 let inference = &mut resolver.inference();
3262 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3263
3264 let generic_params = inference.rewrite(generic_params).no_err();
3265 let resolver_data = Arc::new(resolver.data);
3266 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
3267}
3268
3269#[salsa::tracked(returns(ref))]
3271fn impl_function_declaration_data<'db>(
3272 db: &'db dyn Database,
3273 impl_function_id: ImplFunctionId<'db>,
3274) -> Maybe<ImplFunctionDeclarationData<'db>> {
3275 let impl_def_id = impl_function_id.impl_def_id(db);
3276 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3277 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3278 let function_syntax = &data.function_asts[&impl_function_id];
3279 let declaration = function_syntax.declaration(db);
3280
3281 let generic_params_data =
3282 impl_function_generic_params_data(db, impl_function_id).maybe_as_ref()?.clone();
3283 let generic_params = generic_params_data.generic_params;
3284 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3285 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3286 let mut resolver = Resolver::with_data(
3287 db,
3288 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3289 );
3290 diagnostics.extend(generic_params_data.diagnostics);
3291 resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3292
3293 let mut environment = Environment::empty();
3294 let signature = semantic::Signature::from_ast(
3295 &mut diagnostics,
3296 db,
3297 &mut resolver,
3298 &declaration,
3299 FunctionTitleId::Impl(impl_function_id),
3300 &mut environment,
3301 );
3302
3303 let attributes = function_syntax.attributes(db).structurize(db);
3304 let (implicit_precedence, _) =
3305 get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
3306
3307 let inference = &mut resolver.inference();
3308 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3310 let signature_syntax = declaration.signature(db);
3311 let trait_function_id = validate_impl_function_signature(
3312 db,
3313 &mut diagnostics,
3314 inference,
3315 ValidateImplFunctionSignatureParams {
3316 impl_function_id,
3317 signature_syntax: &signature_syntax,
3318 signature: &signature,
3319 impl_function_syntax: function_syntax,
3320 impl_func_generics: &generic_params,
3321 },
3322 );
3323
3324 let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3325
3326 forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3327
3328 let signature = inference.rewrite(signature).no_err();
3329
3330 let resolver_data = Arc::new(resolver.data);
3331 Ok(ImplFunctionDeclarationData {
3332 function_declaration_data: FunctionDeclarationData {
3333 diagnostics: diagnostics.build(),
3334 signature,
3335 environment,
3336 attributes,
3337 resolver_data,
3338 inline_config,
3339 implicit_precedence,
3340 },
3341 trait_function_id,
3342 })
3343}
3344
3345struct ValidateImplFunctionSignatureParams<'a, 'r> {
3347 impl_function_id: ImplFunctionId<'a>,
3349 signature_syntax: &'r ast::FunctionSignature<'a>,
3351 signature: &'r semantic::Signature<'a>,
3353 impl_function_syntax: &'r ast::FunctionWithBody<'a>,
3355 impl_func_generics: &'r [GenericParam<'a>],
3357}
3358
3359fn validate_impl_function_signature<'db>(
3361 db: &'db dyn Database,
3362 diagnostics: &mut SemanticDiagnostics<'db>,
3363 inference: &mut Inference<'db, '_>,
3364 ValidateImplFunctionSignatureParams {
3365 impl_function_id,
3366 signature_syntax,
3367 signature,
3368 impl_function_syntax,
3369 impl_func_generics,
3370 }: ValidateImplFunctionSignatureParams<'db, '_>,
3371) -> Maybe<TraitFunctionId<'db>> {
3372 let impl_def_id = impl_function_id.impl_def_id(db);
3373 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3374 let trait_id = concrete_trait_id.trait_id(db);
3375 let function_name = impl_function_id.name(db);
3376 let trait_function_id =
3377 db.trait_function_by_name(trait_id, function_name)?.ok_or_else(|| {
3378 diagnostics.report(
3379 impl_function_syntax.stable_ptr(db),
3380 ImplItemNotInTrait {
3381 impl_def_id,
3382 impl_item_name: function_name,
3383 trait_id,
3384 item_kind: "function".into(),
3385 },
3386 )
3387 })?;
3388 let concrete_trait_function =
3389 ConcreteTraitGenericFunctionId::new_from_data(db, concrete_trait_id, trait_function_id);
3390 let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3391
3392 let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3396 if impl_func_generics.len() != func_generics.len() {
3397 diagnostics.report(
3398 impl_function_syntax.declaration(db).name(db).stable_ptr(db),
3399 WrongNumberOfGenericParamsForImplFunction {
3400 expected: func_generics.len(),
3401 actual: impl_func_generics.len(),
3402 },
3403 );
3404 return Ok(trait_function_id);
3405 }
3406 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3407 let func_generics: Vec<GenericParam<'_>> =
3408 impl_def_substitution.substitute(db, func_generics.to_vec())?;
3409
3410 let function_substitution =
3411 GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3412
3413 for (trait_generic_param, generic_param) in izip!(func_generics, impl_func_generics.iter()) {
3414 if let Some(name) = trait_generic_param.id().name(db)
3415 && Some(name) != generic_param.id().name(db)
3416 {
3417 diagnostics.report(
3418 generic_param.stable_ptr(db),
3419 WrongParameterName { impl_def_id, impl_function_id, trait_id, expected_name: name },
3420 );
3421 }
3422 match (generic_param, trait_generic_param) {
3423 (GenericParam::Type(_), GenericParam::Type(_)) => {}
3424 (GenericParam::Impl(generic_param), GenericParam::Impl(trait_generic_param))
3425 | (GenericParam::NegImpl(generic_param), GenericParam::NegImpl(trait_generic_param)) => {
3426 let rewritten_trait_param_trait =
3427 function_substitution.substitute(db, trait_generic_param.concrete_trait)?;
3428 let rewritten_trait_param_type_constraints =
3429 function_substitution.substitute(db, trait_generic_param.type_constraints)?;
3430 generic_param
3431 .concrete_trait
3432 .map(|actual_trait| {
3433 rewritten_trait_param_trait
3434 .map(|expected_trait| {
3435 if actual_trait != expected_trait
3436 || generic_param.type_constraints
3437 != rewritten_trait_param_type_constraints
3438 {
3439 diagnostics.report(
3440 generic_param.id.stable_ptr(db),
3441 WrongGenericParamTraitForImplFunction {
3442 impl_def_id,
3443 impl_function_id,
3444 trait_id,
3445 expected_trait,
3446 actual_trait,
3447 },
3448 );
3449 }
3450 })
3451 .ok();
3452 })
3453 .ok();
3454 }
3455 (GenericParam::Const(generic_param), GenericParam::Const(trait_generic_param)) => {
3456 let expected_ty = function_substitution.substitute(db, trait_generic_param.ty)?;
3457 if generic_param.ty != expected_ty {
3458 diagnostics.report(
3459 generic_param.id.stable_ptr(db),
3460 WrongParameterType {
3461 impl_def_id,
3462 impl_function_id,
3463 trait_id,
3464 expected_ty,
3465 actual_ty: generic_param.ty,
3466 },
3467 );
3468 }
3469 }
3470 (generic_param, trait_generic_param) => {
3471 diagnostics.report(
3472 generic_param.stable_ptr(db),
3473 WrongGenericParamKindForImplFunction {
3474 impl_def_id,
3475 impl_function_id,
3476 trait_id,
3477 expected_kind: trait_generic_param.kind(),
3478 actual_kind: generic_param.kind(),
3479 },
3480 );
3481 }
3482 }
3483 }
3484
3485 let concrete_trait_signature =
3486 function_substitution.substitute(db, concrete_trait_signature.clone())?;
3487
3488 if signature.params.len() != concrete_trait_signature.params.len() {
3489 diagnostics.report(
3490 signature_syntax.parameters(db).stable_ptr(db),
3491 WrongNumberOfParameters {
3492 impl_def_id,
3493 impl_function_id,
3494 trait_id,
3495 expected: concrete_trait_signature.params.len(),
3496 actual: signature.params.len(),
3497 },
3498 );
3499 }
3500 let concrete_trait_signature =
3501 impl_def_substitution.substitute(db, concrete_trait_signature)?;
3502 for (param, trait_param) in
3503 izip!(signature.params.iter(), concrete_trait_signature.params.iter())
3504 {
3505 let expected_ty = inference.rewrite(trait_param.ty).no_err();
3506 let actual_ty = inference.rewrite(param.ty).no_err();
3507
3508 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3509 diagnostics.report(
3510 extract_matches!(
3511 param.stable_ptr(db).lookup(db).type_clause(db),
3512 OptionTypeClause::TypeClause
3513 )
3514 .ty(db)
3515 .stable_ptr(db),
3516 WrongParameterType {
3517 impl_def_id,
3518 impl_function_id,
3519 trait_id,
3520 expected_ty,
3521 actual_ty,
3522 },
3523 );
3524 }
3525
3526 if trait_param.mutability != param.mutability {
3527 if trait_param.mutability == Mutability::Reference {
3528 diagnostics.report(
3529 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3530 ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3531 );
3532 }
3533
3534 if param.mutability == Mutability::Reference {
3535 diagnostics.report(
3536 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3537 ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3538 );
3539 }
3540 }
3541
3542 if trait_param.name != param.name {
3543 diagnostics.report(
3544 param.stable_ptr(db).lookup(db).name(db).stable_ptr(db),
3545 WrongParameterName {
3546 impl_def_id,
3547 impl_function_id,
3548 trait_id,
3549 expected_name: trait_param.name,
3550 },
3551 );
3552 }
3553 }
3554
3555 if !concrete_trait_signature.panicable && signature.panicable {
3556 diagnostics.report(
3557 signature_syntax.stable_ptr(db),
3558 PassPanicAsNopanic { impl_function_id, trait_id },
3559 );
3560 }
3561
3562 if concrete_trait_signature.is_const && !signature.is_const {
3563 diagnostics.report(
3564 signature_syntax.stable_ptr(db),
3565 PassConstAsNonConst { impl_function_id, trait_id },
3566 );
3567 }
3568
3569 let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3570 let actual_ty = inference.rewrite(signature.return_type).no_err();
3571
3572 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3573 let location_ptr = match signature_syntax.ret_ty(db) {
3574 OptionReturnTypeClause::ReturnTypeClause(ret_ty) => ret_ty.ty(db).as_syntax_node(),
3575 OptionReturnTypeClause::Empty(_) => {
3576 impl_function_syntax.body(db).lbrace(db).as_syntax_node()
3577 }
3578 }
3579 .stable_ptr(db);
3580 diagnostics.report(
3581 location_ptr,
3582 WrongReturnTypeForImpl {
3583 impl_def_id,
3584 impl_function_id,
3585 trait_id,
3586 expected_ty,
3587 actual_ty,
3588 },
3589 );
3590 }
3591 Ok(trait_function_id)
3592}
3593
3594fn priv_impl_function_body_data<'db>(
3596 db: &'db dyn Database,
3597 impl_function_id: ImplFunctionId<'db>,
3598) -> Maybe<FunctionBodyData<'db>> {
3599 let impl_def_id = impl_function_id.impl_def_id(db);
3600 let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3601 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3602 let function_syntax = &data.function_asts[&impl_function_id];
3603 let declaration = impl_function_declaration_data(db, impl_function_id).maybe_as_ref()?;
3605 let parent_resolver_data = declaration.function_declaration_data.resolver_data.clone();
3606 let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3607 ImplItemId::Function(impl_function_id),
3608 ));
3609 let mut resolver =
3610 Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3611 let environment: Environment<'_> = declaration.function_declaration_data.environment.clone();
3612
3613 let function_id = (|| {
3614 let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3615 let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3616
3617 let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3618 impl_id: ImplLongId::Concrete(
3619 ConcreteImplLongId {
3620 impl_def_id,
3621 generic_args: generic_params_to_args(generic_parameters, db),
3622 }
3623 .intern(db),
3624 )
3625 .intern(db),
3626 function: trait_function_id,
3627 });
3628
3629 Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3630 })();
3631 let mut ctx = ComputationContext::new(
3633 db,
3634 &mut diagnostics,
3635 &mut resolver,
3636 Some(&declaration.function_declaration_data.signature),
3637 environment,
3638 ContextFunction::Function(function_id),
3639 );
3640 let function_body = function_syntax.body(db);
3641 let return_type = declaration.function_declaration_data.signature.return_type;
3642 let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3643 let ComputationContext { arenas, .. } = ctx;
3644
3645 let expr_lookup: UnorderedHashMap<_, _> =
3646 arenas.exprs.iter().map(|(id, expr)| (expr.stable_ptr(), id)).collect();
3647 let pattern_lookup: UnorderedHashMap<_, _> =
3648 arenas.patterns.iter().map(|(id, pattern)| (pattern.stable_ptr(), id)).collect();
3649 let resolver_data = Arc::new(resolver.data);
3650 Ok(FunctionBodyData {
3651 diagnostics: diagnostics.build(),
3652 expr_lookup,
3653 pattern_lookup,
3654 resolver_data,
3655 body: FunctionBody { arenas, body_expr },
3656 })
3657}
3658
3659#[salsa::tracked(returns(ref))]
3661fn priv_impl_function_body_data_tracked<'db>(
3662 db: &'db dyn Database,
3663 impl_function_id: ImplFunctionId<'db>,
3664) -> Maybe<FunctionBodyData<'db>> {
3665 priv_impl_function_body_data(db, impl_function_id)
3666}
3667
3668#[salsa::tracked]
3669fn impl_is_fully_concrete<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3670 impl_id.long(db).is_fully_concrete(db)
3671}
3672
3673#[salsa::tracked]
3674fn impl_is_var_free<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3675 impl_id.long(db).is_var_free(db)
3676}
3677
3678#[salsa::tracked(returns(ref))]
3680fn crate_dependencies<'db>(
3681 db: &'db dyn Database,
3682 crate_id: CrateId<'db>,
3683) -> OrderedHashSet<CrateId<'db>> {
3684 let mut crates = [crate_id, db.core_crate()].into_iter().unique().collect_vec();
3685 let mut crates_set: OrderedHashSet<CrateId<'db>, _> = OrderedHashSet::<
3686 CrateId<'db>,
3687 std::collections::hash_map::RandomState,
3688 >::from_iter(crates.iter().copied());
3689 while let Some(crate_id) = crates.pop() {
3690 let default_settings = Default::default();
3691 let settings =
3692 db.crate_config(crate_id).as_ref().map(|c| &c.settings).unwrap_or(&default_settings);
3693
3694 for (ident, dep) in &settings.dependencies {
3695 let dep_crate_id = CrateLongId::Real {
3696 name: SmolStrId::from(db, ident.clone()),
3697 discriminator: dep.discriminator.clone(),
3698 }
3699 .intern(db);
3700 if !crates_set.contains(&dep_crate_id) {
3701 crates.push(dep_crate_id);
3702 crates_set.insert(dep_crate_id);
3703 }
3704 }
3705 }
3706 crates_set
3707}
3708
3709#[salsa::tracked(returns(ref))]
3710fn crate_global_impls<'db>(
3712 db: &'db dyn Database,
3713 crate_id: CrateId<'db>,
3714) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
3715 let mut crate_global_impls: UnorderedHashMap<
3716 TraitId<'db>,
3717 OrderedHashSet<UninferredImplById<'db>>,
3718 > = UnorderedHashMap::default();
3719 for crate_id in crate_dependencies(db, crate_id).iter() {
3720 let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3721 while let Some(module_id) = modules.pop() {
3722 if let Ok(module_impls) = db.module_global_impls((), module_id) {
3723 for (trait_id, impls) in module_impls.globals_by_trait.iter() {
3724 crate_global_impls.entry(*trait_id).or_default().extend(impls.clone());
3725 }
3726 }
3727 if let Ok(x) = db.module_submodules_ids(module_id) {
3728 modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3729 }
3730 if let Ok(macro_call_ids) = db.module_macro_calls_ids(module_id) {
3731 modules.extend(
3732 macro_call_ids
3733 .iter()
3734 .map(|id| db.macro_call_module_id(*id))
3735 .filter_map(|x| x.ok()),
3736 )
3737 }
3738 }
3739 }
3740 crate_global_impls
3741}
3742
3743#[salsa::tracked(returns(ref))]
3745fn crate_traits_dependencies<'db>(
3746 db: &'db dyn Database,
3747 crate_id: CrateId<'db>,
3748) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
3749 let mut dependencies: UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> =
3750 UnorderedHashMap::default();
3751 for crate_id in crate_dependencies(db, crate_id).iter() {
3752 let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3753 while let Some(module_id) = modules.pop() {
3754 if let Ok(module_impls) = db.module_global_impls((), module_id) {
3755 for (trait_id, impls) in module_impls.trait_deps.iter() {
3756 dependencies.entry(*trait_id).or_default().extend(impls.clone());
3757 }
3758 }
3759 if let Ok(x) = db.module_submodules_ids(module_id) {
3760 modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3761 }
3762 }
3763 }
3764
3765 dependencies
3766}
3767
3768#[salsa::tracked(returns(ref))]
3770fn reachable_trait_dependencies<'db>(
3771 db: &'db dyn Database,
3772 trait_id: TraitId<'db>,
3773 crate_id: CrateId<'db>,
3774) -> OrderedHashSet<TraitId<'db>> {
3775 let dependencies = db.crate_traits_dependencies(crate_id);
3776 let mut reachable_deps = OrderedHashSet::default();
3777 let mut to_visit = vec![trait_id];
3778 let mut visited: UnorderedHashSet<TraitId<'db>> = UnorderedHashSet::default();
3779 while let Some(current_trait) = to_visit.pop() {
3780 if visited.contains(¤t_trait) {
3781 continue;
3782 }
3783 visited.insert(current_trait);
3784 if let Some(deps) = dependencies.get(¤t_trait) {
3785 for dep in deps.iter() {
3786 reachable_deps.insert(*dep);
3787 if !visited.contains(dep) {
3788 to_visit.push(*dep);
3789 }
3790 }
3791 }
3792 }
3793 reachable_deps
3794}
3795
3796fn uninferred_impl_trait_dependency<'db>(
3798 db: &'db dyn Database,
3799 impl_id: UninferredImpl<'db>,
3800 trait_deps: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3801) -> Maybe<()> {
3802 if let Ok(imp_trait_id) = impl_id.trait_id(db) {
3803 let (mut resolver, module_id, generic_params, mut diagnostics) = match impl_id {
3804 UninferredImpl::Def(impl_def_id) => {
3805 let module_id = impl_def_id.parent_module(db);
3806 let mut diagnostics = SemanticDiagnostics::new(module_id);
3807
3808 let impl_ast = db.module_impl_by_id(impl_def_id)?;
3809 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
3810
3811 let mut resolver = Resolver::new(db, module_id, inference_id);
3812 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
3813 (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3814 }
3815 UninferredImpl::ImplAlias(impl_alias_id) => {
3816 let module_id = impl_alias_id.parent_module(db);
3817 let mut diagnostics = SemanticDiagnostics::new(module_id);
3818
3819 let impl_ast = db.module_impl_alias_by_id(impl_alias_id)?;
3820 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
3821
3822 let mut resolver = Resolver::new(db, module_id, inference_id);
3823 resolver.set_feature_config(&impl_alias_id, &impl_ast, &mut diagnostics);
3824 (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3825 }
3826 _ => {
3827 return Ok(());
3828 }
3829 };
3830 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) = generic_params
3831 {
3832 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
3833 let generic_param_id =
3834 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
3835 resolver.add_generic_param(generic_param_id);
3836 let trait_path = match param_syntax {
3837 ast::GenericParam::ImplNamed(param) => param.trait_path(db),
3838 ast::GenericParam::ImplAnonymous(param) => param.trait_path(db),
3839 ast::GenericParam::NegativeImpl(param) => param.trait_path(db),
3840
3841 _ => return,
3842 };
3843 let dependant_trait_id =
3844 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path);
3845
3846 let Ok(dependant_trait_id) = dependant_trait_id else {
3847 return;
3848 };
3849 trait_deps.entry(imp_trait_id).or_default().insert(dependant_trait_id);
3850 })
3851 };
3852 };
3853 Ok(())
3854}
3855
3856#[derive(Default, Debug, Eq, PartialEq, salsa::Update)]
3857struct ModuleImpls<'db> {
3858 globals_by_trait: OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3859 trait_deps: OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3860 globals_by_type: OrderedHashMap<TypeId<'db>, Vec<UninferredImpl<'db>>>,
3861
3862 locals: BTreeSet<UninferredImplById<'db>>,
3863}
3864
3865#[salsa::tracked(returns(ref))]
3866fn module_global_impls<'db>(
3867 db: &'db dyn Database,
3868 _tracked: Tracked,
3869 module_id: ModuleId<'db>,
3870) -> Maybe<ModuleImpls<'db>> {
3871 let mut module_impls = ModuleImpls::default();
3872 for (containing_module, info) in db.module_imported_modules((), module_id).iter() {
3873 for defined_module in module_macro_modules(db, true, *containing_module) {
3874 let Ok(module_semantic_data) = db.priv_module_semantic_data(*defined_module) else {
3875 continue;
3876 };
3877 for item in module_semantic_data.items.values().filter(|item| {
3878 info.user_modules.iter().any(|user_module| {
3879 peek_visible_in(db, item.visibility, *containing_module, *user_module)
3880 })
3881 }) {
3882 let imp = match item.item_id {
3883 ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
3884 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
3885 UninferredImpl::Def(impl_def_id)
3886 }
3887 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
3888 UninferredImpl::ImplAlias(impl_alias_id)
3889 }
3890 _ => continue,
3891 },
3892 ModuleItemId::Impl(impl_def_id) => {
3893 if let Ok(impl_ast) = db.module_impl_by_id(impl_def_id) {
3894 global_impls_insert_generic_impls(
3895 db,
3896 &impl_ast.generic_params(db),
3897 impl_def_id.parent_module(db),
3898 &mut module_impls.globals_by_trait,
3899 );
3900 }
3901
3902 UninferredImpl::Def(impl_def_id)
3905 }
3906 ModuleItemId::ImplAlias(impl_alias_id) => {
3908 UninferredImpl::ImplAlias(impl_alias_id)
3909 }
3910 ModuleItemId::FreeFunction(free_function_id) => {
3911 if let Ok(function_ast) = db.module_free_function_by_id(free_function_id) {
3912 let declaration = function_ast.declaration(db);
3913 global_impls_insert_generic_impls(
3914 db,
3915 &declaration.generic_params(db),
3916 free_function_id.parent_module(db),
3917 &mut module_impls.globals_by_trait,
3918 );
3919 }
3920 continue;
3921 }
3922 _ => continue,
3923 };
3924
3925 uninferred_impl_trait_dependency(db, imp, &mut module_impls.trait_deps)?;
3926
3927 if let Ok(true) = is_global_impl(db, imp, module_id) {
3928 let trait_id = imp.trait_id(db)?;
3929 module_impls.globals_by_trait.entry(trait_id).or_default().insert(imp.into());
3930 } else {
3931 module_impls.locals.insert(imp.into());
3932 }
3933 }
3934 }
3935 }
3936
3937 Ok(module_impls)
3938}
3939
3940fn is_global_impl<'db>(
3944 db: &'db dyn Database,
3945 impl_id: UninferredImpl<'db>,
3946 impl_module: ModuleId<'db>,
3947) -> Maybe<bool> {
3948 let trait_id = impl_id.trait_id(db)?;
3949 if trait_id.parent_module(db) == impl_module {
3950 return Ok(true);
3951 }
3952
3953 Ok(impl_id
3954 .trait_shallow_generic_args(db)?
3955 .iter()
3956 .any(|(_, arg)| arg.module_id(db) == Some(impl_module)))
3957}
3958
3959fn global_impls_insert_generic_impls<'db>(
3963 db: &'db dyn Database,
3964 generic_params: &ast::OptionWrappedGenericParamList<'db>,
3965 module_id: ModuleId<'db>,
3966 globals_by_trait: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3967) {
3968 let ast::OptionWrappedGenericParamList::WrappedGenericParamList(generic_params) =
3969 generic_params
3970 else {
3971 return;
3972 };
3973 let mut generic_types = OrderedHashMap::<_, GenericParamId<'db>, _>::default();
3974 for param in generic_params.generic_params(db).elements(db) {
3975 let (trait_path, type_constraints) = match ¶m {
3976 ast::GenericParam::Type(_) => {
3977 let param_id = GenericParamLongId(module_id, param.stable_ptr(db)).intern(db);
3978 if let Some(name) = param_id.name(db) {
3979 generic_types.insert(name, param_id);
3980 }
3981 continue;
3982 }
3983 ast::GenericParam::ImplNamed(impl_param) => {
3984 (impl_param.trait_path(db), impl_param.type_constrains(db))
3985 }
3986 ast::GenericParam::ImplAnonymous(impl_param) => {
3987 (impl_param.trait_path(db), impl_param.type_constrains(db))
3988 }
3989 _ => continue,
3990 };
3991 if is_global_impl_generic_param(db, &generic_types, &trait_path) {
3992 let uninferred_impl = UninferredImpl::GenericParam(
3993 GenericParamLongId(module_id, param.stable_ptr(db)).intern(db),
3994 );
3995 if let Ok(trait_id) = uninferred_impl.trait_id(db) {
3996 if trait_id == db.core_info().type_eq_trt {
3997 continue;
3998 }
3999 if matches!(
4000 type_constraints,
4001 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
4002 ) {
4003 continue;
4004 }
4005 globals_by_trait.entry(trait_id).or_default().insert(uninferred_impl.into());
4006 }
4007 }
4008 }
4009}
4010
4011fn is_global_impl_generic_param<'db>(
4013 db: &'db dyn Database,
4014 generic_types: &OrderedHashMap<SmolStrId<'db>, GenericParamId<'db>>,
4015 trait_syntax: &ast::ExprPath<'db>,
4016) -> bool {
4017 let trait_segments = trait_syntax.to_segments(db);
4018 let ast::PathSegment::WithGenericArgs(trait_segment) = trait_segments.last().unwrap() else {
4019 return false;
4020 };
4021
4022 let generic_args = trait_segment.generic_args(db);
4023
4024 for arg in generic_args.generic_args(db).elements(db) {
4025 let mut expr = match arg {
4026 ast::GenericArg::Unnamed(arg) => arg.value(db),
4027 ast::GenericArg::Named(arg) => arg.value(db),
4028 };
4029
4030 while let ast::Expr::Unary(unary_expr) = &expr {
4031 if !matches!(unary_expr.op(db), UnaryOperator::At(_)) {
4032 break;
4033 }
4034
4035 expr = unary_expr.expr(db);
4036 }
4037
4038 let ast::Expr::Path(path) = expr else {
4039 continue;
4040 };
4041 let path_segments = path.to_segments(db);
4042 let [segment] = path_segments.as_slice() else {
4043 continue;
4044 };
4045
4046 let ast::PathSegment::Simple(simple_segment) = segment else {
4047 continue;
4048 };
4049 if generic_types.contains_key(&simple_segment.identifier(db)) {
4050 return true;
4051 }
4052 }
4053
4054 false
4055}
4056
4057pub trait ImplSemantic<'db>: Database {
4059 fn impl_semantic_declaration_diagnostics(
4061 &'db self,
4062 impl_def_id: ImplDefId<'db>,
4063 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4064 impl_declaration_data(self.as_dyn_database(), impl_def_id)
4065 .as_ref()
4066 .map(|data| data.diagnostics.clone())
4067 .unwrap_or_default()
4068 }
4069 fn impl_def_generic_params(
4071 &'db self,
4072 impl_def_id: ImplDefId<'db>,
4073 ) -> Maybe<&'db [GenericParam<'db>]> {
4074 Ok(&impl_def_generic_params_data(self.as_dyn_database(), impl_def_id)
4075 .maybe_as_ref()?
4076 .generic_params)
4077 }
4078 fn impl_def_resolver_data(
4080 &'db self,
4081 impl_def_id: ImplDefId<'db>,
4082 ) -> Maybe<Arc<ResolverData<'db>>> {
4083 Ok(impl_declaration_data(self.as_dyn_database(), impl_def_id)
4084 .maybe_as_ref()?
4085 .resolver_data
4086 .clone())
4087 }
4088 fn impl_def_concrete_trait(
4090 &'db self,
4091 impl_def_id: ImplDefId<'db>,
4092 ) -> Maybe<ConcreteTraitId<'db>> {
4093 impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.concrete_trait
4094 }
4095 fn impl_def_attributes(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4097 Ok(&impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.attributes)
4098 }
4099 fn impl_concrete_trait(&'db self, impl_id: ImplId<'db>) -> Maybe<ConcreteTraitId<'db>> {
4101 impl_concrete_trait_tracked(self.as_dyn_database(), impl_id)
4102 }
4103 fn impl_def_trait(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
4106 impl_def_trait(self.as_dyn_database(), impl_def_id)
4107 }
4108 fn impl_semantic_definition_diagnostics(
4110 &'db self,
4111 impl_def_id: ImplDefId<'db>,
4112 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4113 impl_semantic_definition_diagnostics_tracked(self.as_dyn_database(), impl_def_id)
4114 }
4115 fn impl_item_info_by_name(
4117 &'db self,
4118 impl_def_id: ImplDefId<'db>,
4119 name: SmolStrId<'db>,
4120 ) -> Maybe<Option<ImplItemInfo<'db>>> {
4121 impl_item_info_by_name_tracked(self.as_dyn_database(), impl_def_id, name)
4122 }
4123 fn impl_all_used_uses(
4125 &'db self,
4126 impl_def_id: ImplDefId<'db>,
4127 ) -> Maybe<&'db OrderedHashSet<UseId<'db>>> {
4128 impl_all_used_uses(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4129 }
4130 fn impl_types(
4132 &'db self,
4133 impl_def_id: ImplDefId<'db>,
4134 ) -> Maybe<&'db OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>> {
4135 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4136 .maybe_as_ref()?
4137 .item_type_asts)
4138 }
4139 fn impl_type_by_trait_type(
4141 &'db self,
4142 impl_def_id: ImplDefId<'db>,
4143 trait_type_id: TraitTypeId<'db>,
4144 ) -> Maybe<ImplTypeDefId<'db>> {
4145 impl_type_by_trait_type_tracked(self.as_dyn_database(), impl_def_id, trait_type_id)
4146 }
4147 fn impl_constants(
4149 &'db self,
4150 impl_def_id: ImplDefId<'db>,
4151 ) -> Maybe<&'db OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>> {
4152 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4153 .maybe_as_ref()?
4154 .item_constant_asts)
4155 }
4156 fn impl_functions(
4158 &'db self,
4159 impl_def_id: ImplDefId<'db>,
4160 ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
4161 impl_functions(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4162 }
4163
4164 fn impl_type_def_resolved_type(&'db self, id: ImplTypeDefId<'db>) -> Maybe<TypeId<'db>> {
4168 impl_type_semantic_data(self.as_dyn_database(), id, false)
4169 .maybe_as_ref()?
4170 .type_alias_data
4171 .resolved_type
4172 }
4173 fn impl_type_def_generic_params(
4175 &'db self,
4176 id: ImplTypeDefId<'db>,
4177 ) -> Maybe<Vec<GenericParam<'db>>> {
4178 Ok(impl_type_def_generic_params_data(self.as_dyn_database(), id)
4179 .maybe_as_ref()?
4180 .generic_params
4181 .clone())
4182 }
4183 fn impl_type_def_attributes(&'db self, id: ImplTypeDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4185 Ok(&impl_type_semantic_data(self.as_dyn_database(), id, false)
4186 .maybe_as_ref()?
4187 .type_alias_data
4188 .attributes)
4189 }
4190 fn impl_type_def_resolver_data(
4192 &'db self,
4193 id: ImplTypeDefId<'db>,
4194 ) -> Maybe<Arc<ResolverData<'db>>> {
4195 Ok(impl_type_semantic_data(self.as_dyn_database(), id, false)
4196 .maybe_as_ref()?
4197 .type_alias_data
4198 .resolver_data
4199 .clone())
4200 }
4201 fn deref_chain(
4203 &'db self,
4204 ty: TypeId<'db>,
4205 crate_id: CrateId<'db>,
4206 try_deref_mut: bool,
4207 ) -> Maybe<&'db DerefChain<'db>> {
4208 deref_chain(self.as_dyn_database(), ty, crate_id, try_deref_mut).maybe_as_ref()
4209 }
4210
4211 fn impl_type_concrete_implized(
4217 &'db self,
4218 impl_type_def_id: ImplTypeId<'db>,
4219 ) -> Maybe<TypeId<'db>> {
4220 impl_type_concrete_implized_tracked(self.as_dyn_database(), impl_type_def_id)
4221 }
4222
4223 fn impl_constant_def_value(&'db self, id: ImplConstantDefId<'db>) -> Maybe<ConstValueId<'db>> {
4227 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4228 .maybe_as_ref()?
4229 .constant_data
4230 .const_value)
4231 }
4232 fn impl_constant_def_resolver_data(
4234 &'db self,
4235 id: ImplConstantDefId<'db>,
4236 ) -> Maybe<Arc<ResolverData<'db>>> {
4237 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4238 .maybe_as_ref()?
4239 .constant_data
4240 .resolver_data
4241 .clone())
4242 }
4243
4244 fn impl_constant_concrete_implized_value(
4249 &'db self,
4250 impl_constant_id: ImplConstantId<'db>,
4251 ) -> Maybe<ConstValueId<'db>> {
4252 impl_constant_concrete_implized_value_tracked(self.as_dyn_database(), impl_constant_id)
4253 }
4254 fn impl_constant_concrete_implized_type(
4257 &'db self,
4258 impl_constant_id: ImplConstantId<'db>,
4259 ) -> Maybe<TypeId<'db>> {
4260 impl_constant_concrete_implized_type_tracked(self.as_dyn_database(), impl_constant_id)
4261 }
4262
4263 fn impl_impl_def_resolver_data(
4267 &'db self,
4268 id: ImplImplDefId<'db>,
4269 ) -> Maybe<Arc<ResolverData<'db>>> {
4270 Ok(impl_impl_semantic_data(self.as_dyn_database(), id, false)
4271 .maybe_as_ref()?
4272 .impl_data
4273 .resolver_data
4274 .clone())
4275 }
4276
4277 fn impl_impl_concrete_implized(&'db self, impl_impl_id: ImplImplId<'db>) -> Maybe<ImplId<'db>> {
4281 impl_impl_concrete_implized_tracked(self.as_dyn_database(), impl_impl_id)
4282 }
4283
4284 fn impl_function_declaration_diagnostics(
4288 &'db self,
4289 id: ImplFunctionId<'db>,
4290 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4291 impl_function_declaration_data(self.as_dyn_database(), id)
4292 .as_ref()
4293 .map(|data| data.function_declaration_data.diagnostics.clone())
4294 .unwrap_or_default()
4295 }
4296 fn impl_function_signature(
4298 &'db self,
4299 id: ImplFunctionId<'db>,
4300 ) -> Maybe<&'db semantic::Signature<'db>> {
4301 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4302 .maybe_as_ref()?
4303 .function_declaration_data
4304 .signature)
4305 }
4306 fn impl_function_generic_params(
4308 &'db self,
4309 id: ImplFunctionId<'db>,
4310 ) -> Maybe<&'db [GenericParam<'db>]> {
4311 Ok(&impl_function_generic_params_data(self.as_dyn_database(), id)
4312 .maybe_as_ref()?
4313 .generic_params)
4314 }
4315 fn impl_function_attributes(
4317 &'db self,
4318 id: ImplFunctionId<'db>,
4319 ) -> Maybe<&'db [Attribute<'db>]> {
4320 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4321 .maybe_as_ref()?
4322 .function_declaration_data
4323 .attributes)
4324 }
4325 fn impl_function_resolver_data(
4327 &'db self,
4328 id: ImplFunctionId<'db>,
4329 ) -> Maybe<Arc<ResolverData<'db>>> {
4330 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4331 .maybe_as_ref()?
4332 .function_declaration_data
4333 .resolver_data
4334 .clone())
4335 }
4336 fn impl_function_declaration_inline_config(
4338 &'db self,
4339 id: ImplFunctionId<'db>,
4340 ) -> Maybe<InlineConfiguration<'db>> {
4341 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4342 .maybe_as_ref()?
4343 .function_declaration_data
4344 .inline_config
4345 .clone())
4346 }
4347 fn impl_function_declaration_implicit_precedence(
4349 &'db self,
4350 id: ImplFunctionId<'db>,
4351 ) -> Maybe<&'db ImplicitPrecedence<'db>> {
4352 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4353 .maybe_as_ref()?
4354 .function_declaration_data
4355 .implicit_precedence)
4356 }
4357 fn impl_function_trait_function(
4359 &'db self,
4360 id: ImplFunctionId<'db>,
4361 ) -> Maybe<TraitFunctionId<'db>> {
4362 impl_function_declaration_data(self.as_dyn_database(), id).maybe_as_ref()?.trait_function_id
4363 }
4364 fn impl_function_body_diagnostics(
4366 &'db self,
4367 impl_function_id: ImplFunctionId<'db>,
4368 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4369 self.priv_impl_function_body_data(impl_function_id)
4370 .map(|data| data.diagnostics.clone())
4371 .unwrap_or_default()
4372 }
4373 fn impl_function_body(
4375 &'db self,
4376 impl_function_id: ImplFunctionId<'db>,
4377 ) -> Maybe<&'db FunctionBody<'db>> {
4378 Ok(&self.priv_impl_function_body_data(impl_function_id)?.body)
4379 }
4380 fn impl_function_body_resolver_data(
4382 &'db self,
4383 impl_function_id: ImplFunctionId<'db>,
4384 ) -> Maybe<Arc<ResolverData<'db>>> {
4385 Ok(self.priv_impl_function_body_data(impl_function_id)?.resolver_data.clone())
4386 }
4387 fn priv_impl_function_body_data(
4389 &'db self,
4390 impl_function_id: ImplFunctionId<'db>,
4391 ) -> Maybe<&'db FunctionBodyData<'db>> {
4392 priv_impl_function_body_data_tracked(self.as_dyn_database(), impl_function_id)
4393 .maybe_as_ref()
4394 }
4395}
4396impl<'db, T: Database + ?Sized> ImplSemantic<'db> for T {}
4397
4398trait PrivImplSemantic<'db>: Database {
4400 fn impl_def_substitution(
4402 &'db self,
4403 impl_def_id: ImplDefId<'db>,
4404 ) -> Maybe<&'db GenericSubstitution<'db>> {
4405 impl_def_substitution(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4406 }
4407 fn impl_def_shallow_trait_generic_args(
4409 &'db self,
4410 impl_def_id: ImplDefId<'db>,
4411 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4412 impl_def_shallow_trait_generic_args(self.as_dyn_database(), impl_def_id)
4413 }
4414 fn impl_alias_trait_generic_args(
4416 &'db self,
4417 impl_def_id: ImplAliasId<'db>,
4418 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4419 impl_alias_trait_generic_args(self.as_dyn_database(), impl_def_id)
4420 }
4421 fn impl_item_by_name(
4423 &'db self,
4424 impl_def_id: ImplDefId<'db>,
4425 name: SmolStrId<'db>,
4426 ) -> Maybe<Option<ImplItemId<'db>>> {
4427 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4428 .maybe_as_ref()?
4429 .item_id_by_name
4430 .get(&name)
4431 .map(|info| info.id))
4432 }
4433 fn impl_implicit_impl_by_name(
4435 &'db self,
4436 impl_def_id: ImplDefId<'db>,
4437 name: SmolStrId<'db>,
4438 ) -> Maybe<Option<TraitImplId<'db>>> {
4439 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4440 .maybe_as_ref()?
4441 .implicit_impls_id_by_name
4442 .get(&name)
4443 .copied())
4444 }
4445 fn impl_type_by_id(
4447 &'db self,
4448 impl_type_id: ImplTypeDefId<'db>,
4449 ) -> Maybe<ast::ItemTypeAlias<'db>> {
4450 impl_type_by_id(self.as_dyn_database(), impl_type_id)
4451 }
4452 fn impl_impls(
4454 &'db self,
4455 impl_def_id: ImplDefId<'db>,
4456 ) -> Maybe<&'db OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>> {
4457 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4458 .maybe_as_ref()?
4459 .item_impl_asts)
4460 }
4461 fn impl_impl_by_id(
4463 &'db self,
4464 impl_impl_id: ImplImplDefId<'db>,
4465 ) -> Maybe<ast::ItemImplAlias<'db>> {
4466 impl_impl_by_id(self.as_dyn_database(), impl_impl_id)
4467 }
4468 fn impl_impl_by_trait_impl(
4470 &'db self,
4471 impl_def_id: ImplDefId<'db>,
4472 trait_impl_id: TraitImplId<'db>,
4473 ) -> Maybe<ImplImplDefId<'db>> {
4474 impl_impl_by_trait_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4475 }
4476 fn is_implicit_impl_impl(
4478 &self,
4479 impl_def_id: ImplDefId<'db>,
4480 trait_impl_id: TraitImplId<'db>,
4481 ) -> Maybe<bool> {
4482 is_implicit_impl_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4483 }
4484 fn impl_constant_by_trait_constant(
4486 &'db self,
4487 impl_def_id: ImplDefId<'db>,
4488 trait_constant_id: TraitConstantId<'db>,
4489 ) -> Maybe<ImplConstantDefId<'db>> {
4490 impl_constant_by_trait_constant(self.as_dyn_database(), impl_def_id, trait_constant_id)
4491 }
4492 fn impl_function_by_trait_function(
4497 &'db self,
4498 impl_def_id: ImplDefId<'db>,
4499 trait_function_id: TraitFunctionId<'db>,
4500 ) -> Maybe<Option<ImplFunctionId<'db>>> {
4501 impl_function_by_trait_function(self.as_dyn_database(), impl_def_id, trait_function_id)
4502 }
4503 fn impl_type_def_semantic_diagnostics(
4505 &'db self,
4506 id: ImplTypeDefId<'db>,
4507 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4508 impl_type_semantic_data(self.as_dyn_database(), id, false)
4509 .as_ref()
4510 .map(|data| data.diagnostics.clone())
4511 .unwrap_or_default()
4512 }
4513 fn impl_constant_def_semantic_diagnostics(
4515 &'db self,
4516 id: ImplConstantDefId<'db>,
4517 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4518 impl_constant_semantic_data(self.as_dyn_database(), id, false)
4519 .as_ref()
4520 .map(|data| data.diagnostics.clone())
4521 .unwrap_or_default()
4522 }
4523 fn impl_constant_implized_by_context(
4525 &'db self,
4526 impl_constant_id: ImplConstantId<'db>,
4527 impl_def_id: ImplDefId<'db>,
4528 ) -> Maybe<ConstValueId<'db>> {
4529 impl_constant_implized_by_context_tracked(
4530 self.as_dyn_database(),
4531 impl_constant_id,
4532 impl_def_id,
4533 )
4534 }
4535 fn impl_impl_def_semantic_diagnostics(
4537 &'db self,
4538 id: ImplImplDefId<'db>,
4539 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4540 impl_impl_semantic_data(self.as_dyn_database(), id, false)
4541 .as_ref()
4542 .map(|data| data.diagnostics.clone())
4543 .unwrap_or_default()
4544 }
4545 fn impl_impl_def_impl(
4547 &'db self,
4548 impl_impl_def_id: ImplImplDefId<'db>,
4549 in_cycle: bool,
4550 ) -> Maybe<ImplId<'db>> {
4551 impl_impl_semantic_data(self.as_dyn_database(), impl_impl_def_id, in_cycle)
4552 .maybe_as_ref()?
4553 .impl_data
4554 .resolved_impl
4555 }
4556 fn implicit_impl_impl_semantic_diagnostics(
4558 &'db self,
4559 impl_def_id: ImplDefId<'db>,
4560 trait_impl_id: TraitImplId<'db>,
4561 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4562 implicit_impl_impl_semantic_data_tracked(
4563 self.as_dyn_database(),
4564 impl_def_id,
4565 trait_impl_id,
4566 false,
4567 )
4568 .as_ref()
4569 .map(|data| data.diagnostics.clone())
4570 .unwrap_or_default()
4571 }
4572 fn implicit_impl_impl_impl(
4574 &'db self,
4575 impl_def_id: ImplDefId<'db>,
4576 trait_impl_id: TraitImplId<'db>,
4577 in_cycle: bool,
4578 ) -> Maybe<ImplId<'db>> {
4579 implicit_impl_impl_semantic_data_tracked(
4580 self.as_dyn_database(),
4581 impl_def_id,
4582 trait_impl_id,
4583 in_cycle,
4584 )
4585 .maybe_as_ref()?
4586 .resolved_impl
4587 }
4588 fn impl_impl_implized_by_context(
4590 &'db self,
4591 impl_impl_id: ImplImplId<'db>,
4592 impl_def_id: ImplDefId<'db>,
4593 in_cycle: bool,
4594 ) -> Maybe<ImplId<'db>> {
4595 impl_impl_implized_by_context_tracked(
4596 self.as_dyn_database(),
4597 impl_impl_id,
4598 impl_def_id,
4599 in_cycle,
4600 )
4601 }
4602 fn impl_impl_concrete_trait(
4604 &'db self,
4605 impl_impl_id: ImplImplId<'db>,
4606 ) -> Maybe<ConcreteTraitId<'db>> {
4607 impl_impl_concrete_trait_tracked(self.as_dyn_database(), impl_impl_id)
4608 }
4609 fn crate_global_impls(
4613 &'db self,
4614 crate_id: CrateId<'db>,
4615 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4616 crate_global_impls(self.as_dyn_database(), crate_id)
4617 }
4618 fn crate_traits_dependencies(
4620 &'db self,
4621 crate_id: CrateId<'db>,
4622 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
4623 crate_traits_dependencies(self.as_dyn_database(), crate_id)
4624 }
4625 fn reachable_trait_dependencies(
4627 &'db self,
4628 trait_id: TraitId<'db>,
4629 crate_id: CrateId<'db>,
4630 ) -> &'db OrderedHashSet<TraitId<'db>> {
4631 reachable_trait_dependencies(self.as_dyn_database(), trait_id, crate_id)
4632 }
4633 fn module_global_impls(
4635 &'db self,
4636 _tracked: Tracked,
4637 module_id: ModuleId<'db>,
4638 ) -> &'db Maybe<ModuleImpls<'db>> {
4639 module_global_impls(self.as_dyn_database(), _tracked, module_id)
4640 }
4641 fn trait_candidate_by_head(
4643 &'db self,
4644 crate_id: CrateId<'db>,
4645 trait_id: TraitId<'db>,
4646 ) -> &'db OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4647 trait_candidate_by_head(self.as_dyn_database(), crate_id, trait_id)
4648 }
4649}
4650impl<'db, T: Database + ?Sized> PrivImplSemantic<'db> for T {}