1//! Type inference, i.e. the process of walking through the code and determining2//! the type of each expression and pattern.3//!4//! For type inference, compare the implementations in rustc (the various5//! check_* methods in [`rustc_hir_typeck/check.rs`] are a good entry point) and6//! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for7//! inference here is the `infer` function, which infers the types of all8//! expressions in a given function.9//!10//! During inference, types (i.e. the `Ty` struct) can contain type 'variables'11//! which represent currently unknown types; as we walk through the expressions,12//! we might determine that certain variables need to be equal to each other, or13//! to certain types. To record this, we use the union-find implementation from14//! the `ena` crate, which is extracted from rustc.15//!16//! [`rustc_hir_typeck/check.rs`]: https://github.com/rust-lang/rust/blob/5503df87342a73d0c29126a7e08dc9c1255c46ad/compiler/rustc_hir_typeck/src/check.rs1718mod autoderef;19mod callee;20pub(crate) mod cast;21pub(crate) mod closure;22mod coerce;23pub(crate) mod diagnostics;24mod expr;25mod fallback;26mod mutability;27mod op;28mod opaques;29mod pat;30mod path;31mod place_op;32pub(crate) mod unify;3334use std::{35 cell::{OnceCell, RefCell},36 convert::identity,37 fmt,38 hash::Hash,39 ops::Deref,40};4142use base_db::{Crate, FxIndexMap};43use either::Either;44use hir_def::{45 AdtId, AssocItemId, AttrDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,46 FunctionId, GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, StaticId, TraitId,47 TupleFieldId, TupleId, VariantId,48 attrs::AttrFlags,49 expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path},50 hir::{BindingId, ExprId, ExprOrPatId, ExprOrPatIdPacked, LabelId, PatId},51 lang_item::LangItems,52 layout::Integer,53 resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},54 signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},55 type_ref::{LifetimeRefId, TypeRefId},56 unstable_features::UnstableFeatures,57};58use hir_expand::{mod_path::ModPath, name::Name};59use indexmap::IndexSet;60use la_arena::ArenaMap;61use macros::{TypeFoldable, TypeVisitable};62use rustc_abi::TargetDataLayout;63use rustc_ast_ir::Mutability;64use rustc_hash::{FxHashMap, FxHashSet};65use rustc_type_ir::{66 AliasTyKind, TypeFoldable, TypeVisitableExt,67 inherent::{GenericArgs as _, IntoKind, Ty as _},68};69use salsa::SalsaValue;70use smallvec::SmallVec;71use span::Edition;72use stdx::never;73use thin_vec::ThinVec;7475use crate::{76 ImplTraitId, IncorrectGenericsLenKind, InferBodyId, PathLoweringDiagnostic, Span,77 TargetFeatures,78 closure_analysis::PlaceBase,79 consteval::{create_anon_const, path_to_const},80 db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},81 generics::Generics,82 infer::{83 callee::DeferredCallResolution,84 closure::analysis::{85 BorrowKind,86 expr_use_visitor::{FakeReadCause, Place},87 },88 coerce::{CoerceMany, DynamicCoerceMany},89 diagnostics::{90 Diagnostics, InferenceTyLoweringContext as TyLoweringContext,91 InferenceTyLoweringVarsCtx,92 },93 expr::ExprIsRead,94 pat::PatOrigin,95 unify::resolve_completely::WriteBackCtxt,96 },97 lower::{98 ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, LifetimeLoweringMode,99 LoweringMode, diagnostics::TyLoweringDiagnostic,100 },101 method_resolution::CandidateId,102 next_solver::{103 AliasTy, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, StoredFnSig,104 StoredGenericArg, StoredGenericArgs, StoredTy, StoredTys, Term, Ty, TyKind, Tys,105 abi::Safety,106 infer::{InferCtxt, ObligationInspector, traits::ObligationCause},107 },108 solver_errors::SolverDiagnostic,109 utils::TargetFeatureIsSafeInTarget,110};111112// This lint has a false positive here. See the link below for details.113//114// https://github.com/rust-lang/rust/issues/57411115#[allow(unreachable_pub)]116pub use coerce::could_coerce;117#[allow(unreachable_pub)]118pub use unify::{could_unify, could_unify_deeply};119120use cast::{CastCheck, CastError};121122/// The entry point of type inference.123fn infer_query<'db>(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {124 infer_query_with_inspect(db, def, None, LoweringMode::Analysis)125}126127pub fn infer_query_with_inspect<'db>(128 db: &'db dyn HirDatabase,129 def: DefWithBodyId,130 inspect: Option<ObligationInspector<'db>>,131 lowering_mode: LoweringMode,132) -> InferenceResult<'db> {133 let _p = tracing::info_span!("infer_query").entered();134 let resolver = def.resolver(db);135 let body = Body::of(db, def);136 let mut ctx = InferenceContext::new(137 db,138 InferBodyId::DefWithBodyId(def),139 ExpressionStoreOwnerId::Body(def),140 def.generic_def(db),141 &body.store,142 resolver,143 true,144 lowering_mode,145 );146147 if let Some(inspect) = inspect {148 ctx.table.infer_ctxt.attach_obligation_inspector(inspect);149 }150151 match def {152 DefWithBodyId::FunctionId(f) => {153 ctx.collect_fn(f, body.self_param.map(|param| param.formal), &body.params)154 }155 DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),156 DefWithBodyId::StaticId(s) => ctx.collect_static(s, StaticSignature::of(db, s)),157 DefWithBodyId::VariantId(v) => {158 ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {159 hir_def::layout::IntegerType::Pointer(signed) => match signed {160 true => ctx.types.types.isize,161 false => ctx.types.types.usize,162 },163 hir_def::layout::IntegerType::Fixed(size, signed) => match signed {164 true => match size {165 Integer::I8 => ctx.types.types.i8,166 Integer::I16 => ctx.types.types.i16,167 Integer::I32 => ctx.types.types.i32,168 Integer::I64 => ctx.types.types.i64,169 Integer::I128 => ctx.types.types.i128,170 },171 false => match size {172 Integer::I8 => ctx.types.types.u8,173 Integer::I16 => ctx.types.types.u16,174 Integer::I32 => ctx.types.types.u32,175 Integer::I64 => ctx.types.types.u64,176 Integer::I128 => ctx.types.types.u128,177 },178 },179 };180 }181 }182183 ctx.infer_body(body.root_expr());184185 ctx.infer_mut_body(body.root_expr());186187 infer_finalize(ctx)188}189190fn infer_cycle_result<'db>(191 db: &'db dyn HirDatabase,192 _: salsa::Id,193 _: DefWithBodyId,194) -> InferenceResult<'db> {195 InferenceResult {196 has_errors: true,197 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))198 }199}200201/// Infer types for an anonymous const expression.202fn infer_anon_const_query<'db>(203 db: &'db dyn HirDatabase,204 def: AnonConstId<'db>,205) -> InferenceResult<'db> {206 let _p = tracing::info_span!("infer_anon_const_query").entered();207 let loc = def.loc(db);208 let store_owner = loc.owner;209 let store = ExpressionStore::of(db, store_owner);210211 let resolver = store_owner.resolver(db);212213 let mut ctx = InferenceContext::new(214 db,215 InferBodyId::AnonConstId(def),216 store_owner,217 loc.owner.generic_def(db),218 store,219 resolver,220 loc.allow_using_generic_params,221 LoweringMode::Analysis,222 );223224 ctx.infer_expr(225 loc.expr,226 &Expectation::has_type(loc.ty.get().instantiate_identity().skip_norm_wip()),227 ExprIsRead::Yes,228 );229230 infer_finalize(ctx)231}232233fn infer_anon_const_cycle_result<'db>(234 db: &'db dyn HirDatabase,235 _: salsa::Id,236 _: AnonConstId<'db>,237) -> InferenceResult<'db> {238 InferenceResult {239 has_errors: true,240 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))241 }242}243244fn infer_finalize<'db>(mut ctx: InferenceContext<'db>) -> InferenceResult<'db> {245 ctx.handle_opaque_type_uses();246247 ctx.type_inference_fallback();248249 // Comment from rustc:250 // Even though coercion casts provide type hints, we check casts after fallback for251 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.252 let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);253 for mut cast in cast_checks.into_iter() {254 if let Err(diag) = cast.check(&mut ctx) {255 ctx.diagnostics.push(diag);256 }257 }258259 ctx.table.select_obligations_where_possible();260261 // Closure and coroutine analysis may run after fallback262 // because they don't constrain other type variables.263 ctx.closure_analyze();264 assert!(ctx.deferred_call_resolutions.is_empty());265266 ctx.table.select_obligations_where_possible();267268 ctx.handle_opaque_type_uses();269270 ctx.merge_anon_consts();271272 ctx.resolve_all()273}274275#[derive(Clone, Copy, Debug, Eq, PartialEq)]276pub enum ByRef {277 Yes(Mutability),278 No,279}280281/// The mode of a binding (`mut`, `ref mut`, etc).282/// Used for both the explicit binding annotations given in the HIR for a binding283/// and the final binding mode that we infer after type inference/match ergonomics.284/// `.0` is the by-reference mode (`ref`, `ref mut`, or by value),285/// `.1` is the mutability of the binding.286#[derive(Copy, Clone, Debug, Eq, PartialEq)]287pub struct BindingMode(pub ByRef, pub Mutability);288289#[derive(Debug, PartialEq, Eq, Clone, Copy)]290pub enum InferenceTyDiagnosticSource {291 /// Diagnostics that come from types in the body.292 Body,293 /// Diagnostics that come from types in fn parameters/return type, or static & const types.294 Signature,295}296297#[derive(Debug, PartialEq, Eq, Clone, TypeVisitable, TypeFoldable)]298pub enum InferenceDiagnostic {299 NoSuchField {300 #[type_visitable(ignore)]301 field: ExprOrPatIdPacked,302 #[type_visitable(ignore)]303 private: Option<LocalFieldId>,304 #[type_visitable(ignore)]305 variant: VariantId,306 },307 MismatchedArrayPatLen {308 #[type_visitable(ignore)]309 pat: PatId,310 #[type_visitable(ignore)]311 expected: u64,312 #[type_visitable(ignore)]313 found: u64,314 #[type_visitable(ignore)]315 has_rest: bool,316 },317 ArrayPatternWithoutFixedLength {318 #[type_visitable(ignore)]319 pat: PatId,320 },321 ExpectedArrayOrSlicePat {322 #[type_visitable(ignore)]323 pat: PatId,324 found: StoredTy,325 },326 InvalidRangePatType {327 #[type_visitable(ignore)]328 pat: PatId,329 },330 DuplicateField {331 #[type_visitable(ignore)]332 field: ExprOrPatIdPacked,333 #[type_visitable(ignore)]334 variant: VariantId,335 },336 PrivateField {337 #[type_visitable(ignore)]338 expr: ExprId,339 #[type_visitable(ignore)]340 field: FieldId,341 },342 PrivateAssocItem {343 #[type_visitable(ignore)]344 id: ExprOrPatIdPacked,345 #[type_visitable(ignore)]346 item: AssocItemId,347 },348 UnresolvedField {349 #[type_visitable(ignore)]350 expr: ExprId,351 receiver: StoredTy,352 #[type_visitable(ignore)]353 name: Name,354 #[type_visitable(ignore)]355 method_with_same_name_exists: bool,356 },357 UnresolvedMethodCall {358 #[type_visitable(ignore)]359 expr: ExprId,360 receiver: StoredTy,361 #[type_visitable(ignore)]362 name: Name,363 /// Contains the type the field resolves to364 field_with_same_name: Option<StoredTy>,365 #[type_visitable(ignore)]366 assoc_func_with_same_name: Option<FunctionId>,367 },368 UnresolvedAssocItem {369 #[type_visitable(ignore)]370 id: ExprOrPatIdPacked,371 },372 UnresolvedIdent {373 #[type_visitable(ignore)]374 id: ExprOrPatIdPacked,375 },376 // FIXME: This should be emitted in body lowering377 BreakOutsideOfLoop {378 #[type_visitable(ignore)]379 expr: ExprId,380 #[type_visitable(ignore)]381 is_break: bool,382 #[type_visitable(ignore)]383 bad_value_break: bool,384 },385 NonExhaustiveRecordExpr {386 #[type_visitable(ignore)]387 expr: ExprId,388 },389 NonExhaustiveRecordPat {390 #[type_visitable(ignore)]391 pat: PatId,392 #[type_visitable(ignore)]393 variant: VariantId,394 },395 UnionPatMustHaveExactlyOneField {396 #[type_visitable(ignore)]397 pat: PatId,398 },399 UnionPatHasRest {400 #[type_visitable(ignore)]401 pat: PatId,402 },403 FunctionalRecordUpdateOnNonStruct {404 #[type_visitable(ignore)]405 base_expr: ExprId,406 },407 MismatchedArgCount {408 #[type_visitable(ignore)]409 call_expr: ExprId,410 #[type_visitable(ignore)]411 expected: usize,412 #[type_visitable(ignore)]413 found: usize,414 /// True when the call goes through the `Fn`/`FnMut`/`FnOnce` trait415 /// (i.e. arguments were bundled into a tuple). Determines whether the416 /// diagnostic surface uses E0057 (Fn-trait call) or E0061 (regular call).417 #[type_visitable(ignore)]418 is_fn_trait_call: bool,419 },420 MismatchedTupleStructPatArgCount {421 #[type_visitable(ignore)]422 pat: PatId,423 #[type_visitable(ignore)]424 expected: usize,425 #[type_visitable(ignore)]426 found: usize,427 },428 ExpectedFunction {429 #[type_visitable(ignore)]430 call_expr: ExprId,431 found: StoredTy,432 },433 CannotBeDereferenced {434 #[type_visitable(ignore)]435 expr: ExprId,436 found: StoredTy,437 },438 MutRefInImmRefPat {439 #[type_visitable(ignore)]440 pat: PatId,441 },442 CannotImplicitlyDerefTraitObject {443 #[type_visitable(ignore)]444 pat: PatId,445 found: StoredTy,446 },447 CannotIndexInto {448 #[type_visitable(ignore)]449 expr: ExprId,450 found: StoredTy,451 },452 TypedHole {453 #[type_visitable(ignore)]454 expr: ExprId,455 expected: StoredTy,456 },457 CastToUnsized {458 #[type_visitable(ignore)]459 expr: ExprId,460 cast_ty: StoredTy,461 },462 InvalidCast {463 #[type_visitable(ignore)]464 expr: ExprId,465 #[type_visitable(ignore)]466 error: CastError,467 expr_ty: StoredTy,468 cast_ty: StoredTy,469 },470 TyDiagnostic {471 #[type_visitable(ignore)]472 source: InferenceTyDiagnosticSource,473 #[type_visitable(ignore)]474 diag: TyLoweringDiagnostic,475 },476 PathDiagnostic {477 #[type_visitable(ignore)]478 node: ExprOrPatIdPacked,479 #[type_visitable(ignore)]480 diag: PathLoweringDiagnostic,481 },482 MethodCallIncorrectGenericsLen {483 #[type_visitable(ignore)]484 expr: ExprId,485 #[type_visitable(ignore)]486 provided_count: u32,487 #[type_visitable(ignore)]488 expected_count: u32,489 #[type_visitable(ignore)]490 kind: IncorrectGenericsLenKind,491 #[type_visitable(ignore)]492 def: GenericDefId,493 },494 MethodCallIllegalSizedBound {495 #[type_visitable(ignore)]496 call_expr: ExprId,497 },498 MethodCallIncorrectGenericsOrder {499 #[type_visitable(ignore)]500 expr: ExprId,501 #[type_visitable(ignore)]502 param_id: GenericParamId,503 #[type_visitable(ignore)]504 arg_idx: u32,505 /// Whether the `GenericArgs` contains a `Self` arg.506 #[type_visitable(ignore)]507 has_self_arg: bool,508 },509 InvalidLhsOfAssignment {510 #[type_visitable(ignore)]511 lhs: ExprId,512 },513 TypeMustBeKnown {514 #[type_visitable(ignore)]515 at_point: Span,516 top_term: Option<StoredGenericArg>,517 },518 UnionExprMustHaveExactlyOneField {519 #[type_visitable(ignore)]520 expr: ExprId,521 },522 TypeMismatch {523 #[type_visitable(ignore)]524 node: ExprOrPatIdPacked,525 expected: StoredTy,526 found: StoredTy,527 },528 SolverDiagnostic(SolverDiagnostic),529 ExplicitDropMethodUse {530 #[type_visitable(ignore)]531 kind: ExplicitDropMethodUseKind,532 },533 MutableRefBinding {534 #[type_visitable(ignore)]535 pat: PatId,536 },537 YieldOutsideCoroutine {538 #[type_visitable(ignore)]539 expr: ExprId,540 },541 ReturnOutsideFunction {542 #[type_visitable(ignore)]543 expr: ExprId,544 #[type_visitable(ignore)]545 kind: ReturnKind,546 },547 RecordMissingFields {548 #[type_visitable(ignore)]549 record: ExprOrPatId,550 #[type_visitable(ignore)]551 variant: VariantId,552 #[type_visitable(ignore)]553 missed_fields: Vec<LocalFieldId>,554 },555}556557#[derive(Debug, PartialEq, Eq, Clone, Copy)]558pub enum ReturnKind {559 ReturnExpr,560 BecomeExpr,561}562563#[derive(Debug, PartialEq, Eq, Clone)]564pub enum ExplicitDropMethodUseKind {565 MethodCall(ExprId),566 Path(ExprOrPatIdPacked),567}568569/// Represents coercing a value to a different type of value.570///571/// We transform values by following a number of `Adjust` steps in order.572/// See the documentation on variants of `Adjust` for more details.573///574/// Here are some common scenarios:575///576/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.577/// Here the pointer will be dereferenced N times (where a dereference can578/// happen to raw or borrowed pointers or any smart pointer which implements579/// Deref, including Box<_>). The types of dereferences is given by580/// `autoderefs`. It can then be auto-referenced zero or one times, indicated581/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is582/// `false`.583///584/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start585/// with a thin pointer, deref a number of times, unsize the underlying data,586/// then autoref. The 'unsize' phase may change a fixed length array to a587/// dynamically sized one, a concrete object to a trait object, or statically588/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is589/// represented by:590///591/// ```ignore592/// Deref(None) -> [i32; 4],593/// Borrow(AutoBorrow::Ref) -> &[i32; 4],594/// Unsize -> &[i32],595/// ```596///597/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.598/// E.g., `struct Foo<T> { it: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>599/// The autoderef and -ref are the same as in the above example, but the type600/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about601/// the underlying conversions from `[i32; 4]` to `[i32]`.602///603/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In604/// that case, we have the pointer we need coming in, so there are no605/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.606/// At some point, of course, `Box` should move out of the compiler, in which607/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->608/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.609#[derive(Clone, Debug, PartialEq, Eq, Hash)]610pub struct Adjustment {611 pub kind: Adjust,612 pub target: StoredTy,613}614615impl Adjustment {616 pub fn borrow<'db>(617 interner: DbInterner<'db>,618 m: Mutability,619 ty: Ty<'db>,620 lt: Region<'db>,621 ) -> Self {622 let ty = Ty::new_ref(interner, lt, ty, m);623 Adjustment {624 kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(m, AllowTwoPhase::No))),625 target: ty.store(),626 }627 }628}629630/// At least for initial deployment, we want to limit two-phase borrows to631/// only a few specific cases. Right now, those are mostly "things that desugar"632/// into method calls:633/// - using `x.some_method()` syntax, where some_method takes `&mut self`,634/// - using `Foo::some_method(&mut x, ...)` syntax,635/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).636///637/// Anything else should be rejected until generalized two-phase borrow support638/// is implemented. Right now, dataflow can't handle the general case where there639/// is more than one use of a mutable borrow, and we don't want to accept too much640/// new code via two-phase borrows, so we try to limit where we create two-phase641/// capable mutable borrows.642/// See #49434 for tracking.643#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]644pub enum AllowTwoPhase {645 // FIXME: We should use this when appropriate.646 Yes,647 No,648}649650#[derive(Clone, Debug, PartialEq, Eq, Hash)]651pub enum Adjust {652 /// Go from ! to any type.653 NeverToAny,654 /// Dereference once, producing a place.655 Deref(Option<OverloadedDeref>),656 /// Take the address and produce either a `&` or `*` pointer.657 Borrow(AutoBorrow),658 Pointer(PointerCast),659}660661/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`662/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.663/// The target type is `U` in both cases, with the region and mutability664/// being those shared by both the receiver and the returned reference.665#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]666pub struct OverloadedDeref(pub Mutability);667668#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]669pub enum AutoBorrowMutability {670 Mut { allow_two_phase_borrow: AllowTwoPhase },671 Not,672}673674impl AutoBorrowMutability {675 /// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows.676 ///677 /// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored678 pub fn new(mutbl: Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self {679 match mutbl {680 Mutability::Not => Self::Not,681 Mutability::Mut => Self::Mut { allow_two_phase_borrow },682 }683 }684}685686impl From<AutoBorrowMutability> for Mutability {687 fn from(m: AutoBorrowMutability) -> Self {688 match m {689 AutoBorrowMutability::Mut { .. } => Mutability::Mut,690 AutoBorrowMutability::Not => Mutability::Not,691 }692 }693}694695#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]696pub enum AutoBorrow {697 /// Converts from T to &T.698 Ref(AutoBorrowMutability),699 /// Converts from T to *T.700 RawPtr(Mutability),701}702703#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]704pub enum PointerCast {705 /// Go from a fn-item type to a fn-pointer type.706 ReifyFnPointer,707708 /// Go from a safe fn pointer to an unsafe fn pointer.709 UnsafeFnPointer,710711 /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.712 /// It cannot convert a closure that requires unsafe.713 ClosureFnPointer(Safety),714715 /// Go from a mut raw pointer to a const raw pointer.716 MutToConstPointer,717718 #[allow(dead_code)]719 /// Go from `*const [T; N]` to `*const T`720 ArrayToPointer,721722 /// Unsize a pointer/reference value, e.g., `&[T; n]` to723 /// `&[T]`. Note that the source could be a thin or fat pointer.724 /// This will do things like convert thin pointers to fat725 /// pointers, or convert structs containing thin pointers to726 /// structs containing fat pointers, or convert between fat727 /// pointers. We don't store the details of how the transform is728 /// done (in fact, we don't know that, because it might depend on729 /// the precise type parameters). We just store the target730 /// type. Codegen backends and miri figure out what has to be done731 /// based on the precise source/target type at hand.732 Unsize,733}734735/// Represents an implicit coercion applied to the scrutinee of a match before testing a pattern736/// against it. Currently, this is used only for implicit dereferences.737#[derive(Debug, Clone, PartialEq, Eq)]738pub struct PatAdjustment {739 pub kind: PatAdjust,740 /// The type of the scrutinee before the adjustment is applied, or the "adjusted type" of the741 /// pattern.742 pub source: StoredTy,743}744745/// Represents implicit coercions of patterns' types, rather than values' types.746#[derive(Clone, Copy, PartialEq, Eq, Debug)]747pub enum PatAdjust {748 /// An implicit dereference before matching, such as when matching the pattern `0` against a749 /// scrutinee of type `&u8` or `&mut u8`.750 BuiltinDeref,751 /// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the752 /// pattern `[..]` against a scrutinee of type `Vec<T>`.753 OverloadedDeref,754}755756/// The result of type inference: A mapping from expressions and patterns to types.757///758/// When you add a field that stores types (including `Substitution` and the like), don't forget759/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must760/// not appear in the final inference result.761#[derive(Clone, PartialEq, Eq, Debug, SalsaValue)]762pub struct InferenceResult<'db> {763 /// For each method call expr, records the function it resolves to.764 method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,765 /// For each field access expr, records the field it resolves to.766 field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,767 /// For each struct literal or pattern, records the variant it resolves to.768 variant_resolutions: FxHashMap<ExprOrPatIdPacked, VariantId>,769 /// For each associated item record what it resolves to770 assoc_resolutions: FxHashMap<ExprOrPatIdPacked, (CandidateId, StoredGenericArgs)>,771 /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in772 /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of773 /// that which allows us to resolve a [`TupleFieldId`]s type.774 tuple_field_access_types: ThinVec<StoredTys>,775776 pub(crate) type_of_expr: ArenaMap<ExprId, StoredTy>,777 /// For each pattern record the type it resolves to.778 ///779 /// **Note**: When a pattern type is resolved it may still contain780 /// unresolved or missing subpatterns or subpatterns of mismatched types.781 pub(crate) type_of_pat: ArenaMap<PatId, StoredTy>,782 pub(crate) type_of_binding: ArenaMap<BindingId, StoredTy>,783 pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, StoredTy>,784 pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId<'db>, StoredTy>,785786 /// Whether there are any type-mismatching errors in the result.787 // FIXME: This isn't as useful as initially thought due to us falling back placeholders to788 // `TyKind::Error`.789 // Which will then mark this field.790 pub(crate) has_errors: bool,791 /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.792 diagnostics: ThinVec<InferenceDiagnostic>,793 // FIXME: Remove this, change it to be in `InferenceContext`:794 nodes_with_type_mismatches: Option<Box<FxHashSet<ExprOrPatIdPacked>>>,795796 /// Interned `Error` type to return references to.797 // FIXME: Remove this.798 error_ty: StoredTy,799800 pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,801 /// Stores the types which were implicitly dereferenced in pattern binding modes.802 pub(crate) pat_adjustments: FxHashMap<PatId, Vec<PatAdjustment>>,803 /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.804 ///805 /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an806 /// or pattern can have multiple binding modes. For example:807 /// ```808 /// fn foo(mut slice: &[u32]) -> usize {809 /// slice = match slice {810 /// [0, rest @ ..] | rest => rest,811 /// };812 /// 0813 /// }814 /// ```815 /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.816 pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,817818 /// Set of reference patterns that match against a match-ergonomics inserted reference819 /// (as opposed to against a reference in the scrutinee type).820 skipped_ref_pats: FxHashSet<PatId>,821822 pub(crate) coercion_casts: FxHashSet<ExprId>,823824 pub closures_data: FxHashMap<ExprId, ClosureData>,825826 defined_anon_consts: ThinVec<AnonConstId<'db>>,827}828829#[derive(Clone, PartialEq, Eq, Debug)]830pub struct ClosureData {831 /// Tracks the minimum captures required for a closure;832 /// see `MinCaptureInformationMap` for more details.833 pub min_captures: RootVariableMinCaptureList,834835 /// Tracks the fake reads required for a closure and the reason for the fake read.836 /// When performing pattern matching for closures, there are times we don't end up837 /// reading places that are mentioned in a closure (because of _ patterns). However,838 /// to ensure the places are initialized, we introduce fake reads.839 /// Consider these two examples:840 /// ```ignore (discriminant matching with only wildcard arm)841 /// let x: u8;842 /// let c = || match x { _ => () };843 /// ```844 /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't845 /// want to capture it. However, we do still want an error here, because `x` should have846 /// to be initialized at the point where c is created. Therefore, we add a "fake read"847 /// instead.848 /// ```ignore (destructured assignments)849 /// let c = || {850 /// let (t1, t2) = t;851 /// }852 /// ```853 /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but854 /// we never capture `t`. This becomes an issue when we build MIR as we require855 /// information on `t` in order to create place `t.0` and `t.1`. We can solve this856 /// issue by fake reading `t`.857 pub fake_reads: Box<[(Place, FakeReadCause, SmallVec<[CaptureSourceStack; 2]>)]>,858859 /// For each fn, records the "liberated" types of its arguments860 /// and return type. Liberated means that all bound regions861 /// (including late-bound regions) are replaced with free862 /// equivalents. This table is not used in codegen (since regions863 /// are erased there) and hence is not serialized to metadata.864 ///865 /// This table also contains the "revealed" values for any `impl Trait`866 /// that appear in the signature and whose values are being inferred867 /// by this function.868 ///869 /// # Example870 ///871 /// ```rust872 /// # use std::fmt::Debug;873 /// fn foo(x: &u32) -> impl Debug { *x }874 /// ```875 ///876 /// The function signature here would be:877 ///878 /// ```ignore (illustrative)879 /// for<'a> fn(&'a u32) -> Foo880 /// ```881 ///882 /// where `Foo` is an opaque type created for this function.883 ///884 ///885 /// The *liberated* form of this would be886 ///887 /// ```ignore (illustrative)888 /// fn(&'a u32) -> u32889 /// ```890 ///891 /// Note that `'a` is not bound (it would be an `ReLateParam`) and892 /// that the `Foo` opaque type is replaced by its hidden type.893 pub liberated_sig: StoredFnSig,894}895896/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.897/// Used to track the minimum set of `Place`s that need to be captured to support all898/// Places captured by the closure starting at a given root variable.899///900/// This provides a convenient and quick way of checking if a variable being used within901/// a closure is a capture of a local variable.902pub(crate) type RootVariableMinCaptureList = FxIndexMap<BindingId, MinCaptureList>;903904/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.905pub(crate) type MinCaptureList = Vec<CapturedPlace>;906907/// A composite describing a `Place` that is captured by a closure.908#[derive(Eq, PartialEq, Clone, Debug, Hash)]909pub struct CapturedPlace {910 /// The `Place` that is captured.911 pub place: Place,912913 /// `CaptureKind` and expression(s) that resulted in such capture of `place`.914 pub info: CaptureInfo,915916 /// Represents if `place` can be mutated or not.917 pub mutability: Mutability,918}919920impl CapturedPlace {921 pub fn is_by_ref(&self) -> bool {922 match self.info.capture_kind {923 UpvarCapture::ByValue | UpvarCapture::ByUse => false,924 UpvarCapture::ByRef(..) => true,925 }926 }927928 pub fn captured_local(&self) -> BindingId {929 match self.place.base {930 PlaceBase::Upvar { var_id: local, .. } | PlaceBase::Local(local) => local,931 PlaceBase::Rvalue | PlaceBase::StaticItem => {932 unreachable!("only locals can be captured")933 }934 }935 }936937 /// The type of the capture stored in the closure, which is different from the type of the captured place938 /// if we capture by reference.939 pub fn captured_ty<'db>(&self, db: &'db dyn HirDatabase) -> Ty<'db> {940 let place_ty = self.place.ty();941 let make_ref = |mutbl| {942 let interner = DbInterner::new_no_crate(db);943 let region = Region::new_erased(interner);944 Ty::new_ref(interner, region, place_ty, mutbl)945 };946 match self.info.capture_kind {947 UpvarCapture::ByUse | UpvarCapture::ByValue => place_ty,948 UpvarCapture::ByRef(kind) => make_ref(kind.to_mutbl_lossy()),949 }950 }951}952953#[derive(Clone)]954pub struct CaptureSourceStack(CaptureSourceStackRepr);955956#[derive(Clone)]957enum CaptureSourceStackRepr {958 One(ExprOrPatIdPacked),959 Two([ExprOrPatIdPacked; 2]),960 Many(ThinVec<ExprOrPatIdPacked>),961}962963impl PartialEq for CaptureSourceStack {964 fn eq(&self, other: &Self) -> bool {965 **self == **other966 }967}968969impl Eq for CaptureSourceStack {}970971impl std::hash::Hash for CaptureSourceStack {972 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {973 (**self).hash(state);974 }975}976977#[cfg(target_pointer_width = "64")]978const _: () = assert!(size_of::<CaptureSourceStack>() == 16);979980impl Deref for CaptureSourceStack {981 type Target = [ExprOrPatIdPacked];982983 #[inline]984 fn deref(&self) -> &Self::Target {985 match &self.0 {986 CaptureSourceStackRepr::One(it) => std::slice::from_ref(it),987 CaptureSourceStackRepr::Two(it) => it,988 CaptureSourceStackRepr::Many(it) => it,989 }990 }991}992993impl fmt::Debug for CaptureSourceStack {994 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {995 f.debug_tuple("CaptureSourceStack").field(&&**self).finish()996 }997}998999impl CaptureSourceStack {1000 #[inline]1001 pub fn len(&self) -> usize {1002 match &self.0 {1003 CaptureSourceStackRepr::One(_) => 1,1004 CaptureSourceStackRepr::Two(_) => 2,1005 CaptureSourceStackRepr::Many(it) => it.len(),1006 }1007 }10081009 #[inline]1010 pub(crate) fn from_single(id: ExprOrPatIdPacked) -> Self {1011 Self(CaptureSourceStackRepr::One(id))1012 }10131014 #[inline]1015 pub fn final_source(&self) -> ExprOrPatIdPacked {1016 *self.last().expect("should always have a final source")1017 }10181019 pub fn push(&mut self, new_id: ExprOrPatIdPacked) {1020 match &mut self.0 {1021 CaptureSourceStackRepr::One(old_id) => {1022 self.0 = CaptureSourceStackRepr::Two([*old_id, new_id])1023 }1024 CaptureSourceStackRepr::Two([old_id1, old_id2]) => {1025 self.0 = CaptureSourceStackRepr::Many(ThinVec::from([*old_id1, *old_id2, new_id]));1026 }1027 CaptureSourceStackRepr::Many(old_ids) => old_ids.push(new_id),1028 }1029 }10301031 pub fn truncate(&mut self, new_len: usize) {1032 debug_assert!(new_len > 0);1033 match &mut self.0 {1034 CaptureSourceStackRepr::One(_) => {}1035 CaptureSourceStackRepr::Two([first, _]) => {1036 if new_len == 1 {1037 self.0 = CaptureSourceStackRepr::One(*first)1038 }1039 }1040 CaptureSourceStackRepr::Many(ids) => ids.truncate(new_len),1041 }1042 }10431044 pub fn shrink_to_fit(&mut self) {1045 match &mut self.0 {1046 CaptureSourceStackRepr::One(_) | CaptureSourceStackRepr::Two(_) => {}1047 CaptureSourceStackRepr::Many(ids) => match **ids {1048 [one] => self.0 = CaptureSourceStackRepr::One(one),1049 [first, second] => self.0 = CaptureSourceStackRepr::Two([first, second]),1050 _ => ids.shrink_to_fit(),1051 },1052 }1053 }1054}10551056/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)1057/// for a particular capture as well as identifying the part of the source code1058/// that triggered this capture to occur.1059#[derive(Eq, PartialEq, Clone, Debug, Hash)]1060pub struct CaptureInfo {1061 pub sources: SmallVec<[CaptureSourceStack; 2]>,10621063 /// Capture mode that was selected1064 pub capture_kind: UpvarCapture,1065}10661067/// Information describing the capture of an upvar. This is computed1068/// during `typeck`, specifically by `regionck`.1069#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash)]1070pub enum UpvarCapture {1071 /// Upvar is captured by value. This is always true when the1072 /// closure is labeled `move`, but can also be true in other cases1073 /// depending on inference.1074 ByValue,10751076 /// Upvar is captured by use. This is true when the closure is labeled `use`.1077 ByUse,10781079 /// Upvar is captured by reference.1080 ByRef(BorrowKind),1081}10821083#[salsa::tracked]1084impl<'db> InferenceResult<'db> {1085 #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]1086 fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_> {1087 infer_query(db, def)1088 }10891090 /// Infer types for all const expressions in an item's signature.1091 ///1092 /// Returns an `InferenceResult` containing type information for array lengths,1093 /// const generic arguments, and other const expressions appearing in type1094 /// positions within the item's signature.1095 #[salsa::tracked(returns(ref), cycle_result = infer_anon_const_cycle_result)]1096 fn for_anon_const(db: &'db dyn HirDatabase, def: AnonConstId<'db>) -> InferenceResult<'db> {1097 infer_anon_const_query(db, def)1098 }1099}11001101impl<'db> InferenceResult<'db> {1102 #[inline]1103 pub fn of(1104 db: &'db dyn HirDatabase,1105 def: impl Into<InferBodyId<'db>>,1106 ) -> &'db InferenceResult<'db> {1107 match def.into() {1108 InferBodyId::DefWithBodyId(it) => InferenceResult::for_body(db, it),1109 InferBodyId::AnonConstId(it) => InferenceResult::for_anon_const(db, it),1110 }1111 }1112}11131114impl<'db> InferenceResult<'db> {1115 fn new(error_ty: Ty<'_>) -> Self {1116 Self {1117 method_resolutions: Default::default(),1118 field_resolutions: Default::default(),1119 variant_resolutions: Default::default(),1120 assoc_resolutions: Default::default(),1121 tuple_field_access_types: Default::default(),1122 diagnostics: Default::default(),1123 nodes_with_type_mismatches: Default::default(),1124 type_of_expr: Default::default(),1125 type_of_pat: Default::default(),1126 type_of_binding: Default::default(),1127 type_of_type_placeholder: Default::default(),1128 type_of_opaque: Default::default(),1129 skipped_ref_pats: Default::default(),1130 has_errors: Default::default(),1131 error_ty: error_ty.store(),1132 pat_adjustments: Default::default(),1133 binding_modes: Default::default(),1134 expr_adjustments: Default::default(),1135 coercion_casts: Default::default(),1136 closures_data: Default::default(),1137 defined_anon_consts: Default::default(),1138 }1139 }11401141 pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {1142 self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))1143 }1144 pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {1145 self.field_resolutions.get(&expr).copied()1146 }1147 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {1148 self.variant_resolutions.get(&id.into()).copied()1149 }1150 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {1151 self.variant_resolutions.get(&id.into()).copied()1152 }1153 pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {1154 match id {1155 ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),1156 ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),1157 }1158 }1159 pub fn assoc_resolutions_for_expr<'a>(1160 &self,1161 id: ExprId,1162 ) -> Option<(CandidateId, GenericArgs<'a>)> {1163 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))1164 }1165 pub fn assoc_resolutions_for_pat<'a>(1166 &self,1167 id: PatId,1168 ) -> Option<(CandidateId, GenericArgs<'a>)> {1169 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))1170 }1171 pub fn assoc_resolutions_for_expr_or_pat<'a>(1172 &self,1173 id: ExprOrPatId,1174 ) -> Option<(CandidateId, GenericArgs<'a>)> {1175 match id {1176 ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),1177 ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),1178 }1179 }1180 pub fn expr_or_pat_has_type_mismatch(&self, node: ExprOrPatIdPacked) -> bool {1181 self.nodes_with_type_mismatches.as_ref().is_some_and(|it| it.contains(&node))1182 }1183 pub fn expr_has_type_mismatch(&self, expr: ExprId) -> bool {1184 self.expr_or_pat_has_type_mismatch(expr.into())1185 }1186 pub fn pat_has_type_mismatch(&self, pat: PatId) -> bool {1187 self.expr_or_pat_has_type_mismatch(pat.into())1188 }1189 pub fn exprs_have_type_mismatches(&self) -> bool {1190 self.nodes_with_type_mismatches1191 .as_ref()1192 .is_some_and(|it| it.iter().any(|node| node.is_expr()))1193 }1194 pub fn has_type_mismatches(&self) -> bool {1195 self.nodes_with_type_mismatches.is_some()1196 }1197 pub fn placeholder_types<'a>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'a>)> {1198 self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref()))1199 }1200 pub fn type_of_type_placeholder<'a>(&self, type_ref: TypeRefId) -> Option<Ty<'a>> {1201 self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())1202 }1203 pub fn type_of_expr_or_pat<'a>(&self, id: ExprOrPatId) -> Option<Ty<'a>> {1204 match id {1205 ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),1206 ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),1207 }1208 }1209 pub fn type_of_expr_with_adjust<'a>(&self, id: ExprId) -> Option<Ty<'a>> {1210 match self.expr_adjustments.get(&id).and_then(|adjustments| {1211 adjustments.iter().rfind(|adj| {1212 // https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L1401213 !matches!(1214 adj,1215 Adjustment {1216 kind: Adjust::NeverToAny,1217 target,1218 } if target.as_ref().is_never()1219 )1220 })1221 }) {1222 Some(adjustment) => Some(adjustment.target.as_ref()),1223 None => self.type_of_expr.get(id).map(|it| it.as_ref()),1224 }1225 }1226 pub fn type_of_pat_with_adjust<'a>(&self, id: PatId) -> Ty<'a> {1227 match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {1228 Some(adjusted) => adjusted.source.as_ref(),1229 None => self.pat_ty(id),1230 }1231 }1232 pub fn is_erroneous(&self) -> bool {1233 self.has_errors && self.type_of_expr.iter().count() == 01234 }12351236 pub fn diagnostics(&self) -> &[InferenceDiagnostic] {1237 &self.diagnostics1238 }12391240 pub fn tuple_field_access_type<'a>(&self, id: TupleId) -> Tys<'a> {1241 self.tuple_field_access_types[id.0 as usize].as_ref()1242 }12431244 pub fn pat_adjustment(&self, id: PatId) -> Option<&[PatAdjustment]> {1245 self.pat_adjustments.get(&id).map(|it| &**it)1246 }12471248 pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {1249 self.expr_adjustments.get(&id).map(|it| &**it)1250 }12511252 pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {1253 self.binding_modes.get(id).copied()1254 }12551256 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1257 pub fn expression_types<'a>(&self) -> impl Iterator<Item = (ExprId, Ty<'a>)> {1258 self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))1259 }12601261 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1262 pub fn pattern_types<'a>(&self) -> impl Iterator<Item = (PatId, Ty<'a>)> {1263 self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))1264 }12651266 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1267 pub fn binding_types<'a>(&self) -> impl Iterator<Item = (BindingId, Ty<'a>)> {1268 self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))1269 }12701271 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1272 pub fn return_position_impl_trait_types<'a>(1273 &'a self,1274 db: &'a dyn HirDatabase,1275 ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'a>)> {1276 self.type_of_opaque.iter().filter_map(move |(&id, ty)| {1277 let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {1278 return None;1279 };1280 Some((rpit_idx, ty.as_ref()))1281 })1282 }12831284 pub fn expr_ty<'a>(&self, id: ExprId) -> Ty<'a> {1285 self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1286 }12871288 pub fn pat_ty<'a>(&self, id: PatId) -> Ty<'a> {1289 self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1290 }12911292 pub fn expr_or_pat_ty<'a>(&self, id: ExprOrPatId) -> Ty<'a> {1293 self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())1294 }12951296 pub fn binding_ty<'a>(&self, id: BindingId) -> Ty<'a> {1297 self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1298 }12991300 /// This does not deduplicate, which means you'll get the types once per capture.1301 pub fn closure_captures_tys<'a>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'a>> {1302 self.closures_data[&closure]1303 .min_captures1304 .values()1305 .flat_map(|captures| captures.iter().map(|capture| capture.place.ty()))1306 }13071308 /// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].1309 pub fn closure_captures_captured_tys<'a>(1310 &self,1311 db: &'a dyn HirDatabase,1312 closure: ExprId,1313 ) -> impl Iterator<Item = Ty<'a>> {1314 self.closures_data[&closure]1315 .min_captures1316 .values()1317 .flat_map(|captures| captures.iter().map(|capture| capture.captured_ty(db)))1318 }13191320 pub fn is_skipped_ref_pat(&self, pat: PatId) -> bool {1321 self.skipped_ref_pats.contains(&pat)1322 }1323}13241325#[derive(Debug, Clone, Copy)]1326enum DerefPatBorrowMode {1327 Borrow(Mutability),1328 Box,1329}13301331/// The inference context contains all information needed during type inference.1332#[derive(Debug)]1333pub(crate) struct InferenceContext<'db> {1334 pub(crate) db: &'db dyn HirDatabase,1335 pub(crate) owner: InferBodyId<'db>,1336 pub(crate) store_owner: ExpressionStoreOwnerId,1337 pub(crate) generic_def: GenericDefId,1338 pub(crate) store: &'db ExpressionStore,1339 pub(crate) lowering_mode: LoweringMode,1340 /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext1341 /// and resolve the path via its methods. This will ensure proper error reporting.1342 pub(crate) resolver: Resolver<'db>,1343 target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,1344 data_layout: OnceCell<&'db TargetDataLayout>,1345 pub(crate) edition: Edition,1346 allow_using_generic_params: bool,1347 generics: OnceCell<Generics<'db>>,1348 identity_args: OnceCell<GenericArgs<'db>>,1349 pub(crate) table: unify::InferenceTable<'db>,1350 pub(crate) lang_items: &'db LangItems,1351 pub(crate) features: &'db UnstableFeatures,1352 /// The traits in scope, disregarding block modules. This is used for caching purposes.1353 traits_in_scope: FxHashSet<TraitId>,1354 pub(crate) result: InferenceResult<'db>,1355 tuple_field_accesses_rev:1356 IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,1357 /// The return type of the function being inferred, the closure or async block if we're1358 /// currently within one.1359 ///1360 /// We might consider using a nested inference context for checking1361 /// closures so we can swap all shared things out at once.1362 return_ty: Ty<'db>,1363 /// If `Some`, this stores coercion information for returned1364 /// expressions. If `None`, this is in a context where return is1365 /// inappropriate, such as a const expression.1366 return_coercion: Option<DynamicCoerceMany<'db>>,1367 /// The resume type and the yield type, respectively, of the coroutine being inferred.1368 resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,1369 diverges: Diverges,1370 breakables: Vec<BreakableContext<'db>>,1371 types: &'db crate::next_solver::DefaultAny<'db>,13721373 deferred_cast_checks: Vec<CastCheck<'db>>,13741375 /// The key is an expression defining a closure or a coroutine closure.1376 deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>,13771378 diagnostics: Diagnostics,1379 vars_emitted_type_must_be_known_for: FxHashSet<Term<'db>>,13801381 defined_anon_consts: RefCell<ThinVec<AnonConstId<'db>>>,1382}13831384#[derive(Clone, Debug)]1385struct BreakableContext<'db> {1386 /// Whether this context contains at least one break expression.1387 may_break: bool,1388 /// The coercion target of the context.1389 coerce: Option<DynamicCoerceMany<'db>>,1390 /// The optional label of the context.1391 label: Option<LabelId>,1392 kind: BreakableKind,1393}13941395#[derive(Clone, Debug)]1396enum BreakableKind {1397 Block,1398 Loop,1399 /// A border is something like an async block, closure etc. Anything that prevents1400 /// breaking/continuing through1401 Border,1402}14031404fn find_breakable(ctxs: &[BreakableContext<'_>], label: Option<LabelId>) -> Option<usize> {1405 let mut ctxs = ctxs1406 .iter()1407 .enumerate()1408 .rev()1409 .take_while(|(_, it)| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));1410 let result = match label {1411 Some(_) => ctxs.find(|(_, ctx)| ctx.label == label),1412 None => ctxs.find(|(_, ctx)| matches!(ctx.kind, BreakableKind::Loop)),1413 };1414 result.map(|(idx, _)| idx)1415}14161417fn find_continuable(ctxs: &[BreakableContext<'_>], label: Option<LabelId>) -> Option<usize> {1418 find_breakable(ctxs, label)1419 .filter(|&idx| label.is_none() || matches!(ctxs[idx].kind, BreakableKind::Loop))1420}14211422impl<'db> InferenceContext<'db> {1423 fn new(1424 db: &'db dyn HirDatabase,1425 owner: InferBodyId<'db>,1426 store_owner: ExpressionStoreOwnerId,1427 generic_def: GenericDefId,1428 store: &'db ExpressionStore,1429 resolver: Resolver<'db>,1430 allow_using_generic_params: bool,1431 lowering_mode: LoweringMode,1432 ) -> Self {1433 let trait_env = db.trait_environment(generic_def);1434 let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), owner);1435 let types = crate::next_solver::default_types(db);1436 InferenceContext {1437 result: InferenceResult::new(types.types.error),1438 return_ty: types.types.error, // set in collect_* calls1439 types,1440 target_features: OnceCell::new(),1441 data_layout: OnceCell::new(),1442 lang_items: table.interner().lang_items(),1443 features: resolver.top_level_def_map().features(),1444 edition: resolver.krate().data(db).edition,1445 table,1446 tuple_field_accesses_rev: Default::default(),1447 resume_yield_tys: None,1448 return_coercion: None,1449 db,1450 owner,1451 store_owner,1452 generic_def,1453 allow_using_generic_params,1454 generics: OnceCell::new(),1455 identity_args: OnceCell::new(),1456 store,1457 traits_in_scope: resolver.traits_in_scope(db),1458 resolver,1459 diverges: Diverges::Maybe,1460 breakables: Vec::new(),1461 deferred_cast_checks: Vec::new(),1462 diagnostics: Diagnostics::default(),1463 vars_emitted_type_must_be_known_for: FxHashSet::default(),1464 deferred_call_resolutions: FxHashMap::default(),1465 defined_anon_consts: RefCell::new(ThinVec::new()),1466 lowering_mode,1467 }1468 }14691470 fn merge(&mut self, other: &InferenceResult<'db>) {1471 let InferenceResult {1472 method_resolutions,1473 field_resolutions,1474 variant_resolutions,1475 assoc_resolutions,1476 tuple_field_access_types: _,1477 type_of_expr,1478 type_of_pat,1479 type_of_binding,1480 type_of_type_placeholder,1481 type_of_opaque,1482 has_errors: _,1483 diagnostics: _,1484 error_ty: _,1485 expr_adjustments,1486 pat_adjustments,1487 binding_modes,1488 skipped_ref_pats,1489 coercion_casts,1490 closures_data,1491 nodes_with_type_mismatches,1492 defined_anon_consts: _,1493 } = &mut self.result;1494 merge_hash_maps(method_resolutions, &other.method_resolutions);1495 merge_hash_maps(variant_resolutions, &other.variant_resolutions);1496 merge_hash_maps(assoc_resolutions, &other.assoc_resolutions);1497 field_resolutions.extend(other.field_resolutions.iter().map(1498 |(&field_expr, &field_resolution)| {1499 let mut field_resolution = field_resolution;1500 if let Either::Right(tuple_field) = &mut field_resolution {1501 let tys = other.tuple_field_access_type(tuple_field.tuple);1502 tuple_field.tuple =1503 TupleId(self.tuple_field_accesses_rev.insert_full(tys).0 as u32);1504 };1505 (field_expr, field_resolution)1506 },1507 ));1508 merge_arena_maps(type_of_expr, &other.type_of_expr);1509 merge_arena_maps(type_of_pat, &other.type_of_pat);1510 merge_arena_maps(type_of_binding, &other.type_of_binding);1511 merge_hash_maps(type_of_type_placeholder, &other.type_of_type_placeholder);1512 merge_hash_maps(type_of_opaque, &other.type_of_opaque);1513 merge_hash_maps(expr_adjustments, &other.expr_adjustments);1514 merge_hash_maps(pat_adjustments, &other.pat_adjustments);1515 merge_arena_maps(binding_modes, &other.binding_modes);1516 merge_hash_set(skipped_ref_pats, &other.skipped_ref_pats);1517 merge_hash_set(coercion_casts, &other.coercion_casts);1518 merge_hash_maps(closures_data, &other.closures_data);1519 if let Some(other_nodes_with_type_mismatches) = &other.nodes_with_type_mismatches {1520 merge_hash_set(1521 nodes_with_type_mismatches.get_or_insert_default(),1522 other_nodes_with_type_mismatches,1523 );1524 }1525 self.defined_anon_consts.borrow_mut().extend(other.defined_anon_consts.iter().copied());15261527 fn merge_hash_set<T: Hash + Eq + Clone>(dest: &mut FxHashSet<T>, source: &FxHashSet<T>) {1528 dest.extend(source.iter().cloned());1529 }15301531 #[cfg_attr(debug_assertions, track_caller)]1532 fn merge_hash_maps<K: Hash + Eq + Clone, V: Clone + PartialEq>(1533 dest: &mut FxHashMap<K, V>,1534 source: &FxHashMap<K, V>,1535 ) {1536 if cfg!(debug_assertions) {1537 for (key, src) in source {1538 assert!(dest.get(key).is_none_or(|dst| dst == src));1539 }1540 }15411542 dest.extend(source.iter().map(|(k, v)| (k.clone(), v.clone())));1543 }15441545 #[cfg_attr(debug_assertions, track_caller)]1546 fn merge_arena_maps<K, V: Clone + PartialEq>(1547 dest: &mut ArenaMap<la_arena::Idx<K>, V>,1548 source: &ArenaMap<la_arena::Idx<K>, V>,1549 ) {1550 if cfg!(debug_assertions) {1551 for (key, src) in source.iter() {1552 assert!(dest.get(key).is_none_or(|dst| dst == src));1553 }1554 }15551556 dest.extend(source.iter().map(|(k, v)| (k, v.clone())));1557 }1558 }15591560 #[inline]1561 fn krate(&self) -> Crate {1562 self.resolver.krate()1563 }15641565 fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {1566 let (target_features, target_feature_is_safe) = self.target_features.get_or_init(|| {1567 let target_features = match self.store_owner {1568 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => {1569 TargetFeatures::from_fn(self.db, id)1570 }1571 _ => TargetFeatures::default(),1572 };1573 let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {1574 Ok(target) => crate::utils::target_feature_is_safe_in_target(target),1575 Err(_) => TargetFeatureIsSafeInTarget::No,1576 };1577 (target_features, target_feature_is_safe)1578 });1579 (target_features, *target_feature_is_safe)1580 }15811582 fn data_layout(&self) -> &'db TargetDataLayout {1583 self.data_layout.get_or_init(|| self.db.target_data_layout_or_default(self.krate()))1584 }15851586 /// How should a deref pattern find the place for its inner pattern to match on?1587 ///1588 /// In most cases, if the pattern recursively contains a `ref mut` binding, we find the inner1589 /// pattern's scrutinee by calling `DerefMut::deref_mut`, and otherwise we call `Deref::deref`.1590 /// However, for boxes we can use a built-in deref instead, which doesn't borrow the scrutinee;1591 /// in this case, we return `DerefPatBorrowMode::Box`.1592 fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: PatId) -> DerefPatBorrowMode {1593 if pointer_ty.is_box() {1594 DerefPatBorrowMode::Box1595 } else {1596 let mutability =1597 if self.pat_has_ref_mut_binding(inner) { Mutability::Mut } else { Mutability::Not };1598 DerefPatBorrowMode::Borrow(mutability)1599 }1600 }16011602 #[inline]1603 fn set_tainted_by_errors(&mut self) {1604 self.result.has_errors = true;1605 }16061607 /// Copy the inference of defined anon consts to ourselves, so that we don't need to lookup the defining1608 /// anon const when looking the type of something.1609 fn merge_anon_consts(&mut self) {1610 let mut defined_anon_consts = std::mem::take(&mut *self.defined_anon_consts.borrow_mut());1611 defined_anon_consts.retain(|&konst| {1612 if konst.loc(self.db).owner != self.store_owner {1613 // This comes from the signature, we don't define it.1614 return false;1615 }16161617 let const_infer = InferenceResult::of(self.db, konst);1618 self.merge(const_infer);1619 true1620 });1621 // Caution, other defined anon consts might have been added by `merge()`!1622 self.defined_anon_consts.borrow_mut().append(&mut defined_anon_consts);1623 }16241625 // FIXME: This function should be private in module. It is currently only used in the consteval, since we need1626 // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you1627 // used this function for another workaround, mention it here. If you really need this function and believe that1628 // there is no problem in it being `pub(crate)`, remove this comment.1629 fn resolve_all(self) -> InferenceResult<'db> {1630 let InferenceContext {1631 table,1632 mut result,1633 tuple_field_accesses_rev,1634 diagnostics,1635 types,1636 vars_emitted_type_must_be_known_for,1637 ..1638 } = self;1639 let diagnostics = diagnostics.finish();1640 // Destructure every single field so whenever new fields are added to `InferenceResult` we1641 // don't forget to handle them here.1642 let InferenceResult {1643 method_resolutions,1644 field_resolutions: _,1645 variant_resolutions: _,1646 assoc_resolutions,1647 type_of_expr,1648 type_of_pat,1649 type_of_binding,1650 type_of_type_placeholder,1651 type_of_opaque,1652 skipped_ref_pats,1653 closures_data,1654 has_errors,1655 error_ty: _,1656 pat_adjustments,1657 binding_modes: _,1658 expr_adjustments,1659 tuple_field_access_types,1660 coercion_casts: _,1661 diagnostics: result_diagnostics,1662 nodes_with_type_mismatches,1663 defined_anon_consts: result_defined_anon_consts,1664 } = &mut result;16651666 *result_defined_anon_consts = self.defined_anon_consts.into_inner();1667 result_defined_anon_consts.shrink_to_fit();16681669 let mut resolver =1670 WriteBackCtxt::new(table, diagnostics, vars_emitted_type_must_be_known_for);16711672 skipped_ref_pats.shrink_to_fit();1673 for ty in type_of_expr.values_mut() {1674 resolver.resolve_completely(ty);1675 }1676 type_of_expr.shrink_to_fit();1677 for ty in type_of_pat.values_mut() {1678 resolver.resolve_completely(ty);1679 }1680 type_of_pat.shrink_to_fit();1681 for ty in type_of_binding.values_mut() {1682 resolver.resolve_completely(ty);1683 }1684 type_of_binding.shrink_to_fit();1685 for ty in type_of_type_placeholder.values_mut() {1686 resolver.resolve_completely(ty);1687 }1688 type_of_type_placeholder.shrink_to_fit();1689 type_of_opaque.shrink_to_fit();16901691 if let Some(nodes_with_type_mismatches) = nodes_with_type_mismatches {1692 *has_errors = true;1693 nodes_with_type_mismatches.shrink_to_fit();1694 }1695 for (_, subst) in method_resolutions.values_mut() {1696 resolver.resolve_completely(subst);1697 }1698 method_resolutions.shrink_to_fit();1699 for (_, subst) in assoc_resolutions.values_mut() {1700 resolver.resolve_completely(subst);1701 }1702 assoc_resolutions.shrink_to_fit();1703 for adjustment in expr_adjustments.values_mut().flatten() {1704 resolver.resolve_completely(&mut adjustment.target);1705 }1706 expr_adjustments.shrink_to_fit();1707 for adjustments in pat_adjustments.values_mut() {1708 for adjustment in &mut *adjustments {1709 resolver.resolve_completely(&mut adjustment.source);1710 }1711 adjustments.shrink_to_fit();1712 }1713 pat_adjustments.shrink_to_fit();1714 for closure_data in closures_data.values_mut() {1715 let ClosureData { min_captures, fake_reads, liberated_sig } = closure_data;1716 let dummy_place = || Place {1717 base_ty: types.types.error.store(),1718 base: closure::analysis::expr_use_visitor::PlaceBase::Rvalue,1719 projections: Vec::new(),1720 };17211722 for (place, _, sources) in fake_reads {1723 resolver.resolve_completely_with_default(place, dummy_place());1724 place.projections.shrink_to_fit();1725 for source in &mut *sources {1726 source.shrink_to_fit();1727 }1728 sources.shrink_to_fit();1729 }17301731 for min_capture in min_captures.values_mut() {1732 for captured in &mut *min_capture {1733 let CapturedPlace { place, info, mutability: _ } = captured;1734 resolver.resolve_completely_with_default(place, dummy_place());1735 let CaptureInfo { sources, capture_kind: _ } = info;1736 for source in &mut *sources {1737 source.shrink_to_fit();1738 }1739 sources.shrink_to_fit();1740 }1741 min_capture.shrink_to_fit();1742 }1743 min_captures.shrink_to_fit();17441745 resolver.resolve_completely(liberated_sig);1746 }1747 closures_data.shrink_to_fit();1748 *tuple_field_access_types = tuple_field_accesses_rev1749 .into_iter()1750 .map(|mut subst| {1751 resolver.resolve_completely(&mut subst);1752 subst.store()1753 })1754 .collect();1755 tuple_field_access_types.shrink_to_fit();17561757 let (diagnostics, resolver_has_errors) = resolver.resolve_diagnostics();1758 *result_diagnostics = diagnostics;1759 *has_errors |= resolver_has_errors;17601761 result1762 }17631764 fn collect_const(&mut self, id: ConstId, data: &'db ConstSignature) {1765 let return_ty = self.make_ty(1766 data.type_ref,1767 &data.store,1768 InferenceTyDiagnosticSource::Signature,1769 ExpressionStoreOwnerId::Signature(id.into()),1770 LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container),1771 );17721773 self.return_ty = return_ty;1774 }17751776 fn collect_static(&mut self, id: StaticId, data: &'db StaticSignature) {1777 let return_ty = self.make_ty(1778 data.type_ref,1779 &data.store,1780 InferenceTyDiagnosticSource::Signature,1781 ExpressionStoreOwnerId::Signature(id.into()),1782 LifetimeElisionKind::Elided(self.types.regions.statik),1783 );17841785 self.return_ty = return_ty;1786 }17871788 fn collect_fn(1789 &mut self,1790 func: FunctionId,1791 self_param: Option<BindingId>,1792 params: &[Param<PatId>],1793 ) {1794 let data = FunctionSignature::of(self.db, func);1795 let mut param_tys = self.with_ty_lowering(1796 &data.store,1797 InferenceTyDiagnosticSource::Signature,1798 ExpressionStoreOwnerId::Signature(func.into()),1799 LifetimeElisionKind::for_fn_params(data),1800 |ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(),1801 );18021803 // Check if function contains a va_list, if it does then we append it to the parameter types1804 // that are collected from the function data1805 if data.is_varargs() {1806 let va_list_ty = match self.resolve_va_list() {1807 Some(va_list) => Ty::new_adt(1808 self.interner(),1809 va_list,1810 GenericArgs::for_item_with_defaults(1811 self.interner(),1812 va_list.into(),1813 |_, id, _| self.table.var_for_def(id, Span::Dummy),1814 ),1815 ),1816 None => self.err_ty(),1817 };18181819 param_tys.push(va_list_ty);1820 }1821 let mut param_tys = param_tys.into_iter();1822 if let Some(self_param) = self_param1823 && let Some(ty) = param_tys.next()1824 {1825 let ty = self.process_user_written_ty(ty);1826 self.write_binding_ty(self_param, ty);1827 }1828 for pat in params {1829 let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy));1830 let ty = self.process_user_written_ty(ty);18311832 self.infer_top_pat(pat.formal, ty, PatOrigin::Param);1833 }1834 self.return_ty = match data.ret_type {1835 Some(return_ty) => {1836 let return_ty = self.with_ty_lowering(1837 &data.store,1838 InferenceTyDiagnosticSource::Signature,1839 ExpressionStoreOwnerId::Signature(func.into()),1840 LifetimeElisionKind::for_fn_ret(self.interner()),1841 |ctx| {1842 ctx.impl_trait_mode(ImplTraitLoweringMode::Opaque);1843 ctx.lower_ty(return_ty)1844 },1845 );1846 self.process_user_written_ty(return_ty)1847 }1848 None => self.types.types.unit,1849 };18501851 self.return_coercion = Some(CoerceMany::new(self.return_ty));1852 }18531854 #[inline]1855 pub(crate) fn interner(&self) -> DbInterner<'db> {1856 self.table.interner()1857 }18581859 #[inline]1860 pub(crate) fn infcx(&self) -> &InferCtxt<'db> {1861 &self.table.infer_ctxt1862 }18631864 /// If `ty` is an error, returns an infer var instead. Otherwise, returns it.1865 ///1866 /// "Refreshing" types like this is useful for getting better types, but it is also1867 /// very dangerous: we might create duplicate diagnostics, for example if we try1868 /// to resolve it and fail. rustc doesn't do that for this reason (and is in general1869 /// more strict with how it uses error types; an error type in inputs will almost1870 /// always cause it to infer an error type in output, while we infer some type as much1871 /// as we can).1872 ///1873 /// Unfortunately, we cannot allow ourselves to do that. Not only we more often work1874 /// with incomplete code, we also have assists, for example "Generate constant", that1875 /// will assume the inferred type is the expected type even if the expression itself1876 /// cannot be inferred. Therefore, we choose a middle ground: refresh the type,1877 /// but if we return a new var, mark it so that no diagnostics will be issued on it.1878 fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {1879 if ty.is_ty_error() {1880 let var = self.table.next_ty_var(Span::Dummy);18811882 // Suppress future errors on this var. Add more things here when we add more diagnostics.1883 self.vars_emitted_type_must_be_known_for.insert(var.into());18841885 var1886 } else {1887 ty1888 }1889 }18901891 fn infer_body(&mut self, body_expr: ExprId) {1892 match self.return_coercion {1893 Some(_) => self.infer_return(body_expr),1894 None => {1895 _ = self.infer_expr_coerce(1896 body_expr,1897 &Expectation::has_type(self.return_ty),1898 ExprIsRead::Yes,1899 )1900 }1901 }1902 }19031904 fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {1905 self.result.type_of_expr.insert(expr, ty.store());1906 }19071908 pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {1909 if adjustments.is_empty() {1910 return;1911 }1912 match self.result.expr_adjustments.entry(expr) {1913 std::collections::hash_map::Entry::Occupied(mut entry) => {1914 match (&mut entry.get_mut()[..], &adjustments[..]) {1915 (1916 [Adjustment { kind: Adjust::NeverToAny, target }],1917 [.., Adjustment { target: new_target, .. }],1918 ) => {1919 // NeverToAny coercion can target any type, so instead of adding a new1920 // adjustment on top we can change the target.1921 *target = new_target.clone();1922 }1923 _ => {1924 *entry.get_mut() = adjustments;1925 }1926 }1927 }1928 std::collections::hash_map::Entry::Vacant(entry) => {1929 entry.insert(adjustments);1930 }1931 }1932 }19331934 pub(crate) fn write_method_resolution(1935 &mut self,1936 expr: ExprId,1937 func: FunctionId,1938 subst: GenericArgs<'db>,1939 ) {1940 self.result.method_resolutions.insert(expr, (func, subst.store()));1941 }19421943 fn write_variant_resolution(&mut self, id: ExprOrPatIdPacked, variant: VariantId) {1944 self.result.variant_resolutions.insert(id, variant);1945 }19461947 fn write_assoc_resolution(1948 &mut self,1949 id: ExprOrPatIdPacked,1950 item: CandidateId,1951 subs: GenericArgs<'db>,1952 ) {1953 self.result.assoc_resolutions.insert(id, (item, subs.store()));1954 }19551956 fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {1957 self.result.type_of_pat.insert(pat, ty.store());1958 }19591960 fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {1961 self.result.type_of_binding.insert(id, ty.store());1962 }19631964 pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {1965 self.diagnostics.push(diagnostic);1966 }19671968 fn record_deferred_call_resolution(1969 &mut self,1970 closure_def_id: ExprId,1971 r: DeferredCallResolution<'db>,1972 ) {1973 self.deferred_call_resolutions.entry(closure_def_id).or_default().push(r);1974 }19751976 fn remove_deferred_call_resolutions(1977 &mut self,1978 closure_def_id: ExprId,1979 ) -> Vec<DeferredCallResolution<'db>> {1980 self.deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default()1981 }19821983 fn with_ty_lowering<R>(1984 &mut self,1985 store: &'db ExpressionStore,1986 types_source: InferenceTyDiagnosticSource,1987 store_owner: ExpressionStoreOwnerId,1988 lifetime_elision: LifetimeElisionKind<'db>,1989 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,1990 ) -> R {1991 let infer_vars = match types_source {1992 InferenceTyDiagnosticSource::Body => Some(&mut InferenceTyLoweringVarsCtx {1993 table: &mut self.table,1994 type_of_type_placeholder: &mut self.result.type_of_type_placeholder,1995 } as _),1996 InferenceTyDiagnosticSource::Signature => None,1997 };1998 let mut ctx = TyLoweringContext::new(1999 self.db,2000 &self.resolver,
Findings
✓ No findings reported for this file.