Struct rustc_hir_typeck::fn_ctxt::FnCtxt

source ·
pub(crate) struct FnCtxt<'a, 'tcx> {
Show 13 fields pub(crate) body_id: LocalDefId, pub(crate) param_env: ParamEnv<'tcx>, pub(crate) ret_coercion: Option<RefCell<CoerceMany<'tcx, 'tcx, &'tcx Expr<'tcx>>>>, pub(crate) ret_coercion_span: Cell<Option<Span>>, pub(crate) coroutine_types: Option<CoroutineTypes<'tcx>>, pub(crate) diverges: Cell<Diverges>, pub(crate) function_diverges_because_of_empty_arguments: Cell<Diverges>, pub(crate) is_whole_body: Cell<bool>, pub(crate) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>, pub(crate) root_ctxt: &'a TypeckRootCtxt<'tcx>, pub(crate) fallback_has_occurred: Cell<bool>, pub(crate) diverging_fallback_behavior: DivergingFallbackBehavior, pub(crate) diverging_block_behavior: DivergingBlockBehavior,
}
Expand description

The FnCtxt stores type-checking context needed to type-check bodies of functions, closures, and consts, including performing type inference with InferCtxt.

This is in contrast to ItemCtxt, which is used to type-check item signatures and thus does not perform type inference.

See ItemCtxt’s docs for more.

Fields§

§body_id: LocalDefId§param_env: ParamEnv<'tcx>

The parameter environment used for proving trait obligations in this function. This can change when we descend into closures (as they bring new things into scope), hence it is not part of Inherited (as of the time of this writing, closures do not yet change the environment, but they will eventually).

§ret_coercion: Option<RefCell<CoerceMany<'tcx, 'tcx, &'tcx Expr<'tcx>>>>

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.

This is a RefCell<DynamicCoerceMany>, which means that we can track all the return expressions and then use them to compute a useful coercion from the set, similar to a match expression or other branching context. You can use methods like expected_ty to access the declared return type (if any).

§ret_coercion_span: Cell<Option<Span>>

First span of a return site that we find. Used in error messages.

§coroutine_types: Option<CoroutineTypes<'tcx>>§diverges: Cell<Diverges>

Whether the last checked node generates a divergence (e.g., return will set this to Always). In general, when entering an expression or other node in the tree, the initial value indicates whether prior parts of the containing expression may have diverged. It is then typically set to Maybe (and the old value remembered) for processing the subparts of the current expression. As each subpart is processed, they may set the flag to Always, etc. Finally, at the end, we take the result and “union” it with the original value, so that when we return the flag indicates if any subpart of the parent expression (up to and including this part) has diverged. So, if you read it after evaluating a subexpression X, the value you get indicates whether any subexpression that was evaluating up to and including X diverged.

We currently use this flag only for diagnostic purposes:

  • To warn about unreachable code: if, after processing a sub-expression but before we have applied the effects of the current node, we see that the flag is set to Always, we can issue a warning. This corresponds to something like foo(return); we warn on the foo() expression. (We then update the flag to WarnedAlways to suppress duplicate reports.) Similarly, if we traverse to a fresh statement (or tail expression) from an Always setting, we will issue a warning. This corresponds to something like {return; foo();} or {return; 22}, where we would warn on the foo() or 22.

An expression represents dead code if, after checking it, the diverges flag is set to something other than Maybe.

§function_diverges_because_of_empty_arguments: Cell<Diverges>

If one of the function arguments is a never pattern, this counts as diverging code. This affect typechecking of the function body.

§is_whole_body: Cell<bool>

Whether the currently checked node is the whole body of the function.

§enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>§root_ctxt: &'a TypeckRootCtxt<'tcx>§fallback_has_occurred: Cell<bool>§diverging_fallback_behavior: DivergingFallbackBehavior§diverging_block_behavior: DivergingBlockBehavior

Implementations§

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub fn check_match( &self, expr: &'tcx Expr<'tcx>, scrut: &'tcx Expr<'tcx>, arms: &'tcx [Arm<'tcx>], orig_expected: Expectation<'tcx>, match_src: MatchSource, ) -> Ty<'tcx>

source

fn explain_never_type_coerced_to_unit( &self, err: &mut Diag<'_>, arm: &Arm<'tcx>, arm_ty: Ty<'tcx>, prior_arm: Option<(Option<HirId>, Ty<'tcx>, Span)>, expr: &Expr<'tcx>, )

source

fn suggest_removing_semicolon_for_coerce( &self, diag: &mut Diag<'_>, expr: &Expr<'tcx>, arm_ty: Ty<'tcx>, prior_arm: Option<(Option<HirId>, Ty<'tcx>, Span)>, )

source

fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [Arm<'tcx>])

When the previously checked expression (the scrutinee) diverges, warn the user about the match arms being unreachable.

source

pub(crate) fn if_fallback_coercion<T>( &self, if_span: Span, cond_expr: &'tcx Expr<'tcx>, then_expr: &'tcx Expr<'tcx>, coercion: &mut CoerceMany<'tcx, '_, T>, ) -> bool
where T: AsCoercionSite,

Handle the fallback arm of a desugared if(-let) like a missing else.

Returns true if there was an error forcing the coercion to the () type.

source

fn explain_if_expr( &self, err: &mut Diag<'_>, ret_reason: Option<(Span, String)>, if_span: Span, cond_expr: &'tcx Expr<'tcx>, then_expr: &'tcx Expr<'tcx>, error: &mut bool, )

Explain why if expressions without else evaluate to () and detect likely irrefutable if let PAT = EXPR {} expressions that could be turned into let PAT = EXPR;.

source

pub(crate) fn maybe_get_coercion_reason( &self, hir_id: HirId, sp: Span, ) -> Option<(Span, String)>

source

pub(crate) fn if_cause( &self, span: Span, cond_span: Span, then_expr: &'tcx Expr<'tcx>, else_expr: &'tcx Expr<'tcx>, then_ty: Ty<'tcx>, else_ty: Ty<'tcx>, tail_defines_return_position_impl_trait: Option<LocalDefId>, ) -> ObligationCause<'tcx>

source

pub(crate) fn demand_scrutinee_type( &self, scrut: &'tcx Expr<'tcx>, contains_ref_bindings: Option<Mutability>, no_arms: bool, ) -> Ty<'tcx>

source

pub(crate) fn return_position_impl_trait_from_match_expectation( &self, expectation: Expectation<'tcx>, ) -> Option<LocalDefId>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn autoderef( &'a self, span: Span, base_ty: Ty<'tcx>, ) -> Autoderef<'a, 'tcx>

source

pub(crate) fn try_overloaded_deref( &self, span: Span, base_ty: Ty<'tcx>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>

source

pub(crate) fn adjust_steps( &self, autoderef: &Autoderef<'a, 'tcx>, ) -> Vec<Adjustment<'tcx>>

Returns the adjustment steps.

source

pub(crate) fn adjust_steps_as_infer_ok( &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_call( &self, call_expr: &'tcx Expr<'tcx>, callee_expr: &'tcx Expr<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn try_overloaded_call_step( &self, call_expr: &'tcx Expr<'tcx>, callee_expr: &'tcx Expr<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], autoderef: &Autoderef<'a, 'tcx>, ) -> Option<CallStep<'tcx>>

source

fn try_overloaded_call_traits( &self, call_expr: &Expr<'_>, adjusted_ty: Ty<'tcx>, opt_arg_exprs: Option<&'tcx [Expr<'tcx>]>, ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)>

source

fn identify_bad_closure_def_and_call( &self, err: &mut Diag<'_>, hir_id: HirId, callee_node: &ExprKind<'_>, callee_span: Span, )

Give appropriate suggestion when encountering ||{/* not callable */}(), where the likely intention is to call the closure, suggest (||{})(). (#55851)

source

fn maybe_suggest_bad_array_definition( &self, err: &mut Diag<'_>, call_expr: &'tcx Expr<'tcx>, callee_expr: &'tcx Expr<'tcx>, ) -> bool

Give appropriate suggestion when encountering [("a", 0) ("b", 1)], where the likely intention is to create an array containing tuples.

source

fn confirm_builtin_call( &self, call_expr: &'tcx Expr<'tcx>, callee_expr: &'tcx Expr<'tcx>, callee_ty: Ty<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn suggest_call_as_method( &self, diag: &mut Diag<'_>, segment: &'tcx PathSegment<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], call_expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, )

Attempts to reinterpret method(rcvr, args...) as rcvr.method(args...) and suggesting the fix if the method probe is successful.

source

fn report_invalid_callee( &self, call_expr: &'tcx Expr<'tcx>, callee_expr: &'tcx Expr<'tcx>, callee_ty: Ty<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], ) -> ErrorGuaranteed

source

fn confirm_deferred_closure_call( &self, call_expr: &'tcx Expr<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, closure_def_id: LocalDefId, fn_sig: FnSig<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn enforce_context_effects( &self, span: Span, callee_did: DefId, callee_args: GenericArgsRef<'tcx>, )

source

fn confirm_overloaded_call( &self, call_expr: &'tcx Expr<'tcx>, arg_exprs: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, method_callee: MethodCallee<'tcx>, ) -> Ty<'tcx>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

fn pointer_kind( &self, t: Ty<'tcx>, span: Span, ) -> Result<Option<PointerKind<'tcx>>, ErrorGuaranteed>

Returns the kind of unsize information of t, or None if t is unknown.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub fn check_expr_closure( &self, closure: &Closure<'tcx>, expr_span: Span, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn deduce_closure_signature( &self, expected_ty: Ty<'tcx>, closure_kind: ClosureKind, ) -> (Option<ExpectedSig<'tcx>>, Option<ClosureKind>)

Given the expected type, figures out what it can about this closure we are about to type check:

source

fn deduce_closure_signature_from_predicates( &self, expected_ty: Ty<'tcx>, closure_kind: ClosureKind, predicates: impl DoubleEndedIterator<Item = (Predicate<'tcx>, Span)>, ) -> (Option<ExpectedSig<'tcx>>, Option<ClosureKind>)

source

fn deduce_sig_from_projection( &self, cause_span: Option<Span>, closure_kind: ClosureKind, projection: PolyProjectionPredicate<'tcx>, ) -> Option<ExpectedSig<'tcx>>

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.

source

fn extract_sig_from_projection( &self, cause_span: Option<Span>, projection: PolyProjectionPredicate<'tcx>, ) -> Option<ExpectedSig<'tcx>>

Given an FnOnce::Output or AsyncFn::Output projection, extract the args and return type to infer a ty::PolyFnSig for the closure.

source

fn extract_sig_from_projection_and_future_bound( &self, cause_span: Option<Span>, projection: PolyProjectionPredicate<'tcx>, ) -> Option<ExpectedSig<'tcx>>

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.

source

fn sig_of_closure( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, closure_kind: ClosureKind, expected_sig: Option<ExpectedSig<'tcx>>, ) -> ClosureSignatures<'tcx>

source

fn sig_of_closure_no_expectation( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, closure_kind: ClosureKind, ) -> ClosureSignatures<'tcx>

If there is no expected signature, then we will convert the types that the user gave into a signature.

source

fn sig_of_closure_with_expectation( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, closure_kind: ClosureKind, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx>

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 S be the (higher-ranked) signature that we derive from the user’s annotations.
  • Let E be the (higher-ranked) signature that we derive from the expectations, if any.
    • If we have no expectation E, then the signature of the closure is S.
    • Otherwise, the signature of the closure is E. Moreover:
      • Skolemize the late-bound regions in E, yielding E'.
      • Instantiate all the late-bound regions bound in the closure within S with fresh (existential) variables, yielding S'
      • 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.

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: the LocalDefId of the closure expression
  • decl: the HIR declaration of the closure
  • body: the body of the closure
  • expected_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.
source

fn sig_of_closure_with_mismatched_number_of_arguments( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx>

source

fn merge_supplied_sig_with_expectation( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, closure_kind: ClosureKind, expected_sigs: ClosureSignatures<'tcx>, ) -> InferResult<'tcx, ClosureSignatures<'tcx>>

Enforce the user’s types against the expectation. See sig_of_closure_with_expectation for details on the overall strategy.

source

fn supplied_sig_of_closure( &self, expr_def_id: LocalDefId, decl: &FnDecl<'tcx>, closure_kind: ClosureKind, ) -> PolyFnSig<'tcx>

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.

source

fn deduce_future_output_from_obligations( &self, body_def_id: LocalDefId, ) -> Option<Ty<'tcx>>

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.

source

fn deduce_future_output_from_projection( &self, cause_span: Span, predicate: PolyProjectionPredicate<'tcx>, ) -> Option<Ty<'tcx>>

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.

source

fn error_sig_of_closure( &self, decl: &FnDecl<'tcx>, guar: ErrorGuaranteed, ) -> PolyFnSig<'tcx>

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.

source

fn closure_sigs( &self, expr_def_id: LocalDefId, bound_sig: PolyFnSig<'tcx>, ) -> ClosureSignatures<'tcx>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn coerce( &self, expr: &Expr<'_>, expr_ty: Ty<'tcx>, target: Ty<'tcx>, allow_two_phase: AllowTwoPhase, cause: Option<ObligationCause<'tcx>>, ) -> RelateResult<'tcx, Ty<'tcx>>

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.

source

pub(crate) fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool

Same as coerce(), but without side-effects.

Returns false if the coercion creates any obligations that result in errors.

source

pub(crate) fn deref_steps( &self, expr_ty: Ty<'tcx>, target: Ty<'tcx>, ) -> Option<usize>

Given a type and a target type, this function will calculate and return how many dereference steps needed to achieve expr_ty <: target. If it’s not possible, return None.

source

pub(crate) fn deref_once_mutably_for_diagnostic( &self, expr_ty: Ty<'tcx>, ) -> Option<Ty<'tcx>>

Given a type, this function will calculate and return the type given for <Ty as Deref>::Target only if Ty also implements DerefMut.

This function is for diagnostics only, since it does not register trait or region sub-obligations. (presumably we could, but it’s not particularly important for diagnostics…)

source

fn try_find_coercion_lub<E>( &self, cause: &ObligationCause<'tcx>, exprs: &[E], prev_ty: Ty<'tcx>, new: &Expr<'_>, new_ty: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>>
where E: AsCoercionSite,

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<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn emit_type_mismatch_suggestions( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, error: Option<TypeError<'tcx>>, )

source

pub(crate) fn emit_coerce_suggestions( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, error: Option<TypeError<'tcx>>, )

source

fn adjust_expr_for_assert_eq_macro( &self, found_expr: &mut &'tcx Expr<'tcx>, expected_expr: &mut Option<&'tcx Expr<'tcx>>, )

Really hacky heuristic to remap an assert_eq! error to the user expressions provided to the macro.

source

pub(crate) fn demand_suptype( &self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, )

Requires that the two types unify, and prints an error message if they don’t.

source

pub(crate) fn demand_suptype_diag( &'a self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Result<(), Diag<'a>>

source

pub fn demand_suptype_with_origin( &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Result<(), Diag<'a>>

source

pub(crate) fn demand_eqtype( &self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, )

source

pub(crate) fn demand_eqtype_diag( &'a self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Result<(), Diag<'a>>

source

pub(crate) fn demand_eqtype_with_origin( &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Result<(), Diag<'a>>

source

pub(crate) fn demand_coerce( &self, expr: &'tcx Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, allow_two_phase: AllowTwoPhase, ) -> Ty<'tcx>

source

pub fn demand_coerce_diag( &'a self, expr: &'tcx Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, allow_two_phase: AllowTwoPhase, ) -> Result<Ty<'tcx>, Diag<'a>>

Checks that the type of expr can be coerced to expected.

N.B., this code relies on self.diverges to be accurate. In particular, assignments to ! will be permitted if the diverges flag is currently “always”.

source

pub(crate) fn note_source_of_type_mismatch_constraint( &self, err: &mut Diag<'_>, expr: &Expr<'_>, source: TypeMismatchSource<'tcx>, ) -> bool

Notes the point at which a variable is constrained to some type incompatible with some expectation given by source.

source

pub(crate) fn annotate_loop_expected_due_to_inference( &self, err: &mut Diag<'_>, expr: &Expr<'_>, error: Option<TypeError<'tcx>>, )

source

fn annotate_expected_due_to_let_ty( &self, err: &mut Diag<'_>, expr: &Expr<'_>, error: Option<TypeError<'tcx>>, )

source

fn annotate_alternative_method_deref( &self, err: &mut Diag<'_>, expr: &Expr<'_>, error: Option<TypeError<'tcx>>, )

source

pub(crate) fn get_conversion_methods_for_diagnostic( &self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>, hir_id: HirId, ) -> Vec<AssocItem>

source

fn has_only_self_parameter(&self, method: &AssocItem) -> bool

This function checks whether the method is not static and does not accept other parameters than self.

source

pub(crate) fn maybe_get_block_expr( &self, expr: &Expr<'tcx>, ) -> Option<&'tcx Expr<'tcx>>

If the given HirId corresponds to a block with a trailing expression, return that expression

source

pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &Expr<'_>) -> bool

source

fn explain_self_literal( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, )

source

fn note_wrong_return_ty_due_to_generic_arg( &self, err: &mut Diag<'_>, expr: &Expr<'_>, checked_ty: Ty<'tcx>, )

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_expr_has_type_or_error( &self, expr: &'tcx Expr<'tcx>, expected_ty: Ty<'tcx>, extend_err: impl FnOnce(&mut Diag<'_>), ) -> Ty<'tcx>

source

pub(crate) fn check_expr_coercible_to_type( &self, expr: &'tcx Expr<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, ) -> Ty<'tcx>

source

pub(crate) fn check_expr_with_hint( &self, expr: &'tcx Expr<'tcx>, expected: Ty<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_with_expectation_and_needs( &self, expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, needs: Needs, ) -> Ty<'tcx>

source

pub(crate) fn check_expr(&self, expr: &'tcx Expr<'tcx>) -> Ty<'tcx>

source

pub(crate) fn check_expr_with_needs( &self, expr: &'tcx Expr<'tcx>, needs: Needs, ) -> Ty<'tcx>

source

pub(crate) fn check_expr_with_expectation( &self, expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>

Invariant: If an expression has any sub-expressions that result in a type error, inspecting that expression’s type with ty.references_error() will return true. Likewise, if an expression is known to diverge, inspecting its type with ty::type_is_bot will return true (n.b.: since Rust is strict, | can appear in the type of an expression that does not, itself, diverge: for example, fn() -> |.) Note that inspecting a type’s structure directly may expose the fact that there are actually multiple representations for Error, so avoid that when err needs to be handled differently.

source

pub(crate) fn check_expr_with_expectation_and_args( &self, expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, args: &'tcx [Expr<'tcx>], call: Option<&'tcx Expr<'tcx>>, ) -> Ty<'tcx>

Same as check_expr_with_expectation, but allows us to pass in the arguments of a ExprKind::Call when evaluating its callee when it is an ExprKind::Path.

source

fn check_expr_kind( &self, expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_unary( &self, unop: UnOp, oprnd: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_addr_of( &self, kind: BorrowKind, mutbl: Mutability, oprnd: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_named_place_expr(&self, oprnd: &'tcx Expr<'tcx>)

Does this expression refer to a place that either:

  • Is based on a local or static.
  • Contains a dereference Note that the adjustments for the children of expr should already have been resolved.
source

fn check_lang_item_path( &self, lang_item: LangItem, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn check_expr_path( &self, qpath: &'tcx QPath<'tcx>, expr: &'tcx Expr<'tcx>, args: Option<&'tcx [Expr<'tcx>]>, call: Option<&'tcx Expr<'tcx>>, ) -> Ty<'tcx>

source

fn check_expr_break( &self, destination: Destination, expr_opt: Option<&'tcx Expr<'tcx>>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_return( &self, expr_opt: Option<&'tcx Expr<'tcx>>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_become( &self, call: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn check_return_expr( &self, return_expr: &'tcx Expr<'tcx>, explicit_return: bool, )

Check an expression that is being returned. For example, this is called with return_expr: $expr when return $expr is encountered.

Note that this function must only be called in function bodies.

explicit_return is true if we’re checking an explicit return expr, and false if we’re checking a trailing expression.

source

fn emit_return_outside_of_fn_body( &self, expr: &Expr<'_>, kind: ReturnLikeStatementKind, )

Emit an error because return or become is used outside of a function body.

expr is the return (become) “statement”, kind is the kind of the statement either Return or Become.

source

fn point_at_return_for_opaque_ty_error( &self, errors: &mut Vec<FulfillmentError<'tcx>>, hir_id: HirId, span: Span, return_expr_ty: Ty<'tcx>, return_span: Span, )

source

pub(crate) fn check_lhs_assignable( &self, lhs: &'tcx Expr<'tcx>, code: ErrCode, op_span: Span, adjust_err: impl FnOnce(&mut Diag<'_>), )

source

pub(crate) fn check_for_missing_semi( &self, expr: &'tcx Expr<'tcx>, err: &mut Diag<'_>, ) -> bool

Check if the expression that could not be assigned to was a typoed expression that

source

pub(crate) fn comes_from_while_condition( &self, original_expr_id: HirId, then: impl FnOnce(&Expr<'_>), )

as opposed from the body of a while loop, which we can naively check by iterating parents until we find a loop…

source

fn check_then_else( &self, cond_expr: &'tcx Expr<'tcx>, then_expr: &'tcx Expr<'tcx>, opt_else_expr: Option<&'tcx Expr<'tcx>>, sp: Span, orig_expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_assign( &self, expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, lhs: &'tcx Expr<'tcx>, rhs: &'tcx Expr<'tcx>, span: Span, ) -> Ty<'tcx>

Type check assignment expression expr of form lhs = rhs. The expected type is () and is passed to the function for the purposes of diagnostics.

source

pub(crate) fn check_expr_let( &self, let_expr: &'tcx LetExpr<'tcx>, hir_id: HirId, ) -> Ty<'tcx>

source

fn check_expr_loop( &self, body: &'tcx Block<'tcx>, source: LoopSource, expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_method_call( &self, expr: &'tcx Expr<'tcx>, segment: &'tcx PathSegment<'tcx>, rcvr: &'tcx Expr<'tcx>, args: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx>

Checks a method call.

source

fn check_expr_cast( &self, e: &'tcx Expr<'tcx>, t: &'tcx Ty<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_array( &self, args: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn suggest_array_len(&self, expr: &'tcx Expr<'tcx>, array_len: u64)

source

fn check_expr_const_block( &self, block: &'tcx ConstBlock, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_repeat( &self, element: &'tcx Expr<'tcx>, count: &'tcx ArrayLen<'tcx>, expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_repeat_element_needs_copy_bound( &self, element: &Expr<'_>, count: Const<'tcx>, element_ty: Ty<'tcx>, )

source

fn check_expr_tuple( &self, elts: &'tcx [Expr<'tcx>], expected: Expectation<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_struct( &self, expr: &Expr<'_>, expected: Expectation<'tcx>, qpath: &QPath<'tcx>, fields: &'tcx [ExprField<'tcx>], base_expr: &'tcx Option<&'tcx Expr<'tcx>>, ) -> Ty<'tcx>

source

fn check_expr_struct_fields( &self, adt_ty: Ty<'tcx>, expected: Expectation<'tcx>, expr: &Expr<'_>, span: Span, variant: &'tcx VariantDef, hir_fields: &'tcx [ExprField<'tcx>], base_expr: &'tcx Option<&'tcx Expr<'tcx>>, )

source

fn check_struct_fields_on_error( &self, fields: &'tcx [ExprField<'tcx>], base_expr: &'tcx Option<&'tcx Expr<'tcx>>, )

source

fn report_missing_fields( &self, adt_ty: Ty<'tcx>, span: Span, remaining_fields: UnordMap<Ident, (FieldIdx, &FieldDef)>, variant: &'tcx VariantDef, hir_fields: &'tcx [ExprField<'tcx>], args: GenericArgsRef<'tcx>, )

Report an error for a struct field expression when there are fields which aren’t provided.

error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
 --> src/main.rs:8:5
  |
8 |     foo::Foo {};
  |     ^^^^^^^^ missing `you_can_use_this_field`

error: aborting due to 1 previous error
source

fn suggest_fru_from_range_and_emit( &self, last_expr_field: &ExprField<'tcx>, variant: &VariantDef, args: GenericArgsRef<'tcx>, err: Diag<'_>, )

If the last field is a range literal, but it isn’t supposed to be, then they probably meant to use functional update syntax.

source

fn report_private_fields( &self, adt_ty: Ty<'tcx>, span: Span, expr_span: Span, private_fields: Vec<&FieldDef>, used_fields: &'tcx [ExprField<'tcx>], )

Report an error for a struct field expression when there are invisible fields.

error: cannot construct `Foo` with struct literal syntax due to private fields
 --> src/main.rs:8:5
  |
8 |     foo::Foo {};
  |     ^^^^^^^^

error: aborting due to 1 previous error
source

fn report_unknown_field( &self, ty: Ty<'tcx>, variant: &'tcx VariantDef, expr: &Expr<'_>, field: &ExprField<'_>, skip_fields: &[ExprField<'_>], kind_name: &str, ) -> ErrorGuaranteed

source

fn available_field_names( &self, variant: &'tcx VariantDef, expr: &Expr<'_>, skip_fields: &[ExprField<'_>], ) -> Vec<Symbol>

source

fn name_series_display(&self, names: Vec<Symbol>) -> String

source

fn find_adt_field( &self, base_def: AdtDef<'tcx>, ident: Ident, nested_fields: &mut SmallVec<[(FieldIdx, &'tcx FieldDef); 1]>, ) -> bool

Find the position of a field named ident in base_def, accounting for unnammed fields. Return whether such a field has been found. The path to it is stored in nested_fields. ident must have been adjusted beforehand.

source

fn check_field( &self, expr: &'tcx Expr<'tcx>, base: &'tcx Expr<'tcx>, field: Ident, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn suggest_await_on_field_access( &self, err: &mut Diag<'_>, field_ident: Ident, base: &'tcx Expr<'tcx>, ty: Ty<'tcx>, )

source

fn ban_nonexisting_field( &self, ident: Ident, base: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>, base_ty: Ty<'tcx>, ) -> ErrorGuaranteed

source

fn ban_private_field_access( &self, expr: &Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident, base_did: DefId, return_ty: Option<Ty<'tcx>>, ) -> ErrorGuaranteed

source

fn ban_take_value_of_method( &self, expr: &Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident, ) -> ErrorGuaranteed

source

fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ParamTy)

source

fn maybe_suggest_array_indexing( &self, err: &mut Diag<'_>, base: &Expr<'_>, field: Ident, len: Const<'tcx>, )

source

fn suggest_first_deref_field( &self, err: &mut Diag<'_>, base: &Expr<'_>, field: Ident, )

source

fn no_such_field_err( &self, field: Ident, expr_t: Ty<'tcx>, id: HirId, ) -> Diag<'_>

source

fn private_field_err(&self, field: Ident, base_did: DefId) -> Diag<'_>

source

pub(crate) fn get_field_candidates_considering_privacy( &self, span: Span, base_ty: Ty<'tcx>, mod_id: DefId, hir_id: HirId, ) -> Vec<(Vec<&'tcx FieldDef>, GenericArgsRef<'tcx>)>

source

pub(crate) fn check_for_nested_field_satisfying( &self, span: Span, matches: &impl Fn(&FieldDef, Ty<'tcx>) -> bool, candidate_field: &FieldDef, subst: GenericArgsRef<'tcx>, field_path: Vec<Ident>, mod_id: DefId, hir_id: HirId, ) -> Option<Vec<Ident>>

This method is called after we have encountered a missing field error to recursively search for the field

source

fn check_expr_index( &self, base: &'tcx Expr<'tcx>, idx: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>, brackets_span: Span, ) -> Ty<'tcx>

source

fn find_and_report_unsatisfied_index_impl( &self, base_expr: &Expr<'_>, base_ty: Ty<'tcx>, ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)>

Try to match an implementation of Index against a self type, and report the unsatisfied predicates that result from confirming this impl.

Given an index expression, sometimes the Self type shallowly but does not deeply satisfy an impl predicate. Instead of simply saying that the type does not support being indexed, we want to point out exactly what nested predicates cause this to be, so that the user can add them to fix their code.

source

fn point_at_index(&self, errors: &mut Vec<FulfillmentError<'tcx>>, span: Span)

source

fn check_expr_yield( &self, value: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

fn check_expr_asm_operand(&self, expr: &'tcx Expr<'tcx>, is_input: bool)

source

fn check_expr_asm(&self, asm: &'tcx InlineAsm<'tcx>) -> Ty<'tcx>

source

fn check_offset_of( &self, container: &'tcx Ty<'tcx>, fields: &[Ident], expr: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source§

impl<'tcx> FnCtxt<'_, 'tcx>

source

pub(crate) fn type_inference_fallback(&self)

Performs type inference fallback, setting FnCtxt::fallback_has_occurred if fallback has occurred.

source

fn fallback_types(&self) -> bool

source

fn fallback_effects(&self) -> bool

source

fn fallback_if_possible( &self, ty: Ty<'tcx>, diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>, ) -> bool

source

fn calculate_diverging_fallback( &self, unresolved_variables: &[Ty<'tcx>], behavior: DivergingFallbackBehavior, ) -> UnordMap<Ty<'tcx>, Ty<'tcx>>

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 != ?NonDiverging

Here ?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.
source

fn lint_never_type_fallback_flowing_into_unsafe_code( &self, unsafe_infer_vars: &OnceCell<UnordMap<TyVid, (HirId, Span, UnsafeUseReason)>>, coercion_graph: &VecGraph<TyVid, true>, root_vid: TyVid, )

source

fn lint_obligations_broken_by_never_type_fallback_change( &self, behavior: DivergingFallbackBehavior, diverging_vids: &[TyVid], )

source

fn create_coercion_graph(&self) -> VecGraph<TyVid, true>

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

fn root_vid(&self, ty: Ty<'tcx>) -> Option<TyVid>

If ty is an unresolved type variable, returns its root vid.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str)

Produces warning on the given node, if the current point in the function is unreachable, and there hasn’t been another warning.

source

pub(crate) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx>

Resolves type and const variables in ty if possible. Unlike the infcx version (resolve_vars_if_possible), this version will also select obligations if it seems useful, in an effort to get more type information.

source

pub(crate) fn record_deferred_call_resolution( &self, closure_def_id: LocalDefId, r: DeferredCallResolution<'tcx>, )

source

pub(crate) fn remove_deferred_call_resolutions( &self, closure_def_id: LocalDefId, ) -> Vec<DeferredCallResolution<'tcx>>

source

fn tag(&self) -> String

source

pub(crate) fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx>

source

pub(crate) fn write_ty(&self, id: HirId, ty: Ty<'tcx>)

source

pub(crate) fn write_field_index( &self, hir_id: HirId, index: FieldIdx, nested_fields: Vec<(Ty<'tcx>, FieldIdx)>, )

source

pub(crate) fn write_resolution( &self, hir_id: HirId, r: Result<(DefKind, DefId), ErrorGuaranteed>, )

source

pub fn write_method_call_and_enforce_effects( &self, hir_id: HirId, span: Span, method: MethodCallee<'tcx>, )

source

fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>)

source

pub fn write_user_type_annotation_from_args( &self, hir_id: HirId, def_id: DefId, args: GenericArgsRef<'tcx>, user_self_ty: Option<UserSelfTy<'tcx>>, )

Given the args that we just converted from the HIR, try to canonicalize them and store them as user-given parameters (i.e., parameters that must be respected by the NLL check).

This should be invoked before any unifications have occurred, so that annotations like Vec<_> are preserved properly.

source

pub fn write_user_type_annotation( &self, hir_id: HirId, canonical_user_type_annotation: CanonicalUserType<'tcx>, )

source

pub fn apply_adjustments(&self, expr: &Expr<'_>, adj: Vec<Adjustment<'tcx>>)

source

pub(crate) fn instantiate_bounds( &self, span: Span, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> InstantiatedPredicates<'tcx>

Instantiates and normalizes the bounds for a given item

source

pub(crate) fn normalize<T>(&self, span: Span, value: T) -> T
where T: TypeFoldable<TyCtxt<'tcx>>,

source

pub(crate) fn require_type_meets( &self, ty: Ty<'tcx>, span: Span, code: ObligationCauseCode<'tcx>, def_id: DefId, )

source

pub(crate) fn require_type_is_sized( &self, ty: Ty<'tcx>, span: Span, code: ObligationCauseCode<'tcx>, )

source

pub(crate) fn require_type_is_sized_deferred( &self, ty: Ty<'tcx>, span: Span, code: ObligationCauseCode<'tcx>, )

source

pub(crate) fn require_type_has_static_alignment( &self, ty: Ty<'tcx>, span: Span, code: ObligationCauseCode<'tcx>, )

source

pub(crate) fn register_bound( &self, ty: Ty<'tcx>, def_id: DefId, cause: ObligationCause<'tcx>, )

source

pub(crate) fn lower_ty(&self, hir_ty: &Ty<'tcx>) -> LoweredTy<'tcx>

source

pub fn lower_ty_saving_user_provided_ty(&self, hir_ty: &Ty<'tcx>) -> Ty<'tcx>

source

pub(super) fn user_args_for_adt(ty: LoweredTy<'tcx>) -> UserArgs<'tcx>

source

pub(crate) fn lower_array_length(&self, length: &ArrayLen<'tcx>) -> Const<'tcx>

source

pub(crate) fn lower_const_arg( &self, const_arg: &'tcx ConstArg<'tcx>, param_def_id: DefId, ) -> Const<'tcx>

source

fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
where T: TypeVisitable<TyCtxt<'tcx>>,

source

pub(crate) fn node_ty(&self, id: HirId) -> Ty<'tcx>

source

pub(crate) fn node_ty_opt(&self, id: HirId) -> Option<Ty<'tcx>>

source

pub(crate) fn register_wf_obligation( &self, arg: GenericArg<'tcx>, span: Span, code: ObligationCauseCode<'tcx>, )

Registers an obligation for checking later, during regionck, that arg is well-formed.

source

pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &Expr<'_>)

Registers obligations that all args are well-formed.

source

pub(crate) fn field_ty( &self, span: Span, field: &'tcx FieldDef, args: GenericArgsRef<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn resolve_rvalue_scopes(&self, def_id: DefId)

source

pub(crate) fn resolve_coroutine_interiors(&self)

Unify the inference variables corresponding to coroutine witnesses, and save all the predicates that were stalled on those inference variables.

This process allows to conservatively save all predicates that do depend on the coroutine interior types, for later processing by check_coroutine_obligations.

We must not attempt to select obligations after this method has run, or risk query cycle ICE.

source

pub(crate) fn report_ambiguity_errors(&self)

source

pub(crate) fn select_obligations_where_possible( &self, mutate_fulfillment_errors: impl Fn(&mut Vec<FulfillmentError<'tcx>>), )

Select as many obligations as we can at present.

source

pub(crate) fn make_overloaded_place_return_type( &self, method: MethodCallee<'tcx>, ) -> Ty<'tcx>

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.

source

pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool

source

pub(crate) fn err_args( &self, len: usize, guar: ErrorGuaranteed, ) -> Vec<Ty<'tcx>>

source

pub(crate) fn resolve_lang_item_path( &self, lang_item: LangItem, span: Span, hir_id: HirId, ) -> (Res, Ty<'tcx>)

source

pub fn resolve_ty_and_res_fully_qualified_call( &self, qpath: &'tcx QPath<'tcx>, hir_id: HirId, span: Span, ) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [PathSegment<'tcx>])

Resolves an associated value path into a base type and associated constant, or method resolution. The newly resolved definition is written into type_dependent_defs.

source

pub(crate) fn get_fn_decl( &self, blk_id: HirId, ) -> Option<(LocalDefId, &'tcx FnDecl<'tcx>, bool)>

Given a HirId, return the HirId of the enclosing function, its FnDecl, and whether a suggestion can be made, None otherwise.

source

pub(crate) fn note_internal_mutation_in_method( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected: Option<Ty<'tcx>>, found: Ty<'tcx>, )

source

pub fn instantiate_value_path( &self, segments: &'tcx [PathSegment<'tcx>], self_ty: Option<LoweredTy<'tcx>>, res: Res, span: Span, path_span: Span, hir_id: HirId, ) -> (Ty<'tcx>, Res)

source

pub(crate) fn add_required_obligations_for_hir( &self, span: Span, def_id: DefId, args: GenericArgsRef<'tcx>, hir_id: HirId, )

Add all the obligations that are required, instantiated and normalized appropriately.

source

fn add_required_obligations_with_code( &self, span: Span, def_id: DefId, args: GenericArgsRef<'tcx>, code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>, )

source

pub fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx>

Try to resolve ty to a structural type, normalizing aliases.

In case there is still ambiguity, the returned type may be an inference variable. This is different from structurally_resolve_type which errors in this case.

source

pub(crate) fn structurally_resolve_type( &self, sp: Span, ty: Ty<'tcx>, ) -> Ty<'tcx>

Resolves ty by a single level if ty is a type variable.

When the new solver is enabled, this will also attempt to normalize the type if it’s a projection (note that it will not deeply normalize projections within the type, just the outermost layer of the type).

If no resolution is possible, then an error is reported. Numeric inference variables may be left unresolved.

source

pub(crate) fn with_breakable_ctxt<F: FnOnce() -> R, R>( &self, id: HirId, ctxt: BreakableCtxt<'tcx>, f: F, ) -> (BreakableCtxt<'tcx>, R)

source

pub(crate) fn probe_instantiate_query_response( &self, span: Span, original_values: &OriginalQueryValues<'tcx>, query_result: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, ) -> InferResult<'tcx, Ty<'tcx>>

Instantiate a QueryResponse in a probe context, without a good ObligationCause.

source

pub(crate) fn expr_in_place(&self, expr_id: HirId) -> bool

Returns true if an expression is contained inside the LHS of an assignment expression.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn adjust_fulfillment_error_for_expr_obligation( &self, error: &mut FulfillmentError<'tcx>, ) -> bool

source

fn point_at_path_if_possible( &self, error: &mut FulfillmentError<'tcx>, def_id: DefId, param: GenericArg<'tcx>, qpath: &QPath<'tcx>, ) -> bool

source

fn point_at_generic_if_possible( &self, error: &mut FulfillmentError<'tcx>, def_id: DefId, param_to_point_at: GenericArg<'tcx>, segment: &PathSegment<'tcx>, ) -> bool

source

fn find_ambiguous_parameter_in<T: TypeVisitable<TyCtxt<'tcx>>>( &self, item_def_id: DefId, t: T, ) -> Option<GenericArg<'tcx>>

source

fn closure_span_overlaps_error( &self, error: &FulfillmentError<'tcx>, span: Span, ) -> bool

source

fn point_at_field_if_possible( &self, def_id: DefId, param_to_point_at: GenericArg<'tcx>, variant_def_id: DefId, expr_fields: &[ExprField<'tcx>], ) -> Option<(&'tcx Expr<'tcx>, Ty<'tcx>)>

source

fn blame_specific_arg_if_possible( &self, error: &mut FulfillmentError<'tcx>, def_id: DefId, param_to_point_at: GenericArg<'tcx>, call_hir_id: HirId, callee_span: Span, receiver: Option<&'tcx Expr<'tcx>>, args: &'tcx [Expr<'tcx>], ) -> bool

  • blame_specific_* means that the function will recursively traverse the expression, looking for the most-specific-possible span to blame.

  • point_at_* means that the function will only go “one level”, pointing at the specific expression mentioned.

blame_specific_arg_if_possible will find the most-specific expression anywhere inside the provided function call expression, and mark it as responsible for the fulfillment error.

source

pub(crate) fn blame_specific_expr_if_possible( &self, error: &mut FulfillmentError<'tcx>, expr: &'tcx Expr<'tcx>, )

Recursively searches for the most-specific blameable expression. For example, if you have a chain of constraints like:

  • want Vec<i32>: Copy
  • because Option<Vec<i32>>: Copy needs Vec<i32>: Copy because impl <T: Copy> Copy for Option<T>
  • because (Option<Vec<i32>, bool) needs Option<Vec<i32>>: Copy because impl <A: Copy, B: Copy> Copy for (A, B) then if you pass in (Some(vec![1, 2, 3]), false), this helper point_at_specific_expr_if_possible will find the expression vec![1, 2, 3] as the “most blameable” reason for this missing constraint.

This function only updates the error span.

source

fn blame_specific_expr_if_possible_for_obligation_cause_code( &self, obligation_cause_code: &ObligationCauseCode<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Result<&'tcx Expr<'tcx>, &'tcx Expr<'tcx>>

source

fn blame_specific_expr_if_possible_for_derived_predicate_obligation( &self, obligation: &ImplDerivedCause<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Result<&'tcx Expr<'tcx>, &'tcx Expr<'tcx>>

We want to achieve the error span in the following example:

struct Burrito<Filling> {
  filling: Filling,
}
impl <Filling: Delicious> Delicious for Burrito<Filling> {}
fn eat_delicious_food<Food: Delicious>(_food: Food) {}

fn will_type_error() {
  eat_delicious_food(Burrito { filling: Kale });
} //                                    ^--- The trait bound `Kale: Delicious`
  //                                         is not satisfied

Without calling this function, the error span will cover the entire argument expression.

Before we do any of this logic, we recursively call point_at_specific_expr_if_possible on the parent obligation. Hence we refine the expr “outwards-in” and bail at the first kind of expression/impl we don’t recognize.

This function returns a Result<&Expr, &Expr> - either way, it returns the Expr whose span should be reported as an error. If it is Ok, then it means it refined successful. If it is Err, then it may be only a partial success - but it cannot be refined even further.

source

fn blame_specific_part_of_expr_corresponding_to_generic_param( &self, param: GenericArg<'tcx>, expr: &'tcx Expr<'tcx>, in_ty: GenericArg<'tcx>, ) -> Result<&'tcx Expr<'tcx>, &'tcx Expr<'tcx>>

Drills into expr to arrive at the equivalent location of find_generic_param in in_ty. For example, given

  • expr: (Some(vec![1, 2, 3]), false)
  • param: T
  • in_ty: (Option<Vec<T>, bool) we would drill until we arrive at vec![1, 2, 3].

If successful, we return Ok(refined_expr). If unsuccessful, we return Err(partially_refined_expr), which will go as far as possible. For example, given (foo(), false) instead, we would drill to foo() and then return Err("foo()").

This means that you can (and should) use the ? try operator to chain multiple calls to this function with different types, since you can only continue drilling the second time if you succeeded the first time.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_casts(&mut self)

source

pub(crate) fn check_transmutes(&self)

source

pub(crate) fn check_asms(&self)

source

pub(crate) fn check_method_argument_types( &self, sp: Span, expr: &'tcx Expr<'tcx>, method: Result<MethodCallee<'tcx>, ErrorGuaranteed>, args_no_rcvr: &'tcx [Expr<'tcx>], tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn check_argument_types( &self, call_span: Span, call_expr: &'tcx Expr<'tcx>, formal_input_tys: &[Ty<'tcx>], formal_output: Ty<'tcx>, expectation: Expectation<'tcx>, provided_args: &'tcx [Expr<'tcx>], c_variadic: bool, tuple_arguments: TupleArgumentsFlag, fn_def_id: Option<DefId>, )

Generic function that factors out common logic from function calls, method calls and overloaded operators.

source

fn report_arg_errors( &self, compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>, formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>, provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>, c_variadic: bool, err_code: ErrCode, fn_def_id: Option<DefId>, call_span: Span, call_expr: &'tcx Expr<'tcx>, ) -> ErrorGuaranteed

source

fn suggest_ptr_null_mut( &self, expected_ty: Ty<'tcx>, provided_ty: Ty<'tcx>, arg: &Expr<'tcx>, err: &mut Diag<'_>, )

source

pub(crate) fn check_lit( &self, lit: &Lit, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn check_struct_path( &self, qpath: &QPath<'tcx>, hir_id: HirId, ) -> Result<(&'tcx VariantDef, Ty<'tcx>), ErrorGuaranteed>

source

fn check_decl_initializer( &self, hir_id: HirId, pat: &'tcx Pat<'tcx>, init: &'tcx Expr<'tcx>, ) -> Ty<'tcx>

source

pub(crate) fn check_decl(&self, decl: Declaration<'tcx>)

source

fn check_decl_local(&self, local: &'tcx LetStmt<'tcx>)

Type check a let statement.

source

fn check_stmt(&self, stmt: &'tcx Stmt<'tcx>)

source

pub(crate) fn check_block_no_value(&self, blk: &'tcx Block<'tcx>)

source

pub(crate) fn check_block_with_expected( &self, blk: &'tcx Block<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn parent_item_span(&self, id: HirId) -> Option<Span>

source

fn get_expr_coercion_span(&self, expr: &Expr<'_>) -> Span

If expr is a match expression that has only one non-! arm, use that arm’s tail expression’s Span, otherwise return expr.span. This is done to give better errors when given code like the following:

if false { return 0i32; } else { 1u32 }
//                               ^^^^ point at this instead of the whole `if` expression
source

fn overwrite_local_ty_if_err( &self, hir_id: HirId, pat: &'tcx Pat<'tcx>, ty: Ty<'tcx>, )

source

fn finish_resolving_struct_path( &self, qpath: &QPath<'tcx>, path_span: Span, hir_id: HirId, ) -> (Res, LoweredTy<'tcx>)

source

pub(super) fn collect_unused_stmts_for_coerce_return_ty( &self, errors_causecode: Vec<(Span, ObligationCauseCode<'tcx>)>, )

source

pub(super) fn adjust_fulfillment_errors_for_expr_obligation( &self, errors: &mut Vec<FulfillmentError<'tcx>>, )

Given a vector of fulfillment errors, try to adjust the spans of the errors to more accurately point at the cause of the failure.

This applies to calls, methods, and struct expressions. This will also try to deduplicate errors that are due to the same cause but might have been created with different ObligationCauses.

source

fn label_fn_like( &self, err: &mut Diag<'_>, callable_def_id: Option<DefId>, callee_ty: Option<Ty<'tcx>>, call_expr: &'tcx Expr<'tcx>, expected_ty: Option<Ty<'tcx>>, expected_idx: Option<usize>, matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>, formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>, is_method: bool, )

source

fn label_generic_mismatches( &self, err: &mut Diag<'_>, callable_def_id: Option<DefId>, matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>, provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>, formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>, is_method: bool, )

source

fn get_hir_params_with_generics( &self, def_id: DefId, is_method: bool, ) -> Vec<(Option<&GenericParam<'_>>, &Param<'_>)>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn obligations_for_self_ty( &self, self_ty: TyVid, ) -> Vec<PredicateObligation<'tcx>>

Returns a list of all obligations whose self type has been unified with the unconstrained type self_ty.

source

fn predicate_has_self_ty( &self, predicate: Predicate<'tcx>, expected_vid: TyVid, ) -> bool

source

fn type_matches_expected_vid(&self, expected_vid: TyVid, ty: Ty<'tcx>) -> bool

source

pub(crate) fn obligations_for_self_ty_next( &self, self_ty: TyVid, ) -> Vec<PredicateObligation<'tcx>>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn body_fn_sig(&self) -> Option<FnSig<'tcx>>

source

pub(crate) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diag<'_>)

source

pub(crate) fn suggest_mismatched_types_on_tail( &self, err: &mut Diag<'_>, expr: &'tcx Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, blk_id: HirId, ) -> bool

On implicit return expressions with mismatched types, provides the following suggestions:

  • Points out the method’s return type as the reason for the expected type.
  • Possible missing semicolon.
  • Possible missing return type if the return type is the default, and not fn main().
source

pub(crate) fn suggest_fn_call( &self, err: &mut Diag<'_>, expr: &Expr<'_>, found: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>) -> bool, ) -> bool

When encountering an fn-like type, try accessing the output of the type and suggesting calling it if it satisfies a predicate (i.e. if the output has a method or a field):

fn foo(x: usize) -> usize { x }
let x: usize = foo;  // suggest calling the `foo` function: `foo(42)`
source

pub(crate) fn extract_callable_info( &self, ty: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)>

Extracts information about a callable type for diagnostics. This is a heuristic – it doesn’t necessarily mean that a type is always callable, because the callable type must also be well-formed to be called.

source

pub(crate) fn suggest_two_fn_call( &self, err: &mut Diag<'_>, lhs_expr: &'tcx Expr<'tcx>, lhs_ty: Ty<'tcx>, rhs_expr: &'tcx Expr<'tcx>, rhs_ty: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, ) -> bool

source

pub(crate) fn suggest_remove_last_method_call( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_deref_ref_or_into( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, ) -> bool

source

fn deconstruct_option_or_result( &self, found_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> Option<(Ty<'tcx>, Ty<'tcx>, Option<(Ty<'tcx>, Ty<'tcx>)>)>

If ty is Option<T>, returns T, T, None. If ty is Result<T, E>, returns T, T, Some(E, E). Otherwise, returns None.

source

pub(crate) fn suggest_boxing_when_appropriate( &self, err: &mut Diag<'_>, span: Span, hir_id: HirId, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool

When encountering the expected boxed value allocated in the stack, suggest allocating it in the heap by calling Box::new().

source

pub(crate) fn suggest_no_capture_closure( &self, err: &mut Diag<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool

When encountering a closure that captures variables, where a FnPtr is expected, suggest a non-capturing closure

source

pub(crate) fn suggest_calling_boxed_future_when_appropriate( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool

When encountering an impl Future where BoxFuture is expected, suggest Box::pin.

source

pub(crate) fn suggest_missing_semicolon( &self, err: &mut Diag<'_>, expression: &'tcx Expr<'tcx>, expected: Ty<'tcx>, needs_block: bool, )

A common error is to forget to add a semicolon at the end of a block, e.g.,

fn foo() {
    bar_that_returns_u32()
}

This routine checks if the return expression in a block would make sense on its own as a statement and the return type has been left as default or has been specified as (). If so, it suggests adding a semicolon.

If the expression is the expression of a closure without block (|| expr), a block is needed to be added too (|| { expr; }). This is denoted by needs_block.

source

pub(crate) fn suggest_missing_return_type( &self, err: &mut Diag<'_>, fn_decl: &FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, fn_id: LocalDefId, ) -> bool

A possible error is to forget to add a return type that is needed:

fn foo() {
    bar_that_returns_u32()
}

This routine checks if the return type is left as default, the method is not part of an impl block and that it isn’t the main method. If so, it suggests setting the return type.

source

fn try_note_caller_chooses_ty_for_ty_param( &self, diag: &mut Diag<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, )

source

fn try_suggest_return_impl_trait( &self, err: &mut Diag<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, fn_id: LocalDefId, )

check whether the return type is a generic type with a trait bound only suggest this if the generic param is not present in the arguments if this is true, hint them towards changing the return type to impl Trait

fn cant_name_it<T: Fn() -> u32>() -> T {
    || 3
}
source

pub(crate) fn suggest_missing_break_or_return_expr( &self, err: &mut Diag<'_>, expr: &'tcx Expr<'tcx>, fn_decl: &FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, id: HirId, fn_id: LocalDefId, )

source

pub(crate) fn suggest_missing_parentheses( &self, err: &mut Diag<'_>, expr: &Expr<'_>, ) -> bool

source

pub(crate) fn suggest_block_to_brackets_peeling_refs( &self, diag: &mut Diag<'_>, expr: &Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

Given an expression type mismatch, peel any & expressions until we get to a block expression, and then suggest replacing the braces with square braces if it was possibly mistaken array syntax.

source

pub(crate) fn suggest_clone_for_ref( &self, diag: &mut Diag<'_>, expr: &Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_copied_cloned_or_as_ref( &self, diag: &mut Diag<'_>, expr: &Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_into( &self, diag: &mut Diag<'_>, expr: &Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_option_to_bool( &self, diag: &mut Diag<'_>, expr: &Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

When expecting a bool and finding an Option, suggests using let Some(..) or .is_some()

source

pub(crate) fn suggest_deref_unwrap_or( &self, err: &mut Diag<'_>, error_span: Span, callee_ty: Option<Ty<'tcx>>, call_ident: Option<Ident>, expected_ty: Ty<'tcx>, provided_ty: Ty<'tcx>, provided_expr: &Expr<'tcx>, is_method: bool, )

source

pub(crate) fn suggest_block_to_brackets( &self, diag: &mut Diag<'_>, blk: &Block<'_>, blk_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, )

Suggest wrapping the block in square brackets instead of curly braces in case the block was mistaken array syntax, e.g. { 1 } -> [ 1 ].

source

pub(crate) fn suggest_floating_point_literal( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected_ty: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected_ty: Ty<'tcx>, ) -> bool

Suggest providing std::ptr::null() or std::ptr::null_mut() if they pass in a literal 0 to an raw pointer.

source

pub(crate) fn suggest_associated_const( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected_ty: Ty<'tcx>, ) -> bool

source

fn is_loop(&self, id: HirId) -> bool

source

fn is_local_statement(&self, id: HirId) -> bool

source

pub(crate) fn note_type_is_not_clone( &self, diag: &mut Diag<'_>, expected_ty: Ty<'tcx>, found_ty: Ty<'tcx>, expr: &Expr<'_>, )

Suggest that &T was cloned instead of T because T does not implement Clone, which is a side-effect of autoref.

source

fn note_type_is_not_clone_inner_expr<'b>( &'b self, expr: &'b Expr<'b>, ) -> &'b Expr<'b>

Given a type mismatch error caused by &T being cloned instead of T, and the expr as the source of this type mismatch, try to find the method call as the source of this error and return that instead. Otherwise, return the original expression.

source

pub(crate) fn is_field_suggestable( &self, field: &FieldDef, hir_id: HirId, span: Span, ) -> bool

source

pub(crate) fn suggest_missing_unwrap_expect( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_coercing_result_via_try_operator( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_returning_value_after_loop( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, expected: Ty<'tcx>, ) -> bool

source

pub(crate) fn suggest_compatible_variants( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected: Ty<'tcx>, expr_ty: Ty<'tcx>, ) -> bool

If the expected type is an enum (Issue #55250) with any variants whose sole field is of the found type, suggest such variants. (Issue #42764)

source

pub(crate) fn suggest_non_zero_new_unwrap( &self, err: &mut Diag<'_>, expr: &Expr<'_>, expected: Ty<'tcx>, expr_ty: Ty<'tcx>, ) -> bool

source

fn can_use_as_ref( &self, expr: &Expr<'_>, ) -> Option<(Vec<(Span, String)>, &'static str)>

Identify some cases where as_ref() would be appropriate and suggest it.

Given the following code:

struct Foo;
fn takes_ref(_: &Foo) {}
let ref opt = Some(Foo);

opt.map(|param| takes_ref(param));

Suggest using opt.as_ref().map(|param| takes_ref(param)); instead.

It only checks for Option and Result and won’t work with

opt.map(|param| { takes_ref(param) });
source

pub(crate) fn suggest_deref_or_ref( &self, expr: &Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, ) -> Option<(Vec<(Span, String)>, String, Applicability, bool, bool)>

This function is used to determine potential “simple” improvements or users’ errors and provide them useful help. For example:

fn some_fn(s: &str) {}

let x = "hey!".to_owned();
some_fn(x); // error

No need to find every potential function which could make a coercion to transform a String into a &str since a & would do the trick!

In addition of this check, it also checks between references mutability state. If the expected is mutable but the provided isn’t, maybe we could just say “Hey, try with &mut!”.

source

fn is_else_if_block(&self, expr: &Expr<'_>) -> bool

Returns whether the given expression is an else if.

source

pub(crate) fn suggest_cast( &self, err: &mut Diag<'_>, expr: &Expr<'_>, checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, expected_ty_expr: Option<&'tcx Expr<'tcx>>, ) -> bool

source

pub(crate) fn suggest_method_call_on_range_literal( &self, err: &mut Diag<'_>, expr: &Expr<'tcx>, checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, )

Identify when the user has written foo..bar() instead of foo.bar().

source

pub(crate) fn suggest_return_binding_for_missing_tail_expr( &self, err: &mut Diag<'_>, expr: &Expr<'_>, checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, )

Identify when the type error is because () is found in a binding that was assigned a block without a tail expression.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn new( root_ctxt: &'a TypeckRootCtxt<'tcx>, param_env: ParamEnv<'tcx>, body_id: LocalDefId, ) -> FnCtxt<'a, 'tcx>

source

pub(crate) fn dcx(&self) -> DiagCtxtHandle<'a>

source

pub(crate) fn cause( &self, span: Span, code: ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx>

source

pub(crate) fn misc(&self, span: Span) -> ObligationCause<'tcx>

source

pub(crate) fn sess(&self) -> &Session

source

pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx>

Creates an TypeErrCtxt with a reference to the in-progress TypeckResults which is used for diagnostics. Use InferCtxtErrorExt::err_ctxt to start one without a TypeckResults.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_transmute( &self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId, )

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn confirm_method( &self, span: Span, self_expr: &'tcx Expr<'tcx>, call_expr: &'tcx Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &Pick<'tcx>, segment: &'tcx PathSegment<'tcx>, ) -> ConfirmResult<'tcx>

source

pub(crate) fn confirm_method_for_diagnostic( &self, span: Span, self_expr: &'tcx Expr<'tcx>, call_expr: &'tcx Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &Pick<'tcx>, segment: &PathSegment<'tcx>, ) -> ConfirmResult<'tcx>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(super) fn lint_edition_dependent_dot_call( &self, self_ty: Ty<'tcx>, segment: &PathSegment<'_>, span: Span, call_expr: &'tcx Expr<'tcx>, self_expr: &'tcx Expr<'tcx>, pick: &Pick<'tcx>, args: &'tcx [Expr<'tcx>], )

source

pub(super) fn lint_fully_qualified_call_from_2018( &self, span: Span, method_name: Ident, self_ty: Ty<'tcx>, self_ty_span: Span, expr_id: HirId, pick: &Pick<'tcx>, )

source

fn trait_path_or_bare_name( &self, span: Span, expr_hir_id: HirId, trait_def_id: DefId, ) -> String

source

fn trait_path( &self, span: Span, expr_hir_id: HirId, trait_def_id: DefId, ) -> Option<String>

source

fn adjust_expr( &self, pick: &Pick<'tcx>, expr: &Expr<'tcx>, outer: Span, ) -> (String, bool)

Creates a string version of the expr that includes explicit adjustments. Returns the string and also a bool indicating whether this is a precise suggestion.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub fn probe_for_return_type_for_diagnostic( &self, span: Span, mode: Mode, return_type: Ty<'tcx>, self_ty: Ty<'tcx>, scope_expr_id: HirId, candidate_filter: impl Fn(&AssocItem) -> bool, ) -> Vec<AssocItem>

This is used to offer suggestions to users. It returns methods that could have been called which have the desired return type. Some effort is made to rule out methods that, if called, would result in an error (basically, the same criteria we would use to decide if a method is a plausible fit for ambiguity purposes).

source

pub fn probe_for_name( &self, mode: Mode, item_name: Ident, return_type: Option<Ty<'tcx>>, is_suggestion: IsSuggestion, self_ty: Ty<'tcx>, scope_expr_id: HirId, scope: ProbeScope, ) -> Result<Pick<'tcx>, MethodError<'tcx>>

source

pub(crate) fn probe_for_name_many( &self, mode: Mode, item_name: Ident, return_type: Option<Ty<'tcx>>, is_suggestion: IsSuggestion, self_ty: Ty<'tcx>, scope_expr_id: HirId, scope: ProbeScope, ) -> Result<Vec<Candidate<'tcx>>, MethodError<'tcx>>

source

pub(crate) fn probe_op<OP, R>( &'a self, span: Span, mode: Mode, method_name: Option<Ident>, return_type: Option<Ty<'tcx>>, is_suggestion: IsSuggestion, self_ty: Ty<'tcx>, scope_expr_id: HirId, scope: ProbeScope, op: OP, ) -> Result<R, MethodError<'tcx>>
where OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool

source

fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool

source

fn impl_into_iterator_should_be_iterator( &self, ty: Ty<'tcx>, span: Span, unsatisfied_predicates: &Vec<(Predicate<'_>, Option<Predicate<'_>>, Option<ObligationCause<'_>>)>, ) -> bool

source

pub fn report_method_error( &self, call_id: HirId, rcvr_ty: Ty<'tcx>, error: MethodError<'tcx>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> ErrorGuaranteed

source

fn suggest_missing_writer( &self, rcvr_ty: Ty<'tcx>, rcvr_expr: &Expr<'tcx>, ) -> Diag<'_>

source

fn suggest_use_shadowed_binding_with_method( &self, self_source: SelfSource<'tcx>, method_name: Ident, ty_str_reported: &str, err: &mut Diag<'_>, )

source

fn report_no_match_method_error( &self, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, expr_id: HirId, source: SelfSource<'tcx>, args: Option<&'tcx [Expr<'tcx>]>, sugg_span: Span, no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> ErrorGuaranteed

source

fn lookup_segments_chain_for_no_match_method( &self, err: &mut Diag<'_>, item_name: Ident, item_kind: &str, source: SelfSource<'tcx>, no_match_data: &NoMatchData<'tcx>, )

If an appropriate error source is not found, check method chain for possible candidates

source

fn find_likely_intended_associated_item( &self, err: &mut Diag<'_>, similar_candidate: AssocItem, span: Span, args: Option<&'tcx [Expr<'tcx>]>, mode: Mode, )

source

pub(crate) fn confusable_method_name( &self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, item_name: Ident, call_args: Option<Vec<Ty<'tcx>>>, ) -> Option<Symbol>

source

fn note_candidates_on_method_error( &self, rcvr_ty: Ty<'tcx>, item_name: Ident, self_source: SelfSource<'tcx>, args: Option<&'tcx [Expr<'tcx>]>, span: Span, err: &mut Diag<'_>, sources: &mut Vec<CandidateSource>, sugg_span: Option<Span>, )

source

fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: HirId)

Look at all the associated functions without receivers in the type’s inherent impls to look for builders that return Self, Option<Self> or Result<Self, _>.

source

fn suggest_associated_call_syntax( &self, err: &mut Diag<'_>, static_candidates: &Vec<CandidateSource>, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, args: Option<&'tcx [Expr<'tcx>]>, sugg_span: Span, )

Suggest calling Ty::method if .method() isn’t found because the method doesn’t take a self receiver.

source

fn suggest_calling_field_as_fn( &self, span: Span, rcvr_ty: Ty<'tcx>, expr: &Expr<'_>, item_name: Ident, err: &mut Diag<'_>, ) -> bool

Suggest calling a field with a type that implements the Fn* traits instead of a method with the same name as the field i.e. (a.my_fn_ptr)(10) instead of a.my_fn_ptr(10).

source

fn report_failed_method_call_on_range_end( &self, tcx: TyCtxt<'tcx>, actual: Ty<'tcx>, source: SelfSource<'tcx>, span: Span, item_name: Ident, ty_str: &str, ) -> Result<(), ErrorGuaranteed>

Suggest possible range with adding parentheses, for example: when encountering 0..1.map(|i| i + 1) suggest (0..1).map(|i| i + 1).

source

fn report_failed_method_call_on_numerical_infer_var( &self, tcx: TyCtxt<'tcx>, actual: Ty<'tcx>, source: SelfSource<'_>, span: Span, item_kind: &str, item_name: Ident, ty_str: &str, ) -> Result<(), ErrorGuaranteed>

source

pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>])

For code rect::area(...), if rect is a local variable and area is a valid assoc method for it, we try to suggest rect.area()

source

fn suggest_calling_method_on_field( &self, err: &mut Diag<'_>, source: SelfSource<'tcx>, span: Span, actual: Ty<'tcx>, item_name: Ident, return_type: Option<Ty<'tcx>>, )

Suggest calling a method on a field i.e. a.field.bar() instead of a.bar()

source

fn suggest_unwrapping_inner_self( &self, err: &mut Diag<'_>, source: SelfSource<'tcx>, actual: Ty<'tcx>, item_name: Ident, )

source

pub(crate) fn note_unmet_impls_on_type( &self, err: &mut Diag<'_>, errors: Vec<FulfillmentError<'tcx>>, suggest_derive: bool, )

source

fn note_predicate_source_and_get_derives( &self, err: &mut Diag<'_>, unsatisfied_predicates: &[(Predicate<'tcx>, Option<Predicate<'tcx>>, Option<ObligationCause<'tcx>>)], ) -> Vec<(String, Span, Symbol)>

source

pub(crate) fn suggest_derive( &self, err: &mut Diag<'_>, unsatisfied_predicates: &[(Predicate<'tcx>, Option<Predicate<'tcx>>, Option<ObligationCause<'tcx>>)], ) -> bool

source

fn note_derefed_ty_has_method( &self, err: &mut Diag<'_>, self_source: SelfSource<'tcx>, rcvr_ty: Ty<'tcx>, item_name: Ident, expected: Expectation<'tcx>, )

source

fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String

Print out the type for use in value namespace.

source

fn suggest_await_before_method( &self, err: &mut Diag<'_>, item_name: Ident, ty: Ty<'tcx>, call: &Expr<'_>, span: Span, return_type: Option<Ty<'tcx>>, )

source

fn suggest_use_candidates<F>( &self, candidates: Vec<DefId>, handle_candidates: F, )
where F: FnOnce(Vec<String>, Vec<String>, Span),

source

fn suggest_valid_traits( &self, err: &mut Diag<'_>, item_name: Ident, valid_out_of_scope_traits: Vec<DefId>, explain: bool, ) -> bool

source

fn suggest_traits_to_import( &self, err: &mut Diag<'_>, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, inputs_len: Option<usize>, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec<DefId>, static_candidates: &[CandidateSource], unsatisfied_bounds: bool, return_type: Option<Ty<'tcx>>, trait_missing_method: bool, )

source

fn detect_and_explain_multiple_crate_versions( &self, err: &mut Diag<'_>, item_def_id: DefId, hir_id: HirId, rcvr_ty: Option<Ty<'_>>, ) -> bool

source

pub(crate) fn suggest_else_fn_with_closure( &self, err: &mut Diag<'_>, expr: &Expr<'_>, found: Ty<'tcx>, expected: Ty<'tcx>, ) -> bool

issue #102320, for unwrap_or with closure as argument, suggest unwrap_or_else FIXME: currently not working for suggesting map_or_else, see #102408

source

fn type_derefs_to_local( &self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, ) -> bool

Checks whether there is a local type somewhere in the chain of autoderefs of rcvr_ty.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub fn method_exists_for_diagnostic( &self, method_name: Ident, self_ty: Ty<'tcx>, call_expr_id: HirId, return_type: Option<Ty<'tcx>>, ) -> bool

Determines whether the type self_ty supports a visible method named method_name or not.

source

pub(crate) fn suggest_method_call( &self, err: &mut Diag<'_>, msg: impl Into<SubdiagMessage> + Debug, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &Expr<'tcx>, span: Option<Span>, )

Adds a suggestion to call the given method to the provided diagnostic.

source

pub fn lookup_method( &self, self_ty: Ty<'tcx>, segment: &'tcx PathSegment<'tcx>, span: Span, call_expr: &'tcx Expr<'tcx>, self_expr: &'tcx Expr<'tcx>, args: &'tcx [Expr<'tcx>], ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>>

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).

§Arguments

Given a method call like foo.bar::<T1,...Tn>(a, b + 1, ...):

  • self: the surrounding FnCtxt (!)
  • self_ty: the (unadjusted) type of the self expression (foo)
  • segment: the name and generic arguments of the method (bar::<T1, ...Tn>)
  • span: the span for the method call
  • call_expr: the complete method call: (foo.bar::<T1,...Tn>(...))
  • self_expr: the self expression (foo)
  • args: the expressions of the arguments (a, b + 1, ...)
source

pub(crate) fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, segment: &PathSegment<'tcx>, span: Span, call_expr: &'tcx Expr<'tcx>, self_expr: &'tcx Expr<'tcx>, ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>>

source

pub fn lookup_probe( &self, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &Expr<'_>, scope: ProbeScope, ) -> Result<Pick<'tcx>, MethodError<'tcx>>

source

pub(crate) fn lookup_probe_for_diagnostic( &self, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &Expr<'_>, scope: ProbeScope, return_type: Option<Ty<'tcx>>, ) -> Result<Pick<'tcx>, MethodError<'tcx>>

source

pub(crate) fn obligation_for_method( &self, cause: ObligationCause<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, ) -> (PredicateObligation<'tcx>, GenericArgsRef<'tcx>)

source

pub(crate) fn lookup_method_in_trait( &self, cause: ObligationCause<'tcx>, m_name: Ident, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>

lookup_method_in_trait is used for overloaded operators. It does a very narrow slice of what the normal probe/confirm path does. In particular, it doesn’t really do any probing: it simply constructs an obligation for a particular trait with the given self type and checks whether that trait is implemented.

source

fn construct_obligation_for_trait( &self, m_name: Ident, trait_def_id: DefId, obligation: PredicateObligation<'tcx>, args: GenericArgsRef<'tcx>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>

source

pub fn resolve_fully_qualified_call( &self, span: Span, method_name: Ident, self_ty: Ty<'tcx>, self_ty_span: Span, expr_id: HirId, ) -> Result<(DefKind, DefId), MethodError<'tcx>>

Performs a full-qualified function call (formerly “universal function call”) lookup. If lookup is successful, it will return the type of definition and the DefId of the found function definition.

§Arguments

Given a function call like Foo::bar::<T1,...Tn>(...):

  • self: the surrounding FnCtxt (!)
  • span: the span of the call, excluding arguments (Foo::bar::<T1, ...Tn>)
  • method_name: the identifier of the function within the container type (bar)
  • self_ty: the type to search within (Foo)
  • self_ty_span the span for the type being searched within (span of Foo)
  • expr_id: the hir::HirId of the expression composing the entire call
source

fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option<AssocItem>

Finds item with name item_name defined in impl/trait def_id and return it, or None, if no such item was defined there.

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_binop_assign( &self, expr: &'tcx Expr<'tcx>, op: BinOp, lhs: &'tcx Expr<'tcx>, rhs: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>

Checks a a <op>= b

source

pub(crate) fn check_binop( &self, expr: &'tcx Expr<'tcx>, op: BinOp, lhs_expr: &'tcx Expr<'tcx>, rhs_expr: &'tcx Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>

Checks a potentially overloaded binary operator.

source

fn enforce_builtin_binop_types( &self, lhs_span: Span, lhs_ty: Ty<'tcx>, rhs_span: Span, rhs_ty: Ty<'tcx>, op: BinOp, ) -> Ty<'tcx>

source

fn check_overloaded_binop( &self, expr: &'tcx Expr<'tcx>, lhs_expr: &'tcx Expr<'tcx>, rhs_expr: &'tcx Expr<'tcx>, op: BinOp, is_assign: IsAssign, expected: Expectation<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)

source

fn check_str_addition( &self, lhs_expr: &'tcx Expr<'tcx>, rhs_expr: &'tcx Expr<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>, err: &mut Diag<'_>, is_assign: IsAssign, op: BinOp, ) -> bool

Provide actionable suggestions when trying to add two strings with incorrect types, like &str + &str, String + String and &str + &String.

If this function returns true it means a note was printed, so we don’t need to print the normal “implementation of std::ops::Add might be missing” note

source

pub(crate) fn check_user_unop( &self, ex: &'tcx Expr<'tcx>, operand_ty: Ty<'tcx>, op: UnOp, expected: Expectation<'tcx>, ) -> Ty<'tcx>

source

fn lookup_op_method( &self, (lhs_expr, lhs_ty): (&'tcx Expr<'tcx>, Ty<'tcx>), opt_rhs: Option<(&'tcx Expr<'tcx>, Ty<'tcx>)>, op: Op, expected: Expectation<'tcx>, ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

fn pattern_cause( &self, ti: &TopInfo<'tcx>, cause_span: Span, ) -> ObligationCause<'tcx>

source

fn demand_eqtype_pat_diag( &'a self, cause_span: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Result<(), Diag<'a>>

source

fn demand_eqtype_pat( &self, cause_span: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Result<(), ErrorGuaranteed>

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn check_pat_top( &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, span: Option<Span>, origin_expr: Option<&'tcx Expr<'tcx>>, decl_origin: Option<DeclOrigin<'tcx>>, )

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.

source

fn check_pat( &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, )

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.

source

fn calc_default_binding_mode( &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, def_br: ByRef, adjust_mode: AdjustMode, max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap)

Compute the new expected type and default binding mode from the old ones as well as the pattern form we are currently checking.

source

fn calc_adjust_mode( &self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>, ) -> AdjustMode

How should the binding mode and expected type be adjusted?

When the pattern is a path pattern, opt_path_res must be Some(res).

source

fn peel_off_references( &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, def_br: ByRef, max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap)

Peel off as many immediately nested & mut? from the expected type as possible and return the new expected type and binding default binding mode. The adjustments vector, if non-empty is stored in a table.

source

fn check_pat_lit( &self, span: Span, lt: &Expr<'tcx>, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx>

source

fn check_pat_range( &self, span: Span, lhs: Option<&'tcx Expr<'tcx>>, rhs: Option<&'tcx Expr<'tcx>>, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx>

source

fn endpoint_has_type(&self, err: &mut Diag<'_>, span: Span, ty: Ty<'_>)

source

fn emit_err_pat_range( &self, span: Span, lhs: Option<(bool, Ty<'tcx>, Span)>, rhs: Option<(bool, Ty<'tcx>, Span)>, ) -> ErrorGuaranteed

source

fn check_pat_ident( &self, pat: &'tcx Pat<'tcx>, user_bind_annot: BindingMode, var_id: HirId, ident: Ident, sub: Option<&'tcx Pat<'tcx>>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn check_binding_alt_eq_ty( &self, ba: BindingMode, span: Span, var_id: HirId, ty: Ty<'tcx>, ti: &TopInfo<'tcx>, )

When a variable is bound several times in a PatKind::Or, it’ll resolve all of the subsequent bindings of the same name to the first usage. Verify that all of these bindings have the same type by comparing them all against the type of that first pat.

source

fn suggest_adding_missing_ref_or_removing_ref( &self, err: &mut Diag<'_>, span: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, ba: BindingMode, )

source

fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>)

Precondition: pat is a Ref(_) pattern

source

fn check_dereferenceable( &self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>, ) -> Result<(), ErrorGuaranteed>

source

fn check_pat_struct( &self, pat: &'tcx Pat<'tcx>, qpath: &QPath<'tcx>, fields: &'tcx [PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn check_pat_path( &self, pat: &Pat<'tcx>, qpath: &QPath<'_>, path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [PathSegment<'tcx>]), expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx>

source

fn maybe_suggest_range_literal( &self, e: &mut Diag<'_>, opt_def_id: Option<DefId>, ident: Ident, ) -> bool

source

fn emit_bad_pat_path( &self, e: Diag<'_>, pat: &Pat<'tcx>, res: Res, pat_res: Res, pat_ty: Ty<'tcx>, segments: &'tcx [PathSegment<'tcx>], )

source

fn check_pat_tuple_struct( &self, pat: &'tcx Pat<'tcx>, qpath: &'tcx QPath<'tcx>, subpats: &'tcx [Pat<'tcx>], ddpos: DotDotPos, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn emit_err_pat_wrong_number_of_fields( &self, pat_span: Span, res: Res, qpath: &QPath<'_>, subpats: &'tcx [Pat<'tcx>], fields: &'tcx [FieldDef], expected: Ty<'tcx>, had_err: Result<(), ErrorGuaranteed>, ) -> ErrorGuaranteed

source

fn check_pat_tuple( &self, span: Span, elements: &'tcx [Pat<'tcx>], ddpos: DotDotPos, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn check_struct_pat_fields( &self, adt_ty: Ty<'tcx>, pat: &'tcx Pat<'tcx>, variant: &'tcx VariantDef, fields: &'tcx [PatField<'tcx>], has_rest_pat: bool, pat_info: PatInfo<'tcx, '_>, ) -> Result<(), ErrorGuaranteed>

source

fn error_tuple_variant_index_shorthand( &self, variant: &VariantDef, pat: &Pat<'_>, fields: &[PatField<'_>], ) -> Result<(), ErrorGuaranteed>

source

fn error_foreign_non_exhaustive_spat( &self, pat: &Pat<'_>, descr: &str, no_fields: bool, )

source

fn error_field_already_bound( &self, span: Span, ident: Ident, other_field: Span, ) -> ErrorGuaranteed

source

fn error_inexistent_fields( &self, kind_name: &str, inexistent_fields: &[&PatField<'tcx>], unmentioned_fields: &mut Vec<(&'tcx FieldDef, Ident)>, pat: &'tcx Pat<'tcx>, variant: &VariantDef, args: GenericArgsRef<'tcx>, ) -> Diag<'a>

source

fn error_tuple_variant_as_struct_pat( &self, pat: &Pat<'_>, fields: &'tcx [PatField<'tcx>], variant: &VariantDef, ) -> Result<(), ErrorGuaranteed>

source

fn get_suggested_tuple_struct_pattern( &self, fields: &[PatField<'_>], variant: &VariantDef, ) -> String

source

fn error_no_accessible_fields( &self, pat: &Pat<'_>, fields: &'tcx [PatField<'tcx>], ) -> Diag<'a>

Returns a diagnostic reporting a struct pattern which is missing an .. due to inaccessible fields.

error: pattern requires `..` due to inaccessible fields
  --> src/main.rs:10:9
   |
LL |     let foo::Foo {} = foo::Foo::default();
   |         ^^^^^^^^^^^
   |
help: add a `..`
   |
LL |     let foo::Foo { .. } = foo::Foo::default();
   |                  ^^^^^^
source

fn lint_non_exhaustive_omitted_patterns( &self, pat: &Pat<'_>, unmentioned_fields: &[(&FieldDef, Ident)], ty: Ty<'tcx>, )

Report that a pattern for a #[non_exhaustive] struct marked with non_exhaustive_omitted_patterns is not exhaustive enough.

Nb: the partner lint for enums lives in compiler/rustc_mir_build/src/thir/pattern/usefulness.rs.

source

fn error_unmentioned_fields( &self, pat: &Pat<'_>, unmentioned_fields: &[(&FieldDef, Ident)], have_inaccessible_fields: bool, fields: &'tcx [PatField<'tcx>], ) -> Diag<'a>

Returns a diagnostic reporting a struct pattern which does not mention some fields.

error[E0027]: pattern does not mention field `bar`
  --> src/main.rs:15:9
   |
LL |     let foo::Foo {} = foo::Foo::new();
   |         ^^^^^^^^^^^ missing field `bar`
source

fn check_pat_box( &self, span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn check_pat_deref( &self, span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn check_pat_ref( &self, pat: &'tcx Pat<'tcx>, inner: &'tcx Pat<'tcx>, pat_mutbl: Mutability, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

source

fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx>

Create a reference type with a fresh region variable.

source

fn try_resolve_slice_ty_to_array_ty( &self, before: &'tcx [Pat<'tcx>], slice: Option<&'tcx Pat<'tcx>>, span: Span, ) -> Option<Ty<'tcx>>

source

fn pat_is_irrefutable(&self, decl_origin: Option<DeclOrigin<'_>>) -> 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).

source

fn check_pat_slice( &self, span: Span, before: &'tcx [Pat<'tcx>], slice: Option<&'tcx Pat<'tcx>>, after: &'tcx [Pat<'tcx>], expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx>

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.

source

fn check_array_pat_len( &self, span: Span, element_ty: Ty<'tcx>, arr_ty: Ty<'tcx>, slice: Option<&'tcx Pat<'tcx>>, len: Const<'tcx>, min_len: u64, ) -> (Option<Ty<'tcx>>, Ty<'tcx>)

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().

source

fn error_scrutinee_inconsistent_length( &self, span: Span, min_len: u64, size: u64, ) -> ErrorGuaranteed

source

fn error_scrutinee_with_rest_inconsistent_length( &self, span: Span, min_len: u64, size: u64, ) -> ErrorGuaranteed

source

fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed

source

fn error_expected_array_or_slice( &self, span: Span, expected_ty: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> ErrorGuaranteed

source

fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>)

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn lookup_derefing( &self, expr: &Expr<'_>, oprnd_expr: &'tcx Expr<'tcx>, oprnd_ty: Ty<'tcx>, ) -> Option<Ty<'tcx>>

Type-check *oprnd_expr with oprnd_expr type-checked already.

source

pub(crate) fn lookup_indexing( &self, expr: &Expr<'_>, base_expr: &'tcx Expr<'tcx>, base_ty: Ty<'tcx>, index_expr: &'tcx Expr<'tcx>, idx_ty: Ty<'tcx>, ) -> Option<(Ty<'tcx>, Ty<'tcx>)>

Type-check *base_expr[index_expr] with base_expr and index_expr type-checked already.

source

fn negative_index( &self, ty: Ty<'tcx>, span: Span, base_expr: &Expr<'_>, ) -> Option<(Ty<'tcx>, Ty<'tcx>)>

source

fn try_index_step( &self, expr: &Expr<'_>, base_expr: &Expr<'_>, autoderef: &Autoderef<'a, 'tcx>, index_ty: Ty<'tcx>, index_expr: &Expr<'_>, ) -> Option<(Ty<'tcx>, Ty<'tcx>)>

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.

source

pub(crate) fn try_overloaded_place_op( &self, span: Span, base_ty: Ty<'tcx>, arg_tys: &[Ty<'tcx>], op: PlaceOp, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>

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.

source

fn try_mutable_overloaded_place_op( &self, span: Span, base_ty: Ty<'tcx>, arg_tys: &[Ty<'tcx>], op: PlaceOp, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>

source

pub(crate) fn convert_place_derefs_to_mutable(&self, expr: &Expr<'_>)

Convert auto-derefs, indices, etc of an expression from Deref and Index into DerefMut and IndexMut respectively.

This is a second pass of typechecking derefs/indices. We need this because we do not always know whether a place needs to be mutable or not in the first pass. This happens whether there is an implicit mutable reborrow, e.g. when the type is used as the receiver of a method call.

source

fn convert_place_op_to_mutable( &self, op: PlaceOp, expr: &Expr<'_>, base_expr: &Expr<'_>, )

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn closure_analyze(&self, body: &'tcx Body<'tcx>)

source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

fn analyze_closure( &self, closure_hir_id: HirId, span: Span, body_id: BodyId, body: &'tcx Body<'tcx>, capture_clause: CaptureBy, )

Analysis starting point.

source

fn coroutine_body_consumes_upvars( &self, coroutine_def_id: LocalDefId, body: &'tcx Body<'tcx>, ) -> 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.

source

fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>>

source

fn process_collected_capture_information( &self, capture_clause: CaptureBy, capture_information: &Vec<(Place<'tcx>, CaptureInfo)>, ) -> (Vec<(Place<'tcx>, CaptureInfo)>, ClosureKind, Option<(Span, Place<'tcx>)>)

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.

source

fn compute_min_captures( &self, closure_def_id: LocalDefId, capture_information: Vec<(Place<'tcx>, CaptureInfo)>, closure_span: Span, )

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
                                                          },
      ],
}
source

fn perform_2229_migration_analysis( &self, closure_def_id: LocalDefId, body_id: BodyId, capture_clause: CaptureBy, span: Span, )

Perform the migration analysis for RFC 2229, and emit lint disjoint_capture_drop_reorder if needed.

source

fn compute_2229_migrations_reasons( &self, auto_trait_reasons: UnordSet<&'static str>, drop_order: bool, ) -> MigrationWarningReason

Combines all the reasons for 2229 migrations

source

fn compute_2229_migrations_for_trait( &self, min_captures: Option<&RootVariableMinCaptureList<'tcx>>, var_hir_id: HirId, closure_clause: CaptureBy, ) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>>

Figures out the list of root variables (and their types) that aren’t completely captured by the closure when capture_disjoint_fields is enabled and auto-traits differ between the root variable and the captured paths.

Returns a tuple containing a HashMap of CapturesInfo that maps to a HashSet of trait names if migration is needed for traits for the provided var_hir_id, otherwise returns None

source

fn compute_2229_migrations_for_drop( &self, closure_def_id: LocalDefId, closure_span: Span, min_captures: Option<&RootVariableMinCaptureList<'tcx>>, closure_clause: CaptureBy, var_hir_id: HirId, ) -> Option<FxIndexSet<UpvarMigrationInfo>>

Figures out the list of root variables (and their types) that aren’t completely captured by the closure when capture_disjoint_fields is enabled and drop order of some path starting at that root variable might be affected.

The output list would include a root variable if:

  • It would have been moved into the closure when capture_disjoint_fields wasn’t enabled, and
  • It wasn’t completely captured by the closure, and
  • One of the paths starting at this root variable, that is not captured needs Drop.

This function only returns a HashSet of CapturesInfo for significant drops. If there are no significant drops than None is returned

source

fn compute_2229_migrations( &self, closure_def_id: LocalDefId, closure_span: Span, closure_clause: CaptureBy, min_captures: Option<&RootVariableMinCaptureList<'tcx>>, ) -> (Vec<NeededMigration>, MigrationWarningReason)

Figures out the list of root variables (and their types) that aren’t completely captured by the closure when capture_disjoint_fields is enabled and either drop order of some path starting at that root variable might be affected or auto-traits differ between the root variable and the captured paths.

The output list would include a root variable if:

  • It would have been moved into the closure when capture_disjoint_fields wasn’t enabled, and
  • It wasn’t completely captured by the closure, and
  • One of the paths starting at this root variable, that is not captured needs Drop or
  • One of the paths captured does not implement all the auto-traits its root variable implements.

Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String containing the reason why root variables whose HirId is contained in the vector should be captured

source

fn has_significant_drop_outside_of_captures( &self, closure_def_id: LocalDefId, closure_span: Span, base_path_ty: Ty<'tcx>, captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool

This is a helper function to compute_2229_migrations_precise_pass. Provided the type of a root variable and a list of captured paths starting at this root variable (expressed using list of Projection slices), it returns true if there is a path that is not captured starting at this root variable that implements Drop.

The way this function works is at a given call it looks at type base_path_ty of some base path say P and then list of projection slices which represent the different captures moved into the closure starting off of P.

This will make more sense with an example:


struct FancyInteger(i32); // This implements Drop

struct Point { x: FancyInteger, y: FancyInteger }
struct Color;

struct Wrapper { p: Point, c: Color }

fn f(w: Wrapper) {
  let c = || {
      // Closure captures w.p.x and w.c by move.
  };

  c();
}

If capture_disjoint_fields wasn’t enabled the closure would’ve moved w instead of the precise paths. If we look closely w.p.y isn’t captured which implements Drop and therefore Drop ordering would change and we want this function to return true.

Call stack to figure out if we need to migrate for w would look as follows:

Our initial base path is just w, and the paths captured from it are w[p, x] and w[c]. Notation:

  • Ty(place): Type of place
  • (a, b): Represents the function parameters base_path_ty and captured_by_move_projs respectively.
                 (Ty(w), [ &[p, x], &[c] ])
//                              |
//                 ----------------------------
//                 |                          |
//                 v                          v
       (Ty(w.p), [ &[x] ])          (Ty(w.c), [ &[] ]) // I(1)
//                 |                          |
//                 v                          v
       (Ty(w.p), [ &[x] ])                 false
//                 |
//                 |
//       -------------------------------
//       |                             |
//       v                             v
    (Ty((w.p).x), [ &[] ])     (Ty((w.p).y), []) // IMP 2
//       |                             |
//       v                             v
       false              NeedsSignificantDrop(Ty(w.p.y))
//                                     |
//                                     v
                                     true

IMP 1 (Ty(w.c), [ &[] ]): Notice the single empty slice inside captured_projs. This implies that the w.c is completely captured by the closure. Since drop for this path will be called when the closure is dropped we don’t need to migrate for it.

IMP 2 (Ty((w.p).y), []): Notice that captured_projs is empty. This implies that this path wasn’t captured by the closure. Also note that even though we didn’t capture this path, the function visits it, which is kind of the point of this function. We then return if the type of w.p.y implements Drop, which in this case is true.

Consider another example:

struct X;
impl Drop for X {}

struct Y(X);
impl Drop for Y {}

fn foo() {
    let y = Y(X);
    let c = || move(y.0);
}

Note that y.0 is captured by the closure. When this function is called for y, it will return true, because even though all paths starting at y are captured, y itself implements Drop which will be affected since y isn’t completely captured.

source

fn init_capture_kind_for_place( &self, place: &Place<'tcx>, capture_clause: CaptureBy, ) -> UpvarCapture

source

fn place_for_root_variable( &self, closure_def_id: LocalDefId, var_hir_id: HirId, ) -> Place<'tcx>

source

fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool

source

fn log_capture_analysis_first_pass( &self, closure_def_id: LocalDefId, capture_information: &Vec<(Place<'tcx>, CaptureInfo)>, closure_span: Span, )

source

fn log_closure_min_capture_info( &self, closure_def_id: LocalDefId, closure_span: Span, )

source

fn determine_capture_mutability( &self, typeck_results: &'a TypeckResults<'tcx>, place: &Place<'tcx>, ) -> Mutability

A captured place is mutable if

  1. Projections don’t include a Deref of an immut-borrow, and
  2. PlaceBase is mut or projections include a Deref of a mut-borrow.
source§

impl<'a, 'tcx> FnCtxt<'a, 'tcx>

source

pub(crate) fn resolve_type_vars_in_body( &self, body: &'tcx Body<'tcx>, ) -> &'tcx TypeckResults<'tcx>

Methods from Deref<Target = TypeckRootCtxt<'tcx>>§

source

pub(crate) fn register_predicate(&self, obligation: PredicateObligation<'tcx>)

source

pub(crate) fn register_predicates<I>(&self, obligations: I)
where I: IntoIterator<Item = PredicateObligation<'tcx>>,

source

pub(crate) fn register_infer_ok_obligations<T>( &self, infer_ok: InferOk<'tcx, T>, ) -> T

source

fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>)

Methods from Deref<Target = InferCtxt<'tcx>>§

source

pub fn at<'a>( &'a self, cause: &'a ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, ) -> At<'a, 'tcx>

source

pub fn fork(&self) -> InferCtxt<'tcx>

Forks the inference context, creating a new inference context with the same inference variables in the same state. This can be used to “branch off” many tests from the same common state.

source

pub fn fork_with_intercrate(&self, intercrate: bool) -> InferCtxt<'tcx>

Forks the inference context, creating a new inference context with the same inference variables in the same state, except possibly changing the intercrate mode. This can be used to “branch off” many tests from the same common state. Used in negative coherence.

source

pub fn canonicalize_query<V>( &self, value: ParamEnvAnd<'tcx, V>, query_state: &mut OriginalQueryValues<'tcx>, ) -> Canonical<TyCtxt<'tcx>, ParamEnvAnd<'tcx, V>>
where V: TypeFoldable<TyCtxt<'tcx>>,

Canonicalizes a query value V. When we canonicalize a query, we not only canonicalize unbound inference variables, but we also replace all free regions whatsoever. So for example a query like T: Trait<'static> would be canonicalized to

T: Trait<'?0>

with a mapping M that maps '?0 to 'static.

To get a good understanding of what is happening here, check out the chapter in the rustc dev guide.

source

pub fn canonicalize_response<V>(&self, value: V) -> Canonical<TyCtxt<'tcx>, V>
where V: TypeFoldable<TyCtxt<'tcx>>,

Canonicalizes a query response V. When we canonicalize a query response, we only canonicalize unbound inference variables, and we leave other free regions alone. So, continuing with the example from canonicalize_query, if there was an input query T: Trait<'static>, it would have been canonicalized to

T: Trait<'?0>

with a mapping M that maps '?0 to 'static. But if we found that there exists only one possible impl of Trait, and it looks like

impl<T> Trait<'static> for T { .. }

then we would prepare a query result R that (among other things) includes a mapping to '?0 := 'static. When canonicalizing this query result R, we would leave this reference to 'static alone.

To get a good understanding of what is happening here, check out the chapter in the rustc dev guide.

source

pub fn canonicalize_user_type_annotation<V>( &self, value: V, ) -> Canonical<TyCtxt<'tcx>, V>
where V: TypeFoldable<TyCtxt<'tcx>>,

source

pub fn make_canonicalized_query_response<T>( &self, inference_vars: CanonicalVarValues<TyCtxt<'tcx>>, answer: T, fulfill_cx: &mut (dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>> + 'tcx), ) -> Result<&'tcx Canonical<TyCtxt<'tcx>, QueryResponse<'tcx, T>>, NoSolution>
where T: Debug + TypeFoldable<TyCtxt<'tcx>>, Canonical<TyCtxt<'tcx>, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,

This method is meant to be invoked as the final step of a canonical query implementation. It is given:

  • the instantiated variables inference_vars created from the query key
  • the result answer of the query
  • a fulfillment context fulfill_cx that may contain various obligations which have yet to be proven.

Given this, the function will process the obligations pending in fulfill_cx:

  • If all the obligations can be proven successfully, it will package up any resulting region obligations (extracted from infcx) along with the fully resolved value answer into a query result (which is then itself canonicalized).
  • If some obligations can be neither proven nor disproven, then the same thing happens, but the resulting query is marked as ambiguous.
  • Finally, if any of the obligations result in a hard error, then Err(NoSolution) is returned.
source

pub fn make_query_response_ignoring_pending_obligations<T>( &self, inference_vars: CanonicalVarValues<TyCtxt<'tcx>>, answer: T, ) -> Canonical<TyCtxt<'tcx>, QueryResponse<'tcx, T>>
where T: Debug + TypeFoldable<TyCtxt<'tcx>>,

A version of make_canonicalized_query_response that does not pack in obligations, for contexts that want to drop pending obligations instead of treating them as an ambiguity (e.g. typeck “probing” contexts).

If you DO want to keep track of pending obligations (which include all region obligations, so this includes all cases that care about regions) with this function, you have to do it yourself, by e.g., having them be a part of the answer.

source

pub fn clone_opaque_types_for_query_response( &self, ) -> Vec<(OpaqueTypeKey<TyCtxt<'tcx>>, Ty<'tcx>)>

Used by the new solver as that one takes the opaque types at the end of a probe to deal with multiple candidates without having to recompute them.

source

pub fn instantiate_query_response_and_region_obligations<R>( &self, cause: &ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<TyCtxt<'tcx>, QueryResponse<'tcx, R>>, ) -> Result<InferOk<'tcx, R>, TypeError<TyCtxt<'tcx>>>
where R: Debug + TypeFoldable<TyCtxt<'tcx>>,

Given the (canonicalized) result to a canonical query, instantiates the result so it can be used, plugging in the values from the canonical query. (Note that the result may have been ambiguous; you should check the certainty level of the query before applying this function.)

To get a good understanding of what is happening here, check out the chapter in the rustc dev guide.

source

pub fn instantiate_nll_query_response_and_region_obligations<R>( &self, cause: &ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<TyCtxt<'tcx>, QueryResponse<'tcx, R>>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, ) -> Result<InferOk<'tcx, R>, TypeError<TyCtxt<'tcx>>>
where R: Debug + TypeFoldable<TyCtxt<'tcx>>,

An alternative to instantiate_query_response_and_region_obligations that is more efficient for NLL. NLL is a bit more advanced in the “transition to chalk” than the rest of the compiler. During the NLL type check, all of the “processing” of types and things happens in queries – the NLL checker itself is only interested in the region obligations ('a: 'b or T: 'b) that come out of these queries, which it wants to convert into MIR-based constraints and solve. Therefore, it is most convenient for the NLL Type Checker to directly consume the QueryOutlivesConstraint values that arise from doing a query. This is contrast to other parts of the compiler, which would prefer for those QueryOutlivesConstraint to be converted into the older infcx-style constraints (e.g., calls to sub_regions or register_region_obligation).

Therefore, instantiate_nll_query_response_and_region_obligations performs the same basic operations as instantiate_query_response_and_region_obligations but it returns its result differently:

  • It creates an instantiation S that maps from the original query variables to the values computed in the query result. If any errors arise, they are propagated back as an Err result.
  • In the case of a successful instantiation, we will append QueryOutlivesConstraint values onto the output_query_region_constraints vector for the solver to use (if an error arises, some values may also be pushed, but they should be ignored).
  • It can happen (though it rarely does currently) that equating types and things will give rise to subobligations that must be processed. In this case, those subobligations are propagated back in the return value.
  • Finally, the query result (of type R) is propagated back, after applying the instantiation S.
source

pub fn query_outlives_constraint_to_obligation( &self, _: (OutlivesPredicate<TyCtxt<'tcx>, GenericArg<'tcx>>, ConstraintCategory<'tcx>), cause: ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, ) -> Obligation<'tcx, Predicate<'tcx>>

source

pub fn instantiate_canonical<T>( &self, span: Span, canonical: &Canonical<TyCtxt<'tcx>, T>, ) -> (T, CanonicalVarValues<TyCtxt<'tcx>>)
where T: TypeFoldable<TyCtxt<'tcx>>,

Creates an instantiation S for the canonical value with fresh inference variables and placeholders then applies it to the canonical value. Returns both the instantiated result and the instantiation S.

This can be invoked as part of constructing an inference context at the start of a query (see InferCtxtBuilder::build_with_canonical). It basically brings the canonical value “into scope” within your new infcx.

At the end of processing, the instantiation S (once canonicalized) then represents the values that you computed for each of the canonical inputs to your query.

source

pub fn instantiate_canonical_var( &self, span: Span, cv_info: CanonicalVarInfo<TyCtxt<'tcx>>, universe_map: impl Fn(UniverseIndex) -> UniverseIndex, ) -> GenericArg<'tcx>

Given the “info” about a canonical variable, creates a fresh variable for it. If this is an existentially quantified variable, then you’ll get a new inference variable; if it is a universally quantified variable, you get a placeholder.

FIXME(-Znext-solver): This is public because it’s used by the new trait solver which has a different canonicalization routine. We should somehow deduplicate all of this.

source

pub fn replace_opaque_types_with_inference_vars<T>( &self, value: T, body_id: LocalDefId, span: Span, param_env: ParamEnv<'tcx>, ) -> InferOk<'tcx, T>
where T: TypeFoldable<TyCtxt<'tcx>>,

This is a backwards compatibility hack to prevent breaking changes from lazy TAIT around RPIT handling.

source

pub fn handle_opaque_type( &self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span, param_env: ParamEnv<'tcx>, ) -> Result<Vec<Goal<TyCtxt<'tcx>, Predicate<'tcx>>>, TypeError<TyCtxt<'tcx>>>

source

pub fn register_member_constraints( &self, opaque_type_key: OpaqueTypeKey<TyCtxt<'tcx>>, concrete_ty: Ty<'tcx>, span: Span, )

Given the map opaque_types containing the opaque impl Trait types whose underlying, hidden types are being inferred, this method adds constraints to the regions appearing in those underlying hidden types to ensure that they at least do not refer to random scopes within the current function. These constraints are not (quite) sufficient to guarantee that the regions are actually legal values; that final condition is imposed after region inference is done.

§The Problem

Let’s work through an example to explain how it works. Assume the current function is as follows:

fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)

Here, we have two impl Trait types whose values are being inferred (the impl Bar<'a> and the impl Bar<'b>). Conceptually, this is sugar for a setup where we define underlying opaque types (Foo1, Foo2) and then, in the return type of foo, we reference those definitions:

type Foo1<'x> = impl Bar<'x>;
type Foo2<'x> = impl Bar<'x>;
fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
                   //  ^^^^ ^^
                   //  |    |
                   //  |    args
                   //  def_id

As indicating in the comments above, each of those references is (in the compiler) basically generic paramters (args) applied to the type of a suitable def_id (which identifies Foo1 or Foo2).

Now, at this point in compilation, what we have done is to replace each of the references (Foo1<'a>, Foo2<'b>) with fresh inference variables C1 and C2. We wish to use the values of these variables to infer the underlying types of Foo1 and Foo2. That is, this gives rise to higher-order (pattern) unification constraints like:

for<'a> (Foo1<'a> = C1)
for<'b> (Foo1<'b> = C2)

For these equation to be satisfiable, the types C1 and C2 can only refer to a limited set of regions. For example, C1 can only refer to 'static and 'a, and C2 can only refer to 'static and 'b. The job of this function is to impose that constraint.

Up to this point, C1 and C2 are basically just random type inference variables, and hence they may contain arbitrary regions. In fact, it is fairly likely that they do! Consider this possible definition of foo:

fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
        (&*x, &*y)
    }

Here, the values for the concrete types of the two impl traits will include inference variables:

&'0 i32
&'1 i32

Ordinarily, the subtyping rules would ensure that these are sufficiently large. But since impl Bar<'a> isn’t a specific type per se, we don’t get such constraints by default. This is where this function comes into play. It adds extra constraints to ensure that all the regions which appear in the inferred type are regions that could validly appear.

This is actually a bit of a tricky constraint in general. We want to say that each variable (e.g., '0) can only take on values that were supplied as arguments to the opaque type (e.g., 'a for Foo1<'a>) or 'static, which is always in scope. We don’t have a constraint quite of this kind in the current region checker.

§The Solution

We generally prefer to make <= constraints, since they integrate best into the region solver. To do that, we find the “minimum” of all the arguments that appear in the args: that is, some region which is less than all the others. In the case of Foo1<'a>, that would be 'a (it’s the only choice, after all). Then we apply that as a least bound to the variables (e.g., 'a <= '0).

In some cases, there is no minimum. Consider this example:

fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }

Here we would report a more complex “in constraint”, like 'r in ['a, 'b, 'static] (where 'r is some region appearing in the hidden type).

§Constrain regions, not the hidden concrete type

Note that generating constraints on each region Rc is not the same as generating an outlives constraint on Tc itself. For example, if we had a function like this:

fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
  (x, y)
}

// Equivalent to:
type FooReturn<'a, T> = impl Foo<'a>;
fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> {
  (x, y)
}

then the hidden type Tc would be (&'0 u32, T) (where '0 is an inference variable). If we generated a constraint that Tc: 'a, then this would incorrectly require that T: 'a – but this is not necessary, because the opaque type we create will be allowed to reference T. So we only generate a constraint that '0: 'a.

source

pub fn inject_new_hidden_type_unchecked( &self, opaque_type_key: OpaqueTypeKey<TyCtxt<'tcx>>, hidden_ty: OpaqueHiddenType<'tcx>, )

Insert a hidden type into the opaque type storage, making sure it hasn’t previously been defined. This does not emit any constraints and it’s the responsibility of the caller to make sure that the item bounds of the opaque are checked.

source

pub fn insert_hidden_type( &self, opaque_type_key: OpaqueTypeKey<TyCtxt<'tcx>>, span: Span, param_env: ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, goals: &mut Vec<Goal<TyCtxt<'tcx>, Predicate<'tcx>>>, ) -> Result<(), TypeError<TyCtxt<'tcx>>>

Insert a hidden type into the opaque type storage, equating it with any previous entries if necessary.

This does not add the item bounds of the opaque as nested obligations. That is only necessary when normalizing the opaque itself, not when getting the opaque type constraints from somewhere else.

source

pub fn add_item_bounds_for_hidden_type( &self, def_id: DefId, args: &'tcx RawList<(), GenericArg<'tcx>>, param_env: ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, goals: &mut Vec<Goal<TyCtxt<'tcx>, Predicate<'tcx>>>, )

source

pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>)

Registers that the given region obligation must be resolved from within the scope of body_id. These regions are enqueued and later processed by regionck, when full type information is available (see region_obligations field for more information).

source

pub fn register_region_obligation_with_cause( &self, sup_type: Ty<'tcx>, sub_region: Region<'tcx>, cause: &ObligationCause<'tcx>, )

source

pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>>

Trait queries just want to pass back type obligations “as is”

source

pub fn process_registered_region_obligations( &self, outlives_env: &OutlivesEnvironment<'tcx>, deeply_normalize_ty: impl FnMut(Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Ty<'tcx>>>, SubregionOrigin<'tcx>) -> Result<Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Ty<'tcx>>>, NoSolution>, ) -> Result<(), (Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Ty<'tcx>>>, SubregionOrigin<'tcx>)>

Process the region obligations that must be proven (during regionck) for the given body_id, given information about the region bounds in scope and so forth.

See the region_obligations field of InferCtxt for some comments about how this function fits into the overall expected flow of the inferencer. The key point is that it is invoked after all type-inference variables have been bound – right before lexical region resolution.

source

pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, deeply_normalize_ty: impl Fn(Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Ty<'tcx>>>, SubregionOrigin<'tcx>) -> Result<Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Ty<'tcx>>>, NoSolution>, ) -> Vec<RegionResolutionError<'tcx>>

Process the region constraints and return any errors that result. After this, no more unification operations should be done – or the compiler will panic – but it is legal to use resolve_vars_if_possible as well as fully_resolve.

If you are in a crate that has access to rustc_trait_selection, then it’s probably better to use resolve_regions, which knows how to normalize registered region obligations.

source

pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx>

Obtains (and clears) the current set of region constraints. The inference context is still usable: further unifications will simply add new constraints.

This method is not meant to be used with normal lexical region resolution. Rather, it is used in the NLL mode as a kind of interim hack: basically we run normal type-check and generate region constraints as normal, but then we take them and translate them into the form that the NLL solver understands. See the NLL module for mode details.

source

pub fn with_region_constraints<R>( &self, op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, ) -> R

Gives temporary access to the region constraint data.

source

pub fn projection_ty_to_infer( &self, param_env: ParamEnv<'tcx>, projection_ty: AliasTy<TyCtxt<'tcx>>, cause: ObligationCause<'tcx>, recursion_depth: usize, obligations: &mut Vec<Obligation<'tcx, Predicate<'tcx>>>, ) -> Ty<'tcx>

Instead of normalizing an associated type projection, this function generates an inference variable and registers an obligation that this inference variable must be the result of the given projection. This allows us to proceed with projections while they cannot be resolved yet due to missing information or simply due to the lack of access to the trait resolution machinery.

source

pub fn super_combine_tys<R>( &self, relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, ) -> Result<Ty<'tcx>, TypeError<TyCtxt<'tcx>>>

source

pub fn super_combine_consts<R>( &self, relation: &mut R, a: Const<'tcx>, b: Const<'tcx>, ) -> Result<Const<'tcx>, TypeError<TyCtxt<'tcx>>>

source

pub fn instantiate_ty_var<R>( &self, relation: &mut R, target_is_expected: bool, target_vid: TyVid, instantiation_variance: Variance, source_ty: Ty<'tcx>, ) -> Result<(), TypeError<TyCtxt<'tcx>>>

The idea is that we should ensure that the type variable target_vid is equal to, a subtype of, or a supertype of source_ty.

For this, we will instantiate target_vid with a generalized version of source_ty. Generalization introduces other inference variables wherever subtyping could occur. This also does the occurs checks, detecting whether instantiating target_vid would result in a cyclic type. We eagerly error in this case.

This is not expected to be used anywhere except for an implementation of TypeRelation. Do not use this, and instead please use At::eq, for all other usecases (i.e. setting the value of a type var).

source

pub fn enter_forall_and_leak_universe<T>( &self, binder: Binder<TyCtxt<'tcx>, T>, ) -> T
where T: TypeFoldable<TyCtxt<'tcx>> + Copy,

Replaces all bound variables (lifetimes, types, and constants) bound by binder with placeholder variables in a new universe. This means that the new placeholders can only be named by inference variables created after this method has been called.

This is the first step of checking subtyping when higher-ranked things are involved. For more details visit the relevant sections of the rustc dev guide.

fn enter_forall should be preferred over this method.

source

pub fn enter_forall<T, U>( &self, forall: Binder<TyCtxt<'tcx>, T>, f: impl FnOnce(T) -> U, ) -> U
where T: TypeFoldable<TyCtxt<'tcx>> + Copy,

Replaces all bound variables (lifetimes, types, and constants) bound by binder with placeholder variables in a new universe and then calls the closure f with the instantiated value. The new placeholders can only be named by inference variables created inside of the closure f or afterwards.

This is the first step of checking subtyping when higher-ranked things are involved. For more details visit the relevant sections of the rustc dev guide.

This method should be preferred over fn enter_forall_and_leak_universe.

source

pub fn leak_check( &self, outer_universe: UniverseIndex, only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, ) -> Result<(), TypeError<TyCtxt<'tcx>>>

See RegionConstraintCollector::leak_check. We only check placeholder leaking into outer_universe, i.e. placeholders which cannot be named by that universe.

source

pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
where F: FnOnce() -> Result<T, E>, T: TypeFoldable<TyCtxt<'tcx>>,

This rather funky routine is used while processing expected types. What happens here is that we want to propagate a coercion through the return type of a fn to its argument. Consider the type of Option::Some, which is basically for<T> fn(T) -> Option<T>. So if we have an expression Some(&[1, 2, 3]), and that has the expected type Option<&[u32]>, we would like to type check &[1, 2, 3] with the expectation of &[u32]. This will cause us to coerce from &[u32; 3] to &[u32] and make the users life more pleasant.

The way we do this is using fudge_inference_if_ok. What the routine actually does is to start a snapshot and execute the closure f. In our example above, what this closure will do is to unify the expectation (Option<&[u32]>) with the actual return type (Option<?T>, where ?T represents the variable instantiated for T). This will cause ?T to be unified with &?a [u32], where ?a is a fresh lifetime variable. The input type (?T) is then returned by f().

At this point, fudge_inference_if_ok will normalize all type variables, converting ?T to &?a [u32] and end the snapshot. The problem is that we can’t just return this type out, because it references the region variable ?a, and that region variable was popped when we popped the snapshot.

So what we do is to keep a list (region_vars, in the code below) of region variables created during the snapshot (here, ?a). We fold the return value and replace any such regions with a new region variable (e.g., ?b) and return the result (&?b [u32]). This can then be used as the expectation for the fn argument.

The important point here is that, for soundness purposes, the regions in question are not particularly important. We will use the expected types to guide coercions, but we will still type-check the resulting types from those coercions against the actual types (?T, Option<?T>) – and remember that after the snapshot is popped, the variable ?T is no longer unified.

source

pub fn in_snapshot(&self) -> bool

source

pub fn num_open_snapshots(&self) -> usize

source

pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
where F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,

Execute f and commit the bindings if closure f returns Ok(_).

source

pub fn probe<R, F>(&self, f: F) -> R
where F: FnOnce(&CombinedSnapshot<'tcx>) -> R,

Execute f then unroll any bindings it creates.

source

pub fn region_constraints_added_in_snapshot( &self, snapshot: &CombinedSnapshot<'tcx>, ) -> bool

Scan the constraints produced since snapshot and check whether we added any region constraints.

source

pub fn opaque_types_added_in_snapshot( &self, snapshot: &CombinedSnapshot<'tcx>, ) -> bool

source

pub fn dcx(&self) -> DiagCtxtHandle<'_>

source

pub fn defining_opaque_types(&self) -> &'tcx RawList<(), LocalDefId>

source

pub fn next_trait_solver(&self) -> bool

source

pub fn freshen<T>(&self, t: T) -> T
where T: TypeFoldable<TyCtxt<'tcx>>,

source

pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin

Returns the origin of the type variable identified by vid.

No attempt is made to resolve vid to its root variable.

source

pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin>

Returns the origin of the const variable identified by vid

source

pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx>

source

pub fn unresolved_variables(&self) -> Vec<Ty<'tcx>>

source

pub fn unsolved_effects(&self) -> Vec<Const<'tcx>>

source

pub fn sub_regions( &self, origin: SubregionOrigin<'tcx>, a: Region<'tcx>, b: Region<'tcx>, )

source

pub fn member_constraint( &self, key: OpaqueTypeKey<TyCtxt<'tcx>>, definition_span: Span, hidden_ty: Ty<'tcx>, region: Region<'tcx>, in_regions: &Rc<Vec<Region<'tcx>>>, )

Require that the region r be equal to one of the regions in the set regions.

source

pub fn coerce_predicate( &self, cause: &ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, predicate: Binder<TyCtxt<'tcx>, CoercePredicate<TyCtxt<'tcx>>>, ) -> Result<Result<InferOk<'tcx, ()>, TypeError<TyCtxt<'tcx>>>, (TyVid, TyVid)>

Processes a Coerce predicate from the fulfillment context. This is NOT the preferred way to handle coercion, which is to invoke FnCtxt::coerce or a similar method (see coercion.rs).

This method here is actually a fallback that winds up being invoked when FnCtxt::coerce encounters unresolved type variables and records a coercion predicate. Presently, this method is equivalent to subtype_predicate – that is, “coercing” a to b winds up actually requiring a <: b. This is of course a valid coercion, but it’s not as flexible as FnCtxt::coerce would be.

(We may refactor this in the future, but there are a number of practical obstacles. Among other things, FnCtxt::coerce presently records adjustments that are required on the HIR in order to perform the coercion, and we don’t currently have a way to manage that.)

source

pub fn subtype_predicate( &self, cause: &ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, predicate: Binder<TyCtxt<'tcx>, SubtypePredicate<TyCtxt<'tcx>>>, ) -> Result<Result<InferOk<'tcx, ()>, TypeError<TyCtxt<'tcx>>>, (TyVid, TyVid)>

source

pub fn region_outlives_predicate( &self, cause: &ObligationCause<'tcx>, predicate: Binder<TyCtxt<'tcx>, OutlivesPredicate<TyCtxt<'tcx>, Region<'tcx>>>, )

source

pub fn num_ty_vars(&self) -> usize

Number of type variables created so far.

source

pub fn next_ty_var(&self, span: Span) -> Ty<'tcx>

source

pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx>

source

pub fn next_ty_var_id_in_universe( &self, span: Span, universe: UniverseIndex, ) -> TyVid

source

pub fn next_ty_var_in_universe( &self, span: Span, universe: UniverseIndex, ) -> Ty<'tcx>

source

pub fn next_const_var(&self, span: Span) -> Const<'tcx>

source

pub fn next_const_var_with_origin( &self, origin: ConstVariableOrigin, ) -> Const<'tcx>

source

pub fn next_const_var_in_universe( &self, span: Span, universe: UniverseIndex, ) -> Const<'tcx>

source

pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid

source

pub fn next_int_var(&self) -> Ty<'tcx>

source

pub fn next_float_var(&self) -> Ty<'tcx>

source

pub fn next_region_var(&self, origin: RegionVariableOrigin) -> Region<'tcx>

Creates a fresh region variable with the next available index. The variable will be created in the maximum universe created thus far, allowing it to name any region created thus far.

source

pub fn next_region_var_in_universe( &self, origin: RegionVariableOrigin, universe: UniverseIndex, ) -> Region<'tcx>

Creates a fresh region variable with the next available index in the given universe; typically, you can use next_region_var and just use the maximal universe.

source

pub fn universe_of_region(&self, r: Region<'tcx>) -> UniverseIndex

Return the universe that the region r was created in. For most regions (e.g., 'static, named regions from the user, etc) this is the root universe U0. For inference variables or placeholders, however, it will return the universe which they are associated.

source

pub fn num_region_vars(&self) -> usize

Number of region variables created so far.

source

pub fn next_nll_region_var( &self, origin: NllRegionVariableOrigin, ) -> Region<'tcx>

Just a convenient wrapper of next_region_var for using during NLL.

source

pub fn next_nll_region_var_in_universe( &self, origin: NllRegionVariableOrigin, universe: UniverseIndex, ) -> Region<'tcx>

Just a convenient wrapper of next_region_var for using during NLL.

source

pub fn var_for_def( &self, span: Span, param: &GenericParamDef, ) -> GenericArg<'tcx>

source

pub fn var_for_effect(&self, param: &GenericParamDef) -> GenericArg<'tcx>

source

pub fn fresh_args_for_item( &self, span: Span, def_id: DefId, ) -> &'tcx RawList<(), GenericArg<'tcx>>

Given a set of generics defined on a type or impl, returns the generic parameters mapping each type/region parameter to a fresh inference variable.

source

pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed>

Returns true if errors have been reported since this infcx was created. This is sometimes used as a heuristic to skip reporting errors that often occur as a result of earlier errors, but where it’s hard to be 100% sure (e.g., unresolved inference variables, regionck errors).

source

pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed)

Set the “tainted by errors” flag to true. We call this when we observe an error from a prior pass.

source

pub fn region_var_origin(&self, vid: RegionVid) -> RegionVariableOrigin

source

pub fn get_region_var_origins(&self) -> IndexVec<RegionVid, RegionVariableInfo>

Clone the list of variable regions. This is used only during NLL processing to put the set of region variables into the NLL region context.

source

pub fn take_opaque_types( &self, ) -> IndexMap<OpaqueTypeKey<TyCtxt<'tcx>>, OpaqueTypeDecl<'tcx>, BuildHasherDefault<FxHasher>>

source

pub fn clone_opaque_types( &self, ) -> IndexMap<OpaqueTypeKey<TyCtxt<'tcx>>, OpaqueTypeDecl<'tcx>, BuildHasherDefault<FxHasher>>

source

pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool

source

pub fn ty_to_string(&self, t: Ty<'tcx>) -> String

source

pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, UniverseIndex>

If TyVar(vid) resolves to a type, return that type. Else, return the universe index of TyVar(vid).

source

pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx>

source

pub fn shallow_resolve_const(&self, ct: Const<'tcx>) -> Const<'tcx>

source

pub fn root_var(&self, var: TyVid) -> TyVid

source

pub fn root_const_var(&self, var: ConstVid) -> ConstVid

source

pub fn root_effect_var(&self, var: EffectVid) -> EffectVid

source

pub fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'tcx>

Resolves an int var to a rigid int type, if it was constrained to one, or else the root int var in the unification table.

source

pub fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'tcx>

Resolves a float var to a rigid int type, if it was constrained to one, or else the root float var in the unification table.

source

pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
where T: TypeFoldable<TyCtxt<'tcx>>,

Where possible, replaces type/const variables in value with their final value. Note that region variables are unaffected. If a type/const variable has not been unified, it is left as is. This is an idempotent operation that does not affect inference state in any way and so you can do it at will.

source

pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
where T: TypeFoldable<TyCtxt<'tcx>>,

source

pub fn probe_const_var( &self, vid: ConstVid, ) -> Result<Const<'tcx>, UniverseIndex>

source

pub fn probe_effect_var(&self, vid: EffectVid) -> Option<Const<'tcx>>

source

pub fn fully_resolve<T>(&self, value: T) -> Result<T, FixupError>
where T: TypeFoldable<TyCtxt<'tcx>>,

Attempts to resolve all type/region/const variables in value. Region inference must have been run already (e.g., by calling resolve_regions_and_report_errors). If some variable was never unified, an Err results.

This method is idempotent, but it not typically not invoked except during the writeback phase.

source

pub fn instantiate_binder_with_fresh_vars<T>( &self, span: Span, lbrct: BoundRegionConversionTime, value: Binder<TyCtxt<'tcx>, T>, ) -> T
where T: TypeFoldable<TyCtxt<'tcx>> + Copy,

source

pub fn verify_generic_bound( &self, origin: SubregionOrigin<'tcx>, kind: GenericKind<'tcx>, a: Region<'tcx>, bound: VerifyBound<'tcx>, )

source

pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option<ClosureKind>

Obtains the latest type of the given closure; this may be a closure in the current function, in which case its ClosureKind may not yet be known.

source

pub fn universe(&self) -> UniverseIndex

source

pub fn create_next_universe(&self) -> UniverseIndex

Creates and return a fresh universe that extends all previous universes. Updates self.universe to that new universe.

source

pub fn try_const_eval_resolve( &self, param_env: ParamEnv<'tcx>, unevaluated: UnevaluatedConst<TyCtxt<'tcx>>, span: Span, ) -> Result<Const<'tcx>, ErrorHandled>

source

pub fn const_eval_resolve( &self, param_env: ParamEnv<'tcx>, unevaluated: UnevaluatedConst<TyCtxt<'tcx>>, span: Span, ) -> Result<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>

Resolves and evaluates a constant.

The constant can be located on a trait like <A as B>::C, in which case the given generic parameters and environment are used to resolve the constant. Alternatively if the constant has generic parameters in scope the instantiations are used to evaluate the value of the constant. For example in fn foo<T>() { let _ = [0; bar::<T>()]; } the repeat count constant bar::<T>() requires a instantiation for T, if the instantiation for T is still too generic for the constant to be evaluated then Err(ErrorHandled::TooGeneric) is returned.

This handles inferences variables within both param_env and args by performing the operation on their respective canonical forms.

source

pub fn is_ty_infer_var_definitely_unchanged<'a>( &'a self, ) -> impl Fn(TyOrConstInferVar) + Captures<'tcx> + 'a

The returned function is used in a fast path. If it returns true the variable is unchanged, false indicates that the status is unknown.

source

pub fn ty_or_const_infer_var_changed( &self, infer_var: TyOrConstInferVar, ) -> bool

ty_or_const_infer_var_changed is equivalent to one of these two:

  • shallow_resolve(ty) != ty (where ty.kind = ty::Infer(_))
  • shallow_resolve(ct) != ct (where ct.kind = ty::ConstKind::Infer(_))

However, ty_or_const_infer_var_changed is more efficient. It’s always inlined, despite being large, because it has only two call sites that are extremely hot (both in traits::fulfill’s checking of stalled_on inference variables), and it handles both Ty and ty::Const without having to resort to storing full GenericArgs in stalled_on.

source

pub fn attach_obligation_inspector( &self, inspector: fn(_: &InferCtxt<'tcx>, _: &Obligation<'tcx, Predicate<'tcx>>, _: Result<Certainty, NoSolution>), )

Attach a callback to be invoked on each root obligation evaluated in the new trait solver.

source

pub fn find_block_span(&self, block: &'tcx Block<'tcx>) -> Span

Given a hir::Block, get the span of its last expression or statement, peeling off any inner blocks.

source

pub fn find_block_span_from_hir_id(&self, hir_id: HirId) -> Span

Given a hir::HirId for a block, get the span of its last expression or statement, peeling off any inner blocks.

Trait Implementations§

source§

impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx>

source§

type Target = TypeckRootCtxt<'tcx>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx>

source§

fn tcx(&self) -> TyCtxt<'tcx>

source§

fn dcx(&self) -> DiagCtxtHandle<'_>

source§

fn item_def_id(&self) -> LocalDefId

Returns the LocalDefId of the overarching item whose constituents get lowered.
source§

fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> Region<'tcx>

Returns the region to use when a lifetime is omitted (and not elided).
source§

fn ty_infer(&self, param: Option<&GenericParamDef>, span: Span) -> Ty<'tcx>

Returns the type to use when a type is omitted.
source§

fn ct_infer(&self, param: Option<&GenericParamDef>, span: Span) -> Const<'tcx>

Returns the const to use when a const is omitted.
source§

fn probe_ty_param_bounds( &self, _: Span, def_id: LocalDefId, _: Ident, ) -> EarlyBinder<'tcx, &'tcx [(Clause<'tcx>, Span)]>

Probe bounds in scope where the bounded type coincides with the given type parameter. Read more
source§

fn lower_assoc_ty( &self, span: Span, item_def_id: DefId, item_segment: &PathSegment<'tcx>, poly_trait_ref: PolyTraitRef<'tcx>, ) -> Ty<'tcx>

Lower an associated type to a projection. Read more
source§

fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<AdtDef<'tcx>>

Returns AdtDef if ty is an ADT. Read more
source§

fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span)

Record the lowered type of a HIR node in this context.
source§

fn infcx(&self) -> Option<&InferCtxt<'tcx>>

The inference context of the lowering context if applicable.
source§

fn lower_fn_sig( &self, decl: &FnDecl<'tcx>, _generics: Option<&Generics<'_>>, _hir_id: HirId, _hir_ty: Option<&Ty<'_>>, ) -> (Vec<Ty<'tcx>>, Ty<'tcx>)

source§

fn lowerer(&self) -> &dyn HirTyLowerer<'tcx>
where Self: Sized,

Convenience method for coercing the lowering context into a trait object type. Read more
source§

impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx>

source§

type TypeckResults<'a> = Ref<'a, TypeckResults<'tcx>> where Self: 'a

source§

type Error = ErrorGuaranteed

source§

fn typeck_results(&self) -> Self::TypeckResults<'_>

source§

fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T

source§

fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx>

source§

fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error

source§

fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>

source§

fn tainted_by_errors(&self) -> Result<(), ErrorGuaranteed>

source§

fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool

source§

fn body_owner_def_id(&self) -> LocalDefId

source§

fn tcx(&self) -> TyCtxt<'tcx>

Auto Trait Implementations§

§

impl<'a, 'tcx> !Freeze for FnCtxt<'a, 'tcx>

§

impl<'a, 'tcx> !RefUnwindSafe for FnCtxt<'a, 'tcx>

§

impl<'a, 'tcx> !Send for FnCtxt<'a, 'tcx>

§

impl<'a, 'tcx> !Sync for FnCtxt<'a, 'tcx>

§

impl<'a, 'tcx> Unpin for FnCtxt<'a, 'tcx>

§

impl<'a, 'tcx> !UnwindSafe for FnCtxt<'a, 'tcx>

Blanket Implementations§

source§

impl<T> Aligned for T

source§

const ALIGN: Alignment = _

Alignment of Self.
source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, R> CollectAndApply<T, R> for T

source§

fn collect_and_apply<I, F>(iter: I, f: F) -> R
where I: Iterator<Item = T>, F: FnOnce(&[T]) -> R,

Equivalent to f(&iter.collect::<Vec<_>>()).

source§

type Output = R

source§

impl<T> Filterable for T

source§

fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>

Creates a filterable data provider with the given name for debugging. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
source§

impl<P> IntoQueryParam<P> for P

source§

impl<T> MaybeResult<T> for T

source§

type Error = !

source§

fn from(_: Result<T, <T as MaybeResult<T>>::Error>) -> T

source§

fn to_result(self) -> Result<T, <T as MaybeResult<T>>::Error>

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<I, T, U> Upcast<I, U> for T
where U: UpcastFrom<I, T>,

source§

fn upcast(self, interner: I) -> U

source§

impl<I, T> UpcastFrom<I, T> for T

source§

fn upcast_from(from: T, _tcx: I) -> T

source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<Tcx, T> Value<Tcx> for T
where Tcx: DepContext,

source§

default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed, ) -> T

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<'a, T> Captures<'a> for T
where T: ?Sized,

source§

impl<T> ErasedDestructor for T
where T: 'static,

source§

impl<T> MaybeSendSync for T

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 272 bytes