pub(crate) struct InferenceContext<'db> {Show 30 fields
pub(crate) db: &'db dyn HirDatabase,
pub(crate) owner: InferBodyId<'db>,
pub(crate) store_owner: ExpressionStoreOwnerId,
pub(crate) generic_def: GenericDefId,
pub(crate) store: &'db ExpressionStore,
pub(crate) lowering_mode: LoweringMode,
pub(crate) resolver: Resolver<'db>,
target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,
pub(crate) edition: Edition,
allow_using_generic_params: bool,
generics: OnceCell<Generics<'db>>,
identity_args: OnceCell<GenericArgs<'db>>,
pub(crate) table: InferenceTable<'db>,
pub(crate) lang_items: &'db LangItems,
pub(crate) features: &'db UnstableFeatures,
traits_in_scope: FxHashSet<TraitId>,
pub(crate) result: InferenceResult<'db>,
tuple_field_accesses_rev: IndexSet<Tys<'db>, BuildHasherDefault<FxHasher>>,
return_ty: Ty<'db>,
return_coercion: Option<CoerceMany<'db, 'db>>,
resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,
diverges: Diverges,
breakables: Vec<BreakableContext<'db>>,
types: &'db DefaultAny<'db>,
inside_assignment: bool,
deferred_cast_checks: Vec<CastCheck<'db>>,
deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>,
diagnostics: Diagnostics,
vars_emitted_type_must_be_known_for: FxHashSet<Term<'db>>,
defined_anon_consts: RefCell<ThinVec<AnonConstId<'db>>>,
}Expand description
The inference context contains all information needed during type inference.
Fields§
§db: &'db dyn HirDatabase§owner: InferBodyId<'db>§store_owner: ExpressionStoreOwnerId§generic_def: GenericDefId§store: &'db ExpressionStore§lowering_mode: LoweringMode§resolver: Resolver<'db>Generally you should not resolve things via this resolver. Instead create a TyLoweringContext and resolve the path via its methods. This will ensure proper error reporting.
target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>§edition: Edition§allow_using_generic_params: bool§generics: OnceCell<Generics<'db>>§identity_args: OnceCell<GenericArgs<'db>>§table: InferenceTable<'db>§lang_items: &'db LangItems§features: &'db UnstableFeatures§traits_in_scope: FxHashSet<TraitId>The traits in scope, disregarding block modules. This is used for caching purposes.
result: InferenceResult<'db>§tuple_field_accesses_rev: IndexSet<Tys<'db>, BuildHasherDefault<FxHasher>>§return_ty: Ty<'db>The return type of the function being inferred, the closure or async block if we’re currently within one.
We might consider using a nested inference context for checking closures so we can swap all shared things out at once.
return_coercion: Option<CoerceMany<'db, 'db>>If Some, this stores coercion information for returned
expressions. If None, this is in a context where return is
inappropriate, such as a const expression.
resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>The resume type and the yield type, respectively, of the coroutine being inferred.
diverges: Diverges§breakables: Vec<BreakableContext<'db>>§types: &'db DefaultAny<'db>§inside_assignment: boolWhether we are inside the pattern of a destructuring assignment.
deferred_cast_checks: Vec<CastCheck<'db>>§deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>The key is an expression defining a closure or a coroutine closure.
diagnostics: Diagnostics§vars_emitted_type_must_be_known_for: FxHashSet<Term<'db>>§defined_anon_consts: RefCell<ThinVec<AnonConstId<'db>>>Implementations§
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(crate) fn infer_call( &mut self, call_expr: ExprId, callee_expr: ExprId, arg_exprs: &[ExprId], expected: &Expectation<'db>, ) -> Ty<'db>
fn try_overloaded_call_step( call_expr: ExprId, callee_expr: ExprId, arg_exprs: &[ExprId], autoderef: &mut GeneralAutoderef<'db, InferenceContextAutoderefCtx<'_, 'db>, Vec<(Ty<'db>, AutoderefKind)>>, error_reported: &mut bool, ) -> Option<CallStep<'db>>
fn try_overloaded_call_traits( &mut self, call_expr: ExprId, adjusted_ty: Ty<'db>, opt_arg_exprs: Option<&[ExprId]>, ) -> Option<(Option<Adjustment>, MethodCallee<'db>)>
Sourcefn check_legacy_const_generics(
&mut self,
callee: Option<CallableDefId>,
callee_ty: Ty<'db>,
args: &[ExprId],
) -> Box<[u32]>
fn check_legacy_const_generics( &mut self, callee: Option<CallableDefId>, callee_ty: Ty<'db>, args: &[ExprId], ) -> Box<[u32]>
Returns the argument indices to skip.
fn confirm_builtin_call( &mut self, callee_expr: ExprId, call_expr: ExprId, callee_ty: Ty<'db>, arg_exprs: &[ExprId], expected: &Expectation<'db>, ) -> Ty<'db>
fn confirm_deferred_closure_call( &mut self, call_expr: ExprId, arg_exprs: &[ExprId], expected: &Expectation<'db>, fn_sig: FnSig<'db>, ) -> Ty<'db>
fn confirm_overloaded_call( &mut self, call_expr: ExprId, arg_exprs: &[ExprId], expected: &Expectation<'db>, method: MethodCallee<'db>, ) -> Ty<'db>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(crate) fn closure_analyze(&mut self)
fn analyze_closures_in_expr( &mut self, expr: ExprId, upvars: &'db FxHashMap<ExprId, Upvars>, )
Sourcefn analyze_closure(
&mut self,
closure_expr_id: ExprId,
params: &[PatId],
body: ExprId,
capture_clause: CaptureBy,
closure_kind: ClosureKind,
upvars: UpvarsRef<'db>,
)
fn analyze_closure( &mut self, closure_expr_id: ExprId, params: &[PatId], body: ExprId, capture_clause: CaptureBy, closure_kind: ClosureKind, upvars: UpvarsRef<'db>, )
Analysis starting point.
Sourcefn coroutine_body_consumes_upvars(
&mut self,
coroutine_def_id: ExprId,
body: ExprId,
upvars: UpvarsRef<'db>,
) -> bool
fn coroutine_body_consumes_upvars( &mut self, coroutine_def_id: ExprId, body: ExprId, upvars: UpvarsRef<'db>, ) -> bool
Determines whether the body of the coroutine uses its upvars in a way that
consumes (i.e. moves) the value, which would force the coroutine to FnOnce.
In a more detailed comment above, we care whether this happens, since if
this happens, we want to force the coroutine to move all of the upvars it
would’ve borrowed from the parent coroutine-closure.
This only really makes sense to be called on the child coroutine of a coroutine-closure.
fn final_upvar_tys(&self, closure_id: ExprId) -> Vec<Ty<'db>>
Sourcefn process_collected_capture_information(
&mut self,
capture_clause: CaptureBy,
capture_information: &Vec<(Place, CaptureInfo)>,
) -> (Vec<(Place, CaptureInfo)>, ClosureKind, Option<Place>)
fn process_collected_capture_information( &mut self, capture_clause: CaptureBy, capture_information: &Vec<(Place, CaptureInfo)>, ) -> (Vec<(Place, CaptureInfo)>, ClosureKind, Option<Place>)
Adjusts the closure capture information to ensure that the operations aren’t unsafe, and that the path can be captured with required capture kind (depending on use in closure, move closure etc.)
Returns the set of adjusted information along with the inferred closure kind and span associated with the closure kind inference.
Note that we always infer a minimal kind, even if we don’t always use that in the final result (i.e., sometimes we’ve taken the closure kind from the expectations instead, and for coroutines we don’t even implement the closure traits really).
If we inferred that the closure needs to be FnMut/FnOnce, last element of the returned tuple
contains a Some() with the Place that caused us to do so.
Sourcefn compute_min_captures(
&mut self,
closure_def_id: ExprId,
capture_information: Vec<(Place, CaptureInfo)>,
)
fn compute_min_captures( &mut self, closure_def_id: ExprId, capture_information: Vec<(Place, CaptureInfo)>, )
Analyzes the information collected by InferBorrowKind to compute the min number of
Places (and corresponding capture kind) that we need to keep track of to support all
the required captured paths.
Note: If this function is called multiple times for the same closure, it will update the existing min_capture map that is stored in TypeckResults.
Eg:
#[derive(Debug)]
struct Point { x: i32, y: i32 }
let s = String::from("s"); // hir_id_s
let mut p = Point { x: 2, y: -2 }; // his_id_p
let c = || {
println!("{s:?}"); // L1
p.x += 10; // L2
println!("{}" , p.y); // L3
println!("{p:?}"); // L4
drop(s); // L5
};and let hir_id_L1..5 be the expressions pointing to use of a captured variable on the lines L1..5 respectively.
InferBorrowKind results in a structure like this:
{
Place(base: hir_id_s, projections: [], ....) -> {
capture_kind_expr: hir_id_L5,
path_expr_id: hir_id_L5,
capture_kind: ByValue
},
Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> {
capture_kind_expr: hir_id_L2,
path_expr_id: hir_id_L2,
capture_kind: ByValue
},
Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> {
capture_kind_expr: hir_id_L3,
path_expr_id: hir_id_L3,
capture_kind: ByValue
},
Place(base: hir_id_p, projections: [], ...) -> {
capture_kind_expr: hir_id_L4,
path_expr_id: hir_id_L4,
capture_kind: ByValue
},
}After the min capture analysis, we get:
{
hir_id_s -> [
Place(base: hir_id_s, projections: [], ....) -> {
capture_kind_expr: hir_id_L5,
path_expr_id: hir_id_L5,
capture_kind: ByValue
},
],
hir_id_p -> [
Place(base: hir_id_p, projections: [], ...) -> {
capture_kind_expr: hir_id_L2,
path_expr_id: hir_id_L4,
capture_kind: ByValue
},
],
}fn normalize_capture_place(&mut self, span: Span, place: Place) -> Place
fn closure_min_captures_flattened( &self, closure_expr_id: ExprId, ) -> impl Iterator<Item = &CapturedPlace>
fn init_capture_kind_for_place( &self, place: &Place, capture_clause: CaptureBy, ) -> UpvarCapture
fn place_for_root_variable( &mut self, closure_def_id: ExprId, var_hir_id: BindingId, ) -> Place
Sourcefn determine_capture_mutability(
&mut self,
closure_expr: ExprId,
place: &Place,
) -> Mutability
fn determine_capture_mutability( &mut self, closure_expr: ExprId, place: &Place, ) -> Mutability
A captured place is mutable if
- Projections don’t include a Deref of an immut-borrow, and
- PlaceBase is mut or projections include a Deref of a mut-borrow.
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
fn poll_option_ty(&mut self, item_ty: Ty<'db>) -> Ty<'db>
pub(super) fn infer_closure( &mut self, body: ExprId, args: &[PatId], ret_type: Option<TypeRefId>, arg_types: &[Option<TypeRefId>], closure_kind: ClosureKind, closure_expr: ExprId, expected: &Expectation<'db>, ) -> Ty<'db>
fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<ClosureKind>
fn async_fn_trait_kind_from_def_id( &self, trait_id: TraitId, ) -> Option<ClosureKind>
Sourcefn deduce_closure_signature(
&mut self,
closure_expr: ExprId,
expected_ty: Ty<'db>,
closure_kind: ClosureKind,
) -> (Option<PolyFnSig<'db>>, Option<ClosureKind>)
fn deduce_closure_signature( &mut self, closure_expr: ExprId, expected_ty: Ty<'db>, closure_kind: ClosureKind, ) -> (Option<PolyFnSig<'db>>, Option<ClosureKind>)
Given the expected type, figures out what it can about this closure we are about to type check:
fn deduce_closure_signature_from_predicates( &mut self, closure_expr: ExprId, expected_ty: Ty<'db>, closure_kind: ClosureKind, predicates: impl DoubleEndedIterator<Item = Predicate<'db>>, ) -> (Option<PolyFnSig<'db>>, Option<ClosureKind>)
Sourcefn deduce_sig_from_projection(
&mut self,
closure_expr: ExprId,
closure_kind: ClosureKind,
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>>
fn deduce_sig_from_projection( &mut self, closure_expr: ExprId, closure_kind: ClosureKind, projection: PolyProjectionPredicate<'db>, ) -> Option<PolyFnSig<'db>>
Given a projection like “<F as Fn(X)>::Result == Y”, we can deduce everything we need to know about a closure or coroutine.
The cause_span should be the span that caused us to
have this expected signature, or None if we can’t readily
know that.
Sourcefn extract_sig_from_projection(
&self,
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>>
fn extract_sig_from_projection( &self, projection: PolyProjectionPredicate<'db>, ) -> Option<PolyFnSig<'db>>
Given an FnOnce::Output or AsyncFn::Output projection, extract the args
and return type to infer a PolyFnSig for the closure.
Sourcefn extract_sig_from_projection_and_future_bound(
&mut self,
closure_expr: ExprId,
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>>
fn extract_sig_from_projection_and_future_bound( &mut self, closure_expr: ExprId, projection: PolyProjectionPredicate<'db>, ) -> Option<PolyFnSig<'db>>
When an async closure is passed to a function that has a “two-part” Fn
and Future trait bound, like:
use std::future::Future;
fn not_exactly_an_async_closure<F, Fut>(_f: F)
where
F: FnOnce(String, u32) -> Fut,
Fut: Future<Output = i32>,
{}The we want to be able to extract the signature to guide inference in the async
closure. We will have two projection predicates registered in this case. First,
we identify the FnOnce<Args, Output = ?Fut> bound, and if the output type is
an inference variable ?Fut, we check if that is bounded by a Future<Output = Ty>
projection.
This function is actually best-effort with the return type; if we don’t find a
Future projection, we still will return arguments that we extracted from the FnOnce
projection, and the output will be an unconstrained type variable instead.
fn sig_of_closure( &mut self, closure_expr: ExprId, decl_inputs: &[PatId], decl_input_tys: &[Option<TypeRefId>], decl_output_ty: Option<TypeRefId>, expected_sig: Option<PolyFnSig<'db>>, closure_kind: ClosureKind, ) -> ClosureSignatures<'db>
Sourcefn sig_of_closure_no_expectation(
&mut self,
closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
closure_kind: ClosureKind,
) -> ClosureSignatures<'db>
fn sig_of_closure_no_expectation( &mut self, closure_expr: ExprId, decl_inputs: &[Option<TypeRefId>], decl_output: Option<TypeRefId>, closure_kind: ClosureKind, ) -> ClosureSignatures<'db>
If there is no expected signature, then we will convert the types that the user gave into a signature.
Sourcefn sig_of_closure_with_expectation(
&mut self,
closure_expr: ExprId,
decl_inputs: &[PatId],
decl_input_tys: &[Option<TypeRefId>],
decl_output_ty: Option<TypeRefId>,
expected_sig: PolyFnSig<'db>,
closure_kind: ClosureKind,
) -> ClosureSignatures<'db>
fn sig_of_closure_with_expectation( &mut self, closure_expr: ExprId, decl_inputs: &[PatId], decl_input_tys: &[Option<TypeRefId>], decl_output_ty: Option<TypeRefId>, expected_sig: PolyFnSig<'db>, closure_kind: ClosureKind, ) -> ClosureSignatures<'db>
Invoked to compute the signature of a closure expression. This
combines any user-provided type annotations (e.g., |x: u32| -> u32 { .. }) with the expected signature.
The approach is as follows:
- Let
Sbe the (higher-ranked) signature that we derive from the user’s annotations. - Let
Ebe the (higher-ranked) signature that we derive from the expectations, if any.- If we have no expectation
E, then the signature of the closure isS. - Otherwise, the signature of the closure is E. Moreover:
- Skolemize the late-bound regions in
E, yieldingE'. - Instantiate all the late-bound regions bound in the closure within
Swith fresh (existential) variables, yieldingS' - Require that
E' = S'- We could use some kind of subtyping relationship here, I imagine, but equality is easier and works fine for our purposes.
- Skolemize the late-bound regions in
- If we have no expectation
The key intuition here is that the user’s types must be valid from “the inside” of the closure, but the expectation ultimately drives the overall signature.
§Examples
fn with_closure<F>(_: F)
where F: Fn(&u32) -> &u32 { .. }
with_closure(|x: &u32| { ... })Here:
- E would be
fn(&u32) -> &u32. - S would be
fn(&u32) -> ?T - E’ is
&'!0 u32 -> &'!0 u32 - S’ is
&'?0 u32 -> ?T
S’ can be unified with E’ with ['?0 = '!0, ?T = &'!10 u32].
§Arguments
expr_def_id: theLocalDefIdof the closure expressiondecl: the HIR declaration of the closurebody: the body of the closureexpected_sig: the expected signature (if any). Note that this is missing a binder: that is, there may be late-bound regions with depth 1, which are bound then by the closure.
fn sig_of_closure_with_mismatched_number_of_arguments( &mut self, decl_inputs: &[Option<TypeRefId>], decl_output: Option<TypeRefId>, ) -> ClosureSignatures<'db>
Sourcefn merge_supplied_sig_with_expectation(
&mut self,
closure_expr: ExprId,
decl_inputs: &[PatId],
decl_input_tys: &[Option<TypeRefId>],
decl_output_ty: Option<TypeRefId>,
expected_sigs: ClosureSignatures<'db>,
closure_kind: ClosureKind,
) -> InferResult<'db, ClosureSignatures<'db>>
fn merge_supplied_sig_with_expectation( &mut self, closure_expr: ExprId, decl_inputs: &[PatId], decl_input_tys: &[Option<TypeRefId>], decl_output_ty: Option<TypeRefId>, expected_sigs: ClosureSignatures<'db>, closure_kind: ClosureKind, ) -> InferResult<'db, ClosureSignatures<'db>>
Enforce the user’s types against the expectation. See
sig_of_closure_with_expectation for details on the overall
strategy.
Sourcefn supplied_sig_of_closure(
&mut self,
closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
closure_kind: ClosureKind,
) -> PolyFnSig<'db>
fn supplied_sig_of_closure( &mut self, closure_expr: ExprId, decl_inputs: &[Option<TypeRefId>], decl_output: Option<TypeRefId>, closure_kind: ClosureKind, ) -> PolyFnSig<'db>
If there is no expected signature, then we will convert the types that the user gave into a signature.
Also, record this closure signature for later.
Sourcefn deduce_future_output_from_obligations(
&mut self,
body_def_id: ExprId,
) -> Option<Ty<'db>>
fn deduce_future_output_from_obligations( &mut self, body_def_id: ExprId, ) -> Option<Ty<'db>>
Invoked when we are translating the coroutine that results
from desugaring an async fn. Returns the “sugared” return
type of the async fn – that is, the return type that the
user specified. The “desugared” return type is an impl Future<Output = T>, so we do this by searching through the
obligations to extract the T.
Sourcefn deduce_future_output_from_projection(
&self,
predicate: PolyProjectionPredicate<'db>,
) -> Option<Ty<'db>>
fn deduce_future_output_from_projection( &self, predicate: PolyProjectionPredicate<'db>, ) -> Option<Ty<'db>>
Given a projection like
<X as Future>::Output = T
where X is some type that has no late-bound regions, returns
Some(T). If the projection is for some other trait, returns
None.
Sourcefn error_sig_of_closure(
&mut self,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
) -> PolyFnSig<'db>
fn error_sig_of_closure( &mut self, decl_inputs: &[Option<TypeRefId>], decl_output: Option<TypeRefId>, ) -> PolyFnSig<'db>
Converts the types that the user supplied, in case that doing
so should yield an error, but returns back a signature where
all parameters are of type ty::Error.
fn closure_sigs(&self, bound_sig: PolyFnSig<'db>) -> ClosureSignatures<'db>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
Sourcepub(crate) fn coerce(
&mut self,
expr: ExprId,
expr_ty: Ty<'db>,
target: Ty<'db>,
allow_two_phase: AllowTwoPhase,
expr_is_read: ExprIsRead,
) -> RelateResult<'db, Ty<'db>>
pub(crate) fn coerce( &mut self, expr: ExprId, expr_ty: Ty<'db>, target: Ty<'db>, allow_two_phase: AllowTwoPhase, expr_is_read: ExprIsRead, ) -> RelateResult<'db, Ty<'db>>
Attempt to coerce an expression to a type, and return the adjusted type of the expression, if successful. Adjustments are only recorded if the coercion succeeded. The expressions must not have any preexisting adjustments.
Sourcefn try_find_coercion_lub(
&mut self,
exprs: &[ExprId],
prev_ty: Ty<'db>,
new: ExprId,
new_ty: Ty<'db>,
) -> RelateResult<'db, Ty<'db>>
fn try_find_coercion_lub( &mut self, exprs: &[ExprId], prev_ty: Ty<'db>, new: ExprId, new_ty: Ty<'db>, ) -> RelateResult<'db, Ty<'db>>
Given some expressions, their known unified type and another expression, tries to unify the types, potentially inserting coercions on any of the provided expressions and returns their LUB (aka “common supertype”).
This is really an internal helper. From outside the coercion
module, you should instantiate a CoerceMany instance.
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(crate) fn infer_expr( &mut self, tgt_expr: ExprId, expected: &Expectation<'db>, is_read: ExprIsRead, ) -> Ty<'db>
pub(crate) fn infer_expr_suptype_coerce_never( &mut self, expr: ExprId, expected: &Expectation<'db>, is_read: ExprIsRead, ) -> Ty<'db>
pub(crate) fn infer_expr_no_expect( &mut self, tgt_expr: ExprId, is_read: ExprIsRead, ) -> Ty<'db>
Sourcepub(super) fn infer_expr_coerce(
&mut self,
expr: ExprId,
expected: &Expectation<'db>,
is_read: ExprIsRead,
) -> Ty<'db>
pub(super) fn infer_expr_coerce( &mut self, expr: ExprId, expected: &Expectation<'db>, is_read: ExprIsRead, ) -> Ty<'db>
Infer type of expression with possibly implicit coerce to the expected type. Return the type after possible coercion.
Sourcepub(super) fn expr_guaranteed_to_constitute_read_for_never(
&mut self,
expr: ExprId,
is_read: ExprIsRead,
) -> bool
pub(super) fn expr_guaranteed_to_constitute_read_for_never( &mut self, expr: ExprId, is_read: ExprIsRead, ) -> bool
Whether this expression constitutes a read of value of the type that it evaluates to.
This is used to determine if we should consider the block to diverge
if the expression evaluates to !, and if we should insert a NeverToAny
coercion for values of type !.
This function generally returns false if the expression is a place
expression and the parent expression is the scrutinee of a match or
the pointee of an & addr-of expression, since both of those parent
expressions take a place and not a value.
Sourcefn pat_guaranteed_to_constitute_read_for_never(&self, pat: PatId) -> bool
fn pat_guaranteed_to_constitute_read_for_never(&self, pat: PatId) -> bool
Whether this pattern constitutes a read of value of the scrutinee that
it is matching against. This is used to determine whether we should
perform NeverToAny coercions.
Sourcefn contains_explicit_ref_binding(&self, pat: PatId) -> bool
fn contains_explicit_ref_binding(&self, pat: PatId) -> bool
Checks if the pattern contains any ref or ref mut bindings, and if
yes whether it contains mutable or just immutables ones.
fn is_syntactic_place_expr(&self, expr: ExprId) -> bool
pub(crate) fn check_lhs_assignable(&self, lhs: ExprId)
fn infer_expr_coerce_never( &mut self, expr: ExprId, expected: &Expectation<'db>, is_read: ExprIsRead, ) -> Ty<'db>
pub(super) fn infer_expr_inner( &mut self, tgt_expr: ExprId, expected: &Expectation<'db>, is_read: ExprIsRead, ) -> Ty<'db>
fn infer_ref_expr( &mut self, rawness: Rawness, mutbl: Mutability, oprnd: ExprId, expected: &Expectation<'db>, expr: ExprId, ) -> Ty<'db>
fn infer_await_expr(&mut self, expr: ExprId, awaitee: ExprId) -> Ty<'db>
fn infer_record_expr( &mut self, expr: ExprId, expected: &Expectation<'db>, path: &Path, fields: &[RecordLitField], base_expr: RecordSpread, ) -> Ty<'db>
fn check_record_expr_fields( &mut self, adt_ty: Ty<'db>, expected: &Expectation<'db>, expr: ExprId, variant: VariantId, hir_fields: &[RecordLitField], base_expr: RecordSpread, )
fn demand_scrutinee_type( &mut self, scrut: ExprId, contains_ref_bindings: bool, no_arms: bool, scrutinee_is_read: ExprIsRead, ) -> Ty<'db>
fn infer_expr_path( &mut self, path: &Path, id: ExprOrPatIdPacked, scope_id: ExprId, ) -> Ty<'db>
fn infer_unop_expr( &mut self, unop: UnaryOp, oprnd: ExprId, expected: &Expectation<'db>, expr: ExprId, ) -> Ty<'db>
fn infer_array_repeat_expr( &mut self, element: ExprId, count: ExprId, expected: &Expectation<'db>, expr: ExprId, ) -> Ty<'db>
fn infer_array_elements_expr( &mut self, args: &[ExprId], expected: &Expectation<'db>, expr: ExprId, ) -> Ty<'db>
pub(super) fn infer_return(&mut self, expr: ExprId)
fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty<'db>
fn infer_expr_become(&mut self, tgt_expr: ExprId, expr: ExprId) -> Ty<'db>
fn infer_expr_box( &mut self, inner_expr: ExprId, expected: &Expectation<'db>, ) -> Ty<'db>
fn infer_block( &mut self, expr: ExprId, statements: &[Statement], tail: Option<ExprId>, label: Option<LabelId>, expected: &Expectation<'db>, ) -> Ty<'db>
fn lookup_field( &mut self, field_expr: ExprId, receiver_ty: Ty<'db>, name: &Name, ) -> Option<(Ty<'db>, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)>
fn infer_field_access( &mut self, tgt_expr: ExprId, receiver: ExprId, name: &Name, expected: &Expectation<'db>, ) -> Ty<'db>
fn instantiate_erroneous_method( &mut self, def_id: FunctionId, ) -> MethodCallee<'db>
fn infer_method_call_as_call( &mut self, tgt_expr: ExprId, args: &[ExprId], callee_ty: Ty<'db>, param_tys: &[Ty<'db>], ret_ty: Ty<'db>, indices_to_skip: &[u32], is_varargs: bool, expected: &Expectation<'db>, ) -> Ty<'db>
fn infer_method_call( &mut self, tgt_expr: ExprId, receiver: ExprId, args: &[ExprId], method_name: &Name, generic_args: Option<&HirGenericArgs>, expected: &Expectation<'db>, ) -> Ty<'db>
fn check_method_call( &mut self, tgt_expr: ExprId, args: &[ExprId], sig: FnSig<'db>, expected: &Expectation<'db>, ) -> Ty<'db>
Sourcepub(super) fn check_call_arguments(
&mut self,
call_expr: ExprId,
formal_input_tys: &[Ty<'db>],
formal_output: Ty<'db>,
expectation: &Expectation<'db>,
provided_args: &[ExprId],
skip_indices: &[u32],
c_variadic: bool,
tuple_arguments: TupleArgumentsFlag,
)
pub(super) fn check_call_arguments( &mut self, call_expr: ExprId, formal_input_tys: &[Ty<'db>], formal_output: Ty<'db>, expectation: &Expectation<'db>, provided_args: &[ExprId], skip_indices: &[u32], c_variadic: bool, tuple_arguments: TupleArgumentsFlag, )
Generic function that factors out common logic from function calls, method calls and overloaded operators.
pub(super) fn with_breakable_ctx<T>( &mut self, kind: BreakableKind, ty: Option<Ty<'db>>, label: Option<LabelId>, cb: impl FnOnce(&mut Self) -> T, ) -> (BreakableContext<'db>, T)
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(super) fn type_inference_fallback(&mut self)
fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior
fn fallback_types(&mut self) -> bool
fn fallback_if_possible( &mut self, ty: Ty<'db>, diverging_fallback: &FxHashMap<Ty<'db>, Ty<'db>>, ) -> bool
Sourcefn calculate_diverging_fallback(
&self,
unresolved_variables: &[Ty<'db>],
behavior: DivergingFallbackBehavior,
) -> FxHashMap<Ty<'db>, Ty<'db>>
fn calculate_diverging_fallback( &self, unresolved_variables: &[Ty<'db>], behavior: DivergingFallbackBehavior, ) -> FxHashMap<Ty<'db>, Ty<'db>>
The “diverging fallback” system is rather complicated. This is a result of our need to balance ‘do the right thing’ with backwards compatibility.
“Diverging” type variables are variables created when we
coerce a ! type into an unbound type variable ?X. If they
never wind up being constrained, the “right and natural” thing
is that ?X should “fallback” to !. This means that e.g. an
expression like Some(return) will ultimately wind up with a
type like Option<!> (presuming it is not assigned or
constrained to have some other type).
However, the fallback used to be () (before the ! type was
added). Moreover, there are cases where the ! type ‘leaks
out’ from dead code into type variables that affect live
code. The most common case is something like this:
match foo() {
22 => Default::default(), // call this type `?D`
_ => return, // return has type `!`
} // call the type of this match `?M`Here, coercing the type ! into ?M will create a diverging
type variable ?X where ?X <: ?M. We also have that ?D <: ?M. If ?M winds up unconstrained, then ?X will
fallback. If it falls back to !, then all the type variables
will wind up equal to ! – this includes the type ?D
(since ! doesn’t implement Default, we wind up a “trait
not implemented” error in code like this). But since the
original fallback was (), this code used to compile with ?D = (). This is somewhat surprising, since Default::default()
on its own would give an error because the types are
insufficiently constrained.
Our solution to this dilemma is to modify diverging variables
so that they can either fallback to ! (the default) or to
() (the backwards compatibility case). We decide which
fallback to use based on whether there is a coercion pattern
like this:
?Diverging -> ?V
?NonDiverging -> ?V
?V != ?NonDivergingHere ?Diverging represents some diverging type variable and
?NonDiverging represents some non-diverging type
variable. ?V can be any type variable (diverging or not), so
long as it is not equal to ?NonDiverging.
Intuitively, what we are looking for is a case where a
“non-diverging” type variable (like ?M in our example above)
is coerced into some variable ?V that would otherwise
fallback to !. In that case, we make ?V fallback to !,
along with anything that would flow into ?V.
The algorithm we use:
- Identify all variables that are coerced into by a
diverging variable. Do this by iterating over each
diverging, unsolved variable and finding all variables
reachable from there. Call that set
D. - Walk over all unsolved, non-diverging variables, and find
any variable that has an edge into
D.
Sourcefn create_coercion_graph(&self) -> Graph<(), ()>
fn create_coercion_graph(&self) -> Graph<(), ()>
Returns a graph whose nodes are (unresolved) inference variables and where
an edge ?A -> ?B indicates that the variable ?A is coerced to ?B.
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(crate) fn infer_mut_body(&mut self, body_expr: ExprId)
fn infer_mut_expr(&mut self, tgt_expr: ExprId, mutability: Mutability)
fn infer_mut_expr_without_adjust( &mut self, tgt_expr: ExprId, mutability: Mutability, )
fn infer_mut_not_expr_iter(&mut self, exprs: impl Iterator<Item = ExprId>)
fn pat_iter_bound_mutability( &self, pat: impl Iterator<Item = PatId>, ) -> Mutability
Sourcefn pat_bound_mutability(&self, pat: PatId) -> Mutability
fn pat_bound_mutability(&self, pat: PatId) -> Mutability
Checks if the pat contains a ref mut binding. Such paths makes the context of bounded expressions
mutable. For example in let (ref mut x0, ref x1) = *it; we need to use DerefMut for *it but in
let (ref x0, ref x1) = *it; we should use Deref.
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
Sourcepub(crate) fn infer_assign_op_expr(
&mut self,
expr: ExprId,
op: ArithOp,
lhs: ExprId,
rhs: ExprId,
) -> Ty<'db>
pub(crate) fn infer_assign_op_expr( &mut self, expr: ExprId, op: ArithOp, lhs: ExprId, rhs: ExprId, ) -> Ty<'db>
Checks a a <op>= b
Sourcepub(crate) fn infer_binop_expr(
&mut self,
expr: ExprId,
op: BinaryOp,
lhs_expr: ExprId,
rhs_expr: ExprId,
) -> Ty<'db>
pub(crate) fn infer_binop_expr( &mut self, expr: ExprId, op: BinaryOp, lhs_expr: ExprId, rhs_expr: ExprId, ) -> Ty<'db>
Checks a potentially overloaded binary operator.
fn enforce_builtin_binop_types( &mut self, expr: ExprId, lhs_ty: Ty<'db>, rhs_ty: Ty<'db>, category: BinOpCategory, ) -> Ty<'db>
fn infer_overloaded_binop( &mut self, expr: ExprId, lhs_expr: ExprId, rhs_expr: ExprId, op: BinaryOp, ) -> (Ty<'db>, Ty<'db>, Ty<'db>)
pub(crate) fn infer_user_unop( &mut self, ex: ExprId, operand_ty: Ty<'db>, op: UnaryOp, ) -> Ty<'db>
fn lookup_op_method( &mut self, expr: ExprId, lhs_ty: Ty<'db>, opt_rhs: Option<(ExprId, Ty<'db>)>, (op_method, trait_did): (Option<FunctionId>, Option<TraitId>), ) -> Result<MethodCallee<'db>, Vec<NextSolverError<'db>>>
fn lang_item_for_bin_op( &self, op: BinaryOp, ) -> (Option<FunctionId>, Option<TraitId>)
fn lang_item_for_unop( &self, op: UnaryOp, ) -> (Option<FunctionId>, Option<TraitId>)
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
Sourcepub(super) fn handle_opaque_type_uses(&mut self)
pub(super) fn handle_opaque_type_uses(&mut self)
This takes all the opaque type uses during HIR typeck. It first computes the concrete hidden type by iterating over all defining uses.
A use during HIR typeck is defining if all non-lifetime arguments are unique generic parameters and the hidden type does not reference any inference variables.
It then uses these defining uses to guide inference for all other uses.
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
fn consider_opaque_type_use( &self, opaque_type_key: OpaqueTypeKey<'db>, hidden_type: OpaqueHiddenType<'db>, ) -> UsageKind<'db>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
Experimental pattern feature: after matching against a shared reference, do we limit the
default binding mode in subpatterns to be ref when it would otherwise be ref mut?
This corresponds to Rule 3 of RFC 3627.
Sourcefn ref_pat_matches_inherited_ref(
&self,
edition: Edition,
) -> InheritedRefMatchRule
fn ref_pat_matches_inherited_ref( &self, edition: Edition, ) -> InheritedRefMatchRule
Experimental pattern feature: when do reference patterns match against inherited references? This corresponds to variations on Rule 4 of RFC 3627.
Sourcefn ref_pat_matches_mut_ref(&self) -> bool
fn ref_pat_matches_mut_ref(&self) -> bool
Experimental pattern feature: do & patterns match against &mut references, treating them
as if they were shared references? This corresponds to Rule 5 of RFC 3627.
Sourcepub(super) fn infer_top_pat(
&mut self,
pat: PatId,
expected: Ty<'db>,
pat_origin: PatOrigin,
)
pub(super) fn infer_top_pat( &mut self, pat: PatId, expected: Ty<'db>, pat_origin: PatOrigin, )
Type check the given top level pattern against the expected type.
If a Some(span) is provided and origin_expr holds,
then the span represents the scrutinee’s span.
The scrutinee is found in e.g. match scrutinee { ... } and let pat = scrutinee;.
Otherwise, Some(span) represents the span of a type expression
which originated the expected type.
Sourcefn infer_pat(&mut self, pat_id: PatId, expected: Ty<'db>, pat_info: PatInfo)
fn infer_pat(&mut self, pat_id: PatId, expected: Ty<'db>, pat_info: PatInfo)
Type check the given pat against the expected type
with the provided binding_mode (default binding mode).
Outside of this module, check_pat_top should always be used.
Conversely, inside this module, check_pat_top should never be used.
fn infer_pat_inner( &mut self, pat: PatId, opt_path_res: Option<Result<ResolvedPat<'db>, ()>>, adjust_mode: AdjustMode, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn adjust_pat_info( &self, inner_mutability: Mutability, pat_info: PatInfo, ) -> PatInfo
fn check_deref_pattern( &mut self, pat: PatId, opt_path_res: Option<Result<ResolvedPat<'db>, ()>>, adjust_mode: AdjustMode, expected: Ty<'db>, inner_ty: Ty<'db>, pat_adjust_kind: PatAdjust, pat_info: PatInfo, ) -> Ty<'db>
Sourcefn calc_adjust_mode(
&mut self,
pat_id: PatId,
pat: &Pat,
opt_path_res: Option<Result<ResolvedPat<'db>, ()>>,
) -> AdjustMode
fn calc_adjust_mode( &mut self, pat_id: PatId, pat: &Pat, opt_path_res: Option<Result<ResolvedPat<'db>, ()>>, ) -> AdjustMode
How should the binding mode and expected type be adjusted?
When the pattern contains a path, opt_path_res must be Some(path_res).
Sourcefn should_peel_ref(&self, peel_kind: PeelKind, expected: Ty<'db>) -> bool
fn should_peel_ref(&self, peel_kind: PeelKind, expected: Ty<'db>) -> bool
Assuming expected is a reference type, determine whether to peel it before matching.
Sourcefn should_peel_smart_pointer(
&self,
peel_kind: PeelKind,
expected: Ty<'db>,
) -> bool
fn should_peel_smart_pointer( &self, peel_kind: PeelKind, expected: Ty<'db>, ) -> bool
Determine whether expected is a smart pointer type that should be peeled before matching.
fn infer_expr_pat_unadjusted(&mut self, expr: ExprId) -> Ty<'db>
fn infer_lit_pat(&mut self, expr: ExprId, expected: Ty<'db>) -> Ty<'db>
fn infer_range_pat( &mut self, pat: PatId, lhs_expr: Option<ExprId>, rhs_expr: Option<ExprId>, expected: Ty<'db>, ) -> Ty<'db>
fn infer_bind_pat( &mut self, pat: PatId, var_id: BindingId, sub: Option<PatId>, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn check_dereferenceable( &mut self, expected: Ty<'db>, pat: PatId, inner: PatId, ) -> Result<(), ()>
fn resolve_record_pat( &mut self, pat: PatId, path: &Path, ) -> Result<ResolvedPat<'db>, ()>
fn infer_record_pat( &mut self, pat: PatId, fields: &[RecordFieldPat], has_rest_pat: bool, pat_ty: Ty<'db>, variant: VariantId, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn resolve_pat_path( &mut self, pat: PatId, path: &Path, ) -> Result<ResolvedPat<'db>, ()>
fn infer_pat_path( &mut self, pat: PatId, resolved: &ResolvedPat<'db>, expected: Ty<'db>, ) -> Ty<'db>
fn resolve_tuple_struct_pat( &mut self, pat: PatId, path: &Path, ) -> Result<ResolvedPat<'db>, ()>
fn infer_tuple_struct_pat( &mut self, pat: PatId, subpats: &[PatId], ddpos: Option<u32>, pat_ty: Ty<'db>, variant: VariantId, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn infer_tuple_pat( &mut self, pat: PatId, elements: &[PatId], ddpos: Option<u32>, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn check_record_pat_fields( &mut self, adt_ty: Ty<'db>, pat: PatId, variant: VariantId, fields: &[RecordFieldPat], has_rest_pat: bool, pat_info: PatInfo, )
fn infer_box_pat( &mut self, pat: PatId, inner: PatId, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn infer_deref_pat( &mut self, pat: PatId, inner: PatId, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
fn deref_pat_target(&mut self, pat: PatId, source_ty: Ty<'db>) -> Ty<'db>
Sourcefn register_deref_mut_bounds_if_needed(
&self,
pat: PatId,
inner: PatId,
derefed_tys: impl IntoIterator<Item = Ty<'db>>,
) -> InferOk<'db, ()>
fn register_deref_mut_bounds_if_needed( &self, pat: PatId, inner: PatId, derefed_tys: impl IntoIterator<Item = Ty<'db>>, ) -> InferOk<'db, ()>
Check if the interior of a deref pattern (either explicit or implicit) has any ref mut
bindings, which would require DerefMut to be emitted in MIR building instead of just
Deref. We do this after checking the inner pattern, since we want to make sure to
account for ref mut binding modes inherited from implicitly dereferencing &mut refs.
Sourcepub(super) fn pat_has_ref_mut_binding(&self, pat: PatId) -> bool
pub(super) fn pat_has_ref_mut_binding(&self, pat: PatId) -> bool
Does the pattern recursively contain a ref mut binding in it?
This is used to determined whether a deref pattern should emit a Deref
or DerefMut call for its pattern scrutinee.
This is computed from the typeck results since we want to make sure to apply any match-ergonomics adjustments, which we cannot determine from the HIR alone.
fn infer_ref_pat( &mut self, pat: PatId, inner: PatId, pat_mutbl: Mutability, expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
Sourcefn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db>
fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db>
Create a reference or pinned reference type with a fresh region variable.
fn try_resolve_slice_ty_to_array_ty( &self, before: &[PatId], slice: Option<PatId>, pat: PatId, ) -> Option<Ty<'db>>
Sourcefn pat_is_irrefutable(&self, pat_origin: PatOrigin) -> bool
fn pat_is_irrefutable(&self, pat_origin: PatOrigin) -> bool
Used to determines whether we can infer the expected type in the slice pattern to be of type array. This is only possible if we’re in an irrefutable pattern. If we were to allow this in refutable patterns we wouldn’t e.g. report ambiguity in the following situation:
struct Zeroes;
const ARR: [usize; 2] = [0; 2];
const ARR2: [usize; 2] = [2; 2];
impl Into<&'static [usize; 2]> for Zeroes {
fn into(self) -> &'static [usize; 2] {
&ARR
}
}
impl Into<&'static [usize]> for Zeroes {
fn into(self) -> &'static [usize] {
&ARR2
}
}
fn main() {
let &[a, b]: &[usize] = Zeroes.into() else {
..
};
}If we’re in an irrefutable pattern we prefer the array impl candidate given that the slice impl candidate would be rejected anyway (if no ambiguity existed).
Sourcefn infer_slice_pat(
&mut self,
pat: PatId,
before: &[PatId],
slice: Option<PatId>,
after: &[PatId],
expected: Ty<'db>,
pat_info: PatInfo,
) -> Ty<'db>
fn infer_slice_pat( &mut self, pat: PatId, before: &[PatId], slice: Option<PatId>, after: &[PatId], expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db>
Type check a slice pattern.
Syntactically, these look like [pat_0, ..., pat_n].
Semantically, we are type checking a pattern with structure:
[before_0, ..., before_n, (slice, after_0, ... after_n)?]The type of slice, if it is present, depends on the expected type.
If slice is missing, then so is after_i.
If slice is present, it can still represent 0 elements.
Sourcefn check_array_pat_len(
&mut self,
pat: PatId,
element_ty: Ty<'db>,
arr_ty: Ty<'db>,
slice: Option<PatId>,
len: Const<'db>,
min_len: u128,
) -> (Option<Ty<'db>>, Ty<'db>)
fn check_array_pat_len( &mut self, pat: PatId, element_ty: Ty<'db>, arr_ty: Ty<'db>, slice: Option<PatId>, len: Const<'db>, min_len: u128, ) -> (Option<Ty<'db>>, Ty<'db>)
Type check the length of an array pattern.
Returns both the type of the variable length pattern (or None), and the potentially
inferred array type. We only return None for the slice type if slice.is_none().
fn infer_destructuring_assignment_expr( &mut self, expr: ExprId, expected: Ty<'db>, ) -> Ty<'db>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(super) fn infer_path( &mut self, path: &Path, id: ExprOrPatIdPacked, ) -> Option<(ValueNs, Ty<'db>)>
fn resolve_value_path( &mut self, path: &Path, id: ExprOrPatIdPacked, value: ValueNs, self_subst: Option<GenericArgs<'db>>, ) -> Option<ValuePathResolution<'db>>
pub(super) fn resolve_value_path_inner( &mut self, path: &Path, id: ExprOrPatIdPacked, no_diagnostics: bool, ) -> Option<(ValueNs, Option<GenericArgs<'db>>)>
pub(super) fn add_required_obligations_for_value_path( &mut self, node: ExprOrPatIdPacked, def: GenericDefId, subst: GenericArgs<'db>, )
fn resolve_trait_assoc_item( &mut self, trait_ref: TraitRef<'db>, segment: PathSegment<'_>, id: ExprOrPatIdPacked, ) -> Option<(ValueNs, GenericArgs<'db>)>
fn resolve_ty_assoc_item( &mut self, ty: Ty<'db>, name: &Name, id: ExprOrPatIdPacked, ) -> Option<(ValueNs, GenericArgs<'db>)>
fn resolve_enum_variant_on_ty( &mut self, ty: Ty<'db>, name: &Name, id: ExprOrPatIdPacked, ) -> Option<(ValueNs, GenericArgs<'db>)>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(super) fn try_overloaded_deref( &self, expr: ExprId, base_ty: Ty<'db>, ) -> Option<InferOk<'db, MethodCallee<'db>>>
Sourcefn make_overloaded_place_return_type(
&self,
method: MethodCallee<'db>,
) -> Ty<'db>
fn make_overloaded_place_return_type( &self, method: MethodCallee<'db>, ) -> Ty<'db>
For the overloaded place expressions (*x, x[3]), the trait
returns a type of &T, but the actual type we assign to the
expression is T. So this function just peels off the return
type by one layer to yield T.
Sourcepub(super) fn lookup_derefing(
&mut self,
expr: ExprId,
oprnd_expr: ExprId,
oprnd_ty: Ty<'db>,
) -> Option<Ty<'db>>
pub(super) fn lookup_derefing( &mut self, expr: ExprId, oprnd_expr: ExprId, oprnd_ty: Ty<'db>, ) -> Option<Ty<'db>>
Type-check *oprnd_expr with oprnd_expr type-checked already.
Sourcepub(super) fn lookup_indexing(
&mut self,
expr: ExprId,
base_expr: ExprId,
index_expr: ExprId,
base_ty: Ty<'db>,
idx_ty: Ty<'db>,
) -> Option<(Ty<'db>, Ty<'db>)>
pub(super) fn lookup_indexing( &mut self, expr: ExprId, base_expr: ExprId, index_expr: ExprId, base_ty: Ty<'db>, idx_ty: Ty<'db>, ) -> Option<(Ty<'db>, Ty<'db>)>
Type-check *base_expr[index_expr] with base_expr and index_expr type-checked already.
Sourcefn try_index_step(
expr: ExprId,
base_expr: ExprId,
index_expr: ExprId,
autoderef: &mut GeneralAutoderef<'db, InferenceContextAutoderefCtx<'_, 'db>, Vec<(Ty<'db>, AutoderefKind)>>,
index_ty: Ty<'db>,
) -> Option<(Ty<'db>, Ty<'db>)>
fn try_index_step( expr: ExprId, base_expr: ExprId, index_expr: ExprId, autoderef: &mut GeneralAutoderef<'db, InferenceContextAutoderefCtx<'_, 'db>, Vec<(Ty<'db>, AutoderefKind)>>, index_ty: Ty<'db>, ) -> Option<(Ty<'db>, Ty<'db>)>
To type-check base_expr[index_expr], we progressively autoderef
(and otherwise adjust) base_expr, looking for a type which either
supports builtin indexing or overloaded indexing.
This loop implements one step in that search; the autoderef loop
is implemented by lookup_indexing.
Sourcepub(super) fn try_overloaded_place_op(
&self,
expr: ExprId,
base_ty: Ty<'db>,
opt_rhs_ty: Option<Ty<'db>>,
op: PlaceOp,
) -> Option<InferOk<'db, MethodCallee<'db>>>
pub(super) fn try_overloaded_place_op( &self, expr: ExprId, base_ty: Ty<'db>, opt_rhs_ty: Option<Ty<'db>>, op: PlaceOp, ) -> Option<InferOk<'db, MethodCallee<'db>>>
Try to resolve an overloaded place op. We only deal with the immutable
variant here (Deref/Index). In some contexts we would need the mutable
variant (DerefMut/IndexMut); those would be later converted by
convert_place_derefs_to_mutable.
pub(super) fn try_mutable_overloaded_place_op( table: &InferenceTable<'db>, expr: ExprId, base_ty: Ty<'db>, opt_rhs_ty: Option<Ty<'db>>, op: PlaceOp, ) -> Option<InferOk<'db, MethodCallee<'db>>>
pub(super) fn convert_place_op_to_mutable( &mut self, op: PlaceOp, expr: ExprId, base_expr: ExprId, index_expr: Option<ExprId>, )
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
fn new( db: &'db dyn HirDatabase, owner: InferBodyId<'db>, store_owner: ExpressionStoreOwnerId, generic_def: GenericDefId, store: &'db ExpressionStore, resolver: Resolver<'db>, allow_using_generic_params: bool, lowering_mode: LoweringMode, ) -> Self
fn merge(&mut self, other: &InferenceResult<'db>)
fn krate(&self) -> Crate
fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget)
Sourcefn deref_pat_borrow_mode(
&self,
pointer_ty: Ty<'_>,
inner: PatId,
) -> DerefPatBorrowMode
fn deref_pat_borrow_mode( &self, pointer_ty: Ty<'_>, inner: PatId, ) -> DerefPatBorrowMode
How should a deref pattern find the place for its inner pattern to match on?
In most cases, if the pattern recursively contains a ref mut binding, we find the inner
pattern’s scrutinee by calling DerefMut::deref_mut, and otherwise we call Deref::deref.
However, for boxes we can use a built-in deref instead, which doesn’t borrow the scrutinee;
in this case, we return DerefPatBorrowMode::Box.
fn set_tainted_by_errors(&mut self)
Sourcefn merge_anon_consts(&mut self)
fn merge_anon_consts(&mut self)
Copy the inference of defined anon consts to ourselves, so that we don’t need to lookup the defining anon const when looking the type of something.
fn resolve_all(self) -> InferenceResult<'db>
fn collect_const(&mut self, id: ConstId, data: &'db ConstSignature)
fn collect_static(&mut self, id: StaticId, data: &'db StaticSignature)
fn collect_fn( &mut self, func: FunctionId, self_param: Option<BindingId>, params: &[Param<PatId>], )
pub(crate) fn interner(&self) -> DbInterner<'db>
pub(crate) fn infcx(&self) -> &InferCtxt<'db>
Sourcefn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db>
fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db>
If ty is an error, returns an infer var instead. Otherwise, returns it.
“Refreshing” types like this is useful for getting better types, but it is also very dangerous: we might create duplicate diagnostics, for example if we try to resolve it and fail. rustc doesn’t do that for this reason (and is in general more strict with how it uses error types; an error type in inputs will almost always cause it to infer an error type in output, while we infer some type as much as we can).
Unfortunately, we cannot allow ourselves to do that. Not only we more often work with incomplete code, we also have assists, for example “Generate constant”, that will assume the inferred type is the expected type even if the expression itself cannot be inferred. Therefore, we choose a middle ground: refresh the type, but if we return a new var, mark it so that no diagnostics will be issued on it.
fn infer_body(&mut self, body_expr: ExprId)
fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>)
pub(crate) fn write_expr_adj( &mut self, expr: ExprId, adjustments: Box<[Adjustment]>, )
pub(crate) fn write_method_resolution( &mut self, expr: ExprId, func: FunctionId, subst: GenericArgs<'db>, )
fn write_variant_resolution( &mut self, id: ExprOrPatIdPacked, variant: VariantId, )
fn write_assoc_resolution( &mut self, id: ExprOrPatIdPacked, item: CandidateId, subs: GenericArgs<'db>, )
fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>)
fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>)
pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic)
fn record_deferred_call_resolution( &mut self, closure_def_id: ExprId, r: DeferredCallResolution<'db>, )
fn remove_deferred_call_resolutions( &mut self, closure_def_id: ExprId, ) -> Vec<DeferredCallResolution<'db>>
fn with_ty_lowering<R>( &mut self, store: &'db ExpressionStore, types_source: InferenceTyDiagnosticSource, store_owner: ExpressionStoreOwnerId, lifetime_elision: LifetimeElisionKind<'db>, f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R, ) -> R
fn with_body_ty_lowering<R>( &mut self, f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R, ) -> R
fn make_ty( &mut self, type_ref: TypeRefId, store: &'db ExpressionStore, type_source: InferenceTyDiagnosticSource, store_owner: ExpressionStoreOwnerId, lifetime_elision: LifetimeElisionKind<'db>, ) -> Ty<'db>
pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db>
fn generics(&self) -> &Generics<'db>
fn identity_args(&self) -> GenericArgs<'db>
pub(crate) fn create_body_anon_const( &mut self, expr: ExprId, expected_ty: Ty<'db>, allow_using_generic_params: bool, ) -> Const<'db>
pub(crate) fn make_path_as_body_const(&mut self, path: &Path) -> Const<'db>
fn err_ty(&self) -> Ty<'db>
pub(crate) fn make_body_lifetime( &mut self, lifetime_ref: LifetimeRefId, ) -> Region<'db>
fn insert_type_vars<T>(&mut self, ty: T) -> Twhere
T: TypeFoldable<DbInterner<'db>>,
Sourcefn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db>
fn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db>
Attempts to returns the deeply last field of nested structures, but
does not apply any normalization in its search. Returns the same type
if input ty is not a structure at all.
Sourcefn struct_tail_with_normalize(
&mut self,
ty: Ty<'db>,
normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
) -> Ty<'db>
fn struct_tail_with_normalize( &mut self, ty: Ty<'db>, normalize: impl FnMut(Ty<'db>) -> Ty<'db>, ) -> Ty<'db>
Returns the deeply last field of nested structures, or the same type if not a structure at all. Corresponds to the only possible unsized field, and its type can be used to determine unsizing strategy.
This is parameterized over the normalization strategy (i.e. how to
handle <T as Trait>::Assoc and impl Trait); pass the identity
function to indicate no normalization should take place.
Sourcefn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db>
fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db>
Whenever you lower a user-written type, you should call this.
Sourcefn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db>
fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db>
The difference of this method from process_user_written_ty() is that this method doesn’t register a well-formed obligation,
while process_user_written_ty() should (but doesn’t currently).
fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db>
pub(crate) fn resolve_vars_if_possible<T: TypeFoldable<DbInterner<'db>>>( &self, t: T, ) -> T
pub(crate) fn structurally_resolve_type( &mut self, node: ExprOrPatIdPacked, ty: Ty<'db>, ) -> Ty<'db>
pub(crate) fn emit_type_mismatch( &mut self, node: ExprOrPatIdPacked, expected: Ty<'db>, found: Ty<'db>, )
fn demand_eqtype( &mut self, id: ExprOrPatIdPacked, expected: Ty<'db>, actual: Ty<'db>, ) -> Result<(), ()>
fn demand_eqtype_fixme_no_diag( &mut self, expected: Ty<'db>, actual: Ty<'db>, ) -> Result<(), ()>
fn demand_suptype( &mut self, id: ExprOrPatIdPacked, expected: Ty<'db>, actual: Ty<'db>, ) -> Result<(), ()>
fn demand_coerce( &mut self, expr: ExprId, checked_ty: Ty<'db>, expected: Ty<'db>, allow_two_phase: AllowTwoPhase, expr_is_read: ExprIsRead, ) -> Ty<'db>
pub(crate) fn type_must_be_known_at_this_point( &mut self, node: ExprOrPatIdPacked, ty: Ty<'db>, ) -> Ty<'db>
pub(crate) fn require_type_is_sized(&mut self, ty: Ty<'db>, span: Span)
fn expr_ty(&self, expr: ExprId) -> Ty<'db>
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db>
fn resolve_variant( &mut self, node: ExprOrPatIdPacked, path: &Path, value_ns: bool, ) -> (Ty<'db>, Option<VariantId>)
fn resolve_variant_on_alias( &mut self, node: ExprOrPatIdPacked, ty: Ty<'db>, unresolved: Option<usize>, path: &ModPath, ) -> (Ty<'db>, Option<VariantId>)
fn resolve_boxed_box(&self) -> Option<AdtId>
fn resolve_range_full(&self) -> Option<AdtId>
fn has_new_range_feature(&self) -> bool
fn resolve_range(&self) -> Option<AdtId>
fn resolve_range_inclusive(&self) -> Option<AdtId>
fn resolve_range_from(&self) -> Option<AdtId>
fn resolve_range_to(&self) -> Option<AdtId>
fn resolve_range_to_inclusive(&self) -> Option<AdtId>
fn resolve_va_list(&self) -> Option<AdtId>
pub(crate) fn get_traits_in_scope( &self, ) -> Either<FxHashSet<TraitId>, &FxHashSet<TraitId>> ⓘ
fn has_applicable_non_exhaustive(&self, def: AttrDefId) -> bool
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
pub(crate) fn confirm_method( &mut self, pick: &Pick<'db>, unadjusted_self_ty: Ty<'db>, expr: ExprId, generic_args: Option<&HirGenericArgs>, ) -> ConfirmResult<'db>
Source§impl<'db> InferenceContext<'db>
impl<'db> InferenceContext<'db>
Sourcepub(crate) fn lookup_method_including_private(
&mut self,
self_ty: Ty<'db>,
name: Name,
generic_args: Option<&HirGenericArgs>,
receiver: ExprId,
call_expr: ExprId,
) -> Result<(MethodCallee<'db>, bool), MethodError<'db>>
pub(crate) fn lookup_method_including_private( &mut self, self_ty: Ty<'db>, name: Name, generic_args: Option<&HirGenericArgs>, receiver: ExprId, call_expr: ExprId, ) -> Result<(MethodCallee<'db>, bool), MethodError<'db>>
Performs method lookup. If lookup is successful, it will return the callee
and store an appropriate adjustment for the self-expr. In some cases it may
report an error (e.g., invoking the drop method).
pub(crate) fn lookup_probe( &self, call_expr: ExprId, receiver: ExprId, method_name: Name, self_ty: Ty<'db>, ) -> Result<Pick<'db>, MethodError<'db>>
pub(crate) fn with_method_resolution<R>( &self, call_span: Span, receiver_span: Span, f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R, ) -> R
Trait Implementations§
Auto Trait Implementations§
impl<'db> !Freeze for InferenceContext<'db>
impl<'db> !RefUnwindSafe for InferenceContext<'db>
impl<'db> !Send for InferenceContext<'db>
impl<'db> !Sync for InferenceContext<'db>
impl<'db> Unpin for InferenceContext<'db>
impl<'db> UnsafeUnpin for InferenceContext<'db>
impl<'db> !UnwindSafe for InferenceContext<'db>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more