1#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
5
6#[cfg(feature = "in-rust-tree")]
7extern crate rustc_index;
8
9#[cfg(not(feature = "in-rust-tree"))]
10extern crate ra_ap_rustc_index as rustc_index;
11
12#[cfg(feature = "in-rust-tree")]
13extern crate rustc_abi;
14
15#[cfg(not(feature = "in-rust-tree"))]
16extern crate ra_ap_rustc_abi as rustc_abi;
17
18#[cfg(feature = "in-rust-tree")]
19extern crate rustc_pattern_analysis;
20
21#[cfg(not(feature = "in-rust-tree"))]
22extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
23
24#[cfg(feature = "in-rust-tree")]
25extern crate rustc_ast_ir;
26
27#[cfg(not(feature = "in-rust-tree"))]
28extern crate ra_ap_rustc_ast_ir as rustc_ast_ir;
29
30#[cfg(feature = "in-rust-tree")]
31extern crate rustc_type_ir;
32
33#[cfg(not(feature = "in-rust-tree"))]
34extern crate ra_ap_rustc_type_ir as rustc_type_ir;
35
36#[cfg(feature = "in-rust-tree")]
37extern crate rustc_next_trait_solver;
38
39#[cfg(not(feature = "in-rust-tree"))]
40extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver;
41
42mod builder;
43mod chalk_db;
44mod chalk_ext;
45mod drop;
46mod infer;
47mod inhabitedness;
48mod interner;
49mod lower;
50mod lower_nextsolver;
51mod mapping;
52pub mod next_solver;
53mod target_feature;
54mod tls;
55mod utils;
56
57pub mod autoderef;
58pub mod consteval;
59pub mod consteval_nextsolver;
60pub mod db;
61pub mod diagnostics;
62pub mod display;
63pub mod dyn_compatibility;
64pub mod generics;
65pub mod lang_items;
66pub mod layout;
67pub mod method_resolution;
68pub mod mir;
69pub mod primitive;
70pub mod traits;
71
72#[cfg(test)]
73mod test_db;
74#[cfg(test)]
75mod tests;
76mod variance;
77
78use std::hash::Hash;
79
80use chalk_ir::{
81 NoSolution, VariableKinds,
82 fold::{Shift, TypeFoldable},
83 interner::HasInterner,
84};
85use either::Either;
86use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
87use hir_expand::name::Name;
88use indexmap::{IndexMap, map::Entry};
89use intern::{Symbol, sym};
90use la_arena::{Arena, Idx};
91use mir::{MirEvalError, VTableMap};
92use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
93use rustc_type_ir::inherent::SliceLike;
94use syntax::ast::{ConstArg, make};
95use traits::FnTrait;
96use triomphe::Arc;
97
98use crate::{
99 consteval::unknown_const,
100 db::HirDatabase,
101 display::{DisplayTarget, HirDisplay},
102 generics::Generics,
103 infer::unify::InferenceTable,
104 next_solver::{DbInterner, mapping::convert_ty_for_result},
105};
106
107pub use autoderef::autoderef;
108pub use builder::{ParamKind, TyBuilder};
109pub use chalk_ext::*;
110pub use drop::DropGlue;
111pub use infer::{
112 Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult,
113 InferenceTyDiagnosticSource, OverloadedDeref, PointerCast,
114 cast::CastError,
115 closure::{CaptureKind, CapturedItem},
116 could_coerce, could_unify, could_unify_deeply,
117};
118pub use interner::Interner;
119pub use lower::{
120 ImplTraitLoweringMode, LifetimeElisionKind, ParamLoweringMode, TyDefId, TyLoweringContext,
121 ValueTyDefId, diagnostics::*,
122};
123pub use lower_nextsolver::associated_type_shorthand_candidates;
124pub use mapping::{
125 ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
126 lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
127 to_foreign_def_id, to_placeholder_idx,
128};
129pub use method_resolution::check_orphan_rules;
130pub use target_feature::TargetFeatures;
131pub use traits::TraitEnvironment;
132pub use utils::{Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call};
133pub use variance::Variance;
134
135pub use chalk_ir::{
136 AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
137 cast::Cast,
138 visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
139};
140
141pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
142pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
143pub type FnDefId = chalk_ir::FnDefId<Interner>;
144pub type ClosureId = chalk_ir::ClosureId<Interner>;
145pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
146pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
147
148pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
149
150pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>;
151pub type Binders<T> = chalk_ir::Binders<T>;
160pub type Substitution = chalk_ir::Substitution<Interner>;
166pub type GenericArg = chalk_ir::GenericArg<Interner>;
167pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
168
169pub type Ty = chalk_ir::Ty<Interner>;
170pub type TyKind = chalk_ir::TyKind<Interner>;
171pub type TypeFlags = chalk_ir::TypeFlags;
172pub(crate) type DynTy = chalk_ir::DynTy<Interner>;
173pub type FnPointer = chalk_ir::FnPointer<Interner>;
174pub(crate) use chalk_ir::FnSubst; pub type AliasTy = chalk_ir::AliasTy<Interner>;
177
178pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
179pub(crate) type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
180pub(crate) type InferenceVar = chalk_ir::InferenceVar;
181
182pub(crate) type Lifetime = chalk_ir::Lifetime<Interner>;
183pub(crate) type LifetimeData = chalk_ir::LifetimeData<Interner>;
184pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
185
186pub type ConstValue = chalk_ir::ConstValue<Interner>;
187
188pub type Const = chalk_ir::Const<Interner>;
189pub(crate) type ConstData = chalk_ir::ConstData<Interner>;
190pub(crate) type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
191
192pub type TraitRef = chalk_ir::TraitRef<Interner>;
193pub type QuantifiedWhereClause = Binders<WhereClause>;
194pub type Canonical<T> = chalk_ir::Canonical<T>;
195
196pub(crate) type ChalkTraitId = chalk_ir::TraitId<Interner>;
197pub(crate) type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
198
199pub(crate) type FnSig = chalk_ir::FnSig<Interner>;
200
201pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
202pub type AliasEq = chalk_ir::AliasEq<Interner>;
203pub type WhereClause = chalk_ir::WhereClause<Interner>;
204
205pub(crate) type DomainGoal = chalk_ir::DomainGoal<Interner>;
206pub(crate) type Goal = chalk_ir::Goal<Interner>;
207
208pub(crate) type CanonicalVarKind = chalk_ir::CanonicalVarKind<Interner>;
209pub(crate) type GoalData = chalk_ir::GoalData<Interner>;
210pub(crate) type ProgramClause = chalk_ir::ProgramClause<Interner>;
211
212#[derive(Debug, Default, Clone, PartialEq, Eq)]
216pub enum MemoryMap<'db> {
217 #[default]
218 Empty,
219 Simple(Box<[u8]>),
220 Complex(Box<ComplexMemoryMap<'db>>),
221}
222
223#[derive(Debug, Default, Clone, PartialEq, Eq)]
224pub struct ComplexMemoryMap<'db> {
225 memory: IndexMap<usize, Box<[u8]>, FxBuildHasher>,
226 vtable: VTableMap<'db>,
227}
228
229impl ComplexMemoryMap<'_> {
230 fn insert(&mut self, addr: usize, val: Box<[u8]>) {
231 match self.memory.entry(addr) {
232 Entry::Occupied(mut e) => {
233 if e.get().len() < val.len() {
234 e.insert(val);
235 }
236 }
237 Entry::Vacant(e) => {
238 e.insert(val);
239 }
240 }
241 }
242}
243
244impl<'db> MemoryMap<'db> {
245 pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError> {
246 match self {
247 MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)),
248 MemoryMap::Complex(cm) => cm.vtable.ty(id),
249 }
250 }
251
252 fn simple(v: Box<[u8]>) -> Self {
253 MemoryMap::Simple(v)
254 }
255
256 fn transform_addresses(
260 &self,
261 mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError>,
262 ) -> Result<FxHashMap<usize, usize>, MirEvalError> {
263 let mut transform = |(addr, val): (&usize, &[u8])| {
264 let addr = *addr;
265 let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
266 f(val, align).map(|it| (addr, it))
267 };
268 match self {
269 MemoryMap::Empty => Ok(Default::default()),
270 MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| {
271 let mut map = FxHashMap::with_capacity_and_hasher(1, rustc_hash::FxBuildHasher);
272 map.insert(addr, val);
273 map
274 }),
275 MemoryMap::Complex(cm) => {
276 cm.memory.iter().map(|(addr, val)| transform((addr, val))).collect()
277 }
278 }
279 }
280
281 fn get(&self, addr: usize, size: usize) -> Option<&[u8]> {
282 if size == 0 {
283 Some(&[])
284 } else {
285 match self {
286 MemoryMap::Empty => Some(&[]),
287 MemoryMap::Simple(m) if addr == 0 => m.get(0..size),
288 MemoryMap::Simple(_) => None,
289 MemoryMap::Complex(cm) => cm.memory.get(&addr)?.get(0..size),
290 }
291 }
292 }
293}
294
295#[derive(Debug, Clone, PartialEq, Eq)]
298pub enum ConstScalar {
299 Bytes(Box<[u8]>, MemoryMap<'static>),
300 UnevaluatedConst(GeneralConstId, Substitution),
303 Unknown,
309}
310
311impl Hash for ConstScalar {
312 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
313 core::mem::discriminant(self).hash(state);
314 if let ConstScalar::Bytes(b, _) = self {
315 b.hash(state)
316 }
317 }
318}
319
320#[derive(Debug, Clone, PartialEq, Eq)]
322pub enum ConstScalarNs<'db> {
323 Bytes(Box<[u8]>, MemoryMap<'db>),
324 UnevaluatedConst(GeneralConstId, Substitution),
327 Unknown,
333}
334
335impl Hash for ConstScalarNs<'_> {
336 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
337 core::mem::discriminant(self).hash(state);
338 if let ConstScalarNs::Bytes(b, _) = self {
339 b.hash(state)
340 }
341 }
342}
343
344pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
346 generics::generics(db, id.parent).type_or_const_param_idx(id)
347}
348
349pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
350where
351 T: TypeFoldable<Interner> + HasInterner<Interner = Interner>,
352{
353 Binders::empty(Interner, value.shifted_in_from(Interner, DebruijnIndex::ONE))
354}
355
356pub(crate) fn make_single_type_binders<T: HasInterner<Interner = Interner>>(
357 value: T,
358) -> Binders<T> {
359 Binders::new(
360 chalk_ir::VariableKinds::from_iter(
361 Interner,
362 std::iter::once(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)),
363 ),
364 value,
365 )
366}
367
368pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
369 db: &dyn HirDatabase,
370 generics: &Generics,
371 value: T,
372) -> Binders<T> {
373 Binders::new(variable_kinds_from_iter(db, generics.iter_id()), value)
374}
375
376pub(crate) fn variable_kinds_from_iter(
377 db: &dyn HirDatabase,
378 iter: impl Iterator<Item = hir_def::GenericParamId>,
379) -> VariableKinds<Interner> {
380 VariableKinds::from_iter(
381 Interner,
382 iter.map(|x| match x {
383 hir_def::GenericParamId::ConstParamId(id) => {
384 chalk_ir::VariableKind::Const(db.const_param_ty(id))
385 }
386 hir_def::GenericParamId::TypeParamId(_) => {
387 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
388 }
389 hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
390 }),
391 )
392}
393
394#[derive(Clone, PartialEq, Eq, Debug)]
398pub struct CallableSig {
399 params_and_return: Arc<[Ty]>,
400 is_varargs: bool,
401 safety: Safety,
402 abi: FnAbi,
403}
404
405has_interner!(CallableSig);
406
407#[derive(Debug, Copy, Clone, Eq)]
408pub enum FnAbi {
409 Aapcs,
410 AapcsUnwind,
411 AvrInterrupt,
412 AvrNonBlockingInterrupt,
413 C,
414 CCmseNonsecureCall,
415 CCmseNonsecureEntry,
416 CDecl,
417 CDeclUnwind,
418 CUnwind,
419 Efiapi,
420 Fastcall,
421 FastcallUnwind,
422 Msp430Interrupt,
423 PtxKernel,
424 RiscvInterruptM,
425 RiscvInterruptS,
426 Rust,
427 RustCall,
428 RustCold,
429 RustIntrinsic,
430 Stdcall,
431 StdcallUnwind,
432 System,
433 SystemUnwind,
434 Sysv64,
435 Sysv64Unwind,
436 Thiscall,
437 ThiscallUnwind,
438 Unadjusted,
439 Vectorcall,
440 VectorcallUnwind,
441 Wasm,
442 Win64,
443 Win64Unwind,
444 X86Interrupt,
445 Unknown,
446}
447
448impl PartialEq for FnAbi {
449 fn eq(&self, _other: &Self) -> bool {
450 true
452 }
453}
454
455impl Hash for FnAbi {
456 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
457 core::mem::discriminant(&Self::Unknown).hash(state);
460 }
461}
462
463impl FnAbi {
464 #[rustfmt::skip]
465 pub fn from_symbol(s: &Symbol) -> FnAbi {
466 match s {
467 s if *s == sym::aapcs_dash_unwind => FnAbi::AapcsUnwind,
468 s if *s == sym::aapcs => FnAbi::Aapcs,
469 s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
470 s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
471 s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
472 s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
473 s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
474 s if *s == sym::C => FnAbi::C,
475 s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
476 s if *s == sym::cdecl => FnAbi::CDecl,
477 s if *s == sym::efiapi => FnAbi::Efiapi,
478 s if *s == sym::fastcall_dash_unwind => FnAbi::FastcallUnwind,
479 s if *s == sym::fastcall => FnAbi::Fastcall,
480 s if *s == sym::msp430_dash_interrupt => FnAbi::Msp430Interrupt,
481 s if *s == sym::ptx_dash_kernel => FnAbi::PtxKernel,
482 s if *s == sym::riscv_dash_interrupt_dash_m => FnAbi::RiscvInterruptM,
483 s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS,
484 s if *s == sym::rust_dash_call => FnAbi::RustCall,
485 s if *s == sym::rust_dash_cold => FnAbi::RustCold,
486 s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic,
487 s if *s == sym::Rust => FnAbi::Rust,
488 s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind,
489 s if *s == sym::stdcall => FnAbi::Stdcall,
490 s if *s == sym::system_dash_unwind => FnAbi::SystemUnwind,
491 s if *s == sym::system => FnAbi::System,
492 s if *s == sym::sysv64_dash_unwind => FnAbi::Sysv64Unwind,
493 s if *s == sym::sysv64 => FnAbi::Sysv64,
494 s if *s == sym::thiscall_dash_unwind => FnAbi::ThiscallUnwind,
495 s if *s == sym::thiscall => FnAbi::Thiscall,
496 s if *s == sym::unadjusted => FnAbi::Unadjusted,
497 s if *s == sym::vectorcall_dash_unwind => FnAbi::VectorcallUnwind,
498 s if *s == sym::vectorcall => FnAbi::Vectorcall,
499 s if *s == sym::wasm => FnAbi::Wasm,
500 s if *s == sym::win64_dash_unwind => FnAbi::Win64Unwind,
501 s if *s == sym::win64 => FnAbi::Win64,
502 s if *s == sym::x86_dash_interrupt => FnAbi::X86Interrupt,
503 _ => FnAbi::Unknown,
504 }
505 }
506
507 pub fn as_str(self) -> &'static str {
508 match self {
509 FnAbi::Aapcs => "aapcs",
510 FnAbi::AapcsUnwind => "aapcs-unwind",
511 FnAbi::AvrInterrupt => "avr-interrupt",
512 FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
513 FnAbi::C => "C",
514 FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
515 FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
516 FnAbi::CDecl => "C-decl",
517 FnAbi::CDeclUnwind => "cdecl-unwind",
518 FnAbi::CUnwind => "C-unwind",
519 FnAbi::Efiapi => "efiapi",
520 FnAbi::Fastcall => "fastcall",
521 FnAbi::FastcallUnwind => "fastcall-unwind",
522 FnAbi::Msp430Interrupt => "msp430-interrupt",
523 FnAbi::PtxKernel => "ptx-kernel",
524 FnAbi::RiscvInterruptM => "riscv-interrupt-m",
525 FnAbi::RiscvInterruptS => "riscv-interrupt-s",
526 FnAbi::Rust => "Rust",
527 FnAbi::RustCall => "rust-call",
528 FnAbi::RustCold => "rust-cold",
529 FnAbi::RustIntrinsic => "rust-intrinsic",
530 FnAbi::Stdcall => "stdcall",
531 FnAbi::StdcallUnwind => "stdcall-unwind",
532 FnAbi::System => "system",
533 FnAbi::SystemUnwind => "system-unwind",
534 FnAbi::Sysv64 => "sysv64",
535 FnAbi::Sysv64Unwind => "sysv64-unwind",
536 FnAbi::Thiscall => "thiscall",
537 FnAbi::ThiscallUnwind => "thiscall-unwind",
538 FnAbi::Unadjusted => "unadjusted",
539 FnAbi::Vectorcall => "vectorcall",
540 FnAbi::VectorcallUnwind => "vectorcall-unwind",
541 FnAbi::Wasm => "wasm",
542 FnAbi::Win64 => "win64",
543 FnAbi::Win64Unwind => "win64-unwind",
544 FnAbi::X86Interrupt => "x86-interrupt",
545 FnAbi::Unknown => "unknown-abi",
546 }
547 }
548}
549
550pub type PolyFnSig = Binders<CallableSig>;
552
553impl CallableSig {
554 pub fn from_params_and_return(
555 params: impl Iterator<Item = Ty>,
556 ret: Ty,
557 is_varargs: bool,
558 safety: Safety,
559 abi: FnAbi,
560 ) -> CallableSig {
561 let mut params_and_return = Vec::with_capacity(params.size_hint().0 + 1);
562 params_and_return.extend(params);
563 params_and_return.push(ret);
564 CallableSig { params_and_return: params_and_return.into(), is_varargs, safety, abi }
565 }
566
567 pub fn from_def(db: &dyn HirDatabase, def: FnDefId, substs: &Substitution) -> CallableSig {
568 let callable_def = ToChalk::from_chalk(db, def);
569 let sig = db.callable_item_signature(callable_def);
570 sig.substitute(Interner, substs)
571 }
572 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
573 CallableSig {
574 params_and_return: Arc::from_iter(
576 fn_ptr
577 .substitution
578 .clone()
579 .shifted_out_to(Interner, DebruijnIndex::ONE)
580 .expect("unexpected lifetime vars in fn ptr")
581 .0
582 .as_slice(Interner)
583 .iter()
584 .map(|arg| arg.assert_ty_ref(Interner).clone()),
585 ),
586 is_varargs: fn_ptr.sig.variadic,
587 safety: fn_ptr.sig.safety,
588 abi: fn_ptr.sig.abi,
589 }
590 }
591 pub fn from_fn_sig_and_header<'db>(
592 interner: DbInterner<'db>,
593 sig: crate::next_solver::Binder<'db, rustc_type_ir::FnSigTys<DbInterner<'db>>>,
594 header: rustc_type_ir::FnHeader<DbInterner<'db>>,
595 ) -> CallableSig {
596 CallableSig {
597 params_and_return: Arc::from_iter(
599 sig.skip_binder()
600 .inputs_and_output
601 .iter()
602 .map(|t| convert_ty_for_result(interner, t)),
603 ),
604 is_varargs: header.c_variadic,
605 safety: match header.safety {
606 next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe,
607 next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe,
608 },
609 abi: header.abi,
610 }
611 }
612
613 pub fn to_fn_ptr(&self) -> FnPointer {
614 FnPointer {
615 num_binders: 0,
616 sig: FnSig { abi: self.abi, safety: self.safety, variadic: self.is_varargs },
617 substitution: FnSubst(Substitution::from_iter(
618 Interner,
619 self.params_and_return.iter().cloned(),
620 )),
621 }
622 }
623
624 pub fn abi(&self) -> FnAbi {
625 self.abi
626 }
627
628 pub fn params(&self) -> &[Ty] {
629 &self.params_and_return[0..self.params_and_return.len() - 1]
630 }
631
632 pub fn ret(&self) -> &Ty {
633 &self.params_and_return[self.params_and_return.len() - 1]
634 }
635}
636
637impl TypeFoldable<Interner> for CallableSig {
638 fn try_fold_with<E>(
639 self,
640 folder: &mut dyn chalk_ir::fold::FallibleTypeFolder<Interner, Error = E>,
641 outer_binder: DebruijnIndex,
642 ) -> Result<Self, E> {
643 let vec = self.params_and_return.to_vec();
644 let folded = vec.try_fold_with(folder, outer_binder)?;
645 Ok(CallableSig {
646 params_and_return: folded.into(),
647 is_varargs: self.is_varargs,
648 safety: self.safety,
649 abi: self.abi,
650 })
651 }
652}
653
654#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
655pub enum ImplTraitId {
656 ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx),
657 TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
658 AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
659}
660
661#[derive(PartialEq, Eq, Debug, Hash)]
662pub struct ImplTraits {
663 pub(crate) impl_traits: Arena<ImplTrait>,
664}
665
666has_interner!(ImplTraits);
667
668#[derive(PartialEq, Eq, Debug, Hash)]
669pub struct ImplTrait {
670 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
671}
672
673pub type ImplTraitIdx = Idx<ImplTrait>;
674
675pub fn static_lifetime() -> Lifetime {
676 LifetimeData::Static.intern(Interner)
677}
678
679pub fn error_lifetime() -> Lifetime {
680 LifetimeData::Error.intern(Interner)
681}
682
683pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
684 t: T,
685 for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
686 for_const: impl FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
687) -> T {
688 use chalk_ir::fold::TypeFolder;
689
690 #[derive(chalk_derive::FallibleTypeFolder)]
691 #[has_interner(Interner)]
692 struct FreeVarFolder<
693 F1: FnMut(BoundVar, DebruijnIndex) -> Ty,
694 F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
695 >(F1, F2);
696 impl<F1: FnMut(BoundVar, DebruijnIndex) -> Ty, F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const>
697 TypeFolder<Interner> for FreeVarFolder<F1, F2>
698 {
699 fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
700 self
701 }
702
703 fn interner(&self) -> Interner {
704 Interner
705 }
706
707 fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty {
708 self.0(bound_var, outer_binder)
709 }
710
711 fn fold_free_var_const(
712 &mut self,
713 ty: Ty,
714 bound_var: BoundVar,
715 outer_binder: DebruijnIndex,
716 ) -> Const {
717 self.1(ty, bound_var, outer_binder)
718 }
719 }
720 t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST)
721}
722
723pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
724 t: T,
725 mut for_ty: impl FnMut(Ty, DebruijnIndex) -> Ty,
726 binders: DebruijnIndex,
727) -> T {
728 fold_tys_and_consts(
729 t,
730 |x, d| match x {
731 Either::Left(x) => Either::Left(for_ty(x, d)),
732 Either::Right(x) => Either::Right(x),
733 },
734 binders,
735 )
736}
737
738pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
739 t: T,
740 f: impl FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>,
741 binders: DebruijnIndex,
742) -> T {
743 use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
744 #[derive(chalk_derive::FallibleTypeFolder)]
745 #[has_interner(Interner)]
746 struct TyFolder<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>>(F);
747 impl<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>> TypeFolder<Interner>
748 for TyFolder<F>
749 {
750 fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
751 self
752 }
753
754 fn interner(&self) -> Interner {
755 Interner
756 }
757
758 fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
759 let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
760 self.0(Either::Left(ty), outer_binder).left().unwrap()
761 }
762
763 fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
764 self.0(Either::Right(c), outer_binder).right().unwrap()
765 }
766 }
767 t.fold_with(&mut TyFolder(f), binders)
768}
769
770pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
771 t: T,
772 f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData,
773 binders: DebruijnIndex,
774) -> T {
775 use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
776 #[derive(chalk_derive::FallibleTypeFolder)]
777 #[has_interner(Interner)]
778 struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F);
779 impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner>
780 for TyFolder<F>
781 {
782 fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
783 self
784 }
785
786 fn interner(&self) -> Interner {
787 Interner
788 }
789
790 fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
791 let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
792 self.0(GenericArgData::Ty(ty), outer_binder)
793 .intern(Interner)
794 .ty(Interner)
795 .unwrap()
796 .clone()
797 }
798
799 fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
800 self.0(GenericArgData::Const(c), outer_binder)
801 .intern(Interner)
802 .constant(Interner)
803 .unwrap()
804 .clone()
805 }
806
807 fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime {
808 let lt = lt.super_fold_with(self.as_dyn(), outer_binder);
809 self.0(GenericArgData::Lifetime(lt), outer_binder)
810 .intern(Interner)
811 .lifetime(Interner)
812 .unwrap()
813 .clone()
814 }
815 }
816 t.fold_with(&mut TyFolder(f), binders)
817}
818
819pub fn replace_errors_with_variables<T>(t: &T) -> Canonical<T>
823where
824 T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + Clone,
825{
826 use chalk_ir::{
827 Fallible,
828 fold::{FallibleTypeFolder, TypeSuperFoldable},
829 };
830 struct ErrorReplacer {
831 vars: usize,
832 }
833 impl FallibleTypeFolder<Interner> for ErrorReplacer {
834 type Error = NoSolution;
835
836 fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
837 self
838 }
839
840 fn interner(&self) -> Interner {
841 Interner
842 }
843
844 fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
845 if let TyKind::Error = ty.kind(Interner) {
846 let index = self.vars;
847 self.vars += 1;
848 Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner))
849 } else {
850 ty.try_super_fold_with(self.as_dyn(), outer_binder)
851 }
852 }
853
854 fn try_fold_inference_ty(
855 &mut self,
856 _var: InferenceVar,
857 _kind: TyVariableKind,
858 _outer_binder: DebruijnIndex,
859 ) -> Fallible<Ty> {
860 if cfg!(debug_assertions) {
861 Err(NoSolution)
864 } else {
865 Ok(TyKind::Error.intern(Interner))
866 }
867 }
868
869 fn try_fold_free_var_ty(
870 &mut self,
871 _bound_var: BoundVar,
872 _outer_binder: DebruijnIndex,
873 ) -> Fallible<Ty> {
874 if cfg!(debug_assertions) {
875 Err(NoSolution)
878 } else {
879 Ok(TyKind::Error.intern(Interner))
880 }
881 }
882
883 fn try_fold_inference_const(
884 &mut self,
885 ty: Ty,
886 _var: InferenceVar,
887 _outer_binder: DebruijnIndex,
888 ) -> Fallible<Const> {
889 if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) }
890 }
891
892 fn try_fold_free_var_const(
893 &mut self,
894 ty: Ty,
895 _bound_var: BoundVar,
896 _outer_binder: DebruijnIndex,
897 ) -> Fallible<Const> {
898 if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) }
899 }
900
901 fn try_fold_inference_lifetime(
902 &mut self,
903 _var: InferenceVar,
904 _outer_binder: DebruijnIndex,
905 ) -> Fallible<Lifetime> {
906 if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) }
907 }
908
909 fn try_fold_free_var_lifetime(
910 &mut self,
911 _bound_var: BoundVar,
912 _outer_binder: DebruijnIndex,
913 ) -> Fallible<Lifetime> {
914 if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) }
915 }
916 }
917 let mut error_replacer = ErrorReplacer { vars: 0 };
918 let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) {
919 Ok(t) => t,
920 Err(_) => panic!("Encountered unbound or inference vars in {t:?}"),
921 };
922 let kinds = (0..error_replacer.vars).map(|_| {
923 chalk_ir::CanonicalVarKind::new(
924 chalk_ir::VariableKind::Ty(TyVariableKind::General),
925 chalk_ir::UniverseIndex::ROOT,
926 )
927 });
928 Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
929}
930
931pub fn callable_sig_from_fn_trait(
932 self_ty: &Ty,
933 trait_env: Arc<TraitEnvironment>,
934 db: &dyn HirDatabase,
935) -> Option<(FnTrait, CallableSig)> {
936 let krate = trait_env.krate;
937 let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
938 let output_assoc_type = fn_once_trait
939 .trait_items(db)
940 .associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
941
942 let mut table = InferenceTable::new(db, trait_env.clone());
943 let b = TyBuilder::trait_ref(db, fn_once_trait);
944 if b.remaining() != 2 {
945 return None;
946 }
947
948 let args_ty = table.new_type_var();
952 let mut trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
953 let projection = TyBuilder::assoc_type_projection(
954 db,
955 output_assoc_type,
956 Some(trait_ref.substitution.clone()),
957 )
958 .build();
959
960 let block = trait_env.block;
961 let trait_env = trait_env.env.clone();
962 let obligation =
963 InEnvironment { goal: trait_ref.clone().cast(Interner), environment: trait_env.clone() };
964 let canonical = table.canonicalize(obligation.clone());
965 if !db.trait_solve(krate, block, canonical.cast(Interner)).no_solution() {
966 table.register_obligation(obligation.goal);
967 let return_ty = table.normalize_projection_ty(projection);
968 for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
969 let fn_x_trait = fn_x.get_id(db, krate)?;
970 trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
971 let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
972 goal: trait_ref.clone().cast(Interner),
973 environment: trait_env.clone(),
974 };
975 let canonical = table.canonicalize(obligation.clone());
976 if !db.trait_solve(krate, block, canonical.cast(Interner)).no_solution() {
977 let ret_ty = table.resolve_completely(return_ty);
978 let args_ty = table.resolve_completely(args_ty);
979 let params = args_ty
980 .as_tuple()?
981 .iter(Interner)
982 .map(|it| it.assert_ty_ref(Interner))
983 .cloned();
984
985 return Some((
986 fn_x,
987 CallableSig::from_params_and_return(
988 params,
989 ret_ty,
990 false,
991 Safety::Safe,
992 FnAbi::RustCall,
993 ),
994 ));
995 }
996 }
997 unreachable!("It should at least implement FnOnce at this point");
998 } else {
999 None
1000 }
1001}
1002
1003struct PlaceholderCollector<'db> {
1004 db: &'db dyn HirDatabase,
1005 placeholders: FxHashSet<TypeOrConstParamId>,
1006}
1007
1008impl PlaceholderCollector<'_> {
1009 fn collect(&mut self, idx: PlaceholderIndex) {
1010 let id = from_placeholder_idx(self.db, idx);
1011 self.placeholders.insert(id);
1012 }
1013}
1014
1015impl TypeVisitor<Interner> for PlaceholderCollector<'_> {
1016 type BreakTy = ();
1017
1018 fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
1019 self
1020 }
1021
1022 fn interner(&self) -> Interner {
1023 Interner
1024 }
1025
1026 fn visit_ty(
1027 &mut self,
1028 ty: &Ty,
1029 outer_binder: DebruijnIndex,
1030 ) -> std::ops::ControlFlow<Self::BreakTy> {
1031 let has_placeholder_bits = TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER;
1032 let chalk_ir::TyData { kind, flags } = ty.data(Interner);
1033
1034 if let TyKind::Placeholder(idx) = kind {
1035 self.collect(*idx);
1036 } else if flags.intersects(has_placeholder_bits) {
1037 return ty.super_visit_with(self, outer_binder);
1038 } else {
1039 }
1042
1043 std::ops::ControlFlow::Continue(())
1044 }
1045
1046 fn visit_const(
1047 &mut self,
1048 constant: &chalk_ir::Const<Interner>,
1049 _outer_binder: DebruijnIndex,
1050 ) -> std::ops::ControlFlow<Self::BreakTy> {
1051 if let chalk_ir::ConstValue::Placeholder(idx) = constant.data(Interner).value {
1052 self.collect(idx);
1053 }
1054 std::ops::ControlFlow::Continue(())
1055 }
1056}
1057
1058pub fn collect_placeholders<T>(value: &T, db: &dyn HirDatabase) -> Vec<TypeOrConstParamId>
1060where
1061 T: ?Sized + TypeVisitable<Interner>,
1062{
1063 let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() };
1064 _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
1065 collector.placeholders.into_iter().collect()
1066}
1067
1068pub fn known_const_to_ast(
1069 konst: &Const,
1070 db: &dyn HirDatabase,
1071 display_target: DisplayTarget,
1072) -> Option<ConstArg> {
1073 Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str()))
1074}
1075
1076#[derive(Debug, Copy, Clone)]
1077pub(crate) enum DeclOrigin {
1078 LetExpr,
1079 LocalDecl {
1081 has_else: bool,
1082 },
1083}
1084
1085#[derive(Debug, Copy, Clone)]
1089pub(crate) struct DeclContext {
1090 pub(crate) origin: DeclOrigin,
1091}
1092
1093pub fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
1094 use std::env;
1095 use std::sync::LazyLock;
1096 use tracing_subscriber::{Registry, layer::SubscriberExt};
1097 use tracing_tree::HierarchicalLayer;
1098
1099 static ENABLE: LazyLock<bool> = LazyLock::new(|| env::var("CHALK_DEBUG").is_ok());
1100 if !*ENABLE {
1101 return None;
1102 }
1103
1104 let filter: tracing_subscriber::filter::Targets =
1105 env::var("CHALK_DEBUG").ok().and_then(|it| it.parse().ok()).unwrap_or_default();
1106 let layer = HierarchicalLayer::default()
1107 .with_indent_lines(true)
1108 .with_ansi(false)
1109 .with_indent_amount(2)
1110 .with_writer(std::io::stderr);
1111 let subscriber = Registry::default().with(filter).with(layer);
1112 Some(tracing::subscriber::set_default(subscriber))
1113}