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::ids::{
9 FunctionTitleId, GenericKind, GenericParamId, ImplAliasId, ImplConstantDefId,
10 ImplConstantDefLongId, ImplDefId, ImplFunctionId, ImplFunctionLongId, ImplImplDefId,
11 ImplImplDefLongId, ImplItemId, ImplTypeDefId, ImplTypeDefLongId, LanguageElementId,
12 LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId, NamedLanguageElementLongId,
13 TopLevelLanguageElementId, TraitConstantId, TraitFunctionId, TraitId, TraitImplId, TraitTypeId,
14 UseId,
15};
16use cairo_lang_diagnostics::{
17 DiagnosticAdded, Diagnostics, DiagnosticsBuilder, Maybe, ToMaybe, skip_diagnostic,
18};
19use cairo_lang_filesystem::ids::UnstableSalsaId;
20use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
21use cairo_lang_syntax as syntax;
22use cairo_lang_syntax::node::ast::OptionTypeClause;
23use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
24use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
25use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
26use cairo_lang_utils::{Intern, LookupIntern, define_short_id, extract_matches};
27use itertools::{Itertools, chain, izip};
28use smol_str::SmolStr;
29use syntax::attribute::structured::{Attribute, AttributeListStructurize};
30use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
31use syntax::node::db::SyntaxGroup;
32use syntax::node::helpers::OptionWrappedGenericParamListHelper;
33use syntax::node::ids::SyntaxStablePtrId;
34use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
35
36use super::constant::{
37 ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
38 constant_semantic_data_helper,
39};
40use super::enm::SemanticEnumEx;
41use super::feature_kind::{FeatureKind, HasFeatureKind};
42use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
43use super::functions::{
44 FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
45 forbid_inline_always_with_impl_generic_param,
46};
47use super::generics::{
48 GenericArgumentHead, GenericParamImpl, GenericParamsData, fmt_generic_args,
49 generic_params_to_args, semantic_generic_params,
50};
51use super::impl_alias::{
52 ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
53 impl_alias_semantic_data_helper,
54};
55use super::trt::{
56 ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
57 ConcreteTraitImplId,
58};
59use super::type_aliases::{
60 TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
61 type_alias_semantic_data_helper,
62};
63use super::visibility::peek_visible_in;
64use super::{TraitOrImplContext, resolve_trait_path};
65use crate::corelib::{concrete_destruct_trait, concrete_drop_trait, core_crate};
66use crate::db::{SemanticGroup, get_resolver_data_options};
67use crate::diagnostic::SemanticDiagnosticKind::{self, *};
68use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
69use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
70use crate::expr::fmt::CountingWriter;
71use crate::expr::inference::canonic::ResultNoErrEx;
72use crate::expr::inference::conform::InferenceConform;
73use crate::expr::inference::infers::InferenceEmbeddings;
74use crate::expr::inference::solver::{Ambiguity, SolutionSet, enrich_lookup_context_with_ty};
75use crate::expr::inference::{
76 ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId,
77};
78use crate::items::function_with_body::get_implicit_precedence;
79use crate::items::functions::ImplicitPrecedence;
80use crate::items::us::SemanticUseEx;
81use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem, Resolver, ResolverData};
82use crate::substitution::{GenericSubstitution, SemanticRewriter};
83use crate::types::{ImplTypeId, add_type_based_diagnostics, get_impl_at_context, resolve_type};
84use crate::{
85 Arenas, ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
86 GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
87 semantic_object_for_id,
88};
89
90#[cfg(test)]
91#[path = "imp_test.rs"]
92mod test;
93
94#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
95pub struct ConcreteImplLongId {
96 pub impl_def_id: ImplDefId,
97 pub generic_args: Vec<GenericArgumentId>,
98}
99define_short_id!(
100 ConcreteImplId,
101 ConcreteImplLongId,
102 SemanticGroup,
103 lookup_intern_concrete_impl,
104 intern_concrete_impl
105);
106semantic_object_for_id!(
107 ConcreteImplId,
108 lookup_intern_concrete_impl,
109 intern_concrete_impl,
110 ConcreteImplLongId
111);
112impl DebugWithDb<dyn SemanticGroup> for ConcreteImplLongId {
113 fn fmt(
114 &self,
115 f: &mut std::fmt::Formatter<'_>,
116 db: &(dyn SemanticGroup + 'static),
117 ) -> std::fmt::Result {
118 let mut f = CountingWriter::new(f);
119 write!(f, "{}", self.impl_def_id.full_path(db))?;
120 fmt_generic_args(&self.generic_args, &mut f, db)
121 }
122}
123impl ConcreteImplId {
124 pub fn impl_def_id(&self, db: &dyn SemanticGroup) -> ImplDefId {
125 self.lookup_intern(db).impl_def_id
126 }
127 pub fn get_impl_function(
128 &self,
129 db: &dyn SemanticGroup,
130 function: TraitFunctionId,
131 ) -> Maybe<Option<ImplFunctionId>> {
132 db.impl_function_by_trait_function(self.impl_def_id(db), function)
133 }
134 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
135 self.impl_def_id(db).name(db)
136 }
137 pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
138 format!("{:?}", self.debug(db.elongate()))
139 }
140 pub fn substitution(&self, db: &dyn SemanticGroup) -> Maybe<GenericSubstitution> {
141 Ok(GenericSubstitution::from_impl(ImplLongId::Concrete(*self).intern(db)).concat(
142 GenericSubstitution::new(
143 &db.impl_def_generic_params(self.impl_def_id(db))?,
144 &self.lookup_intern(db).generic_args,
145 ),
146 ))
147 }
148 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
150 self.lookup_intern(db)
151 .generic_args
152 .iter()
153 .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
154 }
155 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
157 self.lookup_intern(db)
158 .generic_args
159 .iter()
160 .all(|generic_argument_id| generic_argument_id.is_var_free(db))
161 }
162}
163
164#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
167pub enum ImplLongId {
168 Concrete(ConcreteImplId),
169 GenericParameter(GenericParamId),
170 ImplVar(ImplVarId),
171 ImplImpl(ImplImplId),
172 SelfImpl(ConcreteTraitId),
173 GeneratedImpl(GeneratedImplId),
174}
175impl ImplLongId {
176 pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
178 Some(match self {
179 ImplLongId::Concrete(concrete) => ImplHead::Concrete(concrete.impl_def_id(db)),
180 ImplLongId::GenericParameter(_)
181 | ImplLongId::ImplVar(_)
182 | ImplLongId::ImplImpl(_)
183 | ImplLongId::SelfImpl(_)
184 | ImplLongId::GeneratedImpl(_) => {
185 return None;
186 }
187 })
188 }
189 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
190 match self {
191 ImplLongId::Concrete(concrete_impl) => concrete_impl.name(db),
192 ImplLongId::GenericParameter(generic_param_impl) => {
193 generic_param_impl.name(db).unwrap_or_else(|| "_".into())
194 }
195 ImplLongId::ImplVar(var) => {
196 format!("ImplVar({})", var.concrete_trait_id(db).full_path(db)).into()
197 }
198 ImplLongId::ImplImpl(impl_impl) => format!(
199 "{}::{}",
200 impl_impl.impl_id().name(db),
201 db.impl_impl_concrete_trait(*impl_impl)
202 .map(|trait_impl| trait_impl.full_path(db))
203 .unwrap_or_else(|_| "_".into())
204 )
205 .into(),
206 ImplLongId::SelfImpl(trait_impl) => trait_impl.name(db),
207 ImplLongId::GeneratedImpl(generated_impl) => {
208 format!("{:?}", generated_impl.debug(db.elongate())).into()
209 }
210 }
211 }
212 pub fn format(&self, db: &dyn SemanticGroup) -> String {
213 match self {
214 ImplLongId::Concrete(concrete_impl) => {
215 format!("{:?}", concrete_impl.debug(db.elongate()))
216 }
217 ImplLongId::GenericParameter(generic_param_impl) => generic_param_impl.format(db),
218 ImplLongId::ImplVar(var) => format!("{var:?}"),
219 ImplLongId::ImplImpl(impl_impl) => format!("{:?}", impl_impl.debug(db.elongate())),
220 ImplLongId::SelfImpl(concrete_trait_id) => {
221 format!("{:?}", concrete_trait_id.debug(db.elongate()))
222 }
223 ImplLongId::GeneratedImpl(generated_impl) => {
224 format!("{:?}", generated_impl.debug(db.elongate()))
225 }
226 }
227 }
228
229 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
231 match self {
232 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
233 ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id.is_var_free(db),
234 ImplLongId::GenericParameter(_) => true,
235 ImplLongId::ImplVar(_) => false,
236 ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
237 ImplLongId::GeneratedImpl(generated_impl) => {
238 generated_impl.concrete_trait(db).is_var_free(db)
239 && generated_impl
240 .lookup_intern(db)
241 .impl_items
242 .0
243 .values()
244 .all(|type_id| type_id.is_var_free(db))
245 }
246 }
247 }
248
249 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
251 match self {
252 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
253 ImplLongId::GenericParameter(_) => false,
254 ImplLongId::ImplVar(_) => false,
255 ImplLongId::ImplImpl(_) | ImplLongId::SelfImpl(_) => false,
256 ImplLongId::GeneratedImpl(generated_impl) => {
257 generated_impl.concrete_trait(db).is_fully_concrete(db)
258 && generated_impl
259 .lookup_intern(db)
260 .impl_items
261 .0
262 .values()
263 .all(|type_id| type_id.is_fully_concrete(db))
264 }
265 }
266 }
267}
268impl DebugWithDb<dyn SemanticGroup> for ImplLongId {
269 fn fmt(
270 &self,
271 f: &mut std::fmt::Formatter<'_>,
272 db: &(dyn SemanticGroup + 'static),
273 ) -> std::fmt::Result {
274 match self {
275 ImplLongId::Concrete(concrete_impl_id) => write!(f, "{:?}", concrete_impl_id.debug(db)),
276 ImplLongId::GenericParameter(param) => write!(f, "{}", param.debug_name(db)),
277 ImplLongId::ImplVar(var) => write!(f, "?{}", var.lookup_intern(db).id.0),
278 ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
279 ImplLongId::SelfImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
280 ImplLongId::GeneratedImpl(generated_impl) => {
281 write!(f, "{:?}", generated_impl.debug(db))
282 }
283 }
284 }
285}
286
287define_short_id!(ImplId, ImplLongId, SemanticGroup, lookup_intern_impl, intern_impl);
288semantic_object_for_id!(ImplId, lookup_intern_impl, intern_impl, ImplLongId);
289impl ImplId {
290 pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
291 db.impl_concrete_trait(*self)
292 }
293
294 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
296 db.priv_impl_is_fully_concrete(*self)
297 }
298
299 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
301 db.priv_impl_is_var_free(*self)
302 }
303
304 pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
306 self.lookup_intern(db).head(db)
307 }
308
309 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
311 self.lookup_intern(db).name(db)
312 }
313
314 pub fn format(&self, db: &dyn SemanticGroup) -> String {
315 self.lookup_intern(db).format(db)
316 }
317}
318
319define_short_id!(
320 GeneratedImplId,
321 GeneratedImplLongId,
322 SemanticGroup,
323 lookup_intern_generated_impl,
324 intern_generated_impl
325);
326semantic_object_for_id!(
327 GeneratedImplId,
328 lookup_intern_generated_impl,
329 intern_generated_impl,
330 GeneratedImplLongId
331);
332
333impl GeneratedImplId {
334 pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
335 db.lookup_intern_generated_impl(self).concrete_trait
336 }
337
338 pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
339 self.concrete_trait(db).trait_id(db)
340 }
341}
342
343#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
347pub struct GeneratedImplLongId {
348 pub concrete_trait: ConcreteTraitId,
349 pub generic_params: Vec<GenericParam>,
352 pub impl_items: GeneratedImplItems,
353}
354#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, SemanticObject)]
355pub struct GeneratedImplItems(pub OrderedHashMap<TraitTypeId, TypeId>);
356
357pub enum GeneratedImplAssociatedTypes {
358 Unresolved,
360 Resolved(OrderedHashMap<TraitTypeId, TypeId>),
362}
363
364impl DebugWithDb<dyn SemanticGroup> for GeneratedImplLongId {
365 fn fmt(
366 &self,
367 f: &mut std::fmt::Formatter<'_>,
368 db: &(dyn SemanticGroup + 'static),
369 ) -> std::fmt::Result {
370 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
371 }
372}
373
374#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
376pub struct ImplImplId {
377 impl_id: ImplId,
379 trait_impl_id: TraitImplId,
381}
382
383impl ImplImplId {
384 pub fn new(impl_id: ImplId, trait_impl_id: TraitImplId, db: &dyn SemanticGroup) -> Self {
387 if let crate::items::imp::ImplLongId::Concrete(concrete_impl) = impl_id.lookup_intern(db) {
388 let impl_def_id = concrete_impl.impl_def_id(db);
389 assert_eq!(Ok(trait_impl_id.trait_id(db)), db.impl_def_trait(impl_def_id));
390 }
391
392 ImplImplId { impl_id, trait_impl_id }
393 }
394 pub fn impl_id(&self) -> ImplId {
395 self.impl_id
396 }
397 pub fn trait_impl_id(&self) -> TraitImplId {
398 self.trait_impl_id
399 }
400
401 pub fn concrete_trait_impl_id(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitImplId> {
402 Ok(ConcreteTraitImplId::new(db, self.impl_id.concrete_trait(db)?, self.trait_impl_id))
403 }
404
405 pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
406 format!("{:?}", self.debug(db.elongate()))
407 }
408}
409impl DebugWithDb<dyn SemanticGroup> for ImplImplId {
410 fn fmt(
411 &self,
412 f: &mut std::fmt::Formatter<'_>,
413 db: &(dyn SemanticGroup + 'static),
414 ) -> std::fmt::Result {
415 write!(f, "{:?}::{}", self.impl_id.debug(db), self.trait_impl_id.name(db))
416 }
417}
418
419impl UnstableSalsaId for ImplId {
420 fn get_internal_id(&self) -> &salsa::InternId {
421 &self.0
422 }
423}
424
425#[derive(Clone, Debug, Hash, PartialEq, Eq)]
431pub enum ImplHead {
432 Concrete(ImplDefId),
433}
434
435#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
438#[debug_db(dyn SemanticGroup + 'static)]
439pub struct ImplDeclarationData {
440 diagnostics: Diagnostics<SemanticDiagnostic>,
441 generic_params: Vec<semantic::GenericParam>,
442 concrete_trait: Maybe<ConcreteTraitId>,
444 attributes: Vec<Attribute>,
445 resolver_data: Arc<ResolverData>,
446}
447
448pub fn impl_semantic_declaration_diagnostics(
452 db: &dyn SemanticGroup,
453 impl_def_id: ImplDefId,
454) -> Diagnostics<SemanticDiagnostic> {
455 db.priv_impl_declaration_data(impl_def_id).map(|data| data.diagnostics).unwrap_or_default()
456}
457
458pub fn impl_def_generic_params_data(
460 db: &dyn SemanticGroup,
461 impl_def_id: ImplDefId,
462) -> Maybe<GenericParamsData> {
463 let module_file_id = impl_def_id.module_file_id(db);
464 let mut diagnostics = SemanticDiagnostics::default();
465
466 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
467 let inference_id =
468 InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
469
470 let mut resolver = Resolver::new(db, module_file_id, inference_id);
471 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
472 let generic_params = semantic_generic_params(
473 db,
474 &mut diagnostics,
475 &mut resolver,
476 module_file_id,
477 &impl_ast.generic_params(db),
478 );
479 let inference = &mut resolver.inference();
480 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
481
482 let generic_params = inference.rewrite(generic_params).no_err();
483 let resolver_data = Arc::new(resolver.data);
484 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
485}
486
487pub fn impl_def_generic_params(
489 db: &dyn SemanticGroup,
490 impl_def_id: ImplDefId,
491) -> Maybe<Vec<semantic::GenericParam>> {
492 Ok(db.impl_def_generic_params_data(impl_def_id)?.generic_params)
493}
494
495pub fn impl_def_resolver_data(
497 db: &dyn SemanticGroup,
498 impl_def_id: ImplDefId,
499) -> Maybe<Arc<ResolverData>> {
500 Ok(db.priv_impl_declaration_data(impl_def_id)?.resolver_data)
501}
502
503pub fn impl_def_resolver_data_cycle(
505 db: &dyn SemanticGroup,
506 _cycle: &salsa::Cycle,
507 impl_def_id: &ImplDefId,
508) -> Maybe<Arc<ResolverData>> {
509 impl_def_resolver_data(db, *impl_def_id)
511}
512
513pub fn impl_def_concrete_trait(
515 db: &dyn SemanticGroup,
516 impl_def_id: ImplDefId,
517) -> Maybe<ConcreteTraitId> {
518 db.priv_impl_declaration_data(impl_def_id)?.concrete_trait
519}
520
521pub fn impl_def_concrete_trait_cycle(
523 db: &dyn SemanticGroup,
524 _cycle: &salsa::Cycle,
525 impl_def_id: &ImplDefId,
526) -> Maybe<ConcreteTraitId> {
527 impl_def_concrete_trait(db, *impl_def_id)
529}
530
531pub fn impl_def_substitution(
533 db: &dyn SemanticGroup,
534 impl_def_id: ImplDefId,
535) -> Maybe<Arc<GenericSubstitution>> {
536 let params = db.impl_def_generic_params(impl_def_id)?;
537 let generic_args = generic_params_to_args(¶ms, db);
538 Ok(Arc::new(ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)?))
539}
540
541pub fn impl_def_attributes(
543 db: &dyn SemanticGroup,
544 impl_def_id: ImplDefId,
545) -> Maybe<Vec<Attribute>> {
546 Ok(db.priv_impl_declaration_data(impl_def_id)?.attributes)
547}
548
549pub fn impl_def_trait(db: &dyn SemanticGroup, impl_def_id: ImplDefId) -> Maybe<TraitId> {
551 let module_file_id = impl_def_id.module_file_id(db);
552 let mut diagnostics = SemanticDiagnostics::default();
553
554 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
555 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
556
557 let mut resolver = Resolver::new(db, module_file_id, inference_id);
558 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
559
560 let trait_path_syntax = impl_ast.trait_path(db);
561
562 resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path_syntax)
563}
564
565pub fn impl_concrete_trait(db: &dyn SemanticGroup, impl_id: ImplId) -> Maybe<ConcreteTraitId> {
567 match impl_id.lookup_intern(db) {
568 ImplLongId::Concrete(concrete_impl_id) => {
569 let long_impl = concrete_impl_id.lookup_intern(db);
570 let substitution = GenericSubstitution::new(
571 &db.impl_def_generic_params(long_impl.impl_def_id)?,
572 &long_impl.generic_args,
573 );
574
575 let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
576 substitution.substitute(db, impl_concrete_trait_id)
577 }
578 ImplLongId::GenericParameter(param) => {
579 let param_impl =
580 extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
581 param_impl.concrete_trait
582 }
583 ImplLongId::ImplVar(var) => Ok(var.lookup_intern(db).concrete_trait_id),
584 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl),
585 ImplLongId::SelfImpl(concrete_trait_id) => Ok(concrete_trait_id),
586 ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
587 }
588}
589
590pub fn priv_impl_declaration_data_cycle(
594 db: &dyn SemanticGroup,
595 _cycle: &salsa::Cycle,
596 impl_def_id: &ImplDefId,
597) -> Maybe<ImplDeclarationData> {
598 priv_impl_declaration_data_inner(db, *impl_def_id, false)
599}
600
601pub fn priv_impl_declaration_data(
603 db: &dyn SemanticGroup,
604 impl_def_id: ImplDefId,
605) -> Maybe<ImplDeclarationData> {
606 priv_impl_declaration_data_inner(db, impl_def_id, true)
607}
608
609pub fn priv_impl_declaration_data_inner(
612 db: &dyn SemanticGroup,
613 impl_def_id: ImplDefId,
614 resolve_trait: bool,
615) -> Maybe<ImplDeclarationData> {
616 let mut diagnostics = SemanticDiagnostics::default();
617
618 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
622 let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
623 ModuleItemId::Impl(impl_def_id),
624 ));
625
626 let generic_params_data = db.impl_def_generic_params_data(impl_def_id)?;
628 let generic_params = generic_params_data.generic_params;
629 let mut resolver = Resolver::with_data(
630 db,
631 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
632 );
633 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
634 diagnostics.extend(generic_params_data.diagnostics);
635 let trait_path_syntax = impl_ast.trait_path(db);
636
637 let concrete_trait = if resolve_trait {
638 resolver
639 .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
640 .and_then(|resolved_item| match resolved_item {
641 ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
642 _ => Err(diagnostics
643 .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
644 })
645 } else {
646 Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
647 };
648
649 let info = db.core_info();
650
651 if let Ok(concrete_trait) = concrete_trait {
653 if [
654 info.type_eq_trt,
655 info.fn_trt,
656 info.fn_once_trt,
657 info.felt252_dict_value_trt,
658 info.numeric_literal_trt,
659 info.string_literal_trt,
660 ]
661 .contains(&concrete_trait.trait_id(db))
662 && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
663 {
664 diagnostics.report(
665 trait_path_syntax.stable_ptr(db),
666 CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
667 );
668 }
669 }
670
671 let inference = &mut resolver.inference();
673 inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
674
675 let concrete_trait: Result<ConcreteTraitId, DiagnosticAdded> =
676 inference.rewrite(concrete_trait).no_err();
677 let generic_params: Vec<GenericParam> = inference.rewrite(generic_params).no_err();
678
679 let attributes = impl_ast.attributes(db).structurize(db);
680 let mut resolver_data = resolver.data;
681 resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
682 Ok(ImplDeclarationData {
683 diagnostics: diagnostics.build(),
684 generic_params,
685 concrete_trait,
686 attributes,
687 resolver_data: Arc::new(resolver_data),
688 })
689}
690
691#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
694#[debug_db(dyn SemanticGroup + 'static)]
695pub struct ImplDefinitionData {
696 diagnostics: Diagnostics<SemanticDiagnostic>,
701
702 function_asts: OrderedHashMap<ImplFunctionId, ast::FunctionWithBody>,
704 item_type_asts: Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>,
705 item_constant_asts: Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>,
706 item_impl_asts: Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>,
707
708 item_id_by_name: Arc<OrderedHashMap<SmolStr, ImplItemInfo>>,
711
712 implicit_impls_id_by_name: Arc<OrderedHashMap<SmolStr, TraitImplId>>,
714}
715
716impl ImplDefinitionData {
717 pub fn get_impl_item_info(&self, item_name: &SmolStr) -> Option<ImplItemInfo> {
719 self.item_id_by_name.get(item_name).cloned()
720 }
721}
722#[derive(Clone, Debug, PartialEq, Eq)]
724pub struct ImplItemInfo {
725 pub id: ImplItemId,
727 pub feature_kind: FeatureKind,
729}
730
731impl HasFeatureKind for ImplItemInfo {
732 fn feature_kind(&self) -> &FeatureKind {
734 &self.feature_kind
735 }
736}
737
738pub fn impl_semantic_definition_diagnostics(
742 db: &dyn SemanticGroup,
743 impl_def_id: ImplDefId,
744) -> Diagnostics<SemanticDiagnostic> {
745 let mut diagnostics = DiagnosticsBuilder::default();
746
747 let Ok(data) = db.priv_impl_definition_data(impl_def_id) else {
748 return Diagnostics::default();
749 };
750
751 diagnostics.extend(data.diagnostics);
754 for impl_function_id in data.function_asts.keys() {
755 diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
756 diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
757 }
758 for impl_item_type_id in data.item_type_asts.keys() {
759 diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
760 if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
761 add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
762 }
763 }
764 for impl_item_constant_id in data.item_constant_asts.keys() {
765 diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
766 }
767 for impl_item_impl_id in data.item_impl_asts.keys() {
768 diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
769 }
770 for implicit_impl_id in data.implicit_impls_id_by_name.values() {
771 diagnostics
772 .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
773 }
774 if diagnostics.error_count == 0 {
776 let concrete_trait =
777 db.priv_impl_declaration_data(impl_def_id).unwrap().concrete_trait.unwrap();
778
779 let trait_id = concrete_trait.trait_id(db);
780 if trait_id == db.core_info().deref_trt {
781 deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
782 }
783 }
784 diagnostics.build()
785}
786
787#[derive(Clone, Debug, Eq, PartialEq)]
789pub struct DerefChain {
790 pub derefs: Arc<[DerefInfo]>,
791}
792
793#[derive(Clone, Debug, Eq, PartialEq)]
795pub struct DerefInfo {
796 pub function_id: FunctionId,
798 pub self_mutability: Mutability,
800 pub target_ty: TypeId,
802}
803
804pub fn deref_chain_cycle(
806 _db: &dyn SemanticGroup,
807 _cycle: &salsa::Cycle,
808 _ty: &TypeId,
809 _try_deref_mut: &bool,
810) -> Maybe<DerefChain> {
811 Maybe::Err(skip_diagnostic())
813}
814
815pub fn deref_chain(db: &dyn SemanticGroup, ty: TypeId, try_deref_mut: bool) -> Maybe<DerefChain> {
817 let mut opt_deref = None;
818 if try_deref_mut {
819 opt_deref = try_get_deref_func_and_target(db, ty, true)?;
820 }
821 let self_mutability = if opt_deref.is_some() {
822 Mutability::Reference
823 } else {
824 opt_deref = try_get_deref_func_and_target(db, ty, false)?;
825 Mutability::Immutable
826 };
827
828 let Some((function_id, target_ty)) = opt_deref else {
829 return Ok(DerefChain { derefs: Arc::new([]) });
830 };
831
832 let inner_chain = db.deref_chain(target_ty, false)?;
833
834 Ok(DerefChain {
835 derefs: chain!(
836 [DerefInfo { function_id, target_ty, self_mutability }],
837 inner_chain.derefs.iter().cloned()
838 )
839 .collect(),
840 })
841}
842
843fn try_get_deref_func_and_target(
845 db: &dyn SemanticGroup,
846 ty: TypeId,
847 is_mut_deref: bool,
848) -> Result<Option<(FunctionId, TypeId)>, DiagnosticAdded> {
849 let info = db.core_info();
850 let (deref_trait_id, deref_method) = if is_mut_deref {
851 (info.deref_mut_trt, info.deref_mut_fn)
852 } else {
853 (info.deref_trt, info.deref_fn)
854 };
855
856 let mut lookup_context = ImplLookupContext::new(deref_trait_id.module_file_id(db).0, vec![]);
857 enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
858 let concrete_trait = ConcreteTraitLongId {
859 trait_id: deref_trait_id,
860 generic_args: vec![GenericArgumentId::Type(ty)],
861 }
862 .intern(db);
863 let Ok(deref_impl) = get_impl_at_context(db, lookup_context, concrete_trait, None) else {
864 return Ok(None);
865 };
866 let concrete_impl_id = match deref_impl.lookup_intern(db) {
867 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id,
868 _ => panic!("Expected concrete impl"),
869 };
870
871 let function_id = FunctionLongId {
872 function: ConcreteFunction {
873 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
874 impl_id: deref_impl,
875 function: deref_method,
876 }),
877 generic_args: vec![],
878 },
879 }
880 .intern(db);
881
882 let data = db.priv_impl_definition_data(concrete_impl_id.impl_def_id(db)).unwrap();
883 let mut types_iter = data.item_type_asts.iter();
884 let (impl_item_type_id, _) = types_iter.next().unwrap();
885 if types_iter.next().is_some() {
886 panic!(
887 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
888 );
889 }
890 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
891 let ty = concrete_impl_id.substitution(db)?.substitute(db, ty).unwrap();
892
893 Ok(Some((function_id, ty)))
894}
895
896fn deref_impl_diagnostics(
898 db: &dyn SemanticGroup,
899 mut impl_def_id: ImplDefId,
900 concrete_trait: ConcreteTraitId,
901 diagnostics: &mut DiagnosticsBuilder<SemanticDiagnostic>,
902) {
903 let mut visited_impls: OrderedHashSet<ImplDefId> = OrderedHashSet::default();
904 let deref_trait_id = concrete_trait.trait_id(db);
905
906 let impl_module = impl_def_id.module_file_id(db).0;
907
908 let mut impl_in_valid_location = false;
909 if impl_module == deref_trait_id.module_file_id(db).0 {
910 impl_in_valid_location = true;
911 }
912
913 let gargs = concrete_trait.generic_args(db);
914 let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
915 if let Some(module_id) = deref_ty.lookup_intern(db).module_id(db) {
916 if module_id == impl_module {
917 impl_in_valid_location = true;
918 }
919 }
920
921 if !impl_in_valid_location {
922 diagnostics.report(
923 impl_def_id.stable_ptr(db),
924 SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
925 );
926 return;
927 }
928
929 loop {
930 let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
931 ConcreteTraitLongId {
932 trait_id: deref_trait_id,
933 generic_args: vec![GenericArgumentId::Type(ty)],
934 }
935 .intern(db)
936 }) else {
937 return;
940 };
941
942 impl_def_id = match impl_id.lookup_intern(db) {
943 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
944 _ => return,
945 };
946
947 if !visited_impls.insert(impl_def_id) {
948 let deref_chain = visited_impls
949 .iter()
950 .map(|visited_impl| {
951 format!(
952 "{:?}",
953 db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db.elongate())
954 )
955 })
956 .join(" -> ");
957 diagnostics.report(
958 impl_def_id.stable_ptr(db),
959 SemanticDiagnosticKind::DerefCycle { deref_chain },
960 );
961 return;
962 }
963 }
964}
965
966fn get_impl_based_on_single_impl_type(
970 db: &dyn SemanticGroup,
971 impl_def_id: ImplDefId,
972 concrete_trait_id: impl FnOnce(TypeId) -> ConcreteTraitId,
973) -> Result<ImplId, (InferenceError, ImplTypeDefId)> {
974 let data = db.priv_impl_definition_data(impl_def_id).unwrap();
975 let mut types_iter = data.item_type_asts.iter();
976 let (impl_item_type_id, _) = types_iter.next().unwrap();
977 if types_iter.next().is_some() {
978 panic!(
979 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
980 );
981 }
982 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
983
984 let module_file_id = impl_def_id.module_file_id(db);
985 let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
986 let generic_params_ids =
987 generic_params.iter().map(|generic_param| generic_param.id()).collect();
988 let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
989 get_impl_at_context(db, lookup_context, concrete_trait_id(ty), None)
990 .map_err(|err| (err, *impl_item_type_id))
991}
992
993pub fn impl_functions(
995 db: &dyn SemanticGroup,
996 impl_def_id: ImplDefId,
997) -> Maybe<OrderedHashMap<SmolStr, ImplFunctionId>> {
998 Ok(db
999 .priv_impl_definition_data(impl_def_id)?
1000 .function_asts
1001 .keys()
1002 .map(|function_id| {
1003 let function_long_id = function_id.lookup_intern(db);
1004 (function_long_id.name(db), *function_id)
1005 })
1006 .collect())
1007}
1008
1009pub fn impl_function_by_trait_function(
1011 db: &dyn SemanticGroup,
1012 impl_def_id: ImplDefId,
1013 trait_function_id: TraitFunctionId,
1014) -> Maybe<Option<ImplFunctionId>> {
1015 let name = trait_function_id.name(db);
1016 for impl_function_id in db.priv_impl_definition_data(impl_def_id)?.function_asts.keys() {
1017 if impl_function_id.lookup_intern(db).name(db) == name {
1018 return Ok(Some(*impl_function_id));
1019 }
1020 }
1021 Ok(None)
1022}
1023
1024pub fn impl_item_by_name(
1026 db: &dyn SemanticGroup,
1027 impl_def_id: ImplDefId,
1028 name: SmolStr,
1029) -> Maybe<Option<ImplItemId>> {
1030 Ok(db.priv_impl_definition_data(impl_def_id)?.item_id_by_name.get(&name).map(|info| info.id))
1031}
1032
1033pub fn impl_item_info_by_name(
1035 db: &dyn SemanticGroup,
1036 impl_def_id: ImplDefId,
1037 name: SmolStr,
1038) -> Maybe<Option<ImplItemInfo>> {
1039 let impl_definition_data = db.priv_impl_definition_data(impl_def_id)?;
1040 Ok(impl_definition_data.get_impl_item_info(&name))
1041}
1042
1043pub fn impl_implicit_impl_by_name(
1045 db: &dyn SemanticGroup,
1046 impl_def_id: ImplDefId,
1047 name: SmolStr,
1048) -> Maybe<Option<TraitImplId>> {
1049 Ok(db.priv_impl_definition_data(impl_def_id)?.implicit_impls_id_by_name.get(&name).cloned())
1050}
1051
1052pub fn impl_all_used_uses(
1054 db: &dyn SemanticGroup,
1055 impl_def_id: ImplDefId,
1056) -> Maybe<Arc<OrderedHashSet<UseId>>> {
1057 let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1058 let data = db.priv_impl_definition_data(impl_def_id)?;
1059 for item in data.item_id_by_name.values() {
1060 for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1061 all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1062 }
1063 }
1064 Ok(all_used_uses.into())
1065}
1066
1067pub fn impl_types(
1069 db: &dyn SemanticGroup,
1070 impl_def_id: ImplDefId,
1071) -> Maybe<Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>> {
1072 Ok(db.priv_impl_definition_data(impl_def_id)?.item_type_asts)
1073}
1074
1075pub fn impl_type_ids(
1077 db: &dyn SemanticGroup,
1078 impl_def_id: ImplDefId,
1079) -> Maybe<Arc<[ImplTypeDefId]>> {
1080 Ok(db.impl_types(impl_def_id)?.keys().copied().collect_vec().into())
1081}
1082
1083pub fn impl_type_by_id(
1085 db: &dyn SemanticGroup,
1086 impl_type_id: ImplTypeDefId,
1087) -> Maybe<Option<ast::ItemTypeAlias>> {
1088 let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1089 Ok(impl_types.get(&impl_type_id).cloned())
1090}
1091
1092pub fn impl_type_by_trait_type(
1094 db: &dyn SemanticGroup,
1095 impl_def_id: ImplDefId,
1096 trait_type_id: TraitTypeId,
1097) -> Maybe<ImplTypeDefId> {
1098 if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1099 unreachable!(
1100 "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1101 trait"
1102 )
1103 }
1104
1105 let name = trait_type_id.name(db);
1106 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1108 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
1109 None => Err(skip_diagnostic()),
1110 })
1111}
1112
1113pub fn impl_constants(
1115 db: &dyn SemanticGroup,
1116 impl_def_id: ImplDefId,
1117) -> Maybe<Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>> {
1118 Ok(db.priv_impl_definition_data(impl_def_id)?.item_constant_asts)
1119}
1120
1121pub fn impl_constant_by_trait_constant(
1123 db: &dyn SemanticGroup,
1124 impl_def_id: ImplDefId,
1125 trait_constant_id: TraitConstantId,
1126) -> Maybe<ImplConstantDefId> {
1127 if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1128 unreachable!(
1129 "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1130 the impl's trait"
1131 )
1132 }
1133
1134 let name = trait_constant_id.name(db);
1135 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1137 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
1138 None => Err(skip_diagnostic()),
1139 })
1140}
1141
1142pub fn impl_impls(
1144 db: &dyn SemanticGroup,
1145 impl_def_id: ImplDefId,
1146) -> Maybe<Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>> {
1147 Ok(db.priv_impl_definition_data(impl_def_id)?.item_impl_asts)
1148}
1149
1150pub fn impl_impl_ids(
1152 db: &dyn SemanticGroup,
1153 impl_def_id: ImplDefId,
1154) -> Maybe<Arc<[ImplImplDefId]>> {
1155 Ok(db.impl_impls(impl_def_id)?.keys().copied().collect_vec().into())
1156}
1157
1158pub fn impl_impl_by_id(
1160 db: &dyn SemanticGroup,
1161 impl_impl_id: ImplImplDefId,
1162) -> Maybe<Option<ast::ItemImplAlias>> {
1163 let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1164 Ok(impl_impls.get(&impl_impl_id).cloned())
1165}
1166
1167pub fn impl_impl_by_trait_impl(
1169 db: &dyn SemanticGroup,
1170 impl_def_id: ImplDefId,
1171 trait_impl_id: TraitImplId,
1172) -> Maybe<ImplImplDefId> {
1173 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1174 unreachable!(
1175 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1176 trait"
1177 )
1178 }
1179
1180 let name = trait_impl_id.name(db);
1181 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1183 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1184 None => Err(skip_diagnostic()),
1185 })
1186}
1187
1188pub fn is_implicit_impl_impl(
1190 db: &dyn SemanticGroup,
1191 impl_def_id: ImplDefId,
1192 trait_impl_id: TraitImplId,
1193) -> Maybe<bool> {
1194 if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1195 unreachable!(
1196 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1197 trait"
1198 )
1199 }
1200
1201 let name = trait_impl_id.name(db);
1202 Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1204}
1205
1206pub fn priv_impl_definition_data(
1210 db: &dyn SemanticGroup,
1211 impl_def_id: ImplDefId,
1212) -> Maybe<ImplDefinitionData> {
1213 let module_file_id = impl_def_id.module_file_id(db);
1214 let mut diagnostics = SemanticDiagnostics::default();
1215
1216 let generic_params = db.impl_def_generic_params(impl_def_id)?;
1217 let concrete_trait = db.priv_impl_declaration_data(impl_def_id)?.concrete_trait?;
1218
1219 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
1220
1221 let generic_params_ids =
1222 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1223 let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
1224 check_special_impls(
1225 db,
1226 &mut diagnostics,
1227 lookup_context,
1228 concrete_trait,
1229 impl_ast.stable_ptr(db).untyped(),
1230 )
1231 .ok();
1233
1234 let mut function_asts = OrderedHashMap::default();
1235 let mut item_type_asts = OrderedHashMap::default();
1236 let mut item_constant_asts = OrderedHashMap::default();
1237 let mut item_impl_asts = OrderedHashMap::default();
1238 let mut item_id_by_name: OrderedHashMap<SmolStr, ImplItemInfo> = OrderedHashMap::default();
1239
1240 if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1241 for item in body.items(db).elements(db) {
1242 match item {
1243 ImplItem::Module(module) => {
1244 report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1245 }
1246
1247 ImplItem::Use(use_item) => {
1248 report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1249 }
1250 ImplItem::ExternFunction(extern_func) => {
1251 report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1252 }
1253 ImplItem::ExternType(extern_type) => {
1254 report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1255 }
1256 ImplItem::Trait(trt) => {
1257 report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1258 }
1259 ImplItem::Struct(structure) => {
1260 report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1261 }
1262 ImplItem::Enum(enm) => {
1263 report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1264 }
1265 ImplItem::Function(func) => {
1266 let impl_function_id =
1267 ImplFunctionLongId(module_file_id, func.stable_ptr(db)).intern(db);
1268 let name_node = func.declaration(db).name(db);
1269 let name = name_node.text(db);
1270 let feature_kind =
1271 FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1272 if item_id_by_name
1273 .insert(
1274 name.clone(),
1275 ImplItemInfo {
1276 id: ImplItemId::Function(impl_function_id),
1277 feature_kind,
1278 },
1279 )
1280 .is_some()
1281 {
1282 diagnostics
1283 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1284 }
1285 function_asts.insert(impl_function_id, func);
1286 }
1287 ImplItem::Type(ty) => {
1288 let impl_type_id =
1289 ImplTypeDefLongId(module_file_id, ty.stable_ptr(db)).intern(db);
1290 let name_node = ty.name(db);
1291 let name = name_node.text(db);
1292 let feature_kind =
1293 FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1294 if item_id_by_name
1295 .insert(
1296 name.clone(),
1297 ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1298 )
1299 .is_some()
1300 {
1301 diagnostics
1302 .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1303 }
1304 item_type_asts.insert(impl_type_id, ty);
1305 }
1306 ImplItem::Constant(constant) => {
1307 let impl_constant_id =
1308 ImplConstantDefLongId(module_file_id, constant.stable_ptr(db)).intern(db);
1309 let name_node = constant.name(db);
1310 let name = name_node.text(db);
1311 let feature_kind =
1312 FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1313 if item_id_by_name
1314 .insert(
1315 name.clone(),
1316 ImplItemInfo {
1317 id: ImplItemId::Constant(impl_constant_id),
1318 feature_kind,
1319 },
1320 )
1321 .is_some()
1322 {
1323 diagnostics.report(
1324 name_node.stable_ptr(db),
1325 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1326 );
1327 }
1328 item_constant_asts.insert(impl_constant_id, constant);
1329 }
1330 ImplItem::Impl(imp) => {
1331 let impl_impl_id =
1332 ImplImplDefLongId(module_file_id, imp.stable_ptr(db)).intern(db);
1333 let name_node = imp.name(db);
1334 let name = name_node.text(db);
1335 let feature_kind =
1336 FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1337 if item_id_by_name
1338 .insert(
1339 name.clone(),
1340 ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1341 )
1342 .is_some()
1343 {
1344 diagnostics.report(
1345 name_node.stable_ptr(db),
1346 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1347 );
1348 }
1349 item_impl_asts.insert(impl_impl_id, imp);
1350 }
1351 ImplItem::Missing(_) => {}
1353 }
1354 }
1355 }
1356
1357 let mut implicit_impls_id_by_name = OrderedHashMap::default();
1358
1359 let trait_id = concrete_trait.lookup_intern(db).trait_id;
1360 for trait_impl_id in db.trait_impls(trait_id)? {
1361 if item_id_by_name.contains_key(&trait_impl_id.0) {
1362 continue;
1363 }
1364 implicit_impls_id_by_name.insert(trait_impl_id.0, trait_impl_id.1);
1365 }
1366
1367 let impl_item_names: OrderedHashSet<SmolStr> = item_id_by_name.keys().cloned().collect();
1371
1372 let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1373 let missing_items_in_impl =
1374 trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1375 if !missing_items_in_impl.is_empty() {
1376 diagnostics.report(
1377 impl_ast.name(db).stable_ptr(db),
1382 SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1383 );
1384 }
1385
1386 Ok(ImplDefinitionData {
1387 diagnostics: diagnostics.build(),
1388 function_asts,
1389 item_type_asts: item_type_asts.into(),
1390 item_id_by_name: item_id_by_name.into(),
1391 item_constant_asts: item_constant_asts.into(),
1392 item_impl_asts: item_impl_asts.into(),
1393 implicit_impls_id_by_name: implicit_impls_id_by_name.into(),
1394 })
1395}
1396
1397fn report_invalid_impl_item<Terminal: syntax::node::Terminal>(
1400 db: &dyn SyntaxGroup,
1401 diagnostics: &mut SemanticDiagnostics,
1402 kw_terminal: Terminal,
1403) {
1404 diagnostics
1405 .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1406}
1407
1408fn check_special_impls(
1410 db: &dyn SemanticGroup,
1411 diagnostics: &mut SemanticDiagnostics,
1412 lookup_context: ImplLookupContext,
1413 concrete_trait: ConcreteTraitId,
1414 stable_ptr: SyntaxStablePtrId,
1415) -> Maybe<()> {
1416 let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.lookup_intern(db);
1417 let info = db.core_info();
1418 let copy = info.copy_trt;
1419 let drop = info.drop_trt;
1420
1421 if trait_id == copy {
1422 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1423 for inference_error in tys
1424 .into_iter()
1425 .map(|ty| db.type_info(lookup_context.clone(), ty))
1426 .flat_map(|info| info.copyable.err())
1427 {
1428 if matches!(
1429 inference_error,
1430 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1431 ) {
1432 continue;
1434 }
1435 return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1436 }
1437 }
1438 if trait_id == drop {
1439 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1440 for inference_error in tys
1441 .into_iter()
1442 .map(|ty| db.type_info(lookup_context.clone(), ty))
1443 .flat_map(|info| info.droppable.err())
1444 {
1445 if matches!(
1446 inference_error,
1447 InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1448 ) {
1449 continue;
1451 }
1452 return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1453 }
1454 }
1455
1456 Ok(())
1457}
1458
1459fn get_inner_types(db: &dyn SemanticGroup, ty: TypeId) -> Maybe<Vec<TypeId>> {
1466 Ok(match ty.lookup_intern(db) {
1467 TypeLongId::Concrete(concrete_type_id) => {
1468 match concrete_type_id {
1470 crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1471 .concrete_struct_members(concrete_struct_id)?
1472 .values()
1473 .map(|member| member.ty)
1474 .collect(),
1475 crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1476 .concrete_enum_variants(concrete_enum_id)?
1477 .into_iter()
1478 .map(|variant| variant.ty)
1479 .collect(),
1480 crate::ConcreteTypeId::Extern(_) => vec![],
1481 }
1482 }
1483 TypeLongId::Tuple(tys) => tys,
1484 TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1485 TypeLongId::GenericParameter(_) => {
1486 return Err(skip_diagnostic());
1487 }
1488 TypeLongId::Var(_) | TypeLongId::ImplType(_) => {
1489 panic!("Types should be fully resolved at this point.")
1490 }
1491 TypeLongId::Coupon(_) => vec![],
1492 TypeLongId::FixedSizeArray { type_id, .. } => vec![type_id],
1493 TypeLongId::Missing(diag_added) => {
1494 return Err(diag_added);
1495 }
1496 })
1497}
1498
1499#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1504pub struct TraitFilter {
1505 pub trait_id: TraitId,
1506 pub generics_filter: GenericsHeadFilter,
1508}
1509
1510#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1513pub enum GenericsHeadFilter {
1514 NoFilter,
1517 FirstGenericFilter(GenericArgumentHead),
1520 NoGenerics,
1522}
1523
1524pub fn module_impl_ids_for_trait_filter(
1526 db: &dyn SemanticGroup,
1527 module_id: ModuleId,
1528 trait_filter: TraitFilter,
1529) -> Maybe<Vec<UninferredImpl>> {
1530 let mut uninferred_impls: OrderedHashSet<UninferredImpl> =
1532 OrderedHashSet::from_iter(module_impl_ids(db, module_id, module_id)?);
1533 for (user_module, containing_module) in &db.priv_module_use_star_modules(module_id).accessible {
1534 if let Ok(star_module_uninferred_impls) =
1535 module_impl_ids(db, *user_module, *containing_module)
1536 {
1537 uninferred_impls.extend(star_module_uninferred_impls);
1538 }
1539 }
1540 let mut res = Vec::new();
1541 for uninferred_impl in uninferred_impls {
1542 let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1543 if trait_id != trait_filter.trait_id {
1544 continue;
1545 }
1546 let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1547 continue;
1548 };
1549 if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1550 res.push(uninferred_impl);
1551 }
1552 }
1553 Ok(res)
1554}
1555
1556fn module_impl_ids(
1558 db: &dyn SemanticGroup,
1559 user_module: ModuleId,
1560 containing_module: ModuleId,
1561) -> Maybe<Vec<UninferredImpl>> {
1562 let mut uninferred_impls = Vec::new();
1563 for item in db.priv_module_semantic_data(containing_module)?.items.values() {
1564 if !matches!(
1565 item.item_id,
1566 ModuleItemId::Impl(_) | ModuleItemId::ImplAlias(_) | ModuleItemId::Use(_)
1567 ) {
1568 continue;
1569 }
1570 if !peek_visible_in(db, item.visibility, containing_module, user_module) {
1571 continue;
1572 }
1573 match item.item_id {
1574 ModuleItemId::Impl(impl_def_id) => {
1575 uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1576 }
1577 ModuleItemId::ImplAlias(impl_alias_id) => {
1578 uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1579 }
1580 ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
1581 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
1582 uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1583 }
1584 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
1585 uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1586 }
1587 _ => {}
1588 },
1589 _ => {}
1590 }
1591 }
1592 Ok(uninferred_impls)
1593}
1594
1595pub fn module_impl_ids_for_trait_filter_cycle(
1597 _db: &dyn SemanticGroup,
1598 _cycle: &salsa::Cycle,
1599 _module_id: &ModuleId,
1600 _trait_filter: &TraitFilter,
1601) -> Maybe<Vec<UninferredImpl>> {
1602 Err(skip_diagnostic())
1605}
1606
1607pub fn impl_impl_ids_for_trait_filter(
1609 db: &dyn SemanticGroup,
1610 impl_id: ImplId,
1611 trait_filter: TraitFilter,
1612) -> Maybe<Vec<UninferredImpl>> {
1613 let mut uninferred_impls = Vec::new();
1614 for (_, trait_impl_id) in db.trait_impls(impl_id.concrete_trait(db)?.trait_id(db))?.iter() {
1615 uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1616 impl_id,
1617 *trait_impl_id,
1618 db,
1619 )));
1620 }
1621 let mut res = Vec::new();
1622 for uninferred_impl in uninferred_impls {
1623 let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1624 if trait_id != trait_filter.trait_id {
1625 continue;
1626 }
1627 let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1628 continue;
1629 };
1630 if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1631 res.push(uninferred_impl);
1632 }
1633 }
1634
1635 Ok(res)
1636}
1637pub fn impl_impl_ids_for_trait_filter_cycle(
1639 _db: &dyn SemanticGroup,
1640 _cycle: &salsa::Cycle,
1641 _imp: &ImplId,
1642 _trait_filter: &TraitFilter,
1643) -> Maybe<Vec<UninferredImpl>> {
1644 Err(skip_diagnostic())
1647}
1648
1649fn concrete_trait_fits_trait_filter(
1651 db: &dyn SemanticGroup,
1652 concrete_trait_id: ConcreteTraitId,
1653 trait_filter: &TraitFilter,
1654) -> Maybe<bool> {
1655 if trait_filter.trait_id != concrete_trait_id.trait_id(db) {
1656 return Ok(false);
1657 }
1658 let generic_args = concrete_trait_id.generic_args(db);
1659 let first_generic = generic_args.first();
1660 Ok(match &trait_filter.generics_filter {
1661 GenericsHeadFilter::NoFilter => true,
1662 GenericsHeadFilter::FirstGenericFilter(constraint_head) => {
1663 let Some(first_generic) = first_generic else {
1664 return Ok(false);
1665 };
1666 let Some(first_generic_head) = first_generic.head(db) else {
1667 return Ok(true);
1668 };
1669 &first_generic_head == constraint_head
1670 }
1671 GenericsHeadFilter::NoGenerics => first_generic.is_none(),
1672 })
1673}
1674
1675#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1676pub enum ImplOrModuleById {
1677 Impl(ImplId),
1678 Module(ModuleId),
1679}
1680impl From<ImplId> for ImplOrModuleById {
1681 fn from(impl_id: ImplId) -> Self {
1682 ImplOrModuleById::Impl(impl_id)
1683 }
1684}
1685impl From<ModuleId> for ImplOrModuleById {
1686 fn from(module_id: ModuleId) -> Self {
1687 ImplOrModuleById::Module(module_id)
1688 }
1689}
1690
1691impl Ord for ImplOrModuleById {
1692 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1693 match (self, other) {
1694 (ImplOrModuleById::Impl(imp), ImplOrModuleById::Impl(other_impl)) => {
1695 imp.get_internal_id().cmp(other_impl.get_internal_id())
1696 }
1697 (ImplOrModuleById::Module(module), ImplOrModuleById::Module(other_module)) => {
1698 match (module, other_module) {
1699 (ModuleId::CrateRoot(crate_id), ModuleId::CrateRoot(other_crate_id)) => {
1700 crate_id.get_internal_id().cmp(other_crate_id.get_internal_id())
1701 }
1702 (ModuleId::CrateRoot(_), ModuleId::Submodule(_)) => std::cmp::Ordering::Less,
1703 (ModuleId::Submodule(_), ModuleId::CrateRoot(_)) => std::cmp::Ordering::Greater,
1704 (ModuleId::Submodule(module_id), ModuleId::Submodule(other_module_id)) => {
1705 module_id.get_internal_id().cmp(other_module_id.get_internal_id())
1706 }
1707 }
1708 }
1709 (ImplOrModuleById::Impl(_), ImplOrModuleById::Module(_)) => std::cmp::Ordering::Less,
1710 (ImplOrModuleById::Module(_), ImplOrModuleById::Impl(_)) => std::cmp::Ordering::Greater,
1711 }
1712 }
1713}
1714impl PartialOrd for ImplOrModuleById {
1715 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1716 Some(self.cmp(other))
1717 }
1718}
1719
1720#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, DebugWithDb)]
1721#[debug_db(dyn SemanticGroup + 'static)]
1722pub struct ImplLookupContext {
1723 pub modules_and_impls: BTreeSet<ImplOrModuleById>,
1724 pub generic_params: Vec<GenericParamId>,
1725}
1726impl ImplLookupContext {
1727 pub fn new(module_id: ModuleId, generic_params: Vec<GenericParamId>) -> ImplLookupContext {
1728 Self { modules_and_impls: [ImplOrModuleById::Module(module_id)].into(), generic_params }
1729 }
1730 pub fn insert_lookup_scope(&mut self, db: &dyn SemanticGroup, imp: &UninferredImpl) {
1731 let item = match imp {
1732 UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(db).0.into(),
1733 UninferredImpl::ImplAlias(impl_alias_id) => impl_alias_id.module_file_id(db).0.into(),
1734 UninferredImpl::GenericParam(param) => param.module_file_id(db).0.into(),
1735 UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1736 UninferredImpl::GeneratedImpl(_) => {
1737 return;
1739 }
1740 };
1741 self.modules_and_impls.insert(item);
1742 }
1743 pub fn insert_module(&mut self, module_id: ModuleId) -> bool {
1744 self.modules_and_impls.insert(ImplOrModuleById::Module(module_id))
1745 }
1746
1747 pub fn insert_impl(&mut self, impl_id: ImplId) -> bool {
1748 self.modules_and_impls.insert(ImplOrModuleById::Impl(impl_id))
1749 }
1750}
1751
1752#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1754pub enum UninferredImpl {
1755 Def(ImplDefId),
1756 ImplAlias(ImplAliasId),
1757 GenericParam(GenericParamId),
1758 ImplImpl(ImplImplId),
1759 GeneratedImpl(UninferredGeneratedImplId),
1760}
1761impl UninferredImpl {
1762 pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
1763 match self {
1764 UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1765 UninferredImpl::ImplAlias(impl_alias_id) => {
1766 let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1767 impl_id.concrete_trait(db)
1768 }
1769 UninferredImpl::GenericParam(param) => {
1770 let param =
1771 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1772 param.concrete_trait
1773 }
1774 UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1775 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1776 }
1777 }
1778
1779 fn trait_id(&self, db: &dyn SemanticGroup) -> Maybe<TraitId> {
1780 match self {
1781 UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1782 UninferredImpl::ImplAlias(impl_alias_id) => {
1783 let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1784 db.impl_def_trait(impl_def_id)
1785 }
1786 UninferredImpl::GenericParam(param) => {
1787 let param =
1788 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1789 param.concrete_trait.map(|concrete_trait| concrete_trait.trait_id(db))
1790 }
1791 UninferredImpl::ImplImpl(impl_impl_id) => db
1792 .impl_impl_concrete_trait(*impl_impl_id)
1793 .map(|concrete_trait| concrete_trait.trait_id(db)),
1794 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1795 }
1796 }
1797
1798 pub fn lookup_scope(&self, db: &dyn SemanticGroup) -> ImplOrModuleById {
1799 match self {
1800 UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(db).0.into(),
1801 UninferredImpl::ImplAlias(impl_alias_id) => impl_alias_id.module_file_id(db).0.into(),
1802 UninferredImpl::GenericParam(param) => param.module_file_id(db).0.into(),
1803 UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1804 UninferredImpl::GeneratedImpl(generated_impl) => {
1805 generated_impl.concrete_trait(db).trait_id(db).module_file_id(db).0.into()
1806 }
1807 }
1808 }
1809}
1810impl DebugWithDb<dyn SemanticGroup> for UninferredImpl {
1811 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn SemanticGroup) -> std::fmt::Result {
1812 match self {
1813 UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
1814 UninferredImpl::ImplAlias(impl_alias) => {
1815 write!(f, "{:?}", impl_alias.full_path(db))
1816 }
1817 UninferredImpl::GenericParam(param) => {
1818 write!(f, "generic param {}", param.name(db).unwrap_or_else(|| "_".into()))
1819 }
1820 UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db.elongate()),
1821 UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db.elongate()),
1822 }
1823 }
1824}
1825
1826define_short_id!(
1827 UninferredGeneratedImplId,
1828 UninferredGeneratedImplLongId,
1829 SemanticGroup,
1830 lookup_intern_uninferred_generated_impl,
1831 intern_uninferred_generated_impl
1832);
1833semantic_object_for_id!(
1834 UninferredGeneratedImplId,
1835 lookup_intern_uninferred_generated_impl,
1836 intern_uninferred_generated_impl,
1837 UninferredGeneratedImplLongId
1838);
1839
1840impl UninferredGeneratedImplId {
1841 pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
1842 db.lookup_intern_uninferred_generated_impl(self).concrete_trait
1843 }
1844
1845 pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
1846 self.concrete_trait(db).trait_id(db)
1847 }
1848}
1849
1850#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1852pub struct UninferredGeneratedImplLongId {
1853 pub concrete_trait: ConcreteTraitId,
1854 pub generic_params: Vec<GenericParam>,
1855 pub impl_items: GeneratedImplItems,
1856}
1857
1858impl DebugWithDb<dyn SemanticGroup> for UninferredGeneratedImplLongId {
1859 fn fmt(
1860 &self,
1861 f: &mut std::fmt::Formatter<'_>,
1862 db: &(dyn SemanticGroup + 'static),
1863 ) -> std::fmt::Result {
1864 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
1865 }
1866}
1867
1868pub fn find_candidates_at_context(
1870 db: &dyn SemanticGroup,
1871 lookup_context: &ImplLookupContext,
1872 filter: &TraitFilter,
1873) -> Maybe<OrderedHashSet<UninferredImpl>> {
1874 let mut res = OrderedHashSet::default();
1875 for generic_param_id in &lookup_context.generic_params {
1876 if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1877 continue;
1878 };
1879 let Ok(trait_id) = db.generic_impl_param_trait(*generic_param_id) else {
1880 continue;
1881 };
1882 if filter.trait_id != trait_id {
1883 continue;
1884 }
1885 let Ok(generic_param_semantic) = db.generic_param_semantic(*generic_param_id) else {
1886 continue;
1887 };
1888 let param = extract_matches!(generic_param_semantic, GenericParam::Impl);
1889 let Ok(imp_concrete_trait_id) = param.concrete_trait else { continue };
1890 let Ok(trait_fits_filter) =
1891 concrete_trait_fits_trait_filter(db, imp_concrete_trait_id, filter)
1892 else {
1893 continue;
1894 };
1895 if !trait_fits_filter {
1896 continue;
1897 }
1898 res.insert(UninferredImpl::GenericParam(*generic_param_id));
1899 }
1900 for module_or_impl_id in &lookup_context.modules_and_impls {
1901 let Ok(imps) = (match module_or_impl_id {
1902 ImplOrModuleById::Module(module_id) => {
1903 db.module_impl_ids_for_trait_filter(*module_id, filter.clone())
1904 }
1905 ImplOrModuleById::Impl(impl_id) => {
1906 db.impl_impl_ids_for_trait_filter(*impl_id, filter.clone())
1907 }
1908 }) else {
1909 continue;
1910 };
1911 for imp in imps {
1912 res.insert(imp);
1913 }
1914 }
1915 Ok(res)
1916}
1917
1918pub fn find_closure_generated_candidate(
1920 db: &dyn SemanticGroup,
1921 concrete_trait_id: ConcreteTraitId,
1922) -> Option<UninferredImpl> {
1923 let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
1924 return None;
1925 };
1926 let TypeLongId::Closure(closure_type_long) = closure_type.lookup_intern(db) else {
1927 return None;
1928 };
1929
1930 let info = db.core_info();
1931
1932 let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
1934 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1935 chain!(
1936 closure_type_long.captured_types.iter().unique().map(|ty| {
1937 GenericParam::Impl(GenericParamImpl {
1938 id,
1939 concrete_trait: Maybe::Ok(db.intern_concrete_trait(ConcreteTraitLongId {
1940 trait_id,
1941 generic_args: vec![GenericArgumentId::Type(*ty)],
1942 })),
1943 type_constraints: Default::default(),
1944 })
1945 }),
1946 neg_impl_trait.map(|neg_impl_trait| {
1947 GenericParam::NegImpl(GenericParamImpl {
1948 id,
1949 concrete_trait: Maybe::Ok(neg_impl_trait),
1950 type_constraints: Default::default(),
1951 })
1952 })
1953 )
1954 .collect()
1955 };
1956 let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
1957 (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
1958 };
1959 let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
1960 trait_id if trait_id == info.fn_once_trt => {
1961 let concrete_trait = ConcreteTraitLongId {
1962 trait_id,
1963 generic_args: vec![
1964 GenericArgumentId::Type(closure_type),
1965 GenericArgumentId::Type(
1966 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1967 ),
1968 ],
1969 }
1970 .intern(db);
1971 let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
1972
1973 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1974 let param: GenericParam = GenericParam::NegImpl(GenericParamImpl {
1976 id,
1977 concrete_trait: Maybe::Ok(
1978 ConcreteTraitLongId {
1979 trait_id: info.fn_trt,
1980 generic_args: vec![
1981 GenericArgumentId::Type(closure_type),
1982 GenericArgumentId::Type(
1983 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1984 ),
1985 ],
1986 }
1987 .intern(db),
1988 ),
1989 type_constraints: Default::default(),
1990 });
1991 (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
1992 }
1993 trait_id if trait_id == info.fn_trt => {
1994 let concrete_trait = ConcreteTraitLongId {
1995 trait_id,
1996 generic_args: vec![
1997 GenericArgumentId::Type(closure_type),
1998 GenericArgumentId::Type(
1999 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2000 ),
2001 ],
2002 }
2003 .intern(db);
2004 let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
2005
2006 (
2007 concrete_trait,
2008 mem_trait_generic_params(info.copy_trt, None),
2010 [(ret_ty, closure_type_long.ret_ty)].into(),
2011 )
2012 }
2013 trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2014 trait_id if trait_id == info.destruct_trt => {
2015 handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2016 }
2017 trait_id if trait_id == info.panic_destruct_trt => {
2018 handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2019 }
2020 trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2021 _ => return None,
2022 };
2023 Some(UninferredImpl::GeneratedImpl(
2024 UninferredGeneratedImplLongId {
2025 concrete_trait,
2026 generic_params,
2027 impl_items: GeneratedImplItems(impl_items),
2028 }
2029 .intern(db),
2030 ))
2031}
2032
2033pub fn can_infer_impl_by_self(
2039 ctx: &ComputationContext<'_>,
2040 inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
2041 trait_function_id: TraitFunctionId,
2042 self_ty: TypeId,
2043 stable_ptr: SyntaxStablePtrId,
2044) -> bool {
2045 let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2046 let mut temp_inference = temp_inference_data.inference(ctx.db);
2047 let lookup_context = ctx.resolver.impl_lookup_context();
2048
2049 let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2050 trait_function_id,
2051 self_ty,
2052 &lookup_context,
2053 Some(stable_ptr),
2054 |err| inference_errors.push((trait_function_id, err)),
2055 ) else {
2056 return false;
2057 };
2058 if let Err(err_set) = temp_inference.solve() {
2060 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2062 inference_errors.push((trait_function_id, err));
2063 }
2064 }
2065 match temp_inference.trait_solution_set(
2066 concrete_trait_id,
2067 ImplVarTraitItemMappings::default(),
2068 lookup_context.clone(),
2069 ) {
2070 Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2071 Ok(SolutionSet::None) => {
2072 inference_errors
2073 .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2074 false
2075 }
2076 Err(err_set) => {
2077 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2079 inference_errors.push((trait_function_id, err));
2080 }
2081 false
2082 }
2083 }
2084}
2085
2086pub fn infer_impl_by_self(
2089 ctx: &mut ComputationContext<'_>,
2090 trait_function_id: TraitFunctionId,
2091 self_ty: TypeId,
2092 stable_ptr: SyntaxStablePtrId,
2093 generic_args_syntax: Option<Vec<GenericArg>>,
2094) -> Maybe<(FunctionId, usize)> {
2095 let lookup_context = ctx.resolver.impl_lookup_context();
2096 let (concrete_trait_id, n_snapshots) = ctx
2097 .resolver
2098 .inference()
2099 .infer_concrete_trait_by_self(
2100 trait_function_id,
2101 self_ty,
2102 &lookup_context,
2103 Some(stable_ptr),
2104 |_| {},
2105 )
2106 .ok_or_else(skip_diagnostic)?;
2107
2108 let concrete_trait_function_id =
2109 ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2110 .intern(ctx.db);
2111 let trait_func_generic_params =
2112 ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2113
2114 let impl_lookup_context = ctx.resolver.impl_lookup_context();
2115 let inference = &mut ctx.resolver.inference();
2116 let generic_function = inference.infer_trait_generic_function(
2117 concrete_trait_function_id,
2118 &impl_lookup_context,
2119 Some(stable_ptr),
2120 );
2121 let generic_args = ctx.resolver.resolve_generic_args(
2122 ctx.diagnostics,
2123 GenericSubstitution::from_impl(generic_function.impl_id),
2124 &trait_func_generic_params,
2125 &generic_args_syntax.unwrap_or_default(),
2126 stable_ptr,
2127 )?;
2128
2129 Ok((
2130 FunctionLongId {
2131 function: ConcreteFunction {
2132 generic_function: GenericFunctionId::Impl(generic_function),
2133 generic_args,
2134 },
2135 }
2136 .intern(ctx.db),
2137 n_snapshots,
2138 ))
2139}
2140
2141pub fn filter_candidate_traits(
2147 ctx: &mut ComputationContext<'_>,
2148 inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
2149 self_ty: TypeId,
2150 candidate_traits: &[TraitId],
2151 function_name: SmolStr,
2152 stable_ptr: SyntaxStablePtrId,
2153) -> Vec<TraitFunctionId> {
2154 let mut candidates = Vec::new();
2155 for trait_id in candidate_traits.iter().copied() {
2156 let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2157 continue;
2158 };
2159 for (name, trait_function) in trait_functions {
2160 if name == function_name
2161 && can_infer_impl_by_self(
2162 ctx,
2163 inference_errors,
2164 trait_function,
2165 self_ty,
2166 stable_ptr,
2167 )
2168 {
2169 candidates.push(trait_function);
2170 }
2171 }
2172 }
2173 candidates
2174}
2175
2176#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2179#[debug_db(dyn SemanticGroup + 'static)]
2180pub struct ImplItemTypeData {
2181 type_alias_data: TypeAliasData,
2182 trait_type_id: Maybe<TraitTypeId>,
2183 diagnostics: Diagnostics<SemanticDiagnostic>,
2185}
2186
2187pub fn impl_type_def_semantic_diagnostics(
2191 db: &dyn SemanticGroup,
2192 impl_type_def_id: ImplTypeDefId,
2193) -> Diagnostics<SemanticDiagnostic> {
2194 db.priv_impl_type_semantic_data(impl_type_def_id, false)
2195 .map(|data| data.diagnostics)
2196 .unwrap_or_default()
2197}
2198
2199pub fn impl_type_def_resolved_type(
2201 db: &dyn SemanticGroup,
2202 impl_type_def_id: ImplTypeDefId,
2203) -> Maybe<TypeId> {
2204 db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolved_type
2205}
2206
2207pub fn impl_type_def_resolved_type_cycle(
2209 db: &dyn SemanticGroup,
2210 _cycle: &salsa::Cycle,
2211 impl_type_def_id: &ImplTypeDefId,
2212) -> Maybe<TypeId> {
2213 db.priv_impl_type_semantic_data(*impl_type_def_id, true)?.type_alias_data.resolved_type
2214}
2215
2216pub fn impl_type_def_generic_params(
2218 db: &dyn SemanticGroup,
2219 impl_type_def_id: ImplTypeDefId,
2220) -> Maybe<Vec<GenericParam>> {
2221 Ok(db.priv_impl_type_def_generic_params_data(impl_type_def_id)?.generic_params)
2222}
2223
2224pub fn impl_type_def_attributes(
2226 db: &dyn SemanticGroup,
2227 impl_type_def_id: ImplTypeDefId,
2228) -> Maybe<Vec<Attribute>> {
2229 Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.attributes)
2230}
2231
2232pub fn impl_type_def_resolver_data(
2234 db: &dyn SemanticGroup,
2235 impl_type_def_id: ImplTypeDefId,
2236) -> Maybe<Arc<ResolverData>> {
2237 Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolver_data)
2238}
2239
2240pub fn impl_type_def_trait_type(
2242 db: &dyn SemanticGroup,
2243 impl_type_def_id: ImplTypeDefId,
2244) -> Maybe<TraitTypeId> {
2245 db.priv_impl_type_semantic_data(impl_type_def_id, false)?.trait_type_id
2246}
2247
2248pub fn priv_impl_type_semantic_data(
2252 db: &dyn SemanticGroup,
2253 impl_type_def_id: ImplTypeDefId,
2254 in_cycle: bool,
2255) -> Maybe<ImplItemTypeData> {
2256 let mut diagnostics = SemanticDiagnostics::default();
2257 let impl_type_defs = db.impl_types(impl_type_def_id.impl_def_id(db))?;
2258 let impl_type_def_ast = impl_type_defs.get(&impl_type_def_id).to_maybe()?;
2259 let generic_params_data = db.priv_impl_type_def_generic_params_data(impl_type_def_id)?;
2260 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2261
2262 let trait_type_id =
2263 validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, impl_type_def_ast);
2264
2265 if in_cycle {
2266 Ok(ImplItemTypeData {
2267 type_alias_data: type_alias_semantic_data_cycle_helper(
2268 db,
2269 &mut diagnostics,
2270 impl_type_def_ast,
2271 lookup_item_id,
2272 generic_params_data,
2273 )?,
2274 trait_type_id,
2275 diagnostics: diagnostics.build(),
2276 })
2277 } else {
2278 Ok(ImplItemTypeData {
2281 type_alias_data: type_alias_semantic_data_helper(
2282 db,
2283 &mut diagnostics,
2284 impl_type_def_ast,
2285 lookup_item_id,
2286 generic_params_data,
2287 )?,
2288 trait_type_id,
2289 diagnostics: diagnostics.build(),
2290 })
2291 }
2292}
2293
2294pub fn priv_impl_type_semantic_data_cycle(
2296 db: &dyn SemanticGroup,
2297 _cycle: &salsa::Cycle,
2298 impl_type_def_id: &ImplTypeDefId,
2299 _in_cycle: &bool,
2300) -> Maybe<ImplItemTypeData> {
2301 priv_impl_type_semantic_data(db, *impl_type_def_id, true)
2303}
2304
2305pub fn priv_impl_type_def_generic_params_data(
2307 db: &dyn SemanticGroup,
2308 impl_type_def_id: ImplTypeDefId,
2309) -> Maybe<GenericParamsData> {
2310 let module_file_id = impl_type_def_id.module_file_id(db);
2311 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?.to_maybe()?;
2312 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2313
2314 let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2315 type_alias_generic_params_data_helper(
2316 db,
2317 module_file_id,
2318 &impl_type_def_ast,
2319 lookup_item_id,
2320 Some(impl_resolver_data),
2321 )
2322}
2323
2324fn validate_impl_item_type(
2326 db: &dyn SemanticGroup,
2327 diagnostics: &mut SemanticDiagnostics,
2328 impl_type_def_id: ImplTypeDefId,
2329 impl_type_ast: &ast::ItemTypeAlias,
2330) -> Maybe<TraitTypeId> {
2331 let impl_def_id = impl_type_def_id.impl_def_id(db);
2332 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2333 let trait_id = concrete_trait_id.trait_id(db);
2334 let type_name = impl_type_def_id.name(db);
2335 let trait_type_id = db.trait_type_by_name(trait_id, type_name.clone())?.ok_or_else(|| {
2336 diagnostics.report(
2337 impl_type_ast.stable_ptr(db),
2338 ImplItemNotInTrait {
2339 impl_def_id,
2340 impl_item_name: type_name,
2341 trait_id,
2342 item_kind: "type".into(),
2343 },
2344 )
2345 })?;
2346
2347 let generic_params_node = impl_type_ast.generic_params(db);
2350 if !generic_params_node.is_empty(db) {
2351 diagnostics.report(
2352 generic_params_node.stable_ptr(db),
2353 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2354 );
2355 }
2356
2357 Ok(trait_type_id)
2358}
2359
2360pub fn impl_type_concrete_implized(
2364 db: &dyn SemanticGroup,
2365 impl_type_id: ImplTypeId,
2366) -> Maybe<TypeId> {
2367 let concrete_impl = match impl_type_id.impl_id().lookup_intern(db) {
2368 ImplLongId::Concrete(concrete_impl) => concrete_impl,
2369 ImplLongId::ImplImpl(imp_impl_id) => {
2370 let ImplLongId::Concrete(concrete_impl) =
2371 db.impl_impl_concrete_implized(imp_impl_id)?.lookup_intern(db)
2372 else {
2373 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2374 };
2375 concrete_impl
2376 }
2377 ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2378 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2379 }
2380 ImplLongId::GeneratedImpl(generated) => {
2381 return Ok(*generated.lookup_intern(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2382 }
2383 };
2384
2385 let impl_def_id = concrete_impl.impl_def_id(db);
2386 let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id);
2387 let Ok(ty) = ty else {
2388 return ty;
2389 };
2390 concrete_impl.substitution(db)?.substitute(db, ty)
2391}
2392
2393pub fn impl_type_concrete_implized_cycle(
2395 db: &dyn SemanticGroup,
2396 _cycle: &salsa::Cycle,
2397 impl_type_id: &ImplTypeId,
2398) -> Maybe<TypeId> {
2399 impl_type_concrete_implized(db, *impl_type_id)
2401}
2402
2403#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2406#[debug_db(dyn SemanticGroup + 'static)]
2407pub struct ImplItemConstantData {
2408 constant_data: ConstantData,
2409 trait_constant_id: Maybe<TraitConstantId>,
2410 diagnostics: Diagnostics<SemanticDiagnostic>,
2412}
2413
2414pub fn impl_constant_def_semantic_diagnostics(
2418 db: &dyn SemanticGroup,
2419 impl_constant_def_id: ImplConstantDefId,
2420) -> Diagnostics<SemanticDiagnostic> {
2421 db.priv_impl_constant_semantic_data(impl_constant_def_id, false)
2422 .map(|data| data.diagnostics)
2423 .unwrap_or_default()
2424}
2425
2426pub fn impl_constant_def_value(
2428 db: &dyn SemanticGroup,
2429 impl_constant_def_id: ImplConstantDefId,
2430) -> Maybe<ConstValueId> {
2431 Ok(db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.constant_data.const_value)
2432}
2433
2434pub fn impl_constant_def_value_cycle(
2436 db: &dyn SemanticGroup,
2437 _cycle: &salsa::Cycle,
2438 impl_constant_def_id: &ImplConstantDefId,
2439) -> Maybe<ConstValueId> {
2440 Ok(db.priv_impl_constant_semantic_data(*impl_constant_def_id, true)?.constant_data.const_value)
2441}
2442
2443pub fn impl_constant_def_resolver_data(
2445 db: &dyn SemanticGroup,
2446 impl_constant_def_id: ImplConstantDefId,
2447) -> Maybe<Arc<ResolverData>> {
2448 Ok(db
2449 .priv_impl_constant_semantic_data(impl_constant_def_id, false)?
2450 .constant_data
2451 .resolver_data)
2452}
2453
2454pub fn impl_constant_def_trait_constant(
2456 db: &dyn SemanticGroup,
2457 impl_constant_def_id: ImplConstantDefId,
2458) -> Maybe<TraitConstantId> {
2459 db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.trait_constant_id
2460}
2461
2462pub fn priv_impl_constant_semantic_data(
2466 db: &dyn SemanticGroup,
2467 impl_constant_def_id: ImplConstantDefId,
2468 in_cycle: bool,
2469) -> Maybe<ImplItemConstantData> {
2470 let mut diagnostics = SemanticDiagnostics::default();
2471 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2472 let impl_constant_defs = db.impl_constants(impl_def_id)?;
2473 let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2474 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2475
2476 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2477 ImplItemId::Constant(impl_constant_def_id),
2478 ));
2479 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2480 let mut resolver =
2481 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2482
2483 let trait_constant_id = validate_impl_item_constant(
2484 db,
2485 &mut diagnostics,
2486 impl_constant_def_id,
2487 impl_constant_def_ast,
2488 &mut resolver,
2489 );
2490 let mut constant_data = if in_cycle {
2491 constant_semantic_data_cycle_helper(
2492 db,
2493 impl_constant_def_ast,
2494 lookup_item_id,
2495 Some(Arc::new(resolver.data)),
2496 &impl_def_id,
2497 )?
2498 } else {
2499 constant_semantic_data_helper(
2500 db,
2501 impl_constant_def_ast,
2502 lookup_item_id,
2503 Some(Arc::new(resolver.data)),
2504 &impl_def_id,
2505 )?
2506 };
2507 diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2508 Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2509}
2510
2511pub fn priv_impl_constant_semantic_data_cycle(
2513 db: &dyn SemanticGroup,
2514 _cycle: &salsa::Cycle,
2515 impl_constant_def_id: &ImplConstantDefId,
2516 _in_cycle: &bool,
2517) -> Maybe<ImplItemConstantData> {
2518 priv_impl_constant_semantic_data(db, *impl_constant_def_id, true)
2520}
2521
2522fn validate_impl_item_constant(
2524 db: &dyn SemanticGroup,
2525 diagnostics: &mut SemanticDiagnostics,
2526 impl_constant_def_id: ImplConstantDefId,
2527 impl_constant_ast: &ast::ItemConstant,
2528 resolver: &mut Resolver<'_>,
2529) -> Maybe<TraitConstantId> {
2530 let impl_def_id = impl_constant_def_id.impl_def_id(db);
2531 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2532 let trait_id = concrete_trait_id.trait_id(db);
2533 let constant_name = impl_constant_def_id.name(db);
2534
2535 let trait_constant_id =
2536 db.trait_constant_by_name(trait_id, constant_name.clone())?.ok_or_else(|| {
2537 diagnostics.report(
2538 impl_constant_ast.stable_ptr(db),
2539 ImplItemNotInTrait {
2540 impl_def_id,
2541 impl_item_name: constant_name,
2542 trait_id,
2543 item_kind: "const".into(),
2544 },
2545 )
2546 })?;
2547 let concrete_trait_constant =
2548 ConcreteTraitConstantId::new(db, concrete_trait_id, trait_constant_id);
2549 let concrete_trait_constant_ty = db.concrete_trait_constant_type(concrete_trait_constant)?;
2550
2551 let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2552
2553 let constant_ty =
2554 resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2555
2556 let inference = &mut resolver.inference();
2557
2558 let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2559 let actual_ty = inference.rewrite(constant_ty).no_err();
2560 if expected_ty != actual_ty {
2561 diagnostics.report(
2562 impl_constant_type_clause_ast.stable_ptr(db),
2563 WrongType { expected_ty, actual_ty },
2564 );
2565 }
2566 Ok(trait_constant_id)
2567}
2568
2569pub fn impl_constant_implized_by_context(
2573 db: &dyn SemanticGroup,
2574 impl_constant_id: ImplConstantId,
2575 impl_def_id: ImplDefId,
2576) -> Maybe<ConstValueId> {
2577 let impl_constant_def_id: ImplConstantDefId =
2578 db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2579
2580 db.impl_constant_def_value(impl_constant_def_id)
2581}
2582
2583pub fn impl_constant_implized_by_context_cycle(
2585 db: &dyn SemanticGroup,
2586 _cycle: &salsa::Cycle,
2587 impl_constant_id: &ImplConstantId,
2588 impl_def_id: &ImplDefId,
2589) -> Maybe<ConstValueId> {
2590 impl_constant_implized_by_context(db, *impl_constant_id, *impl_def_id)
2592}
2593
2594pub fn impl_constant_concrete_implized_value(
2596 db: &dyn SemanticGroup,
2597 impl_constant_id: ImplConstantId,
2598) -> Maybe<ConstValueId> {
2599 if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().lookup_intern(db) {
2600 let impl_def_id = concrete_impl.impl_def_id(db);
2601 let constant = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2602 return concrete_impl.substitution(db)?.substitute(db, constant);
2603 }
2604 Ok(ConstValue::ImplConstant(
2605 GenericSubstitution::from_impl(impl_constant_id.impl_id())
2606 .substitute(db, impl_constant_id)?,
2607 )
2608 .intern(db))
2609}
2610
2611pub fn impl_constant_concrete_implized_value_cycle(
2613 db: &dyn SemanticGroup,
2614 _cycle: &salsa::Cycle,
2615 impl_constant_id: &ImplConstantId,
2616) -> Maybe<ConstValueId> {
2617 impl_constant_concrete_implized_value(db, *impl_constant_id)
2619}
2620
2621pub fn impl_constant_concrete_implized_type(
2623 db: &dyn SemanticGroup,
2624 impl_constant_id: ImplConstantId,
2625) -> Maybe<TypeId> {
2626 let concrete_trait_id = match impl_constant_id.impl_id().lookup_intern(db) {
2627 ImplLongId::Concrete(concrete_impl) => {
2628 let impl_def_id = concrete_impl.impl_def_id(db);
2629 let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2630 return concrete_impl.substitution(db)?.substitute(db, ty);
2631 }
2632 ImplLongId::GenericParameter(param) => {
2633 let param_impl =
2634 extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
2635 param_impl.concrete_trait?
2636 }
2637 ImplLongId::ImplVar(var) => var.lookup_intern(db).concrete_trait_id,
2638 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl)?,
2639 ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id,
2640 ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2641 };
2642
2643 let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new(
2644 db,
2645 concrete_trait_id,
2646 impl_constant_id.trait_constant_id(),
2647 ))?;
2648 GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2649}
2650
2651pub fn impl_constant_concrete_implized_type_cycle(
2653 db: &dyn SemanticGroup,
2654 _cycle: &salsa::Cycle,
2655 impl_constant_id: &ImplConstantId,
2656) -> Maybe<TypeId> {
2657 impl_constant_concrete_implized_type(db, *impl_constant_id)
2659}
2660
2661#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2664#[debug_db(dyn SemanticGroup + 'static)]
2665pub struct ImplItemImplData {
2666 impl_data: ImplAliasData,
2667 trait_impl_id: Maybe<TraitImplId>,
2668 diagnostics: Diagnostics<SemanticDiagnostic>,
2670}
2671
2672pub fn impl_impl_def_semantic_diagnostics(
2676 db: &dyn SemanticGroup,
2677 impl_impl_def_id: ImplImplDefId,
2678) -> Diagnostics<SemanticDiagnostic> {
2679 db.priv_impl_impl_semantic_data(impl_impl_def_id, false)
2680 .map(|data| data.diagnostics)
2681 .unwrap_or_default()
2682}
2683
2684pub fn impl_impl_def_resolver_data(
2686 db: &dyn SemanticGroup,
2687 impl_impl_def_id: ImplImplDefId,
2688) -> Maybe<Arc<ResolverData>> {
2689 Ok(db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.impl_data.resolver_data)
2690}
2691
2692pub fn impl_impl_def_trait_impl(
2694 db: &dyn SemanticGroup,
2695 impl_impl_def_id: ImplImplDefId,
2696) -> Maybe<TraitImplId> {
2697 db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.trait_impl_id
2698}
2699
2700pub fn impl_impl_def_impl(
2702 db: &dyn SemanticGroup,
2703 impl_impl_def_id: ImplImplDefId,
2704 in_cycle: bool,
2705) -> Maybe<ImplId> {
2706 db.priv_impl_impl_semantic_data(impl_impl_def_id, in_cycle)?.impl_data.resolved_impl
2707}
2708pub fn impl_impl_def_impl_cycle(
2710 db: &dyn SemanticGroup,
2711 _cycle: &salsa::Cycle,
2712 impl_impl_def_id: &ImplImplDefId,
2713 _in_cycle: &bool,
2714) -> Maybe<ImplId> {
2715 db.priv_impl_impl_semantic_data(*impl_impl_def_id, true)?.impl_data.resolved_impl
2716}
2717
2718pub fn priv_impl_impl_semantic_data(
2722 db: &dyn SemanticGroup,
2723 impl_impl_def_id: ImplImplDefId,
2724 in_cycle: bool,
2725) -> Maybe<ImplItemImplData> {
2726 let mut diagnostics = SemanticDiagnostics::default();
2727 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2728 let impl_impl_defs = db.impl_impls(impl_def_id)?;
2729 let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2730 let generic_params_data = db.priv_impl_impl_def_generic_params_data(impl_impl_def_id)?;
2731 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2732
2733 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2734 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2735 let mut resolver =
2736 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2737
2738 let mut impl_data = if in_cycle {
2739 impl_alias_semantic_data_cycle_helper(
2740 db,
2741 impl_impl_def_ast,
2742 lookup_item_id,
2743 generic_params_data,
2744 )?
2745 } else {
2746 impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2747 };
2748
2749 diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2750
2751 let trait_impl_id = validate_impl_item_impl(
2752 db,
2753 &mut diagnostics,
2754 impl_impl_def_id,
2755 impl_impl_def_ast,
2756 &impl_data,
2757 &mut resolver,
2758 );
2759
2760 Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2761}
2762
2763pub fn priv_impl_impl_semantic_data_cycle(
2765 db: &dyn SemanticGroup,
2766 _cycle: &salsa::Cycle,
2767 impl_impl_def_id: &ImplImplDefId,
2768 _in_cycle: &bool,
2769) -> Maybe<ImplItemImplData> {
2770 priv_impl_impl_semantic_data(db, *impl_impl_def_id, true)
2772}
2773
2774pub fn priv_impl_impl_def_generic_params_data(
2776 db: &dyn SemanticGroup,
2777 impl_impl_def_id: ImplImplDefId,
2778) -> Maybe<GenericParamsData> {
2779 let module_file_id = impl_impl_def_id.module_file_id(db);
2780 let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?.to_maybe()?;
2781 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2782
2783 let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2784 impl_alias_generic_params_data_helper(
2785 db,
2786 module_file_id,
2787 &impl_impl_def_ast,
2788 lookup_item_id,
2789 Some(impl_resolver_data),
2790 )
2791}
2792
2793fn validate_impl_item_impl(
2795 db: &dyn SemanticGroup,
2796 diagnostics: &mut SemanticDiagnostics,
2797 impl_impl_def_id: ImplImplDefId,
2798 impl_impl_ast: &ast::ItemImplAlias,
2799 impl_data: &ImplAliasData,
2800 resolver: &mut Resolver<'_>,
2801) -> Maybe<TraitImplId> {
2802 let impl_def_id = impl_impl_def_id.impl_def_id(db);
2803 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2804 let trait_id = concrete_trait_id.trait_id(db);
2805 let impl_name = impl_impl_def_id.name(db);
2806 let trait_impl_id = db.trait_impl_by_name(trait_id, impl_name.clone())?.ok_or_else(|| {
2807 diagnostics.report(
2808 impl_impl_ast.stable_ptr(db),
2809 ImplItemNotInTrait {
2810 impl_def_id,
2811 impl_item_name: impl_name,
2812 trait_id,
2813 item_kind: "impl".into(),
2814 },
2815 )
2816 })?;
2817
2818 let generic_params_node = impl_impl_ast.generic_params(db);
2821 if !generic_params_node.is_empty(db) {
2822 diagnostics.report(
2823 generic_params_node.stable_ptr(db),
2824 GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2825 );
2826 }
2827
2828 let concrete_trait_impl = ConcreteTraitImplId::new(db, concrete_trait_id, trait_impl_id);
2829 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2830
2831 let concrete_trait_impl_concrete_trait = db
2832 .concrete_trait_impl_concrete_trait(concrete_trait_impl)
2833 .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
2834
2835 let resolved_impl_concrete_trait =
2836 impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2837 let _ = (|| -> Result<(), DiagnosticAdded> {
2839 if resolver
2840 .inference()
2841 .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
2842 .is_err()
2843 {
2844 diagnostics.report(
2845 impl_impl_ast.stable_ptr(db),
2846 TraitMismatch {
2847 expected_trt: concrete_trait_impl_concrete_trait?,
2848 actual_trt: resolved_impl_concrete_trait?,
2849 },
2850 );
2851 }
2852 Ok(())
2853 })();
2854
2855 Ok(trait_impl_id)
2856}
2857
2858#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2859#[debug_db(dyn SemanticGroup + 'static)]
2860pub struct ImplicitImplImplData {
2861 resolved_impl: Maybe<ImplId>,
2862 trait_impl_id: TraitImplId,
2863 diagnostics: Diagnostics<SemanticDiagnostic>,
2864}
2865
2866pub fn implicit_impl_impl_semantic_diagnostics(
2868 db: &dyn SemanticGroup,
2869 impl_def_id: ImplDefId,
2870 trait_impl_id: TraitImplId,
2871) -> Diagnostics<SemanticDiagnostic> {
2872 db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, false)
2873 .map(|data| data.diagnostics)
2874 .unwrap_or_default()
2875}
2876pub fn implicit_impl_impl_impl(
2878 db: &dyn SemanticGroup,
2879 impl_def_id: ImplDefId,
2880 trait_impl_id: TraitImplId,
2881 in_cycle: bool,
2882) -> Maybe<ImplId> {
2883 db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, in_cycle)?.resolved_impl
2884}
2885pub fn implicit_impl_impl_impl_cycle(
2887 db: &dyn SemanticGroup,
2888 _cycle: &salsa::Cycle,
2889 impl_def_id: &ImplDefId,
2890 trait_impl_id: &TraitImplId,
2891 _in_cycle: &bool,
2892) -> Maybe<ImplId> {
2893 db.priv_implicit_impl_impl_semantic_data(*impl_def_id, *trait_impl_id, true)?.resolved_impl
2894}
2895
2896pub fn priv_implicit_impl_impl_semantic_data(
2898 db: &dyn SemanticGroup,
2899 impl_def_id: ImplDefId,
2900 trait_impl_id: TraitImplId,
2901 in_cycle: bool,
2902) -> Maybe<ImplicitImplImplData> {
2903 let mut diagnostics = SemanticDiagnostics::default();
2904 if in_cycle {
2905 let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
2906 return Ok(ImplicitImplImplData {
2907 resolved_impl: err,
2908 trait_impl_id,
2909 diagnostics: diagnostics.build(),
2910 });
2911 }
2912 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
2913
2914 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2915 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2916
2917 let mut resolver =
2918 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2919 resolver.trait_or_impl_ctx = TraitOrImplContext::None;
2921
2922 let concrete_trait_impl_concrete_trait = db
2923 .impl_def_concrete_trait(impl_def_id)
2924 .and_then(|concrete_trait_id| {
2925 db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new(
2926 db,
2927 concrete_trait_id,
2928 trait_impl_id,
2929 ))
2930 })
2931 .and_then(|concrete_trait_id| {
2932 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2933 impl_def_substitution.substitute(db, concrete_trait_id)
2934 });
2935 let impl_lookup_context = resolver.impl_lookup_context();
2936 let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
2937 let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
2938 resolver.inference().finalize_without_reporting().map_err(|(err_set, _)| {
2939 diagnostics.report(
2940 impl_def_id.stable_ptr(db).untyped(),
2941 ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
2942 );
2943 resolver.inference().report_on_pending_error(
2944 err_set,
2945 &mut diagnostics,
2946 impl_def_id.stable_ptr(db).untyped(),
2947 )
2948 })?;
2949 resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
2950 });
2951
2952 Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
2953}
2954pub fn priv_implicit_impl_impl_semantic_data_cycle(
2956 db: &dyn SemanticGroup,
2957 _cycle: &salsa::Cycle,
2958 impl_def_id: &ImplDefId,
2959 trait_impl_id: &TraitImplId,
2960 _in_cycle: &bool,
2961) -> Maybe<ImplicitImplImplData> {
2962 priv_implicit_impl_impl_semantic_data(db, *impl_def_id, *trait_impl_id, true)
2964}
2965
2966pub fn impl_impl_implized_by_context(
2970 db: &dyn SemanticGroup,
2971 impl_impl_id: ImplImplId,
2972 impl_def_id: ImplDefId,
2973 in_cycle: bool,
2974) -> Maybe<ImplId> {
2975 if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
2976 return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
2977 }
2978
2979 let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
2980
2981 db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
2982}
2983
2984pub fn impl_impl_implized_by_context_cycle(
2986 db: &dyn SemanticGroup,
2987 _cycle: &salsa::Cycle,
2988 impl_impl_id: &ImplImplId,
2989 impl_def_id: &ImplDefId,
2990 _in_cycle: &bool,
2991) -> Maybe<ImplId> {
2992 impl_impl_implized_by_context(db, *impl_impl_id, *impl_def_id, true)
2994}
2995
2996pub fn impl_impl_concrete_implized(
2998 db: &dyn SemanticGroup,
2999 impl_impl_id: ImplImplId,
3000) -> Maybe<ImplId> {
3001 impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3002}
3003
3004pub fn impl_impl_concrete_implized_cycle(
3006 db: &dyn SemanticGroup,
3007 _cycle: &salsa::Cycle,
3008 impl_impl_id: &ImplImplId,
3009) -> Maybe<ImplId> {
3010 impl_impl_concrete_implized_ex(db, *impl_impl_id, true)
3011}
3012
3013fn impl_impl_concrete_implized_ex(
3014 db: &dyn SemanticGroup,
3015 impl_impl_id: ImplImplId,
3016 in_cycle: bool,
3017) -> Maybe<ImplId> {
3018 if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().lookup_intern(db) {
3019 let impl_def_id = concrete_impl.impl_def_id(db);
3020 let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
3021 return concrete_impl.substitution(db)?.substitute(db, imp);
3022 }
3023
3024 Ok(ImplLongId::ImplImpl(
3025 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, impl_impl_id)?,
3026 )
3027 .intern(db))
3028}
3029
3030pub fn impl_impl_concrete_trait(
3032 db: &dyn SemanticGroup,
3033 impl_impl_id: ImplImplId,
3034) -> Maybe<ConcreteTraitId> {
3035 let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
3036 db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
3037 GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, concrete_trait_id)
3038 })
3039}
3040
3041#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
3044#[debug_db(dyn SemanticGroup + 'static)]
3045pub struct ImplFunctionDeclarationData {
3046 pub function_declaration_data: FunctionDeclarationData,
3047 trait_function_id: Maybe<TraitFunctionId>,
3048}
3049
3050pub fn impl_function_declaration_diagnostics(
3054 db: &dyn SemanticGroup,
3055 impl_function_id: ImplFunctionId,
3056) -> Diagnostics<SemanticDiagnostic> {
3057 db.priv_impl_function_declaration_data(impl_function_id)
3058 .map(|data| data.function_declaration_data.diagnostics)
3059 .unwrap_or_default()
3060}
3061
3062pub fn impl_function_signature(
3064 db: &dyn SemanticGroup,
3065 impl_function_id: ImplFunctionId,
3066) -> Maybe<semantic::Signature> {
3067 Ok(db
3068 .priv_impl_function_declaration_data(impl_function_id)?
3069 .function_declaration_data
3070 .signature)
3071}
3072
3073pub fn impl_function_generic_params(
3075 db: &dyn SemanticGroup,
3076 impl_function_id: ImplFunctionId,
3077) -> Maybe<Vec<semantic::GenericParam>> {
3078 Ok(db.priv_impl_function_generic_params_data(impl_function_id)?.generic_params)
3079}
3080
3081pub fn priv_impl_function_generic_params_data(
3083 db: &dyn SemanticGroup,
3084 impl_function_id: ImplFunctionId,
3085) -> Maybe<GenericParamsData> {
3086 let module_file_id = impl_function_id.module_file_id(db);
3087 let mut diagnostics = SemanticDiagnostics::default();
3088 let impl_def_id = impl_function_id.impl_def_id(db);
3089 let data = db.priv_impl_definition_data(impl_def_id)?;
3090 let function_syntax = &data.function_asts[&impl_function_id];
3091 let declaration = function_syntax.declaration(db);
3092 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
3093 ImplItemId::Function(impl_function_id),
3094 ));
3095 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3096 let mut resolver =
3097 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3098 let generic_params = semantic_generic_params(
3099 db,
3100 &mut diagnostics,
3101 &mut resolver,
3102 module_file_id,
3103 &declaration.generic_params(db),
3104 );
3105 let inference = &mut resolver.inference();
3106 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3107
3108 let generic_params = inference.rewrite(generic_params).no_err();
3109 let resolver_data = Arc::new(resolver.data);
3110 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
3111}
3112
3113pub fn impl_function_attributes(
3115 db: &dyn SemanticGroup,
3116 impl_function_id: ImplFunctionId,
3117) -> Maybe<Vec<Attribute>> {
3118 Ok(db
3119 .priv_impl_function_declaration_data(impl_function_id)?
3120 .function_declaration_data
3121 .attributes)
3122}
3123
3124pub fn impl_function_resolver_data(
3126 db: &dyn SemanticGroup,
3127 impl_function_id: ImplFunctionId,
3128) -> Maybe<Arc<ResolverData>> {
3129 Ok(db
3130 .priv_impl_function_declaration_data(impl_function_id)?
3131 .function_declaration_data
3132 .resolver_data)
3133}
3134
3135pub fn impl_function_declaration_inline_config(
3137 db: &dyn SemanticGroup,
3138 impl_function_id: ImplFunctionId,
3139) -> Maybe<InlineConfiguration> {
3140 Ok(db
3141 .priv_impl_function_declaration_data(impl_function_id)?
3142 .function_declaration_data
3143 .inline_config)
3144}
3145
3146pub fn impl_function_declaration_implicit_precedence(
3148 db: &dyn SemanticGroup,
3149 impl_function_id: ImplFunctionId,
3150) -> Maybe<ImplicitPrecedence> {
3151 Ok(db
3152 .priv_impl_function_declaration_data(impl_function_id)?
3153 .function_declaration_data
3154 .implicit_precedence)
3155}
3156
3157pub fn impl_function_declaration_implicits(
3159 db: &dyn SemanticGroup,
3160 impl_function_id: ImplFunctionId,
3161) -> Maybe<Vec<TypeId>> {
3162 Ok(db
3163 .priv_impl_function_declaration_data(impl_function_id)?
3164 .function_declaration_data
3165 .signature
3166 .implicits)
3167}
3168
3169pub fn impl_function_trait_function(
3171 db: &dyn SemanticGroup,
3172 impl_function_id: ImplFunctionId,
3173) -> Maybe<TraitFunctionId> {
3174 db.priv_impl_function_declaration_data(impl_function_id)?.trait_function_id
3175}
3176
3177pub fn priv_impl_function_declaration_data(
3181 db: &dyn SemanticGroup,
3182 impl_function_id: ImplFunctionId,
3183) -> Maybe<ImplFunctionDeclarationData> {
3184 let mut diagnostics = SemanticDiagnostics::default();
3185 let impl_def_id = impl_function_id.impl_def_id(db);
3186 let data = db.priv_impl_definition_data(impl_def_id)?;
3187 let function_syntax = &data.function_asts[&impl_function_id];
3188 let declaration = function_syntax.declaration(db);
3189
3190 let generic_params_data = db.priv_impl_function_generic_params_data(impl_function_id)?;
3191 let generic_params = generic_params_data.generic_params;
3192 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3193 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3194 let mut resolver = Resolver::with_data(
3195 db,
3196 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3197 );
3198 diagnostics.extend(generic_params_data.diagnostics);
3199 resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3200
3201 let mut environment = Environment::empty();
3202 let signature = semantic::Signature::from_ast(
3203 &mut diagnostics,
3204 db,
3205 &mut resolver,
3206 &declaration,
3207 FunctionTitleId::Impl(impl_function_id),
3208 &mut environment,
3209 );
3210
3211 let attributes = function_syntax.attributes(db).structurize(db);
3212 let (implicit_precedence, _) =
3213 get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
3214
3215 let inference = &mut resolver.inference();
3216 inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3218 let trait_function_id = validate_impl_function_signature(
3219 db,
3220 &mut diagnostics,
3221 inference,
3222 ValidateImplFunctionSignatureParams {
3223 impl_function_id,
3224 signature_syntax: &declaration.signature(db),
3225 signature: &signature,
3226 impl_function_syntax: function_syntax,
3227 impl_func_generics: &generic_params,
3228 },
3229 );
3230
3231 let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3232
3233 forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3234
3235 let signature = inference.rewrite(signature).no_err();
3236 let generic_params = inference.rewrite(generic_params).no_err();
3237
3238 let resolver_data = Arc::new(resolver.data);
3239 Ok(ImplFunctionDeclarationData {
3240 function_declaration_data: FunctionDeclarationData {
3241 diagnostics: diagnostics.build(),
3242 signature,
3243 generic_params,
3244 environment,
3245 attributes,
3246 resolver_data,
3247 inline_config,
3248 implicit_precedence,
3249 },
3250 trait_function_id,
3251 })
3252}
3253
3254struct ValidateImplFunctionSignatureParams<'a> {
3256 impl_function_id: ImplFunctionId,
3258 signature_syntax: &'a ast::FunctionSignature,
3260 signature: &'a semantic::Signature,
3262 impl_function_syntax: &'a ast::FunctionWithBody,
3264 impl_func_generics: &'a [GenericParam],
3266}
3267
3268fn validate_impl_function_signature(
3270 db: &dyn SemanticGroup,
3271 diagnostics: &mut SemanticDiagnostics,
3272 inference: &mut Inference<'_>,
3273 ValidateImplFunctionSignatureParams {
3274 impl_function_id,
3275 signature_syntax,
3276 signature,
3277 impl_function_syntax,
3278 impl_func_generics,
3279 }: ValidateImplFunctionSignatureParams<'_>,
3280) -> Maybe<TraitFunctionId> {
3281 let impl_def_id = impl_function_id.impl_def_id(db);
3282 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3283 let trait_id = concrete_trait_id.trait_id(db);
3284 let function_name = impl_function_id.name(db);
3285 let trait_function_id =
3286 db.trait_function_by_name(trait_id, function_name.clone())?.ok_or_else(|| {
3287 diagnostics.report(
3288 impl_function_syntax.stable_ptr(db),
3289 ImplItemNotInTrait {
3290 impl_def_id,
3291 impl_item_name: function_name,
3292 trait_id,
3293 item_kind: "function".into(),
3294 },
3295 )
3296 })?;
3297 let concrete_trait_function =
3298 ConcreteTraitGenericFunctionId::new(db, concrete_trait_id, trait_function_id);
3299 let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3300
3301 let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3305 if impl_func_generics.len() != func_generics.len() {
3306 diagnostics.report(
3307 impl_function_syntax.declaration(db).name(db).stable_ptr(db),
3308 WrongNumberOfGenericParamsForImplFunction {
3309 expected: func_generics.len(),
3310 actual: impl_func_generics.len(),
3311 },
3312 );
3313 return Ok(trait_function_id);
3314 }
3315 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3316 let func_generics: Vec<GenericParam> = impl_def_substitution.substitute(db, func_generics)?;
3317
3318 let function_substitution =
3319 GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3320
3321 for (trait_generic_param, generic_param) in izip!(func_generics, impl_func_generics.iter()) {
3322 if let Some(name) = trait_generic_param.id().name(db) {
3323 if Some(name.clone()) != generic_param.id().name(db) {
3324 diagnostics.report(
3325 generic_param.stable_ptr(db),
3326 WrongParameterName {
3327 impl_def_id,
3328 impl_function_id,
3329 trait_id,
3330 expected_name: name,
3331 },
3332 );
3333 }
3334 }
3335 match (generic_param, trait_generic_param) {
3336 (GenericParam::Type(_), GenericParam::Type(_)) => {}
3337 (GenericParam::Impl(generic_param), GenericParam::Impl(trait_generic_param))
3338 | (GenericParam::NegImpl(generic_param), GenericParam::NegImpl(trait_generic_param)) => {
3339 let rewritten_trait_param_trait =
3340 function_substitution.substitute(db, trait_generic_param.concrete_trait)?;
3341 let rewritten_trait_param_type_constraints =
3342 function_substitution.substitute(db, trait_generic_param.type_constraints)?;
3343 generic_param
3344 .concrete_trait
3345 .map(|actual_trait| {
3346 rewritten_trait_param_trait
3347 .map(|expected_trait| {
3348 if actual_trait != expected_trait
3349 || generic_param.type_constraints
3350 != rewritten_trait_param_type_constraints
3351 {
3352 diagnostics.report(
3353 generic_param.id.stable_ptr(db),
3354 WrongGenericParamTraitForImplFunction {
3355 impl_def_id,
3356 impl_function_id,
3357 trait_id,
3358 expected_trait,
3359 actual_trait,
3360 },
3361 );
3362 }
3363 })
3364 .ok();
3365 })
3366 .ok();
3367 }
3368 (GenericParam::Const(generic_param), GenericParam::Const(trait_generic_param)) => {
3369 let expected_ty = function_substitution.substitute(db, trait_generic_param.ty)?;
3370 if generic_param.ty != expected_ty {
3371 diagnostics.report(
3372 generic_param.id.stable_ptr(db),
3373 WrongParameterType {
3374 impl_def_id,
3375 impl_function_id,
3376 trait_id,
3377 expected_ty,
3378 actual_ty: generic_param.ty,
3379 },
3380 );
3381 }
3382 }
3383 (generic_param, trait_generic_param) => {
3384 diagnostics.report(
3385 generic_param.stable_ptr(db),
3386 WrongGenericParamKindForImplFunction {
3387 impl_def_id,
3388 impl_function_id,
3389 trait_id,
3390 expected_kind: trait_generic_param.kind(),
3391 actual_kind: generic_param.kind(),
3392 },
3393 );
3394 }
3395 }
3396 }
3397
3398 let concrete_trait_signature =
3399 function_substitution.substitute(db, concrete_trait_signature)?;
3400
3401 if signature.params.len() != concrete_trait_signature.params.len() {
3402 diagnostics.report(
3403 signature_syntax.parameters(db).stable_ptr(db),
3404 WrongNumberOfParameters {
3405 impl_def_id,
3406 impl_function_id,
3407 trait_id,
3408 expected: concrete_trait_signature.params.len(),
3409 actual: signature.params.len(),
3410 },
3411 );
3412 }
3413 let concrete_trait_signature =
3414 impl_def_substitution.substitute(db, concrete_trait_signature)?;
3415 for (param, trait_param) in
3416 izip!(signature.params.iter(), concrete_trait_signature.params.iter())
3417 {
3418 let expected_ty = inference.rewrite(trait_param.ty).no_err();
3419 let actual_ty = inference.rewrite(param.ty).no_err();
3420
3421 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3422 diagnostics.report(
3423 extract_matches!(
3424 param.stable_ptr(db).lookup(db).type_clause(db),
3425 OptionTypeClause::TypeClause
3426 )
3427 .ty(db)
3428 .stable_ptr(db),
3429 WrongParameterType {
3430 impl_def_id,
3431 impl_function_id,
3432 trait_id,
3433 expected_ty,
3434 actual_ty,
3435 },
3436 );
3437 }
3438
3439 if trait_param.mutability != param.mutability {
3440 if trait_param.mutability == Mutability::Reference {
3441 diagnostics.report(
3442 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3443 ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3444 );
3445 }
3446
3447 if param.mutability == Mutability::Reference {
3448 diagnostics.report(
3449 param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3450 ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3451 );
3452 }
3453 }
3454
3455 if trait_param.name != param.name {
3456 diagnostics.report(
3457 param.stable_ptr(db).lookup(db).name(db).stable_ptr(db),
3458 WrongParameterName {
3459 impl_def_id,
3460 impl_function_id,
3461 trait_id,
3462 expected_name: trait_param.name.clone(),
3463 },
3464 );
3465 }
3466 }
3467
3468 if !concrete_trait_signature.panicable && signature.panicable {
3469 diagnostics.report(
3470 signature_syntax.stable_ptr(db),
3471 PassPanicAsNopanic { impl_function_id, trait_id },
3472 );
3473 }
3474
3475 if concrete_trait_signature.is_const && !signature.is_const {
3476 diagnostics.report(
3477 signature_syntax.stable_ptr(db),
3478 PassConstAsNonConst { impl_function_id, trait_id },
3479 );
3480 }
3481
3482 let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3483 let actual_ty = inference.rewrite(signature.return_type).no_err();
3484
3485 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3486 let location_ptr = match signature_syntax.ret_ty(db) {
3487 OptionReturnTypeClause::ReturnTypeClause(ret_ty) => ret_ty.ty(db).as_syntax_node(),
3488 OptionReturnTypeClause::Empty(_) => {
3489 impl_function_syntax.body(db).lbrace(db).as_syntax_node()
3490 }
3491 }
3492 .stable_ptr(db);
3493 diagnostics.report(
3494 location_ptr,
3495 WrongReturnTypeForImpl {
3496 impl_def_id,
3497 impl_function_id,
3498 trait_id,
3499 expected_ty,
3500 actual_ty,
3501 },
3502 );
3503 }
3504 Ok(trait_function_id)
3505}
3506
3507pub fn impl_function_body_diagnostics(
3513 db: &dyn SemanticGroup,
3514 impl_function_id: ImplFunctionId,
3515) -> Diagnostics<SemanticDiagnostic> {
3516 db.priv_impl_function_body_data(impl_function_id)
3517 .map(|data| data.diagnostics)
3518 .unwrap_or_default()
3519}
3520
3521pub fn impl_function_body(
3523 db: &dyn SemanticGroup,
3524 impl_function_id: ImplFunctionId,
3525) -> Maybe<Arc<FunctionBody>> {
3526 Ok(db.priv_impl_function_body_data(impl_function_id)?.body)
3527}
3528
3529pub fn impl_function_body_resolver_data(
3531 db: &dyn SemanticGroup,
3532 impl_function_id: ImplFunctionId,
3533) -> Maybe<Arc<ResolverData>> {
3534 Ok(db.priv_impl_function_body_data(impl_function_id)?.resolver_data)
3535}
3536
3537pub fn priv_impl_function_body_data(
3541 db: &dyn SemanticGroup,
3542 impl_function_id: ImplFunctionId,
3543) -> Maybe<FunctionBodyData> {
3544 let mut diagnostics = SemanticDiagnostics::default();
3545 let impl_def_id = impl_function_id.impl_def_id(db);
3546 let data = db.priv_impl_definition_data(impl_def_id)?;
3547 let function_syntax = &data.function_asts[&impl_function_id];
3548 let declaration = db.priv_impl_function_declaration_data(impl_function_id)?;
3550 let parent_resolver_data = declaration.function_declaration_data.resolver_data;
3551 let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3552 ImplItemId::Function(impl_function_id),
3553 ));
3554 let resolver =
3555 Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3556 let environment: Environment = declaration.function_declaration_data.environment;
3557
3558 let function_id = (|| {
3559 let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3560 let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3561
3562 let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3563 impl_id: ImplLongId::Concrete(
3564 ConcreteImplLongId {
3565 impl_def_id,
3566 generic_args: generic_params_to_args(&generic_parameters, db),
3567 }
3568 .intern(db),
3569 )
3570 .intern(db),
3571 function: trait_function_id,
3572 });
3573
3574 Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3575 })();
3576 let mut ctx = ComputationContext::new(
3578 db,
3579 &mut diagnostics,
3580 resolver,
3581 Some(&declaration.function_declaration_data.signature),
3582 environment,
3583 ContextFunction::Function(function_id),
3584 );
3585 let function_body = function_syntax.body(db);
3586 let return_type = declaration.function_declaration_data.signature.return_type;
3587 let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3588 let ComputationContext { arenas: Arenas { exprs, patterns, statements }, resolver, .. } = ctx;
3589
3590 let expr_lookup: UnorderedHashMap<_, _> =
3591 exprs.iter().map(|(expr_id, expr)| (expr.stable_ptr(), expr_id)).collect();
3592 let pattern_lookup: UnorderedHashMap<_, _> =
3593 patterns.iter().map(|(pattern_id, pattern)| (pattern.stable_ptr(), pattern_id)).collect();
3594 let resolver_data = Arc::new(resolver.data);
3595 Ok(FunctionBodyData {
3596 diagnostics: diagnostics.build(),
3597 expr_lookup,
3598 pattern_lookup,
3599 resolver_data,
3600 body: Arc::new(FunctionBody { arenas: Arenas { exprs, patterns, statements }, body_expr }),
3601 })
3602}
3603
3604pub fn priv_impl_is_fully_concrete(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3605 impl_id.lookup_intern(db).is_fully_concrete(db)
3606}
3607
3608pub fn priv_impl_is_var_free(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3609 impl_id.lookup_intern(db).is_var_free(db)
3610}