File is large — showing lines 1–2,000 of 2,534.
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_analysis/check/mod.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.1516mod autoderef;17mod callee;18pub(crate) mod cast;19pub(crate) mod closure;20mod coerce;21pub(crate) mod diagnostics;22mod expr;23mod fallback;24mod mutability;25mod op;26mod opaques;27mod pat;28mod path;29mod place_op;30pub(crate) mod unify;3132use std::{cell::OnceCell, convert::identity, fmt, iter, ops::Deref};3334use base_db::{Crate, FxIndexMap};35use either::Either;36use hir_def::{37 AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,38 FunctionId, GenericDefId, GenericParamId, ItemContainerId, LocalFieldId, Lookup, TraitId,39 TupleFieldId, TupleId, TypeAliasId, TypeOrConstParamId, VariantId,40 expr_store::{Body, ExpressionStore, HygieneId, RootExprOrigin, path::Path},41 hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},42 lang_item::LangItems,43 layout::Integer,44 resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},45 signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},46 type_ref::{ConstRef, LifetimeRefId, TypeRef, TypeRefId},47};48use hir_expand::{mod_path::ModPath, name::Name};49use indexmap::IndexSet;50use intern::sym;51use la_arena::ArenaMap;52use rustc_ast_ir::Mutability;53use rustc_hash::{FxHashMap, FxHashSet};54use rustc_type_ir::{55 AliasTyKind, TypeFoldable,56 inherent::{AdtDef, IntoKind, Ty as _},57};58use smallvec::SmallVec;59use span::Edition;60use stdx::never;61use thin_vec::ThinVec;6263use crate::{64 ImplTraitId, IncorrectGenericsLenKind, PathLoweringDiagnostic, TargetFeatures,65 closure_analysis::PlaceBase,66 collect_type_inference_vars,67 db::{HirDatabase, InternedOpaqueTyId},68 infer::{69 callee::DeferredCallResolution,70 closure::analysis::{71 BorrowKind,72 expr_use_visitor::{FakeReadCause, Place},73 },74 coerce::{CoerceMany, DynamicCoerceMany},75 diagnostics::{Diagnostics, InferenceTyLoweringContext as TyLoweringContext},76 expr::ExprIsRead,77 },78 lower::{79 ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,80 },81 method_resolution::{CandidateId, MethodResolutionUnstableFeatures},82 next_solver::{83 AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region,84 StoredGenericArgs, StoredTy, StoredTys, Ty, TyKind, Tys,85 abi::Safety,86 infer::{InferCtxt, ObligationInspector, traits::ObligationCause},87 },88 utils::TargetFeatureIsSafeInTarget,89};9091// This lint has a false positive here. See the link below for details.92//93// https://github.com/rust-lang/rust/issues/5741194#[allow(unreachable_pub)]95pub use coerce::could_coerce;96#[allow(unreachable_pub)]97pub use unify::{could_unify, could_unify_deeply};9899use cast::{CastCheck, CastError};100101/// The entry point of type inference.102fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {103 infer_query_with_inspect(db, def, None)104}105106pub fn infer_query_with_inspect<'db>(107 db: &'db dyn HirDatabase,108 def: DefWithBodyId,109 inspect: Option<ObligationInspector<'db>>,110) -> InferenceResult {111 let _p = tracing::info_span!("infer_query").entered();112 let resolver = def.resolver(db);113 let body = Body::of(db, def);114 let mut ctx =115 InferenceContext::new(db, ExpressionStoreOwnerId::Body(def), &body.store, resolver);116117 if let Some(inspect) = inspect {118 ctx.table.infer_ctxt.attach_obligation_inspector(inspect);119 }120121 match def {122 DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param, &body.params),123 DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),124 DefWithBodyId::StaticId(s) => ctx.collect_static(StaticSignature::of(db, s)),125 DefWithBodyId::VariantId(v) => {126 ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {127 hir_def::layout::IntegerType::Pointer(signed) => match signed {128 true => ctx.types.types.isize,129 false => ctx.types.types.usize,130 },131 hir_def::layout::IntegerType::Fixed(size, signed) => match signed {132 true => match size {133 Integer::I8 => ctx.types.types.i8,134 Integer::I16 => ctx.types.types.i16,135 Integer::I32 => ctx.types.types.i32,136 Integer::I64 => ctx.types.types.i64,137 Integer::I128 => ctx.types.types.i128,138 },139 false => match size {140 Integer::I8 => ctx.types.types.u8,141 Integer::I16 => ctx.types.types.u16,142 Integer::I32 => ctx.types.types.u32,143 Integer::I64 => ctx.types.types.u64,144 Integer::I128 => ctx.types.types.u128,145 },146 },147 };148 }149 }150151 ctx.infer_body(body.root_expr());152153 ctx.infer_mut_body(body.root_expr());154155 infer_finalize(ctx)156}157158fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {159 InferenceResult {160 has_errors: true,161 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))162 }163}164165/// Infer types for all const expressions in an item's signature.166///167/// This handles const expressions that appear in type positions within a generic168/// item's signature, such as array lengths (`[T; N]`) and const generic arguments169/// (`Foo<{ expr }>`). Each root expression is inferred independently within170/// a shared `InferenceContext`, accumulating results into a single `InferenceResult`.171fn infer_signature_query(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {172 let _p = tracing::info_span!("infer_signature_query").entered();173 let store = ExpressionStore::of(db, def.into());174 let mut roots = store.expr_roots_with_origins().peekable();175 let Some(_) = roots.peek() else {176 return InferenceResult::new(crate::next_solver::default_types(db).types.error);177 };178179 let resolver = def.resolver(db);180 let owner = ExpressionStoreOwnerId::Signature(def);181182 let mut ctx = InferenceContext::new(db, owner, store, resolver);183184 for (root_expr, origin) in roots {185 let expected = match origin {186 // Array lengths are always `usize`.187 RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),188 // Const parameter default: look up the param's declared type.189 RootExprOrigin::ConstParam(local_id) => Expectation::has_type(db.const_param_ty_ns(190 ConstParamId::from_unchecked(TypeOrConstParamId { parent: def, local_id }),191 )),192 // Path const generic args: determining the expected type requires193 // path resolution.194 // FIXME195 RootExprOrigin::GenericArgsPath => Expectation::None,196 RootExprOrigin::BodyRoot => Expectation::None,197 };198 ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);199 }200201 infer_finalize(ctx)202}203204fn infer_variant_fields_query(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {205 let _p = tracing::info_span!("infer_variant_fields_query").entered();206 let store = ExpressionStore::of(db, def.into());207 let mut roots = store.expr_roots_with_origins().peekable();208 let Some(_) = roots.peek() else {209 return InferenceResult::new(crate::next_solver::default_types(db).types.error);210 };211212 let resolver = def.resolver(db);213 let owner = ExpressionStoreOwnerId::VariantFields(def);214215 let mut ctx = InferenceContext::new(db, owner, store, resolver);216217 for (root_expr, origin) in roots {218 let expected = match origin {219 // Array lengths are always `usize`.220 RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),221 // unreachable222 RootExprOrigin::ConstParam(_) => Expectation::None,223 // Path const generic args: determining the expected type requires224 // path resolution.225 // FIXME226 RootExprOrigin::GenericArgsPath => Expectation::None,227 RootExprOrigin::BodyRoot => Expectation::None,228 };229 ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);230 }231232 infer_finalize(ctx)233}234235fn infer_signature_cycle_result(236 db: &dyn HirDatabase,237 _: salsa::Id,238 _: GenericDefId,239) -> InferenceResult {240 InferenceResult {241 has_errors: true,242 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))243 }244}245246fn infer_variant_fields_cycle_result(247 db: &dyn HirDatabase,248 _: salsa::Id,249 _: VariantId,250) -> InferenceResult {251 InferenceResult {252 has_errors: true,253 ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))254 }255}256257fn infer_finalize(mut ctx: InferenceContext<'_, '_>) -> InferenceResult {258 ctx.handle_opaque_type_uses();259260 ctx.type_inference_fallback();261262 // Comment from rustc:263 // Even though coercion casts provide type hints, we check casts after fallback for264 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.265 let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);266 for mut cast in cast_checks.into_iter() {267 if let Err(diag) = cast.check(&mut ctx) {268 ctx.diagnostics.push(diag);269 }270 }271272 ctx.table.select_obligations_where_possible();273274 // Closure and coroutine analysis may run after fallback275 // because they don't constrain other type variables.276 ctx.closure_analyze();277 assert!(ctx.deferred_call_resolutions.is_empty());278279 ctx.table.select_obligations_where_possible();280281 ctx.handle_opaque_type_uses();282283 ctx.resolve_all()284}285/// Binding modes inferred for patterns.286/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>287#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]288pub enum BindingMode {289 #[default]290 Move,291 Ref(Mutability),292}293294impl BindingMode {295 fn convert(annotation: BindingAnnotation) -> BindingMode {296 match annotation {297 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,298 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not),299 BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),300 }301 }302}303304#[derive(Debug, PartialEq, Eq, Clone, Copy)]305pub enum InferenceTyDiagnosticSource {306 /// Diagnostics that come from types in the body.307 Body,308 /// Diagnostics that come from types in fn parameters/return type, or static & const types.309 Signature,310}311312#[derive(Debug, PartialEq, Eq, Clone)]313pub enum InferenceDiagnostic {314 NoSuchField {315 field: ExprOrPatId,316 private: Option<LocalFieldId>,317 variant: VariantId,318 },319 PrivateField {320 expr: ExprId,321 field: FieldId,322 },323 PrivateAssocItem {324 id: ExprOrPatId,325 item: AssocItemId,326 },327 UnresolvedField {328 expr: ExprId,329 receiver: StoredTy,330 name: Name,331 method_with_same_name_exists: bool,332 },333 UnresolvedMethodCall {334 expr: ExprId,335 receiver: StoredTy,336 name: Name,337 /// Contains the type the field resolves to338 field_with_same_name: Option<StoredTy>,339 assoc_func_with_same_name: Option<FunctionId>,340 },341 UnresolvedAssocItem {342 id: ExprOrPatId,343 },344 UnresolvedIdent {345 id: ExprOrPatId,346 },347 // FIXME: This should be emitted in body lowering348 BreakOutsideOfLoop {349 expr: ExprId,350 is_break: bool,351 bad_value_break: bool,352 },353 MismatchedArgCount {354 call_expr: ExprId,355 expected: usize,356 found: usize,357 },358 MismatchedTupleStructPatArgCount {359 pat: ExprOrPatId,360 expected: usize,361 found: usize,362 },363 ExpectedFunction {364 call_expr: ExprId,365 found: StoredTy,366 },367 TypedHole {368 expr: ExprId,369 expected: StoredTy,370 },371 CastToUnsized {372 expr: ExprId,373 cast_ty: StoredTy,374 },375 InvalidCast {376 expr: ExprId,377 error: CastError,378 expr_ty: StoredTy,379 cast_ty: StoredTy,380 },381 TyDiagnostic {382 source: InferenceTyDiagnosticSource,383 diag: TyLoweringDiagnostic,384 },385 PathDiagnostic {386 node: ExprOrPatId,387 diag: PathLoweringDiagnostic,388 },389 MethodCallIncorrectGenericsLen {390 expr: ExprId,391 provided_count: u32,392 expected_count: u32,393 kind: IncorrectGenericsLenKind,394 def: GenericDefId,395 },396 MethodCallIncorrectGenericsOrder {397 expr: ExprId,398 param_id: GenericParamId,399 arg_idx: u32,400 /// Whether the `GenericArgs` contains a `Self` arg.401 has_self_arg: bool,402 },403}404405/// A mismatch between an expected and an inferred type.406#[derive(Clone, PartialEq, Eq, Debug, Hash)]407pub struct TypeMismatch {408 pub expected: StoredTy,409 pub actual: StoredTy,410}411412/// Represents coercing a value to a different type of value.413///414/// We transform values by following a number of `Adjust` steps in order.415/// See the documentation on variants of `Adjust` for more details.416///417/// Here are some common scenarios:418///419/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.420/// Here the pointer will be dereferenced N times (where a dereference can421/// happen to raw or borrowed pointers or any smart pointer which implements422/// Deref, including Box<_>). The types of dereferences is given by423/// `autoderefs`. It can then be auto-referenced zero or one times, indicated424/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is425/// `false`.426///427/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start428/// with a thin pointer, deref a number of times, unsize the underlying data,429/// then autoref. The 'unsize' phase may change a fixed length array to a430/// dynamically sized one, a concrete object to a trait object, or statically431/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is432/// represented by:433///434/// ```ignore435/// Deref(None) -> [i32; 4],436/// Borrow(AutoBorrow::Ref) -> &[i32; 4],437/// Unsize -> &[i32],438/// ```439///440/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.441/// E.g., `struct Foo<T> { it: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>442/// The autoderef and -ref are the same as in the above example, but the type443/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about444/// the underlying conversions from `[i32; 4]` to `[i32]`.445///446/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In447/// that case, we have the pointer we need coming in, so there are no448/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.449/// At some point, of course, `Box` should move out of the compiler, in which450/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->451/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.452#[derive(Clone, Debug, PartialEq, Eq, Hash)]453pub struct Adjustment {454 pub kind: Adjust,455 pub target: StoredTy,456}457458impl Adjustment {459 pub fn borrow<'db>(460 interner: DbInterner<'db>,461 m: Mutability,462 ty: Ty<'db>,463 lt: Region<'db>,464 ) -> Self {465 let ty = Ty::new_ref(interner, lt, ty, m);466 Adjustment {467 kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(m, AllowTwoPhase::No))),468 target: ty.store(),469 }470 }471}472473/// At least for initial deployment, we want to limit two-phase borrows to474/// only a few specific cases. Right now, those are mostly "things that desugar"475/// into method calls:476/// - using `x.some_method()` syntax, where some_method takes `&mut self`,477/// - using `Foo::some_method(&mut x, ...)` syntax,478/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).479///480/// Anything else should be rejected until generalized two-phase borrow support481/// is implemented. Right now, dataflow can't handle the general case where there482/// is more than one use of a mutable borrow, and we don't want to accept too much483/// new code via two-phase borrows, so we try to limit where we create two-phase484/// capable mutable borrows.485/// See #49434 for tracking.486#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]487pub enum AllowTwoPhase {488 // FIXME: We should use this when appropriate.489 Yes,490 No,491}492493#[derive(Clone, Debug, PartialEq, Eq, Hash)]494pub enum Adjust {495 /// Go from ! to any type.496 NeverToAny,497 /// Dereference once, producing a place.498 Deref(Option<OverloadedDeref>),499 /// Take the address and produce either a `&` or `*` pointer.500 Borrow(AutoBorrow),501 Pointer(PointerCast),502}503504/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`505/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.506/// The target type is `U` in both cases, with the region and mutability507/// being those shared by both the receiver and the returned reference.508#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]509pub struct OverloadedDeref(pub Mutability);510511#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]512pub enum AutoBorrowMutability {513 Mut { allow_two_phase_borrow: AllowTwoPhase },514 Not,515}516517impl AutoBorrowMutability {518 /// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows.519 ///520 /// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored521 pub fn new(mutbl: Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self {522 match mutbl {523 Mutability::Not => Self::Not,524 Mutability::Mut => Self::Mut { allow_two_phase_borrow },525 }526 }527}528529impl From<AutoBorrowMutability> for Mutability {530 fn from(m: AutoBorrowMutability) -> Self {531 match m {532 AutoBorrowMutability::Mut { .. } => Mutability::Mut,533 AutoBorrowMutability::Not => Mutability::Not,534 }535 }536}537538#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]539pub enum AutoBorrow {540 /// Converts from T to &T.541 Ref(AutoBorrowMutability),542 /// Converts from T to *T.543 RawPtr(Mutability),544}545546#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]547pub enum PointerCast {548 /// Go from a fn-item type to a fn-pointer type.549 ReifyFnPointer,550551 /// Go from a safe fn pointer to an unsafe fn pointer.552 UnsafeFnPointer,553554 /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.555 /// It cannot convert a closure that requires unsafe.556 ClosureFnPointer(Safety),557558 /// Go from a mut raw pointer to a const raw pointer.559 MutToConstPointer,560561 #[allow(dead_code)]562 /// Go from `*const [T; N]` to `*const T`563 ArrayToPointer,564565 /// Unsize a pointer/reference value, e.g., `&[T; n]` to566 /// `&[T]`. Note that the source could be a thin or fat pointer.567 /// This will do things like convert thin pointers to fat568 /// pointers, or convert structs containing thin pointers to569 /// structs containing fat pointers, or convert between fat570 /// pointers. We don't store the details of how the transform is571 /// done (in fact, we don't know that, because it might depend on572 /// the precise type parameters). We just store the target573 /// type. Codegen backends and miri figure out what has to be done574 /// based on the precise source/target type at hand.575 Unsize,576}577578/// The result of type inference: A mapping from expressions and patterns to types.579///580/// When you add a field that stores types (including `Substitution` and the like), don't forget581/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must582/// not appear in the final inference result.583#[derive(Clone, PartialEq, Eq, Debug)]584pub struct InferenceResult {585 /// For each method call expr, records the function it resolves to.586 method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,587 /// For each field access expr, records the field it resolves to.588 field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,589 /// For each struct literal or pattern, records the variant it resolves to.590 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,591 /// For each associated item record what it resolves to592 assoc_resolutions: FxHashMap<ExprOrPatId, (CandidateId, StoredGenericArgs)>,593 /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in594 /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of595 /// that which allows us to resolve a [`TupleFieldId`]s type.596 tuple_field_access_types: ThinVec<StoredTys>,597598 pub(crate) type_of_expr: ArenaMap<ExprId, StoredTy>,599 /// For each pattern record the type it resolves to.600 ///601 /// **Note**: When a pattern type is resolved it may still contain602 /// unresolved or missing subpatterns or subpatterns of mismatched types.603 pub(crate) type_of_pat: ArenaMap<PatId, StoredTy>,604 pub(crate) type_of_binding: ArenaMap<BindingId, StoredTy>,605 pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, StoredTy>,606 pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, StoredTy>,607608 pub(crate) type_mismatches: Option<Box<FxHashMap<ExprOrPatId, TypeMismatch>>>,609 /// Whether there are any type-mismatching errors in the result.610 // FIXME: This isn't as useful as initially thought due to us falling back placeholders to611 // `TyKind::Error`.612 // Which will then mark this field.613 pub(crate) has_errors: bool,614 /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.615 diagnostics: ThinVec<InferenceDiagnostic>,616617 /// Interned `Error` type to return references to.618 // FIXME: Remove this.619 error_ty: StoredTy,620621 pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,622 /// Stores the types which were implicitly dereferenced in pattern binding modes.623 pub(crate) pat_adjustments: FxHashMap<PatId, Vec<StoredTy>>,624 /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.625 ///626 /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an627 /// or pattern can have multiple binding modes. For example:628 /// ```629 /// fn foo(mut slice: &[u32]) -> usize {630 /// slice = match slice {631 /// [0, rest @ ..] | rest => rest,632 /// };633 /// 0634 /// }635 /// ```636 /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.637 pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,638639 pub(crate) coercion_casts: FxHashSet<ExprId>,640641 pub closures_data: FxHashMap<ExprId, ClosureData>,642}643644#[derive(Clone, PartialEq, Eq, Debug, Default)]645pub struct ClosureData {646 /// Tracks the minimum captures required for a closure;647 /// see `MinCaptureInformationMap` for more details.648 pub min_captures: RootVariableMinCaptureList,649650 /// Tracks the fake reads required for a closure and the reason for the fake read.651 /// When performing pattern matching for closures, there are times we don't end up652 /// reading places that are mentioned in a closure (because of _ patterns). However,653 /// to ensure the places are initialized, we introduce fake reads.654 /// Consider these two examples:655 /// ```ignore (discriminant matching with only wildcard arm)656 /// let x: u8;657 /// let c = || match x { _ => () };658 /// ```659 /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't660 /// want to capture it. However, we do still want an error here, because `x` should have661 /// to be initialized at the point where c is created. Therefore, we add a "fake read"662 /// instead.663 /// ```ignore (destructured assignments)664 /// let c = || {665 /// let (t1, t2) = t;666 /// }667 /// ```668 /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but669 /// we never capture `t`. This becomes an issue when we build MIR as we require670 /// information on `t` in order to create place `t.0` and `t.1`. We can solve this671 /// issue by fake reading `t`.672 pub fake_reads: Box<[(Place, FakeReadCause, SmallVec<[CaptureSourceStack; 2]>)]>,673}674675/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.676/// Used to track the minimum set of `Place`s that need to be captured to support all677/// Places captured by the closure starting at a given root variable.678///679/// This provides a convenient and quick way of checking if a variable being used within680/// a closure is a capture of a local variable.681pub(crate) type RootVariableMinCaptureList = FxIndexMap<BindingId, MinCaptureList>;682683/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.684pub(crate) type MinCaptureList = Vec<CapturedPlace>;685686/// A composite describing a `Place` that is captured by a closure.687#[derive(Eq, PartialEq, Clone, Debug, Hash)]688pub struct CapturedPlace {689 /// The `Place` that is captured.690 pub place: Place,691692 /// `CaptureKind` and expression(s) that resulted in such capture of `place`.693 pub info: CaptureInfo,694695 /// Represents if `place` can be mutated or not.696 pub mutability: Mutability,697}698699impl CapturedPlace {700 pub fn is_by_ref(&self) -> bool {701 match self.info.capture_kind {702 UpvarCapture::ByValue | UpvarCapture::ByUse => false,703 UpvarCapture::ByRef(..) => true,704 }705 }706707 pub fn captured_local(&self) -> BindingId {708 match self.place.base {709 PlaceBase::Upvar { var_id: local, .. } | PlaceBase::Local(local) => local,710 PlaceBase::Rvalue | PlaceBase::StaticItem => {711 unreachable!("only locals can be captured")712 }713 }714 }715716 /// The type of the capture stored in the closure, which is different from the type of the captured place717 /// if we capture by reference.718 pub fn captured_ty<'db>(&self, db: &'db dyn HirDatabase) -> Ty<'db> {719 let place_ty = self.place.ty();720 let make_ref = |mutbl| {721 let interner = DbInterner::new_no_crate(db);722 let region = Region::new_erased(interner);723 Ty::new_ref(interner, region, place_ty, mutbl)724 };725 match self.info.capture_kind {726 UpvarCapture::ByUse | UpvarCapture::ByValue => place_ty,727 UpvarCapture::ByRef(kind) => make_ref(kind.to_mutbl_lossy()),728 }729 }730}731732#[derive(Clone)]733pub struct CaptureSourceStack(CaptureSourceStackRepr);734735#[derive(Clone)]736enum CaptureSourceStackRepr {737 One(ExprOrPatId),738 Two([ExprOrPatId; 2]),739 Many(ThinVec<ExprOrPatId>),740}741742impl PartialEq for CaptureSourceStack {743 fn eq(&self, other: &Self) -> bool {744 **self == **other745 }746}747748impl Eq for CaptureSourceStack {}749750impl std::hash::Hash for CaptureSourceStack {751 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {752 (**self).hash(state);753 }754}755756const _: () = assert!(size_of::<CaptureSourceStack>() == 16);757758impl Deref for CaptureSourceStack {759 type Target = [ExprOrPatId];760761 #[inline]762 fn deref(&self) -> &Self::Target {763 match &self.0 {764 CaptureSourceStackRepr::One(it) => std::slice::from_ref(it),765 CaptureSourceStackRepr::Two(it) => it,766 CaptureSourceStackRepr::Many(it) => it,767 }768 }769}770771impl fmt::Debug for CaptureSourceStack {772 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {773 f.debug_tuple("CaptureSourceStack").field(&&**self).finish()774 }775}776777impl CaptureSourceStack {778 #[inline]779 pub fn len(&self) -> usize {780 match &self.0 {781 CaptureSourceStackRepr::One(_) => 1,782 CaptureSourceStackRepr::Two(_) => 2,783 CaptureSourceStackRepr::Many(it) => it.len(),784 }785 }786787 #[inline]788 pub(crate) fn from_single(id: ExprOrPatId) -> Self {789 Self(CaptureSourceStackRepr::One(id))790 }791792 #[inline]793 pub fn final_source(&self) -> ExprOrPatId {794 *self.last().expect("should always have a final source")795 }796797 pub fn push(&mut self, new_id: ExprOrPatId) {798 match &mut self.0 {799 CaptureSourceStackRepr::One(old_id) => {800 self.0 = CaptureSourceStackRepr::Two([*old_id, new_id])801 }802 CaptureSourceStackRepr::Two([old_id1, old_id2]) => {803 self.0 = CaptureSourceStackRepr::Many(ThinVec::from([*old_id1, *old_id2, new_id]));804 }805 CaptureSourceStackRepr::Many(old_ids) => old_ids.push(new_id),806 }807 }808809 pub fn truncate(&mut self, new_len: usize) {810 debug_assert!(new_len > 0);811 match &mut self.0 {812 CaptureSourceStackRepr::One(_) => {}813 CaptureSourceStackRepr::Two([first, _]) => {814 if new_len == 1 {815 self.0 = CaptureSourceStackRepr::One(*first)816 }817 }818 CaptureSourceStackRepr::Many(ids) => ids.truncate(new_len),819 }820 }821822 pub fn shrink_to_fit(&mut self) {823 match &mut self.0 {824 CaptureSourceStackRepr::One(_) | CaptureSourceStackRepr::Two(_) => {}825 CaptureSourceStackRepr::Many(ids) => match **ids {826 [one] => self.0 = CaptureSourceStackRepr::One(one),827 [first, second] => self.0 = CaptureSourceStackRepr::Two([first, second]),828 _ => ids.shrink_to_fit(),829 },830 }831 }832}833834/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)835/// for a particular capture as well as identifying the part of the source code836/// that triggered this capture to occur.837#[derive(Eq, PartialEq, Clone, Debug, Hash)]838pub struct CaptureInfo {839 pub sources: SmallVec<[CaptureSourceStack; 2]>,840841 /// Capture mode that was selected842 pub capture_kind: UpvarCapture,843}844845/// Information describing the capture of an upvar. This is computed846/// during `typeck`, specifically by `regionck`.847#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash)]848pub enum UpvarCapture {849 /// Upvar is captured by value. This is always true when the850 /// closure is labeled `move`, but can also be true in other cases851 /// depending on inference.852 ByValue,853854 /// Upvar is captured by use. This is true when the closure is labeled `use`.855 ByUse,856857 /// Upvar is captured by reference.858 ByRef(BorrowKind),859}860861#[salsa::tracked]862impl InferenceResult {863 #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]864 fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {865 infer_query(db, def)866 }867868 /// Infer types for all const expressions in an item's signature.869 ///870 /// Returns an `InferenceResult` containing type information for array lengths,871 /// const generic arguments, and other const expressions appearing in type872 /// positions within the item's signature.873 #[salsa::tracked(returns(ref), cycle_result = infer_signature_cycle_result)]874 fn for_signature(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {875 infer_signature_query(db, def)876 }877878 #[salsa::tracked(returns(ref), cycle_result = infer_variant_fields_cycle_result)]879 fn for_variant_fields(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {880 infer_variant_fields_query(db, def)881 }882}883884impl InferenceResult {885 pub fn of(db: &dyn HirDatabase, def: impl Into<ExpressionStoreOwnerId>) -> &InferenceResult {886 match def.into() {887 ExpressionStoreOwnerId::Signature(generic_def_id) => {888 Self::for_signature(db, generic_def_id)889 }890 ExpressionStoreOwnerId::Body(def_with_body_id) => Self::for_body(db, def_with_body_id),891 ExpressionStoreOwnerId::VariantFields(variant_id) => {892 Self::for_variant_fields(db, variant_id)893 }894 }895 }896897 fn new(error_ty: Ty<'_>) -> Self {898 Self {899 method_resolutions: Default::default(),900 field_resolutions: Default::default(),901 variant_resolutions: Default::default(),902 assoc_resolutions: Default::default(),903 tuple_field_access_types: Default::default(),904 diagnostics: Default::default(),905 type_of_expr: Default::default(),906 type_of_pat: Default::default(),907 type_of_binding: Default::default(),908 type_of_type_placeholder: Default::default(),909 type_of_opaque: Default::default(),910 type_mismatches: Default::default(),911 has_errors: Default::default(),912 error_ty: error_ty.store(),913 pat_adjustments: Default::default(),914 binding_modes: Default::default(),915 expr_adjustments: Default::default(),916 coercion_casts: Default::default(),917 closures_data: Default::default(),918 }919 }920921 pub fn method_resolution<'db>(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {922 self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))923 }924 pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {925 self.field_resolutions.get(&expr).copied()926 }927 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {928 self.variant_resolutions.get(&id.into()).copied()929 }930 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {931 self.variant_resolutions.get(&id.into()).copied()932 }933 pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {934 match id {935 ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),936 ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),937 }938 }939 pub fn assoc_resolutions_for_expr<'db>(940 &self,941 id: ExprId,942 ) -> Option<(CandidateId, GenericArgs<'db>)> {943 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))944 }945 pub fn assoc_resolutions_for_pat<'db>(946 &self,947 id: PatId,948 ) -> Option<(CandidateId, GenericArgs<'db>)> {949 self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))950 }951 pub fn assoc_resolutions_for_expr_or_pat<'db>(952 &self,953 id: ExprOrPatId,954 ) -> Option<(CandidateId, GenericArgs<'db>)> {955 match id {956 ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),957 ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),958 }959 }960 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {961 self.type_mismatches.as_deref()?.get(&expr.into())962 }963 pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {964 self.type_mismatches.as_deref()?.get(&pat.into())965 }966 pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {967 self.type_mismatches968 .as_deref()969 .into_iter()970 .flatten()971 .map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))972 }973 pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {974 self.type_mismatches.as_deref().into_iter().flatten().filter_map(975 |(expr_or_pat, mismatch)| match *expr_or_pat {976 ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),977 _ => None,978 },979 )980 }981 pub fn placeholder_types<'db>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'db>)> {982 self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref()))983 }984 pub fn type_of_type_placeholder<'db>(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {985 self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())986 }987 pub fn type_of_expr_or_pat<'db>(&self, id: ExprOrPatId) -> Option<Ty<'db>> {988 match id {989 ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),990 ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),991 }992 }993 pub fn type_of_expr_with_adjust<'db>(&self, id: ExprId) -> Option<Ty<'db>> {994 match self.expr_adjustments.get(&id).and_then(|adjustments| {995 adjustments.iter().rfind(|adj| {996 // https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L140997 !matches!(998 adj,999 Adjustment {1000 kind: Adjust::NeverToAny,1001 target,1002 } if target.as_ref().is_never()1003 )1004 })1005 }) {1006 Some(adjustment) => Some(adjustment.target.as_ref()),1007 None => self.type_of_expr.get(id).map(|it| it.as_ref()),1008 }1009 }1010 pub fn type_of_pat_with_adjust<'db>(&self, id: PatId) -> Option<Ty<'db>> {1011 match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {1012 Some(adjusted) => Some(adjusted.as_ref()),1013 None => self.type_of_pat.get(id).map(|it| it.as_ref()),1014 }1015 }1016 pub fn is_erroneous(&self) -> bool {1017 self.has_errors && self.type_of_expr.iter().count() == 01018 }10191020 pub fn diagnostics(&self) -> &[InferenceDiagnostic] {1021 &self.diagnostics1022 }10231024 pub fn tuple_field_access_type<'db>(&self, id: TupleId) -> Tys<'db> {1025 self.tuple_field_access_types[id.0 as usize].as_ref()1026 }10271028 pub fn pat_adjustment(&self, id: PatId) -> Option<&[StoredTy]> {1029 self.pat_adjustments.get(&id).map(|it| &**it)1030 }10311032 pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {1033 self.expr_adjustments.get(&id).map(|it| &**it)1034 }10351036 pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {1037 self.binding_modes.get(id).copied()1038 }10391040 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1041 pub fn expression_types<'db>(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {1042 self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))1043 }10441045 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1046 pub fn pattern_types<'db>(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {1047 self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))1048 }10491050 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1051 pub fn binding_types<'db>(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {1052 self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))1053 }10541055 // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1056 pub fn return_position_impl_trait_types<'db>(1057 &'db self,1058 db: &'db dyn HirDatabase,1059 ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'db>)> {1060 self.type_of_opaque.iter().filter_map(move |(&id, ty)| {1061 let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {1062 return None;1063 };1064 Some((rpit_idx, ty.as_ref()))1065 })1066 }10671068 pub fn expr_ty<'db>(&self, id: ExprId) -> Ty<'db> {1069 self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1070 }10711072 pub fn pat_ty<'db>(&self, id: PatId) -> Ty<'db> {1073 self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1074 }10751076 pub fn expr_or_pat_ty<'db>(&self, id: ExprOrPatId) -> Ty<'db> {1077 self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())1078 }10791080 pub fn binding_ty<'db>(&self, id: BindingId) -> Ty<'db> {1081 self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1082 }10831084 /// This does not deduplicate, which means you'll get the types once per capture.1085 pub fn closure_captures_tys<'db>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'db>> {1086 self.closures_data[&closure]1087 .min_captures1088 .values()1089 .flat_map(|captures| captures.iter().map(|capture| capture.place.ty()))1090 }10911092 /// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].1093 pub fn closure_captures_captured_tys<'db>(1094 &self,1095 db: &'db dyn HirDatabase,1096 closure: ExprId,1097 ) -> impl Iterator<Item = Ty<'db>> {1098 self.closures_data[&closure]1099 .min_captures1100 .values()1101 .flat_map(|captures| captures.iter().map(|capture| capture.captured_ty(db)))1102 }1103}11041105/// The inference context contains all information needed during type inference.1106#[derive(Clone, Debug)]1107pub(crate) struct InferenceContext<'body, 'db> {1108 pub(crate) db: &'db dyn HirDatabase,1109 pub(crate) owner: ExpressionStoreOwnerId,1110 pub(crate) store: &'body ExpressionStore,1111 /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext1112 /// and resolve the path via its methods. This will ensure proper error reporting.1113 pub(crate) resolver: Resolver<'db>,1114 target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,1115 pub(crate) unstable_features: MethodResolutionUnstableFeatures,1116 pub(crate) edition: Edition,1117 pub(crate) generic_def: GenericDefId,1118 pub(crate) table: unify::InferenceTable<'db>,1119 pub(crate) lang_items: &'db LangItems,1120 /// The traits in scope, disregarding block modules. This is used for caching purposes.1121 traits_in_scope: FxHashSet<TraitId>,1122 pub(crate) result: InferenceResult,1123 tuple_field_accesses_rev:1124 IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,1125 /// The return type of the function being inferred, the closure or async block if we're1126 /// currently within one.1127 ///1128 /// We might consider using a nested inference context for checking1129 /// closures so we can swap all shared things out at once.1130 return_ty: Ty<'db>,1131 /// If `Some`, this stores coercion information for returned1132 /// expressions. If `None`, this is in a context where return is1133 /// inappropriate, such as a const expression.1134 return_coercion: Option<DynamicCoerceMany<'db>>,1135 /// The resume type and the yield type, respectively, of the coroutine being inferred.1136 resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,1137 diverges: Diverges,1138 breakables: Vec<BreakableContext<'db>>,1139 types: &'db crate::next_solver::DefaultAny<'db>,11401141 /// Whether we are inside the pattern of a destructuring assignment.1142 inside_assignment: bool,11431144 deferred_cast_checks: Vec<CastCheck<'db>>,11451146 /// The key is an expression defining a closure or a coroutine closure.1147 deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>,11481149 diagnostics: Diagnostics,1150}11511152#[derive(Clone, Debug)]1153struct BreakableContext<'db> {1154 /// Whether this context contains at least one break expression.1155 may_break: bool,1156 /// The coercion target of the context.1157 coerce: Option<DynamicCoerceMany<'db>>,1158 /// The optional label of the context.1159 label: Option<LabelId>,1160 kind: BreakableKind,1161}11621163#[derive(Clone, Debug)]1164enum BreakableKind {1165 Block,1166 Loop,1167 /// A border is something like an async block, closure etc. Anything that prevents1168 /// breaking/continuing through1169 Border,1170}11711172fn find_breakable<'a, 'db>(1173 ctxs: &'a mut [BreakableContext<'db>],1174 label: Option<LabelId>,1175) -> Option<&'a mut BreakableContext<'db>> {1176 let mut ctxs = ctxs1177 .iter_mut()1178 .rev()1179 .take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));1180 match label {1181 Some(_) => ctxs.find(|ctx| ctx.label == label),1182 None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),1183 }1184}11851186fn find_continuable<'a, 'db>(1187 ctxs: &'a mut [BreakableContext<'db>],1188 label: Option<LabelId>,1189) -> Option<&'a mut BreakableContext<'db>> {1190 match label {1191 Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),1192 None => find_breakable(ctxs, label),1193 }1194}11951196impl<'body, 'db> InferenceContext<'body, 'db> {1197 fn new(1198 db: &'db dyn HirDatabase,1199 owner: ExpressionStoreOwnerId,1200 store: &'body ExpressionStore,1201 resolver: Resolver<'db>,1202 ) -> Self {1203 let trait_env = match owner {1204 ExpressionStoreOwnerId::Signature(generic_def_id) => {1205 db.trait_environment(ExpressionStoreOwnerId::from(generic_def_id))1206 }1207 ExpressionStoreOwnerId::Body(def_with_body_id) => {1208 db.trait_environment(ExpressionStoreOwnerId::Body(def_with_body_id))1209 }1210 ExpressionStoreOwnerId::VariantFields(variant_id) => {1211 db.trait_environment(ExpressionStoreOwnerId::VariantFields(variant_id))1212 }1213 };1214 let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));1215 let types = crate::next_solver::default_types(db);1216 InferenceContext {1217 result: InferenceResult::new(types.types.error),1218 return_ty: types.types.error, // set in collect_* calls1219 types,1220 target_features: OnceCell::new(),1221 unstable_features: MethodResolutionUnstableFeatures::from_def_map(1222 resolver.top_level_def_map(),1223 ),1224 lang_items: table.interner().lang_items(),1225 edition: resolver.krate().data(db).edition,1226 table,1227 tuple_field_accesses_rev: Default::default(),1228 resume_yield_tys: None,1229 return_coercion: None,1230 db,1231 owner,1232 generic_def: owner.generic_def(db),1233 store,1234 traits_in_scope: resolver.traits_in_scope(db),1235 resolver,1236 diverges: Diverges::Maybe,1237 breakables: Vec::new(),1238 deferred_cast_checks: Vec::new(),1239 inside_assignment: false,1240 diagnostics: Diagnostics::default(),1241 deferred_call_resolutions: FxHashMap::default(),1242 }1243 }12441245 #[inline]1246 fn krate(&self) -> Crate {1247 self.resolver.krate()1248 }12491250 fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {1251 let (target_features, target_feature_is_safe) = self.target_features.get_or_init(|| {1252 let target_features = match self.owner {1253 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => {1254 TargetFeatures::from_fn(self.db, id)1255 }1256 _ => TargetFeatures::default(),1257 };1258 let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {1259 Ok(target) => crate::utils::target_feature_is_safe_in_target(target),1260 Err(_) => TargetFeatureIsSafeInTarget::No,1261 };1262 (target_features, target_feature_is_safe)1263 });1264 (target_features, *target_feature_is_safe)1265 }12661267 #[inline]1268 fn set_tainted_by_errors(&mut self) {1269 self.result.has_errors = true;1270 }12711272 /// Clones `self` and calls `resolve_all()` on it.1273 // FIXME: Remove this.1274 pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult {1275 let mut ctx = self.clone();12761277 ctx.type_inference_fallback();12781279 // Comment from rustc:1280 // Even though coercion casts provide type hints, we check casts after fallback for1281 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.1282 let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);1283 for mut cast in cast_checks.into_iter() {1284 if let Err(diag) = cast.check(&mut ctx) {1285 ctx.diagnostics.push(diag);1286 }1287 }12881289 ctx.table.select_obligations_where_possible();12901291 ctx.resolve_all()1292 }12931294 // FIXME: This function should be private in module. It is currently only used in the consteval, since we need1295 // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you1296 // used this function for another workaround, mention it here. If you really need this function and believe that1297 // there is no problem in it being `pub(crate)`, remove this comment.1298 fn resolve_all(self) -> InferenceResult {1299 let InferenceContext {1300 mut table,1301 mut result,1302 tuple_field_accesses_rev,1303 diagnostics,1304 types,1305 ..1306 } = self;1307 let mut diagnostics = diagnostics.finish();1308 // Destructure every single field so whenever new fields are added to `InferenceResult` we1309 // don't forget to handle them here.1310 let InferenceResult {1311 method_resolutions,1312 field_resolutions: _,1313 variant_resolutions: _,1314 assoc_resolutions,1315 type_of_expr,1316 type_of_pat,1317 type_of_binding,1318 type_of_type_placeholder,1319 type_of_opaque,1320 type_mismatches,1321 closures_data,1322 has_errors,1323 error_ty: _,1324 pat_adjustments,1325 binding_modes: _,1326 expr_adjustments,1327 tuple_field_access_types: _,1328 coercion_casts: _,1329 diagnostics: _,1330 } = &mut result;13311332 for ty in type_of_expr.values_mut() {1333 *ty = table.resolve_completely(ty.as_ref()).store();1334 *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1335 }1336 type_of_expr.shrink_to_fit();1337 for ty in type_of_pat.values_mut() {1338 *ty = table.resolve_completely(ty.as_ref()).store();1339 *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1340 }1341 type_of_pat.shrink_to_fit();1342 for ty in type_of_binding.values_mut() {1343 *ty = table.resolve_completely(ty.as_ref()).store();1344 *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1345 }1346 type_of_binding.shrink_to_fit();1347 for ty in type_of_type_placeholder.values_mut() {1348 *ty = table.resolve_completely(ty.as_ref()).store();1349 *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1350 }1351 type_of_type_placeholder.shrink_to_fit();1352 type_of_opaque.shrink_to_fit();13531354 if let Some(type_mismatches) = type_mismatches {1355 *has_errors = true;1356 for mismatch in type_mismatches.values_mut() {1357 mismatch.expected = table.resolve_completely(mismatch.expected.as_ref()).store();1358 mismatch.actual = table.resolve_completely(mismatch.actual.as_ref()).store();1359 }1360 type_mismatches.shrink_to_fit();1361 }1362 diagnostics.retain_mut(|diagnostic| {1363 use InferenceDiagnostic::*;1364 match diagnostic {1365 ExpectedFunction { found: ty, .. }1366 | UnresolvedField { receiver: ty, .. }1367 | UnresolvedMethodCall { receiver: ty, .. } => {1368 *ty = table.resolve_completely(ty.as_ref()).store();1369 // FIXME: Remove this when we are on par with rustc in terms of inference1370 if ty.as_ref().references_non_lt_error() {1371 return false;1372 }13731374 if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic1375 && let Some(ty) = field_with_same_name1376 {1377 *ty = table.resolve_completely(ty.as_ref()).store();1378 if ty.as_ref().references_non_lt_error() {1379 *field_with_same_name = None;1380 }1381 }1382 }1383 TypedHole { expected: ty, .. } => {1384 *ty = table.resolve_completely(ty.as_ref()).store();1385 }1386 _ => (),1387 }1388 true1389 });1390 diagnostics.shrink_to_fit();1391 for (_, subst) in method_resolutions.values_mut() {1392 *subst = table.resolve_completely(subst.as_ref()).store();1393 *has_errors =1394 *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());1395 }1396 method_resolutions.shrink_to_fit();1397 for (_, subst) in assoc_resolutions.values_mut() {1398 *subst = table.resolve_completely(subst.as_ref()).store();1399 *has_errors =1400 *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());1401 }1402 assoc_resolutions.shrink_to_fit();1403 for adjustment in expr_adjustments.values_mut().flatten() {1404 adjustment.target = table.resolve_completely(adjustment.target.as_ref()).store();1405 *has_errors = *has_errors || adjustment.target.as_ref().references_non_lt_error();1406 }1407 expr_adjustments.shrink_to_fit();1408 for adjustment in pat_adjustments.values_mut().flatten() {1409 *adjustment = table.resolve_completely(adjustment.as_ref()).store();1410 *has_errors = *has_errors || adjustment.as_ref().references_non_lt_error();1411 }1412 pat_adjustments.shrink_to_fit();1413 for closure_data in closures_data.values_mut() {1414 let ClosureData { min_captures, fake_reads } = closure_data;1415 let dummy_place = || Place {1416 base_ty: types.types.error.store(),1417 base: closure::analysis::expr_use_visitor::PlaceBase::Rvalue,1418 projections: Vec::new(),1419 };14201421 for (place, _, sources) in fake_reads {1422 *place = table.resolve_completely(std::mem::replace(place, dummy_place()));1423 place.projections.shrink_to_fit();1424 for source in &mut *sources {1425 source.shrink_to_fit();1426 }1427 sources.shrink_to_fit();1428 }14291430 for min_capture in min_captures.values_mut() {1431 for captured in &mut *min_capture {1432 let CapturedPlace { place, info, mutability: _ } = captured;1433 *place = table.resolve_completely(std::mem::replace(place, dummy_place()));1434 let CaptureInfo { sources, capture_kind: _ } = info;1435 for source in &mut *sources {1436 source.shrink_to_fit();1437 }1438 sources.shrink_to_fit();1439 }1440 min_capture.shrink_to_fit();1441 }1442 min_captures.shrink_to_fit();1443 }1444 closures_data.shrink_to_fit();1445 result.tuple_field_access_types = tuple_field_accesses_rev1446 .into_iter()1447 .map(|subst| table.resolve_completely(subst).store())1448 .inspect(|subst| {1449 *has_errors =1450 *has_errors || subst.as_ref().iter().any(|ty| ty.references_non_lt_error());1451 })1452 .collect();1453 result.tuple_field_access_types.shrink_to_fit();14541455 result.diagnostics = diagnostics;14561457 result1458 }14591460 fn collect_const(&mut self, id: ConstId, data: &ConstSignature) {1461 let return_ty = self.make_ty(1462 data.type_ref,1463 &data.store,1464 InferenceTyDiagnosticSource::Signature,1465 LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container),1466 );14671468 self.return_ty = return_ty;1469 }14701471 fn collect_static(&mut self, data: &StaticSignature) {1472 let return_ty = self.make_ty(1473 data.type_ref,1474 &data.store,1475 InferenceTyDiagnosticSource::Signature,1476 LifetimeElisionKind::Elided(self.types.regions.statik),1477 );14781479 self.return_ty = return_ty;1480 }14811482 fn collect_fn(&mut self, func: FunctionId, self_param: Option<BindingId>, params: &[PatId]) {1483 let data = FunctionSignature::of(self.db, func);1484 let mut param_tys = self.with_ty_lowering(1485 &data.store,1486 InferenceTyDiagnosticSource::Signature,1487 LifetimeElisionKind::for_fn_params(data),1488 |ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(),1489 );14901491 // Check if function contains a va_list, if it does then we append it to the parameter types1492 // that are collected from the function data1493 if data.is_varargs() {1494 let va_list_ty = match self.resolve_va_list() {1495 Some(va_list) => Ty::new_adt(1496 self.interner(),1497 va_list,1498 GenericArgs::for_item_with_defaults(1499 self.interner(),1500 va_list.into(),1501 |_, id, _| self.table.next_var_for_param(id),1502 ),1503 ),1504 None => self.err_ty(),1505 };15061507 param_tys.push(va_list_ty);1508 }1509 let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var()));1510 if let Some(self_param) = self_param1511 && let Some(ty) = param_tys.next()1512 {1513 let ty = self.process_user_written_ty(ty);1514 self.write_binding_ty(self_param, ty);1515 }1516 for (ty, pat) in param_tys.zip(params) {1517 let ty = self.process_user_written_ty(ty);15181519 self.infer_top_pat(*pat, ty, None);1520 }1521 self.return_ty = match data.ret_type {1522 Some(return_ty) => {1523 let return_ty = self.with_ty_lowering(1524 &data.store,1525 InferenceTyDiagnosticSource::Signature,1526 LifetimeElisionKind::for_fn_ret(self.interner()),1527 |ctx| {1528 ctx.impl_trait_mode(ImplTraitLoweringMode::Opaque);1529 ctx.lower_ty(return_ty)1530 },1531 );1532 self.process_user_written_ty(return_ty)1533 }1534 None => self.types.types.unit,1535 };15361537 self.return_coercion = Some(CoerceMany::new(self.return_ty));1538 }15391540 #[inline]1541 pub(crate) fn interner(&self) -> DbInterner<'db> {1542 self.table.interner()1543 }15441545 #[inline]1546 pub(crate) fn infcx(&self) -> &InferCtxt<'db> {1547 &self.table.infer_ctxt1548 }15491550 fn infer_body(&mut self, body_expr: ExprId) {1551 match self.return_coercion {1552 Some(_) => self.infer_return(body_expr),1553 None => {1554 _ = self.infer_expr_coerce(1555 body_expr,1556 &Expectation::has_type(self.return_ty),1557 ExprIsRead::Yes,1558 )1559 }1560 }1561 }15621563 fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {1564 self.result.type_of_expr.insert(expr, ty.store());1565 }15661567 pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {1568 if adjustments.is_empty() {1569 return;1570 }1571 match self.result.expr_adjustments.entry(expr) {1572 std::collections::hash_map::Entry::Occupied(mut entry) => {1573 match (&mut entry.get_mut()[..], &adjustments[..]) {1574 (1575 [Adjustment { kind: Adjust::NeverToAny, target }],1576 [.., Adjustment { target: new_target, .. }],1577 ) => {1578 // NeverToAny coercion can target any type, so instead of adding a new1579 // adjustment on top we can change the target.1580 *target = new_target.clone();1581 }1582 _ => {1583 *entry.get_mut() = adjustments;1584 }1585 }1586 }1587 std::collections::hash_map::Entry::Vacant(entry) => {1588 entry.insert(adjustments);1589 }1590 }1591 }15921593 fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[StoredTy]>) {1594 if adjustments.is_empty() {1595 return;1596 }1597 self.result.pat_adjustments.entry(pat).or_default().extend(adjustments);1598 }15991600 pub(crate) fn write_method_resolution(1601 &mut self,1602 expr: ExprId,1603 func: FunctionId,1604 subst: GenericArgs<'db>,1605 ) {1606 self.result.method_resolutions.insert(expr, (func, subst.store()));1607 }16081609 fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {1610 self.result.variant_resolutions.insert(id, variant);1611 }16121613 fn write_assoc_resolution(1614 &mut self,1615 id: ExprOrPatId,1616 item: CandidateId,1617 subs: GenericArgs<'db>,1618 ) {1619 self.result.assoc_resolutions.insert(id, (item, subs.store()));1620 }16211622 fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {1623 self.result.type_of_pat.insert(pat, ty.store());1624 }16251626 fn write_type_placeholder_ty(&mut self, type_ref: TypeRefId, ty: Ty<'db>) {1627 self.result.type_of_type_placeholder.insert(type_ref, ty.store());1628 }16291630 fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {1631 self.result.type_of_binding.insert(id, ty.store());1632 }16331634 pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {1635 self.diagnostics.push(diagnostic);1636 }16371638 fn record_deferred_call_resolution(1639 &mut self,1640 closure_def_id: ExprId,1641 r: DeferredCallResolution<'db>,1642 ) {1643 self.deferred_call_resolutions.entry(closure_def_id).or_default().push(r);1644 }16451646 fn remove_deferred_call_resolutions(1647 &mut self,1648 closure_def_id: ExprId,1649 ) -> Vec<DeferredCallResolution<'db>> {1650 self.deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default()1651 }16521653 fn with_ty_lowering<R>(1654 &mut self,1655 store: &ExpressionStore,1656 types_source: InferenceTyDiagnosticSource,1657 lifetime_elision: LifetimeElisionKind<'db>,1658 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,1659 ) -> R {1660 let mut ctx = TyLoweringContext::new(1661 self.db,1662 &self.resolver,1663 store,1664 &self.diagnostics,1665 types_source,1666 self.generic_def,1667 lifetime_elision,1668 );1669 f(&mut ctx)1670 }16711672 fn with_body_ty_lowering<R>(1673 &mut self,1674 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,1675 ) -> R {1676 self.with_ty_lowering(1677 self.store,1678 InferenceTyDiagnosticSource::Body,1679 LifetimeElisionKind::Infer,1680 f,1681 )1682 }16831684 fn make_ty(1685 &mut self,1686 type_ref: TypeRefId,1687 store: &ExpressionStore,1688 type_source: InferenceTyDiagnosticSource,1689 lifetime_elision: LifetimeElisionKind<'db>,1690 ) -> Ty<'db> {1691 let ty = self1692 .with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref));1693 let ty = self.process_user_written_ty(ty);16941695 // Record the association from placeholders' TypeRefId to type variables.1696 // We only record them if their number matches. This assumes TypeRef::walk and TypeVisitable process the items in the same order.1697 let type_variables = collect_type_inference_vars(&ty);1698 let mut placeholder_ids = vec![];1699 TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {1700 if matches!(type_ref, TypeRef::Placeholder) {1701 placeholder_ids.push(type_ref_id);1702 }1703 });17041705 if placeholder_ids.len() == type_variables.len() {1706 for (placeholder_id, type_variable) in placeholder_ids.into_iter().zip(type_variables) {1707 self.write_type_placeholder_ty(placeholder_id, type_variable);1708 }1709 }17101711 ty1712 }17131714 pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {1715 self.make_ty(1716 type_ref,1717 self.store,1718 InferenceTyDiagnosticSource::Body,1719 LifetimeElisionKind::Infer,1720 )1721 }17221723 pub(crate) fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty<'db>) -> Const<'db> {1724 let const_ = self.with_ty_lowering(1725 self.store,1726 InferenceTyDiagnosticSource::Body,1727 LifetimeElisionKind::Infer,1728 |ctx| ctx.lower_const(const_ref, ty),1729 );1730 self.insert_type_vars(const_)1731 }17321733 pub(crate) fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> {1734 let const_ = self.with_ty_lowering(1735 self.store,1736 InferenceTyDiagnosticSource::Body,1737 LifetimeElisionKind::Infer,1738 |ctx| ctx.lower_path_as_const(path, ty),1739 );1740 self.insert_type_vars(const_)1741 }17421743 fn err_ty(&self) -> Ty<'db> {1744 self.types.types.error1745 }17461747 pub(crate) fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> {1748 let lt = self.with_ty_lowering(1749 self.store,1750 InferenceTyDiagnosticSource::Body,1751 LifetimeElisionKind::Infer,1752 |ctx| ctx.lower_lifetime(lifetime_ref),1753 );1754 self.insert_type_vars(lt)1755 }17561757 /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.1758 fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {1759 self.table.insert_type_vars_shallow(ty)1760 }17611762 fn insert_type_vars<T>(&mut self, ty: T) -> T1763 where1764 T: TypeFoldable<DbInterner<'db>>,1765 {1766 self.table.insert_type_vars(ty)1767 }17681769 fn unify(&mut self, ty1: Ty<'db>, ty2: Ty<'db>) -> bool {1770 self.table.unify(ty1, ty2)1771 }17721773 /// Attempts to returns the deeply last field of nested structures, but1774 /// does not apply any normalization in its search. Returns the same type1775 /// if input `ty` is not a structure at all.1776 fn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db> {1777 self.struct_tail_with_normalize(ty, identity)1778 }17791780 /// Returns the deeply last field of nested structures, or the same type if1781 /// not a structure at all. Corresponds to the only possible unsized field,1782 /// and its type can be used to determine unsizing strategy.1783 ///1784 /// This is parameterized over the normalization strategy (i.e. how to1785 /// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity1786 /// function to indicate no normalization should take place.1787 fn struct_tail_with_normalize(1788 &mut self,1789 mut ty: Ty<'db>,1790 mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,1791 ) -> Ty<'db> {1792 // FIXME: fetch the limit properly1793 let recursion_limit = 10;1794 for iteration in 0.. {1795 if iteration > recursion_limit {1796 return self.err_ty();1797 }1798 match ty.kind() {1799 TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 {1800 AdtId::StructId(struct_id) => {1801 match self1802 .db1803 .field_types(struct_id.into())1804 .values()1805 .next_back()1806 .map(|it| it.get())1807 {1808 Some(field) => {1809 ty = field.instantiate(self.interner(), substs);1810 }1811 None => break,1812 }1813 }1814 _ => break,1815 },1816 TyKind::Tuple(substs) => match substs.as_slice().split_last() {1817 Some((last_ty, _)) => ty = *last_ty,1818 None => break,1819 },1820 TyKind::Alias(..) => {1821 let normalized = normalize(ty);1822 if ty == normalized {1823 return ty;1824 } else {1825 ty = normalized;1826 }1827 }1828 _ => break,1829 }1830 }1831 ty1832 }18331834 /// Whenever you lower a user-written type, you should call this.1835 fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {1836 self.table.process_user_written_ty(ty)1837 }18381839 /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,1840 /// while `process_user_written_ty()` should (but doesn't currently).1841 fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {1842 self.table.process_remote_user_written_ty(ty)1843 }18441845 fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {1846 self.table.shallow_resolve(ty)1847 }18481849 fn resolve_associated_type(1850 &mut self,1851 inner_ty: Ty<'db>,1852 assoc_ty: Option<TypeAliasId>,1853 ) -> Ty<'db> {1854 self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])1855 }18561857 fn demand_eqtype(1858 &mut self,1859 id: ExprOrPatId,1860 expected: Ty<'db>,1861 actual: Ty<'db>,1862 ) -> Result<(), ()> {1863 let result = self.demand_eqtype_fixme_no_diag(expected, actual);1864 if result.is_err() {1865 self.result1866 .type_mismatches1867 .get_or_insert_default()1868 .insert(id, TypeMismatch { expected: expected.store(), actual: actual.store() });1869 }1870 result1871 }18721873 fn demand_eqtype_fixme_no_diag(1874 &mut self,1875 expected: Ty<'db>,1876 actual: Ty<'db>,1877 ) -> Result<(), ()> {1878 let result = self1879 .table1880 .at(&ObligationCause::new())1881 .eq(expected, actual)1882 .map(|infer_ok| self.table.register_infer_ok(infer_ok));1883 result.map_err(drop)1884 }18851886 fn demand_suptype(&mut self, expected: Ty<'db>, actual: Ty<'db>) {1887 let result = self1888 .table1889 .at(&ObligationCause::new())1890 .sup(expected, actual)1891 .map(|infer_ok| self.table.register_infer_ok(infer_ok));1892 if let Err(_err) = result {1893 // FIXME: Emit diagnostic.1894 }1895 }18961897 fn demand_coerce(1898 &mut self,1899 expr: ExprId,1900 checked_ty: Ty<'db>,1901 expected: Ty<'db>,1902 allow_two_phase: AllowTwoPhase,1903 expr_is_read: ExprIsRead,1904 ) -> Ty<'db> {1905 let result = self.coerce(expr.into(), checked_ty, expected, allow_two_phase, expr_is_read);1906 if let Err(_err) = result {1907 // FIXME: Emit diagnostic.1908 }1909 result.unwrap_or(self.types.types.error)1910 }19111912 pub(crate) fn type_must_be_known_at_this_point(1913 &self,1914 _id: ExprOrPatId,1915 _ty: Ty<'db>,1916 ) -> Ty<'db> {1917 // FIXME: Emit an diagnostic.1918 self.types.types.error1919 }19201921 pub(crate) fn require_type_is_sized(&mut self, ty: Ty<'db>) {1922 if !ty.references_non_lt_error()1923 && let Some(sized_trait) = self.lang_items.Sized1924 {1925 self.table.register_bound(ty, sized_trait, ObligationCause::new());1926 }1927 }19281929 fn expr_ty(&self, expr: ExprId) -> Ty<'db> {1930 self.result.expr_ty(expr)1931 }19321933 fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> {1934 let mut ty = None;1935 if let Some(it) = self.result.expr_adjustments.get(&e)1936 && let Some(it) = it.last()1937 {1938 ty = Some(it.target.as_ref());1939 }1940 ty.unwrap_or_else(|| self.expr_ty(e))1941 }19421943 fn resolve_associated_type_with_params(1944 &mut self,1945 inner_ty: Ty<'db>,1946 assoc_ty: Option<TypeAliasId>,1947 // FIXME(GATs): these are args for the trait ref, args for assoc type itself should be1948 // handled when we support them.1949 params: &[GenericArg<'db>],1950 ) -> Ty<'db> {1951 match assoc_ty {1952 Some(res_assoc_ty) => {1953 let alias = Ty::new_alias(1954 self.interner(),1955 AliasTy::new(1956 self.interner(),1957 AliasTyKind::Projection { def_id: res_assoc_ty.into() },1958 iter::once(inner_ty.into()).chain(params.iter().copied()),1959 ),1960 );1961 self.table.try_structurally_resolve_type(alias)1962 }1963 None => self.err_ty(),1964 }1965 }19661967 fn resolve_variant(1968 &mut self,1969 node: ExprOrPatId,1970 path: Option<&Path>,1971 value_ns: bool,1972 ) -> (Ty<'db>, Option<VariantId>) {1973 let path = match path {1974 Some(path) => path,1975 None => return (self.err_ty(), None),1976 };1977 let mut ctx = TyLoweringContext::new(1978 self.db,1979 &self.resolver,1980 self.store,1981 &self.diagnostics,1982 InferenceTyDiagnosticSource::Body,1983 self.generic_def,1984 LifetimeElisionKind::Infer,1985 );19861987 if let Some(type_anchor) = path.type_anchor() {1988 let mut segments = path.segments();1989 if segments.is_empty() {1990 return (self.err_ty(), None);1991 }1992 let (mut ty, type_ns) = ctx.lower_ty_ext(type_anchor);1993 ty = self.table.process_user_written_ty(ty);19941995 if let Some(TypeNs::SelfType(impl_)) = type_ns1996 && let Some(trait_ref) = self.db.impl_trait(impl_)1997 && let trait_ref = trait_ref.instantiate_identity()1998 && let Some(assoc_type) = trait_ref1999 .def_id2000 .0