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::{
25 Intern, LookupIntern, define_short_id, extract_matches, try_extract_matches,
26};
27use itertools::{Itertools, chain, izip};
28use smol_str::SmolStr;
29use syntax::attribute::structured::{Attribute, AttributeListStructurize};
30use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
31use syntax::node::db::SyntaxGroup;
32use syntax::node::helpers::OptionWrappedGenericParamListHelper;
33use syntax::node::ids::SyntaxStablePtrId;
34use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
35
36use super::constant::{
37 ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
38 constant_semantic_data_helper,
39};
40use super::enm::SemanticEnumEx;
41use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
42use super::functions::{
43 FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
44 forbid_inline_always_with_impl_generic_param,
45};
46use super::generics::{
47 GenericArgumentHead, GenericParamImpl, GenericParamsData, generic_params_to_args,
48 semantic_generic_params,
49};
50use super::impl_alias::{
51 ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
52 impl_alias_semantic_data_helper,
53};
54use super::trt::{
55 ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
56 ConcreteTraitImplId,
57};
58use super::type_aliases::{
59 TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
60 type_alias_semantic_data_helper,
61};
62use super::visibility::peek_visible_in;
63use super::{TraitOrImplContext, resolve_trait_path};
64use crate::corelib::{
65 CoreTraitContext, concrete_destruct_trait, concrete_drop_trait, copy_trait, core_crate,
66 deref_trait, destruct_trait, drop_trait, fn_once_trait, fn_trait, get_core_trait,
67 panic_destruct_trait,
68};
69use crate::db::{SemanticGroup, get_resolver_data_options};
70use crate::diagnostic::SemanticDiagnosticKind::{self, *};
71use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
72use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
73use crate::expr::inference::canonic::ResultNoErrEx;
74use crate::expr::inference::conform::InferenceConform;
75use crate::expr::inference::infers::InferenceEmbeddings;
76use crate::expr::inference::solver::SolutionSet;
77use crate::expr::inference::{
78 ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId,
79};
80use crate::items::function_with_body::get_implicit_precedence;
81use crate::items::functions::ImplicitPrecedence;
82use crate::items::us::SemanticUseEx;
83use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem, Resolver, ResolverData};
84use crate::substitution::{GenericSubstitution, SemanticRewriter, SubstitutionRewriter};
85use crate::types::{ImplTypeId, add_type_based_diagnostics, get_impl_at_context, resolve_type};
86use crate::{
87 Arenas, ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
88 GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
89 semantic_object_for_id,
90};
91
92#[cfg(test)]
93#[path = "imp_test.rs"]
94mod test;
95
96#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
97pub struct ConcreteImplLongId {
98 pub impl_def_id: ImplDefId,
99 pub generic_args: Vec<GenericArgumentId>,
100}
101define_short_id!(
102 ConcreteImplId,
103 ConcreteImplLongId,
104 SemanticGroup,
105 lookup_intern_concrete_impl,
106 intern_concrete_impl
107);
108semantic_object_for_id!(
109 ConcreteImplId,
110 lookup_intern_concrete_impl,
111 intern_concrete_impl,
112 ConcreteImplLongId
113);
114impl DebugWithDb<dyn SemanticGroup> for ConcreteImplLongId {
115 fn fmt(
116 &self,
117 f: &mut std::fmt::Formatter<'_>,
118 db: &(dyn SemanticGroup + 'static),
119 ) -> std::fmt::Result {
120 write!(f, "{}", self.impl_def_id.full_path(db.upcast()))?;
121 if !self.generic_args.is_empty() {
122 write!(f, "::<")?;
123 for (i, arg) in self.generic_args.iter().enumerate() {
124 if i > 0 {
125 write!(f, ", ")?;
126 }
127 write!(f, "{}", arg.format(db))?;
128 }
129 write!(f, ">")?;
130 }
131 Ok(())
132 }
133}
134impl ConcreteImplId {
135 pub fn impl_def_id(&self, db: &dyn SemanticGroup) -> ImplDefId {
136 self.lookup_intern(db).impl_def_id
137 }
138 pub fn get_impl_function(
139 &self,
140 db: &dyn SemanticGroup,
141 function: TraitFunctionId,
142 ) -> Maybe<Option<ImplFunctionId>> {
143 db.impl_function_by_trait_function(self.impl_def_id(db), function)
144 }
145 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
146 self.impl_def_id(db).name(db.upcast())
147 }
148 pub fn substitution(&self, db: &dyn SemanticGroup) -> Maybe<GenericSubstitution> {
149 Ok(GenericSubstitution::from_impl(ImplLongId::Concrete(*self).intern(db)).concat(
150 GenericSubstitution::new(
151 &db.impl_def_generic_params(self.impl_def_id(db))?,
152 &self.lookup_intern(db).generic_args,
153 ),
154 ))
155 }
156 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
158 self.lookup_intern(db)
159 .generic_args
160 .iter()
161 .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
162 }
163 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
165 self.lookup_intern(db)
166 .generic_args
167 .iter()
168 .all(|generic_argument_id| generic_argument_id.is_var_free(db))
169 }
170}
171
172#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
175pub enum ImplLongId {
176 Concrete(ConcreteImplId),
177 GenericParameter(GenericParamId),
178 ImplVar(ImplVarId),
179 ImplImpl(ImplImplId),
180 TraitImpl(TraitImplId),
181 GeneratedImpl(GeneratedImplId),
182}
183impl ImplLongId {
184 pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
186 Some(match self {
187 ImplLongId::Concrete(concrete) => ImplHead::Concrete(concrete.impl_def_id(db)),
188 ImplLongId::GenericParameter(_)
189 | ImplLongId::ImplVar(_)
190 | ImplLongId::ImplImpl(_)
191 | ImplLongId::TraitImpl(_)
192 | ImplLongId::GeneratedImpl(_) => {
193 return None;
194 }
195 })
196 }
197 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
198 match self {
199 ImplLongId::Concrete(concrete_impl) => concrete_impl.name(db),
200 ImplLongId::GenericParameter(generic_param_impl) => {
201 generic_param_impl.name(db.upcast()).unwrap_or_else(|| "_".into())
202 }
203 ImplLongId::ImplVar(var) => {
204 format!("ImplVar({})", var.concrete_trait_id(db).full_path(db)).into()
205 }
206 ImplLongId::ImplImpl(impl_impl) => format!(
207 "{}::{}",
208 impl_impl.impl_id().name(db.upcast()),
209 db.impl_impl_concrete_trait(*impl_impl)
210 .map(|trait_impl| trait_impl.full_path(db))
211 .unwrap_or_else(|_| "_".into())
212 )
213 .into(),
214 ImplLongId::TraitImpl(trait_impl) => trait_impl.name(db.upcast()),
215 ImplLongId::GeneratedImpl(generated_impl) => {
216 format!("{:?}", generated_impl.debug(db.elongate())).into()
217 }
218 }
219 }
220 pub fn format(&self, db: &dyn SemanticGroup) -> String {
221 match self {
222 ImplLongId::Concrete(concrete_impl) => {
223 format!("{:?}", concrete_impl.debug(db.elongate()))
224 }
225 ImplLongId::GenericParameter(generic_param_impl) => {
226 generic_param_impl.format(db.upcast())
227 }
228 ImplLongId::ImplVar(var) => format!("{var:?}"),
229 ImplLongId::ImplImpl(impl_impl) => format!("{:?}", impl_impl.debug(db.elongate())),
230 ImplLongId::TraitImpl(trait_impl) => format!("{:?}", trait_impl.debug(db.elongate())),
231 ImplLongId::GeneratedImpl(generated_impl) => {
232 format!("{:?}", generated_impl.debug(db.elongate()))
233 }
234 }
235 }
236
237 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
239 match self {
240 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
241 ImplLongId::GenericParameter(_) | ImplLongId::TraitImpl(_) => true,
242 ImplLongId::ImplVar(_) => false,
243 ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
244 ImplLongId::GeneratedImpl(generated_impl) => {
245 generated_impl.concrete_trait(db).is_var_free(db)
246 && generated_impl
247 .lookup_intern(db)
248 .impl_items
249 .0
250 .values()
251 .all(|type_id| type_id.is_var_free(db))
252 }
253 }
254 }
255
256 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
258 match self {
259 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
260 ImplLongId::GenericParameter(_) => false,
261 ImplLongId::ImplVar(_) => false,
262 ImplLongId::ImplImpl(_) | ImplLongId::TraitImpl(_) => false,
263 ImplLongId::GeneratedImpl(generated_impl) => {
264 generated_impl.concrete_trait(db).is_fully_concrete(db)
265 && generated_impl
266 .lookup_intern(db)
267 .impl_items
268 .0
269 .values()
270 .all(|type_id| type_id.is_fully_concrete(db))
271 }
272 }
273 }
274}
275impl DebugWithDb<dyn SemanticGroup> for ImplLongId {
276 fn fmt(
277 &self,
278 f: &mut std::fmt::Formatter<'_>,
279 db: &(dyn SemanticGroup + 'static),
280 ) -> std::fmt::Result {
281 match self {
282 ImplLongId::Concrete(concrete_impl_id) => write!(f, "{:?}", concrete_impl_id.debug(db)),
283 ImplLongId::GenericParameter(param) => write!(f, "{:?}", param.debug(db)),
284 ImplLongId::ImplVar(var) => write!(f, "?{}", var.lookup_intern(db).id.0),
285 ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
286 ImplLongId::TraitImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
287 ImplLongId::GeneratedImpl(generated_impl) => {
288 write!(f, "{:?}", generated_impl.debug(db))
289 }
290 }
291 }
292}
293
294define_short_id!(ImplId, ImplLongId, SemanticGroup, lookup_intern_impl, intern_impl);
295semantic_object_for_id!(ImplId, lookup_intern_impl, intern_impl, ImplLongId);
296impl ImplId {
297 pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
298 db.impl_concrete_trait(*self)
299 }
300
301 pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
303 db.priv_impl_is_fully_concrete(*self)
304 }
305
306 pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
308 db.priv_impl_is_var_free(*self)
309 }
310
311 pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
313 self.lookup_intern(db).head(db)
314 }
315
316 pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
318 self.lookup_intern(db).name(db)
319 }
320
321 pub fn format(&self, db: &dyn SemanticGroup) -> String {
322 self.lookup_intern(db).format(db)
323 }
324}
325
326define_short_id!(
327 GeneratedImplId,
328 GeneratedImplLongId,
329 SemanticGroup,
330 lookup_intern_generated_impl,
331 intern_generated_impl
332);
333semantic_object_for_id!(
334 GeneratedImplId,
335 lookup_intern_generated_impl,
336 intern_generated_impl,
337 GeneratedImplLongId
338);
339
340impl GeneratedImplId {
341 pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
342 db.lookup_intern_generated_impl(self).concrete_trait
343 }
344
345 pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
346 self.concrete_trait(db).trait_id(db)
347 }
348}
349
350#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
354pub struct GeneratedImplLongId {
355 pub concrete_trait: ConcreteTraitId,
356 pub generic_params: Vec<GenericParam>,
359 pub impl_items: GeneratedImplItems,
360}
361#[derive(Clone, Debug, Default, PartialEq, Eq, SemanticObject)]
362pub struct GeneratedImplItems(pub OrderedHashMap<TraitTypeId, TypeId>);
363impl Hash for GeneratedImplItems {
364 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
365 self.0.iter().for_each(|(trait_type_id, type_id)| {
366 trait_type_id.hash(state);
367 type_id.hash(state);
368 });
369 }
370}
371pub enum GeneratedImplAssociatedTypes {
372 Unresolved,
374 Resolved(OrderedHashMap<TraitTypeId, TypeId>),
376}
377
378impl DebugWithDb<dyn SemanticGroup> for GeneratedImplLongId {
379 fn fmt(
380 &self,
381 f: &mut std::fmt::Formatter<'_>,
382 db: &(dyn SemanticGroup + 'static),
383 ) -> std::fmt::Result {
384 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
385 }
386}
387
388#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
390pub struct ImplImplId {
391 impl_id: ImplId,
393 trait_impl_id: TraitImplId,
395}
396
397impl ImplImplId {
398 pub fn new(impl_id: ImplId, trait_impl_id: TraitImplId, db: &dyn SemanticGroup) -> Self {
401 if let crate::items::imp::ImplLongId::Concrete(concrete_impl) = impl_id.lookup_intern(db) {
402 let impl_def_id = concrete_impl.impl_def_id(db);
403 assert_eq!(Ok(trait_impl_id.trait_id(db.upcast())), db.impl_def_trait(impl_def_id));
404 }
405
406 ImplImplId { impl_id, trait_impl_id }
407 }
408 pub fn impl_id(&self) -> ImplId {
409 self.impl_id
410 }
411 pub fn trait_impl_id(&self) -> TraitImplId {
412 self.trait_impl_id
413 }
414
415 pub fn concrete_trait_impl_id(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitImplId> {
416 Ok(ConcreteTraitImplId::new(db, self.impl_id.concrete_trait(db)?, self.trait_impl_id))
417 }
418
419 pub fn format(&self, db: &dyn SemanticGroup) -> SmolStr {
420 format!("{}::{}", self.impl_id.name(db.upcast()), self.trait_impl_id.name(db.upcast()),)
421 .into()
422 }
423}
424impl DebugWithDb<dyn SemanticGroup> for ImplImplId {
425 fn fmt(
426 &self,
427 f: &mut std::fmt::Formatter<'_>,
428 db: &(dyn SemanticGroup + 'static),
429 ) -> std::fmt::Result {
430 write!(f, "{}", self.format(db))
431 }
432}
433
434impl UnstableSalsaId for ImplId {
435 fn get_internal_id(&self) -> &salsa::InternId {
436 &self.0
437 }
438}
439
440#[derive(Clone, Debug, Hash, PartialEq, Eq)]
446pub enum ImplHead {
447 Concrete(ImplDefId),
448}
449
450#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
453#[debug_db(dyn SemanticGroup + 'static)]
454pub struct ImplDeclarationData {
455 diagnostics: Diagnostics<SemanticDiagnostic>,
456 generic_params: Vec<semantic::GenericParam>,
457 concrete_trait: Maybe<ConcreteTraitId>,
459 attributes: Vec<Attribute>,
460 resolver_data: Arc<ResolverData>,
461}
462
463pub fn impl_semantic_declaration_diagnostics(
467 db: &dyn SemanticGroup,
468 impl_def_id: ImplDefId,
469) -> Diagnostics<SemanticDiagnostic> {
470 db.priv_impl_declaration_data(impl_def_id).map(|data| data.diagnostics).unwrap_or_default()
471}
472
473pub fn impl_def_generic_params_data(
475 db: &dyn SemanticGroup,
476 impl_def_id: ImplDefId,
477) -> Maybe<GenericParamsData> {
478 let module_file_id = impl_def_id.module_file_id(db.upcast());
479 let mut diagnostics = SemanticDiagnostics::default();
480
481 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
482 let inference_id =
483 InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
484
485 let mut resolver = Resolver::new(db, module_file_id, inference_id);
486 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
487 let generic_params = semantic_generic_params(
488 db,
489 &mut diagnostics,
490 &mut resolver,
491 module_file_id,
492 &impl_ast.generic_params(db.upcast()),
493 );
494 let inference = &mut resolver.inference();
495 inference.finalize(&mut diagnostics, impl_ast.stable_ptr().untyped());
496
497 let generic_params = inference.rewrite(generic_params).no_err();
498 let resolver_data = Arc::new(resolver.data);
499 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
500}
501
502pub fn impl_def_generic_params(
504 db: &dyn SemanticGroup,
505 impl_def_id: ImplDefId,
506) -> Maybe<Vec<semantic::GenericParam>> {
507 Ok(db.impl_def_generic_params_data(impl_def_id)?.generic_params)
508}
509
510pub fn impl_def_resolver_data(
512 db: &dyn SemanticGroup,
513 impl_def_id: ImplDefId,
514) -> Maybe<Arc<ResolverData>> {
515 Ok(db.priv_impl_declaration_data(impl_def_id)?.resolver_data)
516}
517
518pub fn impl_def_resolver_data_cycle(
520 db: &dyn SemanticGroup,
521 _cycle: &salsa::Cycle,
522 impl_def_id: &ImplDefId,
523) -> Maybe<Arc<ResolverData>> {
524 impl_def_resolver_data(db, *impl_def_id)
526}
527
528pub fn impl_def_concrete_trait(
530 db: &dyn SemanticGroup,
531 impl_def_id: ImplDefId,
532) -> Maybe<ConcreteTraitId> {
533 db.priv_impl_declaration_data(impl_def_id)?.concrete_trait
534}
535
536pub fn impl_def_concrete_trait_cycle(
538 db: &dyn SemanticGroup,
539 _cycle: &salsa::Cycle,
540 impl_def_id: &ImplDefId,
541) -> Maybe<ConcreteTraitId> {
542 impl_def_concrete_trait(db, *impl_def_id)
544}
545
546pub fn impl_def_substitution(
548 db: &dyn SemanticGroup,
549 impl_def_id: ImplDefId,
550) -> Maybe<Arc<GenericSubstitution>> {
551 let params = db.impl_def_generic_params(impl_def_id)?;
552 let generic_args = generic_params_to_args(¶ms, db);
553 Ok(Arc::new(ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)?))
554}
555
556pub fn impl_def_attributes(
558 db: &dyn SemanticGroup,
559 impl_def_id: ImplDefId,
560) -> Maybe<Vec<Attribute>> {
561 Ok(db.priv_impl_declaration_data(impl_def_id)?.attributes)
562}
563
564pub fn impl_def_trait(db: &dyn SemanticGroup, impl_def_id: ImplDefId) -> Maybe<TraitId> {
566 let module_file_id = impl_def_id.module_file_id(db.upcast());
567 let mut diagnostics = SemanticDiagnostics::default();
568
569 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
570 let inference_id = InferenceId::ImplDefTrait(impl_def_id);
571
572 let mut resolver = Resolver::new(db, module_file_id, inference_id);
573 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
574
575 let trait_path_syntax = impl_ast.trait_path(db.upcast());
576
577 resolve_trait_path(&mut diagnostics, &mut resolver, &trait_path_syntax)
578}
579
580pub fn impl_concrete_trait(db: &dyn SemanticGroup, impl_id: ImplId) -> Maybe<ConcreteTraitId> {
582 match impl_id.lookup_intern(db) {
583 ImplLongId::Concrete(concrete_impl_id) => {
584 let long_impl = concrete_impl_id.lookup_intern(db);
585 let substitution = GenericSubstitution::new(
586 &db.impl_def_generic_params(long_impl.impl_def_id)?,
587 &long_impl.generic_args,
588 );
589
590 let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
591 SubstitutionRewriter { db, substitution: &substitution }.rewrite(impl_concrete_trait_id)
592 }
593 ImplLongId::GenericParameter(param) => {
594 let param_impl =
595 extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
596 param_impl.concrete_trait
597 }
598 ImplLongId::ImplVar(var) => Ok(var.lookup_intern(db).concrete_trait_id),
599 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl),
600 ImplLongId::TraitImpl(trait_impl) => db.trait_impl_concrete_trait(trait_impl),
601 ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
602 }
603}
604
605pub fn priv_impl_declaration_data_cycle(
609 db: &dyn SemanticGroup,
610 _cycle: &salsa::Cycle,
611 impl_def_id: &ImplDefId,
612) -> Maybe<ImplDeclarationData> {
613 priv_impl_declaration_data_inner(db, *impl_def_id, false)
614}
615
616pub fn priv_impl_declaration_data(
618 db: &dyn SemanticGroup,
619 impl_def_id: ImplDefId,
620) -> Maybe<ImplDeclarationData> {
621 priv_impl_declaration_data_inner(db, impl_def_id, true)
622}
623
624pub fn priv_impl_declaration_data_inner(
627 db: &dyn SemanticGroup,
628 impl_def_id: ImplDefId,
629 resolve_trait: bool,
630) -> Maybe<ImplDeclarationData> {
631 let mut diagnostics = SemanticDiagnostics::default();
632
633 let syntax_db = db.upcast();
637 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
638 let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
639 ModuleItemId::Impl(impl_def_id),
640 ));
641
642 let generic_params_data = db.impl_def_generic_params_data(impl_def_id)?;
644 let generic_params = generic_params_data.generic_params;
645 let mut resolver = Resolver::with_data(
646 db,
647 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
648 );
649 resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
650 diagnostics.extend(generic_params_data.diagnostics);
651 let trait_path_syntax = impl_ast.trait_path(syntax_db);
652
653 let concrete_trait = if resolve_trait {
654 match resolver.resolve_concrete_path(
655 &mut diagnostics,
656 &trait_path_syntax,
657 NotFoundItemType::Trait,
658 ) {
659 Ok(resolved_item) => try_extract_matches!(resolved_item, ResolvedConcreteItem::Trait)
660 .ok_or_else(|| diagnostics.report(&trait_path_syntax, NotATrait)),
661 Err(err) => Err(err),
662 }
663 } else {
664 Err(diagnostics.report(&trait_path_syntax, ImplRequirementCycle))
665 };
666
667 if let Ok(concrete_trait) = concrete_trait {
669 if [
670 get_core_trait(db, CoreTraitContext::MetaProgramming, "TypeEqual".into()),
671 fn_trait(db),
672 fn_once_trait(db),
673 ]
674 .contains(&concrete_trait.trait_id(db))
675 && impl_def_id.parent_module(db.upcast()).owning_crate(db.upcast()) != core_crate(db)
676 {
677 diagnostics.report(&trait_path_syntax, CompilerTraitReImplementation {
678 trait_id: concrete_trait.trait_id(db),
679 });
680 }
681 }
682
683 let inference = &mut resolver.inference();
685 inference.finalize(&mut diagnostics, impl_ast.stable_ptr().untyped());
686
687 let concrete_trait: Result<ConcreteTraitId, DiagnosticAdded> =
688 inference.rewrite(concrete_trait).no_err();
689 let generic_params: Vec<GenericParam> = inference.rewrite(generic_params).no_err();
690
691 let attributes = impl_ast.attributes(syntax_db).structurize(syntax_db);
692 let mut resolver_data = resolver.data;
693 resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
694 Ok(ImplDeclarationData {
695 diagnostics: diagnostics.build(),
696 generic_params,
697 concrete_trait,
698 attributes,
699 resolver_data: Arc::new(resolver_data),
700 })
701}
702
703#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
706#[debug_db(dyn SemanticGroup + 'static)]
707pub struct ImplDefinitionData {
708 diagnostics: Diagnostics<SemanticDiagnostic>,
713
714 function_asts: OrderedHashMap<ImplFunctionId, ast::FunctionWithBody>,
716 item_type_asts: Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>,
717 item_constant_asts: Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>,
718 item_impl_asts: Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>,
719
720 item_id_by_name: Arc<OrderedHashMap<SmolStr, ImplItemId>>,
722
723 implicit_impls_id_by_name: Arc<OrderedHashMap<SmolStr, TraitImplId>>,
725}
726
727pub fn impl_semantic_definition_diagnostics(
731 db: &dyn SemanticGroup,
732 impl_def_id: ImplDefId,
733) -> Diagnostics<SemanticDiagnostic> {
734 let mut diagnostics = DiagnosticsBuilder::default();
735
736 let Ok(data) = db.priv_impl_definition_data(impl_def_id) else {
737 return Diagnostics::default();
738 };
739
740 diagnostics.extend(data.diagnostics);
743 for impl_function_id in data.function_asts.keys() {
744 diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
745 diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
746 }
747 for impl_item_type_id in data.item_type_asts.keys() {
748 diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
749 if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
750 add_type_based_diagnostics(
751 db,
752 &mut diagnostics,
753 ty,
754 impl_item_type_id.stable_ptr(db.upcast()),
755 );
756 }
757 }
758 for impl_item_constant_id in data.item_constant_asts.keys() {
759 diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
760 }
761 for impl_item_impl_id in data.item_impl_asts.keys() {
762 diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
763 }
764 for implicit_impl_id in data.implicit_impls_id_by_name.values() {
765 diagnostics
766 .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
767 }
768 if diagnostics.error_count == 0 {
770 let trait_id = db
771 .priv_impl_declaration_data(impl_def_id)
772 .unwrap()
773 .concrete_trait
774 .unwrap()
775 .trait_id(db);
776 if trait_id == deref_trait(db) {
777 handle_deref_impl(db, impl_def_id, &mut diagnostics);
778 }
779 }
780 diagnostics.build()
781}
782
783fn handle_deref_impl(
785 db: &dyn SemanticGroup,
786 mut impl_def_id: ImplDefId,
787 diagnostics: &mut DiagnosticsBuilder<SemanticDiagnostic>,
788) {
789 let mut visited_impls: OrderedHashSet<ImplDefId> = OrderedHashSet::default();
790 let deref_trait_id = deref_trait(db);
791 loop {
792 let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
793 ConcreteTraitLongId {
794 trait_id: deref_trait_id,
795 generic_args: vec![GenericArgumentId::Type(ty)],
796 }
797 .intern(db)
798 }) else {
799 return;
802 };
803 impl_def_id = match impl_id.lookup_intern(db) {
804 ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
805 _ => return,
806 };
807
808 if !visited_impls.insert(impl_def_id) {
809 let deref_chain = visited_impls
810 .iter()
811 .map(|visited_impl| {
812 format!(
813 "{:?}",
814 db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db.elongate())
815 )
816 })
817 .join(" -> ");
818 diagnostics
819 .report(impl_def_id.stable_ptr(db.upcast()), SemanticDiagnosticKind::DerefCycle {
820 deref_chain,
821 });
822 return;
823 }
824 }
825}
826
827fn get_impl_based_on_single_impl_type(
831 db: &dyn SemanticGroup,
832 impl_def_id: ImplDefId,
833 concrete_trait_id: impl FnOnce(TypeId) -> ConcreteTraitId,
834) -> Result<ImplId, (InferenceError, ImplTypeDefId)> {
835 let data = db.priv_impl_definition_data(impl_def_id).unwrap();
836 let mut types_iter = data.item_type_asts.iter();
837 let (impl_item_type_id, _) = types_iter.next().unwrap();
838 if types_iter.next().is_some() {
839 panic!(
840 "get_impl_based_on_single_impl_type called with an impl that has more than one type"
841 );
842 }
843 let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
844 let module_file_id = impl_def_id.module_file_id(db.upcast());
845 let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
846 let generic_params_ids =
847 generic_params.iter().map(|generic_param| generic_param.id()).collect();
848 let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
849 get_impl_at_context(db, lookup_context, concrete_trait_id(ty), None)
850 .map_err(|err| (err, *impl_item_type_id))
851}
852
853pub fn impl_functions(
855 db: &dyn SemanticGroup,
856 impl_def_id: ImplDefId,
857) -> Maybe<OrderedHashMap<SmolStr, ImplFunctionId>> {
858 Ok(db
859 .priv_impl_definition_data(impl_def_id)?
860 .function_asts
861 .keys()
862 .map(|function_id| {
863 let function_long_id = function_id.lookup_intern(db);
864 (function_long_id.name(db.upcast()), *function_id)
865 })
866 .collect())
867}
868
869pub fn impl_function_by_trait_function(
871 db: &dyn SemanticGroup,
872 impl_def_id: ImplDefId,
873 trait_function_id: TraitFunctionId,
874) -> Maybe<Option<ImplFunctionId>> {
875 let defs_db = db.upcast();
876 let name = trait_function_id.name(defs_db);
877 for impl_function_id in db.priv_impl_definition_data(impl_def_id)?.function_asts.keys() {
878 if impl_function_id.lookup_intern(db).name(defs_db) == name {
879 return Ok(Some(*impl_function_id));
880 }
881 }
882 Ok(None)
883}
884
885pub fn impl_item_by_name(
887 db: &dyn SemanticGroup,
888 impl_def_id: ImplDefId,
889 name: SmolStr,
890) -> Maybe<Option<ImplItemId>> {
891 Ok(db.priv_impl_definition_data(impl_def_id)?.item_id_by_name.get(&name).cloned())
892}
893
894pub fn impl_implicit_impl_by_name(
896 db: &dyn SemanticGroup,
897 impl_def_id: ImplDefId,
898 name: SmolStr,
899) -> Maybe<Option<TraitImplId>> {
900 Ok(db.priv_impl_definition_data(impl_def_id)?.implicit_impls_id_by_name.get(&name).cloned())
901}
902
903pub fn impl_all_used_items(
905 db: &dyn SemanticGroup,
906 impl_def_id: ImplDefId,
907) -> Maybe<Arc<OrderedHashSet<LookupItemId>>> {
908 let mut all_used_items = db.impl_def_resolver_data(impl_def_id)?.used_items.clone();
909 let data = db.priv_impl_definition_data(impl_def_id)?;
910 for item in data.item_id_by_name.values() {
911 for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(*item), db) {
912 all_used_items.extend(resolver_data.used_items.iter().cloned());
913 }
914 }
915 Ok(all_used_items.into())
916}
917
918pub fn impl_types(
920 db: &dyn SemanticGroup,
921 impl_def_id: ImplDefId,
922) -> Maybe<Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>> {
923 Ok(db.priv_impl_definition_data(impl_def_id)?.item_type_asts)
924}
925
926pub fn impl_type_ids(
928 db: &dyn SemanticGroup,
929 impl_def_id: ImplDefId,
930) -> Maybe<Arc<[ImplTypeDefId]>> {
931 Ok(db.impl_types(impl_def_id)?.keys().copied().collect_vec().into())
932}
933
934pub fn impl_type_by_id(
936 db: &dyn SemanticGroup,
937 impl_type_id: ImplTypeDefId,
938) -> Maybe<Option<ast::ItemTypeAlias>> {
939 let impl_types = db.impl_types(impl_type_id.impl_def_id(db.upcast()))?;
940 Ok(impl_types.get(&impl_type_id).cloned())
941}
942
943pub fn impl_type_by_trait_type(
945 db: &dyn SemanticGroup,
946 impl_def_id: ImplDefId,
947 trait_type_id: TraitTypeId,
948) -> Maybe<ImplTypeDefId> {
949 if trait_type_id.trait_id(db.upcast()) != db.impl_def_trait(impl_def_id)? {
950 unreachable!(
951 "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
952 trait"
953 )
954 }
955
956 let defs_db = db.upcast();
957 let name = trait_type_id.name(defs_db);
958 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
960 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
961 None => Err(skip_diagnostic()),
962 })
963}
964
965pub fn impl_constants(
967 db: &dyn SemanticGroup,
968 impl_def_id: ImplDefId,
969) -> Maybe<Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>> {
970 Ok(db.priv_impl_definition_data(impl_def_id)?.item_constant_asts)
971}
972
973pub fn impl_constant_by_trait_constant(
975 db: &dyn SemanticGroup,
976 impl_def_id: ImplDefId,
977 trait_constant_id: TraitConstantId,
978) -> Maybe<ImplConstantDefId> {
979 if trait_constant_id.trait_id(db.upcast()) != db.impl_def_trait(impl_def_id)? {
980 unreachable!(
981 "impl_constant_by_trait_constant called with a trait constant that does not belong to \
982 the impl's trait"
983 )
984 }
985
986 let defs_db = db.upcast();
987 let name = trait_constant_id.name(defs_db);
988 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
990 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
991 None => Err(skip_diagnostic()),
992 })
993}
994
995pub fn impl_impls(
997 db: &dyn SemanticGroup,
998 impl_def_id: ImplDefId,
999) -> Maybe<Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>> {
1000 Ok(db.priv_impl_definition_data(impl_def_id)?.item_impl_asts)
1001}
1002
1003pub fn impl_impl_ids(
1005 db: &dyn SemanticGroup,
1006 impl_def_id: ImplDefId,
1007) -> Maybe<Arc<[ImplImplDefId]>> {
1008 Ok(db.impl_impls(impl_def_id)?.keys().copied().collect_vec().into())
1009}
1010
1011pub fn impl_impl_by_id(
1013 db: &dyn SemanticGroup,
1014 impl_impl_id: ImplImplDefId,
1015) -> Maybe<Option<ast::ItemImplAlias>> {
1016 let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db.upcast()))?;
1017 Ok(impl_impls.get(&impl_impl_id).cloned())
1018}
1019
1020pub fn impl_impl_by_trait_impl(
1022 db: &dyn SemanticGroup,
1023 impl_def_id: ImplDefId,
1024 trait_impl_id: TraitImplId,
1025) -> Maybe<ImplImplDefId> {
1026 if trait_impl_id.trait_id(db.upcast()) != db.impl_def_trait(impl_def_id)? {
1027 unreachable!(
1028 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1029 trait"
1030 )
1031 }
1032
1033 let defs_db = db.upcast();
1034 let name = trait_impl_id.name(defs_db);
1035 db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1037 Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1038 None => Err(skip_diagnostic()),
1039 })
1040}
1041
1042pub fn is_implicit_impl_impl(
1044 db: &dyn SemanticGroup,
1045 impl_def_id: ImplDefId,
1046 trait_impl_id: TraitImplId,
1047) -> Maybe<bool> {
1048 if trait_impl_id.trait_id(db.upcast()) != db.impl_def_trait(impl_def_id)? {
1049 unreachable!(
1050 "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1051 trait"
1052 )
1053 }
1054
1055 let defs_db = db.upcast();
1056 let name = trait_impl_id.name(defs_db);
1057 Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1059}
1060
1061pub fn priv_impl_definition_data(
1065 db: &dyn SemanticGroup,
1066 impl_def_id: ImplDefId,
1067) -> Maybe<ImplDefinitionData> {
1068 let syntax_db = db.upcast();
1069
1070 let module_file_id = impl_def_id.module_file_id(db.upcast());
1071 let mut diagnostics = SemanticDiagnostics::default();
1072
1073 let generic_params = db.impl_def_generic_params(impl_def_id)?;
1074 let concrete_trait = db.priv_impl_declaration_data(impl_def_id)?.concrete_trait?;
1075
1076 let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
1077
1078 let generic_params_ids =
1079 generic_params.iter().map(|generic_param| generic_param.id()).collect();
1080 let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
1081 check_special_impls(
1082 db,
1083 &mut diagnostics,
1084 lookup_context,
1085 concrete_trait,
1086 impl_ast.stable_ptr().untyped(),
1087 )
1088 .ok();
1090
1091 let mut function_asts = OrderedHashMap::default();
1092 let mut item_type_asts = OrderedHashMap::default();
1093 let mut item_constant_asts = OrderedHashMap::default();
1094 let mut item_impl_asts = OrderedHashMap::default();
1095 let mut item_id_by_name = OrderedHashMap::default();
1096
1097 if let MaybeImplBody::Some(body) = impl_ast.body(syntax_db) {
1098 for item in body.items(syntax_db).elements(syntax_db) {
1099 match item {
1100 ImplItem::Module(module) => report_invalid_impl_item(
1101 syntax_db,
1102 &mut diagnostics,
1103 module.module_kw(syntax_db),
1104 ),
1105
1106 ImplItem::Use(use_item) => report_invalid_impl_item(
1107 syntax_db,
1108 &mut diagnostics,
1109 use_item.use_kw(syntax_db),
1110 ),
1111 ImplItem::ExternFunction(extern_func) => report_invalid_impl_item(
1112 syntax_db,
1113 &mut diagnostics,
1114 extern_func.extern_kw(syntax_db),
1115 ),
1116 ImplItem::ExternType(extern_type) => report_invalid_impl_item(
1117 syntax_db,
1118 &mut diagnostics,
1119 extern_type.extern_kw(syntax_db),
1120 ),
1121 ImplItem::Trait(trt) => {
1122 report_invalid_impl_item(syntax_db, &mut diagnostics, trt.trait_kw(syntax_db))
1123 }
1124 ImplItem::Struct(structure) => report_invalid_impl_item(
1125 syntax_db,
1126 &mut diagnostics,
1127 structure.struct_kw(syntax_db),
1128 ),
1129 ImplItem::Enum(enm) => {
1130 report_invalid_impl_item(syntax_db, &mut diagnostics, enm.enum_kw(syntax_db))
1131 }
1132 ImplItem::Function(func) => {
1133 let impl_function_id =
1134 ImplFunctionLongId(module_file_id, func.stable_ptr()).intern(db);
1135 let name_node = func.declaration(syntax_db).name(syntax_db);
1136 let name = name_node.text(syntax_db);
1137 if item_id_by_name
1138 .insert(name.clone(), ImplItemId::Function(impl_function_id))
1139 .is_some()
1140 {
1141 diagnostics.report(&name_node, NameDefinedMultipleTimes(name));
1142 }
1143 function_asts.insert(impl_function_id, func);
1144 }
1145 ImplItem::Type(ty) => {
1146 let impl_type_id =
1147 ImplTypeDefLongId(module_file_id, ty.stable_ptr()).intern(db);
1148 let name_node = ty.name(syntax_db);
1149 let name = name_node.text(syntax_db);
1150 if item_id_by_name
1151 .insert(name.clone(), ImplItemId::Type(impl_type_id))
1152 .is_some()
1153 {
1154 diagnostics.report(&name_node, NameDefinedMultipleTimes(name));
1155 }
1156 item_type_asts.insert(impl_type_id, ty);
1157 }
1158 ImplItem::Constant(constant) => {
1159 let impl_constant_id =
1160 ImplConstantDefLongId(module_file_id, constant.stable_ptr()).intern(db);
1161 let name_node = constant.name(syntax_db);
1162 let name = name_node.text(syntax_db);
1163 if item_id_by_name
1164 .insert(name.clone(), ImplItemId::Constant(impl_constant_id))
1165 .is_some()
1166 {
1167 diagnostics.report(
1168 &name_node,
1169 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1170 );
1171 }
1172 item_constant_asts.insert(impl_constant_id, constant);
1173 }
1174 ImplItem::Impl(imp) => {
1175 let impl_constant_id =
1176 ImplImplDefLongId(module_file_id, imp.stable_ptr()).intern(db);
1177 let name_node = imp.name(syntax_db);
1178 let name = name_node.text(syntax_db);
1179 if item_id_by_name
1180 .insert(name.clone(), ImplItemId::Impl(impl_constant_id))
1181 .is_some()
1182 {
1183 diagnostics.report(
1184 &name_node,
1185 SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1186 );
1187 }
1188 item_impl_asts.insert(impl_constant_id, imp);
1189 }
1190 ImplItem::Missing(_) => {}
1192 }
1193 }
1194 }
1195
1196 let mut implicit_impls_id_by_name = OrderedHashMap::default();
1197
1198 let trait_id = concrete_trait.lookup_intern(db).trait_id;
1199 for trait_impl_id in db.trait_impls(trait_id)? {
1200 if item_id_by_name.contains_key(&trait_impl_id.0) {
1201 continue;
1202 }
1203 implicit_impls_id_by_name.insert(trait_impl_id.0, trait_impl_id.1);
1204 }
1205
1206 let impl_item_names: OrderedHashSet<SmolStr> = item_id_by_name.keys().cloned().collect();
1210
1211 let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1212 let missing_items_in_impl =
1213 trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1214 if !missing_items_in_impl.is_empty() {
1215 diagnostics.report(
1216 &impl_ast.name(syntax_db),
1221 SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1222 );
1223 }
1224
1225 Ok(ImplDefinitionData {
1226 diagnostics: diagnostics.build(),
1227 function_asts,
1228 item_type_asts: item_type_asts.into(),
1229 item_id_by_name: item_id_by_name.into(),
1230 item_constant_asts: item_constant_asts.into(),
1231 item_impl_asts: item_impl_asts.into(),
1232 implicit_impls_id_by_name: implicit_impls_id_by_name.into(),
1233 })
1234}
1235
1236fn report_invalid_impl_item<Terminal: syntax::node::Terminal>(
1239 syntax_db: &dyn SyntaxGroup,
1240 diagnostics: &mut SemanticDiagnostics,
1241 kw_terminal: Terminal,
1242) {
1243 diagnostics.report(
1244 kw_terminal.as_syntax_node().stable_ptr(),
1245 InvalidImplItem(kw_terminal.text(syntax_db)),
1246 );
1247}
1248
1249fn check_special_impls(
1251 db: &dyn SemanticGroup,
1252 diagnostics: &mut SemanticDiagnostics,
1253 lookup_context: ImplLookupContext,
1254 concrete_trait: ConcreteTraitId,
1255 stable_ptr: SyntaxStablePtrId,
1256) -> Maybe<()> {
1257 let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.lookup_intern(db);
1258 let copy = copy_trait(db);
1259 let drop = drop_trait(db);
1260
1261 if trait_id == copy {
1262 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1263 if let Some(inference_error) = tys
1264 .into_iter()
1265 .filter_map(|ty| db.type_info(lookup_context.clone(), ty).to_option())
1266 .flat_map(|info| info.copyable.err())
1267 .next()
1268 {
1269 return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1270 }
1271 }
1272 if trait_id == drop {
1273 let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1274 if let Some(inference_error) = tys
1275 .into_iter()
1276 .filter_map(|ty| db.type_info(lookup_context.clone(), ty).to_option())
1277 .flat_map(|info| info.droppable.err())
1278 .next()
1279 {
1280 return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1281 }
1282 }
1283
1284 Ok(())
1285}
1286
1287fn get_inner_types(db: &dyn SemanticGroup, ty: TypeId) -> Maybe<Vec<TypeId>> {
1294 Ok(match ty.lookup_intern(db) {
1295 TypeLongId::Concrete(concrete_type_id) => {
1296 match concrete_type_id {
1298 crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1299 .concrete_struct_members(concrete_struct_id)?
1300 .values()
1301 .map(|member| member.ty)
1302 .collect(),
1303 crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1304 .concrete_enum_variants(concrete_enum_id)?
1305 .into_iter()
1306 .map(|variant| variant.ty)
1307 .collect(),
1308 crate::ConcreteTypeId::Extern(_) => vec![],
1309 }
1310 }
1311 TypeLongId::Tuple(tys) => tys,
1312 TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1313 TypeLongId::GenericParameter(_) => {
1314 return Err(skip_diagnostic());
1315 }
1316 TypeLongId::Var(_) | TypeLongId::TraitType(_) | TypeLongId::ImplType(_) => {
1317 panic!("Types should be fully resolved at this point.")
1318 }
1319 TypeLongId::Coupon(_) => vec![],
1320 TypeLongId::FixedSizeArray { type_id, .. } => vec![type_id],
1321 TypeLongId::Missing(diag_added) => {
1322 return Err(diag_added);
1323 }
1324 })
1325}
1326
1327#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1332pub struct TraitFilter {
1333 pub trait_id: TraitId,
1334 pub generics_filter: GenericsHeadFilter,
1336}
1337
1338#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1341pub enum GenericsHeadFilter {
1342 NoFilter,
1345 FirstGenericFilter(GenericArgumentHead),
1348 NoGenerics,
1350}
1351
1352pub fn module_impl_ids_for_trait_filter(
1354 db: &dyn SemanticGroup,
1355 module_id: ModuleId,
1356 trait_filter: TraitFilter,
1357) -> Maybe<Vec<UninferredImpl>> {
1358 let mut uninferred_impls: OrderedHashSet<UninferredImpl> =
1360 OrderedHashSet::from_iter(module_impl_ids(db, module_id, module_id)?);
1361 for (user_module, containing_module) in &db.priv_module_use_star_modules(module_id).accessible {
1362 if let Ok(star_module_uninferred_impls) =
1363 module_impl_ids(db, *user_module, *containing_module)
1364 {
1365 uninferred_impls.extend(star_module_uninferred_impls);
1366 }
1367 }
1368 let mut res = Vec::new();
1369 for uninferred_impl in uninferred_impls {
1370 let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1371 if trait_id != trait_filter.trait_id {
1372 continue;
1373 }
1374 let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1375 continue;
1376 };
1377 if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1378 res.push(uninferred_impl);
1379 }
1380 }
1381 Ok(res)
1382}
1383
1384fn module_impl_ids(
1386 db: &dyn SemanticGroup,
1387 user_module: ModuleId,
1388 containing_module: ModuleId,
1389) -> Maybe<Vec<UninferredImpl>> {
1390 let mut uninferred_impls = Vec::new();
1391 for item in db.priv_module_semantic_data(containing_module)?.items.values() {
1392 if !matches!(
1393 item.item_id,
1394 ModuleItemId::Impl(_) | ModuleItemId::ImplAlias(_) | ModuleItemId::Use(_)
1395 ) {
1396 continue;
1397 }
1398 if !peek_visible_in(db.upcast(), item.visibility, containing_module, user_module) {
1399 continue;
1400 }
1401 match item.item_id {
1402 ModuleItemId::Impl(impl_def_id) => {
1403 uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1404 }
1405 ModuleItemId::ImplAlias(impl_alias_id) => {
1406 uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1407 }
1408 ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
1409 Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
1410 uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1411 }
1412 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
1413 uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1414 }
1415 _ => {}
1416 },
1417 _ => {}
1418 }
1419 }
1420 Ok(uninferred_impls)
1421}
1422
1423pub fn module_impl_ids_for_trait_filter_cycle(
1425 _db: &dyn SemanticGroup,
1426 _cycle: &salsa::Cycle,
1427 _module_id: &ModuleId,
1428 _trait_filter: &TraitFilter,
1429) -> Maybe<Vec<UninferredImpl>> {
1430 Err(skip_diagnostic())
1433}
1434
1435pub fn impl_impl_ids_for_trait_filter(
1437 db: &dyn SemanticGroup,
1438 impl_id: ImplId,
1439 trait_filter: TraitFilter,
1440) -> Maybe<Vec<UninferredImpl>> {
1441 let mut uninferred_impls = Vec::new();
1442 for (_, trait_impl_id) in db.trait_impls(impl_id.concrete_trait(db)?.trait_id(db))?.iter() {
1443 uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1444 impl_id,
1445 *trait_impl_id,
1446 db,
1447 )));
1448 }
1449 let mut res = Vec::new();
1450 for uninferred_impl in uninferred_impls {
1451 let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1452 if trait_id != trait_filter.trait_id {
1453 continue;
1454 }
1455 let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1456 continue;
1457 };
1458 if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1459 res.push(uninferred_impl);
1460 }
1461 }
1462
1463 Ok(res)
1464}
1465pub fn impl_impl_ids_for_trait_filter_cycle(
1467 _db: &dyn SemanticGroup,
1468 _cycle: &salsa::Cycle,
1469 _imp: &ImplId,
1470 _trait_filter: &TraitFilter,
1471) -> Maybe<Vec<UninferredImpl>> {
1472 Err(skip_diagnostic())
1475}
1476
1477fn concrete_trait_fits_trait_filter(
1479 db: &dyn SemanticGroup,
1480 concrete_trait_id: ConcreteTraitId,
1481 trait_filter: &TraitFilter,
1482) -> Maybe<bool> {
1483 if trait_filter.trait_id != concrete_trait_id.trait_id(db) {
1484 return Ok(false);
1485 }
1486 let generic_args = concrete_trait_id.generic_args(db);
1487 let first_generic = generic_args.first();
1488 Ok(match &trait_filter.generics_filter {
1489 GenericsHeadFilter::NoFilter => true,
1490 GenericsHeadFilter::FirstGenericFilter(constraint_head) => {
1491 let Some(first_generic) = first_generic else {
1492 return Ok(false);
1493 };
1494 let Some(first_generic_head) = first_generic.head(db) else {
1495 return Ok(true);
1496 };
1497 &first_generic_head == constraint_head
1498 }
1499 GenericsHeadFilter::NoGenerics => first_generic.is_none(),
1500 })
1501}
1502
1503#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1504pub enum ImplOrModuleById {
1505 Impl(ImplId),
1506 Module(ModuleId),
1507}
1508impl From<ImplId> for ImplOrModuleById {
1509 fn from(impl_id: ImplId) -> Self {
1510 ImplOrModuleById::Impl(impl_id)
1511 }
1512}
1513impl From<ModuleId> for ImplOrModuleById {
1514 fn from(module_id: ModuleId) -> Self {
1515 ImplOrModuleById::Module(module_id)
1516 }
1517}
1518
1519impl Ord for ImplOrModuleById {
1520 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1521 match (self, other) {
1522 (ImplOrModuleById::Impl(imp), ImplOrModuleById::Impl(other_impl)) => {
1523 imp.get_internal_id().cmp(other_impl.get_internal_id())
1524 }
1525 (ImplOrModuleById::Module(module), ImplOrModuleById::Module(other_module)) => {
1526 match (module, other_module) {
1527 (ModuleId::CrateRoot(crate_id), ModuleId::CrateRoot(other_crate_id)) => {
1528 crate_id.get_internal_id().cmp(other_crate_id.get_internal_id())
1529 }
1530 (ModuleId::CrateRoot(_), ModuleId::Submodule(_)) => std::cmp::Ordering::Less,
1531 (ModuleId::Submodule(_), ModuleId::CrateRoot(_)) => std::cmp::Ordering::Greater,
1532 (ModuleId::Submodule(module_id), ModuleId::Submodule(other_module_id)) => {
1533 module_id.get_internal_id().cmp(other_module_id.get_internal_id())
1534 }
1535 }
1536 }
1537 (ImplOrModuleById::Impl(_), ImplOrModuleById::Module(_)) => std::cmp::Ordering::Less,
1538 (ImplOrModuleById::Module(_), ImplOrModuleById::Impl(_)) => std::cmp::Ordering::Greater,
1539 }
1540 }
1541}
1542impl PartialOrd for ImplOrModuleById {
1543 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1544 Some(self.cmp(other))
1545 }
1546}
1547
1548#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, DebugWithDb)]
1549#[debug_db(dyn SemanticGroup + 'static)]
1550pub struct ImplLookupContext {
1551 pub modules_and_impls: BTreeSet<ImplOrModuleById>,
1552 pub generic_params: Vec<GenericParamId>,
1553}
1554impl ImplLookupContext {
1555 pub fn new(module_id: ModuleId, generic_params: Vec<GenericParamId>) -> ImplLookupContext {
1556 Self { modules_and_impls: [ImplOrModuleById::Module(module_id)].into(), generic_params }
1557 }
1558 pub fn insert_lookup_scope(&mut self, db: &dyn SemanticGroup, imp: &UninferredImpl) {
1559 let defs_db = db.upcast();
1560 let item = match imp {
1561 UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(defs_db).0.into(),
1562 UninferredImpl::ImplAlias(impl_alias_id) => {
1563 impl_alias_id.module_file_id(defs_db).0.into()
1564 }
1565 UninferredImpl::GenericParam(param) => param.module_file_id(defs_db).0.into(),
1566 UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1567 UninferredImpl::GeneratedImpl(_) => {
1568 return;
1570 }
1571 };
1572 self.modules_and_impls.insert(item);
1573 }
1574 pub fn insert_module(&mut self, module_id: ModuleId) -> bool {
1575 self.modules_and_impls.insert(ImplOrModuleById::Module(module_id))
1576 }
1577
1578 pub fn insert_impl(&mut self, impl_id: ImplId) -> bool {
1579 self.modules_and_impls.insert(ImplOrModuleById::Impl(impl_id))
1580 }
1581}
1582
1583#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1585pub enum UninferredImpl {
1586 Def(ImplDefId),
1587 ImplAlias(ImplAliasId),
1588 GenericParam(GenericParamId),
1589 ImplImpl(ImplImplId),
1590 GeneratedImpl(UninferredGeneratedImplId),
1591}
1592impl UninferredImpl {
1593 pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
1594 match self {
1595 UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1596 UninferredImpl::ImplAlias(impl_alias_id) => {
1597 let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1598 impl_id.concrete_trait(db)
1599 }
1600 UninferredImpl::GenericParam(param) => {
1601 let param =
1602 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1603 param.concrete_trait
1604 }
1605 UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1606 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1607 }
1608 }
1609
1610 fn trait_id(&self, db: &dyn SemanticGroup) -> Maybe<TraitId> {
1611 match self {
1612 UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1613 UninferredImpl::ImplAlias(impl_alias_id) => {
1614 let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1615 db.impl_def_trait(impl_def_id)
1616 }
1617 UninferredImpl::GenericParam(param) => {
1618 let param =
1619 extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1620 param.concrete_trait.map(|concrete_trait| concrete_trait.trait_id(db))
1621 }
1622 UninferredImpl::ImplImpl(impl_impl_id) => db
1623 .impl_impl_concrete_trait(*impl_impl_id)
1624 .map(|concrete_trait| concrete_trait.trait_id(db)),
1625 UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1626 }
1627 }
1628
1629 pub fn lookup_scope(&self, db: &dyn SemanticGroup) -> ImplOrModuleById {
1630 let defs_db = db.upcast();
1631 match self {
1632 UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(defs_db).0.into(),
1633 UninferredImpl::ImplAlias(impl_alias_id) => {
1634 impl_alias_id.module_file_id(defs_db).0.into()
1635 }
1636 UninferredImpl::GenericParam(param) => param.module_file_id(defs_db).0.into(),
1637 UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1638 UninferredImpl::GeneratedImpl(generated_impl) => {
1639 generated_impl.concrete_trait(db).trait_id(db).module_file_id(defs_db).0.into()
1640 }
1641 }
1642 }
1643}
1644impl DebugWithDb<dyn SemanticGroup> for UninferredImpl {
1645 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn SemanticGroup) -> std::fmt::Result {
1646 match self {
1647 UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db.upcast())),
1648 UninferredImpl::ImplAlias(impl_alias) => {
1649 write!(f, "{:?}", impl_alias.full_path(db.upcast()))
1650 }
1651 UninferredImpl::GenericParam(param) => {
1652 write!(f, "generic param {}", param.name(db.upcast()).unwrap_or_else(|| "_".into()))
1653 }
1654 UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db.elongate()),
1655 UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db.elongate()),
1656 }
1657 }
1658}
1659
1660define_short_id!(
1661 UninferredGeneratedImplId,
1662 UninferredGeneratedImplLongId,
1663 SemanticGroup,
1664 lookup_intern_uninferred_generated_impl,
1665 intern_uninferred_generated_impl
1666);
1667semantic_object_for_id!(
1668 UninferredGeneratedImplId,
1669 lookup_intern_uninferred_generated_impl,
1670 intern_uninferred_generated_impl,
1671 UninferredGeneratedImplLongId
1672);
1673
1674impl UninferredGeneratedImplId {
1675 pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
1676 db.lookup_intern_uninferred_generated_impl(self).concrete_trait
1677 }
1678
1679 pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
1680 self.concrete_trait(db).trait_id(db)
1681 }
1682}
1683
1684#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1686pub struct UninferredGeneratedImplLongId {
1687 pub concrete_trait: ConcreteTraitId,
1688 pub generic_params: Vec<GenericParam>,
1689 pub impl_items: GeneratedImplItems,
1690}
1691
1692impl DebugWithDb<dyn SemanticGroup> for UninferredGeneratedImplLongId {
1693 fn fmt(
1694 &self,
1695 f: &mut std::fmt::Formatter<'_>,
1696 db: &(dyn SemanticGroup + 'static),
1697 ) -> std::fmt::Result {
1698 write!(f, "Generated {:?}", self.concrete_trait.debug(db))
1699 }
1700}
1701
1702pub fn find_candidates_at_context(
1704 db: &dyn SemanticGroup,
1705 lookup_context: &ImplLookupContext,
1706 filter: &TraitFilter,
1707) -> Maybe<OrderedHashSet<UninferredImpl>> {
1708 let mut res = OrderedHashSet::default();
1709 for generic_param_id in &lookup_context.generic_params {
1710 if !matches!(generic_param_id.kind(db.upcast()), GenericKind::Impl) {
1711 continue;
1712 };
1713 let Ok(trait_id) = db.generic_impl_param_trait(*generic_param_id) else {
1714 continue;
1715 };
1716 if filter.trait_id != trait_id {
1717 continue;
1718 }
1719 let Ok(generic_param_semantic) = db.generic_param_semantic(*generic_param_id) else {
1720 continue;
1721 };
1722 let param = extract_matches!(generic_param_semantic, GenericParam::Impl);
1723 let Ok(imp_concrete_trait_id) = param.concrete_trait else { continue };
1724 let Ok(trait_fits_filter) =
1725 concrete_trait_fits_trait_filter(db, imp_concrete_trait_id, filter)
1726 else {
1727 continue;
1728 };
1729 if !trait_fits_filter {
1730 continue;
1731 }
1732 res.insert(UninferredImpl::GenericParam(*generic_param_id));
1733 }
1734 for module_or_impl_id in &lookup_context.modules_and_impls {
1735 let Ok(imps) = (match module_or_impl_id {
1736 ImplOrModuleById::Module(module_id) => {
1737 db.module_impl_ids_for_trait_filter(*module_id, filter.clone())
1738 }
1739 ImplOrModuleById::Impl(impl_id) => {
1740 db.impl_impl_ids_for_trait_filter(*impl_id, filter.clone())
1741 }
1742 }) else {
1743 continue;
1744 };
1745 for imp in imps {
1746 res.insert(imp);
1747 }
1748 }
1749 Ok(res)
1750}
1751
1752pub fn find_closure_generated_candidate(
1754 db: &dyn SemanticGroup,
1755 concrete_trait_id: ConcreteTraitId,
1756) -> Option<UninferredImpl> {
1757 let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
1758 return None;
1759 };
1760 let TypeLongId::Closure(closure_type_long) = closure_type.lookup_intern(db) else {
1761 return None;
1762 };
1763
1764 let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
1766 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1767 chain!(
1768 closure_type_long.captured_types.iter().map(|ty| {
1769 GenericParam::Impl(GenericParamImpl {
1770 id,
1771 concrete_trait: Maybe::Ok(db.intern_concrete_trait(ConcreteTraitLongId {
1772 trait_id,
1773 generic_args: vec![GenericArgumentId::Type(*ty)],
1774 })),
1775 type_constraints: Default::default(),
1776 })
1777 }),
1778 neg_impl_trait.map(|neg_impl_trait| {
1779 GenericParam::NegImpl(GenericParamImpl {
1780 id,
1781 concrete_trait: Maybe::Ok(neg_impl_trait),
1782 type_constraints: Default::default(),
1783 })
1784 })
1785 )
1786 .collect()
1787 };
1788 let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
1789 (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
1790 };
1791 let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
1792 trait_id if trait_id == fn_once_trait(db) => {
1793 let concrete_trait = ConcreteTraitLongId {
1794 trait_id,
1795 generic_args: vec![
1796 GenericArgumentId::Type(closure_type),
1797 GenericArgumentId::Type(
1798 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1799 ),
1800 ],
1801 }
1802 .intern(db);
1803 let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
1804
1805 let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1806 let param: GenericParam = GenericParam::NegImpl(GenericParamImpl {
1808 id,
1809 concrete_trait: Maybe::Ok(
1810 ConcreteTraitLongId {
1811 trait_id: fn_trait(db),
1812 generic_args: vec![
1813 GenericArgumentId::Type(closure_type),
1814 GenericArgumentId::Type(
1815 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1816 ),
1817 ],
1818 }
1819 .intern(db),
1820 ),
1821 type_constraints: Default::default(),
1822 });
1823 (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
1824 }
1825 trait_id if trait_id == fn_trait(db) => {
1826 let concrete_trait = ConcreteTraitLongId {
1827 trait_id,
1828 generic_args: vec![
1829 GenericArgumentId::Type(closure_type),
1830 GenericArgumentId::Type(
1831 TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1832 ),
1833 ],
1834 }
1835 .intern(db);
1836 let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
1837
1838 (
1839 concrete_trait,
1840 mem_trait_generic_params(copy_trait(db), None),
1842 [(ret_ty, closure_type_long.ret_ty)].into(),
1843 )
1844 }
1845 trait_id if trait_id == drop_trait(db) => handle_mem_trait(trait_id, None),
1846 trait_id if trait_id == destruct_trait(db) => {
1847 handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
1848 }
1849 trait_id if trait_id == panic_destruct_trait(db) => {
1850 handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
1851 }
1852 trait_id if trait_id == copy_trait(db) => handle_mem_trait(trait_id, None),
1853 _ => return None,
1854 };
1855 Some(UninferredImpl::GeneratedImpl(
1856 UninferredGeneratedImplLongId {
1857 concrete_trait,
1858 generic_params,
1859 impl_items: GeneratedImplItems(impl_items),
1860 }
1861 .intern(db),
1862 ))
1863}
1864
1865pub fn can_infer_impl_by_self(
1871 ctx: &ComputationContext<'_>,
1872 inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
1873 trait_function_id: TraitFunctionId,
1874 self_ty: TypeId,
1875 stable_ptr: SyntaxStablePtrId,
1876) -> bool {
1877 let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
1878 let mut temp_inference = temp_inference_data.inference(ctx.db);
1879 let lookup_context = ctx.resolver.impl_lookup_context();
1880
1881 let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
1882 trait_function_id,
1883 self_ty,
1884 &lookup_context,
1885 Some(stable_ptr),
1886 |err| inference_errors.push((trait_function_id, err)),
1887 ) else {
1888 return false;
1889 };
1890 if let Err(err_set) = temp_inference.solve() {
1892 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
1894 inference_errors.push((trait_function_id, err));
1895 }
1896 }
1897 match temp_inference.trait_solution_set(
1898 concrete_trait_id,
1899 ImplVarTraitItemMappings::default(),
1900 lookup_context.clone(),
1901 ) {
1902 Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
1903 Ok(SolutionSet::None) => {
1904 inference_errors
1905 .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
1906 false
1907 }
1908 Err(err_set) => {
1909 if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
1911 inference_errors.push((trait_function_id, err));
1912 }
1913 false
1914 }
1915 }
1916}
1917
1918pub fn infer_impl_by_self(
1921 ctx: &mut ComputationContext<'_>,
1922 trait_function_id: TraitFunctionId,
1923 self_ty: TypeId,
1924 stable_ptr: SyntaxStablePtrId,
1925 generic_args_syntax: Option<Vec<GenericArg>>,
1926) -> Maybe<(FunctionId, usize)> {
1927 let lookup_context = ctx.resolver.impl_lookup_context();
1928 let (concrete_trait_id, n_snapshots) = ctx
1929 .resolver
1930 .inference()
1931 .infer_concrete_trait_by_self(
1932 trait_function_id,
1933 self_ty,
1934 &lookup_context,
1935 Some(stable_ptr),
1936 |_| {},
1937 )
1938 .ok_or_else(skip_diagnostic)?;
1939
1940 let concrete_trait_function_id =
1941 ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
1942 .intern(ctx.db);
1943 let trait_func_generic_params =
1944 ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
1945 let generic_args = ctx.resolver.resolve_generic_args(
1946 ctx.diagnostics,
1947 &trait_func_generic_params,
1948 &generic_args_syntax.unwrap_or_default(),
1949 stable_ptr,
1950 )?;
1951
1952 let impl_lookup_context = ctx.resolver.impl_lookup_context();
1953 let inference = &mut ctx.resolver.inference();
1954 let generic_function = inference.infer_trait_generic_function(
1955 concrete_trait_function_id,
1956 &impl_lookup_context,
1957 Some(stable_ptr),
1958 );
1959
1960 Ok((
1961 FunctionLongId { function: ConcreteFunction { generic_function, generic_args } }
1962 .intern(ctx.db),
1963 n_snapshots,
1964 ))
1965}
1966
1967pub fn filter_candidate_traits(
1973 ctx: &mut ComputationContext<'_>,
1974 inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
1975 self_ty: TypeId,
1976 candidate_traits: &[TraitId],
1977 function_name: SmolStr,
1978 stable_ptr: SyntaxStablePtrId,
1979) -> Vec<TraitFunctionId> {
1980 let mut candidates = Vec::new();
1981 for trait_id in candidate_traits.iter().copied() {
1982 let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
1983 continue;
1984 };
1985 for (name, trait_function) in trait_functions {
1986 if name == function_name
1987 && can_infer_impl_by_self(
1988 ctx,
1989 inference_errors,
1990 trait_function,
1991 self_ty,
1992 stable_ptr,
1993 )
1994 {
1995 candidates.push(trait_function);
1996 }
1997 }
1998 }
1999 candidates
2000}
2001
2002#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2005#[debug_db(dyn SemanticGroup + 'static)]
2006pub struct ImplItemTypeData {
2007 type_alias_data: TypeAliasData,
2008 trait_type_id: Maybe<TraitTypeId>,
2009 diagnostics: Diagnostics<SemanticDiagnostic>,
2011}
2012
2013pub fn impl_type_def_semantic_diagnostics(
2017 db: &dyn SemanticGroup,
2018 impl_type_def_id: ImplTypeDefId,
2019) -> Diagnostics<SemanticDiagnostic> {
2020 db.priv_impl_type_semantic_data(impl_type_def_id, false)
2021 .map(|data| data.diagnostics)
2022 .unwrap_or_default()
2023}
2024
2025pub fn impl_type_def_resolved_type(
2027 db: &dyn SemanticGroup,
2028 impl_type_def_id: ImplTypeDefId,
2029) -> Maybe<TypeId> {
2030 db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolved_type
2031}
2032
2033pub fn impl_type_def_resolved_type_cycle(
2035 db: &dyn SemanticGroup,
2036 _cycle: &salsa::Cycle,
2037 impl_type_def_id: &ImplTypeDefId,
2038) -> Maybe<TypeId> {
2039 db.priv_impl_type_semantic_data(*impl_type_def_id, true)?.type_alias_data.resolved_type
2040}
2041
2042pub fn impl_type_def_generic_params(
2044 db: &dyn SemanticGroup,
2045 impl_type_def_id: ImplTypeDefId,
2046) -> Maybe<Vec<GenericParam>> {
2047 Ok(db.priv_impl_type_def_generic_params_data(impl_type_def_id)?.generic_params)
2048}
2049
2050pub fn impl_type_def_attributes(
2052 db: &dyn SemanticGroup,
2053 impl_type_def_id: ImplTypeDefId,
2054) -> Maybe<Vec<Attribute>> {
2055 Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.attributes)
2056}
2057
2058pub fn impl_type_def_resolver_data(
2060 db: &dyn SemanticGroup,
2061 impl_type_def_id: ImplTypeDefId,
2062) -> Maybe<Arc<ResolverData>> {
2063 Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolver_data)
2064}
2065
2066pub fn impl_type_def_trait_type(
2068 db: &dyn SemanticGroup,
2069 impl_type_def_id: ImplTypeDefId,
2070) -> Maybe<TraitTypeId> {
2071 db.priv_impl_type_semantic_data(impl_type_def_id, false)?.trait_type_id
2072}
2073
2074pub fn priv_impl_type_semantic_data(
2078 db: &dyn SemanticGroup,
2079 impl_type_def_id: ImplTypeDefId,
2080 in_cycle: bool,
2081) -> Maybe<ImplItemTypeData> {
2082 let mut diagnostics = SemanticDiagnostics::default();
2083 let impl_type_defs = db.impl_types(impl_type_def_id.impl_def_id(db.upcast()))?;
2084 let impl_type_def_ast = impl_type_defs.get(&impl_type_def_id).to_maybe()?;
2085 let generic_params_data = db.priv_impl_type_def_generic_params_data(impl_type_def_id)?;
2086 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2087
2088 let trait_type_id =
2089 validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, impl_type_def_ast);
2090
2091 if in_cycle {
2092 Ok(ImplItemTypeData {
2093 type_alias_data: type_alias_semantic_data_cycle_helper(
2094 db,
2095 &mut diagnostics,
2096 impl_type_def_ast,
2097 lookup_item_id,
2098 generic_params_data,
2099 )?,
2100 trait_type_id,
2101 diagnostics: diagnostics.build(),
2102 })
2103 } else {
2104 Ok(ImplItemTypeData {
2107 type_alias_data: type_alias_semantic_data_helper(
2108 db,
2109 &mut diagnostics,
2110 impl_type_def_ast,
2111 lookup_item_id,
2112 generic_params_data,
2113 )?,
2114 trait_type_id,
2115 diagnostics: diagnostics.build(),
2116 })
2117 }
2118}
2119
2120pub fn priv_impl_type_semantic_data_cycle(
2122 db: &dyn SemanticGroup,
2123 _cycle: &salsa::Cycle,
2124 impl_type_def_id: &ImplTypeDefId,
2125 _in_cycle: &bool,
2126) -> Maybe<ImplItemTypeData> {
2127 priv_impl_type_semantic_data(db, *impl_type_def_id, true)
2129}
2130
2131pub fn priv_impl_type_def_generic_params_data(
2133 db: &dyn SemanticGroup,
2134 impl_type_def_id: ImplTypeDefId,
2135) -> Maybe<GenericParamsData> {
2136 let defs_db = db.upcast();
2137 let module_file_id = impl_type_def_id.module_file_id(defs_db);
2138 let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?.to_maybe()?;
2139 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2140
2141 let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(defs_db))?;
2142 type_alias_generic_params_data_helper(
2143 db,
2144 module_file_id,
2145 &impl_type_def_ast,
2146 lookup_item_id,
2147 Some(impl_resolver_data),
2148 )
2149}
2150
2151fn validate_impl_item_type(
2153 db: &dyn SemanticGroup,
2154 diagnostics: &mut SemanticDiagnostics,
2155 impl_type_def_id: ImplTypeDefId,
2156 impl_type_ast: &ast::ItemTypeAlias,
2157) -> Maybe<TraitTypeId> {
2158 let defs_db = db.upcast();
2159 let syntax_db = db.upcast();
2160 let impl_def_id = impl_type_def_id.impl_def_id(defs_db);
2161 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2162 let trait_id = concrete_trait_id.trait_id(db);
2163 let type_name = impl_type_def_id.name(defs_db);
2164 let trait_type_id = db.trait_type_by_name(trait_id, type_name.clone())?.ok_or_else(|| {
2165 diagnostics.report(impl_type_ast, ImplItemNotInTrait {
2166 impl_def_id,
2167 impl_item_name: type_name,
2168 trait_id,
2169 item_kind: "type".into(),
2170 })
2171 })?;
2172
2173 let generic_params_node = impl_type_ast.generic_params(syntax_db);
2176 if !generic_params_node.is_empty(syntax_db) {
2177 diagnostics.report(&generic_params_node, GenericsNotSupportedInItem {
2178 scope: "Impl".into(),
2179 item_kind: "type".into(),
2180 });
2181 }
2182
2183 Ok(trait_type_id)
2184}
2185
2186pub fn impl_type_concrete_implized(
2190 db: &dyn SemanticGroup,
2191 impl_type_id: ImplTypeId,
2192) -> Maybe<TypeId> {
2193 let concrete_impl = match impl_type_id.impl_id().lookup_intern(db) {
2194 ImplLongId::Concrete(concrete_impl) => concrete_impl,
2195 ImplLongId::ImplImpl(imp_impl_id) => {
2196 let ImplLongId::Concrete(concrete_impl) =
2197 db.impl_impl_concrete_implized(imp_impl_id)?.lookup_intern(db)
2198 else {
2199 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2200 };
2201 concrete_impl
2202 }
2203 ImplLongId::GenericParameter(_) | ImplLongId::TraitImpl(_) | ImplLongId::ImplVar(_) => {
2204 return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2205 }
2206 ImplLongId::GeneratedImpl(generated) => {
2207 return Ok(*generated.lookup_intern(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2208 }
2209 };
2210
2211 let impl_def_id = concrete_impl.impl_def_id(db);
2212 let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id);
2213 let Ok(ty) = ty else {
2214 return ty;
2215 };
2216
2217 let substitution = &concrete_impl.substitution(db)?;
2218 SubstitutionRewriter { db, substitution }.rewrite(ty)
2219}
2220
2221pub fn impl_type_concrete_implized_cycle(
2223 db: &dyn SemanticGroup,
2224 _cycle: &salsa::Cycle,
2225 impl_type_id: &ImplTypeId,
2226) -> Maybe<TypeId> {
2227 impl_type_concrete_implized(db, *impl_type_id)
2229}
2230
2231#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2234#[debug_db(dyn SemanticGroup + 'static)]
2235pub struct ImplItemConstantData {
2236 constant_data: ConstantData,
2237 trait_constant_id: Maybe<TraitConstantId>,
2238 diagnostics: Diagnostics<SemanticDiagnostic>,
2240}
2241
2242pub fn impl_constant_def_semantic_diagnostics(
2246 db: &dyn SemanticGroup,
2247 impl_constant_def_id: ImplConstantDefId,
2248) -> Diagnostics<SemanticDiagnostic> {
2249 db.priv_impl_constant_semantic_data(impl_constant_def_id, false)
2250 .map(|data| data.diagnostics)
2251 .unwrap_or_default()
2252}
2253
2254pub fn impl_constant_def_value(
2256 db: &dyn SemanticGroup,
2257 impl_constant_def_id: ImplConstantDefId,
2258) -> Maybe<ConstValueId> {
2259 Ok(db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.constant_data.const_value)
2260}
2261
2262pub fn impl_constant_def_value_cycle(
2264 db: &dyn SemanticGroup,
2265 _cycle: &salsa::Cycle,
2266 impl_constant_def_id: &ImplConstantDefId,
2267) -> Maybe<ConstValueId> {
2268 Ok(db.priv_impl_constant_semantic_data(*impl_constant_def_id, true)?.constant_data.const_value)
2269}
2270
2271pub fn impl_constant_def_resolver_data(
2273 db: &dyn SemanticGroup,
2274 impl_constant_def_id: ImplConstantDefId,
2275) -> Maybe<Arc<ResolverData>> {
2276 Ok(db
2277 .priv_impl_constant_semantic_data(impl_constant_def_id, false)?
2278 .constant_data
2279 .resolver_data)
2280}
2281
2282pub fn impl_constant_def_trait_constant(
2284 db: &dyn SemanticGroup,
2285 impl_constant_def_id: ImplConstantDefId,
2286) -> Maybe<TraitConstantId> {
2287 db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.trait_constant_id
2288}
2289
2290pub fn priv_impl_constant_semantic_data(
2294 db: &dyn SemanticGroup,
2295 impl_constant_def_id: ImplConstantDefId,
2296 in_cycle: bool,
2297) -> Maybe<ImplItemConstantData> {
2298 let mut diagnostics = SemanticDiagnostics::default();
2299 let impl_def_id = impl_constant_def_id.impl_def_id(db.upcast());
2300 let impl_constant_defs = db.impl_constants(impl_def_id)?;
2301 let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2302 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2303
2304 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2305 ImplItemId::Constant(impl_constant_def_id),
2306 ));
2307 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2308 let mut resolver =
2309 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2310
2311 let trait_constant_id = validate_impl_item_constant(
2312 db,
2313 &mut diagnostics,
2314 impl_constant_def_id,
2315 impl_constant_def_ast,
2316 &mut resolver,
2317 );
2318 let mut constant_data = if in_cycle {
2319 constant_semantic_data_cycle_helper(
2320 db,
2321 impl_constant_def_ast,
2322 lookup_item_id,
2323 Some(Arc::new(resolver.data)),
2324 &impl_def_id,
2325 )?
2326 } else {
2327 constant_semantic_data_helper(
2328 db,
2329 impl_constant_def_ast,
2330 lookup_item_id,
2331 Some(Arc::new(resolver.data)),
2332 &impl_def_id,
2333 )?
2334 };
2335 diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2336 Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2337}
2338
2339pub fn priv_impl_constant_semantic_data_cycle(
2341 db: &dyn SemanticGroup,
2342 _cycle: &salsa::Cycle,
2343 impl_constant_def_id: &ImplConstantDefId,
2344 _in_cycle: &bool,
2345) -> Maybe<ImplItemConstantData> {
2346 priv_impl_constant_semantic_data(db, *impl_constant_def_id, true)
2348}
2349
2350fn validate_impl_item_constant(
2352 db: &dyn SemanticGroup,
2353 diagnostics: &mut SemanticDiagnostics,
2354 impl_constant_def_id: ImplConstantDefId,
2355 impl_constant_ast: &ast::ItemConstant,
2356 resolver: &mut Resolver<'_>,
2357) -> Maybe<TraitConstantId> {
2358 let syntax_db = db.upcast();
2359 let defs_db = db.upcast();
2360 let impl_def_id = impl_constant_def_id.impl_def_id(defs_db);
2361 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2362 let trait_id = concrete_trait_id.trait_id(db);
2363 let constant_name = impl_constant_def_id.name(defs_db);
2364
2365 let trait_constant_id =
2366 db.trait_constant_by_name(trait_id, constant_name.clone())?.ok_or_else(|| {
2367 diagnostics.report(impl_constant_ast, ImplItemNotInTrait {
2368 impl_def_id,
2369 impl_item_name: constant_name,
2370 trait_id,
2371 item_kind: "const".into(),
2372 })
2373 })?;
2374 let concrete_trait_constant =
2375 ConcreteTraitConstantId::new(db, concrete_trait_id, trait_constant_id);
2376 let concrete_trait_constant_ty = db.concrete_trait_constant_type(concrete_trait_constant)?;
2377
2378 let impl_constant_type_clause_ast = impl_constant_ast.type_clause(syntax_db);
2379
2380 let constant_ty =
2381 resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(syntax_db));
2382
2383 let inference = &mut resolver.inference();
2384
2385 let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2386 let actual_ty = inference.rewrite(constant_ty).no_err();
2387 if expected_ty != actual_ty {
2388 diagnostics.report(&impl_constant_type_clause_ast, WrongType { expected_ty, actual_ty });
2389 }
2390 Ok(trait_constant_id)
2391}
2392
2393pub fn impl_constant_implized_by_context(
2397 db: &dyn SemanticGroup,
2398 impl_constant_id: ImplConstantId,
2399 impl_def_id: ImplDefId,
2400) -> Maybe<ConstValueId> {
2401 let impl_constant_def_id: ImplConstantDefId =
2402 db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2403
2404 db.impl_constant_def_value(impl_constant_def_id)
2405}
2406
2407pub fn impl_constant_implized_by_context_cycle(
2409 db: &dyn SemanticGroup,
2410 _cycle: &salsa::Cycle,
2411 impl_constant_id: &ImplConstantId,
2412 impl_def_id: &ImplDefId,
2413) -> Maybe<ConstValueId> {
2414 impl_constant_implized_by_context(db, *impl_constant_id, *impl_def_id)
2416}
2417
2418pub fn impl_constant_concrete_implized_value(
2420 db: &dyn SemanticGroup,
2421 impl_constant_id: ImplConstantId,
2422) -> Maybe<ConstValueId> {
2423 if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().lookup_intern(db) {
2424 let impl_def_id = concrete_impl.impl_def_id(db);
2425 let constant = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2426 let substitution: &GenericSubstitution = &concrete_impl.substitution(db)?;
2427 return SubstitutionRewriter { db, substitution }.rewrite(constant);
2428 }
2429 let substitution = &GenericSubstitution::from_impl(impl_constant_id.impl_id());
2430
2431 Ok(ConstValue::ImplConstant(
2432 SubstitutionRewriter { db, substitution }.rewrite(impl_constant_id)?,
2433 )
2434 .intern(db))
2435}
2436
2437pub fn impl_constant_concrete_implized_value_cycle(
2439 db: &dyn SemanticGroup,
2440 _cycle: &salsa::Cycle,
2441 impl_constant_id: &ImplConstantId,
2442) -> Maybe<ConstValueId> {
2443 impl_constant_concrete_implized_value(db, *impl_constant_id)
2445}
2446
2447pub fn impl_constant_concrete_implized_type(
2449 db: &dyn SemanticGroup,
2450 impl_constant_id: ImplConstantId,
2451) -> Maybe<TypeId> {
2452 let concrete_trait_id = match impl_constant_id.impl_id().lookup_intern(db) {
2453 ImplLongId::Concrete(concrete_impl) => {
2454 let impl_def_id = concrete_impl.impl_def_id(db);
2455 let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2456 let substitution = &concrete_impl.substitution(db)?;
2457 return SubstitutionRewriter { db, substitution }.rewrite(ty);
2458 }
2459 ImplLongId::GenericParameter(param) => {
2460 let param_impl =
2461 extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
2462 param_impl.concrete_trait?
2463 }
2464 ImplLongId::ImplVar(var) => var.lookup_intern(db).concrete_trait_id,
2465 ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl)?,
2466 ImplLongId::TraitImpl(trait_impl) => db.trait_impl_concrete_trait(trait_impl)?,
2467 ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2468 };
2469
2470 let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new(
2471 db,
2472 concrete_trait_id,
2473 impl_constant_id.trait_constant_id(),
2474 ))?;
2475 let substitution = &GenericSubstitution::from_impl(impl_constant_id.impl_id());
2476 SubstitutionRewriter { db, substitution }.rewrite(ty)
2477}
2478
2479pub fn impl_constant_concrete_implized_type_cycle(
2481 db: &dyn SemanticGroup,
2482 _cycle: &salsa::Cycle,
2483 impl_constant_id: &ImplConstantId,
2484) -> Maybe<TypeId> {
2485 impl_constant_concrete_implized_type(db, *impl_constant_id)
2487}
2488
2489#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2492#[debug_db(dyn SemanticGroup + 'static)]
2493pub struct ImplItemImplData {
2494 impl_data: ImplAliasData,
2495 trait_impl_id: Maybe<TraitImplId>,
2496 diagnostics: Diagnostics<SemanticDiagnostic>,
2498}
2499
2500pub fn impl_impl_def_semantic_diagnostics(
2504 db: &dyn SemanticGroup,
2505 impl_impl_def_id: ImplImplDefId,
2506) -> Diagnostics<SemanticDiagnostic> {
2507 db.priv_impl_impl_semantic_data(impl_impl_def_id, false)
2508 .map(|data| data.diagnostics)
2509 .unwrap_or_default()
2510}
2511
2512pub fn impl_impl_def_resolver_data(
2514 db: &dyn SemanticGroup,
2515 impl_impl_def_id: ImplImplDefId,
2516) -> Maybe<Arc<ResolverData>> {
2517 Ok(db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.impl_data.resolver_data)
2518}
2519
2520pub fn impl_impl_def_trait_impl(
2522 db: &dyn SemanticGroup,
2523 impl_impl_def_id: ImplImplDefId,
2524) -> Maybe<TraitImplId> {
2525 db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.trait_impl_id
2526}
2527
2528pub fn impl_impl_def_impl(
2530 db: &dyn SemanticGroup,
2531 impl_impl_def_id: ImplImplDefId,
2532 in_cycle: bool,
2533) -> Maybe<ImplId> {
2534 db.priv_impl_impl_semantic_data(impl_impl_def_id, in_cycle)?.impl_data.resolved_impl
2535}
2536pub fn impl_impl_def_impl_cycle(
2538 db: &dyn SemanticGroup,
2539 _cycle: &salsa::Cycle,
2540 impl_impl_def_id: &ImplImplDefId,
2541 _in_cycle: &bool,
2542) -> Maybe<ImplId> {
2543 db.priv_impl_impl_semantic_data(*impl_impl_def_id, true)?.impl_data.resolved_impl
2544}
2545
2546pub fn priv_impl_impl_semantic_data(
2550 db: &dyn SemanticGroup,
2551 impl_impl_def_id: ImplImplDefId,
2552 in_cycle: bool,
2553) -> Maybe<ImplItemImplData> {
2554 let mut diagnostics = SemanticDiagnostics::default();
2555 let impl_def_id = impl_impl_def_id.impl_def_id(db.upcast());
2556 let impl_impl_defs = db.impl_impls(impl_def_id)?;
2557 let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2558 let generic_params_data = db.priv_impl_impl_def_generic_params_data(impl_impl_def_id)?;
2559 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2560
2561 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2562 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2563 let mut resolver =
2564 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2565
2566 let mut impl_data = if in_cycle {
2567 impl_alias_semantic_data_cycle_helper(
2568 db,
2569 impl_impl_def_ast,
2570 lookup_item_id,
2571 generic_params_data,
2572 )?
2573 } else {
2574 impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2575 };
2576
2577 diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2578
2579 let trait_impl_id = validate_impl_item_impl(
2580 db,
2581 &mut diagnostics,
2582 impl_impl_def_id,
2583 impl_impl_def_ast,
2584 &impl_data,
2585 &mut resolver,
2586 );
2587
2588 Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2589}
2590
2591pub fn priv_impl_impl_semantic_data_cycle(
2593 db: &dyn SemanticGroup,
2594 _cycle: &salsa::Cycle,
2595 impl_impl_def_id: &ImplImplDefId,
2596 _in_cycle: &bool,
2597) -> Maybe<ImplItemImplData> {
2598 priv_impl_impl_semantic_data(db, *impl_impl_def_id, true)
2600}
2601
2602pub fn priv_impl_impl_def_generic_params_data(
2604 db: &dyn SemanticGroup,
2605 impl_impl_def_id: ImplImplDefId,
2606) -> Maybe<GenericParamsData> {
2607 let defs_db = db.upcast();
2608 let module_file_id = impl_impl_def_id.module_file_id(defs_db);
2609 let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?.to_maybe()?;
2610 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2611
2612 let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(defs_db))?;
2613 impl_alias_generic_params_data_helper(
2614 db,
2615 module_file_id,
2616 &impl_impl_def_ast,
2617 lookup_item_id,
2618 Some(impl_resolver_data),
2619 )
2620}
2621
2622fn validate_impl_item_impl(
2624 db: &dyn SemanticGroup,
2625 diagnostics: &mut SemanticDiagnostics,
2626 impl_impl_def_id: ImplImplDefId,
2627 impl_impl_ast: &ast::ItemImplAlias,
2628 impl_data: &ImplAliasData,
2629 resolver: &mut Resolver<'_>,
2630) -> Maybe<TraitImplId> {
2631 let syntax_db = db.upcast();
2632 let defs_db = db.upcast();
2633 let impl_def_id = impl_impl_def_id.impl_def_id(defs_db);
2634 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2635 let trait_id = concrete_trait_id.trait_id(db);
2636 let impl_name = impl_impl_def_id.name(defs_db);
2637 let trait_impl_id = db.trait_impl_by_name(trait_id, impl_name.clone())?.ok_or_else(|| {
2638 diagnostics.report(impl_impl_ast, ImplItemNotInTrait {
2639 impl_def_id,
2640 impl_item_name: impl_name,
2641 trait_id,
2642 item_kind: "impl".into(),
2643 })
2644 })?;
2645
2646 let generic_params_node = impl_impl_ast.generic_params(syntax_db);
2649 if !generic_params_node.is_empty(syntax_db) {
2650 diagnostics.report(&generic_params_node, GenericsNotSupportedInItem {
2651 scope: "Impl".into(),
2652 item_kind: "impl".into(),
2653 });
2654 }
2655
2656 let concrete_trait_impl = ConcreteTraitImplId::new(db, concrete_trait_id, trait_impl_id);
2657 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2658
2659 let concrete_trait_impl_concrete_trait =
2660 db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
2661 SubstitutionRewriter { db, substitution: impl_def_substitution.as_ref() }
2662 .rewrite(concrete_trait_id)
2663 });
2664
2665 let resolved_impl_concrete_trait =
2666 impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2667 let _ = (|| -> Result<(), DiagnosticAdded> {
2669 if resolver
2670 .inference()
2671 .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
2672 .is_err()
2673 {
2674 diagnostics.report(impl_impl_ast, TraitMismatch {
2675 expected_trt: concrete_trait_impl_concrete_trait?,
2676 actual_trt: resolved_impl_concrete_trait?,
2677 });
2678 }
2679 Ok(())
2680 })();
2681
2682 Ok(trait_impl_id)
2683}
2684
2685#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2686#[debug_db(dyn SemanticGroup + 'static)]
2687pub struct ImplicitImplImplData {
2688 resolved_impl: Maybe<ImplId>,
2689 trait_impl_id: TraitImplId,
2690 diagnostics: Diagnostics<SemanticDiagnostic>,
2691}
2692
2693pub fn implicit_impl_impl_semantic_diagnostics(
2695 db: &dyn SemanticGroup,
2696 impl_def_id: ImplDefId,
2697 trait_impl_id: TraitImplId,
2698) -> Diagnostics<SemanticDiagnostic> {
2699 db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, false)
2700 .map(|data| data.diagnostics)
2701 .unwrap_or_default()
2702}
2703pub fn implicit_impl_impl_impl(
2705 db: &dyn SemanticGroup,
2706 impl_def_id: ImplDefId,
2707 trait_impl_id: TraitImplId,
2708 in_cycle: bool,
2709) -> Maybe<ImplId> {
2710 db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, in_cycle)?.resolved_impl
2711}
2712pub fn implicit_impl_impl_impl_cycle(
2714 db: &dyn SemanticGroup,
2715 _cycle: &salsa::Cycle,
2716 impl_def_id: &ImplDefId,
2717 trait_impl_id: &TraitImplId,
2718 _in_cycle: &bool,
2719) -> Maybe<ImplId> {
2720 db.priv_implicit_impl_impl_semantic_data(*impl_def_id, *trait_impl_id, true)?.resolved_impl
2721}
2722
2723pub fn priv_implicit_impl_impl_semantic_data(
2725 db: &dyn SemanticGroup,
2726 impl_def_id: ImplDefId,
2727 trait_impl_id: TraitImplId,
2728 in_cycle: bool,
2729) -> Maybe<ImplicitImplImplData> {
2730 let mut diagnostics = SemanticDiagnostics::default();
2731 if in_cycle {
2732 let err =
2733 Err(diagnostics.report(impl_def_id.stable_ptr(db.upcast()).untyped(), ImplAliasCycle));
2734 return Ok(ImplicitImplImplData {
2735 resolved_impl: err,
2736 trait_impl_id,
2737 diagnostics: diagnostics.build(),
2738 });
2739 }
2740 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
2741
2742 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2743 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2744
2745 let mut resolver =
2746 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2747 resolver.trait_or_impl_ctx = TraitOrImplContext::None;
2749
2750 let concrete_trait_impl_concrete_trait = db
2751 .impl_def_concrete_trait(impl_def_id)
2752 .and_then(|concrete_trait_id| {
2753 db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new(
2754 db,
2755 concrete_trait_id,
2756 trait_impl_id,
2757 ))
2758 })
2759 .and_then(|concrete_trait_id| {
2760 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2761 SubstitutionRewriter { db, substitution: impl_def_substitution.as_ref() }
2762 .rewrite(concrete_trait_id)
2763 });
2764 let impl_lookup_context = resolver.impl_lookup_context();
2765 let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
2766 let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
2767 if let Err((err_set, _)) = resolver.inference().finalize_without_reporting() {
2768 diagnostics.report(
2769 impl_def_id.stable_ptr(db.upcast()).untyped(),
2770 ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
2771 );
2772 resolver.inference().report_on_pending_error(
2773 err_set,
2774 &mut diagnostics,
2775 impl_def_id.stable_ptr(db.upcast()).untyped(),
2776 );
2777 };
2778 resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
2779 });
2780
2781 Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
2782}
2783pub fn priv_implicit_impl_impl_semantic_data_cycle(
2785 db: &dyn SemanticGroup,
2786 _cycle: &salsa::Cycle,
2787 impl_def_id: &ImplDefId,
2788 trait_impl_id: &TraitImplId,
2789 _in_cycle: &bool,
2790) -> Maybe<ImplicitImplImplData> {
2791 priv_implicit_impl_impl_semantic_data(db, *impl_def_id, *trait_impl_id, true)
2793}
2794
2795pub fn impl_impl_implized_by_context(
2799 db: &dyn SemanticGroup,
2800 impl_impl_id: ImplImplId,
2801 impl_def_id: ImplDefId,
2802 in_cycle: bool,
2803) -> Maybe<ImplId> {
2804 if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
2805 return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
2806 }
2807
2808 let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
2809
2810 db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
2811}
2812
2813pub fn impl_impl_implized_by_context_cycle(
2815 db: &dyn SemanticGroup,
2816 _cycle: &salsa::Cycle,
2817 impl_impl_id: &ImplImplId,
2818 impl_def_id: &ImplDefId,
2819 _in_cycle: &bool,
2820) -> Maybe<ImplId> {
2821 impl_impl_implized_by_context(db, *impl_impl_id, *impl_def_id, true)
2823}
2824
2825pub fn impl_impl_concrete_implized(
2827 db: &dyn SemanticGroup,
2828 impl_impl_id: ImplImplId,
2829) -> Maybe<ImplId> {
2830 impl_impl_concrete_implized_ex(db, impl_impl_id, false)
2831}
2832
2833pub fn impl_impl_concrete_implized_cycle(
2835 db: &dyn SemanticGroup,
2836 _cycle: &salsa::Cycle,
2837 impl_impl_id: &ImplImplId,
2838) -> Maybe<ImplId> {
2839 impl_impl_concrete_implized_ex(db, *impl_impl_id, true)
2840}
2841
2842fn impl_impl_concrete_implized_ex(
2843 db: &dyn SemanticGroup,
2844 impl_impl_id: ImplImplId,
2845 in_cycle: bool,
2846) -> Maybe<ImplId> {
2847 if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().lookup_intern(db) {
2848 let impl_def_id = concrete_impl.impl_def_id(db);
2849 let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
2850 let substitution: &GenericSubstitution = &concrete_impl.substitution(db)?;
2851 return SubstitutionRewriter { db, substitution }.rewrite(imp);
2852 }
2853 let substitution = &GenericSubstitution::from_impl(impl_impl_id.impl_id());
2854
2855 Ok(ImplLongId::ImplImpl(SubstitutionRewriter { db, substitution }.rewrite(impl_impl_id)?)
2856 .intern(db))
2857}
2858
2859pub fn impl_impl_concrete_trait(
2861 db: &dyn SemanticGroup,
2862 impl_impl_id: ImplImplId,
2863) -> Maybe<ConcreteTraitId> {
2864 let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
2865 let substitution = GenericSubstitution::from_impl(impl_impl_id.impl_id());
2866
2867 db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
2868 SubstitutionRewriter { db, substitution: &substitution }.rewrite(concrete_trait_id)
2869 })
2870}
2871
2872#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2875#[debug_db(dyn SemanticGroup + 'static)]
2876pub struct ImplFunctionDeclarationData {
2877 pub function_declaration_data: FunctionDeclarationData,
2878 trait_function_id: Maybe<TraitFunctionId>,
2879}
2880
2881pub fn impl_function_declaration_diagnostics(
2885 db: &dyn SemanticGroup,
2886 impl_function_id: ImplFunctionId,
2887) -> Diagnostics<SemanticDiagnostic> {
2888 db.priv_impl_function_declaration_data(impl_function_id)
2889 .map(|data| data.function_declaration_data.diagnostics)
2890 .unwrap_or_default()
2891}
2892
2893pub fn impl_function_signature(
2895 db: &dyn SemanticGroup,
2896 impl_function_id: ImplFunctionId,
2897) -> Maybe<semantic::Signature> {
2898 Ok(db
2899 .priv_impl_function_declaration_data(impl_function_id)?
2900 .function_declaration_data
2901 .signature)
2902}
2903
2904pub fn impl_function_generic_params(
2906 db: &dyn SemanticGroup,
2907 impl_function_id: ImplFunctionId,
2908) -> Maybe<Vec<semantic::GenericParam>> {
2909 Ok(db.priv_impl_function_generic_params_data(impl_function_id)?.generic_params)
2910}
2911
2912pub fn priv_impl_function_generic_params_data(
2914 db: &dyn SemanticGroup,
2915 impl_function_id: ImplFunctionId,
2916) -> Maybe<GenericParamsData> {
2917 let module_file_id = impl_function_id.module_file_id(db.upcast());
2918 let mut diagnostics = SemanticDiagnostics::default();
2919 let impl_def_id = impl_function_id.impl_def_id(db.upcast());
2920 let data = db.priv_impl_definition_data(impl_def_id)?;
2921 let function_syntax = &data.function_asts[&impl_function_id];
2922 let syntax_db = db.upcast();
2923 let declaration = function_syntax.declaration(syntax_db);
2924 let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2925 ImplItemId::Function(impl_function_id),
2926 ));
2927 let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2928 let mut resolver =
2929 Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2930 let generic_params = semantic_generic_params(
2931 db,
2932 &mut diagnostics,
2933 &mut resolver,
2934 module_file_id,
2935 &declaration.generic_params(syntax_db),
2936 );
2937 let inference = &mut resolver.inference();
2938 inference.finalize(&mut diagnostics, function_syntax.stable_ptr().untyped());
2939
2940 let generic_params = inference.rewrite(generic_params).no_err();
2941 let resolver_data = Arc::new(resolver.data);
2942 Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
2943}
2944
2945pub fn impl_function_attributes(
2947 db: &dyn SemanticGroup,
2948 impl_function_id: ImplFunctionId,
2949) -> Maybe<Vec<Attribute>> {
2950 Ok(db
2951 .priv_impl_function_declaration_data(impl_function_id)?
2952 .function_declaration_data
2953 .attributes)
2954}
2955
2956pub fn impl_function_resolver_data(
2958 db: &dyn SemanticGroup,
2959 impl_function_id: ImplFunctionId,
2960) -> Maybe<Arc<ResolverData>> {
2961 Ok(db
2962 .priv_impl_function_declaration_data(impl_function_id)?
2963 .function_declaration_data
2964 .resolver_data)
2965}
2966
2967pub fn impl_function_declaration_inline_config(
2969 db: &dyn SemanticGroup,
2970 impl_function_id: ImplFunctionId,
2971) -> Maybe<InlineConfiguration> {
2972 Ok(db
2973 .priv_impl_function_declaration_data(impl_function_id)?
2974 .function_declaration_data
2975 .inline_config)
2976}
2977
2978pub fn impl_function_declaration_implicit_precedence(
2980 db: &dyn SemanticGroup,
2981 impl_function_id: ImplFunctionId,
2982) -> Maybe<ImplicitPrecedence> {
2983 Ok(db
2984 .priv_impl_function_declaration_data(impl_function_id)?
2985 .function_declaration_data
2986 .implicit_precedence)
2987}
2988
2989pub fn impl_function_declaration_implicits(
2991 db: &dyn SemanticGroup,
2992 impl_function_id: ImplFunctionId,
2993) -> Maybe<Vec<TypeId>> {
2994 Ok(db
2995 .priv_impl_function_declaration_data(impl_function_id)?
2996 .function_declaration_data
2997 .signature
2998 .implicits)
2999}
3000
3001pub fn impl_function_trait_function(
3003 db: &dyn SemanticGroup,
3004 impl_function_id: ImplFunctionId,
3005) -> Maybe<TraitFunctionId> {
3006 db.priv_impl_function_declaration_data(impl_function_id)?.trait_function_id
3007}
3008
3009pub fn priv_impl_function_declaration_data(
3013 db: &dyn SemanticGroup,
3014 impl_function_id: ImplFunctionId,
3015) -> Maybe<ImplFunctionDeclarationData> {
3016 let mut diagnostics = SemanticDiagnostics::default();
3017 let impl_def_id = impl_function_id.impl_def_id(db.upcast());
3018 let data = db.priv_impl_definition_data(impl_def_id)?;
3019 let function_syntax = &data.function_asts[&impl_function_id];
3020 let syntax_db = db.upcast();
3021 let declaration = function_syntax.declaration(syntax_db);
3022
3023 let generic_params_data = db.priv_impl_function_generic_params_data(impl_function_id)?;
3024 let generic_params = generic_params_data.generic_params;
3025 let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3026 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3027 let mut resolver = Resolver::with_data(
3028 db,
3029 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3030 );
3031 diagnostics.extend(generic_params_data.diagnostics);
3032 resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3033
3034 let signature_syntax = declaration.signature(syntax_db);
3035
3036 let mut environment = Environment::empty();
3037 let signature = semantic::Signature::from_ast(
3038 &mut diagnostics,
3039 db,
3040 &mut resolver,
3041 &signature_syntax,
3042 FunctionTitleId::Impl(impl_function_id),
3043 &mut environment,
3044 );
3045
3046 let attributes = function_syntax.attributes(syntax_db).structurize(syntax_db);
3047 let (implicit_precedence, _) =
3048 get_implicit_precedence(&mut diagnostics, &mut resolver, &attributes);
3049
3050 let inference = &mut resolver.inference();
3051 inference.finalize(&mut diagnostics, function_syntax.stable_ptr().untyped());
3053 let trait_function_id = validate_impl_function_signature(
3054 db,
3055 &mut diagnostics,
3056 inference,
3057 ValidateImplFunctionSignatureParams {
3058 impl_function_id,
3059 signature_syntax: &signature_syntax,
3060 signature: &signature,
3061 impl_function_syntax: function_syntax,
3062 impl_func_generics: &generic_params,
3063 },
3064 );
3065
3066 let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3067
3068 forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3069
3070 let signature = inference.rewrite(signature).no_err();
3071 let generic_params = inference.rewrite(generic_params).no_err();
3072
3073 let resolver_data = Arc::new(resolver.data);
3074 Ok(ImplFunctionDeclarationData {
3075 function_declaration_data: FunctionDeclarationData {
3076 diagnostics: diagnostics.build(),
3077 signature,
3078 generic_params,
3079 environment,
3080 attributes,
3081 resolver_data,
3082 inline_config,
3083 implicit_precedence,
3084 },
3085 trait_function_id,
3086 })
3087}
3088
3089struct ValidateImplFunctionSignatureParams<'a> {
3091 impl_function_id: ImplFunctionId,
3093 signature_syntax: &'a ast::FunctionSignature,
3095 signature: &'a semantic::Signature,
3097 impl_function_syntax: &'a ast::FunctionWithBody,
3099 impl_func_generics: &'a [GenericParam],
3101}
3102
3103fn validate_impl_function_signature(
3105 db: &dyn SemanticGroup,
3106 diagnostics: &mut SemanticDiagnostics,
3107 inference: &mut Inference<'_>,
3108 ValidateImplFunctionSignatureParams {
3109 impl_function_id,
3110 signature_syntax,
3111 signature,
3112 impl_function_syntax,
3113 impl_func_generics,
3114 }: ValidateImplFunctionSignatureParams<'_>,
3115) -> Maybe<TraitFunctionId> {
3116 let syntax_db = db.upcast();
3117 let defs_db = db.upcast();
3118 let impl_def_id = impl_function_id.impl_def_id(defs_db);
3119 let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3120 let trait_id = concrete_trait_id.trait_id(db);
3121 let function_name = impl_function_id.name(defs_db);
3122 let trait_function_id =
3123 db.trait_function_by_name(trait_id, function_name.clone())?.ok_or_else(|| {
3124 diagnostics.report(impl_function_syntax, ImplItemNotInTrait {
3125 impl_def_id,
3126 impl_item_name: function_name,
3127 trait_id,
3128 item_kind: "function".into(),
3129 })
3130 })?;
3131 let concrete_trait_function =
3132 ConcreteTraitGenericFunctionId::new(db, concrete_trait_id, trait_function_id);
3133 let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3134
3135 let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3139 if impl_func_generics.len() != func_generics.len() {
3140 diagnostics.report(
3141 &impl_function_syntax.declaration(syntax_db).name(syntax_db),
3142 WrongNumberOfGenericParamsForImplFunction {
3143 expected: func_generics.len(),
3144 actual: impl_func_generics.len(),
3145 },
3146 );
3147 return Ok(trait_function_id);
3148 }
3149 let substitution =
3150 GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3151 let concrete_trait_signature = SubstitutionRewriter { db, substitution: &substitution }
3152 .rewrite(concrete_trait_signature)?;
3153
3154 if signature.params.len() != concrete_trait_signature.params.len() {
3155 diagnostics.report(&signature_syntax.parameters(syntax_db), WrongNumberOfParameters {
3156 impl_def_id,
3157 impl_function_id,
3158 trait_id,
3159 expected: concrete_trait_signature.params.len(),
3160 actual: signature.params.len(),
3161 });
3162 }
3163 let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3164 let concrete_trait_signature =
3165 SubstitutionRewriter { db, substitution: impl_def_substitution.as_ref() }
3166 .rewrite(concrete_trait_signature)?;
3167 for (idx, (param, trait_param)) in
3168 izip!(signature.params.iter(), concrete_trait_signature.params.iter()).enumerate()
3169 {
3170 let expected_ty = inference.rewrite(trait_param.ty).no_err();
3171 let actual_ty = inference.rewrite(param.ty).no_err();
3172
3173 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3174 diagnostics.report(
3175 &extract_matches!(
3176 signature_syntax.parameters(syntax_db).elements(syntax_db)[idx]
3177 .type_clause(syntax_db),
3178 OptionTypeClause::TypeClause
3179 )
3180 .ty(syntax_db),
3181 WrongParameterType {
3182 impl_def_id,
3183 impl_function_id,
3184 trait_id,
3185 expected_ty,
3186 actual_ty,
3187 },
3188 );
3189 }
3190
3191 if trait_param.mutability != param.mutability {
3192 if trait_param.mutability == Mutability::Reference {
3193 diagnostics.report(
3194 &signature_syntax.parameters(syntax_db).elements(syntax_db)[idx]
3195 .modifiers(syntax_db),
3196 ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3197 );
3198 }
3199
3200 if param.mutability == Mutability::Reference {
3201 diagnostics.report(
3202 &signature_syntax.parameters(syntax_db).elements(syntax_db)[idx]
3203 .modifiers(syntax_db),
3204 ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3205 );
3206 }
3207 }
3208
3209 if trait_param.name != param.name {
3210 diagnostics.report(
3211 &signature_syntax.parameters(syntax_db).elements(syntax_db)[idx].name(syntax_db),
3212 WrongParameterName {
3213 impl_def_id,
3214 impl_function_id,
3215 trait_id,
3216 expected_name: trait_param.name.clone(),
3217 },
3218 );
3219 }
3220 }
3221
3222 if !concrete_trait_signature.panicable && signature.panicable {
3223 diagnostics.report(signature_syntax, PassPanicAsNopanic { impl_function_id, trait_id });
3224 }
3225
3226 let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3227 let actual_ty = inference.rewrite(signature.return_type).no_err();
3228
3229 if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3230 let location_ptr = match signature_syntax.ret_ty(syntax_db) {
3231 OptionReturnTypeClause::ReturnTypeClause(ret_ty) => {
3232 ret_ty.ty(syntax_db).as_syntax_node()
3233 }
3234 OptionReturnTypeClause::Empty(_) => {
3235 impl_function_syntax.body(syntax_db).lbrace(syntax_db).as_syntax_node()
3236 }
3237 }
3238 .stable_ptr();
3239 diagnostics.report(location_ptr, WrongReturnTypeForImpl {
3240 impl_def_id,
3241 impl_function_id,
3242 trait_id,
3243 expected_ty,
3244 actual_ty,
3245 });
3246 }
3247 Ok(trait_function_id)
3248}
3249
3250pub fn impl_function_body_diagnostics(
3256 db: &dyn SemanticGroup,
3257 impl_function_id: ImplFunctionId,
3258) -> Diagnostics<SemanticDiagnostic> {
3259 db.priv_impl_function_body_data(impl_function_id)
3260 .map(|data| data.diagnostics)
3261 .unwrap_or_default()
3262}
3263
3264pub fn impl_function_body(
3266 db: &dyn SemanticGroup,
3267 impl_function_id: ImplFunctionId,
3268) -> Maybe<Arc<FunctionBody>> {
3269 Ok(db.priv_impl_function_body_data(impl_function_id)?.body)
3270}
3271
3272pub fn impl_function_body_resolver_data(
3274 db: &dyn SemanticGroup,
3275 impl_function_id: ImplFunctionId,
3276) -> Maybe<Arc<ResolverData>> {
3277 Ok(db.priv_impl_function_body_data(impl_function_id)?.resolver_data)
3278}
3279
3280pub fn priv_impl_function_body_data(
3284 db: &dyn SemanticGroup,
3285 impl_function_id: ImplFunctionId,
3286) -> Maybe<FunctionBodyData> {
3287 let defs_db = db.upcast();
3288 let mut diagnostics = SemanticDiagnostics::default();
3289 let impl_def_id = impl_function_id.impl_def_id(defs_db);
3290 let data = db.priv_impl_definition_data(impl_def_id)?;
3291 let function_syntax = &data.function_asts[&impl_function_id];
3292 let declaration = db.priv_impl_function_declaration_data(impl_function_id)?;
3294 let parent_resolver_data = declaration.function_declaration_data.resolver_data;
3295 let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3296 ImplItemId::Function(impl_function_id),
3297 ));
3298 let resolver =
3299 Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3300 let environment: Environment = declaration.function_declaration_data.environment;
3301
3302 let function_id = (|| {
3303 let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3304 let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3305
3306 let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3307 impl_id: ImplLongId::Concrete(
3308 ConcreteImplLongId {
3309 impl_def_id,
3310 generic_args: generic_params_to_args(&generic_parameters, db),
3311 }
3312 .intern(db),
3313 )
3314 .intern(db),
3315 function: trait_function_id,
3316 });
3317
3318 Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3319 })();
3320 let mut ctx = ComputationContext::new(
3322 db,
3323 &mut diagnostics,
3324 resolver,
3325 Some(&declaration.function_declaration_data.signature),
3326 environment,
3327 ContextFunction::Function(function_id),
3328 );
3329 let function_body = function_syntax.body(db.upcast());
3330 let return_type = declaration.function_declaration_data.signature.return_type;
3331 let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3332 let ComputationContext { arenas: Arenas { exprs, patterns, statements }, resolver, .. } = ctx;
3333
3334 let expr_lookup: UnorderedHashMap<_, _> =
3335 exprs.iter().map(|(expr_id, expr)| (expr.stable_ptr(), expr_id)).collect();
3336 let pattern_lookup: UnorderedHashMap<_, _> =
3337 patterns.iter().map(|(pattern_id, pattern)| (pattern.stable_ptr(), pattern_id)).collect();
3338 let resolver_data = Arc::new(resolver.data);
3339 Ok(FunctionBodyData {
3340 diagnostics: diagnostics.build(),
3341 expr_lookup,
3342 pattern_lookup,
3343 resolver_data,
3344 body: Arc::new(FunctionBody { arenas: Arenas { exprs, patterns, statements }, body_expr }),
3345 })
3346}
3347
3348pub fn priv_impl_is_fully_concrete(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3349 impl_id.lookup_intern(db).is_fully_concrete(db)
3350}
3351
3352pub fn priv_impl_is_var_free(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3353 impl_id.lookup_intern(db).is_var_free(db)
3354}