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 cmp,37 convert::identity,38 fmt,39 hash::Hash,40 ops::Deref,41};4243use base_db::{Crate, FxIndexMap};44use either::Either;45use hir_def::{46 AdtId, AssocItemId, AttrDefId, DefWithBodyId, ExpressionStoreOwnerId, FieldId, FunctionId,47 GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId,48 VariantId,49 attrs::AttrFlags,50 expr_store::{Body, ExpressionStore, HygieneId, body::Param, path::Path},51 hir::{BindingId, ExprId, ExprOrPatId, ExprOrPatIdPacked, LabelId, PatId, UnaryOp},52 lang_item::LangItems,53 layout::Integer,54 resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},55 signatures::EnumSignature,56 type_ref::{LifetimeRefId, TypeRefId},57 unstable_features::UnstableFeatures,58};59use hir_expand::{mod_path::ModPath, name::Name};60use indexmap::IndexSet;61use la_arena::ArenaMap;62use macros::{TypeFoldable, TypeVisitable};63use rustc_abi::TargetDataLayout;64use rustc_ast_ir::Mutability;65use rustc_hash::{FxHashMap, FxHashSet};66use rustc_type_ir::{67 AliasTyKind, TypeFoldable, TypeVisitableExt,68 inherent::{GenericArgs as _, IntoKind, Ty as _},69};70use salsa::SalsaValue;71use smallvec::SmallVec;72use span::Edition;73use stdx::never;74use thin_vec::ThinVec;7576use crate::{77 ImplTraitId, IncorrectGenericsLenKind, InferBodyId, PathLoweringDiagnostic, Span,78 TargetFeatures, ValueTyDefId,79 closure_analysis::PlaceBase,80 consteval::{create_anon_const, path_to_const},81 db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},82 generics::Generics,83 infer::{84 callee::DeferredCallResolution,85 closure::analysis::{86 BorrowKind,87 expr_use_visitor::{FakeReadCause, Place},88 },89 coerce::{CoerceMany, DynamicCoerceMany},90 diagnostics::{91 Diagnostics, InferenceTyLoweringContext as TyLoweringContext,92 InferenceTyLoweringVarsCtx,93 },94 expr::ExprIsRead,95 pat::PatOrigin,96 unify::resolve_completely::WriteBackCtxt,97 },98 lower::{99 ImplTraitIdx, LifetimeElisionKind, LifetimeLoweringMode, LoweringMode,100 diagnostics::TyLoweringDiagnostic,101 },102 method_resolution::CandidateId,103 next_solver::{104 AliasTy, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, StoredFnSig,105 StoredGenericArg, StoredGenericArgs, StoredTy, StoredTys, Term, Ty, TyKind, Tys,106 abi::Safety,107 infer::{InferCtxt, ObligationInspector, traits::ObligationCause},108 },109 solver_errors::SolverDiagnostic,110 utils::TargetFeatureIsSafeInTarget,111};112113pub use coerce::could_coerce;114pub use unify::{could_unify, could_unify_deeply};115116use cast::{CastCheck, CastError};117118/// The entry point of type inference.119fn infer_query<'db>(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {120 infer_query_with_inspect(db, def, None, LoweringMode::Analysis)121}122123pub fn infer_query_with_inspect<'db>(124 db: &'db dyn HirDatabase,125 def: DefWithBodyId,126 inspect: Option<ObligationInspector<'db>>,127 lowering_mode: LoweringMode,128) -> InferenceResult<'db> {129 let _p = tracing::info_span!("infer_query").entered();130 let resolver = def.resolver(db);131 let body = Body::of(db, def);132 let mut ctx = InferenceContext::new(133 db,134 InferBodyId::DefWithBodyId(def),135 ExpressionStoreOwnerId::Body(def),136 def.generic_def(db),137 &body.store,138 resolver,139 true,140 lowering_mode,141 );142143 if let Some(inspect) = inspect {144 ctx.table.infer_ctxt.attach_obligation_inspector(inspect);145 }146147 match def {148 DefWithBodyId::FunctionId(f) => {149 ctx.collect_fn(f, body.self_param.map(|param| param.formal), &body.params)150 }151 DefWithBodyId::ConstId(c) => ctx.collect_const_or_static(c.into()),152 DefWithBodyId::StaticId(s) => ctx.collect_const_or_static(s.into()),153 DefWithBodyId::VariantId(v) => {154 ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {155 hir_def::layout::IntegerType::Pointer(signed) => match signed {156 true => ctx.types.types.isize,157 false => ctx.types.types.usize,158 },159 hir_def::layout::IntegerType::Fixed(size, signed) => match signed {160 true => match size {161 Integer::I8 => ctx.types.types.i8,162 Integer::I16 => ctx.types.types.i16,163 Integer::I32 => ctx.types.types.i32,164 Integer::I64 => ctx.types.types.i64,165 Integer::I128 => ctx.types.types.i128,166 },167 false => match size {168 Integer::I8 => ctx.types.types.u8,169 Integer::I16 => ctx.types.types.u16,170 Integer::I32 => ctx.types.types.u32,171 Integer::I64 => ctx.types.types.u64,172 Integer::I128 => ctx.types.types.u128,173 },174 },175 };176 }177 }178179 ctx.infer_body(body.root_expr());180181 ctx.infer_mut_body(body.root_expr());182183 infer_finalize(ctx)184}185186fn infer_cycle_result<'db>(187 db: &'db dyn HirDatabase,188 _: salsa::Id,189 _: DefWithBodyId,190) -> InferenceResult<'db> {191 InferenceResult {192 has_errors: true,193 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))194 }195}196197/// Infer types for an anonymous const expression.198fn infer_anon_const_query<'db>(199 db: &'db dyn HirDatabase,200 def: AnonConstId<'db>,201) -> InferenceResult<'db> {202 let _p = tracing::info_span!("infer_anon_const_query").entered();203 let loc = def.loc(db);204 let store_owner = loc.owner;205 let store = ExpressionStore::of(db, store_owner);206207 let resolver = store_owner.resolver(db);208209 let mut ctx = InferenceContext::new(210 db,211 InferBodyId::AnonConstId(def),212 store_owner,213 loc.owner.generic_def(db),214 store,215 resolver,216 loc.allow_using_generic_params,217 LoweringMode::Analysis,218 );219220 ctx.infer_expr(221 loc.expr,222 &Expectation::has_type(loc.ty.get().instantiate_identity().skip_norm_wip()),223 ExprIsRead::Yes,224 );225226 infer_finalize(ctx)227}228229fn infer_anon_const_cycle_result<'db>(230 db: &'db dyn HirDatabase,231 _: salsa::Id,232 _: AnonConstId<'db>,233) -> InferenceResult<'db> {234 InferenceResult {235 has_errors: true,236 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))237 }238}239240fn infer_finalize<'db>(mut ctx: InferenceContext<'db>) -> InferenceResult<'db> {241 ctx.handle_opaque_type_uses();242243 ctx.type_inference_fallback();244245 // Comment from rustc:246 // Even though coercion casts provide type hints, we check casts after fallback for247 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.248 let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);249 for mut cast in cast_checks.into_iter() {250 if let Err(diag) = cast.check(&mut ctx) {251 ctx.diagnostics.push(diag);252 }253 }254255 ctx.table.select_obligations_where_possible();256257 // Closure and coroutine analysis may run after fallback258 // because they don't constrain other type variables.259 ctx.closure_analyze();260 assert!(ctx.deferred_call_resolutions.is_empty());261262 ctx.table.select_obligations_where_possible();263264 ctx.handle_opaque_type_uses();265266 ctx.merge_anon_consts();267268 ctx.resolve_all()269}270271#[derive(Clone, Copy, Debug, Eq, PartialEq)]272pub enum ByRef {273 Yes(Mutability),274 No,275}276277/// The mode of a binding (`mut`, `ref mut`, etc).278/// Used for both the explicit binding annotations given in the HIR for a binding279/// and the final binding mode that we infer after type inference/match ergonomics.280/// `.0` is the by-reference mode (`ref`, `ref mut`, or by value),281/// `.1` is the mutability of the binding.282#[derive(Copy, Clone, Debug, Eq, PartialEq)]283pub struct BindingMode(pub ByRef, pub Mutability);284285#[derive(Debug, PartialEq, Eq, Clone, TypeVisitable, TypeFoldable)]286pub enum InferenceDiagnostic {287 NoSuchField {288 #[type_visitable(ignore)]289 field: ExprOrPatIdPacked,290 #[type_visitable(ignore)]291 private: Option<LocalFieldId>,292 #[type_visitable(ignore)]293 variant: VariantId,294 },295 MismatchedArrayPatLen {296 #[type_visitable(ignore)]297 pat: PatId,298 #[type_visitable(ignore)]299 expected: u64,300 #[type_visitable(ignore)]301 found: u64,302 #[type_visitable(ignore)]303 has_rest: bool,304 },305 ArrayPatternWithoutFixedLength {306 #[type_visitable(ignore)]307 pat: PatId,308 },309 ExpectedArrayOrSlicePat {310 #[type_visitable(ignore)]311 pat: PatId,312 found: StoredTy,313 },314 InvalidRangePatType {315 #[type_visitable(ignore)]316 pat: PatId,317 },318 DuplicateField {319 #[type_visitable(ignore)]320 field: ExprOrPatIdPacked,321 #[type_visitable(ignore)]322 variant: VariantId,323 },324 PrivateField {325 #[type_visitable(ignore)]326 expr: ExprId,327 #[type_visitable(ignore)]328 field: FieldId,329 },330 PrivateAssocItem {331 #[type_visitable(ignore)]332 id: ExprOrPatIdPacked,333 #[type_visitable(ignore)]334 item: AssocItemId,335 },336 UnresolvedField {337 #[type_visitable(ignore)]338 expr: ExprId,339 receiver: StoredTy,340 #[type_visitable(ignore)]341 name: Name,342 #[type_visitable(ignore)]343 method_with_same_name_exists: bool,344 },345 UnresolvedMethodCall {346 #[type_visitable(ignore)]347 expr: ExprId,348 receiver: StoredTy,349 #[type_visitable(ignore)]350 name: Name,351 /// Contains the type the field resolves to352 field_with_same_name: Option<StoredTy>,353 #[type_visitable(ignore)]354 assoc_func_with_same_name: Option<FunctionId>,355 },356 UnresolvedAssocItem {357 #[type_visitable(ignore)]358 id: ExprOrPatIdPacked,359 },360 UnresolvedIdent {361 #[type_visitable(ignore)]362 id: ExprOrPatIdPacked,363 },364 // FIXME: This should be emitted in body lowering365 BreakOutsideOfLoop {366 #[type_visitable(ignore)]367 expr: ExprId,368 #[type_visitable(ignore)]369 is_break: bool,370 #[type_visitable(ignore)]371 bad_value_break: bool,372 },373 NonExhaustiveRecordExpr {374 #[type_visitable(ignore)]375 expr: ExprId,376 },377 NonExhaustiveRecordPat {378 #[type_visitable(ignore)]379 pat: PatId,380 #[type_visitable(ignore)]381 variant: VariantId,382 },383 UnionPatMustHaveExactlyOneField {384 #[type_visitable(ignore)]385 pat: PatId,386 },387 UnionPatHasRest {388 #[type_visitable(ignore)]389 pat: PatId,390 },391 FunctionalRecordUpdateOnNonStruct {392 #[type_visitable(ignore)]393 base_expr: ExprId,394 },395 MismatchedArgCount {396 #[type_visitable(ignore)]397 call_expr: ExprId,398 #[type_visitable(ignore)]399 expected: usize,400 #[type_visitable(ignore)]401 found: usize,402 /// True when the call goes through the `Fn`/`FnMut`/`FnOnce` trait403 /// (i.e. arguments were bundled into a tuple). Determines whether the404 /// diagnostic surface uses E0057 (Fn-trait call) or E0061 (regular call).405 #[type_visitable(ignore)]406 is_fn_trait_call: bool,407 },408 MismatchedTupleStructPatArgCount {409 #[type_visitable(ignore)]410 pat: PatId,411 #[type_visitable(ignore)]412 expected: usize,413 #[type_visitable(ignore)]414 found: usize,415 },416 ExpectedFunction {417 #[type_visitable(ignore)]418 call_expr: ExprId,419 found: StoredTy,420 },421 CannotBeDereferenced {422 #[type_visitable(ignore)]423 expr: ExprId,424 found: StoredTy,425 },426 UnaryOperatorCannotBeApplied {427 #[type_visitable(ignore)]428 expr: ExprId,429 #[type_visitable(ignore)]430 op: UnaryOp,431 found: StoredTy,432 },433 MutRefInImmRefPat {434 #[type_visitable(ignore)]435 pat: PatId,436 },437 CannotImplicitlyDerefTraitObject {438 #[type_visitable(ignore)]439 pat: PatId,440 found: StoredTy,441 },442 CannotIndexInto {443 #[type_visitable(ignore)]444 expr: ExprId,445 found: StoredTy,446 },447 TypedHole {448 #[type_visitable(ignore)]449 expr: ExprId,450 expected: StoredTy,451 },452 CastToUnsized {453 #[type_visitable(ignore)]454 expr: ExprId,455 cast_ty: StoredTy,456 },457 InvalidCast {458 #[type_visitable(ignore)]459 expr: ExprId,460 #[type_visitable(ignore)]461 error: CastError,462 expr_ty: StoredTy,463 cast_ty: StoredTy,464 },465 TyDiagnostic {466 #[type_visitable(ignore)]467 diag: TyLoweringDiagnostic,468 },469 PathDiagnostic {470 #[type_visitable(ignore)]471 node: ExprOrPatIdPacked,472 #[type_visitable(ignore)]473 diag: PathLoweringDiagnostic,474 },475 MethodCallIncorrectGenericsLen {476 #[type_visitable(ignore)]477 expr: ExprId,478 #[type_visitable(ignore)]479 provided_count: u32,480 #[type_visitable(ignore)]481 expected_count: u32,482 #[type_visitable(ignore)]483 kind: IncorrectGenericsLenKind,484 #[type_visitable(ignore)]485 def: GenericDefId,486 },487 MethodCallIllegalSizedBound {488 #[type_visitable(ignore)]489 call_expr: ExprId,490 },491 MethodCallIncorrectGenericsOrder {492 #[type_visitable(ignore)]493 expr: ExprId,494 #[type_visitable(ignore)]495 param_id: GenericParamId,496 #[type_visitable(ignore)]497 arg_idx: u32,498 /// Whether the `GenericArgs` contains a `Self` arg.499 #[type_visitable(ignore)]500 has_self_arg: bool,501 },502 InvalidLhsOfAssignment {503 #[type_visitable(ignore)]504 lhs: ExprId,505 },506 TypeMustBeKnown {507 #[type_visitable(ignore)]508 at_point: Span,509 top_term: Option<StoredGenericArg>,510 },511 UnionExprMustHaveExactlyOneField {512 #[type_visitable(ignore)]513 expr: ExprId,514 },515 TypeMismatch {516 #[type_visitable(ignore)]517 node: ExprOrPatIdPacked,518 expected: StoredTy,519 found: StoredTy,520 },521 SolverDiagnostic(SolverDiagnostic),522 ExplicitDropMethodUse {523 #[type_visitable(ignore)]524 kind: ExplicitDropMethodUseKind,525 },526 MutableRefBinding {527 #[type_visitable(ignore)]528 pat: PatId,529 },530 YieldOutsideCoroutine {531 #[type_visitable(ignore)]532 expr: ExprId,533 },534 ReturnOutsideFunction {535 #[type_visitable(ignore)]536 expr: ExprId,537 #[type_visitable(ignore)]538 kind: ReturnKind,539 },540 RecordMissingFields {541 #[type_visitable(ignore)]542 record: ExprOrPatId,543 #[type_visitable(ignore)]544 variant: VariantId,545 #[type_visitable(ignore)]546 missed_fields: Vec<LocalFieldId>,547 },548}549550#[derive(Debug, PartialEq, Eq, Clone, Copy)]551pub enum ReturnKind {552 ReturnExpr,553 BecomeExpr,554}555556#[derive(Debug, PartialEq, Eq, Clone)]557pub enum ExplicitDropMethodUseKind {558 MethodCall(ExprId),559 Path(ExprOrPatIdPacked),560}561562/// Represents coercing a value to a different type of value.563///564/// We transform values by following a number of `Adjust` steps in order.565/// See the documentation on variants of `Adjust` for more details.566///567/// Here are some common scenarios:568///569/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.570/// Here the pointer will be dereferenced N times (where a dereference can571/// happen to raw or borrowed pointers or any smart pointer which implements572/// Deref, including Box<_>). The types of dereferences is given by573/// `autoderefs`. It can then be auto-referenced zero or one times, indicated574/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is575/// `false`.576///577/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start578/// with a thin pointer, deref a number of times, unsize the underlying data,579/// then autoref. The 'unsize' phase may change a fixed length array to a580/// dynamically sized one, a concrete object to a trait object, or statically581/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is582/// represented by:583///584/// ```ignore585/// Deref(None) -> [i32; 4],586/// Borrow(AutoBorrow::Ref) -> &[i32; 4],587/// Unsize -> &[i32],588/// ```589///590/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.591/// E.g., `struct Foo<T> { it: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>592/// The autoderef and -ref are the same as in the above example, but the type593/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about594/// the underlying conversions from `[i32; 4]` to `[i32]`.595///596/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In597/// that case, we have the pointer we need coming in, so there are no598/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.599/// At some point, of course, `Box` should move out of the compiler, in which600/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->601/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.602#[derive(Clone, Debug, PartialEq, Eq, Hash)]603pub struct Adjustment {604 pub kind: Adjust,605 pub target: StoredTy,606}607608impl Adjustment {609 pub fn borrow<'db>(610 interner: DbInterner<'db>,611 m: Mutability,612 ty: Ty<'db>,613 lt: Region<'db>,614 ) -> Self {615 let ty = Ty::new_ref(interner, lt, ty, m);616 Adjustment {617 kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(m, AllowTwoPhase::No))),618 target: ty.store(),619 }620 }621}622623/// At least for initial deployment, we want to limit two-phase borrows to624/// only a few specific cases. Right now, those are mostly "things that desugar"625/// into method calls:626/// - using `x.some_method()` syntax, where some_method takes `&mut self`,627/// - using `Foo::some_method(&mut x, ...)` syntax,628/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).629///630/// Anything else should be rejected until generalized two-phase borrow support631/// is implemented. Right now, dataflow can't handle the general case where there632/// is more than one use of a mutable borrow, and we don't want to accept too much633/// new code via two-phase borrows, so we try to limit where we create two-phase634/// capable mutable borrows.635/// See #49434 for tracking.636#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]637pub enum AllowTwoPhase {638 // FIXME: We should use this when appropriate.639 Yes,640 No,641}642643#[derive(Clone, Debug, PartialEq, Eq, Hash)]644pub enum Adjust {645 /// Go from ! to any type.646 NeverToAny,647 /// Dereference once, producing a place.648 Deref(Option<OverloadedDeref>),649 /// Take the address and produce either a `&` or `*` pointer.650 Borrow(AutoBorrow),651 Pointer(PointerCast),652}653654/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`655/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.656/// The target type is `U` in both cases, with the region and mutability657/// being those shared by both the receiver and the returned reference.658#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]659pub struct OverloadedDeref(pub Mutability);660661#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]662pub enum AutoBorrowMutability {663 Mut { allow_two_phase_borrow: AllowTwoPhase },664 Not,665}666667impl AutoBorrowMutability {668 /// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows.669 ///670 /// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored671 pub fn new(mutbl: Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self {672 match mutbl {673 Mutability::Not => Self::Not,674 Mutability::Mut => Self::Mut { allow_two_phase_borrow },675 }676 }677}678679impl From<AutoBorrowMutability> for Mutability {680 fn from(m: AutoBorrowMutability) -> Self {681 match m {682 AutoBorrowMutability::Mut { .. } => Mutability::Mut,683 AutoBorrowMutability::Not => Mutability::Not,684 }685 }686}687688#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]689pub enum AutoBorrow {690 /// Converts from T to &T.691 Ref(AutoBorrowMutability),692 /// Converts from T to *T.693 RawPtr(Mutability),694}695696#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]697pub enum PointerCast {698 /// Go from a fn-item type to a fn-pointer type.699 ReifyFnPointer,700701 /// Go from a safe fn pointer to an unsafe fn pointer.702 UnsafeFnPointer,703704 /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.705 /// It cannot convert a closure that requires unsafe.706 ClosureFnPointer(Safety),707708 /// Go from a mut raw pointer to a const raw pointer.709 MutToConstPointer,710711 #[allow(dead_code)]712 /// Go from `*const [T; N]` to `*const T`713 ArrayToPointer,714715 /// Unsize a pointer/reference value, e.g., `&[T; n]` to716 /// `&[T]`. Note that the source could be a thin or fat pointer.717 /// This will do things like convert thin pointers to fat718 /// pointers, or convert structs containing thin pointers to719 /// structs containing fat pointers, or convert between fat720 /// pointers. We don't store the details of how the transform is721 /// done (in fact, we don't know that, because it might depend on722 /// the precise type parameters). We just store the target723 /// type. Codegen backends and miri figure out what has to be done724 /// based on the precise source/target type at hand.725 Unsize,726}727728/// Represents an implicit coercion applied to the scrutinee of a match before testing a pattern729/// against it. Currently, this is used only for implicit dereferences.730#[derive(Debug, Clone, PartialEq, Eq)]731pub struct PatAdjustment {732 pub kind: PatAdjust,733 /// The type of the scrutinee before the adjustment is applied, or the "adjusted type" of the734 /// pattern.735 pub source: StoredTy,736}737738/// Represents implicit coercions of patterns' types, rather than values' types.739#[derive(Clone, Copy, PartialEq, Eq, Debug)]740pub enum PatAdjust {741 /// An implicit dereference before matching, such as when matching the pattern `0` against a742 /// scrutinee of type `&u8` or `&mut u8`.743 BuiltinDeref,744 /// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the745 /// pattern `[..]` against a scrutinee of type `Vec<T>`.746 OverloadedDeref,747}748749/// The result of type inference: A mapping from expressions and patterns to types.750///751/// When you add a field that stores types (including `Substitution` and the like), don't forget752/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must753/// not appear in the final inference result.754#[derive(Clone, PartialEq, Eq, Debug, SalsaValue)]755pub struct InferenceResult<'db> {756 /// For each method call expr, records the function it resolves to.757 method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,758 /// For each field access expr, records the field it resolves to.759 field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,760 /// For each struct literal or pattern, records the variant it resolves to.761 variant_resolutions: FxHashMap<ExprOrPatIdPacked, VariantId>,762 /// For each associated item record what it resolves to763 assoc_resolutions: FxHashMap<ExprOrPatIdPacked, (CandidateId, StoredGenericArgs)>,764 /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in765 /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of766 /// that which allows us to resolve a [`TupleFieldId`]s type.767 tuple_field_access_types: ThinVec<StoredTys>,768769 pub(crate) type_of_expr: ArenaMap<ExprId, StoredTy>,770 /// For each pattern record the type it resolves to.771 ///772 /// **Note**: When a pattern type is resolved it may still contain773 /// unresolved or missing subpatterns or subpatterns of mismatched types.774 pub(crate) type_of_pat: ArenaMap<PatId, StoredTy>,775 pub(crate) type_of_binding: ArenaMap<BindingId, StoredTy>,776 pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, StoredTy>,777 pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId<'db>, StoredTy>,778779 /// Whether there are any type-mismatching errors in the result.780 // FIXME: This isn't as useful as initially thought due to us falling back placeholders to781 // `TyKind::Error`.782 // Which will then mark this field.783 pub(crate) has_errors: bool,784 /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.785 diagnostics: ThinVec<InferenceDiagnostic>,786 // FIXME: Remove this, change it to be in `InferenceContext`:787 nodes_with_type_mismatches: Option<Box<FxHashSet<ExprOrPatIdPacked>>>,788789 /// Interned `Error` type to return references to.790 // FIXME: Remove this.791 error_ty: StoredTy,792793 pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,794 /// Stores the types which were implicitly dereferenced in pattern binding modes.795 pub(crate) pat_adjustments: FxHashMap<PatId, Vec<PatAdjustment>>,796 /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.797 ///798 /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an799 /// or pattern can have multiple binding modes. For example:800 /// ```801 /// fn foo(mut slice: &[u32]) -> usize {802 /// slice = match slice {803 /// [0, rest @ ..] | rest => rest,804 /// };805 /// 0806 /// }807 /// ```808 /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.809 pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,810811 /// Set of reference patterns that match against a match-ergonomics inserted reference812 /// (as opposed to against a reference in the scrutinee type).813 skipped_ref_pats: FxHashSet<PatId>,814815 pub(crate) coercion_casts: FxHashSet<ExprId>,816817 pub closures_data: FxHashMap<ExprId, ClosureData>,818819 defined_anon_consts: ThinVec<AnonConstId<'db>>,820}821822#[derive(Clone, PartialEq, Eq, Debug)]823pub struct ClosureData {824 /// Tracks the minimum captures required for a closure;825 /// see `MinCaptureInformationMap` for more details.826 pub min_captures: RootVariableMinCaptureList,827828 /// Tracks the fake reads required for a closure and the reason for the fake read.829 /// When performing pattern matching for closures, there are times we don't end up830 /// reading places that are mentioned in a closure (because of _ patterns). However,831 /// to ensure the places are initialized, we introduce fake reads.832 /// Consider these two examples:833 /// ```ignore (discriminant matching with only wildcard arm)834 /// let x: u8;835 /// let c = || match x { _ => () };836 /// ```837 /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't838 /// want to capture it. However, we do still want an error here, because `x` should have839 /// to be initialized at the point where c is created. Therefore, we add a "fake read"840 /// instead.841 /// ```ignore (destructured assignments)842 /// let c = || {843 /// let (t1, t2) = t;844 /// }845 /// ```846 /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but847 /// we never capture `t`. This becomes an issue when we build MIR as we require848 /// information on `t` in order to create place `t.0` and `t.1`. We can solve this849 /// issue by fake reading `t`.850 pub fake_reads: Box<[(Place, FakeReadCause, SmallVec<[CaptureSourceStack; 2]>)]>,851852 /// For each fn, records the "liberated" types of its arguments853 /// and return type. Liberated means that all bound regions854 /// (including late-bound regions) are replaced with free855 /// equivalents. This table is not used in codegen (since regions856 /// are erased there) and hence is not serialized to metadata.857 ///858 /// This table also contains the "revealed" values for any `impl Trait`859 /// that appear in the signature and whose values are being inferred860 /// by this function.861 ///862 /// # Example863 ///864 /// ```rust865 /// # use std::fmt::Debug;866 /// fn foo(x: &u32) -> impl Debug { *x }867 /// ```868 ///869 /// The function signature here would be:870 ///871 /// ```ignore (illustrative)872 /// for<'a> fn(&'a u32) -> Foo873 /// ```874 ///875 /// where `Foo` is an opaque type created for this function.876 ///877 ///878 /// The *liberated* form of this would be879 ///880 /// ```ignore (illustrative)881 /// fn(&'a u32) -> u32882 /// ```883 ///884 /// Note that `'a` is not bound (it would be an `ReLateParam`) and885 /// that the `Foo` opaque type is replaced by its hidden type.886 pub liberated_sig: StoredFnSig,887}888889/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.890/// Used to track the minimum set of `Place`s that need to be captured to support all891/// Places captured by the closure starting at a given root variable.892///893/// This provides a convenient and quick way of checking if a variable being used within894/// a closure is a capture of a local variable.895pub(crate) type RootVariableMinCaptureList = FxIndexMap<BindingId, MinCaptureList>;896897/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.898pub(crate) type MinCaptureList = Vec<CapturedPlace>;899900/// A composite describing a `Place` that is captured by a closure.901#[derive(Eq, PartialEq, Clone, Debug, Hash)]902pub struct CapturedPlace {903 /// The `Place` that is captured.904 pub place: Place,905906 /// `CaptureKind` and expression(s) that resulted in such capture of `place`.907 pub info: CaptureInfo,908909 /// Represents if `place` can be mutated or not.910 pub mutability: Mutability,911}912913impl CapturedPlace {914 pub fn is_by_ref(&self) -> bool {915 match self.info.capture_kind {916 UpvarCapture::ByValue | UpvarCapture::ByUse => false,917 UpvarCapture::ByRef(..) => true,918 }919 }920921 pub fn captured_local(&self) -> BindingId {922 match self.place.base {923 PlaceBase::Upvar { var_id: local, .. } | PlaceBase::Local(local) => local,924 PlaceBase::Rvalue | PlaceBase::StaticItem => {925 unreachable!("only locals can be captured")926 }927 }928 }929930 /// The type of the capture stored in the closure, which is different from the type of the captured place931 /// if we capture by reference.932 pub fn captured_ty<'db>(&self, db: &'db dyn HirDatabase) -> Ty<'db> {933 let place_ty = self.place.ty();934 let make_ref = |mutbl| {935 let interner = DbInterner::new_no_crate(db);936 let region = Region::new_erased(interner);937 Ty::new_ref(interner, region, place_ty, mutbl)938 };939 match self.info.capture_kind {940 UpvarCapture::ByUse | UpvarCapture::ByValue => place_ty,941 UpvarCapture::ByRef(kind) => make_ref(kind.to_mutbl_lossy()),942 }943 }944}945946#[derive(Clone)]947pub struct CaptureSourceStack(CaptureSourceStackRepr);948949#[derive(Clone)]950enum CaptureSourceStackRepr {951 One(ExprOrPatIdPacked),952 Two([ExprOrPatIdPacked; 2]),953 Many(ThinVec<ExprOrPatIdPacked>),954}955956impl PartialEq for CaptureSourceStack {957 fn eq(&self, other: &Self) -> bool {958 **self == **other959 }960}961962impl Eq for CaptureSourceStack {}963964impl std::hash::Hash for CaptureSourceStack {965 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {966 (**self).hash(state);967 }968}969970#[cfg(target_pointer_width = "64")]971const _: () = assert!(size_of::<CaptureSourceStack>() == 16);972973impl Deref for CaptureSourceStack {974 type Target = [ExprOrPatIdPacked];975976 #[inline]977 fn deref(&self) -> &Self::Target {978 match &self.0 {979 CaptureSourceStackRepr::One(it) => std::slice::from_ref(it),980 CaptureSourceStackRepr::Two(it) => it,981 CaptureSourceStackRepr::Many(it) => it,982 }983 }984}985986impl fmt::Debug for CaptureSourceStack {987 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {988 f.debug_tuple("CaptureSourceStack").field(&&**self).finish()989 }990}991992impl CaptureSourceStack {993 #[inline]994 pub fn len(&self) -> usize {995 match &self.0 {996 CaptureSourceStackRepr::One(_) => 1,997 CaptureSourceStackRepr::Two(_) => 2,998 CaptureSourceStackRepr::Many(it) => it.len(),999 }1000 }10011002 #[inline]1003 pub(crate) fn from_single(id: ExprOrPatIdPacked) -> Self {1004 Self(CaptureSourceStackRepr::One(id))1005 }10061007 #[inline]1008 pub fn final_source(&self) -> ExprOrPatIdPacked {1009 *self.last().expect("should always have a final source")1010 }10111012 pub fn push(&mut self, new_id: ExprOrPatIdPacked) {1013 match &mut self.0 {1014 CaptureSourceStackRepr::One(old_id) => {1015 self.0 = CaptureSourceStackRepr::Two([*old_id, new_id])1016 }1017 CaptureSourceStackRepr::Two([old_id1, old_id2]) => {1018 self.0 = CaptureSourceStackRepr::Many(ThinVec::from([*old_id1, *old_id2, new_id]));1019 }1020 CaptureSourceStackRepr::Many(old_ids) => old_ids.push(new_id),1021 }1022 }10231024 pub fn truncate(&mut self, new_len: usize) {1025 debug_assert!(new_len > 0);1026 match &mut self.0 {1027 CaptureSourceStackRepr::One(_) => {}1028 CaptureSourceStackRepr::Two([first, _]) => {1029 if new_len == 1 {1030 self.0 = CaptureSourceStackRepr::One(*first)1031 }1032 }1033 CaptureSourceStackRepr::Many(ids) => ids.truncate(new_len),1034 }1035 }10361037 pub fn shrink_to_fit(&mut self) {1038 match &mut self.0 {1039 CaptureSourceStackRepr::One(_) | CaptureSourceStackRepr::Two(_) => {}1040 CaptureSourceStackRepr::Many(ids) => match **ids {1041 [one] => self.0 = CaptureSourceStackRepr::One(one),1042 [first, second] => self.0 = CaptureSourceStackRepr::Two([first, second]),1043 _ => ids.shrink_to_fit(),1044 },1045 }1046 }1047}10481049/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)1050/// for a particular capture as well as identifying the part of the source code1051/// that triggered this capture to occur.1052#[derive(Eq, PartialEq, Clone, Debug, Hash)]1053pub struct CaptureInfo {1054 pub sources: SmallVec<[CaptureSourceStack; 2]>,10551056 /// Capture mode that was selected1057 pub capture_kind: UpvarCapture,1058}10591060/// Information describing the capture of an upvar. This is computed1061/// during `typeck`, specifically by `regionck`.1062#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash)]1063pub enum UpvarCapture {1064 /// Upvar is captured by reference.1065 ByRef(BorrowKind),10661067 /// Upvar is captured by use. This is true when the closure is labeled `use`.1068 ByUse,10691070 /// Upvar is captured by value. This is always true when the1071 /// closure is labeled `move`, but can also be true in other cases1072 /// depending on inference.1073 ByValue,1074}10751076// Used in closure::analysis::determine_capture_info1077impl PartialOrd for UpvarCapture {1078 #[inline]1079 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {1080 match (self, other) {1081 (Self::ByValue, Self::ByValue) | (Self::ByUse, Self::ByUse) => {1082 Some(cmp::Ordering::Equal)1083 }1084 (Self::ByValue | Self::ByUse, Self::ByRef(_)) => Some(cmp::Ordering::Greater),1085 (Self::ByRef(_), Self::ByValue | Self::ByUse) => Some(cmp::Ordering::Less),1086 (Self::ByRef(left), Self::ByRef(right)) => Some(left.cmp(right)),1087 (Self::ByUse, Self::ByValue) | (Self::ByValue, Self::ByUse) => None,1088 }1089 }1090}10911092#[salsa::tracked]1093impl<'db> InferenceResult<'db> {1094 #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]1095 fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_> {1096 infer_query(db, def)1097 }10981099 /// Infer types for all const expressions in an item's signature.1100 ///1101 /// Returns an `InferenceResult` containing type information for array lengths,1102 /// const generic arguments, and other const expressions appearing in type1103 /// positions within the item's signature.1104 #[salsa::tracked(returns(ref), cycle_result = infer_anon_const_cycle_result)]1105 fn for_anon_const(db: &'db dyn HirDatabase, def: AnonConstId<'db>) -> InferenceResult<'db> {1106 infer_anon_const_query(db, def)1107 }1108}11091110impl<'db> InferenceResult<'db> {1111 #[inline]1112 pub fn of(1113 db: &'db dyn HirDatabase,1114 def: impl Into<InferBodyId<'db>>,1115 ) -> &'db InferenceResult<'db> {1116 match def.into() {1117 InferBodyId::DefWithBodyId(it) => InferenceResult::for_body(db, it),1118 InferBodyId::AnonConstId(it) => InferenceResult::for_anon_const(db, it),1119 }1120 }1121}11221123impl<'db> InferenceResult<'db> {1124 fn new(error_ty: Ty<'_>) -> Self {1125 Self {1126 method_resolutions: Default::default(),1127 field_resolutions: Default::default(),1128 variant_resolutions: Default::default(),1129 assoc_resolutions: Default::default(),1130 tuple_field_access_types: Default::default(),1131 diagnostics: Default::default(),1132 nodes_with_type_mismatches: Default::default(),1133 type_of_expr: Default::default(),1134 type_of_pat: Default::default(),1135 type_of_binding: Default::default(),1136 type_of_type_placeholder: Default::default(),1137 type_of_opaque: Default::default(),1138 skipped_ref_pats: Default::default(),1139 has_errors: Default::default(),1140 error_ty: error_ty.store(),1141 pat_adjustments: Default::default(),1142 binding_modes: Default::default(),1143 expr_adjustments: Default::default(),1144 coercion_casts: Default::default(),1145 closures_data: Default::default(),1146 defined_anon_consts: Default::default(),1147 }1148 }11491150 pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {1151 self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))1152 }1153 pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {1154 self.field_resolutions.get(&expr).copied()1155 }1156 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {1157 self.variant_resolutions.get(&id.into()).copied()1158 }1159 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {1160 self.variant_resolutions.get(&id.into()).copied()1161 }1162 pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {1163 match id {1164 ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),1165 ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),1166 }1167 }1168 pub fn assoc_resolutions_for_expr<'a>(1169 &self,1170 id: ExprId,1171 ) -> Option<(CandidateId, GenericArgs<'a>)> {1172 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))1173 }1174 pub fn assoc_resolutions_for_pat<'a>(1175 &self,1176 id: PatId,1177 ) -> Option<(CandidateId, GenericArgs<'a>)> {1178 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))1179 }1180 pub fn assoc_resolutions_for_expr_or_pat<'a>(1181 &self,1182 id: ExprOrPatId,1183 ) -> Option<(CandidateId, GenericArgs<'a>)> {1184 match id {1185 ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),1186 ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),1187 }1188 }1189 pub fn expr_or_pat_has_type_mismatch(&self, node: ExprOrPatIdPacked) -> bool {1190 self.nodes_with_type_mismatches.as_ref().is_some_and(|it| it.contains(&node))1191 }1192 pub fn expr_has_type_mismatch(&self, expr: ExprId) -> bool {1193 self.expr_or_pat_has_type_mismatch(expr.into())1194 }1195 pub fn pat_has_type_mismatch(&self, pat: PatId) -> bool {1196 self.expr_or_pat_has_type_mismatch(pat.into())1197 }1198 pub fn exprs_have_type_mismatches(&self) -> bool {1199 self.nodes_with_type_mismatches1200 .as_ref()1201 .is_some_and(|it| it.iter().any(|node| node.is_expr()))1202 }1203 pub fn has_type_mismatches(&self) -> bool {1204 self.nodes_with_type_mismatches.is_some()1205 }1206 pub fn placeholder_types<'a>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'a>)> {1207 self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref()))1208 }1209 pub fn type_of_type_placeholder<'a>(&self, type_ref: TypeRefId) -> Option<Ty<'a>> {1210 self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())1211 }1212 pub fn type_of_expr_or_pat<'a>(&self, id: ExprOrPatId) -> Option<Ty<'a>> {1213 match id {1214 ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),1215 ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),1216 }1217 }1218 pub fn type_of_expr_with_adjust<'a>(&self, id: ExprId) -> Option<Ty<'a>> {1219 match self.expr_adjustments.get(&id).and_then(|adjustments| {1220 adjustments.iter().rfind(|adj| {1221 // https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L1401222 !matches!(1223 adj,1224 Adjustment {1225 kind: Adjust::NeverToAny,1226 target,1227 } if target.as_ref().is_never()1228 )1229 })1230 }) {1231 Some(adjustment) => Some(adjustment.target.as_ref()),1232 None => self.type_of_expr.get(id).map(|it| it.as_ref()),1233 }1234 }1235 pub fn type_of_pat_with_adjust<'a>(&self, id: PatId) -> Ty<'a> {1236 match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {1237 Some(adjusted) => adjusted.source.as_ref(),1238 None => self.pat_ty(id),1239 }1240 }1241 pub fn is_erroneous(&self) -> bool {1242 self.has_errors && self.type_of_expr.iter().count() == 01243 }12441245 pub fn diagnostics(&self) -> &[InferenceDiagnostic] {1246 &self.diagnostics1247 }12481249 pub fn tuple_field_access_type<'a>(&self, id: TupleId) -> Tys<'a> {1250 self.tuple_field_access_types[id.0 as usize].as_ref()1251 }12521253 pub fn pat_adjustment(&self, id: PatId) -> Option<&[PatAdjustment]> {1254 self.pat_adjustments.get(&id).map(|it| &**it)1255 }12561257 pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {1258 self.expr_adjustments.get(&id).map(|it| &**it)1259 }12601261 pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {1262 self.binding_modes.get(id).copied()1263 }12641265 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1266 pub fn expression_types<'a>(&self) -> impl Iterator<Item = (ExprId, Ty<'a>)> {1267 self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))1268 }12691270 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1271 pub fn pattern_types<'a>(&self) -> impl Iterator<Item = (PatId, Ty<'a>)> {1272 self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))1273 }12741275 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1276 pub fn binding_types<'a>(&self) -> impl Iterator<Item = (BindingId, Ty<'a>)> {1277 self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))1278 }12791280 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1281 pub fn return_position_impl_trait_types<'a>(1282 &'a self,1283 db: &'a dyn HirDatabase,1284 ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'a>)> {1285 self.type_of_opaque.iter().filter_map(move |(&id, ty)| {1286 let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {1287 return None;1288 };1289 Some((rpit_idx, ty.as_ref()))1290 })1291 }12921293 pub fn expr_ty<'a>(&self, id: ExprId) -> Ty<'a> {1294 self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1295 }12961297 pub fn pat_ty<'a>(&self, id: PatId) -> Ty<'a> {1298 self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1299 }13001301 pub fn expr_or_pat_ty<'a>(&self, id: ExprOrPatId) -> Ty<'a> {1302 self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())1303 }13041305 pub fn binding_ty<'a>(&self, id: BindingId) -> Ty<'a> {1306 self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1307 }13081309 /// This does not deduplicate, which means you'll get the types once per capture.1310 pub fn closure_captures_tys<'a>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'a>> {1311 self.closures_data[&closure]1312 .min_captures1313 .values()1314 .flat_map(|captures| captures.iter().map(|capture| capture.place.ty()))1315 }13161317 /// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].1318 pub fn closure_captures_captured_tys<'a>(1319 &self,1320 db: &'a dyn HirDatabase,1321 closure: ExprId,1322 ) -> impl Iterator<Item = Ty<'a>> {1323 self.closures_data[&closure]1324 .min_captures1325 .values()1326 .flat_map(|captures| captures.iter().map(|capture| capture.captured_ty(db)))1327 }13281329 pub fn is_skipped_ref_pat(&self, pat: PatId) -> bool {1330 self.skipped_ref_pats.contains(&pat)1331 }1332}13331334#[derive(Debug, Clone, Copy)]1335enum DerefPatBorrowMode {1336 Borrow(Mutability),1337 Box,1338}13391340/// The inference context contains all information needed during type inference.1341#[derive(Debug)]1342pub(crate) struct InferenceContext<'db> {1343 pub(crate) db: &'db dyn HirDatabase,1344 pub(crate) owner: InferBodyId<'db>,1345 pub(crate) store_owner: ExpressionStoreOwnerId,1346 pub(crate) generic_def: GenericDefId,1347 pub(crate) store: &'db ExpressionStore,1348 pub(crate) lowering_mode: LoweringMode,1349 /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext1350 /// and resolve the path via its methods. This will ensure proper error reporting.1351 pub(crate) resolver: Resolver<'db>,1352 target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,1353 data_layout: OnceCell<&'db TargetDataLayout>,1354 pub(crate) edition: Edition,1355 allow_using_generic_params: bool,1356 generics: OnceCell<Generics<'db>>,1357 identity_args: OnceCell<GenericArgs<'db>>,1358 pub(crate) table: unify::InferenceTable<'db>,1359 pub(crate) lang_items: &'db LangItems,1360 pub(crate) features: &'db UnstableFeatures,1361 /// The traits in scope, disregarding block modules. This is used for caching purposes.1362 traits_in_scope: FxHashSet<TraitId>,1363 pub(crate) result: InferenceResult<'db>,1364 tuple_field_accesses_rev:1365 IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,1366 /// The return type of the function being inferred, the closure or async block if we're1367 /// currently within one.1368 ///1369 /// We might consider using a nested inference context for checking1370 /// closures so we can swap all shared things out at once.1371 return_ty: Ty<'db>,1372 /// If `Some`, this stores coercion information for returned1373 /// expressions. If `None`, this is in a context where return is1374 /// inappropriate, such as a const expression.1375 return_coercion: Option<DynamicCoerceMany<'db>>,1376 /// The resume type and the yield type, respectively, of the coroutine being inferred.1377 resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,1378 diverges: Diverges,1379 breakables: Vec<BreakableContext<'db>>,1380 types: &'db crate::next_solver::DefaultAny<'db>,13811382 deferred_cast_checks: Vec<CastCheck<'db>>,13831384 /// The key is an expression defining a closure or a coroutine closure.1385 deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>,13861387 diagnostics: Diagnostics,1388 vars_emitted_type_must_be_known_for: FxHashSet<Term<'db>>,13891390 defined_anon_consts: RefCell<ThinVec<AnonConstId<'db>>>,1391}13921393#[derive(Clone, Debug)]1394struct BreakableContext<'db> {1395 /// Whether this context contains at least one break expression.1396 may_break: bool,1397 /// The coercion target of the context.1398 coerce: Option<DynamicCoerceMany<'db>>,1399 /// The optional label of the context.1400 label: Option<LabelId>,1401 kind: BreakableKind,1402}14031404#[derive(Clone, Debug)]1405enum BreakableKind {1406 Block,1407 Loop,1408 /// A border is something like an async block, closure etc. Anything that prevents1409 /// breaking/continuing through1410 Border,1411}14121413fn find_breakable(ctxs: &[BreakableContext<'_>], label: Option<LabelId>) -> Option<usize> {1414 let mut ctxs = ctxs1415 .iter()1416 .enumerate()1417 .rev()1418 .take_while(|(_, it)| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));1419 let result = match label {1420 Some(_) => ctxs.find(|(_, ctx)| ctx.label == label),1421 None => ctxs.find(|(_, ctx)| matches!(ctx.kind, BreakableKind::Loop)),1422 };1423 result.map(|(idx, _)| idx)1424}14251426fn find_continuable(ctxs: &[BreakableContext<'_>], label: Option<LabelId>) -> Option<usize> {1427 find_breakable(ctxs, label)1428 .filter(|&idx| label.is_none() || matches!(ctxs[idx].kind, BreakableKind::Loop))1429}14301431impl<'db> InferenceContext<'db> {1432 fn new(1433 db: &'db dyn HirDatabase,1434 owner: InferBodyId<'db>,1435 store_owner: ExpressionStoreOwnerId,1436 generic_def: GenericDefId,1437 store: &'db ExpressionStore,1438 resolver: Resolver<'db>,1439 allow_using_generic_params: bool,1440 lowering_mode: LoweringMode,1441 ) -> Self {1442 let trait_env = db.trait_environment(generic_def);1443 let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), owner);1444 let types = crate::next_solver::default_types();1445 InferenceContext {1446 result: InferenceResult::new(types.types.error),1447 return_ty: types.types.error, // set in collect_* calls1448 types,1449 target_features: OnceCell::new(),1450 data_layout: OnceCell::new(),1451 lang_items: table.interner().lang_items(),1452 features: resolver.top_level_def_map().features(),1453 edition: resolver.krate().data(db).edition,1454 table,1455 tuple_field_accesses_rev: Default::default(),1456 resume_yield_tys: None,1457 return_coercion: None,1458 db,1459 owner,1460 store_owner,1461 generic_def,1462 allow_using_generic_params,1463 generics: OnceCell::new(),1464 identity_args: OnceCell::new(),1465 store,1466 traits_in_scope: resolver.traits_in_scope(db),1467 resolver,1468 diverges: Diverges::Maybe,1469 breakables: Vec::new(),1470 deferred_cast_checks: Vec::new(),1471 diagnostics: Diagnostics::default(),1472 vars_emitted_type_must_be_known_for: FxHashSet::default(),1473 deferred_call_resolutions: FxHashMap::default(),1474 defined_anon_consts: RefCell::new(ThinVec::new()),1475 lowering_mode,1476 }1477 }14781479 fn merge(&mut self, other: &InferenceResult<'db>) {1480 let InferenceResult {1481 method_resolutions,1482 field_resolutions,1483 variant_resolutions,1484 assoc_resolutions,1485 tuple_field_access_types: _,1486 type_of_expr,1487 type_of_pat,1488 type_of_binding,1489 type_of_type_placeholder,1490 type_of_opaque,1491 has_errors: _,1492 diagnostics: _,1493 error_ty: _,1494 expr_adjustments,1495 pat_adjustments,1496 binding_modes,1497 skipped_ref_pats,1498 coercion_casts,1499 closures_data,1500 nodes_with_type_mismatches,1501 defined_anon_consts: _,1502 } = &mut self.result;1503 merge_hash_maps(method_resolutions, &other.method_resolutions);1504 merge_hash_maps(variant_resolutions, &other.variant_resolutions);1505 merge_hash_maps(assoc_resolutions, &other.assoc_resolutions);1506 field_resolutions.extend(other.field_resolutions.iter().map(1507 |(&field_expr, &field_resolution)| {1508 let mut field_resolution = field_resolution;1509 if let Either::Right(tuple_field) = &mut field_resolution {1510 let tys = other.tuple_field_access_type(tuple_field.tuple);1511 tuple_field.tuple =1512 TupleId(self.tuple_field_accesses_rev.insert_full(tys).0 as u32);1513 };1514 (field_expr, field_resolution)1515 },1516 ));1517 merge_arena_maps(type_of_expr, &other.type_of_expr);1518 merge_arena_maps(type_of_pat, &other.type_of_pat);1519 merge_arena_maps(type_of_binding, &other.type_of_binding);1520 merge_hash_maps(type_of_type_placeholder, &other.type_of_type_placeholder);1521 merge_hash_maps(type_of_opaque, &other.type_of_opaque);1522 merge_hash_maps(expr_adjustments, &other.expr_adjustments);1523 merge_hash_maps(pat_adjustments, &other.pat_adjustments);1524 merge_arena_maps(binding_modes, &other.binding_modes);1525 merge_hash_set(skipped_ref_pats, &other.skipped_ref_pats);1526 merge_hash_set(coercion_casts, &other.coercion_casts);1527 merge_hash_maps(closures_data, &other.closures_data);1528 if let Some(other_nodes_with_type_mismatches) = &other.nodes_with_type_mismatches {1529 merge_hash_set(1530 nodes_with_type_mismatches.get_or_insert_default(),1531 other_nodes_with_type_mismatches,1532 );1533 }1534 self.defined_anon_consts.borrow_mut().extend(other.defined_anon_consts.iter().copied());1535 self.diagnostics.extend(&other.diagnostics);15361537 fn merge_hash_set<T: Hash + Eq + Clone>(dest: &mut FxHashSet<T>, source: &FxHashSet<T>) {1538 dest.extend(source.iter().cloned());1539 }15401541 #[cfg_attr(debug_assertions, track_caller)]1542 fn merge_hash_maps<K: Hash + Eq + Clone, V: Clone + PartialEq>(1543 dest: &mut FxHashMap<K, V>,1544 source: &FxHashMap<K, V>,1545 ) {1546 if cfg!(debug_assertions) {1547 for (key, src) in source {1548 assert!(dest.get(key).is_none_or(|dst| dst == src));1549 }1550 }15511552 dest.extend(source.iter().map(|(k, v)| (k.clone(), v.clone())));1553 }15541555 #[cfg_attr(debug_assertions, track_caller)]1556 fn merge_arena_maps<K, V: Clone + PartialEq>(1557 dest: &mut ArenaMap<la_arena::Idx<K>, V>,1558 source: &ArenaMap<la_arena::Idx<K>, V>,1559 ) {1560 if cfg!(debug_assertions) {1561 for (key, src) in source.iter() {1562 assert!(dest.get(key).is_none_or(|dst| dst == src));1563 }1564 }15651566 dest.extend(source.iter().map(|(k, v)| (k, v.clone())));1567 }1568 }15691570 #[inline]1571 fn krate(&self) -> Crate {1572 self.resolver.krate()1573 }15741575 fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {1576 let (target_features, target_feature_is_safe) = self.target_features.get_or_init(|| {1577 let target_features = match self.store_owner {1578 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => {1579 TargetFeatures::from_fn(self.db, id)1580 }1581 _ => TargetFeatures::default(),1582 };1583 let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {1584 Ok(target) => crate::utils::target_feature_is_safe_in_target(target),1585 Err(_) => TargetFeatureIsSafeInTarget::No,1586 };1587 (target_features, target_feature_is_safe)1588 });1589 (target_features, *target_feature_is_safe)1590 }15911592 fn data_layout(&self) -> &'db TargetDataLayout {1593 self.data_layout.get_or_init(|| self.db.target_data_layout_or_default(self.krate()))1594 }15951596 /// How should a deref pattern find the place for its inner pattern to match on?1597 ///1598 /// In most cases, if the pattern recursively contains a `ref mut` binding, we find the inner1599 /// pattern's scrutinee by calling `DerefMut::deref_mut`, and otherwise we call `Deref::deref`.1600 /// However, for boxes we can use a built-in deref instead, which doesn't borrow the scrutinee;1601 /// in this case, we return `DerefPatBorrowMode::Box`.1602 fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: PatId) -> DerefPatBorrowMode {1603 if pointer_ty.is_box() {1604 DerefPatBorrowMode::Box1605 } else {1606 let mutability =1607 if self.pat_has_ref_mut_binding(inner) { Mutability::Mut } else { Mutability::Not };1608 DerefPatBorrowMode::Borrow(mutability)1609 }1610 }16111612 #[inline]1613 fn set_tainted_by_errors(&mut self) {1614 self.result.has_errors = true;1615 }16161617 /// Copy the inference of defined anon consts to ourselves, so that we don't need to lookup the defining1618 /// anon const when looking the type of something.1619 fn merge_anon_consts(&mut self) {1620 let mut defined_anon_consts = std::mem::take(&mut *self.defined_anon_consts.borrow_mut());1621 defined_anon_consts.retain(|&konst| {1622 if konst.loc(self.db).owner != self.store_owner {1623 // This comes from the signature, we don't define it.1624 return false;1625 }16261627 let const_infer = InferenceResult::of(self.db, konst);1628 self.merge(const_infer);1629 true1630 });1631 // Caution, other defined anon consts might have been added by `merge()`!1632 self.defined_anon_consts.borrow_mut().append(&mut defined_anon_consts);1633 }16341635 fn resolve_all(self) -> InferenceResult<'db> {1636 let InferenceContext {1637 table,1638 mut result,1639 tuple_field_accesses_rev,1640 diagnostics,1641 types,1642 vars_emitted_type_must_be_known_for,1643 ..1644 } = self;1645 let diagnostics = diagnostics.finish();1646 // Destructure every single field so whenever new fields are added to `InferenceResult` we1647 // don't forget to handle them here.1648 let InferenceResult {1649 method_resolutions,1650 field_resolutions: _,1651 variant_resolutions: _,1652 assoc_resolutions,1653 type_of_expr,1654 type_of_pat,1655 type_of_binding,1656 type_of_type_placeholder,1657 type_of_opaque,1658 skipped_ref_pats,1659 closures_data,1660 has_errors,1661 error_ty: _,1662 pat_adjustments,1663 binding_modes: _,1664 expr_adjustments,1665 tuple_field_access_types,1666 coercion_casts: _,1667 diagnostics: result_diagnostics,1668 nodes_with_type_mismatches,1669 defined_anon_consts: result_defined_anon_consts,1670 } = &mut result;16711672 *result_defined_anon_consts = self.defined_anon_consts.into_inner();1673 result_defined_anon_consts.shrink_to_fit();16741675 let mut resolver =1676 WriteBackCtxt::new(table, diagnostics, vars_emitted_type_must_be_known_for);16771678 skipped_ref_pats.shrink_to_fit();1679 for ty in type_of_expr.values_mut() {1680 resolver.resolve_completely(ty);1681 }1682 type_of_expr.shrink_to_fit();1683 for ty in type_of_pat.values_mut() {1684 resolver.resolve_completely(ty);1685 }1686 type_of_pat.shrink_to_fit();1687 for ty in type_of_binding.values_mut() {1688 resolver.resolve_completely(ty);1689 }1690 type_of_binding.shrink_to_fit();1691 for ty in type_of_type_placeholder.values_mut() {1692 resolver.resolve_completely(ty);1693 }1694 type_of_type_placeholder.shrink_to_fit();1695 type_of_opaque.shrink_to_fit();16961697 if let Some(nodes_with_type_mismatches) = nodes_with_type_mismatches {1698 *has_errors = true;1699 nodes_with_type_mismatches.shrink_to_fit();1700 }1701 for (_, subst) in method_resolutions.values_mut() {1702 resolver.resolve_completely(subst);1703 }1704 method_resolutions.shrink_to_fit();1705 for (_, subst) in assoc_resolutions.values_mut() {1706 resolver.resolve_completely(subst);1707 }1708 assoc_resolutions.shrink_to_fit();1709 for adjustment in expr_adjustments.values_mut().flatten() {1710 resolver.resolve_completely(&mut adjustment.target);1711 }1712 expr_adjustments.shrink_to_fit();1713 for adjustments in pat_adjustments.values_mut() {1714 for adjustment in &mut *adjustments {1715 resolver.resolve_completely(&mut adjustment.source);1716 }1717 adjustments.shrink_to_fit();1718 }1719 pat_adjustments.shrink_to_fit();1720 for closure_data in closures_data.values_mut() {1721 let ClosureData { min_captures, fake_reads, liberated_sig } = closure_data;1722 let dummy_place = || Place {1723 base_ty: types.types.error.store(),1724 base: closure::analysis::expr_use_visitor::PlaceBase::Rvalue,1725 projections: Vec::new(),1726 };17271728 for (place, _, sources) in fake_reads {1729 resolver.resolve_completely_with_default(place, dummy_place());1730 place.projections.shrink_to_fit();1731 for source in &mut *sources {1732 source.shrink_to_fit();1733 }1734 sources.shrink_to_fit();1735 }17361737 for min_capture in min_captures.values_mut() {1738 for captured in &mut *min_capture {1739 let CapturedPlace { place, info, mutability: _ } = captured;1740 resolver.resolve_completely_with_default(place, dummy_place());1741 let CaptureInfo { sources, capture_kind: _ } = info;1742 for source in &mut *sources {1743 source.shrink_to_fit();1744 }1745 sources.shrink_to_fit();1746 }1747 min_capture.shrink_to_fit();1748 }1749 min_captures.shrink_to_fit();17501751 resolver.resolve_completely(liberated_sig);1752 }1753 closures_data.shrink_to_fit();1754 *tuple_field_access_types = tuple_field_accesses_rev1755 .into_iter()1756 .map(|mut subst| {1757 resolver.resolve_completely(&mut subst);1758 subst.store()1759 })1760 .collect();1761 tuple_field_access_types.shrink_to_fit();17621763 let (diagnostics, resolver_has_errors) = resolver.resolve_diagnostics();1764 *result_diagnostics = diagnostics;1765 *has_errors |= resolver_has_errors;17661767 result1768 }17691770 fn collect_const_or_static(&mut self, id: ValueTyDefId) {1771 let return_ty = self.db.value_ty(id).unwrap().instantiate_identity().skip_norm_wip();1772 self.return_ty = self.process_remote_user_written_ty(return_ty);1773 }17741775 fn collect_fn(1776 &mut self,1777 func: FunctionId,1778 self_param: Option<BindingId>,1779 params: &[Param<PatId>],1780 ) {1781 let sig = self.interner().liberate_late_bound_regions(1782 func.into(),1783 self.db.callable_item_signature(func.into()).instantiate_identity().skip_norm_wip(),1784 );17851786 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`1787 // (as it's created inside the body itself, not passed in from outside).1788 let maybe_va_list =1789 if sig.fn_sig_kind.c_variadic() { self.resolve_va_list() } else { None };1790 let maybe_va_list = maybe_va_list.map(|va_list| {1791 let region = self.table.next_region_var(1792 params.last().expect("variadic function must have parameters").user_written.into(),1793 );1794 Ty::new_adt(self.interner(), va_list, GenericArgs::new_from_slice(&[region.into()]))1795 });17961797 let mut param_tys = sig.inputs().iter().copied();17981799 if let Some(self_param) = self_param1800 && let Some(ty) = param_tys.next()1801 {1802 let ty = self.process_remote_user_written_ty(ty);1803 self.write_binding_ty(self_param, ty);1804 }18051806 let mut param_tys = param_tys.chain(maybe_va_list);1807 for pat in params {1808 let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy));1809 let ty = self.process_remote_user_written_ty(ty);18101811 self.infer_top_pat(pat.formal, ty, PatOrigin::Param);1812 }18131814 self.return_ty = self.process_remote_user_written_ty(sig.output());1815 self.return_coercion = Some(CoerceMany::new(self.return_ty));1816 }18171818 #[inline]1819 pub(crate) fn interner(&self) -> DbInterner<'db> {1820 self.table.interner()1821 }18221823 #[inline]1824 pub(crate) fn infcx(&self) -> &InferCtxt<'db> {1825 &self.table.infer_ctxt1826 }18271828 /// If `ty` is an error, returns an infer var instead. Otherwise, returns it.1829 ///1830 /// "Refreshing" types like this is useful for getting better types, but it is also1831 /// very dangerous: we might create duplicate diagnostics, for example if we try1832 /// to resolve it and fail. rustc doesn't do that for this reason (and is in general1833 /// more strict with how it uses error types; an error type in inputs will almost1834 /// always cause it to infer an error type in output, while we infer some type as much1835 /// as we can).1836 ///1837 /// Unfortunately, we cannot allow ourselves to do that. Not only we more often work1838 /// with incomplete code, we also have assists, for example "Generate constant", that1839 /// will assume the inferred type is the expected type even if the expression itself1840 /// cannot be inferred. Therefore, we choose a middle ground: refresh the type,1841 /// but if we return a new var, mark it so that no diagnostics will be issued on it.1842 fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {1843 if ty.is_ty_error() {1844 let var = self.table.next_ty_var(Span::Dummy);18451846 // Suppress future errors on this var. Add more things here when we add more diagnostics.1847 self.vars_emitted_type_must_be_known_for.insert(var.into());18481849 var1850 } else {1851 ty1852 }1853 }18541855 fn infer_body(&mut self, body_expr: ExprId) {1856 match self.return_coercion {1857 Some(_) => self.infer_return(body_expr),1858 None => {1859 _ = self.infer_expr_coerce(1860 body_expr,1861 &Expectation::has_type(self.return_ty),1862 ExprIsRead::Yes,1863 )1864 }1865 }1866 }18671868 fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {1869 self.result.type_of_expr.insert(expr, ty.store());1870 }18711872 pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {1873 if adjustments.is_empty() {1874 return;1875 }1876 match self.result.expr_adjustments.entry(expr) {1877 std::collections::hash_map::Entry::Occupied(mut entry) => {1878 match (&mut entry.get_mut()[..], &adjustments[..]) {1879 (1880 [Adjustment { kind: Adjust::NeverToAny, target }],1881 [.., Adjustment { target: new_target, .. }],1882 ) => {1883 // NeverToAny coercion can target any type, so instead of adding a new1884 // adjustment on top we can change the target.1885 *target = new_target.clone();1886 }1887 _ => {1888 *entry.get_mut() = adjustments;1889 }1890 }1891 }1892 std::collections::hash_map::Entry::Vacant(entry) => {1893 entry.insert(adjustments);1894 }1895 }1896 }18971898 pub(crate) fn write_method_resolution(1899 &mut self,1900 expr: ExprId,1901 func: FunctionId,1902 subst: GenericArgs<'db>,1903 ) {1904 self.result.method_resolutions.insert(expr, (func, subst.store()));1905 }19061907 fn write_variant_resolution(&mut self, id: ExprOrPatIdPacked, variant: VariantId) {1908 self.result.variant_resolutions.insert(id, variant);1909 }19101911 fn write_assoc_resolution(1912 &mut self,1913 id: ExprOrPatIdPacked,1914 item: CandidateId,1915 subs: GenericArgs<'db>,1916 ) {1917 self.result.assoc_resolutions.insert(id, (item, subs.store()));1918 }19191920 fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {1921 self.result.type_of_pat.insert(pat, ty.store());1922 }19231924 fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {1925 self.result.type_of_binding.insert(id, ty.store());1926 }19271928 pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {1929 self.diagnostics.push(diagnostic);1930 }19311932 fn record_deferred_call_resolution(1933 &mut self,1934 closure_def_id: ExprId,1935 r: DeferredCallResolution<'db>,1936 ) {1937 self.deferred_call_resolutions.entry(closure_def_id).or_default().push(r);1938 }19391940 fn remove_deferred_call_resolutions(1941 &mut self,1942 closure_def_id: ExprId,1943 ) -> Vec<DeferredCallResolution<'db>> {1944 self.deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default()1945 }19461947 fn with_ty_lowering<R>(&mut self, f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R) -> R {1948 let mut infer_vars = InferenceTyLoweringVarsCtx {1949 table: &mut self.table,1950 type_of_type_placeholder: &mut self.result.type_of_type_placeholder,1951 };1952 let mut ctx = TyLoweringContext::new(1953 self.db,1954 &self.resolver,1955 self.store,1956 &self.diagnostics,1957 self.store_owner,1958 self.generic_def,1959 &self.generics,1960 LifetimeElisionKind::Infer,1961 self.allow_using_generic_params,1962 &mut infer_vars,1963 &self.defined_anon_consts,1964 LifetimeLoweringMode::LateParam,1965 );1966 f(&mut ctx)1967 }19681969 pub(crate) fn make_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {1970 let ty = self.with_ty_lowering(|ctx| ctx.lower_ty(type_ref));1971 self.process_user_written_ty(ty)1972 }19731974 fn generics(&self) -> &Generics<'db> {1975 self.generics.get_or_init(|| crate::generics::generics(self.db, self.generic_def))1976 }19771978 fn identity_args(&self) -> GenericArgs<'db> {1979 *self.identity_args.get_or_init(|| {1980 GenericArgs::identity_for_item(self.interner(), self.generic_def.into())1981 })1982 }19831984 pub(crate) fn create_anon_const(&mut self, expr: ExprId, expected_ty: Ty<'db>) -> Const<'db> {1985 never!(expected_ty.has_infer(), "cannot have infer vars in an anon const's ty");1986 let konst = create_anon_const(1987 self.interner(),1988 self.store_owner,1989 self.store,1990 expr,1991 &self.resolver,1992 expected_ty,1993 &|| self.generics(),1994 Some(&mut |span| self.table.next_const_var(span)),1995 self.lowering_mode,1996 (!self.allow_using_generic_params).then_some(0),1997 // The situation around body anon consts using generic params is complicated.1998 // rustc disallows them all, except for array repeat expressions. However in another place even repeat exprs1999 // are disallowed, so in practice they cause an error.2000 false,
Findings
✓ No findings reported for this file.