Struct rustc_infer::infer::InferCtxt [−][src]
pub struct InferCtxt<'a, 'tcx> {Show 14 fields
pub tcx: TyCtxt<'tcx>,
pub defining_use_anchor: LocalDefId,
pub in_progress_typeck_results: Option<&'a RefCell<TypeckResults<'tcx>>>,
pub inner: RefCell<InferCtxtInner<'tcx>>,
skip_leak_check: Cell<bool>,
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
pub selection_cache: SelectionCache<'tcx>,
pub evaluation_cache: EvaluationCache<'tcx>,
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<Predicate<'tcx>>>>,
pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
tainted_by_errors_flag: Cell<bool>,
err_count_on_creation: usize,
in_snapshot: Cell<bool>,
universe: Cell<UniverseIndex>,
}
Fields
tcx: TyCtxt<'tcx>
defining_use_anchor: LocalDefId
The DefId
of the item in whose context we are performing inference or typeck.
It is used to check whether an opaque type use is a defining use.
in_progress_typeck_results: Option<&'a RefCell<TypeckResults<'tcx>>>
During type-checking/inference of a body, in_progress_typeck_results
contains a reference to the typeck results being built up, which are
used for reading closure kinds/signatures as they are inferred,
and for error reporting logic to read arbitrary node types.
inner: RefCell<InferCtxtInner<'tcx>>
skip_leak_check: Cell<bool>
If set, this flag causes us to skip the ‘leak check’ during higher-ranked subtyping operations. This flag is a temporary one used to manage the removal of the leak-check: for the time being, we still run the leak-check, but we issue warnings. This flag can only be set to true when entering a snapshot.
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>
Once region inference is done, the values for each variable.
selection_cache: SelectionCache<'tcx>
Caches the results of trait selection. This cache is used for things that have to do with the parameters in scope.
evaluation_cache: EvaluationCache<'tcx>
Caches the results of trait evaluation.
reported_trait_errors: RefCell<FxHashMap<Span, Vec<Predicate<'tcx>>>>
the set of predicates on which errors have been reported, to avoid reporting the same error twice.
reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>
tainted_by_errors_flag: Cell<bool>
When an error occurs, we want to avoid reporting “derived”
errors that are due to this original failure. Normally, we
handle this with the err_count_on_creation
count, which
basically just tracks how many errors were reported when we
started type-checking a fn and checks to see if any new errors
have been reported since then. Not great, but it works.
However, when errors originated in other passes – notably resolve – this heuristic breaks down. Therefore, we have this auxiliary flag that one can set whenever one creates a type-error that is due to an error in a prior pass.
Don’t read this flag directly, call is_tainted_by_errors()
and set_tainted_by_errors()
.
err_count_on_creation: usize
Track how many errors were reported when this infcx is created.
If the number of errors increases, that’s also a sign (line
tained_by_errors
) to avoid reporting certain kinds of errors.
in_snapshot: Cell<bool>
This flag is true while there is an active snapshot.
universe: Cell<UniverseIndex>
What is the innermost universe we have created? Starts out as
UniverseIndex::root()
but grows from there as we enter
universal quantifiers.
N.B., at present, we exclude the universal quantifiers on the
item we are type-checking, and just consider those names as
part of the root universe. So this would only get incremented
when we enter into a higher-ranked (for<..>
) type or trait
bound.
Implementations
pub fn at(
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>
) -> At<'a, 'tcx>
pub fn canonicalize_query<V>(
&self,
value: V,
query_state: &mut OriginalQueryValues<'tcx>
) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'tcx>,
pub fn canonicalize_query<V>(
&self,
value: V,
query_state: &mut OriginalQueryValues<'tcx>
) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'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.
pub fn canonicalize_response<V>(&self, value: V) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'tcx>,
pub fn canonicalize_response<V>(&self, value: V) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'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.
pub fn canonicalize_user_type_annotation<V>(
&self,
value: V
) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'tcx>,
pub fn canonicalize_query_keep_static<V>(
&self,
value: V,
query_state: &mut OriginalQueryValues<'tcx>
) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'tcx>,
pub fn canonicalize_query_keep_static<V>(
&self,
value: V,
query_state: &mut OriginalQueryValues<'tcx>
) -> Canonicalized<'tcx, V> where
V: TypeFoldable<'tcx>,
A variant of canonicalize_query
that does not
canonicalize 'static
. This is useful when
the query implementation can perform more efficient
handling of 'static
regions (e.g. trait evaluation).
pub fn make_canonicalized_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>> where
T: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
pub fn make_canonicalized_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>> where
T: Debug + TypeFoldable<'tcx>,
Canonical<'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 valueanswer
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.
pub fn make_query_response_ignoring_pending_obligations<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T
) -> Canonical<'tcx, QueryResponse<'tcx, T>> where
T: Debug + TypeFoldable<'tcx>,
pub fn make_query_response_ignoring_pending_obligations<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T
) -> Canonical<'tcx, QueryResponse<'tcx, T>> where
T: Debug + TypeFoldable<'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.
fn make_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>
) -> Result<QueryResponse<'tcx, T>, NoSolution> where
T: Debug + TypeFoldable<'tcx>,
fn make_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>
) -> Result<QueryResponse<'tcx, T>, NoSolution> where
T: Debug + TypeFoldable<'tcx>,
Helper for make_canonicalized_query_response
that does
everything up until the final canonicalization.
pub fn instantiate_query_response_and_region_obligations<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, R> where
R: Debug + TypeFoldable<'tcx>,
pub fn instantiate_query_response_and_region_obligations<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, R> where
R: Debug + TypeFoldable<'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.
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<'tcx, QueryResponse<'tcx, R>>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>
) -> InferResult<'tcx, R> where
R: Debug + TypeFoldable<'tcx>,
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<'tcx, QueryResponse<'tcx, R>>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>
) -> InferResult<'tcx, R> where
R: Debug + TypeFoldable<'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 a substitution
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 anErr
result. - In the case of a successful substitution, we will append
QueryOutlivesConstraint
values onto theoutput_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 substitutionS
.
fn query_response_substitution<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where
R: Debug + TypeFoldable<'tcx>,
fn query_response_substitution<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where
R: Debug + TypeFoldable<'tcx>,
Given the original values and the (canonicalized) result from computing a query, returns a substitution that can be applied to the query result to convert the result back into the original namespace.
The substitution also comes accompanied with subobligations that arose from unification; these might occur if (for example) we are doing lazy normalization and the value assigned to a type variable is unified with an unnormalized projection.
fn query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> CanonicalVarValues<'tcx> where
R: Debug + TypeFoldable<'tcx>,
fn query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> CanonicalVarValues<'tcx> where
R: Debug + TypeFoldable<'tcx>,
Given the original values and the (canonicalized) result from computing a query, returns a guess at a substitution that can be applied to the query result to convert the result back into the original namespace. This is called a guess because it uses a quick heuristic to find the values for each canonical variable; if that quick heuristic fails, then we will instantiate fresh inference variables for each canonical variable instead. Therefore, the result of this method must be properly unified
fn unify_query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
result_subst: &CanonicalVarValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, ()> where
R: Debug + TypeFoldable<'tcx>,
fn unify_query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
result_subst: &CanonicalVarValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>
) -> InferResult<'tcx, ()> where
R: Debug + TypeFoldable<'tcx>,
Given a “guess” at the values for the canonical variables in the input, try to unify with the actual values found in the query result. Often, but not always, this is a no-op, because we already found the mapping in the “guessing” step.
See also: query_response_substitution_guess
fn query_outlives_constraints_into_obligations<'a>(
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
result_subst: &'a CanonicalVarValues<'tcx>
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx>
fn query_outlives_constraints_into_obligations<'a>(
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
result_subst: &'a CanonicalVarValues<'tcx>
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx>
Converts the region constraints resulting from a query into an iterator of obligations.
fn unify_canonical_vars(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
variables1: &OriginalQueryValues<'tcx>,
variables2: impl Fn(BoundVar) -> GenericArg<'tcx>
) -> InferResult<'tcx, ()>
fn unify_canonical_vars(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
variables1: &OriginalQueryValues<'tcx>,
variables2: impl Fn(BoundVar) -> GenericArg<'tcx>
) -> InferResult<'tcx, ()>
Given two sets of values for the same set of canonical variables, unify them. The second set is produced lazily by supplying indices from the first set.
pub fn instantiate_canonical_with_fresh_inference_vars<T>(
&self,
span: Span,
canonical: &Canonical<'tcx, T>
) -> (T, CanonicalVarValues<'tcx>) where
T: TypeFoldable<'tcx>,
pub fn instantiate_canonical_with_fresh_inference_vars<T>(
&self,
span: Span,
canonical: &Canonical<'tcx, T>
) -> (T, CanonicalVarValues<'tcx>) where
T: TypeFoldable<'tcx>,
Creates a substitution S for the canonical value with fresh inference variables and applies it to the canonical value. Returns both the instantiated result and the substitution S.
This is only meant to be invoked as part of constructing an
inference context at the start of a query (see
InferCtxtBuilder::enter_with_canonical
). It basically
brings the canonical value “into scope” within your new infcx.
At the end of processing, the substitution S (once canonicalized) then represents the values that you computed for each of the canonical inputs to your query.
fn instantiate_canonical_vars(
&self,
span: Span,
variables: &List<CanonicalVarInfo<'tcx>>,
universe_map: impl Fn(UniverseIndex) -> UniverseIndex
) -> CanonicalVarValues<'tcx>
fn instantiate_canonical_vars(
&self,
span: Span,
variables: &List<CanonicalVarInfo<'tcx>>,
universe_map: impl Fn(UniverseIndex) -> UniverseIndex
) -> CanonicalVarValues<'tcx>
Given the “infos” about the canonical variables from some
canonical, creates fresh variables with the same
characteristics (see instantiate_canonical_var
for
details). You can then use substitute
to instantiate the
canonical variable with these inference variables.
fn instantiate_canonical_var(
&self,
span: Span,
cv_info: CanonicalVarInfo<'tcx>,
universe_map: impl Fn(UniverseIndex) -> UniverseIndex
) -> GenericArg<'tcx>
fn instantiate_canonical_var(
&self,
span: Span,
cv_info: CanonicalVarInfo<'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.
pub fn super_combine_tys<R>(
&self,
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>
) -> RelateResult<'tcx, Ty<'tcx>> where
R: TypeRelation<'tcx>,
pub fn super_combine_consts<R>(
&self,
relation: &mut R,
a: &'tcx Const<'tcx>,
b: &'tcx Const<'tcx>
) -> RelateResult<'tcx, &'tcx Const<'tcx>> where
R: ConstEquateRelation<'tcx>,
fn unify_const_variable(
&self,
param_env: ParamEnv<'tcx>,
target_vid: ConstVid<'tcx>,
ct: &'tcx Const<'tcx>,
vid_is_expected: bool
) -> RelateResult<'tcx, &'tcx Const<'tcx>>
fn unify_const_variable(
&self,
param_env: ParamEnv<'tcx>,
target_vid: ConstVid<'tcx>,
ct: &'tcx Const<'tcx>,
vid_is_expected: bool
) -> RelateResult<'tcx, &'tcx Const<'tcx>>
Unifies the const variable target_vid
with the given constant.
This also tests if the given const ct
contains an inference variable which was previously
unioned with target_vid
. If this is the case, inferring target_vid
to ct
would result in an infinite type as we continuously replace an inference variable
in ct
with ct
itself.
This is especially important as unevaluated consts use their parents generics. They therefore often contain unused substs, making these errors far more likely.
A good example of this is the following:
#![feature(generic_const_exprs)]
fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
todo!()
}
fn main() {
let mut arr = Default::default();
arr = bind(arr);
}
Here 3 + 4
ends up as ConstKind::Unevaluated
which uses the generics
of fn bind
(meaning that its substs contain N
).
bind(arr)
now infers that the type of arr
must be [u8; N]
.
The assignment arr = bind(arr)
now tries to equate N
with 3 + 4
.
As 3 + 4
contains N
in its substs, this must not succeed.
See src/test/ui/const-generics/occurs-check/
for more examples where this is relevant.
fn unify_integral_variable(
&self,
vid_is_expected: bool,
vid: IntVid,
val: IntVarValue
) -> RelateResult<'tcx, Ty<'tcx>>
fn unify_float_variable(
&self,
vid_is_expected: bool,
vid: FloatVid,
val: FloatTy
) -> RelateResult<'tcx, Ty<'tcx>>
pub(super) fn note_region_origin(
&self,
err: &mut DiagnosticBuilder<'_>,
origin: &SubregionOrigin<'tcx>
)
pub(super) fn report_concrete_failure(
&self,
origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>
) -> DiagnosticBuilder<'tcx>
pub(super) fn report_placeholder_failure(
&self,
placeholder_origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>
) -> DiagnosticBuilder<'tcx>
pub fn extract_inference_diagnostics_data(
&self,
arg: GenericArg<'tcx>,
highlight: Option<RegionHighlightMode>
) -> InferenceDiagnosticsData
pub fn extract_inference_diagnostics_data(
&self,
arg: GenericArg<'tcx>,
highlight: Option<RegionHighlightMode>
) -> InferenceDiagnosticsData
Extracts data used by diagnostic for either types or constants which were stuck during inference.
pub fn emit_inference_failure_err(
&self,
body_id: Option<BodyId>,
span: Span,
arg: GenericArg<'tcx>,
impl_candidates: Vec<TraitRef<'tcx>>,
error_code: TypeAnnotationNeeded
) -> DiagnosticBuilder<'tcx>
fn annotate_method_call(
&self,
segment: &PathSegment<'_>,
e: &Expr<'_>,
err: &mut DiagnosticBuilder<'_>
)
fn annotate_method_call(
&self,
segment: &PathSegment<'_>,
e: &Expr<'_>,
err: &mut DiagnosticBuilder<'_>
)
If the FnSig
for the method call can be found and type arguments are identified as
needed, suggest annotating the call, otherwise point out the resulting type of the call.
pub fn need_type_info_err_in_generator(
&self,
kind: GeneratorKind,
span: Span,
ty: Ty<'tcx>
) -> DiagnosticBuilder<'tcx>
fn process_errors(
&self,
errors: &[RegionResolutionError<'tcx>]
) -> Vec<RegionResolutionError<'tcx>>
fn check_and_note_conflicting_crates(
&self,
err: &mut DiagnosticBuilder<'_>,
terr: &TypeError<'tcx>
)
fn check_and_note_conflicting_crates(
&self,
err: &mut DiagnosticBuilder<'_>,
terr: &TypeError<'tcx>
)
Adds a note if the types come from similarly named crates
fn note_error_origin(
&self,
err: &mut DiagnosticBuilder<'tcx>,
cause: &ObligationCause<'tcx>,
exp_found: Option<ExpectedFound<Ty<'tcx>>>,
terr: &TypeError<'tcx>
)
fn suggest_boxing_for_return_impl_trait(
&self,
err: &mut DiagnosticBuilder<'tcx>,
return_sp: Span,
arm_spans: impl Iterator<Item = Span>
)
fn highlight_outer(
&self,
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
name: String,
sub: SubstsRef<'tcx>,
pos: usize,
other_ty: Ty<'tcx>
)
fn highlight_outer(
&self,
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
name: String,
sub: SubstsRef<'tcx>,
pos: usize,
other_ty: Ty<'tcx>
)
Given that other_ty
is the same as a type argument for name
in sub
, populate value
highlighting name
and every type argument that isn’t at pos
(which is other_ty
), and
populate other_value
with other_ty
.
Foo<Bar<Qux>>
^^^^--------^ this is highlighted
| |
| this type argument is exactly the same as the other type, not highlighted
this is highlighted
Bar<Qux>
-------- this type is the same as a type argument in the other type, not highlighted
fn cmp_type_arg(
&self,
t1_out: &mut DiagnosticStyledString,
t2_out: &mut DiagnosticStyledString,
path: String,
sub: SubstsRef<'tcx>,
other_path: String,
other_ty: Ty<'tcx>
) -> Option<()>
fn cmp_type_arg(
&self,
t1_out: &mut DiagnosticStyledString,
t2_out: &mut DiagnosticStyledString,
path: String,
sub: SubstsRef<'tcx>,
other_path: String,
other_ty: Ty<'tcx>
) -> Option<()>
If other_ty
is the same as a type argument present in sub
, highlight path
in t1_out
,
as that is the difference to the other type.
For the following code:
let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
The type error output will behave in the following way:
Foo<Bar<Qux>>
^^^^--------^ this is highlighted
| |
| this type argument is exactly the same as the other type, not highlighted
this is highlighted
Bar<Qux>
-------- this type is the same as a type argument in the other type, not highlighted
fn push_comma(
&self,
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
len: usize,
pos: usize
)
fn push_comma(
&self,
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
len: usize,
pos: usize
)
Adds a ,
to the type representation only if it is appropriate.
fn strip_generic_default_params(
&self,
def_id: DefId,
substs: SubstsRef<'tcx>
) -> SubstsRef<'tcx>
fn strip_generic_default_params(
&self,
def_id: DefId,
substs: SubstsRef<'tcx>
) -> SubstsRef<'tcx>
For generic types with parameters with defaults, remove the parameters corresponding to
the defaults. This repeats a lot of the logic found in ty::print::pretty
.
fn cmp_fn_sig(
&self,
sig1: &PolyFnSig<'tcx>,
sig2: &PolyFnSig<'tcx>
) -> (DiagnosticStyledString, DiagnosticStyledString)
fn cmp_fn_sig(
&self,
sig1: &PolyFnSig<'tcx>,
sig2: &PolyFnSig<'tcx>
) -> (DiagnosticStyledString, DiagnosticStyledString)
Given two fn
signatures highlight only sub-parts that are different.
Compares two given types, eliding parts that are the same between them and highlighting relevant differences, and return two representation of those types for highlighted printing.
pub fn note_type_err(
&self,
diag: &mut DiagnosticBuilder<'tcx>,
cause: &ObligationCause<'tcx>,
secondary_span: Option<(Span, String)>,
values: Option<ValuePairs<'tcx>>,
terr: &TypeError<'tcx>
)
fn suggest_await_on_expect_found(
&self,
cause: &ObligationCause<'tcx>,
exp_span: Span,
exp_found: &ExpectedFound<Ty<'tcx>>,
diag: &mut DiagnosticBuilder<'tcx>
)
fn suggest_await_on_expect_found(
&self,
cause: &ObligationCause<'tcx>,
exp_span: Span,
exp_found: &ExpectedFound<Ty<'tcx>>,
diag: &mut DiagnosticBuilder<'tcx>
)
A possible error is to forget to add .await
when using futures:
async fn make_u32() -> u32 {
22
}
fn take_u32(x: u32) {}
async fn foo() {
let x = make_u32();
take_u32(x);
}
This routine checks if the found type T
implements Future<Output=U>
where U
is the
expected type. If this is the case, and we are inside of an async body, it suggests adding
.await
to the tail of the expression.
fn suggest_accessing_field_where_appropriate(
&self,
cause: &ObligationCause<'tcx>,
exp_found: &ExpectedFound<Ty<'tcx>>,
diag: &mut DiagnosticBuilder<'tcx>
)
fn suggest_as_ref_where_appropriate(
&self,
span: Span,
exp_found: &ExpectedFound<Ty<'tcx>>,
diag: &mut DiagnosticBuilder<'tcx>
)
fn suggest_as_ref_where_appropriate(
&self,
span: Span,
exp_found: &ExpectedFound<Ty<'tcx>>,
diag: &mut DiagnosticBuilder<'tcx>
)
When encountering a case where .as_ref()
on a Result
or Option
would be appropriate,
suggests it.
pub fn report_and_explain_type_error(
&self,
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>
) -> DiagnosticBuilder<'tcx>
fn values_str(
&self,
values: ValuePairs<'tcx>
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
fn expected_found_str_ty(
&self,
exp_found: ExpectedFound<Ty<'tcx>>
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
fn expected_found_str<T: Display + TypeFoldable<'tcx>>(
&self,
exp_found: ExpectedFound<T>
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
fn expected_found_str<T: Display + TypeFoldable<'tcx>>(
&self,
exp_found: ExpectedFound<T>
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
Returns a string of the form “expected {}
, found {}
”.
pub fn report_generic_bound_failure(
&self,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>
)
pub fn construct_generic_bound_failure(
&self,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>
) -> DiagnosticBuilder<'a>
fn report_sub_sup_conflict(
&self,
var_origin: RegionVariableOrigin,
sub_origin: SubregionOrigin<'tcx>,
sub_region: Region<'tcx>,
sup_origin: SubregionOrigin<'tcx>,
sup_region: Region<'tcx>
)
Determine whether an error associated with the given span and definition
should be treated as being caused by the implicit From
conversion
within ?
desugaring.
fn report_inference_failure(
&self,
var_origin: RegionVariableOrigin
) -> DiagnosticBuilder<'tcx>
pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
F: FnOnce() -> Result<T, E>,
T: TypeFoldable<'tcx>,
pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
F: FnOnce() -> Result<T, E>,
T: TypeFoldable<'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.
pub fn replace_bound_vars_with_placeholders<T>(
&self,
binder: Binder<'tcx, T>
) -> T where
T: TypeFoldable<'tcx>,
pub fn replace_bound_vars_with_placeholders<T>(
&self,
binder: Binder<'tcx, T>
) -> T where
T: TypeFoldable<'tcx>,
Replaces all regions (resp. types) bound by binder
with placeholder
regions (resp. types) and return a map indicating which bound-region
placeholder region. This is the first step of checking subtyping
when higher-ranked things are involved.
Important: You have to be careful to not leak these placeholders, for more information about how placeholders and HRTBs work, see the rustc dev guide.
pub fn leak_check(
&self,
overly_polymorphic: bool,
snapshot: &CombinedSnapshot<'_, 'tcx>
) -> RelateResult<'tcx, ()>
pub fn leak_check(
&self,
overly_polymorphic: bool,
snapshot: &CombinedSnapshot<'_, 'tcx>
) -> RelateResult<'tcx, ()>
See infer::region_constraints::RegionConstraintCollector::leak_check
.
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).
pub fn register_region_obligation_with_cause(
&self,
sup_type: Ty<'tcx>,
sub_region: Region<'tcx>,
cause: &ObligationCause<'tcx>
)
Trait queries just want to pass back type obligations “as is”
pub fn process_registered_region_obligations(
&self,
region_bound_pairs_map: &FxHashMap<HirId, RegionBoundPairs<'tcx>>,
implicit_region_bound: Option<Region<'tcx>>,
param_env: ParamEnv<'tcx>
)
pub fn process_registered_region_obligations(
&self,
region_bound_pairs_map: &FxHashMap<HirId, RegionBoundPairs<'tcx>>,
implicit_region_bound: Option<Region<'tcx>>,
param_env: ParamEnv<'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. This function must be
invoked for all relevant body-ids before region inference is
done (or else an assert will fire).
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 –
towards the end of regionck. This also ensures that the
region-bound-pairs are available (see comments above regarding
closures).
Parameters
region_bound_pairs
: the set of region bounds implied by the parameters and where-clauses. In particular, each pair('a, K)
in this list tells us that the bounds in scope indicate thatK: 'a
, whereK
is either a generic parameter likeT
or a projection likeT::Item
.implicit_region_bound
: if some, this is a region bound that is considered to hold for all type parameters (the function body).param_env
is the parameter environment for the enclosing function.body_id
is the body-id whose region obligations are being processed.
Returns
This function may have to perform normalizations, and hence it
returns an InferOk
with subobligations that must be
processed.
pub fn infer_projection(
&self,
param_env: ParamEnv<'tcx>,
projection_ty: ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>
) -> Ty<'tcx>
pub fn infer_projection(
&self,
param_env: ParamEnv<'tcx>,
projection_ty: ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'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.
pub fn try_unify_abstract_consts(
&self,
a: Unevaluated<'tcx, ()>,
b: Unevaluated<'tcx, ()>
) -> bool
pub fn try_unify_abstract_consts(
&self,
a: Unevaluated<'tcx, ()>,
b: Unevaluated<'tcx, ()>
) -> bool
calls tcx.try_unify_abstract_consts
after
canonicalizing the consts.
Returns the origin of the type variable identified by vid
, or None
if this is not a type variable.
No attempt is made to resolve ty
.
Like freshener
, but does not replace 'static
regions.
fn combine_fields(
&'a self,
trace: TypeTrace<'tcx>,
param_env: ParamEnv<'tcx>
) -> CombineFields<'a, 'tcx>
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R where
F: FnOnce(&Self) -> R,
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R where
F: FnOnce(&Self) -> R,
Clear the “currently in a snapshot” flag, invoke the closure,
then restore the flag to its original value. This flag is a
debugging measure designed to detect cases where we start a
snapshot, create type variables, and register obligations
which may involve those type variables in the fulfillment cx,
potentially leaving “dangling type variables” behind.
In such cases, an assertion will fail when attempting to
register obligations, within a snapshot. Very useful, much
better than grovelling through megabytes of RUSTC_LOG
output.
HOWEVER, in some cases the flag is unhelpful. In particular, we sometimes create a “mini-fulfilment-cx” in which we enroll obligations. As long as this fulfillment cx is fully drained before we return, this is not a problem, as there won’t be any escaping obligations in the main cx. In those cases, you can use this function.
pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
Executes f
and commit the bindings.
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
Execute f
and commit the bindings if closure f
returns Ok(_)
.
Execute f
then unroll any bindings it creates.
pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
If should_skip
is true, then execute f
then unroll any bindings it creates.
pub fn region_constraints_added_in_snapshot(
&self,
snapshot: &CombinedSnapshot<'a, 'tcx>
) -> Option<bool>
pub fn region_constraints_added_in_snapshot(
&self,
snapshot: &CombinedSnapshot<'a, 'tcx>
) -> Option<bool>
Scan the constraints produced since snapshot
began and returns:
None
– if none of them involve “region outlives” constraintsSome(true)
– if there are'a: 'b
constraints where'a
or'b
is a placeholderSome(false)
– if there are'a: 'b
constraints but none involve placeholders
pub fn can_sub<T>(
&self,
param_env: ParamEnv<'tcx>,
a: T,
b: T
) -> UnitResult<'tcx> where
T: ToTrace<'tcx>,
pub fn can_eq<T>(
&self,
param_env: ParamEnv<'tcx>,
a: T,
b: T
) -> UnitResult<'tcx> where
T: ToTrace<'tcx>,
Require that the region r
be equal to one of the regions in
the set regions
.
pub fn coerce_predicate(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
predicate: PolyCoercePredicate<'tcx>
) -> Option<InferResult<'tcx, ()>>
pub fn coerce_predicate(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
predicate: PolyCoercePredicate<'tcx>
) -> Option<InferResult<'tcx, ()>>
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.)
pub fn subtype_predicate(
&self,
cause: &ObligationCause<'tcx>,
param_env: ParamEnv<'tcx>,
predicate: PolySubtypePredicate<'tcx>
) -> Option<InferResult<'tcx, ()>>
pub fn region_outlives_predicate(
&self,
cause: &ObligationCause<'tcx>,
predicate: PolyRegionOutlivesPredicate<'tcx>
) -> UnitResult<'tcx>
Number of type variables created so far.
pub fn next_ty_var_in_universe(
&self,
origin: TypeVariableOrigin,
universe: UniverseIndex
) -> Ty<'tcx>
pub fn next_const_var_in_universe(
&self,
ty: Ty<'tcx>,
origin: ConstVariableOrigin,
universe: UniverseIndex
) -> &'tcx Const<'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.
pub fn next_region_var_in_universe(
&self,
origin: RegionVariableOrigin,
universe: UniverseIndex
) -> Region<'tcx>
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.
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 which
they are associated.
Number of region variables created so far.
Just a convenient wrapper of next_region_var
for using during NLL.
pub fn next_nll_region_var_in_universe(
&self,
origin: NllRegionVariableOrigin,
universe: UniverseIndex
) -> Region<'tcx>
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.
Given a set of generics defined on a type or impl, returns a substitution mapping each type/region parameter to a fresh inference variable.
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).
Set the “tainted by errors” flag to true. We call this when we observe an error from a prior pass.
pub fn resolve_regions_and_report_errors(
&self,
region_context: DefId,
outlives_env: &OutlivesEnvironment<'tcx>,
mode: RegionckMode
)
pub fn resolve_regions_and_report_errors(
&self,
region_context: DefId,
outlives_env: &OutlivesEnvironment<'tcx>,
mode: RegionckMode
)
Process the region constraints and report 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
.
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.
pub fn with_region_constraints<R>(
&self,
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R
) -> R
pub fn with_region_constraints<R>(
&self,
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R
) -> R
Gives temporary access to the region constraint data.
Takes ownership of the list of variable regions. This implies
that all the region constraints have already been taken, and
hence that resolve_regions_and_report_errors
can never be
called. This is used only during NLL processing to “hand off” ownership
of the set of region variables into the NLL region context.
If TyVar(vid)
resolves to a type, return that type. Else, return the
universe index of TyVar(vid)
.
Resolve any type variables found in value
– but only one
level. So, if the variable ?X
is bound to some type
Foo<?Y>
, then this would return Foo<?Y>
(but ?Y
may
itself be bound to a type).
Useful when you only need to inspect the outermost level of the type and don’t care about nested types (or perhaps you will be resolving them as well, e.g. in a loop).
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.
pub fn unresolved_type_vars<T>(
&self,
value: &T
) -> Option<(Ty<'tcx>, Option<Span>)> where
T: TypeFoldable<'tcx>,
pub fn unresolved_type_vars<T>(
&self,
value: &T
) -> Option<(Ty<'tcx>, Option<Span>)> where
T: TypeFoldable<'tcx>,
Returns the first unresolved variable contained in T
. In the
process of visiting T
, this will resolve (where possible)
type variables in T
, but it never constructs the final,
resolved type, so it’s more efficient than
resolve_vars_if_possible()
.
pub fn probe_const_var(
&self,
vid: ConstVid<'tcx>
) -> Result<&'tcx Const<'tcx>, UniverseIndex>
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.
pub fn type_error_struct_with_diag<M>(
&self,
sp: Span,
mk_diag: M,
actual_ty: Ty<'tcx>
) -> DiagnosticBuilder<'tcx> where
M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
pub fn report_mismatched_types(
&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
err: TypeError<'tcx>
) -> DiagnosticBuilder<'tcx>
pub fn report_mismatched_consts(
&self,
cause: &ObligationCause<'tcx>,
expected: &'tcx Const<'tcx>,
actual: &'tcx Const<'tcx>,
err: TypeError<'tcx>
) -> DiagnosticBuilder<'tcx>
pub fn replace_bound_vars_with_fresh_vars<T>(
&self,
span: Span,
lbrct: LateBoundRegionConversionTime,
value: Binder<'tcx, T>
) -> (T, BTreeMap<BoundRegion, Region<'tcx>>) where
T: TypeFoldable<'tcx>,
pub fn verify_generic_bound(
&self,
origin: SubregionOrigin<'tcx>,
kind: GenericKind<'tcx>,
a: Region<'tcx>,
bound: VerifyBound<'tcx>
)
pub fn verify_generic_bound(
&self,
origin: SubregionOrigin<'tcx>,
kind: GenericKind<'tcx>,
a: Region<'tcx>,
bound: VerifyBound<'tcx>
)
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.
Clears the selection, evaluation, and projection caches. This is useful when
repeatedly attempting to select an Obligation
while changing only
its ParamEnv
, since FulfillmentContext
doesn’t use probing.
Creates and return a fresh universe that extends all previous
universes. Updates self.universe
to that new universe.
pub fn const_eval_resolve(
&self,
param_env: ParamEnv<'tcx>,
unevaluated: Unevaluated<'tcx>,
span: Option<Span>
) -> EvalToConstValueResult<'tcx>
pub fn const_eval_resolve(
&self,
param_env: ParamEnv<'tcx>,
unevaluated: Unevaluated<'tcx>,
span: Option<Span>
) -> EvalToConstValueResult<'tcx>
Resolves and evaluates a constant.
The constant can be located on a trait like <A as B>::C
, in which case the given
substitutions and environment are used to resolve the constant. Alternatively if the
constant has generic parameters in scope the substitutions 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 substitution for T
, if the substitution 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 substs
by
performing the operation on their respective canonical forms.
If typ
is a type variable of some kind, resolve it one level
(but do not resolve types found in the result). If typ
is
not a type variable, just return it unmodified.
ty_or_const_infer_var_changed
is equivalent to one of these two:
shallow_resolve(ty) != ty
(wherety.kind = ty::Infer(_)
)shallow_resolve(ct) != ct
(wherect.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 GenericArg
s in stalled_on
.
pub fn report_extra_impl_obligation(
&self,
error_span: Span,
item_name: Symbol,
_impl_item_def_id: DefId,
trait_item_def_id: DefId,
requirement: &dyn Display
) -> DiagnosticBuilder<'tcx>
Trait Implementations
fn push_sub_region_constraint(
&mut self,
origin: SubregionOrigin<'tcx>,
a: Region<'tcx>,
b: Region<'tcx>
)
fn push_verify(
&mut self,
origin: SubregionOrigin<'tcx>,
kind: GenericKind<'tcx>,
a: Region<'tcx>,
bound: VerifyBound<'tcx>
)
Auto Trait Implementations
impl<'a, 'tcx> !RefUnwindSafe for InferCtxt<'a, 'tcx>
impl<'a, 'tcx> !UnwindSafe for InferCtxt<'a, 'tcx>
Blanket Implementations
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: 760 bytes