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