1use std::collections::BTreeSet;
2use std::fmt::Write;
3use std::hash::Hash;
4use std::sync::Arc;
5use std::{mem, panic, vec};
6
7use cairo_lang_debug::DebugWithDb;
8use cairo_lang_defs::db::DefsGroup;
9use cairo_lang_defs::ids::{
10 FunctionTitleId, GenericKind, GenericParamId, GenericParamLongId, ImplAliasId,
11 ImplConstantDefId, ImplConstantDefLongId, ImplDefId, ImplFunctionId, ImplFunctionLongId,
12 ImplImplDefId, ImplImplDefLongId, ImplItemId, ImplTypeDefId, ImplTypeDefLongId,
13 LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId,
14 NamedLanguageElementLongId, TopLevelLanguageElementId, TraitConstantId, TraitFunctionId,
15 TraitId, TraitImplId, TraitTypeId, UseId,
16};
17use cairo_lang_diagnostics::{
18 DiagnosticAdded, Diagnostics, DiagnosticsBuilder, Maybe, MaybeAsRef, ToMaybe, skip_diagnostic,
19};
20use cairo_lang_filesystem::db::FilesGroup;
21use cairo_lang_filesystem::ids::{CrateId, CrateLongId, SmolStrId, Tracked, UnstableSalsaId};
22use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
23use cairo_lang_syntax as syntax;
24use cairo_lang_syntax::node::ast::{
25 GenericArgValue, OptionTypeClause, OptionWrappedGenericParamList, UnaryOperator,
26};
27use cairo_lang_syntax::node::helpers::GetIdentifier;
28use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
29use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
30use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
31use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
32use cairo_lang_utils::{Intern, define_short_id, extract_matches};
33use itertools::{Itertools, chain, izip};
34use salsa::Database;
35use syntax::attribute::structured::{Attribute, AttributeListStructurize};
36use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
37use syntax::node::helpers::OptionWrappedGenericParamListHelper;
38use syntax::node::ids::SyntaxStablePtrId;
39use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
40
41use super::constant::{
42 ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
43 constant_semantic_data_helper,
44};
45use super::enm::SemanticEnumEx;
46use super::feature_kind::{FeatureKind, HasFeatureKind};
47use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
48use super::functions::{
49 FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
50 forbid_inline_always_with_impl_generic_param,
51};
52use super::generics::{
53 GenericArgumentHead, GenericParamImpl, GenericParamsData, fmt_generic_args,
54 generic_params_to_args, semantic_generic_params,
55};
56use super::impl_alias::{
57 ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
58 impl_alias_semantic_data_helper,
59};
60use super::trt::{
61 ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
62 ConcreteTraitImplId,
63};
64use super::type_aliases::{
65 TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
66 type_alias_semantic_data_helper,
67};
68use super::visibility::peek_visible_in;
69use super::{TraitOrImplContext, resolve_trait_path};
70use crate::corelib::{CorelibSemantic, concrete_destruct_trait, concrete_drop_trait, core_crate};
71use crate::db::get_resolver_data_options;
72use crate::diagnostic::SemanticDiagnosticKind::{self, *};
73use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
74use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
75use crate::expr::fmt::CountingWriter;
76use crate::expr::inference::canonic::ResultNoErrEx;
77use crate::expr::inference::conform::InferenceConform;
78use crate::expr::inference::infers::InferenceEmbeddings;
79use crate::expr::inference::solver::{Ambiguity, SolutionSet, enrich_lookup_context_with_ty};
80use crate::expr::inference::{
81 ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId, NegativeImplVarId,
82};
83use crate::items::function_with_body::get_implicit_precedence;
84use crate::items::functions::ImplicitPrecedence;
85use crate::items::generics::GenericParamSemantic;
86use crate::items::impl_alias::ImplAliasSemantic;
87use crate::items::implization::ImplizationSemantic;
88use crate::items::macro_call::{MacroCallSemantic, module_macro_modules};
89use crate::items::module::ModuleSemantic;
90use crate::items::structure::StructSemantic;
91use crate::items::trt::TraitSemantic;
92use crate::items::us::{SemanticUseEx, UseSemantic};
93use crate::resolve::{
94 AsSegments, ResolutionContext, ResolvedConcreteItem, ResolvedGenericItem, Resolver,
95 ResolverData,
96};
97use crate::substitution::{GenericSubstitution, SemanticRewriter};
98use crate::types::{
99 ImplTypeId, ShallowGenericArg, TypeHead, TypesSemantic, add_type_based_diagnostics,
100 get_impl_at_context, maybe_resolve_shallow_generic_arg_type, resolve_type,
101};
102use crate::{
103 ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
104 GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
105 semantic_object_for_id,
106};
107
108#[cfg(test)]
109#[path = "imp_test.rs"]
110mod test;
111
112#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
113pub struct ConcreteImplLongId<'db> {
114 pub impl_def_id: ImplDefId<'db>,
115 pub generic_args: Vec<GenericArgumentId<'db>>,
116}
117define_short_id!(ConcreteImplId, ConcreteImplLongId<'db>);
118semantic_object_for_id!(ConcreteImplId, ConcreteImplLongId<'a>);
119impl<'db> DebugWithDb<'db> for ConcreteImplLongId<'db> {
120 type Db = dyn Database;
121
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
123 let mut f = CountingWriter::new(f);
124 write!(f, "{}", self.impl_def_id.full_path(db))?;
125 fmt_generic_args(&self.generic_args, &mut f, db)
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)]
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 match self {
218 ImplLongId::Concrete(concrete_impl) => {
219 format!("{:?}", concrete_impl.debug(db))
220 }
221 ImplLongId::GenericParameter(generic_param_impl) => {
222 generic_param_impl.format(db).to_string(db)
223 }
224 ImplLongId::ImplVar(var) => format!("{var:?}"),
225 ImplLongId::ImplImpl(impl_impl) => format!("{:?}", impl_impl.debug(db)),
226 ImplLongId::SelfImpl(concrete_trait_id) => {
227 format!("{:?}", concrete_trait_id.debug(db))
228 }
229 ImplLongId::GeneratedImpl(generated_impl) => {
230 format!("{:?}", generated_impl.debug(db))
231 }
232 }
233 }
234
235 pub fn is_var_free(&self, db: &dyn Database) -> bool {
237 match self {
238 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
239 ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id.is_var_free(db),
240 ImplLongId::GenericParameter(_) => true,
241 ImplLongId::ImplVar(_) => false,
242 ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
243 ImplLongId::GeneratedImpl(generated_impl) => {
244 generated_impl.concrete_trait(db).is_var_free(db)
245 && generated_impl
246 .long(db)
247 .impl_items
248 .0
249 .values()
250 .all(|type_id| type_id.is_var_free(db))
251 }
252 }
253 }
254
255 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
257 match self {
258 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
259 ImplLongId::GenericParameter(_) => false,
260 ImplLongId::ImplVar(_) => false,
261 ImplLongId::ImplImpl(_) | ImplLongId::SelfImpl(_) => false,
262 ImplLongId::GeneratedImpl(generated_impl) => {
263 generated_impl.concrete_trait(db).is_fully_concrete(db)
264 && generated_impl
265 .long(db)
266 .impl_items
267 .0
268 .values()
269 .all(|type_id| type_id.is_fully_concrete(db))
270 }
271 }
272 }
273}
274impl<'db> DebugWithDb<'db> for ImplLongId<'db> {
275 type Db = dyn Database;
276
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
278 match self {
279 ImplLongId::Concrete(concrete_impl_id) => {
280 write!(f, "{:?}", concrete_impl_id.debug(db))
281 }
282 ImplLongId::GenericParameter(param) => write!(f, "{}", param.debug_name(db).long(db)),
283 ImplLongId::ImplVar(var) => write!(f, "?{}", var.long(db).id.0),
284 ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
285 ImplLongId::SelfImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
286 ImplLongId::GeneratedImpl(generated_impl) => {
287 write!(f, "{:?}", generated_impl.debug(db))
288 }
289 }
290 }
291}
292
293define_short_id!(ImplId, ImplLongId<'db>);
294semantic_object_for_id!(ImplId, ImplLongId<'a>);
295impl<'db> ImplId<'db> {
296 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
297 db.impl_concrete_trait(*self)
298 }
299
300 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
302 impl_is_fully_concrete(db, *self)
303 }
304
305 pub fn is_var_free(&self, db: &dyn Database) -> bool {
307 impl_is_var_free(db, *self)
308 }
309
310 pub fn head(&self, db: &'db dyn Database) -> Option<ImplHead<'db>> {
312 self.long(db).head(db)
313 }
314
315 pub fn name(&self, db: &dyn Database) -> String {
317 self.long(db).name(db)
318 }
319
320 pub fn format(&self, db: &dyn Database) -> String {
321 self.long(db).format(db)
322 }
323}
324
325define_short_id!(GeneratedImplId, GeneratedImplLongId<'db>);
326semantic_object_for_id!(GeneratedImplId, GeneratedImplLongId<'a>);
327
328impl<'db> GeneratedImplId<'db> {
329 pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
330 self.long(db).concrete_trait
331 }
332
333 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
334 self.concrete_trait(db).trait_id(db)
335 }
336}
337
338#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
342pub struct GeneratedImplLongId<'db> {
343 pub concrete_trait: ConcreteTraitId<'db>,
344 pub generic_params: Vec<GenericParam<'db>>,
347 pub impl_items: GeneratedImplItems<'db>,
348}
349#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, SemanticObject)]
350pub struct GeneratedImplItems<'db>(pub OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>);
351
352pub enum GeneratedImplAssociatedTypes<'db> {
353 Unresolved,
355 Resolved(OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>),
357}
358
359impl<'db> DebugWithDb<'db> for GeneratedImplLongId<'db> {
360 type Db = dyn Database;
361
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
363 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
364 }
365}
366
367#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update)]
369pub struct ImplImplId<'db> {
370 impl_id: ImplId<'db>,
372 trait_impl_id: TraitImplId<'db>,
374}
375
376impl<'db> ImplImplId<'db> {
377 pub fn new(impl_id: ImplId<'db>, trait_impl_id: TraitImplId<'db>, db: &dyn Database) -> Self {
380 if let ImplLongId::Concrete(concrete_impl) = impl_id.long(db) {
381 let impl_def_id = concrete_impl.impl_def_id(db);
382 assert_eq!(Ok(trait_impl_id.trait_id(db)), db.impl_def_trait(impl_def_id));
383 }
384
385 ImplImplId { impl_id, trait_impl_id }
386 }
387 pub fn impl_id(&self) -> ImplId<'db> {
388 self.impl_id
389 }
390 pub fn trait_impl_id(&self) -> TraitImplId<'db> {
391 self.trait_impl_id
392 }
393
394 pub fn concrete_trait_impl_id(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitImplId<'db>> {
395 Ok(ConcreteTraitImplId::new_from_data(
396 db,
397 self.impl_id.concrete_trait(db)?,
398 self.trait_impl_id,
399 ))
400 }
401
402 pub fn full_path(&self, db: &dyn Database) -> String {
403 format!("{:?}", self.debug(db))
404 }
405}
406impl<'db> DebugWithDb<'db> for ImplImplId<'db> {
407 type Db = dyn Database;
408
409 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
410 write!(f, "{:?}::{}", self.impl_id.debug(db), self.trait_impl_id.name(db).long(db))
411 }
412}
413
414#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
417pub enum NegativeImplLongId<'db> {
418 Solved(ConcreteTraitId<'db>),
419 GenericParameter(GenericParamId<'db>),
420 NegativeImplVar(NegativeImplVarId<'db>),
421}
422
423impl<'db> NegativeImplLongId<'db> {
424 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
425 match self {
426 NegativeImplLongId::Solved(concrete_trait_id) => Ok(*concrete_trait_id),
427 NegativeImplLongId::GenericParameter(param) => {
428 let param_impl =
429 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::NegImpl);
430 param_impl.concrete_trait
431 }
432 NegativeImplLongId::NegativeImplVar(negative_impl_var_id) => {
433 Ok(negative_impl_var_id.long(db).concrete_trait_id)
434 }
435 }
436 }
437 pub fn is_var_free(&self, db: &dyn Database) -> bool {
438 match self {
439 NegativeImplLongId::Solved(concrete_trait_id) => concrete_trait_id.is_var_free(db),
440 NegativeImplLongId::GenericParameter(_) => true,
441 NegativeImplLongId::NegativeImplVar(_) => false,
442 }
443 }
444 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
445 match self {
446 NegativeImplLongId::Solved(concrete_trait_id) => concrete_trait_id.is_var_free(db),
447 NegativeImplLongId::GenericParameter(_) | NegativeImplLongId::NegativeImplVar(_) => {
448 false
449 }
450 }
451 }
452}
453
454define_short_id!(NegativeImplId, NegativeImplLongId<'db>);
455impl<'db> NegativeImplId<'db> {
456 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
457 self.long(db).concrete_trait(db)
458 }
459 pub fn is_var_free(&self, db: &dyn Database) -> bool {
460 self.long(db).is_var_free(db)
461 }
462 pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
463 self.long(db).is_fully_concrete(db)
464 }
465}
466semantic_object_for_id!(NegativeImplId, NegativeImplLongId<'a>);
467
468impl<'db> UnstableSalsaId for ImplId<'db> {
469 fn get_internal_id(&self) -> salsa::Id {
470 self.as_intern_id()
471 }
472}
473
474#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
480pub enum ImplHead<'db> {
481 Concrete(ImplDefId<'db>),
482}
483
484#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
487#[debug_db(dyn Database)]
488struct ImplDeclarationData<'db> {
489 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
490 concrete_trait: Maybe<ConcreteTraitId<'db>>,
492 attributes: Vec<Attribute<'db>>,
493 resolver_data: Arc<ResolverData<'db>>,
494}
495
496#[salsa::tracked(returns(ref))]
498fn impl_def_generic_params_data<'db>(
499 db: &'db dyn Database,
500 impl_def_id: ImplDefId<'db>,
501) -> Maybe<GenericParamsData<'db>> {
502 let module_id = impl_def_id.module_id(db);
503 let mut diagnostics = SemanticDiagnostics::default();
504
505 let impl_ast = db.module_impl_by_id(impl_def_id)?;
506 let inference_id =
507 InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
508
509 let mut resolver = Resolver::new(db, module_id, inference_id);
510 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
511 let generic_params = semantic_generic_params(
512 db,
513 &mut diagnostics,
514 &mut resolver,
515 module_id,
516 &impl_ast.generic_params(db),
517 );
518 let inference = &mut resolver.inference();
519 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
520 let generic_params = inference.rewrite(generic_params).no_err();
521 let resolver_data = Arc::new(resolver.data);
522 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
523}
524
525#[salsa::tracked(returns(ref))]
527fn impl_def_substitution<'db>(
528 db: &'db dyn Database,
529 impl_def_id: ImplDefId<'db>,
530) -> Maybe<GenericSubstitution<'db>> {
531 let params = db.impl_def_generic_params(impl_def_id)?;
532 let generic_args = generic_params_to_args(params, db);
533 ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)
534}
535
536#[salsa::tracked]
538fn impl_def_trait<'db>(db: &'db dyn Database, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
539 let module_id = impl_def_id.module_id(db);
540 let mut diagnostics = SemanticDiagnostics::default();
541
542 let impl_ast = db.module_impl_by_id(impl_def_id)?;
543 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
544
545 let mut resolver = Resolver::new(db, module_id, inference_id);
546 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
547
548 let trait_path_syntax = impl_ast.trait_path(db);
549
550 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path_syntax)
551}
552
553fn impl_def_shallow_trait_generic_args<'db>(
555 db: &'db dyn Database,
556 impl_def_id: ImplDefId<'db>,
557) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
558 Ok(impl_def_shallow_trait_generic_args_helper(db, impl_def_id).maybe_as_ref()?)
559}
560
561#[salsa::tracked(returns(ref))]
564fn impl_def_shallow_trait_generic_args_helper<'db>(
565 db: &'db dyn Database,
566 impl_def_id: ImplDefId<'db>,
567) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
568 let module_id = impl_def_id.module_id(db);
569 let mut diagnostics = SemanticDiagnostics::default();
570
571 let impl_ast = db.module_impl_by_id(impl_def_id)?;
572 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
573
574 let mut resolver = Resolver::new(db, module_id, inference_id);
575 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
576
577 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
578 impl_ast.generic_params(db)
579 {
580 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
581 let generic_param_id =
582 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
583 resolver.add_generic_param(generic_param_id);
584 })
585 }
586 let trait_path_syntax = impl_ast.trait_path(db);
587
588 let ResolvedGenericItem::Trait(trait_id) = resolver.resolve_generic_path_with_args(
589 &mut diagnostics,
590 &trait_path_syntax,
591 NotFoundItemType::Trait,
592 ResolutionContext::Default,
593 )?
594 else {
595 return Err(skip_diagnostic());
596 };
597 let generic_params = db
598 .trait_generic_params_ids(trait_id)?
599 .iter()
600 .map(|param_syntax| {
601 GenericParamLongId(trait_id.module_id(db), param_syntax.stable_ptr(db)).intern(db)
602 })
603 .collect::<Vec<_>>();
604
605 let elements = trait_path_syntax.segments(db).elements(db);
606 let Some(last) = elements.last() else {
607 return Ok(Vec::new());
608 };
609 match last {
610 ast::PathSegment::Simple(_) => Ok(Vec::new()),
611 ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
612 let generic_args =
613 path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
614
615 let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
616 &mut diagnostics,
617 &generic_params,
618 &generic_args,
619 )?;
620 Ok(generic_params
621 .iter()
622 .filter_map(|generic_param| {
623 let value = arg_syntax_per_param.get(generic_param)?;
624 let GenericArgValue::Expr(expr) = value else {
625 return None;
626 };
627 let arg_ty = maybe_resolve_shallow_generic_arg_type(
628 db,
629 &mut diagnostics,
630 &mut resolver,
631 &expr.expr(db),
632 )?;
633 Some((*generic_param, arg_ty))
634 })
635 .collect::<Vec<_>>())
636 }
637 ast::PathSegment::Missing(_) => Ok(Vec::new()),
638 }
639}
640
641fn impl_alias_trait_generic_args<'db>(
643 db: &'db dyn Database,
644 impl_alias_id: ImplAliasId<'db>,
645) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
646 Ok(impl_alias_trait_generic_args_helper(db, impl_alias_id).maybe_as_ref()?)
647}
648
649#[salsa::tracked(returns(ref))]
650fn impl_alias_trait_generic_args_helper<'db>(
651 db: &'db dyn Database,
652 impl_alias_id: ImplAliasId<'db>,
653) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
654 let module_id = impl_alias_id.module_id(db);
655 let mut diagnostics = SemanticDiagnostics::default();
656
657 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?;
658 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
659
660 let mut resolver = Resolver::new(db, module_id, inference_id);
661 resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
662
663 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
664 impl_alias_ast.generic_params(db)
665 {
666 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
667 let generic_param_id =
668 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
669 resolver.add_generic_param(generic_param_id);
670 })
671 }
672 let rhs_syntax = impl_alias_ast.impl_path(db);
673 let (shallow_args, rhs_generic_params) = match resolver.resolve_generic_path_with_args(
674 &mut diagnostics,
675 &rhs_syntax,
676 NotFoundItemType::Impl,
677 ResolutionContext::Default,
678 ) {
679 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
680 let shallow_args = db.impl_def_shallow_trait_generic_args(impl_def_id)?.to_vec();
681 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
682 db.module_impl_by_id(impl_def_id)?.generic_params(db)
683 else {
684 return Ok(shallow_args);
685 };
686 (
687 shallow_args,
688 params
689 .generic_params(db)
690 .elements(db)
691 .map(|param_syntax| {
692 GenericParamLongId(impl_def_id.module_id(db), param_syntax.stable_ptr(db))
693 .intern(db)
694 })
695 .collect::<Vec<_>>(),
696 )
697 }
698 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => {
699 let shallow_args = db.impl_alias_trait_generic_args(impl_alias)?.to_vec();
700 let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
701 db.module_impl_alias_by_id(impl_alias)?.generic_params(db)
702 else {
703 return Ok(shallow_args);
704 };
705 (
706 shallow_args,
707 params
708 .generic_params(db)
709 .elements(db)
710 .map(|param_syntax| {
711 GenericParamLongId(impl_alias.module_id(db), param_syntax.stable_ptr(db))
712 .intern(db)
713 })
714 .collect::<Vec<_>>(),
715 )
716 }
717 _ => return Ok(Vec::new()),
718 };
719
720 let elements = rhs_syntax.segments(db).elements(db);
721 let Some(last) = elements.last() else {
722 return Ok(Vec::new());
723 };
724
725 match last {
726 ast::PathSegment::Simple(_) => Ok(shallow_args),
727 ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
728 let generic_args =
729 path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
730 let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
731 &mut diagnostics,
732 &rhs_generic_params,
733 &generic_args,
734 )?;
735
736 Ok(shallow_args
737 .iter()
738 .filter_map(|(trait_param, arg)| {
739 let ShallowGenericArg::GenericParameter(arg) = arg else {
740 return Some((*trait_param, arg.clone()));
741 };
742
743 arg_syntax_per_param.get(arg).and_then(|syntax| {
744 let GenericArgValue::Expr(expr) = syntax else {
745 return None;
746 };
747 let arg_ty = maybe_resolve_shallow_generic_arg_type(
748 db,
749 &mut diagnostics,
750 &mut resolver,
751 &expr.expr(db),
752 )?;
753 Some((*trait_param, arg_ty))
754 })
755 })
756 .collect::<Vec<_>>())
757 }
758 ast::PathSegment::Missing(_) => Ok(shallow_args),
759 }
760}
761
762fn impl_concrete_trait<'db>(
764 db: &'db dyn Database,
765 impl_id: ImplId<'db>,
766) -> Maybe<ConcreteTraitId<'db>> {
767 match impl_id.long(db) {
768 ImplLongId::Concrete(concrete_impl_id) => {
769 let long_impl = concrete_impl_id.long(db);
770 let substitution = GenericSubstitution::new(
771 db.impl_def_generic_params(long_impl.impl_def_id)?,
772 &long_impl.generic_args,
773 );
774
775 let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
776 substitution.substitute(db, impl_concrete_trait_id)
777 }
778 ImplLongId::GenericParameter(param) => {
779 let param_impl =
780 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
781 param_impl.concrete_trait
782 }
783 ImplLongId::ImplVar(var) => Ok(var.long(db).concrete_trait_id),
784 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl),
785 ImplLongId::SelfImpl(concrete_trait_id) => Ok(*concrete_trait_id),
786 ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
787 }
788}
789
790#[salsa::tracked]
792fn impl_concrete_trait_tracked<'db>(
793 db: &'db dyn Database,
794 impl_id: ImplId<'db>,
795) -> Maybe<ConcreteTraitId<'db>> {
796 impl_concrete_trait(db, impl_id)
797}
798
799fn impl_declaration_data_cycle<'db>(
803 db: &'db dyn Database,
804 impl_def_id: ImplDefId<'db>,
805) -> Maybe<ImplDeclarationData<'db>> {
806 impl_declaration_data_inner(db, impl_def_id, false)
807}
808
809#[salsa::tracked(cycle_result=impl_declaration_data_cycle, returns(ref))]
811fn impl_declaration_data<'db>(
812 db: &'db dyn Database,
813 impl_def_id: ImplDefId<'db>,
814) -> Maybe<ImplDeclarationData<'db>> {
815 impl_declaration_data_inner(db, impl_def_id, true)
816}
817
818fn impl_declaration_data_inner<'db>(
821 db: &'db dyn Database,
822 impl_def_id: ImplDefId<'db>,
823 resolve_trait: bool,
824) -> Maybe<ImplDeclarationData<'db>> {
825 let mut diagnostics = SemanticDiagnostics::default();
826
827 let impl_ast = db.module_impl_by_id(impl_def_id)?;
831 let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
832 ModuleItemId::Impl(impl_def_id),
833 ));
834
835 let generic_params_data = impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?;
837 let mut resolver = Resolver::with_data(
838 db,
839 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
840 );
841 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
842 diagnostics.extend(generic_params_data.diagnostics.clone());
843 let trait_path_syntax = impl_ast.trait_path(db);
844
845 let concrete_trait = if resolve_trait {
846 resolver
847 .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
848 .and_then(|resolved_item| match resolved_item {
849 ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
850 _ => Err(diagnostics
851 .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
852 })
853 } else {
854 Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
855 };
856
857 let info = db.core_info();
858
859 if let Ok(concrete_trait) = concrete_trait
861 && [
862 info.type_eq_trt,
863 info.fn_trt,
864 info.fn_once_trt,
865 info.felt252_dict_value_trt,
866 info.numeric_literal_trt,
867 info.string_literal_trt,
868 ]
869 .contains(&concrete_trait.trait_id(db))
870 && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
871 {
872 diagnostics.report(
873 trait_path_syntax.stable_ptr(db),
874 CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
875 );
876 }
877
878 let inference = &mut resolver.inference();
880 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
881
882 let concrete_trait: Result<ConcreteTraitId<'_>, DiagnosticAdded> =
883 inference.rewrite(concrete_trait).no_err();
884
885 let attributes = impl_ast.attributes(db).structurize(db);
886 let mut resolver_data = resolver.data;
887 resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
888 Ok(ImplDeclarationData {
889 diagnostics: diagnostics.build(),
890 concrete_trait,
891 attributes,
892 resolver_data: Arc::new(resolver_data),
893 })
894}
895
896#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
899#[debug_db(dyn Database)]
900struct ImplDefinitionData<'db> {
901 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
906
907 function_asts: OrderedHashMap<ImplFunctionId<'db>, ast::FunctionWithBody<'db>>,
909 item_type_asts: OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>,
910 item_constant_asts: OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>,
911 item_impl_asts: OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>,
912
913 item_id_by_name: OrderedHashMap<SmolStrId<'db>, ImplItemInfo<'db>>,
916
917 implicit_impls_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>,
919}
920
921impl<'db> ImplDefinitionData<'db> {
922 pub fn get_impl_item_info(&self, item_name: SmolStrId<'db>) -> Option<ImplItemInfo<'db>> {
924 self.item_id_by_name.get(&item_name).cloned()
925 }
926}
927#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
929pub struct ImplItemInfo<'db> {
930 pub id: ImplItemId<'db>,
932 pub feature_kind: FeatureKind<'db>,
934}
935
936impl<'db> HasFeatureKind<'db> for ImplItemInfo<'db> {
937 fn feature_kind(&self) -> &FeatureKind<'db> {
939 &self.feature_kind
940 }
941}
942
943fn impl_semantic_definition_diagnostics<'db>(
947 db: &'db dyn Database,
948 impl_def_id: ImplDefId<'db>,
949) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
950 let mut diagnostics = DiagnosticsBuilder::default();
951
952 let Ok(data) = impl_definition_data(db, impl_def_id) else {
953 return Diagnostics::default();
954 };
955
956 diagnostics.extend(data.diagnostics.clone());
959 for impl_function_id in data.function_asts.keys() {
960 diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
961 diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
962 }
963 for impl_item_type_id in data.item_type_asts.keys() {
964 diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
965 if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
966 add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
967 }
968 }
969 for impl_item_constant_id in data.item_constant_asts.keys() {
970 diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
971 }
972 for impl_item_impl_id in data.item_impl_asts.keys() {
973 diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
974 }
975 for implicit_impl_id in data.implicit_impls_id_by_name.values() {
976 diagnostics
977 .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
978 }
979 if diagnostics.error_count == 0 {
981 let concrete_trait =
982 impl_declaration_data(db, impl_def_id).as_ref().unwrap().concrete_trait.unwrap();
983
984 let trait_id = concrete_trait.trait_id(db);
985 if trait_id == db.core_info().deref_trt {
986 deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
987 }
988 }
989 diagnostics.build()
990}
991
992#[salsa::tracked]
994fn impl_semantic_definition_diagnostics_tracked<'db>(
995 db: &'db dyn Database,
996 impl_def_id: ImplDefId<'db>,
997) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
998 impl_semantic_definition_diagnostics(db, impl_def_id)
999}
1000
1001#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
1003pub struct DerefChain<'db> {
1004 pub derefs: Arc<Vec<DerefInfo<'db>>>,
1005}
1006
1007#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
1009pub struct DerefInfo<'db> {
1010 pub function_id: FunctionId<'db>,
1012 pub self_mutability: Mutability,
1014 pub target_ty: TypeId<'db>,
1016}
1017
1018fn deref_chain_cycle<'db>(
1020 _db: &dyn Database,
1021 _ty: TypeId<'db>,
1022 _crate_id: CrateId<'db>,
1023 _try_deref_mut: bool,
1024) -> Maybe<DerefChain<'db>> {
1025 Maybe::Err(skip_diagnostic())
1027}
1028
1029#[salsa::tracked(cycle_result=deref_chain_cycle, returns(ref))]
1031fn deref_chain<'db>(
1032 db: &'db dyn Database,
1033 ty: TypeId<'db>,
1034 crate_id: CrateId<'db>,
1035 try_deref_mut: bool,
1036) -> Maybe<DerefChain<'db>> {
1037 let mut opt_deref = None;
1038 if try_deref_mut {
1039 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, true)?;
1040 }
1041 let self_mutability = if opt_deref.is_some() {
1042 Mutability::Reference
1043 } else {
1044 opt_deref = try_get_deref_func_and_target(db, ty, crate_id, false)?;
1045 Mutability::Immutable
1046 };
1047
1048 let Some((function_id, target_ty)) = opt_deref else {
1049 return Ok(DerefChain { derefs: Arc::new(vec![]) });
1050 };
1051
1052 let inner_chain = db.deref_chain(target_ty, crate_id, false)?;
1053
1054 Ok(DerefChain {
1055 derefs: Arc::new(
1056 chain!(
1057 [DerefInfo { function_id, target_ty, self_mutability }],
1058 inner_chain.derefs.iter().cloned()
1059 )
1060 .collect(),
1061 ),
1062 })
1063}
1064
1065fn try_get_deref_func_and_target<'db>(
1067 db: &'db dyn Database,
1068 ty: TypeId<'db>,
1069 crate_id: CrateId<'db>,
1070 is_mut_deref: bool,
1071) -> Result<Option<(FunctionId<'db>, TypeId<'db>)>, DiagnosticAdded> {
1072 let info = db.core_info();
1073 let (deref_trait_id, deref_method) = if is_mut_deref {
1074 (info.deref_mut_trt, info.deref_mut_fn)
1075 } else {
1076 (info.deref_trt, info.deref_fn)
1077 };
1078
1079 let mut lookup_context = ImplLookupContext::new_from_crate(crate_id);
1080 enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
1081 let concrete_trait = ConcreteTraitLongId {
1082 trait_id: deref_trait_id,
1083 generic_args: vec![GenericArgumentId::Type(ty)],
1084 }
1085 .intern(db);
1086 let Ok(deref_impl) = get_impl_at_context(db, lookup_context.intern(db), concrete_trait, None)
1087 else {
1088 return Ok(None);
1089 };
1090 let concrete_impl_id: ConcreteImplId<'db> = match deref_impl.long(db) {
1091 ImplLongId::Concrete(concrete_impl_id) => *concrete_impl_id,
1092 _ => panic!("Expected concrete impl"),
1093 };
1094
1095 let function_id: FunctionId<'db> = FunctionLongId {
1096 function: ConcreteFunction {
1097 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
1098 impl_id: deref_impl,
1099 function: deref_method,
1100 }),
1101 generic_args: vec![],
1102 },
1103 }
1104 .intern(db);
1105
1106 let data = impl_definition_data(db, concrete_impl_id.impl_def_id(db)).clone().unwrap();
1107 let mut types_iter = data.item_type_asts.iter();
1108 let (impl_item_type_id, _) = types_iter.next().unwrap();
1109 if types_iter.next().is_some() {
1110 panic!(
1111 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1112 );
1113 }
1114 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1115 let substitution: GenericSubstitution<'db> = concrete_impl_id.substitution(db)?;
1116 let ty: TypeId<'db> = substitution.substitute(db, ty).unwrap();
1117
1118 Ok(Some((function_id, ty)))
1119}
1120
1121fn deref_impl_diagnostics<'db>(
1123 db: &'db dyn Database,
1124 mut impl_def_id: ImplDefId<'db>,
1125 concrete_trait: ConcreteTraitId<'db>,
1126 diagnostics: &mut DiagnosticsBuilder<'db, SemanticDiagnostic<'db>>,
1127) {
1128 let mut visited_impls: OrderedHashSet<ImplDefId<'_>> = OrderedHashSet::default();
1129 let deref_trait_id = concrete_trait.trait_id(db);
1130
1131 let impl_module = impl_def_id.parent_module(db);
1132
1133 let mut impl_in_valid_location = false;
1134 if impl_module == deref_trait_id.parent_module(db) {
1135 impl_in_valid_location = true;
1136 }
1137
1138 let gargs = concrete_trait.generic_args(db);
1139 let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
1140 if let Some(module_id) = deref_ty.long(db).module_id(db)
1141 && module_id == impl_module
1142 {
1143 impl_in_valid_location = true;
1144 }
1145
1146 if !impl_in_valid_location {
1147 diagnostics.report(
1148 impl_def_id.stable_ptr(db),
1149 SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
1150 );
1151 return;
1152 }
1153
1154 loop {
1155 let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
1156 ConcreteTraitLongId {
1157 trait_id: deref_trait_id,
1158 generic_args: vec![GenericArgumentId::Type(ty)],
1159 }
1160 .intern(db)
1161 }) else {
1162 return;
1165 };
1166
1167 impl_def_id = match impl_id.long(db) {
1168 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
1169 _ => return,
1170 };
1171
1172 if !visited_impls.insert(impl_def_id) {
1173 let deref_chain = visited_impls
1174 .iter()
1175 .map(|visited_impl| {
1176 format!("{:?}", db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db))
1177 })
1178 .join(" -> ");
1179 diagnostics.report(
1180 impl_def_id.stable_ptr(db),
1181 SemanticDiagnosticKind::DerefCycle { deref_chain },
1182 );
1183 return;
1184 }
1185 }
1186}
1187
1188fn get_impl_based_on_single_impl_type<'db>(
1192 db: &'db dyn Database,
1193 impl_def_id: ImplDefId<'db>,
1194 concrete_trait_id: impl FnOnce(TypeId<'db>) -> ConcreteTraitId<'db>,
1195) -> Result<ImplId<'db>, (InferenceError<'db>, ImplTypeDefId<'db>)> {
1196 let data = impl_definition_data(db, impl_def_id).clone().unwrap();
1197 let mut types_iter = data.item_type_asts.iter();
1198 let (impl_item_type_id, _) = types_iter.next().unwrap();
1199 if types_iter.next().is_some() {
1200 panic!(
1201 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1202 );
1203 }
1204 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1205
1206 let module_id = impl_def_id.module_id(db);
1207 let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
1208 let generic_params_ids =
1209 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1210 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db);
1211 get_impl_at_context(db, lookup_context.intern(db), concrete_trait_id(ty), None)
1212 .map_err(|err| (err, *impl_item_type_id))
1213}
1214
1215#[salsa::tracked(returns(ref))]
1217fn impl_functions<'db>(
1218 db: &'db dyn Database,
1219 impl_def_id: ImplDefId<'db>,
1220) -> Maybe<OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
1221 Ok(impl_definition_data(db, impl_def_id)
1222 .maybe_as_ref()?
1223 .function_asts
1224 .keys()
1225 .map(|function_id| {
1226 let function_long_id = function_id.long(db);
1227 (function_long_id.name(db), *function_id)
1228 })
1229 .collect())
1230}
1231
1232#[salsa::tracked]
1234fn impl_function_by_trait_function<'db>(
1235 db: &'db dyn Database,
1236 impl_def_id: ImplDefId<'db>,
1237 trait_function_id: TraitFunctionId<'db>,
1238) -> Maybe<Option<ImplFunctionId<'db>>> {
1239 let name = trait_function_id.name(db);
1240 for impl_function_id in
1241 impl_definition_data(db, impl_def_id).maybe_as_ref()?.function_asts.keys()
1242 {
1243 if impl_function_id.long(db).name(db) == name {
1244 return Ok(Some(*impl_function_id));
1245 }
1246 }
1247 Ok(None)
1248}
1249
1250fn impl_item_info_by_name<'db>(
1252 db: &'db dyn Database,
1253 impl_def_id: ImplDefId<'db>,
1254 name: SmolStrId<'db>,
1255) -> Maybe<Option<ImplItemInfo<'db>>> {
1256 let impl_definition_data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1257 Ok(impl_definition_data.get_impl_item_info(name))
1258}
1259
1260#[salsa::tracked]
1262fn impl_item_info_by_name_tracked<'db>(
1263 db: &'db dyn Database,
1264 impl_def_id: ImplDefId<'db>,
1265 name: SmolStrId<'db>,
1266) -> Maybe<Option<ImplItemInfo<'db>>> {
1267 impl_item_info_by_name(db, impl_def_id, name)
1268}
1269
1270#[salsa::tracked(returns(ref))]
1272fn impl_all_used_uses<'db>(
1273 db: &'db dyn Database,
1274 impl_def_id: ImplDefId<'db>,
1275) -> Maybe<OrderedHashSet<UseId<'db>>> {
1276 let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1277 let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1278 for item in data.item_id_by_name.values() {
1279 for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1280 all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1281 }
1282 }
1283 Ok(all_used_uses)
1284}
1285
1286#[salsa::tracked]
1288fn impl_type_by_id<'db>(
1289 db: &'db dyn Database,
1290 impl_type_id: ImplTypeDefId<'db>,
1291) -> Maybe<ast::ItemTypeAlias<'db>> {
1292 let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1293 impl_types.get(&impl_type_id).cloned().ok_or_else(skip_diagnostic)
1294}
1295
1296fn impl_type_by_trait_type<'db>(
1298 db: &'db dyn Database,
1299 impl_def_id: ImplDefId<'db>,
1300 trait_type_id: TraitTypeId<'db>,
1301) -> Maybe<ImplTypeDefId<'db>> {
1302 if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1303 unreachable!(
1304 "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1305 trait"
1306 )
1307 }
1308
1309 let name = trait_type_id.name(db);
1310 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1312 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
1313 None => Err(skip_diagnostic()),
1314 })
1315}
1316
1317#[salsa::tracked]
1319fn impl_type_by_trait_type_tracked<'db>(
1320 db: &'db dyn Database,
1321 impl_def_id: ImplDefId<'db>,
1322 trait_type_id: TraitTypeId<'db>,
1323) -> Maybe<ImplTypeDefId<'db>> {
1324 impl_type_by_trait_type(db, impl_def_id, trait_type_id)
1325}
1326
1327#[salsa::tracked]
1329fn impl_constant_by_trait_constant<'db>(
1330 db: &'db dyn Database,
1331 impl_def_id: ImplDefId<'db>,
1332 trait_constant_id: TraitConstantId<'db>,
1333) -> Maybe<ImplConstantDefId<'db>> {
1334 if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1335 unreachable!(
1336 "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1337 the impl's trait"
1338 )
1339 }
1340
1341 let name = trait_constant_id.name(db);
1342 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1344 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
1345 None => Err(skip_diagnostic()),
1346 })
1347}
1348
1349#[salsa::tracked]
1351fn impl_impl_by_id<'db>(
1352 db: &'db dyn Database,
1353 impl_impl_id: ImplImplDefId<'db>,
1354) -> Maybe<ast::ItemImplAlias<'db>> {
1355 let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1356 impl_impls.get(&impl_impl_id).cloned().ok_or_else(skip_diagnostic)
1357}
1358
1359#[salsa::tracked]
1361fn impl_impl_by_trait_impl<'db>(
1362 db: &'db dyn Database,
1363 impl_def_id: ImplDefId<'db>,
1364 trait_impl_id: TraitImplId<'db>,
1365) -> Maybe<ImplImplDefId<'db>> {
1366 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1367 unreachable!(
1368 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1369 trait"
1370 )
1371 }
1372
1373 let name = trait_impl_id.name(db);
1374 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1376 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1377 None => Err(skip_diagnostic()),
1378 })
1379}
1380
1381#[salsa::tracked]
1383fn is_implicit_impl_impl<'db>(
1384 db: &'db dyn Database,
1385 impl_def_id: ImplDefId<'db>,
1386 trait_impl_id: TraitImplId<'db>,
1387) -> Maybe<bool> {
1388 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1389 unreachable!(
1390 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1391 trait"
1392 )
1393 }
1394
1395 let name = trait_impl_id.name(db);
1396 Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1398}
1399
1400#[salsa::tracked(returns(ref))]
1404fn impl_definition_data<'db>(
1405 db: &'db dyn Database,
1406 impl_def_id: ImplDefId<'db>,
1407) -> Maybe<ImplDefinitionData<'db>> {
1408 let module_id = impl_def_id.module_id(db);
1409 let mut diagnostics = SemanticDiagnostics::default();
1410
1411 let generic_params =
1412 impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?.generic_params.clone();
1413 let concrete_trait = impl_declaration_data(db, impl_def_id).maybe_as_ref()?.concrete_trait?;
1414
1415 let impl_ast = db.module_impl_by_id(impl_def_id)?;
1416
1417 let generic_params_ids =
1418 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1419 let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db).intern(db);
1420 check_special_impls(
1421 db,
1422 &mut diagnostics,
1423 lookup_context,
1424 concrete_trait,
1425 impl_ast.stable_ptr(db).untyped(),
1426 )
1427 .ok();
1429
1430 let mut function_asts = OrderedHashMap::default();
1431 let mut item_type_asts = OrderedHashMap::default();
1432 let mut item_constant_asts = OrderedHashMap::default();
1433 let mut item_impl_asts = OrderedHashMap::default();
1434 let mut item_id_by_name = OrderedHashMap::default();
1435
1436 if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1437 for item in body.items(db).elements(db) {
1438 match item {
1439 ImplItem::Module(module) => {
1440 report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1441 }
1442
1443 ImplItem::Use(use_item) => {
1444 report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1445 }
1446 ImplItem::ExternFunction(extern_func) => {
1447 report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1448 }
1449 ImplItem::ExternType(extern_type) => {
1450 report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1451 }
1452 ImplItem::Trait(trt) => {
1453 report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1454 }
1455 ImplItem::Struct(structure) => {
1456 report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1457 }
1458 ImplItem::Enum(enm) => {
1459 report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1460 }
1461 ImplItem::Function(func) => {
1462 let impl_function_id =
1463 ImplFunctionLongId(module_id, func.stable_ptr(db)).intern(db);
1464 let name_node = func.declaration(db).name(db);
1465 let name = name_node.text(db);
1466 let feature_kind =
1467 FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1468 if item_id_by_name
1469 .insert(
1470 name,
1471 ImplItemInfo {
1472 id: ImplItemId::Function(impl_function_id),
1473 feature_kind,
1474 },
1475 )
1476 .is_some()
1477 {
1478 diagnostics
1479 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1480 }
1481 function_asts.insert(impl_function_id, func);
1482 }
1483 ImplItem::Type(ty) => {
1484 let impl_type_id = ImplTypeDefLongId(module_id, ty.stable_ptr(db)).intern(db);
1485 let name_node = ty.name(db);
1486 let name = name_node.text(db);
1487 let feature_kind =
1488 FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1489 if item_id_by_name
1490 .insert(
1491 name,
1492 ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1493 )
1494 .is_some()
1495 {
1496 diagnostics
1497 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1498 }
1499 item_type_asts.insert(impl_type_id, ty);
1500 }
1501 ImplItem::Constant(constant) => {
1502 let impl_constant_id =
1503 ImplConstantDefLongId(module_id, constant.stable_ptr(db)).intern(db);
1504 let name_node = constant.name(db);
1505 let name = name_node.text(db);
1506 let feature_kind =
1507 FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1508 if item_id_by_name
1509 .insert(
1510 name,
1511 ImplItemInfo {
1512 id: ImplItemId::Constant(impl_constant_id),
1513 feature_kind,
1514 },
1515 )
1516 .is_some()
1517 {
1518 diagnostics.report(
1519 name_node.stable_ptr(db),
1520 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1521 );
1522 }
1523 item_constant_asts.insert(impl_constant_id, constant);
1524 }
1525 ImplItem::Impl(imp) => {
1526 let impl_impl_id = ImplImplDefLongId(module_id, imp.stable_ptr(db)).intern(db);
1527 let name_node = imp.name(db);
1528 let name = name_node.text(db);
1529 let feature_kind =
1530 FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1531 if item_id_by_name
1532 .insert(
1533 name,
1534 ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1535 )
1536 .is_some()
1537 {
1538 diagnostics.report(
1539 name_node.stable_ptr(db),
1540 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1541 );
1542 }
1543 item_impl_asts.insert(impl_impl_id, imp);
1544 }
1545 ImplItem::Missing(_) => {}
1547 }
1548 }
1549 }
1550
1551 let mut implicit_impls_id_by_name = OrderedHashMap::default();
1552
1553 let trait_id = concrete_trait.long(db).trait_id;
1554 for (name, trait_impl_id) in db.trait_impls(trait_id)?.iter() {
1555 if item_id_by_name.contains_key(name) {
1556 continue;
1557 }
1558 implicit_impls_id_by_name.insert(*name, *trait_impl_id);
1559 }
1560
1561 let impl_item_names: OrderedHashSet<SmolStrId<'db>> = item_id_by_name.keys().copied().collect();
1565
1566 let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1567 let missing_items_in_impl =
1568 trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1569 if !missing_items_in_impl.is_empty() {
1570 diagnostics.report(
1571 impl_ast.name(db).stable_ptr(db),
1576 SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1577 );
1578 }
1579
1580 Ok(ImplDefinitionData {
1581 diagnostics: diagnostics.build(),
1582 function_asts,
1583 item_type_asts,
1584 item_id_by_name,
1585 item_constant_asts,
1586 item_impl_asts,
1587 implicit_impls_id_by_name,
1588 })
1589}
1590
1591fn report_invalid_impl_item<'db, Terminal: syntax::node::Terminal<'db>>(
1594 db: &'db dyn Database,
1595 diagnostics: &mut SemanticDiagnostics<'db>,
1596 kw_terminal: Terminal,
1597) {
1598 diagnostics
1599 .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1600}
1601
1602fn check_special_impls<'db>(
1604 db: &'db dyn Database,
1605 diagnostics: &mut SemanticDiagnostics<'db>,
1606 lookup_context: ImplLookupContextId<'db>,
1607 concrete_trait: ConcreteTraitId<'db>,
1608 stable_ptr: SyntaxStablePtrId<'db>,
1609) -> Maybe<()> {
1610 let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.long(db);
1611 let info = db.core_info();
1612 let copy = info.copy_trt;
1613 let drop = info.drop_trt;
1614
1615 if *trait_id == copy {
1616 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1617 for inference_error in tys
1618 .into_iter()
1619 .map(|ty| db.type_info(lookup_context, ty))
1620 .flat_map(|info| info.copyable.err())
1621 {
1622 if matches!(
1623 inference_error,
1624 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1625 ) {
1626 continue;
1628 }
1629 return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1630 }
1631 }
1632 if *trait_id == drop {
1633 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1634 for inference_error in tys
1635 .into_iter()
1636 .map(|ty| db.type_info(lookup_context, ty))
1637 .flat_map(|info| info.droppable.err())
1638 {
1639 if matches!(
1640 inference_error,
1641 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1642 ) {
1643 continue;
1645 }
1646 return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1647 }
1648 }
1649
1650 Ok(())
1651}
1652
1653fn get_inner_types<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> Maybe<Vec<TypeId<'db>>> {
1660 Ok(match ty.long(db) {
1661 TypeLongId::Concrete(concrete_type_id) => {
1662 match concrete_type_id {
1664 crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1665 .concrete_struct_members(*concrete_struct_id)?
1666 .values()
1667 .map(|member| member.ty)
1668 .collect(),
1669 crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1670 .concrete_enum_variants(*concrete_enum_id)?
1671 .into_iter()
1672 .map(|variant| variant.ty)
1673 .collect(),
1674 crate::ConcreteTypeId::Extern(_) => vec![],
1675 }
1676 }
1677 TypeLongId::Tuple(tys) => tys.to_vec(),
1678 TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1679 TypeLongId::GenericParameter(_) => {
1680 return Err(skip_diagnostic());
1681 }
1682 TypeLongId::Var(_) | TypeLongId::ImplType(_) => {
1683 panic!("Types should be fully resolved at this point.")
1684 }
1685 TypeLongId::Coupon(_) => vec![],
1686 TypeLongId::FixedSizeArray { type_id, .. } => vec![*type_id],
1687 TypeLongId::Missing(diag_added) => {
1688 return Err(*diag_added);
1689 }
1690 })
1691}
1692
1693#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1698pub struct TraitFilter<'db> {
1699 pub trait_id: TraitId<'db>,
1700 pub generics_filter: GenericsHeadFilter<'db>,
1702}
1703
1704#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
1707pub enum GenericsHeadFilter<'db> {
1708 NoFilter,
1711 FirstGenericFilter(GenericArgumentHead<'db>),
1714 NoGenerics,
1716}
1717
1718#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
1719pub struct UninferredImplById<'db>(pub UninferredImpl<'db>);
1720impl<'db> Ord for UninferredImplById<'db> {
1721 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1722 match (&self.0, &other.0) {
1723 (UninferredImpl::Def(impl_def_id), UninferredImpl::Def(other_impl_def_id)) => {
1724 impl_def_id.get_internal_id().cmp(&other_impl_def_id.get_internal_id())
1725 }
1726 (
1727 UninferredImpl::ImplAlias(impl_alias_id),
1728 UninferredImpl::ImplAlias(other_impl_alias_id),
1729 ) => impl_alias_id.get_internal_id().cmp(&other_impl_alias_id.get_internal_id()),
1730 (UninferredImpl::GenericParam(param), UninferredImpl::GenericParam(other_param)) => {
1731 param.get_internal_id().cmp(&other_param.get_internal_id())
1732 }
1733 (
1734 UninferredImpl::ImplImpl(impl_impl_id),
1735 UninferredImpl::ImplImpl(other_impl_impl_id),
1736 ) => {
1737 if impl_impl_id.impl_id() == other_impl_impl_id.impl_id() {
1738 impl_impl_id
1739 .trait_impl_id()
1740 .get_internal_id()
1741 .cmp(&other_impl_impl_id.trait_impl_id().get_internal_id())
1742 } else {
1743 impl_impl_id
1744 .impl_id()
1745 .get_internal_id()
1746 .cmp(&other_impl_impl_id.impl_id().get_internal_id())
1747 }
1748 }
1749 (
1750 UninferredImpl::GeneratedImpl(generated_impl),
1751 UninferredImpl::GeneratedImpl(other_generated_impl),
1752 ) => generated_impl.get_internal_id().cmp(&other_generated_impl.get_internal_id()),
1753 (UninferredImpl::Def(_), _) => std::cmp::Ordering::Less,
1754 (_, UninferredImpl::Def(_)) => std::cmp::Ordering::Greater,
1755 (UninferredImpl::ImplAlias(_), _) => std::cmp::Ordering::Less,
1756 (_, UninferredImpl::ImplAlias(_)) => std::cmp::Ordering::Greater,
1757 (UninferredImpl::GenericParam(_), _) => std::cmp::Ordering::Less,
1758 (_, UninferredImpl::GenericParam(_)) => std::cmp::Ordering::Greater,
1759 (UninferredImpl::ImplImpl(_), _) => std::cmp::Ordering::Less,
1760 (_, UninferredImpl::ImplImpl(_)) => std::cmp::Ordering::Greater,
1761 }
1762 }
1763}
1764impl<'db> PartialOrd for UninferredImplById<'db> {
1765 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1766 Some(self.cmp(other))
1767 }
1768}
1769impl<'db> From<UninferredImpl<'db>> for UninferredImplById<'db> {
1770 fn from(uninferred_impl: UninferredImpl<'db>) -> Self {
1771 UninferredImplById(uninferred_impl)
1772 }
1773}
1774
1775#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb)]
1776#[debug_db(dyn Database)]
1777pub struct ImplLookupContext<'db> {
1778 pub crate_id: CrateId<'db>,
1779 pub generic_params: Vec<GenericParamId<'db>>,
1780 pub inner_impls: BTreeSet<UninferredImplById<'db>>,
1781 pub negative_impls: Vec<GenericParamId<'db>>,
1782}
1783
1784define_short_id!(ImplLookupContextId, ImplLookupContext<'db>);
1785
1786impl<'db> ImplLookupContext<'db> {
1787 pub fn new_from_crate(crate_id: CrateId<'db>) -> Self {
1789 Self {
1790 crate_id,
1791 generic_params: Default::default(),
1792 inner_impls: Default::default(),
1793 negative_impls: Default::default(),
1794 }
1795 }
1796 pub fn new_from_type(ty: TypeId<'db>, db: &'db dyn Database) -> Self {
1799 Self::new_from_crate(
1800 ty.long(db)
1801 .module_id(db)
1802 .map(|m| m.owning_crate(db))
1803 .unwrap_or_else(|| db.core_crate()),
1804 )
1805 }
1806 pub fn new(
1808 module_id: ModuleId<'db>,
1809 generic_params: Vec<GenericParamId<'db>>,
1810 db: &'db dyn Database,
1811 ) -> ImplLookupContext<'db> {
1812 let crate_id = module_id.owning_crate(db);
1813 let negative_impls = generic_params
1814 .iter()
1815 .filter(|generic_param_id| matches!(generic_param_id.kind(db), GenericKind::NegImpl))
1816 .copied()
1817 .collect_vec();
1818 let generic_params = generic_params
1819 .iter()
1820 .filter(|generic_param_id| {
1821 if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1822 return false;
1823 }
1824
1825 let uninferred_impl = UninferredImpl::GenericParam(**generic_param_id);
1826
1827 let Ok(trait_id) = uninferred_impl.trait_id(db) else {
1828 return true;
1829 };
1830 let Some(set) = db.crate_global_impls(crate_id).get(&trait_id) else {
1831 return true;
1832 };
1833 let uninferred_impl: UninferredImplById<'db> = uninferred_impl.into();
1834 if set.contains(&uninferred_impl) {
1835 return false;
1836 };
1837 true
1838 })
1839 .copied()
1840 .collect_vec();
1841 let mut res = Self {
1842 crate_id,
1843 generic_params: generic_params
1844 .clone()
1845 .into_iter()
1846 .filter(|id| id.long(db).has_type_constraints_syntax(db))
1847 .collect_vec(),
1848 inner_impls: BTreeSet::from_iter(
1849 generic_params.into_iter().map(|id| UninferredImpl::GenericParam(id).into()),
1850 ),
1851 negative_impls,
1852 };
1853 res.insert_module(module_id, db);
1854 res
1855 }
1856 pub fn insert_lookup_scope(&mut self, db: &'db dyn Database, imp: &UninferredImpl<'db>) {
1857 match imp {
1858 UninferredImpl::Def(impl_def_id) => {
1859 self.insert_module(impl_def_id.parent_module(db), db)
1860 }
1861 UninferredImpl::ImplAlias(impl_alias_id) => {
1862 self.insert_module(impl_alias_id.parent_module(db), db)
1863 }
1864 UninferredImpl::GenericParam(param) => self.insert_module(param.parent_module(db), db),
1865 UninferredImpl::ImplImpl(impl_impl_id) => self.insert_impl(impl_impl_id.impl_id, db),
1866 UninferredImpl::GeneratedImpl(_) => {
1867 }
1869 };
1870 }
1871 pub fn insert_module(&mut self, module_id: ModuleId<'db>, db: &'db dyn Database) {
1874 let module_id = db.module_perceived_module(module_id);
1876 let crate_global_impls = db.crate_global_impls(self.crate_id);
1877 if let Ok(module_impls) = db.module_global_impls((), module_id) {
1878 module_impls.locals.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 if !crate_dependencies(db, self.crate_id).contains(&module_id.owning_crate(db)) {
1890 module_impls.globals_by_trait.iter().for_each(|(_, imps)| {
1891 imps.iter().for_each(|imp| {
1892 if let Ok(trait_id) = imp.0.trait_id(db)
1893 && let Some(set) = crate_global_impls.get(&trait_id)
1894 && set.contains(imp)
1895 {
1896 return;
1897 }
1898
1899 self.inner_impls.insert(*imp);
1900 });
1901 });
1902 }
1903 }
1904 }
1905
1906 pub fn insert_impl(&mut self, impl_id: ImplId<'db>, db: &'db dyn Database) {
1909 let mut uninferred_impls = Vec::new();
1910 let Ok(concrete_trait) = impl_id.concrete_trait(db) else {
1911 return;
1912 };
1913 let Ok(trait_impls) = db.trait_impls(concrete_trait.trait_id(db)) else {
1914 return;
1915 };
1916 for (_, trait_impl_id) in trait_impls.iter() {
1917 uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1918 impl_id,
1919 *trait_impl_id,
1920 db,
1921 )));
1922 }
1923 for uninferred_impl in uninferred_impls {
1924 self.inner_impls.insert(uninferred_impl.into());
1925 }
1926 }
1927
1928 pub fn strip_for_trait_id(&mut self, db: &dyn Database, trait_id: TraitId<'db>) {
1931 let deps = db.reachable_trait_dependencies(trait_id, self.crate_id);
1932 let type_eq_trt = db.core_info().type_eq_trt;
1933 self.inner_impls.retain(|impl_by_id| {
1934 if let Ok(impl_trait_id) = impl_by_id.0.trait_id(db) {
1935 return trait_id == impl_trait_id
1936 || trait_id == type_eq_trt
1937 || deps.contains(&impl_trait_id);
1938 }
1939
1940 false
1941 });
1942 }
1943}
1944
1945#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update)]
1947pub enum UninferredImpl<'db> {
1948 Def(ImplDefId<'db>),
1949 ImplAlias(ImplAliasId<'db>),
1950 GenericParam(GenericParamId<'db>),
1951 ImplImpl(ImplImplId<'db>),
1952 GeneratedImpl(UninferredGeneratedImplId<'db>),
1953}
1954impl<'db> UninferredImpl<'db> {
1955 pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
1956 match self {
1957 UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1958 UninferredImpl::ImplAlias(impl_alias_id) => {
1959 let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1960 impl_id.concrete_trait(db)
1961 }
1962 UninferredImpl::GenericParam(param) => {
1963 let param =
1964 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1965 param.concrete_trait
1966 }
1967 UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1968 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1969 }
1970 }
1971
1972 fn trait_id(&self, db: &'db dyn Database) -> Maybe<TraitId<'db>> {
1973 match self {
1974 UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1975 UninferredImpl::ImplAlias(impl_alias_id) => {
1976 let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1977 db.impl_def_trait(impl_def_id)
1978 }
1979 UninferredImpl::GenericParam(param) => db.generic_impl_param_trait(*param),
1980 UninferredImpl::ImplImpl(impl_impl_id) => db
1981 .impl_impl_concrete_trait(*impl_impl_id)
1982 .map(|concrete_trait| concrete_trait.trait_id(db)),
1983 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1984 }
1985 }
1986
1987 fn trait_shallow_generic_args(
1989 &self,
1990 db: &'db dyn Database,
1991 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
1992 match self {
1993 UninferredImpl::Def(impl_def_id) => {
1994 db.impl_def_shallow_trait_generic_args(*impl_def_id)
1995 }
1996
1997 UninferredImpl::ImplAlias(impl_alias_id) => {
1998 db.impl_alias_trait_generic_args(*impl_alias_id)
1999 }
2000 UninferredImpl::GenericParam(param) => {
2001 db.generic_impl_param_shallow_trait_generic_args(*param)
2002 }
2003 UninferredImpl::ImplImpl(_impl_impl_id) => Ok(&[]),
2005 UninferredImpl::GeneratedImpl(_generated_impl) => Ok(&[]),
2006 }
2007 }
2008}
2009
2010impl<'db> DebugWithDb<'db> for UninferredImpl<'db> {
2011 type Db = dyn Database;
2012
2013 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2014 match self {
2015 UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
2016 UninferredImpl::ImplAlias(impl_alias) => {
2017 write!(f, "{:?}", impl_alias.full_path(db))
2018 }
2019 UninferredImpl::GenericParam(param) => {
2020 write!(
2021 f,
2022 "generic param {}",
2023 param.name(db).map(|name| name.long(db).as_str()).unwrap_or("_")
2024 )
2025 }
2026 UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db),
2027 UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db),
2028 }
2029 }
2030}
2031
2032define_short_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'db>);
2033impl<'db> UnstableSalsaId for UninferredGeneratedImplId<'db> {
2034 fn get_internal_id(&self) -> salsa::Id {
2035 self.0
2036 }
2037}
2038semantic_object_for_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'a>);
2039
2040impl<'db> UninferredGeneratedImplId<'db> {
2041 pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
2042 self.long(db).concrete_trait
2043 }
2044
2045 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
2046 self.concrete_trait(db).trait_id(db)
2047 }
2048}
2049
2050#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
2052pub struct UninferredGeneratedImplLongId<'db> {
2053 pub concrete_trait: ConcreteTraitId<'db>,
2054 pub generic_params: Vec<GenericParam<'db>>,
2055 pub impl_items: GeneratedImplItems<'db>,
2056}
2057
2058impl<'db> DebugWithDb<'db> for UninferredGeneratedImplLongId<'db> {
2059 type Db = dyn Database;
2060
2061 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2062 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
2063 }
2064}
2065
2066#[salsa::tracked(returns(ref))]
2068fn trait_candidate_by_head<'db>(
2069 db: &'db dyn Database,
2070 crate_id: CrateId<'db>,
2071 trait_id: TraitId<'db>,
2072) -> OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
2073 let mut res: OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> =
2074 OrderedHashMap::default();
2075
2076 if let Some(candidates) = db.crate_global_impls(crate_id).get(&trait_id) {
2077 for candidate in candidates.iter() {
2078 let Ok(shallow_generic_args) = candidate.0.trait_shallow_generic_args(db) else {
2079 continue;
2080 };
2081 let Ok(trait_params) = db.trait_generic_params(trait_id) else {
2082 continue;
2083 };
2084 let Some(first_param) = trait_params.first() else {
2085 res.entry(GenericsHeadFilter::NoGenerics).or_default().insert(*candidate);
2086 continue;
2087 };
2088
2089 let shallow_arg =
2091 shallow_generic_args.iter().find(|(param, _)| *param == first_param.id());
2092 if let Some(first_generic_head) = shallow_arg.map(|(_, arg)| arg.head()) {
2093 if !matches!(candidate.0, UninferredImpl::GenericParam(_)) {
2094 let mut type_head = first_generic_head.clone();
2095 while let TypeHead::Snapshot(inner) = type_head {
2096 type_head = *inner;
2097 }
2098 if matches!(type_head, TypeHead::Generic(_)) {
2099 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2100 continue;
2101 }
2102 }
2103 res.entry(GenericsHeadFilter::FirstGenericFilter(GenericArgumentHead::Type(
2104 first_generic_head,
2105 )))
2106 .or_default()
2107 .insert(*candidate);
2108 } else {
2109 res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2110 }
2111 }
2112 }
2113 res
2114}
2115
2116pub fn find_candidates_at_context<'db>(
2118 db: &'db dyn Database,
2119 lookup_context: ImplLookupContextId<'db>,
2120 filter: TraitFilter<'db>,
2121) -> Maybe<OrderedHashSet<UninferredImplById<'db>>> {
2122 let mut res = OrderedHashSet::default();
2123 let lookup = lookup_context.long(db);
2124 let crate_id = lookup.crate_id;
2125 let locals = lookup
2126 .inner_impls
2127 .iter()
2128 .filter(|uninferred_impl| {
2129 let Ok(trait_id) = uninferred_impl.0.trait_id(db) else { return false };
2130 trait_id == filter.trait_id
2131 })
2132 .cloned();
2133 match filter.generics_filter {
2134 GenericsHeadFilter::NoFilter => {
2135 let globals = db.crate_global_impls(crate_id);
2136 let globals = globals.get(&filter.trait_id);
2137 res.extend(locals);
2138 res.extend(globals.into_iter().flat_map(|s| s.clone().into_iter()))
2139 }
2140 _ => {
2141 let candidates_by_head = db.trait_candidate_by_head(crate_id, filter.trait_id);
2142 let filtered = candidates_by_head.get(&filter.generics_filter).cloned();
2143 let no_filtered = candidates_by_head.get(&GenericsHeadFilter::NoFilter).cloned();
2144 res.extend(filtered.into_iter().flat_map(|s| s.into_iter()));
2145 res.extend(no_filtered.into_iter().flat_map(|s| s.into_iter()));
2146 res.extend(locals.filter(|uninferred_impl| {
2147 let Ok(_) = uninferred_impl.0.concrete_trait(db) else {
2148 return false;
2149 };
2150 true
2153 }));
2154 }
2155 }
2156 Ok(res)
2157}
2158
2159pub fn find_closure_generated_candidate<'db>(
2161 db: &'db dyn Database,
2162 concrete_trait_id: ConcreteTraitId<'db>,
2163) -> Option<UninferredImpl<'db>> {
2164 let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
2165 return None;
2166 };
2167 let TypeLongId::Closure(closure_type_long) = closure_type.long(db) else {
2168 return None;
2169 };
2170
2171 let info = db.core_info();
2172
2173 let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
2175 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2176 chain!(
2177 closure_type_long.captured_types.iter().unique().map(|ty| {
2178 GenericParam::Impl(GenericParamImpl {
2179 id,
2180 concrete_trait: Maybe::Ok(ConcreteTraitId::new(
2181 db,
2182 ConcreteTraitLongId {
2183 trait_id,
2184 generic_args: vec![GenericArgumentId::Type(*ty)],
2185 },
2186 )),
2187 type_constraints: Default::default(),
2188 })
2189 }),
2190 neg_impl_trait.map(|neg_impl_trait| {
2191 GenericParam::NegImpl(GenericParamImpl {
2192 id,
2193 concrete_trait: Maybe::Ok(neg_impl_trait),
2194 type_constraints: Default::default(),
2195 })
2196 })
2197 )
2198 .collect()
2199 };
2200 let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
2201 (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
2202 };
2203 let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
2204 trait_id if trait_id == info.fn_once_trt => {
2205 let concrete_trait = ConcreteTraitLongId {
2206 trait_id,
2207 generic_args: vec![
2208 GenericArgumentId::Type(closure_type),
2209 GenericArgumentId::Type(
2210 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2211 ),
2212 ],
2213 }
2214 .intern(db);
2215 let ret_ty =
2216 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2217
2218 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2219 let param: GenericParam<'_> = GenericParam::NegImpl(GenericParamImpl {
2221 id,
2222 concrete_trait: Maybe::Ok(
2223 ConcreteTraitLongId {
2224 trait_id: info.fn_trt,
2225 generic_args: vec![
2226 GenericArgumentId::Type(closure_type),
2227 GenericArgumentId::Type(
2228 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2229 ),
2230 ],
2231 }
2232 .intern(db),
2233 ),
2234 type_constraints: Default::default(),
2235 });
2236 (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
2237 }
2238 trait_id if trait_id == info.fn_trt => {
2239 let concrete_trait = ConcreteTraitLongId {
2240 trait_id,
2241 generic_args: vec![
2242 GenericArgumentId::Type(closure_type),
2243 GenericArgumentId::Type(
2244 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2245 ),
2246 ],
2247 }
2248 .intern(db);
2249 let ret_ty =
2250 db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2251
2252 (
2253 concrete_trait,
2254 mem_trait_generic_params(info.copy_trt, None),
2256 [(ret_ty, closure_type_long.ret_ty)].into(),
2257 )
2258 }
2259 trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2260 trait_id if trait_id == info.destruct_trt => {
2261 handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2262 }
2263 trait_id if trait_id == info.panic_destruct_trt => {
2264 handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2265 }
2266 trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2267 _ => return None,
2268 };
2269 Some(UninferredImpl::GeneratedImpl(
2270 UninferredGeneratedImplLongId {
2271 concrete_trait,
2272 generic_params,
2273 impl_items: GeneratedImplItems(impl_items),
2274 }
2275 .intern(db),
2276 ))
2277}
2278
2279pub fn can_infer_impl_by_self<'db>(
2285 ctx: &ComputationContext<'db, '_>,
2286 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2287 trait_function_id: TraitFunctionId<'db>,
2288 self_ty: TypeId<'db>,
2289 stable_ptr: SyntaxStablePtrId<'db>,
2290) -> bool {
2291 let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2292 let mut temp_inference = temp_inference_data.inference(ctx.db);
2293 let lookup_context = ctx.resolver.impl_lookup_context();
2294
2295 let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2296 trait_function_id,
2297 self_ty,
2298 lookup_context,
2299 Some(stable_ptr),
2300 inference_errors,
2301 ) else {
2302 return false;
2303 };
2304 if let Err(err_set) = temp_inference.solve() {
2306 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2308 inference_errors.push((trait_function_id, err));
2309 }
2310 }
2311 match temp_inference.trait_solution_set(
2312 concrete_trait_id,
2313 ImplVarTraitItemMappings::default(),
2314 lookup_context,
2315 ) {
2316 Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2317 Ok(SolutionSet::None) => {
2318 inference_errors
2319 .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2320 false
2321 }
2322 Err(err_set) => {
2323 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2325 inference_errors.push((trait_function_id, err));
2326 }
2327 false
2328 }
2329 }
2330}
2331
2332pub fn infer_impl_by_self<'db>(
2335 ctx: &mut ComputationContext<'db, '_>,
2336 trait_function_id: TraitFunctionId<'db>,
2337 self_ty: TypeId<'db>,
2338 stable_ptr: SyntaxStablePtrId<'db>,
2339 generic_args_syntax: Option<Vec<GenericArg<'db>>>,
2340) -> Maybe<(FunctionId<'db>, usize)> {
2341 let lookup_context = ctx.resolver.impl_lookup_context();
2342 let (concrete_trait_id, n_snapshots) = ctx
2343 .resolver
2344 .inference()
2345 .infer_concrete_trait_by_self_without_errors(
2346 trait_function_id,
2347 self_ty,
2348 lookup_context,
2349 Some(stable_ptr),
2350 )
2351 .ok_or_else(skip_diagnostic)?;
2352
2353 let concrete_trait_function_id =
2354 ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2355 .intern(ctx.db);
2356 let trait_func_generic_params =
2357 ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2358
2359 let impl_lookup_context = ctx.resolver.impl_lookup_context();
2360 let inference = &mut ctx.resolver.inference();
2361 let generic_function = inference.infer_trait_generic_function(
2362 concrete_trait_function_id,
2363 impl_lookup_context,
2364 Some(stable_ptr),
2365 );
2366 let generic_args = ctx.resolver.resolve_generic_args(
2367 ctx.diagnostics,
2368 GenericSubstitution::from_impl(generic_function.impl_id),
2369 trait_func_generic_params,
2370 &generic_args_syntax.unwrap_or_default(),
2371 stable_ptr,
2372 )?;
2373
2374 Ok((
2375 FunctionLongId {
2376 function: ConcreteFunction {
2377 generic_function: GenericFunctionId::Impl(generic_function),
2378 generic_args,
2379 },
2380 }
2381 .intern(ctx.db),
2382 n_snapshots,
2383 ))
2384}
2385
2386pub fn filter_candidate_traits<'db>(
2392 ctx: &mut ComputationContext<'db, '_>,
2393 inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2394 self_ty: TypeId<'db>,
2395 candidate_traits: &[TraitId<'db>],
2396 function_name: SmolStrId<'db>,
2397 stable_ptr: SyntaxStablePtrId<'db>,
2398) -> Vec<TraitFunctionId<'db>> {
2399 let mut candidates = Vec::new();
2400 for trait_id in candidate_traits.iter().copied() {
2401 let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2402 continue;
2403 };
2404 for (&name, &trait_function) in trait_functions.iter() {
2405 if name == function_name
2406 && can_infer_impl_by_self(
2407 ctx,
2408 inference_errors,
2409 trait_function,
2410 self_ty,
2411 stable_ptr,
2412 )
2413 {
2414 candidates.push(trait_function);
2415 }
2416 }
2417 }
2418 candidates
2419}
2420
2421#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2424#[debug_db(dyn Database)]
2425struct ImplItemTypeData<'db> {
2426 type_alias_data: TypeAliasData<'db>,
2427 trait_type_id: Maybe<TraitTypeId<'db>>,
2428 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2430}
2431
2432#[salsa::tracked(cycle_result=impl_type_semantic_data_cycle, returns(ref))]
2438fn impl_type_semantic_data<'db>(
2439 db: &'db dyn Database,
2440 impl_type_def_id: ImplTypeDefId<'db>,
2441 in_cycle: bool,
2442) -> Maybe<ImplItemTypeData<'db>> {
2443 let mut diagnostics = SemanticDiagnostics::default();
2444 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2445 let generic_params_data =
2446 impl_type_def_generic_params_data(db, impl_type_def_id).maybe_as_ref()?.clone();
2447 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2448
2449 let trait_type_id =
2450 validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, &impl_type_def_ast);
2451
2452 if in_cycle {
2453 Ok(ImplItemTypeData {
2454 type_alias_data: type_alias_semantic_data_cycle_helper(
2455 db,
2456 &mut diagnostics,
2457 &impl_type_def_ast,
2458 lookup_item_id,
2459 generic_params_data,
2460 )?,
2461 trait_type_id,
2462 diagnostics: diagnostics.build(),
2463 })
2464 } else {
2465 Ok(ImplItemTypeData {
2468 type_alias_data: type_alias_semantic_data_helper(
2469 db,
2470 &mut diagnostics,
2471 &impl_type_def_ast,
2472 lookup_item_id,
2473 generic_params_data,
2474 )?,
2475 trait_type_id,
2476 diagnostics: diagnostics.build(),
2477 })
2478 }
2479}
2480
2481fn impl_type_semantic_data_cycle<'db>(
2482 db: &'db dyn Database,
2483 impl_type_def_id: ImplTypeDefId<'db>,
2484 _in_cycle: bool,
2485) -> Maybe<ImplItemTypeData<'db>> {
2486 impl_type_semantic_data(db, impl_type_def_id, true).clone()
2487}
2488
2489#[salsa::tracked(returns(ref))]
2491fn impl_type_def_generic_params_data<'db>(
2492 db: &'db dyn Database,
2493 impl_type_def_id: ImplTypeDefId<'db>,
2494) -> Maybe<GenericParamsData<'db>> {
2495 let module_id = impl_type_def_id.module_id(db);
2496 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2497 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2498
2499 let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2500 type_alias_generic_params_data_helper(
2501 db,
2502 module_id,
2503 &impl_type_def_ast,
2504 lookup_item_id,
2505 Some(impl_resolver_data),
2506 )
2507}
2508
2509fn validate_impl_item_type<'db>(
2511 db: &'db dyn Database,
2512 diagnostics: &mut SemanticDiagnostics<'db>,
2513 impl_type_def_id: ImplTypeDefId<'db>,
2514 impl_type_ast: &ast::ItemTypeAlias<'db>,
2515) -> Maybe<TraitTypeId<'db>> {
2516 let impl_def_id = impl_type_def_id.impl_def_id(db);
2517 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2518 let trait_id = concrete_trait_id.trait_id(db);
2519 let type_name = impl_type_def_id.name(db);
2520 let trait_type_id = db.trait_type_by_name(trait_id, type_name)?.ok_or_else(|| {
2521 diagnostics.report(
2522 impl_type_ast.stable_ptr(db),
2523 ImplItemNotInTrait {
2524 impl_def_id,
2525 impl_item_name: type_name,
2526 trait_id,
2527 item_kind: "type".into(),
2528 },
2529 )
2530 })?;
2531
2532 let generic_params_node = impl_type_ast.generic_params(db);
2535 if !generic_params_node.is_empty(db) {
2536 diagnostics.report(
2537 generic_params_node.stable_ptr(db),
2538 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2539 );
2540 }
2541
2542 Ok(trait_type_id)
2543}
2544
2545fn impl_type_concrete_implized<'db>(
2549 db: &'db dyn Database,
2550 impl_type_id: ImplTypeId<'db>,
2551) -> Maybe<TypeId<'db>> {
2552 let concrete_impl = match impl_type_id.impl_id().long(db) {
2553 ImplLongId::Concrete(concrete_impl) => concrete_impl,
2554 ImplLongId::ImplImpl(imp_impl_id) => {
2555 let ImplLongId::Concrete(concrete_impl) =
2556 db.impl_impl_concrete_implized(*imp_impl_id)?.long(db)
2557 else {
2558 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2559 };
2560 concrete_impl
2561 }
2562 ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2563 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2564 }
2565 ImplLongId::GeneratedImpl(generated) => {
2566 return Ok(*generated.long(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2567 }
2568 };
2569
2570 let impl_def_id = concrete_impl.impl_def_id(db);
2571 let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id)?;
2572 concrete_impl.substitution(db)?.substitute(db, ty)
2573}
2574
2575#[salsa::tracked(cycle_result=impl_type_concrete_implized_cycle)]
2576fn impl_type_concrete_implized_helper<'db>(
2577 db: &'db dyn Database,
2578 _tracked: Tracked,
2579 impl_type_id: ImplTypeId<'db>,
2580) -> Maybe<TypeId<'db>> {
2581 impl_type_concrete_implized(db, impl_type_id)
2582}
2583
2584fn impl_type_concrete_implized_tracked<'db>(
2586 db: &'db dyn Database,
2587 impl_type_id: ImplTypeId<'db>,
2588) -> Maybe<TypeId<'db>> {
2589 impl_type_concrete_implized_helper(db, (), impl_type_id)
2590}
2591
2592fn impl_type_concrete_implized_cycle<'db>(
2594 db: &'db dyn Database,
2595 _tracked: Tracked,
2596 impl_type_id: ImplTypeId<'db>,
2597) -> Maybe<TypeId<'db>> {
2598 impl_type_concrete_implized(db, impl_type_id)
2600}
2601
2602#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2605#[debug_db(dyn Database)]
2606struct ImplItemConstantData<'db> {
2607 constant_data: ConstantData<'db>,
2608 trait_constant_id: Maybe<TraitConstantId<'db>>,
2609 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2611}
2612
2613#[salsa::tracked(cycle_result=impl_constant_semantic_data_cycle, returns(ref))]
2615fn impl_constant_semantic_data<'db>(
2616 db: &'db dyn Database,
2617 impl_constant_def_id: ImplConstantDefId<'db>,
2618 in_cycle: bool,
2619) -> Maybe<ImplItemConstantData<'db>> {
2620 let mut diagnostics = SemanticDiagnostics::default();
2621 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2622 let impl_constant_defs = db.impl_constants(impl_def_id)?;
2623 let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2624 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2625
2626 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2627 ImplItemId::Constant(impl_constant_def_id),
2628 ));
2629 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2630 let mut resolver =
2631 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2632
2633 let trait_constant_id = validate_impl_item_constant(
2634 db,
2635 &mut diagnostics,
2636 impl_constant_def_id,
2637 impl_constant_def_ast,
2638 &mut resolver,
2639 );
2640 let mut constant_data = if in_cycle {
2641 constant_semantic_data_cycle_helper(
2642 db,
2643 impl_constant_def_ast,
2644 lookup_item_id,
2645 Some(Arc::new(resolver.data)),
2646 &impl_def_id,
2647 )?
2648 } else {
2649 constant_semantic_data_helper(
2650 db,
2651 impl_constant_def_ast,
2652 lookup_item_id,
2653 Some(Arc::new(resolver.data)),
2654 &impl_def_id,
2655 )?
2656 };
2657 diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2658 Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2659}
2660
2661fn impl_constant_semantic_data_cycle<'db>(
2662 db: &'db dyn Database,
2663 impl_constant_def_id: ImplConstantDefId<'db>,
2664 _in_cycle: bool,
2665) -> Maybe<ImplItemConstantData<'db>> {
2666 impl_constant_semantic_data(db, impl_constant_def_id, true).clone()
2667}
2668
2669fn validate_impl_item_constant<'db>(
2671 db: &'db dyn Database,
2672 diagnostics: &mut SemanticDiagnostics<'db>,
2673 impl_constant_def_id: ImplConstantDefId<'db>,
2674 impl_constant_ast: &ast::ItemConstant<'db>,
2675 resolver: &mut Resolver<'db>,
2676) -> Maybe<TraitConstantId<'db>> {
2677 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2678 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2679 let trait_id = concrete_trait_id.trait_id(db);
2680 let constant_name = impl_constant_def_id.name(db);
2681
2682 let trait_constant_id =
2683 db.trait_constant_by_name(trait_id, constant_name)?.ok_or_else(|| {
2684 diagnostics.report(
2685 impl_constant_ast.stable_ptr(db),
2686 ImplItemNotInTrait {
2687 impl_def_id,
2688 impl_item_name: constant_name,
2689 trait_id,
2690 item_kind: "const".into(),
2691 },
2692 )
2693 })?;
2694 let concrete_trait_constant =
2695 ConcreteTraitConstantId::new_from_data(db, concrete_trait_id, trait_constant_id);
2696 let concrete_trait_constant_ty = db.concrete_trait_constant_type(concrete_trait_constant)?;
2697
2698 let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2699
2700 let constant_ty =
2701 resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2702
2703 let inference = &mut resolver.inference();
2704
2705 let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2706 let actual_ty = inference.rewrite(constant_ty).no_err();
2707 if expected_ty != actual_ty {
2708 diagnostics.report(
2709 impl_constant_type_clause_ast.stable_ptr(db),
2710 WrongType { expected_ty, actual_ty },
2711 );
2712 }
2713 Ok(trait_constant_id)
2714}
2715
2716fn impl_constant_implized_by_context<'db>(
2720 db: &'db dyn Database,
2721 impl_constant_id: ImplConstantId<'db>,
2722 impl_def_id: ImplDefId<'db>,
2723) -> Maybe<ConstValueId<'db>> {
2724 let impl_constant_def_id: ImplConstantDefId<'_> =
2725 db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2726
2727 db.impl_constant_def_value(impl_constant_def_id)
2728}
2729
2730#[salsa::tracked(cycle_result=impl_constant_implized_by_context_cycle)]
2732fn impl_constant_implized_by_context_tracked<'db>(
2733 db: &'db dyn Database,
2734 impl_constant_id: ImplConstantId<'db>,
2735 impl_def_id: ImplDefId<'db>,
2736) -> Maybe<ConstValueId<'db>> {
2737 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2738}
2739
2740fn impl_constant_implized_by_context_cycle<'db>(
2742 db: &'db dyn Database,
2743 impl_constant_id: ImplConstantId<'db>,
2744 impl_def_id: ImplDefId<'db>,
2745) -> Maybe<ConstValueId<'db>> {
2746 impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2748}
2749
2750fn impl_constant_concrete_implized_value<'db>(
2752 db: &'db dyn Database,
2753 impl_constant_id: ImplConstantId<'db>,
2754) -> Maybe<ConstValueId<'db>> {
2755 if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().long(db) {
2756 let impl_def_id = concrete_impl.impl_def_id(db);
2757 let constant: ConstValueId<'db> =
2758 db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2759 return concrete_impl.substitution(db)?.substitute(db, constant);
2760 }
2761 let substitution: GenericSubstitution<'db> =
2762 GenericSubstitution::from_impl(impl_constant_id.impl_id());
2763 let substitution_id = substitution.substitute(db, impl_constant_id)?;
2764 let const_val: ConstValue<'db> = ConstValue::ImplConstant(substitution_id);
2765 Ok(const_val.intern(db))
2766}
2767
2768fn impl_constant_concrete_implized_value_tracked<'db>(
2770 db: &'db dyn Database,
2771 impl_constant_id: ImplConstantId<'db>,
2772) -> Maybe<ConstValueId<'db>> {
2773 impl_constant_concrete_implized_value_helper(db, (), impl_constant_id)
2774}
2775
2776#[salsa::tracked(cycle_result=impl_constant_concrete_implized_value_cycle)]
2779fn impl_constant_concrete_implized_value_helper<'db>(
2780 db: &'db dyn Database,
2781 _tracked: Tracked,
2782 impl_constant_id: ImplConstantId<'db>,
2783) -> Maybe<ConstValueId<'db>> {
2784 impl_constant_concrete_implized_value(db, impl_constant_id)
2785}
2786
2787fn impl_constant_concrete_implized_value_cycle<'db>(
2789 db: &'db dyn Database,
2790 _tracked: Tracked,
2791 impl_constant_id: ImplConstantId<'db>,
2792) -> Maybe<ConstValueId<'db>> {
2793 impl_constant_concrete_implized_value(db, impl_constant_id)
2795}
2796
2797fn impl_constant_concrete_implized_type<'db>(
2799 db: &'db dyn Database,
2800 impl_constant_id: ImplConstantId<'db>,
2801) -> Maybe<TypeId<'db>> {
2802 let concrete_trait_id = match impl_constant_id.impl_id().long(db) {
2803 ImplLongId::Concrete(concrete_impl) => {
2804 let impl_def_id = concrete_impl.impl_def_id(db);
2805 let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2806 return concrete_impl.substitution(db)?.substitute(db, ty);
2807 }
2808 ImplLongId::GenericParameter(param) => {
2809 let param_impl =
2810 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
2811 param_impl.concrete_trait?
2812 }
2813 ImplLongId::ImplVar(var) => var.long(db).concrete_trait_id,
2814 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl)?,
2815 ImplLongId::SelfImpl(concrete_trait_id) => *concrete_trait_id,
2816 ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2817 };
2818
2819 let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new_from_data(
2820 db,
2821 concrete_trait_id,
2822 impl_constant_id.trait_constant_id(),
2823 ))?;
2824 GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2825}
2826
2827fn impl_constant_concrete_implized_type_tracked<'db>(
2829 db: &'db dyn Database,
2830 impl_constant_id: ImplConstantId<'db>,
2831) -> Maybe<TypeId<'db>> {
2832 impl_constant_concrete_implized_type_helper(db, (), impl_constant_id)
2833}
2834
2835#[salsa::tracked(cycle_result=impl_constant_concrete_implized_type_cycle)]
2836fn impl_constant_concrete_implized_type_helper<'db>(
2837 db: &'db dyn Database,
2838 _tracked: Tracked,
2839 impl_constant_id: ImplConstantId<'db>,
2840) -> Maybe<TypeId<'db>> {
2841 impl_constant_concrete_implized_type(db, impl_constant_id)
2842}
2843
2844fn impl_constant_concrete_implized_type_cycle<'db>(
2846 db: &'db dyn Database,
2847 _tracked: Tracked,
2848 impl_constant_id: ImplConstantId<'db>,
2849) -> Maybe<TypeId<'db>> {
2850 impl_constant_concrete_implized_type(db, impl_constant_id)
2852}
2853
2854#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2857#[debug_db(dyn Database)]
2858struct ImplItemImplData<'db> {
2859 impl_data: ImplAliasData<'db>,
2860 trait_impl_id: Maybe<TraitImplId<'db>>,
2861 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2863}
2864
2865#[salsa::tracked(cycle_result=impl_impl_semantic_data_cycle, returns(ref))]
2867fn impl_impl_semantic_data<'db>(
2868 db: &'db dyn Database,
2869 impl_impl_def_id: ImplImplDefId<'db>,
2870 in_cycle: bool,
2871) -> Maybe<ImplItemImplData<'db>> {
2872 let mut diagnostics = SemanticDiagnostics::default();
2873 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2874 let impl_impl_defs = db.impl_impls(impl_def_id)?;
2875 let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2876 let generic_params_data =
2877 impl_impl_def_generic_params_data(db, impl_impl_def_id).maybe_as_ref()?.clone();
2878 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2879
2880 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2881 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2882 let mut resolver =
2883 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2884
2885 let mut impl_data = if in_cycle {
2886 impl_alias_semantic_data_cycle_helper(
2887 db,
2888 impl_impl_def_ast,
2889 lookup_item_id,
2890 generic_params_data,
2891 )?
2892 } else {
2893 impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2894 };
2895
2896 diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2897
2898 let trait_impl_id = validate_impl_item_impl(
2899 db,
2900 &mut diagnostics,
2901 impl_impl_def_id,
2902 impl_impl_def_ast,
2903 &impl_data,
2904 &mut resolver,
2905 );
2906
2907 Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2908}
2909
2910fn impl_impl_semantic_data_cycle<'db>(
2911 db: &'db dyn Database,
2912 impl_impl_def_id: ImplImplDefId<'db>,
2913 _in_cycle: bool,
2914) -> Maybe<ImplItemImplData<'db>> {
2915 impl_impl_semantic_data(db, impl_impl_def_id, true).clone()
2916}
2917
2918#[salsa::tracked(returns(ref))]
2920fn impl_impl_def_generic_params_data<'db>(
2921 db: &'db dyn Database,
2922 impl_impl_def_id: ImplImplDefId<'db>,
2923) -> Maybe<GenericParamsData<'db>> {
2924 let module_id = impl_impl_def_id.module_id(db);
2925 let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?;
2926 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2927
2928 let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2929 impl_alias_generic_params_data_helper(
2930 db,
2931 module_id,
2932 &impl_impl_def_ast,
2933 lookup_item_id,
2934 Some(impl_resolver_data),
2935 )
2936}
2937
2938fn validate_impl_item_impl<'db>(
2940 db: &'db dyn Database,
2941 diagnostics: &mut SemanticDiagnostics<'db>,
2942 impl_impl_def_id: ImplImplDefId<'db>,
2943 impl_impl_ast: &ast::ItemImplAlias<'db>,
2944 impl_data: &ImplAliasData<'db>,
2945 resolver: &mut Resolver<'db>,
2946) -> Maybe<TraitImplId<'db>> {
2947 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2948 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2949 let trait_id = concrete_trait_id.trait_id(db);
2950 let impl_item_name = impl_impl_def_id.name(db);
2951 let trait_impl_id = db.trait_impl_by_name(trait_id, impl_item_name)?.ok_or_else(|| {
2952 diagnostics.report(
2953 impl_impl_ast.stable_ptr(db),
2954 ImplItemNotInTrait { impl_def_id, impl_item_name, trait_id, item_kind: "impl".into() },
2955 )
2956 })?;
2957
2958 let generic_params_node = impl_impl_ast.generic_params(db);
2961 if !generic_params_node.is_empty(db) {
2962 diagnostics.report(
2963 generic_params_node.stable_ptr(db),
2964 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2965 );
2966 }
2967
2968 let concrete_trait_impl =
2969 ConcreteTraitImplId::new_from_data(db, concrete_trait_id, trait_impl_id);
2970 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2971
2972 let concrete_trait_impl_concrete_trait = db
2973 .concrete_trait_impl_concrete_trait(concrete_trait_impl)
2974 .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
2975
2976 let resolved_impl_concrete_trait =
2977 impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2978 let _ = (|| -> Result<(), DiagnosticAdded> {
2980 if resolver
2981 .inference()
2982 .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
2983 .is_err()
2984 {
2985 diagnostics.report(
2986 impl_impl_ast.stable_ptr(db),
2987 TraitMismatch {
2988 expected_trt: concrete_trait_impl_concrete_trait?,
2989 actual_trt: resolved_impl_concrete_trait?,
2990 },
2991 );
2992 }
2993 Ok(())
2994 })();
2995
2996 Ok(trait_impl_id)
2997}
2998
2999#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3000#[debug_db(dyn Database)]
3001struct ImplicitImplImplData<'db> {
3002 resolved_impl: Maybe<ImplId<'db>>,
3003 trait_impl_id: TraitImplId<'db>,
3004 diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
3005}
3006
3007fn implicit_impl_impl_semantic_data<'db>(
3009 db: &'db dyn Database,
3010 impl_def_id: ImplDefId<'db>,
3011 trait_impl_id: TraitImplId<'db>,
3012 in_cycle: bool,
3013) -> Maybe<ImplicitImplImplData<'db>> {
3014 let mut diagnostics = SemanticDiagnostics::default();
3015 if in_cycle {
3016 let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
3017 return Ok(ImplicitImplImplData {
3018 resolved_impl: err,
3019 trait_impl_id,
3020 diagnostics: diagnostics.build(),
3021 });
3022 }
3023 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
3024
3025 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3026 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3027
3028 let mut resolver =
3029 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3030 resolver.trait_or_impl_ctx = TraitOrImplContext::None;
3032
3033 let concrete_trait_impl_concrete_trait = db
3034 .impl_def_concrete_trait(impl_def_id)
3035 .and_then(|concrete_trait_id| {
3036 db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new_from_data(
3037 db,
3038 concrete_trait_id,
3039 trait_impl_id,
3040 ))
3041 })
3042 .and_then(|concrete_trait_id| {
3043 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3044 impl_def_substitution.substitute(db, concrete_trait_id)
3045 });
3046 let impl_lookup_context = resolver.impl_lookup_context();
3047 let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
3048 let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
3049 resolver.inference().finalize_without_reporting().map_err(|(err_set, _)| {
3050 diagnostics.report(
3051 impl_def_id.stable_ptr(db).untyped(),
3052 ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
3053 );
3054 resolver.inference().report_on_pending_error(
3055 err_set,
3056 &mut diagnostics,
3057 impl_def_id.stable_ptr(db).untyped(),
3058 )
3059 })?;
3060 resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
3061 });
3062
3063 Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
3064}
3065
3066#[salsa::tracked(cycle_result=implicit_impl_impl_semantic_data_cycle, returns(ref))]
3068fn implicit_impl_impl_semantic_data_tracked<'db>(
3069 db: &'db dyn Database,
3070 impl_def_id: ImplDefId<'db>,
3071 trait_impl_id: TraitImplId<'db>,
3072 in_cycle: bool,
3073) -> Maybe<ImplicitImplImplData<'db>> {
3074 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, in_cycle)
3075}
3076
3077fn implicit_impl_impl_semantic_data_cycle<'db>(
3079 db: &'db dyn Database,
3080 impl_def_id: ImplDefId<'db>,
3081 trait_impl_id: TraitImplId<'db>,
3082 _in_cycle: bool,
3083) -> Maybe<ImplicitImplImplData<'db>> {
3084 implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, true)
3086}
3087
3088fn impl_impl_implized_by_context<'db>(
3092 db: &'db dyn Database,
3093 impl_impl_id: ImplImplId<'db>,
3094 impl_def_id: ImplDefId<'db>,
3095 in_cycle: bool,
3096) -> Maybe<ImplId<'db>> {
3097 if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
3098 return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
3099 }
3100
3101 let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
3102
3103 db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
3104}
3105
3106#[salsa::tracked(cycle_result=impl_impl_implized_by_context_cycle)]
3108fn impl_impl_implized_by_context_tracked<'db>(
3109 db: &'db dyn Database,
3110 impl_impl_id: ImplImplId<'db>,
3111 impl_def_id: ImplDefId<'db>,
3112 in_cycle: bool,
3113) -> Maybe<ImplId<'db>> {
3114 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, in_cycle)
3115}
3116
3117fn impl_impl_implized_by_context_cycle<'db>(
3119 db: &'db dyn Database,
3120 impl_impl_id: ImplImplId<'db>,
3121 impl_def_id: ImplDefId<'db>,
3122 _in_cycle: bool,
3123) -> Maybe<ImplId<'db>> {
3124 impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, true)
3126}
3127
3128fn impl_impl_concrete_implized<'db>(
3130 db: &'db dyn Database,
3131 impl_impl_id: ImplImplId<'db>,
3132) -> Maybe<ImplId<'db>> {
3133 impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3134}
3135
3136fn impl_impl_concrete_implized_tracked<'db>(
3138 db: &'db dyn Database,
3139 impl_impl_id: ImplImplId<'db>,
3140) -> Maybe<ImplId<'db>> {
3141 impl_impl_concrete_implized_helper(db, (), impl_impl_id)
3142}
3143
3144#[salsa::tracked(cycle_result=impl_impl_concrete_implized_cycle)]
3145fn impl_impl_concrete_implized_helper<'db>(
3146 db: &'db dyn Database,
3147 _tracked: Tracked,
3148 impl_impl_id: ImplImplId<'db>,
3149) -> Maybe<ImplId<'db>> {
3150 impl_impl_concrete_implized(db, impl_impl_id)
3151}
3152
3153fn impl_impl_concrete_implized_cycle<'db>(
3155 db: &'db dyn Database,
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.module_id(db);
3223 let mut diagnostics = SemanticDiagnostics::default();
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 mut diagnostics = SemanticDiagnostics::default();
3256 let impl_def_id = impl_function_id.impl_def_id(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 mut diagnostics = SemanticDiagnostics::default();
3580 let impl_def_id = impl_function_id.impl_def_id(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 diagnostics = SemanticDiagnostics::default();
3784 let (mut resolver, module_id, generic_params) = match impl_id {
3785 UninferredImpl::Def(impl_def_id) => {
3786 let module_id = impl_def_id.module_id(db);
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))
3794 }
3795 UninferredImpl::ImplAlias(impl_alias_id) => {
3796 let module_id = impl_alias_id.module_id(db);
3797
3798 let impl_ast = db.module_impl_alias_by_id(impl_alias_id)?;
3799 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
3800
3801 let mut resolver = Resolver::new(db, module_id, inference_id);
3802 resolver.set_feature_config(&impl_alias_id, &impl_ast, &mut diagnostics);
3803 (resolver, module_id, impl_ast.generic_params(db))
3804 }
3805 _ => {
3806 return Ok(());
3807 }
3808 };
3809 if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) = generic_params
3810 {
3811 params_list.generic_params(db).elements(db).for_each(|param_syntax| {
3812 let generic_param_id =
3813 GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
3814 resolver.add_generic_param(generic_param_id);
3815 let trait_path = match param_syntax {
3816 ast::GenericParam::ImplNamed(param) => param.trait_path(db),
3817 ast::GenericParam::ImplAnonymous(param) => param.trait_path(db),
3818 ast::GenericParam::NegativeImpl(param) => param.trait_path(db),
3819
3820 _ => return,
3821 };
3822 let dependant_trait_id =
3823 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path);
3824
3825 let Ok(dependant_trait_id) = dependant_trait_id else {
3826 return;
3827 };
3828 trait_deps.entry(imp_trait_id).or_default().insert(dependant_trait_id);
3829 })
3830 };
3831 };
3832 Ok(())
3833}
3834
3835#[derive(Default, Debug, Eq, PartialEq, salsa::Update)]
3836struct ModuleImpls<'db> {
3837 globals_by_trait: OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3838 trait_deps: OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3839 globals_by_type: OrderedHashMap<TypeId<'db>, Vec<UninferredImpl<'db>>>,
3840
3841 locals: BTreeSet<UninferredImplById<'db>>,
3842}
3843
3844#[salsa::tracked(returns(ref))]
3845fn module_global_impls<'db>(
3846 db: &'db dyn Database,
3847 _tracked: Tracked,
3848 module_id: ModuleId<'db>,
3849) -> Maybe<ModuleImpls<'db>> {
3850 let mut module_impls = ModuleImpls::default();
3851 for (containing_module, info) in db.module_imported_modules((), module_id).iter() {
3852 for defined_module in module_macro_modules(db, true, *containing_module) {
3853 let Ok(module_semantic_data) = db.priv_module_semantic_data(*defined_module) else {
3854 continue;
3855 };
3856 for item in module_semantic_data.items.values().filter(|item| {
3857 info.user_modules.iter().any(|user_module| {
3858 peek_visible_in(db, item.visibility, *containing_module, *user_module)
3859 })
3860 }) {
3861 let imp = match item.item_id {
3862 ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
3863 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
3864 UninferredImpl::Def(impl_def_id)
3865 }
3866 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
3867 UninferredImpl::ImplAlias(impl_alias_id)
3868 }
3869 _ => continue,
3870 },
3871 ModuleItemId::Impl(impl_def_id) => {
3872 if let Ok(impl_ast) = db.module_impl_by_id(impl_def_id) {
3873 global_impls_insert_generic_impls(
3874 db,
3875 &impl_ast.generic_params(db),
3876 impl_def_id.module_id(db),
3877 &mut module_impls.globals_by_trait,
3878 );
3879 }
3880
3881 UninferredImpl::Def(impl_def_id)
3884 }
3885 ModuleItemId::ImplAlias(impl_alias_id) => {
3887 UninferredImpl::ImplAlias(impl_alias_id)
3888 }
3889 ModuleItemId::FreeFunction(free_function_id) => {
3890 if let Ok(function_ast) = db.module_free_function_by_id(free_function_id) {
3891 let declaration = function_ast.declaration(db);
3892 global_impls_insert_generic_impls(
3893 db,
3894 &declaration.generic_params(db),
3895 free_function_id.module_id(db),
3896 &mut module_impls.globals_by_trait,
3897 );
3898 }
3899 continue;
3900 }
3901 _ => continue,
3902 };
3903
3904 uninferred_impl_trait_dependency(db, imp, &mut module_impls.trait_deps)?;
3905
3906 if let Ok(true) = is_global_impl(db, imp, module_id) {
3907 let trait_id = imp.trait_id(db)?;
3908 module_impls.globals_by_trait.entry(trait_id).or_default().insert(imp.into());
3909 } else {
3910 module_impls.locals.insert(imp.into());
3911 }
3912 }
3913 }
3914 }
3915
3916 Ok(module_impls)
3917}
3918
3919fn is_global_impl<'db>(
3923 db: &'db dyn Database,
3924 impl_id: UninferredImpl<'db>,
3925 impl_module: ModuleId<'db>,
3926) -> Maybe<bool> {
3927 let trait_id = impl_id.trait_id(db)?;
3928 if trait_id.parent_module(db) == impl_module {
3929 return Ok(true);
3930 }
3931
3932 Ok(impl_id
3933 .trait_shallow_generic_args(db)?
3934 .iter()
3935 .any(|(_, arg)| arg.module_id(db) == Some(impl_module)))
3936}
3937
3938fn global_impls_insert_generic_impls<'db>(
3942 db: &'db dyn Database,
3943 generic_params: &ast::OptionWrappedGenericParamList<'db>,
3944 module_id: ModuleId<'db>,
3945 globals_by_trait: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3946) {
3947 let ast::OptionWrappedGenericParamList::WrappedGenericParamList(generic_params) =
3948 generic_params
3949 else {
3950 return;
3951 };
3952 let mut generic_types = OrderedHashMap::<_, GenericParamId<'db>, _>::default();
3953 for param in generic_params.generic_params(db).elements(db) {
3954 let (trait_path, type_constraints) = match ¶m {
3955 ast::GenericParam::Type(_) => {
3956 let param_id = GenericParamLongId(module_id, param.stable_ptr(db)).intern(db);
3957 if let Some(name) = param_id.name(db) {
3958 generic_types.insert(name, param_id);
3959 }
3960 continue;
3961 }
3962 ast::GenericParam::ImplNamed(impl_param) => {
3963 (impl_param.trait_path(db), impl_param.type_constrains(db))
3964 }
3965 ast::GenericParam::ImplAnonymous(impl_param) => {
3966 (impl_param.trait_path(db), impl_param.type_constrains(db))
3967 }
3968 _ => continue,
3969 };
3970 if is_global_impl_generic_param(db, &generic_types, &trait_path) {
3971 let uninferred_impl = UninferredImpl::GenericParam(
3972 GenericParamLongId(module_id, param.stable_ptr(db)).intern(db),
3973 );
3974 if let Ok(trait_id) = uninferred_impl.trait_id(db) {
3975 if trait_id == db.core_info().type_eq_trt {
3976 continue;
3977 }
3978 if matches!(
3979 type_constraints,
3980 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
3981 ) {
3982 continue;
3983 }
3984 globals_by_trait.entry(trait_id).or_default().insert(uninferred_impl.into());
3985 }
3986 }
3987 }
3988}
3989
3990fn is_global_impl_generic_param<'db>(
3992 db: &'db dyn Database,
3993 generic_types: &OrderedHashMap<SmolStrId<'db>, GenericParamId<'db>>,
3994 trait_syntax: &ast::ExprPath<'db>,
3995) -> bool {
3996 let trait_segments = trait_syntax.to_segments(db);
3997 let ast::PathSegment::WithGenericArgs(trait_segment) = trait_segments.last().unwrap() else {
3998 return false;
3999 };
4000
4001 let generic_args = trait_segment.generic_args(db);
4002
4003 for arg in generic_args.generic_args(db).elements(db) {
4004 let value = match arg {
4005 ast::GenericArg::Unnamed(arg) => arg.value(db),
4006 ast::GenericArg::Named(arg) => arg.value(db),
4007 };
4008 let mut expr = match value {
4009 GenericArgValue::Expr(generic_arg_value_expr) => generic_arg_value_expr.expr(db),
4010 GenericArgValue::Underscore(_) => continue,
4011 };
4012
4013 while let ast::Expr::Unary(unary_expr) = &expr {
4014 if !matches!(unary_expr.op(db), UnaryOperator::At(_)) {
4015 break;
4016 }
4017
4018 expr = unary_expr.expr(db);
4019 }
4020
4021 let ast::Expr::Path(path) = expr else {
4022 continue;
4023 };
4024 let path_segments = path.to_segments(db);
4025 let [segment] = path_segments.as_slice() else {
4026 continue;
4027 };
4028
4029 let ast::PathSegment::Simple(simple_segment) = segment else {
4030 continue;
4031 };
4032 if generic_types.contains_key(&simple_segment.identifier(db)) {
4033 return true;
4034 }
4035 }
4036
4037 false
4038}
4039
4040pub trait ImplSemantic<'db>: Database {
4042 fn impl_semantic_declaration_diagnostics(
4044 &'db self,
4045 impl_def_id: ImplDefId<'db>,
4046 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4047 impl_declaration_data(self.as_dyn_database(), impl_def_id)
4048 .as_ref()
4049 .map(|data| data.diagnostics.clone())
4050 .unwrap_or_default()
4051 }
4052 fn impl_def_generic_params(
4054 &'db self,
4055 impl_def_id: ImplDefId<'db>,
4056 ) -> Maybe<&'db [GenericParam<'db>]> {
4057 Ok(&impl_def_generic_params_data(self.as_dyn_database(), impl_def_id)
4058 .maybe_as_ref()?
4059 .generic_params)
4060 }
4061 fn impl_def_resolver_data(
4063 &'db self,
4064 impl_def_id: ImplDefId<'db>,
4065 ) -> Maybe<Arc<ResolverData<'db>>> {
4066 Ok(impl_declaration_data(self.as_dyn_database(), impl_def_id)
4067 .maybe_as_ref()?
4068 .resolver_data
4069 .clone())
4070 }
4071 fn impl_def_concrete_trait(
4073 &'db self,
4074 impl_def_id: ImplDefId<'db>,
4075 ) -> Maybe<ConcreteTraitId<'db>> {
4076 impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.concrete_trait
4077 }
4078 fn impl_def_attributes(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4080 Ok(&impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.attributes)
4081 }
4082 fn impl_concrete_trait(&'db self, impl_id: ImplId<'db>) -> Maybe<ConcreteTraitId<'db>> {
4084 impl_concrete_trait_tracked(self.as_dyn_database(), impl_id)
4085 }
4086 fn impl_def_trait(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
4089 impl_def_trait(self.as_dyn_database(), impl_def_id)
4090 }
4091 fn impl_semantic_definition_diagnostics(
4093 &'db self,
4094 impl_def_id: ImplDefId<'db>,
4095 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4096 impl_semantic_definition_diagnostics_tracked(self.as_dyn_database(), impl_def_id)
4097 }
4098 fn impl_item_info_by_name(
4100 &'db self,
4101 impl_def_id: ImplDefId<'db>,
4102 name: SmolStrId<'db>,
4103 ) -> Maybe<Option<ImplItemInfo<'db>>> {
4104 impl_item_info_by_name_tracked(self.as_dyn_database(), impl_def_id, name)
4105 }
4106 fn impl_all_used_uses(
4108 &'db self,
4109 impl_def_id: ImplDefId<'db>,
4110 ) -> Maybe<&'db OrderedHashSet<UseId<'db>>> {
4111 impl_all_used_uses(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4112 }
4113 fn impl_types(
4115 &'db self,
4116 impl_def_id: ImplDefId<'db>,
4117 ) -> Maybe<&'db OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>> {
4118 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4119 .maybe_as_ref()?
4120 .item_type_asts)
4121 }
4122 fn impl_type_by_trait_type(
4124 &'db self,
4125 impl_def_id: ImplDefId<'db>,
4126 trait_type_id: TraitTypeId<'db>,
4127 ) -> Maybe<ImplTypeDefId<'db>> {
4128 impl_type_by_trait_type_tracked(self.as_dyn_database(), impl_def_id, trait_type_id)
4129 }
4130 fn impl_constants(
4132 &'db self,
4133 impl_def_id: ImplDefId<'db>,
4134 ) -> Maybe<&'db OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>> {
4135 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4136 .maybe_as_ref()?
4137 .item_constant_asts)
4138 }
4139 fn impl_functions(
4141 &'db self,
4142 impl_def_id: ImplDefId<'db>,
4143 ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
4144 impl_functions(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4145 }
4146
4147 fn impl_type_def_resolved_type(&'db self, id: ImplTypeDefId<'db>) -> Maybe<TypeId<'db>> {
4151 impl_type_semantic_data(self.as_dyn_database(), id, false)
4152 .maybe_as_ref()?
4153 .type_alias_data
4154 .resolved_type
4155 }
4156 fn impl_type_def_generic_params(
4158 &'db self,
4159 id: ImplTypeDefId<'db>,
4160 ) -> Maybe<Vec<GenericParam<'db>>> {
4161 Ok(impl_type_def_generic_params_data(self.as_dyn_database(), id)
4162 .maybe_as_ref()?
4163 .generic_params
4164 .clone())
4165 }
4166 fn impl_type_def_attributes(&'db self, id: ImplTypeDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4168 Ok(&impl_type_semantic_data(self.as_dyn_database(), id, false)
4169 .maybe_as_ref()?
4170 .type_alias_data
4171 .attributes)
4172 }
4173 fn impl_type_def_resolver_data(
4175 &'db self,
4176 id: ImplTypeDefId<'db>,
4177 ) -> Maybe<Arc<ResolverData<'db>>> {
4178 Ok(impl_type_semantic_data(self.as_dyn_database(), id, false)
4179 .maybe_as_ref()?
4180 .type_alias_data
4181 .resolver_data
4182 .clone())
4183 }
4184 fn deref_chain(
4186 &'db self,
4187 ty: TypeId<'db>,
4188 crate_id: CrateId<'db>,
4189 try_deref_mut: bool,
4190 ) -> Maybe<&'db DerefChain<'db>> {
4191 deref_chain(self.as_dyn_database(), ty, crate_id, try_deref_mut).maybe_as_ref()
4192 }
4193
4194 fn impl_type_concrete_implized(
4200 &'db self,
4201 impl_type_def_id: ImplTypeId<'db>,
4202 ) -> Maybe<TypeId<'db>> {
4203 impl_type_concrete_implized_tracked(self.as_dyn_database(), impl_type_def_id)
4204 }
4205
4206 fn impl_constant_def_value(&'db self, id: ImplConstantDefId<'db>) -> Maybe<ConstValueId<'db>> {
4210 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4211 .maybe_as_ref()?
4212 .constant_data
4213 .const_value)
4214 }
4215 fn impl_constant_def_resolver_data(
4217 &'db self,
4218 id: ImplConstantDefId<'db>,
4219 ) -> Maybe<Arc<ResolverData<'db>>> {
4220 Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4221 .maybe_as_ref()?
4222 .constant_data
4223 .resolver_data
4224 .clone())
4225 }
4226
4227 fn impl_constant_concrete_implized_value(
4232 &'db self,
4233 impl_constant_id: ImplConstantId<'db>,
4234 ) -> Maybe<ConstValueId<'db>> {
4235 impl_constant_concrete_implized_value_tracked(self.as_dyn_database(), impl_constant_id)
4236 }
4237 fn impl_constant_concrete_implized_type(
4240 &'db self,
4241 impl_constant_id: ImplConstantId<'db>,
4242 ) -> Maybe<TypeId<'db>> {
4243 impl_constant_concrete_implized_type_tracked(self.as_dyn_database(), impl_constant_id)
4244 }
4245
4246 fn impl_impl_def_resolver_data(
4250 &'db self,
4251 id: ImplImplDefId<'db>,
4252 ) -> Maybe<Arc<ResolverData<'db>>> {
4253 Ok(impl_impl_semantic_data(self.as_dyn_database(), id, false)
4254 .maybe_as_ref()?
4255 .impl_data
4256 .resolver_data
4257 .clone())
4258 }
4259
4260 fn impl_impl_concrete_implized(&'db self, impl_impl_id: ImplImplId<'db>) -> Maybe<ImplId<'db>> {
4264 impl_impl_concrete_implized_tracked(self.as_dyn_database(), impl_impl_id)
4265 }
4266
4267 fn impl_function_declaration_diagnostics(
4271 &'db self,
4272 id: ImplFunctionId<'db>,
4273 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4274 impl_function_declaration_data(self.as_dyn_database(), id)
4275 .as_ref()
4276 .map(|data| data.function_declaration_data.diagnostics.clone())
4277 .unwrap_or_default()
4278 }
4279 fn impl_function_signature(
4281 &'db self,
4282 id: ImplFunctionId<'db>,
4283 ) -> Maybe<&'db semantic::Signature<'db>> {
4284 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4285 .maybe_as_ref()?
4286 .function_declaration_data
4287 .signature)
4288 }
4289 fn impl_function_generic_params(
4291 &'db self,
4292 id: ImplFunctionId<'db>,
4293 ) -> Maybe<&'db [GenericParam<'db>]> {
4294 Ok(&impl_function_generic_params_data(self.as_dyn_database(), id)
4295 .maybe_as_ref()?
4296 .generic_params)
4297 }
4298 fn impl_function_attributes(
4300 &'db self,
4301 id: ImplFunctionId<'db>,
4302 ) -> Maybe<&'db [Attribute<'db>]> {
4303 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4304 .maybe_as_ref()?
4305 .function_declaration_data
4306 .attributes)
4307 }
4308 fn impl_function_resolver_data(
4310 &'db self,
4311 id: ImplFunctionId<'db>,
4312 ) -> Maybe<Arc<ResolverData<'db>>> {
4313 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4314 .maybe_as_ref()?
4315 .function_declaration_data
4316 .resolver_data
4317 .clone())
4318 }
4319 fn impl_function_declaration_inline_config(
4321 &'db self,
4322 id: ImplFunctionId<'db>,
4323 ) -> Maybe<InlineConfiguration<'db>> {
4324 Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4325 .maybe_as_ref()?
4326 .function_declaration_data
4327 .inline_config
4328 .clone())
4329 }
4330 fn impl_function_declaration_implicit_precedence(
4332 &'db self,
4333 id: ImplFunctionId<'db>,
4334 ) -> Maybe<&'db ImplicitPrecedence<'db>> {
4335 Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4336 .maybe_as_ref()?
4337 .function_declaration_data
4338 .implicit_precedence)
4339 }
4340 fn impl_function_trait_function(
4342 &'db self,
4343 id: ImplFunctionId<'db>,
4344 ) -> Maybe<TraitFunctionId<'db>> {
4345 impl_function_declaration_data(self.as_dyn_database(), id).maybe_as_ref()?.trait_function_id
4346 }
4347 fn impl_function_body_diagnostics(
4349 &'db self,
4350 impl_function_id: ImplFunctionId<'db>,
4351 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4352 self.priv_impl_function_body_data(impl_function_id)
4353 .map(|data| data.diagnostics.clone())
4354 .unwrap_or_default()
4355 }
4356 fn impl_function_body(
4358 &'db self,
4359 impl_function_id: ImplFunctionId<'db>,
4360 ) -> Maybe<&'db FunctionBody<'db>> {
4361 Ok(&self.priv_impl_function_body_data(impl_function_id)?.body)
4362 }
4363 fn impl_function_body_resolver_data(
4365 &'db self,
4366 impl_function_id: ImplFunctionId<'db>,
4367 ) -> Maybe<Arc<ResolverData<'db>>> {
4368 Ok(self.priv_impl_function_body_data(impl_function_id)?.resolver_data.clone())
4369 }
4370 fn priv_impl_function_body_data(
4372 &'db self,
4373 impl_function_id: ImplFunctionId<'db>,
4374 ) -> Maybe<&'db FunctionBodyData<'db>> {
4375 priv_impl_function_body_data_tracked(self.as_dyn_database(), impl_function_id)
4376 .maybe_as_ref()
4377 }
4378}
4379impl<'db, T: Database + ?Sized> ImplSemantic<'db> for T {}
4380
4381trait PrivImplSemantic<'db>: Database {
4383 fn impl_def_substitution(
4385 &'db self,
4386 impl_def_id: ImplDefId<'db>,
4387 ) -> Maybe<&'db GenericSubstitution<'db>> {
4388 impl_def_substitution(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4389 }
4390 fn impl_def_shallow_trait_generic_args(
4392 &'db self,
4393 impl_def_id: ImplDefId<'db>,
4394 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4395 impl_def_shallow_trait_generic_args(self.as_dyn_database(), impl_def_id)
4396 }
4397 fn impl_alias_trait_generic_args(
4399 &'db self,
4400 impl_def_id: ImplAliasId<'db>,
4401 ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4402 impl_alias_trait_generic_args(self.as_dyn_database(), impl_def_id)
4403 }
4404 fn impl_item_by_name(
4406 &'db self,
4407 impl_def_id: ImplDefId<'db>,
4408 name: SmolStrId<'db>,
4409 ) -> Maybe<Option<ImplItemId<'db>>> {
4410 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4411 .maybe_as_ref()?
4412 .item_id_by_name
4413 .get(&name)
4414 .map(|info| info.id))
4415 }
4416 fn impl_implicit_impl_by_name(
4418 &'db self,
4419 impl_def_id: ImplDefId<'db>,
4420 name: SmolStrId<'db>,
4421 ) -> Maybe<Option<TraitImplId<'db>>> {
4422 Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4423 .maybe_as_ref()?
4424 .implicit_impls_id_by_name
4425 .get(&name)
4426 .copied())
4427 }
4428 fn impl_type_by_id(
4430 &'db self,
4431 impl_type_id: ImplTypeDefId<'db>,
4432 ) -> Maybe<ast::ItemTypeAlias<'db>> {
4433 impl_type_by_id(self.as_dyn_database(), impl_type_id)
4434 }
4435 fn impl_impls(
4437 &'db self,
4438 impl_def_id: ImplDefId<'db>,
4439 ) -> Maybe<&'db OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>> {
4440 Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4441 .maybe_as_ref()?
4442 .item_impl_asts)
4443 }
4444 fn impl_impl_by_id(
4446 &'db self,
4447 impl_impl_id: ImplImplDefId<'db>,
4448 ) -> Maybe<ast::ItemImplAlias<'db>> {
4449 impl_impl_by_id(self.as_dyn_database(), impl_impl_id)
4450 }
4451 fn impl_impl_by_trait_impl(
4453 &'db self,
4454 impl_def_id: ImplDefId<'db>,
4455 trait_impl_id: TraitImplId<'db>,
4456 ) -> Maybe<ImplImplDefId<'db>> {
4457 impl_impl_by_trait_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4458 }
4459 fn is_implicit_impl_impl(
4461 &self,
4462 impl_def_id: ImplDefId<'db>,
4463 trait_impl_id: TraitImplId<'db>,
4464 ) -> Maybe<bool> {
4465 is_implicit_impl_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4466 }
4467 fn impl_constant_by_trait_constant(
4469 &'db self,
4470 impl_def_id: ImplDefId<'db>,
4471 trait_constant_id: TraitConstantId<'db>,
4472 ) -> Maybe<ImplConstantDefId<'db>> {
4473 impl_constant_by_trait_constant(self.as_dyn_database(), impl_def_id, trait_constant_id)
4474 }
4475 fn impl_function_by_trait_function(
4480 &'db self,
4481 impl_def_id: ImplDefId<'db>,
4482 trait_function_id: TraitFunctionId<'db>,
4483 ) -> Maybe<Option<ImplFunctionId<'db>>> {
4484 impl_function_by_trait_function(self.as_dyn_database(), impl_def_id, trait_function_id)
4485 }
4486 fn impl_type_def_semantic_diagnostics(
4488 &'db self,
4489 id: ImplTypeDefId<'db>,
4490 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4491 impl_type_semantic_data(self.as_dyn_database(), id, false)
4492 .as_ref()
4493 .map(|data| data.diagnostics.clone())
4494 .unwrap_or_default()
4495 }
4496 fn impl_constant_def_semantic_diagnostics(
4498 &'db self,
4499 id: ImplConstantDefId<'db>,
4500 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4501 impl_constant_semantic_data(self.as_dyn_database(), id, false)
4502 .as_ref()
4503 .map(|data| data.diagnostics.clone())
4504 .unwrap_or_default()
4505 }
4506 fn impl_constant_implized_by_context(
4508 &'db self,
4509 impl_constant_id: ImplConstantId<'db>,
4510 impl_def_id: ImplDefId<'db>,
4511 ) -> Maybe<ConstValueId<'db>> {
4512 impl_constant_implized_by_context_tracked(
4513 self.as_dyn_database(),
4514 impl_constant_id,
4515 impl_def_id,
4516 )
4517 }
4518 fn impl_impl_def_semantic_diagnostics(
4520 &'db self,
4521 id: ImplImplDefId<'db>,
4522 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4523 impl_impl_semantic_data(self.as_dyn_database(), id, false)
4524 .as_ref()
4525 .map(|data| data.diagnostics.clone())
4526 .unwrap_or_default()
4527 }
4528 fn impl_impl_def_impl(
4530 &'db self,
4531 impl_impl_def_id: ImplImplDefId<'db>,
4532 in_cycle: bool,
4533 ) -> Maybe<ImplId<'db>> {
4534 impl_impl_semantic_data(self.as_dyn_database(), impl_impl_def_id, in_cycle)
4535 .maybe_as_ref()?
4536 .impl_data
4537 .resolved_impl
4538 }
4539 fn implicit_impl_impl_semantic_diagnostics(
4541 &'db self,
4542 impl_def_id: ImplDefId<'db>,
4543 trait_impl_id: TraitImplId<'db>,
4544 ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4545 implicit_impl_impl_semantic_data_tracked(
4546 self.as_dyn_database(),
4547 impl_def_id,
4548 trait_impl_id,
4549 false,
4550 )
4551 .as_ref()
4552 .map(|data| data.diagnostics.clone())
4553 .unwrap_or_default()
4554 }
4555 fn implicit_impl_impl_impl(
4557 &'db self,
4558 impl_def_id: ImplDefId<'db>,
4559 trait_impl_id: TraitImplId<'db>,
4560 in_cycle: bool,
4561 ) -> Maybe<ImplId<'db>> {
4562 implicit_impl_impl_semantic_data_tracked(
4563 self.as_dyn_database(),
4564 impl_def_id,
4565 trait_impl_id,
4566 in_cycle,
4567 )
4568 .maybe_as_ref()?
4569 .resolved_impl
4570 }
4571 fn impl_impl_implized_by_context(
4573 &'db self,
4574 impl_impl_id: ImplImplId<'db>,
4575 impl_def_id: ImplDefId<'db>,
4576 in_cycle: bool,
4577 ) -> Maybe<ImplId<'db>> {
4578 impl_impl_implized_by_context_tracked(
4579 self.as_dyn_database(),
4580 impl_impl_id,
4581 impl_def_id,
4582 in_cycle,
4583 )
4584 }
4585 fn impl_impl_concrete_trait(
4587 &'db self,
4588 impl_impl_id: ImplImplId<'db>,
4589 ) -> Maybe<ConcreteTraitId<'db>> {
4590 impl_impl_concrete_trait_tracked(self.as_dyn_database(), impl_impl_id)
4591 }
4592 fn crate_global_impls(
4596 &'db self,
4597 crate_id: CrateId<'db>,
4598 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4599 crate_global_impls(self.as_dyn_database(), crate_id)
4600 }
4601 fn crate_traits_dependencies(
4603 &'db self,
4604 crate_id: CrateId<'db>,
4605 ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
4606 crate_traits_dependencies(self.as_dyn_database(), crate_id)
4607 }
4608 fn reachable_trait_dependencies(
4610 &'db self,
4611 trait_id: TraitId<'db>,
4612 crate_id: CrateId<'db>,
4613 ) -> &'db OrderedHashSet<TraitId<'db>> {
4614 reachable_trait_dependencies(self.as_dyn_database(), trait_id, crate_id)
4615 }
4616 fn module_global_impls(
4618 &'db self,
4619 _tracked: Tracked,
4620 module_id: ModuleId<'db>,
4621 ) -> &'db Maybe<ModuleImpls<'db>> {
4622 module_global_impls(self.as_dyn_database(), _tracked, module_id)
4623 }
4624 fn trait_candidate_by_head(
4626 &'db self,
4627 crate_id: CrateId<'db>,
4628 trait_id: TraitId<'db>,
4629 ) -> &'db OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4630 trait_candidate_by_head(self.as_dyn_database(), crate_id, trait_id)
4631 }
4632}
4633impl<'db, T: Database + ?Sized> PrivImplSemantic<'db> for T {}