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