mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Dejargnonize subst
This commit is contained in:
parent
084ce5bdb5
commit
3856df059e
@ -691,7 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
|
||||
// borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
|
||||
// These types seem reasonably opaque enough that they could be substituted with their
|
||||
// These types seem reasonably opaque enough that they could be instantiated with their
|
||||
// borrowed variants in a function body when we see a move error.
|
||||
let borrow_level = match *ty.kind() {
|
||||
ty::Param(_) => tcx
|
||||
|
@ -45,7 +45,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// be allowed:
|
||||
/// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
|
||||
///
|
||||
/// Then we map the regions in both the type and the subst to their
|
||||
/// Then we map the regions in both the type and the generic parameters to their
|
||||
/// `external_name` giving `concrete_type = &'a i32`,
|
||||
/// `args = ['static, 'a]`. This will then allow
|
||||
/// `infer_opaque_definition_from_instantiation` to determine that
|
||||
@ -77,9 +77,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let args = opaque_type_key.args;
|
||||
debug!(?concrete_type, ?args);
|
||||
|
||||
let mut subst_regions = vec![self.universal_regions.fr_static];
|
||||
let mut arg_regions = vec![self.universal_regions.fr_static];
|
||||
|
||||
let to_universal_region = |vid, subst_regions: &mut Vec<_>| {
|
||||
let to_universal_region = |vid, arg_regions: &mut Vec<_>| {
|
||||
trace!(?vid);
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
trace!(?scc);
|
||||
@ -88,11 +88,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}) {
|
||||
Some(region) => {
|
||||
let vid = self.universal_regions.to_region_vid(region);
|
||||
subst_regions.push(vid);
|
||||
arg_regions.push(vid);
|
||||
region
|
||||
}
|
||||
None => {
|
||||
subst_regions.push(vid);
|
||||
arg_regions.push(vid);
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
@ -106,10 +106,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// This will ensure they get precedence when folding the regions in the concrete type.
|
||||
if let Some(&ci) = member_constraints.get(&opaque_type_key) {
|
||||
for &vid in self.member_constraints.choice_regions(ci) {
|
||||
to_universal_region(vid, &mut subst_regions);
|
||||
to_universal_region(vid, &mut arg_regions);
|
||||
}
|
||||
}
|
||||
debug!(?subst_regions);
|
||||
debug!(?arg_regions);
|
||||
|
||||
// Next, insert universal regions from args, so we can translate regions that appear
|
||||
// in them but are not subject to member constraints, for instance closure args.
|
||||
@ -119,18 +119,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
return region;
|
||||
}
|
||||
let vid = self.to_region_vid(region);
|
||||
to_universal_region(vid, &mut subst_regions)
|
||||
to_universal_region(vid, &mut arg_regions)
|
||||
});
|
||||
debug!(?universal_args);
|
||||
debug!(?subst_regions);
|
||||
debug!(?arg_regions);
|
||||
|
||||
// Deduplicate the set of regions while keeping the chosen order.
|
||||
let subst_regions = subst_regions.into_iter().collect::<FxIndexSet<_>>();
|
||||
debug!(?subst_regions);
|
||||
let arg_regions = arg_regions.into_iter().collect::<FxIndexSet<_>>();
|
||||
debug!(?arg_regions);
|
||||
|
||||
let universal_concrete_type =
|
||||
infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
|
||||
ty::ReVar(vid) => subst_regions
|
||||
ty::ReVar(vid) => arg_regions
|
||||
.iter()
|
||||
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
|
||||
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
|
||||
|
@ -554,18 +554,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
/// Call this on things you got out of the MIR (so it is as generic as the current
|
||||
/// stack frame), to bring it into the proper environment for this interpreter.
|
||||
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<
|
||||
pub(super) fn instantiate_from_current_frame_and_normalize_erasing_regions<
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
>(
|
||||
&self,
|
||||
value: T,
|
||||
) -> Result<T, ErrorHandled> {
|
||||
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
||||
self.instantiate_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
||||
}
|
||||
|
||||
/// Call this on things you got out of the MIR (so it is as generic as the provided
|
||||
/// stack frame), to bring it into the proper environment for this interpreter.
|
||||
pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
pub(super) fn instantiate_from_frame_and_normalize_erasing_regions<
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
>(
|
||||
&self,
|
||||
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
|
||||
value: T,
|
||||
@ -656,7 +658,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
||||
let local_ty = frame.body.local_decls[local].ty;
|
||||
let local_ty = self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
||||
let local_ty =
|
||||
self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
||||
self.layout_of(local_ty)
|
||||
})?;
|
||||
|
||||
@ -791,8 +794,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
|
||||
if M::POST_MONO_CHECKS {
|
||||
for &const_ in &body.required_consts {
|
||||
let c =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
||||
let c = self
|
||||
.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
||||
c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| {
|
||||
err.emit_note(*self.tcx);
|
||||
err
|
||||
|
@ -696,9 +696,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
trace!("eval_place_to_op: got {:?}", op);
|
||||
// Sanity-check the type we ended up with.
|
||||
if cfg!(debug_assertions) {
|
||||
let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||
)?;
|
||||
let normalized_place_ty = self
|
||||
.instantiate_from_current_frame_and_normalize_erasing_regions(
|
||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||
)?;
|
||||
if !mir_assign_valid_types(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
@ -731,8 +732,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
&Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?,
|
||||
|
||||
Constant(constant) => {
|
||||
let c =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(constant.const_)?;
|
||||
let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(
|
||||
constant.const_,
|
||||
)?;
|
||||
|
||||
// This can still fail:
|
||||
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
|
||||
|
@ -542,9 +542,10 @@ where
|
||||
trace!("{:?}", self.dump_place(&place));
|
||||
// Sanity-check the type we ended up with.
|
||||
if cfg!(debug_assertions) {
|
||||
let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||
)?;
|
||||
let normalized_place_ty = self
|
||||
.instantiate_from_current_frame_and_normalize_erasing_regions(
|
||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||
)?;
|
||||
if !mir_assign_valid_types(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
|
@ -235,7 +235,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
NullaryOp(ref null_op, ty) => {
|
||||
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
|
||||
let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?;
|
||||
let layout = self.layout_of(ty)?;
|
||||
if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op
|
||||
&& layout.is_unsized()
|
||||
@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Cast(cast_kind, ref operand, cast_ty) => {
|
||||
let src = self.eval_operand(operand, None)?;
|
||||
let cast_ty =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?;
|
||||
self.instantiate_from_current_frame_and_normalize_erasing_regions(cast_ty)?;
|
||||
self.cast(&src, cast_kind, cast_ty, &dest)?;
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Drop { place, target, unwind, replace: _ } => {
|
||||
let frame = self.frame();
|
||||
let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
|
||||
let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?;
|
||||
let ty = self.instantiate_from_frame_and_normalize_erasing_regions(frame, ty)?;
|
||||
let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
|
||||
if let ty::InstanceDef::DropGlue(_, None) = instance.def {
|
||||
// This is the branch we enter if and only if the dropped type has no drop glue
|
||||
@ -672,8 +672,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Construct the destination place for this argument. At this point all
|
||||
// locals are still dead, so we cannot construct a `PlaceTy`.
|
||||
let dest = mir::Place::from(local);
|
||||
// `layout_of_local` does more than just the substitution we need to get the
|
||||
// type, but the result gets cached so this avoids calling the substitution
|
||||
// `layout_of_local` does more than just the instantiation we need to get the
|
||||
// type, but the result gets cached so this avoids calling the instantiation
|
||||
// query *again* the next time this local is accessed.
|
||||
let ty = self.layout_of_local(self.frame(), local, None)?.ty;
|
||||
if Some(local) == body.spread_arg {
|
||||
|
@ -19,11 +19,11 @@ where
|
||||
}
|
||||
|
||||
struct FoundParam;
|
||||
struct UsedParamsNeedSubstVisitor<'tcx> {
|
||||
struct UsedParamsNeedInstantiationVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedSubstVisitor<'tcx> {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
|
||||
type BreakTy = FoundParam;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
@ -38,17 +38,17 @@ where
|
||||
| ty::FnDef(def_id, args) => {
|
||||
let instance = ty::InstanceDef::Item(def_id);
|
||||
let unused_params = self.tcx.unused_generic_params(instance);
|
||||
for (index, subst) in args.into_iter().enumerate() {
|
||||
for (index, arg) in args.into_iter().enumerate() {
|
||||
let index = index
|
||||
.try_into()
|
||||
.expect("more generic parameters than can fit into a `u32`");
|
||||
// Only recurse when generic parameters in fns, closures and coroutines
|
||||
// are used and have to be instantiated.
|
||||
//
|
||||
// Just in case there are closures or coroutines within this subst,
|
||||
// Just in case there are closures or coroutines within this arg,
|
||||
// recurse.
|
||||
if unused_params.is_used(index) && subst.has_param() {
|
||||
return subst.visit_with(self);
|
||||
if unused_params.is_used(index) && arg.has_param() {
|
||||
return arg.visit_with(self);
|
||||
}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
@ -65,7 +65,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let mut vis = UsedParamsNeedSubstVisitor { tcx };
|
||||
let mut vis = UsedParamsNeedInstantiationVisitor { tcx };
|
||||
if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) {
|
||||
throw_inval!(TooGeneric);
|
||||
} else {
|
||||
|
@ -22,9 +22,9 @@ fn foo<T>(x: Vec<T>) {
|
||||
In this specific case there's a good chance that the transmute is harmless (but
|
||||
this is not guaranteed by Rust). However, when alignment and enum optimizations
|
||||
come into the picture, it's quite likely that the sizes may or may not match
|
||||
with different type parameter substitutions. It's not possible to check this for
|
||||
_all_ possible types, so `transmute()` simply only accepts types without any
|
||||
unsubstituted type parameters.
|
||||
with different type parameter instantiations. It's not possible to check this
|
||||
for _all_ possible types, so `transmute()` simply only accepts types without any
|
||||
uninstantiated type parameters.
|
||||
|
||||
If you need this, there's a good chance you're doing something wrong. Keep in
|
||||
mind that Rust doesn't guarantee much about the layout of different structs
|
||||
@ -32,7 +32,7 @@ mind that Rust doesn't guarantee much about the layout of different structs
|
||||
there is a solution that avoids the transmute entirely, try it instead.
|
||||
|
||||
If it's possible, hand-monomorphize the code by writing the function for each
|
||||
possible type substitution. It's possible to use traits to do this cleanly,
|
||||
possible type instantiation. It's possible to use traits to do this cleanly,
|
||||
for example:
|
||||
|
||||
```
|
||||
|
@ -15,9 +15,9 @@ There will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
instantiation with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will be instantiated to the type (in
|
||||
this case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces contain an identifier which doesn't
|
||||
match with any of the type parameters or the string `Self`. This might happen
|
||||
|
@ -15,9 +15,9 @@ there will be an error about `bool` not implementing `Index<u8>`, followed by a
|
||||
note saying "the type `bool` cannot be indexed by `u8`".
|
||||
|
||||
As you can see, you can specify type parameters in curly braces for
|
||||
substitution with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will substitute to the type (in this
|
||||
case, `bool`) that we tried to use.
|
||||
instantiation with the actual types (using the regular format string syntax) in
|
||||
a given situation. Furthermore, `{Self}` will be instantiated to the type (in
|
||||
this case, `bool`) that we tried to use.
|
||||
|
||||
This error appears when the curly braces do not contain an identifier. Please
|
||||
add one of the same name as a type parameter. If you intended to use literal
|
||||
|
@ -12,12 +12,12 @@ fn together_we_will_rule_the_galaxy(son: &A) {}
|
||||
```
|
||||
|
||||
A trait object is defined over a single, fully-defined trait. With a regular
|
||||
default parameter, this parameter can just be substituted in. However, if the
|
||||
default parameter, this parameter can just be instantiated in. However, if the
|
||||
default parameter is `Self`, the trait changes for each concrete type; i.e.
|
||||
`i32` will be expected to implement `A<i32>`, `bool` will be expected to
|
||||
implement `A<bool>`, etc... These types will not share an implementation of a
|
||||
fully-defined trait; instead they share implementations of a trait with
|
||||
different parameters substituted in for each implementation. This is
|
||||
different parameters instantiated in for each implementation. This is
|
||||
irreconcilable with what we need to make a trait object work, and is thus
|
||||
disallowed. Making the trait concrete by explicitly specifying the value of the
|
||||
defaulted parameter will fix this issue. Fixed example:
|
||||
|
@ -14,7 +14,7 @@ let _ = foo::<'static>;
|
||||
|
||||
The type of a concrete instance of a generic function is universally quantified
|
||||
over late-bound lifetime parameters. This is because we want the function to
|
||||
work for any lifetime substituted for the late-bound lifetime parameter, no
|
||||
work for any lifetime instantiated for the late-bound lifetime parameter, no
|
||||
matter where the function is called. Consequently, it doesn't make sense to
|
||||
specify arguments for late-bound lifetime parameters, since they are not
|
||||
resolved until the function's call site(s).
|
||||
@ -56,7 +56,7 @@ let bar_fn3 = bar::<Bar>; // OK
|
||||
|
||||
In the definition of `bar`, the lifetime parameter `'a` is late-bound, while
|
||||
`'b` is early-bound. This is reflected in the type annotation for `bar_fn`,
|
||||
where `'a` is universally quantified and `'b` is substituted by a specific
|
||||
where `'a` is universally quantified and `'b` is instantiated with a specific
|
||||
lifetime. It is not allowed to explicitly specify early-bound lifetime
|
||||
arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
|
||||
see [issue #42868](https://github.com/rust-lang/rust/issues/42868)), although
|
||||
|
@ -2536,7 +2536,7 @@ pub struct OpaqueTy<'hir> {
|
||||
/// lifetimes that are captured from the function signature they originate from.
|
||||
///
|
||||
/// This is done by generating a new early-bound lifetime parameter local to the
|
||||
/// opaque which is substituted in the function signature with the late-bound
|
||||
/// opaque which is instantiated in the function signature with the late-bound
|
||||
/// lifetime.
|
||||
///
|
||||
/// This mapping associated a captured lifetime (first parameter) with the new
|
||||
|
@ -131,6 +131,8 @@ hir_analysis_function_not_have_default_implementation = function doesn't have a
|
||||
hir_analysis_functions_names_duplicated = functions names are duplicated
|
||||
.note = all `#[rustc_must_implement_one_of]` arguments must be unique
|
||||
|
||||
hir_analysis_generic_args_on_overridden_impl = could not resolve generic parameters on overridden impl
|
||||
|
||||
hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
|
||||
.label = cannot specialize default item `{$ident}`
|
||||
.ok_label = parent `impl` is here
|
||||
@ -365,8 +367,6 @@ hir_analysis_static_mut_ref_lint = {$shared}reference of mutable static is disco
|
||||
|
||||
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
|
||||
|
||||
hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
|
||||
|
||||
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
|
||||
.note = this item must mention the opaque type in its signature in order to be able to register hidden types
|
||||
|
||||
|
@ -336,12 +336,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
|
||||
let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
|
||||
let mut emitted_bad_param_err = None;
|
||||
// If we have an method return type bound, then we need to substitute
|
||||
// If we have an method return type bound, then we need to instantiate
|
||||
// the method's early bound params with suitable late-bound params.
|
||||
let mut num_bound_vars = candidate.bound_vars().len();
|
||||
let args =
|
||||
candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
|
||||
let subst = match param.kind {
|
||||
let arg = match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
@ -379,7 +379,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
};
|
||||
num_bound_vars += 1;
|
||||
subst
|
||||
arg
|
||||
});
|
||||
|
||||
// Next, we need to check that the return-type notation is being used on
|
||||
@ -402,12 +402,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
|
||||
// Finally, move the fn return type's bound vars over to account for the early bound
|
||||
// params (and trait ref's late bound params). This logic is very similar to
|
||||
// `Predicate::subst_supertrait`, and it's no coincidence why.
|
||||
// `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
|
||||
// and it's no coincidence why.
|
||||
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
|
||||
let subst_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
|
||||
let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(binding.hir_id);
|
||||
ty::Binder::bind_with_vars(subst_output, bound_vars)
|
||||
ty::Binder::bind_with_vars(instantiation_output, bound_vars)
|
||||
} else {
|
||||
// Append the generic arguments of the associated type to the `trait_ref`.
|
||||
candidate.map_bound(|trait_ref| {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::IsMethodCall;
|
||||
use crate::astconv::{
|
||||
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
|
||||
errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound,
|
||||
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||
};
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||
@ -177,9 +177,9 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
|
||||
has_self: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
arg_count: &GenericArgCountResult,
|
||||
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
|
||||
ctx: &mut impl CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>,
|
||||
) -> GenericArgsRef<'tcx> {
|
||||
// Collect the segments of the path; we need to substitute arguments
|
||||
// Collect the segments of the path; we need to instantiate arguments
|
||||
// for parameters throughout the entire path (wherever there are
|
||||
// generic parameters).
|
||||
let mut parent_defs = tcx.generics_of(def_id);
|
||||
@ -191,7 +191,7 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
|
||||
}
|
||||
|
||||
// We manually build up the generic arguments, rather than using convenience
|
||||
// methods in `subst.rs`, so that we can iterate over the arguments and
|
||||
// methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, instead of trying to match each pair.
|
||||
let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
|
||||
// Iterate over each segment of the path.
|
||||
|
@ -214,7 +214,7 @@ pub struct GenericArgCountResult {
|
||||
pub correct: Result<(), GenericArgCountMismatch>,
|
||||
}
|
||||
|
||||
pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
|
||||
pub trait CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> {
|
||||
fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
|
||||
|
||||
fn provided_kind(
|
||||
@ -366,8 +366,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
if generics.has_self {
|
||||
if generics.parent.is_some() {
|
||||
// The parent is a trait so it should have at least one subst
|
||||
// for the `Self` type.
|
||||
// The parent is a trait so it should have at least one
|
||||
// generic parameter for the `Self` type.
|
||||
assert!(!parent_args.is_empty())
|
||||
} else {
|
||||
// This item (presumably a trait) needs a self-type.
|
||||
@ -402,7 +402,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
return (tcx.mk_args(parent_args), arg_count);
|
||||
}
|
||||
|
||||
struct SubstsForAstPathCtxt<'a, 'tcx> {
|
||||
struct InstantiationsForAstPathCtxt<'a, 'tcx> {
|
||||
astconv: &'a (dyn AstConv<'tcx> + 'a),
|
||||
def_id: DefId,
|
||||
generic_args: &'a GenericArgs<'tcx>,
|
||||
@ -411,7 +411,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
infer_args: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>
|
||||
for InstantiationsForAstPathCtxt<'a, 'tcx>
|
||||
{
|
||||
fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
|
||||
if did == self.def_id {
|
||||
(Some(self.generic_args), self.infer_args)
|
||||
@ -556,7 +558,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
}
|
||||
|
||||
let mut args_ctx = SubstsForAstPathCtxt {
|
||||
let mut args_ctx = InstantiationsForAstPathCtxt {
|
||||
astconv: self,
|
||||
def_id,
|
||||
span,
|
||||
@ -2412,8 +2414,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
let self_ty = self.tcx().type_of(parent).instantiate_identity();
|
||||
let generic_self_ty = ty::GenericArg::from(self_ty);
|
||||
let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), substs)
|
||||
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), args)
|
||||
} else {
|
||||
sig.instantiate_identity()
|
||||
};
|
||||
|
@ -175,7 +175,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
// A `Self` within the original bound will be substituted with a
|
||||
// A `Self` within the original bound will be instantiated with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self = match pred.skip_binder().term.unpack() {
|
||||
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
||||
|
@ -1030,7 +1030,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
||||
match t.kind() {
|
||||
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
|
||||
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
|
||||
ty::Adt(def, subst) => {
|
||||
ty::Adt(def, args) => {
|
||||
if !def.did().is_local() {
|
||||
let non_exhaustive = def.is_variant_list_non_exhaustive()
|
||||
|| def
|
||||
@ -1042,13 +1042,13 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
||||
return ControlFlow::Break((
|
||||
def.descr(),
|
||||
def.did(),
|
||||
subst,
|
||||
args,
|
||||
non_exhaustive,
|
||||
));
|
||||
}
|
||||
}
|
||||
def.all_fields()
|
||||
.map(|field| field.ty(tcx, subst))
|
||||
.map(|field| field.ty(tcx, args))
|
||||
.try_for_each(|t| check_non_exhaustive(tcx, t))
|
||||
}
|
||||
_ => ControlFlow::Continue(()),
|
||||
|
@ -125,9 +125,9 @@ fn check_method_is_structurally_compatible<'tcx>(
|
||||
/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// We now want to extract and substitute the type of the *trait*
|
||||
/// We now want to extract and instantiate the type of the *trait*
|
||||
/// method and compare it. To do so, we must create a compound
|
||||
/// substitution by combining `trait_to_impl_args` and
|
||||
/// instantiation by combining `trait_to_impl_args` and
|
||||
/// `impl_to_placeholder_args`, and also adding a mapping for the method
|
||||
/// type parameters. We extend the mapping to also include
|
||||
/// the method parameters.
|
||||
@ -146,11 +146,11 @@ fn check_method_is_structurally_compatible<'tcx>(
|
||||
/// vs `'b`). However, the normal subtyping rules on fn types handle
|
||||
/// this kind of equivalency just fine.
|
||||
///
|
||||
/// We now use these substitutions to ensure that all declared bounds are
|
||||
/// satisfied by the implementation's method.
|
||||
/// We now use these generic parameters to ensure that all declared bounds
|
||||
/// are satisfied by the implementation's method.
|
||||
///
|
||||
/// We do this by creating a parameter environment which contains a
|
||||
/// substitution corresponding to `impl_to_placeholder_args`. We then build
|
||||
/// generic parameter corresponding to `impl_to_placeholder_args`. We then build
|
||||
/// `trait_to_placeholder_args` and use it to convert the predicates contained
|
||||
/// in the `trait_m` generics to the placeholder form.
|
||||
///
|
||||
@ -454,7 +454,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
|
||||
// First, check a few of the same things as `compare_impl_method`,
|
||||
// just so we don't ICE during substitution later.
|
||||
// just so we don't ICE during instantiation later.
|
||||
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
|
||||
|
||||
let trait_to_impl_args = impl_trait_ref.args;
|
||||
@ -543,7 +543,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// }
|
||||
// ```
|
||||
// .. to compile. However, since we use both the normalized and unnormalized
|
||||
// inputs and outputs from the substituted trait signature, we will end up
|
||||
// inputs and outputs from the instantiated trait signature, we will end up
|
||||
// seeing the hidden type of an RPIT in the signature itself. Naively, this
|
||||
// means that we will use the hidden type to imply the hidden type's own
|
||||
// well-formedness.
|
||||
@ -699,7 +699,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
|
||||
// region args that are synthesized during AST lowering. These are args
|
||||
// that are appended to the parent args (trait and trait method). However,
|
||||
// we're trying to infer the unsubstituted type value of the RPITIT inside
|
||||
// we're trying to infer the uninstantiated type value of the RPITIT inside
|
||||
// the *impl*, so we can later use the impl's method args to normalize
|
||||
// an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
|
||||
//
|
||||
@ -711,7 +711,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// guarantee that the indices from the trait args and impl args line up.
|
||||
// So to fix this, we subtract the number of trait args and add the number of
|
||||
// impl args to *renumber* these early-bound regions to their corresponding
|
||||
// indices in the impl's substitutions list.
|
||||
// indices in the impl's generic parameters list.
|
||||
//
|
||||
// Also, we only need to account for a difference in trait and impl args,
|
||||
// since we previously enforce that the trait method and impl method have the
|
||||
|
@ -124,14 +124,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// Take the param-env of the adt and substitute the args that show up in
|
||||
// Take the param-env of the adt and instantiate the args that show up in
|
||||
// the implementation's self type. This gives us the assumptions that the
|
||||
// self ty of the implementation is allowed to know just from it being a
|
||||
// well-formed adt, since that's all we're allowed to assume while proving
|
||||
// the Drop implementation is not specialized.
|
||||
//
|
||||
// We don't need to normalize this param-env or anything, since we're only
|
||||
// substituting it with free params, so no additional param-env normalization
|
||||
// instantiating it with free params, so no additional param-env normalization
|
||||
// can occur on top of what has been done in the param_env query itself.
|
||||
let param_env =
|
||||
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
|
||||
|
@ -56,7 +56,7 @@ type variable is an instance of a type parameter. That is,
|
||||
given a generic function `fn foo<T>(t: T)`, while checking the
|
||||
function `foo`, the type `ty_param(0)` refers to the type `T`, which
|
||||
is treated in abstract. However, when `foo()` is called, `T` will be
|
||||
substituted for a fresh type variable `N`. This variable will
|
||||
instantiated with a fresh type variable `N`. This variable will
|
||||
eventually be resolved to some concrete type (which might itself be
|
||||
a type parameter).
|
||||
|
||||
|
@ -618,7 +618,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
// The bounds we that we would require from `to_check`
|
||||
let mut bounds = FxHashSet::default();
|
||||
|
||||
let (regions, types) = GATSubstCollector::visit(gat_def_id.to_def_id(), to_check);
|
||||
let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);
|
||||
|
||||
// If both regions and types are empty, then this GAT isn't in the
|
||||
// set of types we are checking, and we shouldn't try to do clause analysis
|
||||
@ -787,34 +787,34 @@ fn test_region_obligations<'tcx>(
|
||||
/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
|
||||
/// the two vectors, `regions` and `types` (depending on their kind). For each
|
||||
/// parameter `Pi` also track the index `i`.
|
||||
struct GATSubstCollector<'tcx> {
|
||||
struct GATArgsCollector<'tcx> {
|
||||
gat: DefId,
|
||||
// Which region appears and which parameter index its substituted for
|
||||
// Which region appears and which parameter index its instantiated with
|
||||
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
|
||||
// Which params appears and which parameter index its substituted for
|
||||
// Which params appears and which parameter index its instantiated with
|
||||
types: FxHashSet<(Ty<'tcx>, usize)>,
|
||||
}
|
||||
|
||||
impl<'tcx> GATSubstCollector<'tcx> {
|
||||
impl<'tcx> GATArgsCollector<'tcx> {
|
||||
fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
gat: DefId,
|
||||
t: T,
|
||||
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
|
||||
let mut visitor =
|
||||
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
||||
GATArgsCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
||||
t.visit_with(&mut visitor);
|
||||
(visitor.regions, visitor.types)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
|
||||
type BreakTy = !;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
|
||||
for (idx, subst) in p.args.iter().enumerate() {
|
||||
match subst.unpack() {
|
||||
for (idx, arg) in p.args.iter().enumerate() {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Lifetime(lt) if !lt.is_bound() => {
|
||||
self.regions.insert((lt, idx));
|
||||
}
|
||||
@ -1407,14 +1407,14 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
}
|
||||
}
|
||||
|
||||
// Check that trait predicates are WF when params are substituted by their defaults.
|
||||
// Check that trait predicates are WF when params are instantiated with their defaults.
|
||||
// We don't want to overly constrain the predicates that may be written but we want to
|
||||
// catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
|
||||
// Therefore we check if a predicate which contains a single type param
|
||||
// with a concrete default is WF with that default substituted.
|
||||
// with a concrete default is WF with that default instantiated.
|
||||
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
||||
//
|
||||
// First we build the defaulted substitution.
|
||||
// First we build the defaulted generic parameters.
|
||||
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
@ -1428,7 +1428,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
let default_ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ty.has_param() {
|
||||
// ... then substitute it with the default.
|
||||
// ... then instantiate it with the default.
|
||||
return default_ty.into();
|
||||
}
|
||||
}
|
||||
@ -1441,7 +1441,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ct.has_param() {
|
||||
// ... then substitute it with the default.
|
||||
// ... then instantiate it with the default.
|
||||
return default_ct.into();
|
||||
}
|
||||
}
|
||||
@ -1451,7 +1451,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
}
|
||||
});
|
||||
|
||||
// Now we build the substituted predicates.
|
||||
// Now we build the instantiated predicates.
|
||||
let default_obligations = predicates
|
||||
.predicates
|
||||
.iter()
|
||||
@ -1483,23 +1483,25 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
}
|
||||
let mut param_count = CountParams::default();
|
||||
let has_region = pred.visit_with(&mut param_count).is_break();
|
||||
let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
|
||||
let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
|
||||
if instantiated_pred.has_non_region_param()
|
||||
|| param_count.params.len() > 1
|
||||
|| has_region
|
||||
{
|
||||
None
|
||||
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
|
||||
} else if predicates.predicates.iter().any(|&(p, _)| p == instantiated_pred) {
|
||||
// Avoid duplication of predicates that contain no parameters, for example.
|
||||
None
|
||||
} else {
|
||||
Some((substituted_pred, sp))
|
||||
Some((instantiated_pred, sp))
|
||||
}
|
||||
})
|
||||
.map(|(pred, sp)| {
|
||||
// Convert each of those into an obligation. So if you have
|
||||
// something like `struct Foo<T: Copy = String>`, we would
|
||||
// take that predicate `T: Copy`, substitute to `String: Copy`
|
||||
// take that predicate `T: Copy`, instantiated with `String: Copy`
|
||||
// (actually that happens in the previous `flat_map` call),
|
||||
// and then try to prove it (in this case, we'll fail).
|
||||
//
|
||||
|
@ -396,7 +396,7 @@ pub fn coerce_unsized_info<'tcx>(
|
||||
//
|
||||
// To check if this impl is legal, we would walk down
|
||||
// the fields of `Foo` and consider their types with
|
||||
// both substitutes. We are looking to find that
|
||||
// both generic parameters. We are looking to find that
|
||||
// exactly one (non-phantom) field has changed its
|
||||
// type, which we will expect to be the pointer that
|
||||
// is becoming fat (we could probably generalize this
|
||||
|
@ -71,7 +71,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
// end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`.
|
||||
//
|
||||
// This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as
|
||||
// we substitute the defaults with the partially built args when we build the args. Subst'ing
|
||||
// we instantiate the defaults with the partially built args when we build the args. Instantiating
|
||||
// the `N#0` on the unevaluated const indexes into the empty args we're in the process of building.
|
||||
//
|
||||
// We fix this by having this function return the parent's generics ourselves and truncating the
|
||||
|
@ -1786,7 +1786,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
let bound_predicate = pred.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::ClauseKind::Trait(data) => {
|
||||
// The order here needs to match what we would get from `subst_supertrait`
|
||||
// The order here needs to match what we would get from
|
||||
// `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
|
||||
let pred_bound_vars = bound_predicate.bound_vars();
|
||||
let mut all_bound_vars = bound_vars.clone();
|
||||
all_bound_vars.extend(pred_bound_vars.iter());
|
||||
|
@ -119,7 +119,7 @@ pub fn identify_constrained_generic_params<'tcx>(
|
||||
/// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate
|
||||
///
|
||||
/// When we, for example, try to go over the trait-reference
|
||||
/// `IntoIter<u32> as Trait`, we substitute the impl parameters with fresh
|
||||
/// `IntoIter<u32> as Trait`, we instantiate the impl parameters with fresh
|
||||
/// variables and match them with the impl trait-ref, so we know that
|
||||
/// `$U = IntoIter<u32>`.
|
||||
///
|
||||
|
@ -372,8 +372,8 @@ pub struct ManualImplementation {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_substs_on_overridden_impl)]
|
||||
pub struct SubstsOnOverriddenImpl {
|
||||
#[diag(hir_analysis_generic_args_on_overridden_impl)]
|
||||
pub struct GenericArgsOnOverriddenImpl {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -34,8 +34,8 @@
|
||||
//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
|
||||
//! ```
|
||||
//!
|
||||
//! We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is
|
||||
//! constrained to be `<I as Iterator>::Item`, so we check only
|
||||
//! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
|
||||
//! `T` is constrained to be `<I as Iterator>::Item`, so we check only
|
||||
//! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
|
||||
//! predicates of `impl1` are only `T: Sized`, which is also a predicate of
|
||||
//! `impl2`. So this specialization is sound.
|
||||
@ -65,7 +65,7 @@
|
||||
//! cause use after frees with purely safe code in the same way as specializing
|
||||
//! on traits with methods can.
|
||||
|
||||
use crate::errors::SubstsOnOverriddenImpl;
|
||||
use crate::errors::GenericArgsOnOverriddenImpl;
|
||||
use crate::{constrained_generic_params as cgp, errors};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -179,8 +179,8 @@ fn check_constness(
|
||||
}
|
||||
|
||||
/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
|
||||
/// substitutions `(S1, S2)` that equate their trait references. The returned
|
||||
/// types are expressed in terms of the generics of `impl1`.
|
||||
/// generic parameters `(S1, S2)` that equate their trait references.
|
||||
/// The returned types are expressed in terms of the generics of `impl1`.
|
||||
///
|
||||
/// Example
|
||||
///
|
||||
@ -228,13 +228,13 @@ fn get_impl_args(
|
||||
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
|
||||
let span = tcx.def_span(impl1_def_id);
|
||||
let guar = tcx.dcx().emit_err(SubstsOnOverriddenImpl { span });
|
||||
let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span });
|
||||
return Err(guar);
|
||||
};
|
||||
Ok((impl1_args, impl2_args))
|
||||
}
|
||||
|
||||
/// Returns a list of all of the unconstrained subst of the given impl.
|
||||
/// Returns a list of all of the unconstrained generic parameters of the given impl.
|
||||
///
|
||||
/// For example given the impl:
|
||||
///
|
||||
|
@ -229,7 +229,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
||||
/// Here, we should fetch the explicit predicates, which
|
||||
/// will give us `U: 'static` and `U: Outer`. The latter we
|
||||
/// can ignore, but we will want to process `U: 'static`,
|
||||
/// applying the substitution as above.
|
||||
/// applying the instantiation as above.
|
||||
fn check_explicit_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@ -316,7 +316,7 @@ fn check_explicit_predicates<'tcx>(
|
||||
/// Here, when processing the type of field `outer`, we would request the
|
||||
/// set of implicit predicates computed for `Inner` thus far. This will
|
||||
/// initially come back empty, but in next round we will get `U: 'b`.
|
||||
/// We then apply the substitution `['b => 'a, U => T]` and thus get the
|
||||
/// We then apply the instantiation `['b => 'a, U => T]` and thus get the
|
||||
/// requirement that `T: 'a` holds for `Outer`.
|
||||
fn check_inferred_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -334,7 +334,7 @@ fn check_inferred_predicates<'tcx>(
|
||||
|
||||
for (&predicate, &span) in predicates.as_ref().skip_binder() {
|
||||
// `predicate` is `U: 'b` in the example above.
|
||||
// So apply the substitution to get `T: 'a`.
|
||||
// So apply the instantiation to get `T: 'a`.
|
||||
let ty::OutlivesPredicate(arg, region) =
|
||||
predicates.rebind(predicate).instantiate(tcx, args);
|
||||
insert_outlives_predicate(tcx, arg, region, span, required_predicates);
|
||||
|
@ -172,16 +172,16 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
||||
trait_ref: ty::TraitRef { def_id: _, args, .. },
|
||||
polarity: _,
|
||||
}) => {
|
||||
for subst in &args[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
for arg in &args[1..] {
|
||||
arg.visit_with(&mut collector);
|
||||
}
|
||||
}
|
||||
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_ty: ty::AliasTy { args, .. },
|
||||
term,
|
||||
}) => {
|
||||
for subst in &args[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
for arg in &args[1..] {
|
||||
arg.visit_with(&mut collector);
|
||||
}
|
||||
term.visit_with(&mut collector);
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
if let ty::Dynamic(..) = declared_ret_ty.kind() {
|
||||
// We have special-cased the case where the function is declared
|
||||
// `-> dyn Foo` and we don't actually relate it to the
|
||||
// `fcx.ret_coercion`, so just substitute a type variable.
|
||||
// `fcx.ret_coercion`, so just instantiate a type variable.
|
||||
actual_return_ty =
|
||||
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
|
||||
debug!("actual_return_ty replaced with {:?}", actual_return_ty);
|
||||
|
@ -752,7 +752,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let mut obligations: Vec<_> = predicates
|
||||
.iter()
|
||||
.map(|predicate| {
|
||||
// For each existential predicate (e.g., `?Self: Clone`) substitute
|
||||
// For each existential predicate (e.g., `?Self: Clone`) instantiate
|
||||
// the type of the expression (e.g., `usize` in our example above)
|
||||
// and then require that the resulting predicate (e.g., `usize: Clone`)
|
||||
// holds (it does).
|
||||
|
@ -1801,7 +1801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// consistency. But they should be merged as much as possible.
|
||||
let fru_tys = if self.tcx.features().type_changing_struct_update {
|
||||
if adt.is_struct() {
|
||||
// Make some fresh substitutions for our ADT type.
|
||||
// Make some fresh generic parameters for our ADT type.
|
||||
let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
|
||||
// We do subtyping on the FRU fields first, so we can
|
||||
// learn exactly what types we expect the base expr
|
||||
|
@ -15,7 +15,7 @@ use rustc_hir_analysis::astconv::generics::{
|
||||
check_generic_arg_count_for_call, create_args_for_parent_generic_args,
|
||||
};
|
||||
use rustc_hir_analysis::astconv::{
|
||||
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
|
||||
AstConv, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
|
||||
GenericArgCountResult, IsMethodCall, PathSeg,
|
||||
};
|
||||
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
||||
@ -179,8 +179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
/// Given the args that we just converted from the HIR, try to
|
||||
/// canonicalize them and store them as user-given substitutions
|
||||
/// (i.e., substitutions that must be respected by the NLL check).
|
||||
/// 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
|
||||
@ -733,7 +733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return Err(TypeError::Mismatch);
|
||||
}
|
||||
|
||||
// Record all the argument types, with the substitutions
|
||||
// Record all the argument types, with the args
|
||||
// produced from the above subtyping unification.
|
||||
Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
|
||||
})
|
||||
@ -1163,7 +1163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// Now we have to compare the types that the user *actually*
|
||||
// provided against the types that were *expected*. If the user
|
||||
// did not provide any types, then we want to substitute inference
|
||||
// did not provide any types, then we want to instantiate inference
|
||||
// variables. If the user provided some types, we may still need
|
||||
// to add defaults. If the user provided *too many* types, that's
|
||||
// a problem.
|
||||
@ -1253,14 +1253,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
},
|
||||
};
|
||||
|
||||
struct CreateCtorSubstsContext<'a, 'tcx> {
|
||||
struct CreateCtorInstantiationsContext<'a, 'tcx> {
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
path_segs: &'a [PathSeg],
|
||||
infer_args_for_err: &'a FxHashSet<usize>,
|
||||
segments: &'tcx [hir::PathSegment<'tcx>],
|
||||
}
|
||||
impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> {
|
||||
impl<'tcx, 'a> CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>
|
||||
for CreateCtorInstantiationsContext<'a, 'tcx>
|
||||
{
|
||||
fn args_for_def_id(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
@ -1384,7 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
has_self,
|
||||
self_ty.map(|s| s.raw),
|
||||
&arg_count,
|
||||
&mut CreateCtorSubstsContext {
|
||||
&mut CreateCtorInstantiationsContext {
|
||||
fcx: self,
|
||||
span,
|
||||
path_segs: &path_segs,
|
||||
@ -1402,18 +1404,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
self.add_required_obligations_for_hir(span, def_id, args, hir_id);
|
||||
|
||||
// Substitute the values for the type parameters into the type of
|
||||
// Instantiate the values for the type parameters into the type of
|
||||
// the referenced item.
|
||||
let ty = tcx.type_of(def_id);
|
||||
assert!(!args.has_escaping_bound_vars());
|
||||
assert!(!ty.skip_binder().has_escaping_bound_vars());
|
||||
let ty_substituted = self.normalize(span, ty.instantiate(tcx, args));
|
||||
let ty_instantiated = self.normalize(span, ty.instantiate(tcx, args));
|
||||
|
||||
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
|
||||
// In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
|
||||
// is inherent, there is no `Self` parameter; instead, the impl needs
|
||||
// type parameters, which we can infer by unifying the provided `Self`
|
||||
// with the substituted impl type.
|
||||
// with the instantiated impl type.
|
||||
// This also occurs for an enum variant on a type alias.
|
||||
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
|
||||
let self_ty = self.normalize(span, self_ty);
|
||||
@ -1434,13 +1436,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_substituted);
|
||||
debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_instantiated);
|
||||
self.write_args(hir_id, args);
|
||||
|
||||
(ty_substituted, res)
|
||||
(ty_instantiated, res)
|
||||
}
|
||||
|
||||
/// Add all the obligations that are required, substituting and normalized appropriately.
|
||||
/// Add all the obligations that are required, instantiated and normalized appropriately.
|
||||
pub(crate) fn add_required_obligations_for_hir(
|
||||
&self,
|
||||
span: Span,
|
||||
|
@ -21,7 +21,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(unsubstituted_pred) = self
|
||||
let Some(uninstantiated_pred) = self
|
||||
.tcx
|
||||
.predicates_of(def_id)
|
||||
.instantiate_identity(self.tcx)
|
||||
@ -34,7 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let (predicate_args, predicate_self_type_to_point_at) =
|
||||
match unsubstituted_pred.kind().skip_binder() {
|
||||
match uninstantiated_pred.kind().skip_binder() {
|
||||
ty::ClauseKind::Trait(pred) => {
|
||||
(pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
|
||||
}
|
||||
@ -343,10 +343,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
|
||||
&& let generics = self.0.tcx.generics_of(self.1)
|
||||
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
|
||||
&& let Some(subst) =
|
||||
&& let Some(arg) =
|
||||
ty::GenericArgs::identity_for_item(self.0.tcx, self.1).get(index as usize)
|
||||
{
|
||||
ControlFlow::Break(*subst)
|
||||
ControlFlow::Break(*arg)
|
||||
} else {
|
||||
ty.super_visit_with(self)
|
||||
}
|
||||
|
@ -2133,17 +2133,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let tcx = self.tcx;
|
||||
let (adt, substs, unwrap) = match expected.kind() {
|
||||
let (adt, args, unwrap) = match expected.kind() {
|
||||
// In case Option<NonZero*> is wanted, but * is provided, suggest calling new
|
||||
ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
|
||||
let nonzero_type = substs.type_at(0); // Unwrap option type.
|
||||
let ty::Adt(adt, substs) = nonzero_type.kind() else {
|
||||
ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
|
||||
let nonzero_type = args.type_at(0); // Unwrap option type.
|
||||
let ty::Adt(adt, args) = nonzero_type.kind() else {
|
||||
return false;
|
||||
};
|
||||
(adt, substs, "")
|
||||
(adt, args, "")
|
||||
}
|
||||
// In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types.
|
||||
ty::Adt(adt, substs) => (adt, substs, ".unwrap()"),
|
||||
ty::Adt(adt, args) => (adt, args, ".unwrap()"),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
@ -2165,7 +2165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
("NonZeroI128", tcx.types.i128),
|
||||
];
|
||||
|
||||
let int_type = substs.type_at(0);
|
||||
let int_type = args.type_at(0);
|
||||
|
||||
let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
|
||||
if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None }
|
||||
|
@ -7,7 +7,7 @@ use rustc_hir::GenericArg;
|
||||
use rustc_hir_analysis::astconv::generics::{
|
||||
check_generic_arg_count_for_call, create_args_for_parent_generic_args,
|
||||
};
|
||||
use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
|
||||
use rustc_hir_analysis::astconv::{AstConv, CreateInstantiationsForGenericArgsCtxt, IsMethodCall};
|
||||
use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
|
||||
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
|
||||
@ -95,7 +95,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
// Adjust the self expression the user provided and obtain the adjusted type.
|
||||
let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick);
|
||||
|
||||
// Create substitutions for the method's type parameters.
|
||||
// Create generic args for the method's type parameters.
|
||||
let rcvr_args = self.fresh_receiver_args(self_ty, pick);
|
||||
let all_args = self.instantiate_method_args(pick, segment, rcvr_args);
|
||||
|
||||
@ -246,11 +246,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
target
|
||||
}
|
||||
|
||||
/// Returns a set of substitutions for the method *receiver* where all type and region
|
||||
/// parameters are instantiated with fresh variables. This substitution does not include any
|
||||
/// Returns a set of generic parameters for the method *receiver* where all type and region
|
||||
/// parameters are instantiated with fresh variables. This generic paramters does not include any
|
||||
/// parameters declared on the method itself.
|
||||
///
|
||||
/// Note that this substitution may include late-bound regions from the impl level. If so,
|
||||
/// Note that this generic parameters may include late-bound regions from the impl level. If so,
|
||||
/// these are instantiated later in the `instantiate_method_sig` routine.
|
||||
fn fresh_receiver_args(
|
||||
&mut self,
|
||||
@ -272,8 +272,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
|
||||
// The object data has no entry for the Self
|
||||
// Type. For the purposes of this method call, we
|
||||
// substitute the object type itself. This
|
||||
// wouldn't be a sound substitution in all cases,
|
||||
// instantiate the object type itself. This
|
||||
// wouldn't be a sound instantiation in all cases,
|
||||
// since each instance of the object type is a
|
||||
// different existential and hence could match
|
||||
// distinct types (e.g., if `Self` appeared as an
|
||||
@ -362,16 +362,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
IsMethodCall::Yes,
|
||||
);
|
||||
|
||||
// Create subst for early-bound lifetime parameters, combining
|
||||
// parameters from the type and those from the method.
|
||||
// Create generic paramters for early-bound lifetime parameters,
|
||||
// combining parameters from the type and those from the method.
|
||||
assert_eq!(generics.parent_count, parent_args.len());
|
||||
|
||||
struct MethodSubstsCtxt<'a, 'tcx> {
|
||||
struct MethodInstantiationsCtxt<'a, 'tcx> {
|
||||
cfcx: &'a ConfirmContext<'a, 'tcx>,
|
||||
pick: &'a probe::Pick<'tcx>,
|
||||
seg: &'a hir::PathSegment<'tcx>,
|
||||
}
|
||||
impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>
|
||||
for MethodInstantiationsCtxt<'a, 'tcx>
|
||||
{
|
||||
fn args_for_def_id(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
@ -437,7 +439,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
false,
|
||||
None,
|
||||
&arg_count_correct,
|
||||
&mut MethodSubstsCtxt { cfcx: self, pick, seg },
|
||||
&mut MethodInstantiationsCtxt { cfcx: self, pick, seg },
|
||||
);
|
||||
|
||||
// When the method is confirmed, the `args` includes
|
||||
@ -538,15 +540,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
debug!("instantiate_method_sig(pick={:?}, all_args={:?})", pick, all_args);
|
||||
|
||||
// Instantiate the bounds on the method with the
|
||||
// type/early-bound-regions substitutions performed. There can
|
||||
// type/early-bound-regions instatiations performed. There can
|
||||
// be no late-bound regions appearing here.
|
||||
let def_id = pick.item.def_id;
|
||||
let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_args);
|
||||
|
||||
debug!("method_predicates after subst = {:?}", method_predicates);
|
||||
debug!("method_predicates after instantitation = {:?}", method_predicates);
|
||||
|
||||
let sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, all_args);
|
||||
debug!("type scheme substituted, sig={:?}", sig);
|
||||
debug!("type scheme instantiated, sig={:?}", sig);
|
||||
|
||||
let sig = self.instantiate_binder_with_fresh_vars(sig);
|
||||
debug!("late-bound lifetimes from method instantiated, sig={:?}", sig);
|
||||
|
@ -38,7 +38,7 @@ pub struct MethodCallee<'tcx> {
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
|
||||
/// Instantiated method signature, i.e., it has been
|
||||
/// substituted, normalized, and has had late-bound
|
||||
/// instantiated, normalized, and has had late-bound
|
||||
/// lifetimes replaced with inference variables.
|
||||
pub sig: ty::FnSig<'tcx>,
|
||||
}
|
||||
@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
||||
let mut obligations = vec![];
|
||||
|
||||
// Instantiate late-bound regions and substitute the trait
|
||||
// Instantiate late-bound regions and instantiate the trait
|
||||
// parameters into the method type to get the actual method type.
|
||||
//
|
||||
// N.B., instantiate late-bound regions before normalizing the
|
||||
|
@ -111,7 +111,7 @@ pub(crate) struct Candidate<'tcx> {
|
||||
// The way this is handled is through `xform_self_ty`. It contains
|
||||
// the receiver type of this candidate, but `xform_self_ty`,
|
||||
// `xform_ret_ty` and `kind` (which contains the predicates) have the
|
||||
// generic parameters of this candidate substituted with the *same set*
|
||||
// generic parameters of this candidate instantiated with the *same set*
|
||||
// of inference variables, which acts as some weird sort of "query".
|
||||
//
|
||||
// When we check out a candidate, we require `xform_self_ty` to be
|
||||
@ -799,7 +799,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
// the `Self` type. An [`ObjectSafetyViolation::SupertraitSelf`] error
|
||||
// will be reported by `object_safety.rs` if the method refers to the
|
||||
// `Self` type anywhere other than the receiver. Here, we use a
|
||||
// substitution that replaces `Self` with the object type itself. Hence,
|
||||
// instantiation that replaces `Self` with the object type itself. Hence,
|
||||
// a `&self` method will wind up with an argument type like `&dyn Trait`.
|
||||
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
|
||||
self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
|
||||
@ -1857,8 +1857,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
assert!(!args.has_escaping_bound_vars());
|
||||
|
||||
// It is possible for type parameters or early-bound lifetimes
|
||||
// to appear in the signature of `self`. The substitutions we
|
||||
// are given do not include type/lifetime parameters for the
|
||||
// to appear in the signature of `self`. The generic parameters
|
||||
// we are given do not include type/lifetime parameters for the
|
||||
// method yet. So create fresh variables here for those too,
|
||||
// if there are any.
|
||||
let generics = self.tcx.generics_of(method);
|
||||
@ -1889,7 +1889,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
self.instantiate_bound_regions_with_erased(xform_fn_sig)
|
||||
}
|
||||
|
||||
/// Gets the type of an impl and generate substitutions with inference vars.
|
||||
/// Gets the type of an impl and generate generic parameters with inference vars.
|
||||
fn impl_ty_and_args(
|
||||
&self,
|
||||
impl_def_id: DefId,
|
||||
@ -1913,7 +1913,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
/// late-bound regions with 'static. Otherwise, if we were going to replace late-bound
|
||||
/// regions with actual region variables as is proper, we'd have to ensure that the same
|
||||
/// region got replaced with the same variable, which requires a bit more coordination
|
||||
/// and/or tracking the substitution and
|
||||
/// and/or tracking the instantiations and
|
||||
/// so forth.
|
||||
fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T
|
||||
where
|
||||
|
@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
PlaceOp::Deref => None,
|
||||
PlaceOp::Index => {
|
||||
// We would need to recover the `T` used when we resolve `<_ as Index<T>>::index`
|
||||
// in try_index_step. This is the subst at index 1.
|
||||
// in try_index_step. This is the arg at index 1.
|
||||
//
|
||||
// Note: we should *not* use `expr_ty` of index_expr here because autoderef
|
||||
// during coercions can cause type of index_expr to differ from `T` (#72002).
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Type resolution: the phase that finds all the types in the AST with
|
||||
// unresolved type variables and replaces "ty_var" types with their
|
||||
// substitutions.
|
||||
// generic parameters.
|
||||
|
||||
use crate::FnCtxt;
|
||||
use rustc_data_structures::unord::ExtendUnord;
|
||||
@ -616,7 +616,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
self.write_ty_to_typeck_results(hir_id, n_ty);
|
||||
debug!(?n_ty);
|
||||
|
||||
// Resolve any substitutions
|
||||
// Resolve any generic parameters
|
||||
if let Some(args) = self.fcx.typeck_results.borrow().node_args_opt(hir_id) {
|
||||
let args = self.resolve(args, &span);
|
||||
debug!("write_args_to_tcx({:?}, {:?})", hir_id, args);
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! This module contains code to substitute new values into a
|
||||
//! This module contains code to instantiate new values into a
|
||||
//! `Canonical<'tcx, T>`.
|
||||
//!
|
||||
//! For an overview of what canonicalization is and how it fits into
|
||||
@ -16,17 +16,17 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||
pub trait CanonicalExt<'tcx, V> {
|
||||
/// Instantiate the wrapped value, replacing each canonical value
|
||||
/// with the value given in `var_values`.
|
||||
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
|
||||
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
|
||||
where
|
||||
V: TypeFoldable<TyCtxt<'tcx>>;
|
||||
|
||||
/// Allows one to apply a substitute to some subset of
|
||||
/// Allows one to apply a instantiation to some subset of
|
||||
/// `self.value`. Invoke `projection_fn` with `self.value` to get
|
||||
/// a value V that is expressed in terms of the same canonical
|
||||
/// variables bound in `self` (usually this extracts from subset
|
||||
/// of `self`). Apply the substitution `var_values` to this value
|
||||
/// of `self`). Apply the instantiation `var_values` to this value
|
||||
/// V, replacing each of the canonical variables.
|
||||
fn substitute_projected<T>(
|
||||
fn instantiate_projected<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
var_values: &CanonicalVarValues<'tcx>,
|
||||
@ -37,14 +37,14 @@ pub trait CanonicalExt<'tcx, V> {
|
||||
}
|
||||
|
||||
impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
|
||||
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
|
||||
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
|
||||
where
|
||||
V: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.substitute_projected(tcx, var_values, |value| value.clone())
|
||||
self.instantiate_projected(tcx, var_values, |value| value.clone())
|
||||
}
|
||||
|
||||
fn substitute_projected<T>(
|
||||
fn instantiate_projected<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
var_values: &CanonicalVarValues<'tcx>,
|
||||
@ -55,14 +55,14 @@ impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
|
||||
{
|
||||
assert_eq!(self.variables.len(), var_values.len());
|
||||
let value = projection_fn(&self.value);
|
||||
substitute_value(tcx, var_values, value)
|
||||
instantiate_value(tcx, var_values, value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Substitute the values from `var_values` into `value`. `var_values`
|
||||
/// Instantiate the values from `var_values` into `value`. `var_values`
|
||||
/// must be values for the set of canonical variables that appear in
|
||||
/// `value`.
|
||||
pub(super) fn substitute_value<'tcx, T>(
|
||||
pub(super) fn instantiate_value<'tcx, T>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
var_values: &CanonicalVarValues<'tcx>,
|
||||
value: T,
|
@ -30,24 +30,24 @@ use rustc_middle::ty::GenericArg;
|
||||
use rustc_middle::ty::{self, List, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub use instantiate::CanonicalExt;
|
||||
pub use rustc_middle::infer::canonical::*;
|
||||
pub use substitute::CanonicalExt;
|
||||
|
||||
mod canonicalizer;
|
||||
mod instantiate;
|
||||
pub mod query_response;
|
||||
mod substitute;
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
/// Creates a substitution S for the canonical value with fresh
|
||||
/// Creates an instantiation 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.
|
||||
/// 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 substitution S (once
|
||||
/// 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.
|
||||
pub fn instantiate_canonical_with_fresh_inference_vars<T>(
|
||||
@ -73,14 +73,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
let canonical_inference_vars =
|
||||
self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]);
|
||||
let result = canonical.substitute(self.tcx, &canonical_inference_vars);
|
||||
let result = canonical.instantiate(self.tcx, &canonical_inference_vars);
|
||||
(result, canonical_inference_vars)
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// details). You can then use `instantiate` to instantiate the
|
||||
/// canonical variable with these inference variables.
|
||||
fn instantiate_canonical_vars(
|
||||
&self,
|
||||
|
@ -7,7 +7,7 @@
|
||||
//!
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::canonical::substitute::{substitute_value, CanonicalExt};
|
||||
use crate::infer::canonical::instantiate::{instantiate_value, CanonicalExt};
|
||||
use crate::infer::canonical::{
|
||||
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
|
||||
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
|
||||
@ -189,18 +189,18 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
where
|
||||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let InferOk { value: result_subst, mut obligations } =
|
||||
self.query_response_substitution(cause, param_env, original_values, query_response)?;
|
||||
let InferOk { value: result_args, mut obligations } =
|
||||
self.query_response_instantiation(cause, param_env, original_values, query_response)?;
|
||||
|
||||
obligations.extend(self.query_outlives_constraints_into_obligations(
|
||||
cause,
|
||||
param_env,
|
||||
&query_response.value.region_constraints.outlives,
|
||||
&result_subst,
|
||||
&result_args,
|
||||
));
|
||||
|
||||
let user_result: R =
|
||||
query_response.substitute_projected(self.tcx, &result_subst, |q_r| q_r.value.clone());
|
||||
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
|
||||
|
||||
Ok(InferOk { value: user_result, obligations })
|
||||
}
|
||||
@ -225,11 +225,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// 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
|
||||
/// - 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 substitution, we will append
|
||||
/// - 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
|
||||
@ -239,7 +239,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// 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 substitution `S`.
|
||||
/// after applying the instantiation `S`.
|
||||
pub fn instantiate_nll_query_response_and_region_obligations<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
@ -251,8 +251,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
where
|
||||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let InferOk { value: result_subst, mut obligations } = self
|
||||
.query_response_substitution_guess(cause, param_env, original_values, query_response)?;
|
||||
let InferOk { value: result_args, mut obligations } = self
|
||||
.query_response_instantiation_guess(
|
||||
cause,
|
||||
param_env,
|
||||
original_values,
|
||||
query_response,
|
||||
)?;
|
||||
|
||||
// Compute `QueryOutlivesConstraint` values that unify each of
|
||||
// the original values `v_o` that was canonicalized into a
|
||||
@ -262,7 +267,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
for (index, original_value) in original_values.var_values.iter().enumerate() {
|
||||
// ...with the value `v_r` of that variable from the query.
|
||||
let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
|
||||
let result_value = query_response.instantiate_projected(self.tcx, &result_args, |v| {
|
||||
v.var_values[BoundVar::new(index)]
|
||||
});
|
||||
match (original_value.unpack(), result_value.unpack()) {
|
||||
@ -321,7 +326,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
// ...also include the other query region constraints from the query.
|
||||
output_query_region_constraints.outlives.extend(
|
||||
query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| {
|
||||
let r_c = substitute_value(self.tcx, &result_subst, r_c);
|
||||
let r_c = instantiate_value(self.tcx, &result_args, r_c);
|
||||
|
||||
// Screen out `'a: 'a` cases.
|
||||
let ty::OutlivesPredicate(k1, r2) = r_c.0;
|
||||
@ -336,26 +341,26 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
.region_constraints
|
||||
.member_constraints
|
||||
.iter()
|
||||
.map(|p_c| substitute_value(self.tcx, &result_subst, p_c.clone())),
|
||||
.map(|p_c| instantiate_value(self.tcx, &result_args, p_c.clone())),
|
||||
);
|
||||
|
||||
let user_result: R =
|
||||
query_response.substitute_projected(self.tcx, &result_subst, |q_r| q_r.value.clone());
|
||||
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
|
||||
|
||||
Ok(InferOk { value: user_result, obligations })
|
||||
}
|
||||
|
||||
/// Given the original values and the (canonicalized) result from
|
||||
/// computing a query, returns a substitution that can be applied
|
||||
/// computing a query, returns an instantiation that can be applied
|
||||
/// to the query result to convert the result back into the
|
||||
/// original namespace.
|
||||
///
|
||||
/// The substitution also comes accompanied with subobligations
|
||||
/// The instantiation 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<R>(
|
||||
fn query_response_instantiation<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
@ -366,11 +371,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!(
|
||||
"query_response_substitution(original_values={:#?}, query_response={:#?})",
|
||||
"query_response_instantiation(original_values={:#?}, query_response={:#?})",
|
||||
original_values, query_response,
|
||||
);
|
||||
|
||||
let mut value = self.query_response_substitution_guess(
|
||||
let mut value = self.query_response_instantiation_guess(
|
||||
cause,
|
||||
param_env,
|
||||
original_values,
|
||||
@ -378,7 +383,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
)?;
|
||||
|
||||
value.obligations.extend(
|
||||
self.unify_query_response_substitution_guess(
|
||||
self.unify_query_response_instantiation_guess(
|
||||
cause,
|
||||
param_env,
|
||||
original_values,
|
||||
@ -392,7 +397,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
|
||||
/// Given the original values and the (canonicalized) result from
|
||||
/// computing a query, returns a **guess** at a substitution that
|
||||
/// computing a query, returns a **guess** at an instantiation 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
|
||||
@ -401,7 +406,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// variable instead. Therefore, the result of this method must be
|
||||
/// properly unified
|
||||
#[instrument(level = "debug", skip(self, cause, param_env))]
|
||||
fn query_response_substitution_guess<R>(
|
||||
fn query_response_instantiation_guess<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
@ -450,7 +455,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
if let ty::Bound(debruijn, b) = *result_value.kind() {
|
||||
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
|
||||
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var] = Some(*original_value);
|
||||
}
|
||||
@ -460,7 +465,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
if let ty::ReBound(debruijn, br) = *result_value {
|
||||
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
|
||||
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[br.var] = Some(*original_value);
|
||||
}
|
||||
@ -469,7 +474,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
|
||||
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
|
||||
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b] = Some(*original_value);
|
||||
}
|
||||
@ -477,10 +482,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Create a result substitution: if we found a value for a
|
||||
// Create result arguments: if we found a value for a
|
||||
// given variable in the loop above, use that. Otherwise, use
|
||||
// a fresh inference variable.
|
||||
let result_subst = CanonicalVarValues {
|
||||
let result_args = CanonicalVarValues {
|
||||
var_values: self.tcx.mk_args_from_iter(
|
||||
query_response.variables.iter().enumerate().map(|(index, info)| {
|
||||
if info.universe() != ty::UniverseIndex::ROOT {
|
||||
@ -511,8 +516,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
// Carry all newly resolved opaque types to the caller's scope
|
||||
for &(a, b) in &query_response.value.opaque_types {
|
||||
let a = substitute_value(self.tcx, &result_subst, a);
|
||||
let b = substitute_value(self.tcx, &result_subst, b);
|
||||
let a = instantiate_value(self.tcx, &result_args, a);
|
||||
let b = instantiate_value(self.tcx, &result_args, b);
|
||||
debug!(?a, ?b, "constrain opaque type");
|
||||
// We use equate here instead of, for example, just registering the
|
||||
// opaque type's hidden value directly, because we may be instantiating
|
||||
@ -532,7 +537,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
Ok(InferOk { value: result_subst, obligations })
|
||||
Ok(InferOk { value: result_args, obligations })
|
||||
}
|
||||
|
||||
/// Given a "guess" at the values for the canonical variables in
|
||||
@ -540,13 +545,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// 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 unify_query_response_substitution_guess<R>(
|
||||
/// See also: [`Self::query_response_instantiation_guess`]
|
||||
fn unify_query_response_instantiation_guess<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
original_values: &OriginalQueryValues<'tcx>,
|
||||
result_subst: &CanonicalVarValues<'tcx>,
|
||||
result_args: &CanonicalVarValues<'tcx>,
|
||||
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
|
||||
) -> InferResult<'tcx, ()>
|
||||
where
|
||||
@ -554,15 +559,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
{
|
||||
// A closure that yields the result value for the given
|
||||
// canonical variable; this is taken from
|
||||
// `query_response.var_values` after applying the substitution
|
||||
// `result_subst`.
|
||||
let substituted_query_response = |index: BoundVar| -> GenericArg<'tcx> {
|
||||
query_response.substitute_projected(self.tcx, result_subst, |v| v.var_values[index])
|
||||
// `query_response.var_values` after applying the instantiation
|
||||
// by `result_args`.
|
||||
let instantiated_query_response = |index: BoundVar| -> GenericArg<'tcx> {
|
||||
query_response.instantiate_projected(self.tcx, result_args, |v| v.var_values[index])
|
||||
};
|
||||
|
||||
// Unify the original value for each variable with the value
|
||||
// taken from `query_response` (after applying `result_subst`).
|
||||
self.unify_canonical_vars(cause, param_env, original_values, substituted_query_response)
|
||||
// taken from `query_response` (after applying `result_args`).
|
||||
self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response)
|
||||
}
|
||||
|
||||
/// Converts the region constraints resulting from a query into an
|
||||
@ -571,11 +576,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
&'a self,
|
||||
cause: &'a ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
|
||||
result_subst: &'a CanonicalVarValues<'tcx>,
|
||||
uninstantiated_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
|
||||
result_args: &'a CanonicalVarValues<'tcx>,
|
||||
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
|
||||
unsubstituted_region_constraints.iter().map(move |&constraint| {
|
||||
let predicate = substitute_value(self.tcx, result_subst, constraint);
|
||||
uninstantiated_region_constraints.iter().map(move |&constraint| {
|
||||
let predicate = instantiate_value(self.tcx, result_args, constraint);
|
||||
self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
|
||||
})
|
||||
}
|
||||
|
@ -679,7 +679,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
/// inference context that contains each of the bound values
|
||||
/// within instantiated as a fresh variable. The `f` closure is
|
||||
/// invoked with the new infcx, along with the instantiated value
|
||||
/// `V` and a substitution `S`. This substitution `S` maps from
|
||||
/// `V` and a instantiation `S`. This instantiation `S` maps from
|
||||
/// the bound values in `C` to their instantiated values in `V`
|
||||
/// (in other words, `S(C) = V`).
|
||||
pub fn build_with_canonical<T>(
|
||||
@ -691,8 +691,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let infcx = self.build();
|
||||
let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
|
||||
(infcx, value, subst)
|
||||
let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
|
||||
(infcx, value, args)
|
||||
}
|
||||
|
||||
pub fn build(&mut self) -> InferCtxt<'tcx> {
|
||||
@ -1194,13 +1194,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
// Create a type inference variable for the given
|
||||
// type parameter definition. The substitutions are
|
||||
// type parameter definition. The generic parameters are
|
||||
// for actual parameters that may be referred to by
|
||||
// the default of this type parameter, if it exists.
|
||||
// e.g., `struct Foo<A, B, C = (A, B)>(...);` when
|
||||
// used in a path such as `Foo::<T, U>::new()` will
|
||||
// use an inference variable for `C` with `[T, U]`
|
||||
// as the substitutions for the default, `(T, U)`.
|
||||
// as the generic parameters for the default, `(T, U)`.
|
||||
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
|
||||
self.universe(),
|
||||
TypeVariableOrigin {
|
||||
@ -1256,7 +1256,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).into()
|
||||
}
|
||||
|
||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
||||
/// 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.
|
||||
pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
|
||||
GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
|
||||
@ -1411,7 +1411,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
if !value.has_infer() {
|
||||
return value; // Avoid duplicated subst-folding.
|
||||
return value; // Avoid duplicated type-folding.
|
||||
}
|
||||
let mut r = InferenceLiteralEraser { tcx: self.tcx };
|
||||
value.fold_with(&mut r)
|
||||
@ -1458,7 +1458,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
// Instantiates the bound variables in a given binder with fresh inference
|
||||
// variables in the current universe.
|
||||
//
|
||||
// Use this method if you'd like to find some substitution of the binder's
|
||||
// Use this method if you'd like to find some generic parameters of the binder's
|
||||
// variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`]
|
||||
// that corresponds to your use case, consider whether or not you should
|
||||
// use [`InferCtxt::enter_forall`] instead.
|
||||
@ -1603,10 +1603,10 @@ impl<'tcx> InferCtxt<'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
|
||||
/// 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 substitution for `T`, if the substitution for `T` is still
|
||||
/// 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.
|
||||
///
|
||||
@ -1652,7 +1652,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, args: args_erased };
|
||||
|
||||
// The return value is the evaluated value which doesn't contain any reference to inference
|
||||
// variables, thus we don't need to substitute back the original values.
|
||||
// variables, thus we don't need to instantiate back the original values.
|
||||
tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// ```
|
||||
///
|
||||
/// As indicating in the comments above, each of those references
|
||||
/// is (in the compiler) basically a substitution (`args`)
|
||||
/// is (in the compiler) basically generic paramters (`args`)
|
||||
/// applied to the type of a suitable `def_id` (which identifies
|
||||
/// `Foo1` or `Foo2`).
|
||||
///
|
||||
|
@ -25,7 +25,7 @@ use crate::infer::region_constraints::VerifyIfEq;
|
||||
/// * `None` if `some_type` cannot be made equal to `test_ty`,
|
||||
/// no matter the values of the variables in `exists`.
|
||||
/// * `Some(r)` with a suitable bound (typically the value of `bound_region`, modulo
|
||||
/// any bound existential variables, which will be substituted) for the
|
||||
/// any bound existential variables, which will be instantiated) for the
|
||||
/// type under test.
|
||||
///
|
||||
/// NB: This function uses a simplistic, syntactic version of type equality.
|
||||
@ -59,7 +59,7 @@ pub fn extract_verify_if_eq<'tcx>(
|
||||
}
|
||||
} else {
|
||||
// The region does not contain any bound variables, so we don't need
|
||||
// to do any substitution.
|
||||
// to do any instantiation.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
|
@ -277,7 +277,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
/// ```
|
||||
///
|
||||
/// If we were given the `DefId` of `Foo::Bar`, we would return
|
||||
/// `'a`. You could then apply the substitutions from the
|
||||
/// `'a`. You could then apply the instantiations from the
|
||||
/// projection to convert this into your namespace. This also
|
||||
/// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on
|
||||
/// the trait. In fact, it works by searching for just such a
|
||||
|
@ -183,14 +183,14 @@ where
|
||||
fn relate_item_args(
|
||||
&mut self,
|
||||
item_def_id: DefId,
|
||||
a_subst: ty::GenericArgsRef<'tcx>,
|
||||
b_subst: ty::GenericArgsRef<'tcx>,
|
||||
a_arg: ty::GenericArgsRef<'tcx>,
|
||||
b_arg: ty::GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
|
||||
if self.ambient_variance == ty::Variance::Invariant {
|
||||
// Avoid fetching the variance if we are in an invariant
|
||||
// context; no need, and it can induce dependency cycles
|
||||
// (e.g., #41849).
|
||||
relate::relate_args_invariantly(self, a_subst, b_subst)
|
||||
relate::relate_args_invariantly(self, a_arg, b_arg)
|
||||
} else {
|
||||
let tcx = self.tcx();
|
||||
let opt_variances = tcx.variances_of(item_def_id);
|
||||
@ -198,8 +198,8 @@ where
|
||||
self,
|
||||
item_def_id,
|
||||
opt_variances,
|
||||
a_subst,
|
||||
b_subst,
|
||||
a_arg,
|
||||
b_arg,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ pub enum TypeVariableOriginKind {
|
||||
AdjustmentType,
|
||||
|
||||
/// In type check, when we are type checking a function that
|
||||
/// returns `-> dyn Foo`, we substitute a type variable for the
|
||||
/// returns `-> dyn Foo`, we instantiate a type variable with the
|
||||
/// return type for diagnostic purposes.
|
||||
DynReturnFn,
|
||||
LatticeVariable,
|
||||
|
@ -285,7 +285,8 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||
let obligations =
|
||||
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
|
||||
elaboratable.child_with_derived_cause(
|
||||
clause.subst_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
|
||||
clause
|
||||
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
|
||||
span,
|
||||
bound_clause.rebind(data),
|
||||
index,
|
||||
|
@ -53,7 +53,7 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
|
||||
|
||||
/// A set of values corresponding to the canonical variables from some
|
||||
/// `Canonical`. You can give these values to
|
||||
/// `canonical_value.substitute` to substitute them into the canonical
|
||||
/// `canonical_value.instantiate` to instantiate them into the canonical
|
||||
/// value at the right places.
|
||||
///
|
||||
/// When you canonicalize a value `V`, you get back one of these
|
||||
|
@ -11,13 +11,13 @@ use rustc_session::lint;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
||||
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||
// In some situations def_id will have generic parameters within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
|
||||
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
||||
// encountered.
|
||||
let args = GenericArgs::identity_for_item(self, def_id);
|
||||
@ -29,10 +29,10 @@ impl<'tcx> TyCtxt<'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
|
||||
/// generic parameters and environment are used to resolve the constant. Alternatively if the
|
||||
/// constant has generic parameters in scope the generic parameters 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
|
||||
/// 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.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
@ -214,13 +214,13 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxtEnsure<'tcx> {
|
||||
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn const_eval_poly(self, def_id: DefId) {
|
||||
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||
// In some situations def_id will have generic parameters within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
|
||||
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
||||
// encountered.
|
||||
let args = GenericArgs::identity_for_item(self.tcx, def_id);
|
||||
|
@ -186,7 +186,7 @@ impl<'tcx> MonoItem<'tcx> {
|
||||
MonoItem::GlobalAsm(..) => return true,
|
||||
};
|
||||
|
||||
!tcx.subst_and_check_impossible_predicates((def_id, &args))
|
||||
!tcx.instantiate_and_check_impossible_predicates((def_id, &args))
|
||||
}
|
||||
|
||||
pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
|
||||
|
@ -2078,9 +2078,9 @@ rustc_queries! {
|
||||
desc { "normalizing `{:?}`", goal.value.value.value }
|
||||
}
|
||||
|
||||
query subst_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool {
|
||||
query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool {
|
||||
desc { |tcx|
|
||||
"checking impossible substituted predicates: `{}`",
|
||||
"checking impossible instantiated predicates: `{}`",
|
||||
tcx.def_path_str(key.0)
|
||||
}
|
||||
}
|
||||
|
@ -721,7 +721,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||
}
|
||||
|
||||
/// Identifies a particular impl in the source, along with a set of
|
||||
/// substitutions from the impl's type/lifetime parameters. The
|
||||
/// generic parameters from the impl's type/lifetime parameters. The
|
||||
/// `nested` vector corresponds to the nested obligations attached to
|
||||
/// the impl's type parameters.
|
||||
///
|
||||
|
@ -49,7 +49,8 @@ pub type EvaluationCache<'tcx> = Cache<
|
||||
/// parameters don't unify with regular types, but they *can* unify
|
||||
/// with variables from blanket impls, and (unless we know its bounds
|
||||
/// will always be satisfied) picking the blanket impl will be wrong
|
||||
/// for at least *some* substitutions. To make this concrete, if we have
|
||||
/// for at least *some* generic parameters. To make this concrete, if
|
||||
/// we have
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; }
|
||||
|
@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
|
||||
let super_predicates =
|
||||
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|
||||
|&(pred, _)| {
|
||||
let clause = pred.subst_supertrait(self.tcx, &trait_ref);
|
||||
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref);
|
||||
self.visited.insert(clause).then_some(clause)
|
||||
},
|
||||
);
|
||||
|
@ -3,7 +3,7 @@ use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use crate::ty::{self, InferConst, Ty, TyCtxt};
|
||||
|
||||
/// A type "A" *matches* "B" if the fresh types in B could be
|
||||
/// substituted with values so as to make it equal to A. Matching is
|
||||
/// instantiated with values so as to make it equal to A. Matching is
|
||||
/// intended to be used only on freshened types, and it basically
|
||||
/// indicates if the non-freshened versions of A and B could have been
|
||||
/// unified.
|
||||
|
@ -235,7 +235,7 @@ impl<'tcx> Const<'tcx> {
|
||||
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
||||
// does not provide the parents generics to anonymous constants. We still allow generic const
|
||||
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
|
||||
// ever try to substitute the generic parameters in their bodies.
|
||||
// ever try to instantiate the generic parameters in their bodies.
|
||||
match expr.kind {
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
|
@ -418,10 +418,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
// Shifter
|
||||
//
|
||||
// Shifts the De Bruijn indices on all escaping bound vars by a
|
||||
// fixed amount. Useful in substitution or when otherwise introducing
|
||||
// fixed amount. Useful in instantiation or when otherwise introducing
|
||||
// a binding level that is not intended to capture the existing bound
|
||||
// vars. See comment on `shift_vars_through_binders` method in
|
||||
// `subst.rs` for more details.
|
||||
// `rustc_middle/src/ty/generic_args.rs` for more details.
|
||||
|
||||
struct Shifter<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -803,13 +803,13 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The actual substitution engine itself is a type folder.
|
||||
// The actual instantiation engine itself is a type folder.
|
||||
|
||||
struct ArgFolder<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'a [GenericArg<'tcx>],
|
||||
|
||||
/// Number of region binders we have passed through while doing the substitution
|
||||
/// Number of region binders we have passed through while doing the instantiation
|
||||
binders_passed: u32,
|
||||
}
|
||||
|
||||
@ -834,7 +834,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
|
||||
#[inline(never)]
|
||||
fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! {
|
||||
bug!(
|
||||
"Region parameter out of range when substituting in region {} (index={}, args = {:?})",
|
||||
"Region parameter out of range when instantiating in region {} (index={}, args = {:?})",
|
||||
data.name,
|
||||
data.index,
|
||||
args,
|
||||
@ -845,7 +845,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
|
||||
#[inline(never)]
|
||||
fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! {
|
||||
bug!(
|
||||
"Unexpected parameter {:?} when substituting in region {} (index={})",
|
||||
"Unexpected parameter {:?} when instantiating in region {} (index={})",
|
||||
other,
|
||||
data.name,
|
||||
data.index
|
||||
@ -854,7 +854,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
|
||||
|
||||
// Note: This routine only handles regions that are bound on
|
||||
// type declarations and other outer declarations, not those
|
||||
// bound in *fn types*. Region substitution of the bound
|
||||
// bound in *fn types*. Region instantiation of the bound
|
||||
// regions that appear in a function signature is done using
|
||||
// the specialized routine `ty::replace_late_regions()`.
|
||||
match *r {
|
||||
@ -913,7 +913,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
#[inline(never)]
|
||||
fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! {
|
||||
bug!(
|
||||
"expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, args={:?}",
|
||||
"expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}",
|
||||
p,
|
||||
ty,
|
||||
p.index,
|
||||
@ -926,7 +926,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
#[inline(never)]
|
||||
fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! {
|
||||
bug!(
|
||||
"type parameter `{:?}` ({:?}/{}) out of range when substituting, args={:?}",
|
||||
"type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}",
|
||||
p,
|
||||
ty,
|
||||
p.index,
|
||||
@ -955,7 +955,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
kind: GenericArgKind<'tcx>,
|
||||
) -> ! {
|
||||
bug!(
|
||||
"expected const for `{:?}` ({:?}/{}) but found {:?} when substituting args={:?}",
|
||||
"expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}",
|
||||
p,
|
||||
ct,
|
||||
p.index,
|
||||
@ -968,7 +968,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
#[inline(never)]
|
||||
fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! {
|
||||
bug!(
|
||||
"const parameter `{:?}` ({:?}/{}) out of range when substituting args={:?}",
|
||||
"const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
|
||||
p,
|
||||
ct,
|
||||
p.index,
|
||||
@ -976,8 +976,8 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs
|
||||
/// when we are substituting a type with escaping bound vars into a context where we have
|
||||
/// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs
|
||||
/// when we are instantating a type with escaping bound vars into a context where we have
|
||||
/// passed through binders. That's quite a mouthful. Let's see an example:
|
||||
///
|
||||
/// ```
|
||||
@ -997,7 +997,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
|
||||
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
|
||||
/// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a
|
||||
/// De Bruijn index of 1. It's only during the substitution that we can see we must increase the
|
||||
/// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the
|
||||
/// depth by 1 to account for the binder that we passed through.
|
||||
///
|
||||
/// As a second example, consider this twist:
|
||||
@ -1015,7 +1015,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
|
||||
/// // DebruijnIndex of 1 |
|
||||
/// // DebruijnIndex of 2
|
||||
/// ```
|
||||
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
|
||||
/// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the
|
||||
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
|
||||
/// is that only in the second case have we passed through a fn binder.
|
||||
fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T {
|
||||
|
@ -125,7 +125,7 @@ pub struct GenericParamCount {
|
||||
/// Information about the formal type/lifetime parameters associated
|
||||
/// with an item or method. Analogous to `hir::Generics`.
|
||||
///
|
||||
/// The ordering of parameters is the same as in `Subst` (excluding child generics):
|
||||
/// The ordering of parameters is the same as in [`ty::GenericArg`] (excluding child generics):
|
||||
/// `Self` (optionally), `Lifetime` params..., `Type` params...
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
pub struct Generics {
|
||||
@ -140,7 +140,7 @@ pub struct Generics {
|
||||
pub has_self: bool,
|
||||
pub has_late_bound_regions: Option<Span>,
|
||||
|
||||
// The index of the host effect when substituted. (i.e. might be index to parent args)
|
||||
// The index of the host effect when instantiated. (i.e. might be index to parent args)
|
||||
pub host_effect_index: Option<usize>,
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ use std::fmt;
|
||||
///
|
||||
/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
|
||||
/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval
|
||||
/// will do all required substitution as they run.
|
||||
/// will do all required instantiations as they run.
|
||||
///
|
||||
/// Note: the `Lift` impl is currently not used by rustc, but is used by
|
||||
/// rustc_codegen_cranelift when the `jit` feature is enabled.
|
||||
@ -138,7 +138,7 @@ pub enum InstanceDef<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> Instance<'tcx> {
|
||||
/// Returns the `Ty` corresponding to this `Instance`, with generic substitutions applied and
|
||||
/// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and
|
||||
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||
let ty = tcx.type_of(self.def.def_id());
|
||||
@ -298,11 +298,11 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||
}
|
||||
|
||||
/// Returns `true` when the MIR body associated with this instance should be monomorphized
|
||||
/// by its users (e.g. codegen or miri) by substituting the `args` from `Instance` (see
|
||||
/// by its users (e.g. codegen or miri) by instantiating the `args` from `Instance` (see
|
||||
/// `Instance::args_for_mir_body`).
|
||||
///
|
||||
/// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR
|
||||
/// body should perform necessary substitutions.
|
||||
/// body should perform necessary instantiations.
|
||||
pub fn has_polymorphic_mir_body(&self) -> bool {
|
||||
match *self {
|
||||
InstanceDef::CloneShim(..)
|
||||
@ -672,13 +672,13 @@ impl<'tcx> Instance<'tcx> {
|
||||
|
||||
/// Depending on the kind of `InstanceDef`, the MIR body associated with an
|
||||
/// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
|
||||
/// cases the MIR body is expressed in terms of the types found in the substitution array.
|
||||
/// In the former case, we want to substitute those generic types and replace them with the
|
||||
/// cases the MIR body is expressed in terms of the types found in the generic parameter array.
|
||||
/// In the former case, we want to instantiate those generic types and replace them with the
|
||||
/// values from the args when monomorphizing the function body. But in the latter case, we
|
||||
/// don't want to do that substitution, since it has already been done effectively.
|
||||
/// don't want to do that instantiation, since it has already been done effectively.
|
||||
///
|
||||
/// This function returns `Some(args)` in the former case and `None` otherwise -- i.e., if
|
||||
/// this function returns `None`, then the MIR body does not require substitution during
|
||||
/// this function returns `None`, then the MIR body does not require instantiation during
|
||||
/// codegen.
|
||||
fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
|
||||
self.def.has_polymorphic_mir_body().then_some(self.args)
|
||||
|
@ -728,7 +728,7 @@ impl From<ty::ConstVid> for TermVid {
|
||||
/// the `GenericPredicates` are expressed in terms of the bound type
|
||||
/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
|
||||
/// represented a set of bounds for some particular instantiation,
|
||||
/// meaning that the generic parameters have been substituted with
|
||||
/// meaning that the generic parameters have been instantiated with
|
||||
/// their values.
|
||||
///
|
||||
/// Example:
|
||||
@ -1654,7 +1654,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
|
||||
/// Returns the possibly-auto-generated MIR of a [`ty::InstanceDef`].
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||
match instance {
|
||||
|
@ -135,7 +135,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
/// Monomorphizes a type from the AST by first applying the
|
||||
/// in-scope substitutions and then normalizing any associated
|
||||
/// in-scope instantiations and then normalizing any associated
|
||||
/// types.
|
||||
/// Panics if normalization fails. In case normalization might fail
|
||||
/// use `try_instantiate_and_normalize_erasing_regions` instead.
|
||||
@ -149,12 +149,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let substituted = value.instantiate(self, param_args);
|
||||
self.normalize_erasing_regions(param_env, substituted)
|
||||
let instantiated = value.instantiate(self, param_args);
|
||||
self.normalize_erasing_regions(param_env, instantiated)
|
||||
}
|
||||
|
||||
/// Monomorphizes a type from the AST by first applying the
|
||||
/// in-scope substitutions and then trying to normalize any associated
|
||||
/// in-scope instantiations and then trying to normalize any associated
|
||||
/// types. Contrary to `instantiate_and_normalize_erasing_regions` this does
|
||||
/// not assume that normalization succeeds.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
@ -167,8 +167,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let substituted = value.instantiate(self, param_args);
|
||||
self.try_normalize_erasing_regions(param_env, substituted)
|
||||
let instantiated = value.instantiate(self, param_args);
|
||||
self.try_normalize_erasing_regions(param_env, instantiated)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
||||
}
|
||||
|
||||
ty::Param(param) => {
|
||||
// Look it up in the substitution list.
|
||||
// Look it up in the generic parameters list.
|
||||
match self.map.get(&ty.into()).map(|k| k.unpack()) {
|
||||
// Found it in the substitution list; replace with the parameter from the
|
||||
// Found it in the generic parameters list; replace with the parameter from the
|
||||
// opaque type.
|
||||
Some(GenericArgKind::Type(t1)) => t1,
|
||||
Some(u) => panic!("type mapped to unexpected kind: {u:?}"),
|
||||
@ -199,9 +199,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
||||
// Find a const parameter
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Param(..) => {
|
||||
// Look it up in the substitution list.
|
||||
// Look it up in the generic parameters list.
|
||||
match self.map.get(&ct.into()).map(|k| k.unpack()) {
|
||||
// Found it in the substitution list, replace with the parameter from the
|
||||
// Found it in the generic parameters list, replace with the parameter from the
|
||||
// opaque type.
|
||||
Some(GenericArgKind::Const(c1)) => c1,
|
||||
Some(u) => panic!("const mapped to unexpected kind: {u:?}"),
|
||||
|
@ -323,7 +323,7 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
/// and `U` as parameter 1.
|
||||
///
|
||||
/// Trait references also appear in object types like `Foo<U>`, but in
|
||||
/// that case the `Self` parameter is absent from the substitutions.
|
||||
/// that case the `Self` parameter is absent from the generic parameters.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct TraitRef<'tcx> {
|
||||
@ -406,7 +406,7 @@ impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
|
||||
/// ```ignore (illustrative)
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
/// ```
|
||||
/// The substitutions don't include the erased `Self`, only trait
|
||||
/// The generic parameters don't include the erased `Self`, only trait
|
||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
@ -481,8 +481,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
|
||||
/// reference.
|
||||
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
|
||||
let def_id = tcx.parent(self.def_id);
|
||||
let subst_count = tcx.generics_of(def_id).count() - 1;
|
||||
let args = tcx.mk_args(&self.args[..subst_count]);
|
||||
let args_count = tcx.generics_of(def_id).count() - 1;
|
||||
let args = tcx.mk_args(&self.args[..args_count]);
|
||||
ty::ExistentialTraitRef { def_id, args }
|
||||
}
|
||||
|
||||
@ -534,12 +534,12 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> Clause<'tcx> {
|
||||
/// Performs a substitution suitable for going from a
|
||||
/// Performs a instantiation suitable for going from a
|
||||
/// poly-trait-ref to supertraits that must hold if that
|
||||
/// poly-trait-ref holds. This is slightly different from a normal
|
||||
/// substitution in terms of what happens with bound regions. See
|
||||
/// instantiation in terms of what happens with bound regions. See
|
||||
/// lengthy comment below for details.
|
||||
pub fn subst_supertrait(
|
||||
pub fn instantiate_supertrait(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
@ -556,7 +556,7 @@ impl<'tcx> Clause<'tcx> {
|
||||
// we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
|
||||
// knew that `Foo<'x>` (for any 'x) then we also know that
|
||||
// `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
|
||||
// normal substitution.
|
||||
// normal instantiation.
|
||||
//
|
||||
// In terms of why this is sound, the idea is that whenever there
|
||||
// is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
|
||||
@ -582,7 +582,7 @@ impl<'tcx> Clause<'tcx> {
|
||||
// - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
|
||||
// where both `'x` and `'b` would have a DB index of 1.
|
||||
// The substitution from the input trait-ref is therefore going to be
|
||||
// The instantiation from the input trait-ref is therefore going to be
|
||||
// `'a => 'x` (where `'x` has a DB index of 1).
|
||||
// - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
|
||||
// early-bound parameter and `'b` is a late-bound parameter with a
|
||||
@ -591,17 +591,17 @@ impl<'tcx> Clause<'tcx> {
|
||||
// a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
|
||||
// just as we wanted.
|
||||
//
|
||||
// There is only one catch. If we just apply the substitution `'a
|
||||
// => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
|
||||
// adjust the DB index because we substituting into a binder (it
|
||||
// There is only one catch. If we just apply the instantiation `'a
|
||||
// => 'x` to `for<'b> Bar1<'a,'b>`, the instantiation code will
|
||||
// adjust the DB index because we instantiating into a binder (it
|
||||
// tries to be so smart...) resulting in `for<'x> for<'b>
|
||||
// Bar1<'x,'b>` (we have no syntax for this, so use your
|
||||
// imagination). Basically the 'x will have DB index of 2 and 'b
|
||||
// will have DB index of 1. Not quite what we want. So we apply
|
||||
// the substitution to the *contents* of the trait reference,
|
||||
// the instantiation to the *contents* of the trait reference,
|
||||
// rather than the trait reference itself (put another way, the
|
||||
// substitution code expects equal binding levels in the values
|
||||
// from the substitution and the value being substituted into, and
|
||||
// instantiation code expects equal binding levels in the values
|
||||
// from the instantiation and the value being instantiated into, and
|
||||
// this trick achieves that).
|
||||
|
||||
// Working through the second example:
|
||||
|
@ -208,7 +208,7 @@ impl<'tcx> ClosureArgs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the substitutions of the closure's parent.
|
||||
/// Returns the generic parameters of the closure's parent.
|
||||
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
||||
self.split().parent_args
|
||||
}
|
||||
@ -615,7 +615,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the substitutions of the coroutine's parent.
|
||||
/// Returns the generic parameters of the coroutine's parent.
|
||||
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
||||
self.split().parent_args
|
||||
}
|
||||
@ -819,7 +819,7 @@ impl<'tcx> UpvarArgs<'tcx> {
|
||||
/// inherited from the item that defined the inline const,
|
||||
/// - R represents the type of the constant.
|
||||
///
|
||||
/// When the inline const is instantiated, `R` is substituted as the actual inferred
|
||||
/// When the inline const is instantiated, `R` is instantiated as the actual inferred
|
||||
/// type of the constant. The reason that `R` is represented as an extra type parameter
|
||||
/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters:
|
||||
/// inline const can reference lifetimes that are internal to the creating function.
|
||||
@ -858,7 +858,7 @@ impl<'tcx> InlineConstArgs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the substitutions of the inline const's parent.
|
||||
/// Returns the generic parameters of the inline const's parent.
|
||||
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
||||
self.split().parent_args
|
||||
}
|
||||
@ -1105,13 +1105,13 @@ where
|
||||
pub struct AliasTy<'tcx> {
|
||||
/// The parameters of the associated or opaque item.
|
||||
///
|
||||
/// For a projection, these are the substitutions for the trait and the
|
||||
/// GAT substitutions, if there are any.
|
||||
/// For a projection, these are the generic parameters for the trait and the
|
||||
/// GAT parameters, if there are any.
|
||||
///
|
||||
/// For an inherent projection, they consist of the self type and the GAT substitutions,
|
||||
/// For an inherent projection, they consist of the self type and the GAT parameters,
|
||||
/// if there are any.
|
||||
///
|
||||
/// For RPIT the substitutions are for the generics of the function,
|
||||
/// For RPIT the generic parameters are for the generics of the function,
|
||||
/// while for TAIT it is used for the generic parameters of the alias.
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
|
||||
@ -1235,15 +1235,15 @@ impl<'tcx> AliasTy<'tcx> {
|
||||
|
||||
/// The following methods work only with inherent associated type projections.
|
||||
impl<'tcx> AliasTy<'tcx> {
|
||||
/// Transform the substitutions to have the given `impl` args as the base and the GAT args on top of that.
|
||||
/// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
|
||||
///
|
||||
/// Does the following transformation:
|
||||
///
|
||||
/// ```text
|
||||
/// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
|
||||
///
|
||||
/// I_i impl subst
|
||||
/// P_j GAT subst
|
||||
/// I_i impl args
|
||||
/// P_j GAT args
|
||||
/// ```
|
||||
pub fn rebase_inherent_args_onto_impl(
|
||||
self,
|
||||
@ -1690,7 +1690,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
debug_assert_eq!(
|
||||
closure_args.len(),
|
||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
|
||||
"closure constructed with incorrect substitutions"
|
||||
"closure constructed with incorrect generic parameters"
|
||||
);
|
||||
Ty::new(tcx, Closure(def_id, closure_args))
|
||||
}
|
||||
@ -1704,7 +1704,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
debug_assert_eq!(
|
||||
closure_args.len(),
|
||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
|
||||
"closure constructed with incorrect substitutions"
|
||||
"closure constructed with incorrect generic parameters"
|
||||
);
|
||||
Ty::new(tcx, CoroutineClosure(def_id, closure_args))
|
||||
}
|
||||
@ -1718,7 +1718,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
debug_assert_eq!(
|
||||
coroutine_args.len(),
|
||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6,
|
||||
"coroutine constructed with incorrect number of substitutions"
|
||||
"coroutine constructed with incorrect number of generic parameters"
|
||||
);
|
||||
Ty::new(tcx, Coroutine(def_id, coroutine_args))
|
||||
}
|
||||
@ -2530,7 +2530,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
|
||||
/// Returns `true` when the outermost type cannot be further normalized,
|
||||
/// resolved, or substituted. This includes all primitive types, but also
|
||||
/// resolved, or instantiated. This includes all primitive types, but also
|
||||
/// things like ADTs and trait objects, sice even if their arguments or
|
||||
/// nested types may be further simplified, the outermost [`TyKind`] or
|
||||
/// type constructor remains the same.
|
||||
|
@ -49,19 +49,19 @@ pub struct TypeckResults<'tcx> {
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
node_types: ItemLocalMap<Ty<'tcx>>,
|
||||
|
||||
/// Stores the type parameters which were substituted to obtain the type
|
||||
/// Stores the type parameters which were instantiated to obtain the type
|
||||
/// of this node. This only applies to nodes that refer to entities
|
||||
/// parameterized by type parameters, such as generic fns, types, or
|
||||
/// other items.
|
||||
node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
|
||||
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// or the generic parameters that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
/// canonical generic parameters would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
|
||||
@ -329,7 +329,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
}
|
||||
|
||||
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
|
||||
/// doesn't provide type parameter substitutions.
|
||||
/// doesn't provide type parameter args.
|
||||
///
|
||||
/// [`expr_ty`]: TypeckResults::expr_ty
|
||||
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
|
||||
@ -341,9 +341,9 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
|
||||
/// some cases, we insert `Adjustment` annotations such as auto-deref or
|
||||
/// auto-ref. The type returned by this function does not consider such
|
||||
/// adjustments. See `expr_ty_adjusted()` instead.
|
||||
/// adjustments. See [`Self::expr_ty_adjusted`] instead.
|
||||
///
|
||||
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
|
||||
/// NB (2): This type doesn't provide type parameter args; e.g., if you
|
||||
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
|
||||
/// instead of `fn(ty) -> T with T = isize`.
|
||||
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
@ -608,7 +608,7 @@ pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
/// given generic parameters applied.
|
||||
TypeOf(DefId, UserArgs<'tcx>),
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ pub trait IsIdentity {
|
||||
}
|
||||
|
||||
impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`,
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
@ -631,7 +631,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
|
||||
match kind.unpack() {
|
||||
GenericArgKind::Type(ty) => match ty.kind() {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
@ -640,7 +640,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
|
||||
|
||||
GenericArgKind::Lifetime(r) => match *r {
|
||||
ty::ReBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == br.var
|
||||
}
|
||||
@ -649,7 +649,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
|
||||
|
||||
GenericArgKind::Const(ct) => match ct.kind() {
|
||||
ty::ConstKind::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
|
@ -801,7 +801,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
let user_provided_type = match res {
|
||||
// A reference to something callable -- e.g., a fn, method, or
|
||||
// a tuple-struct or tuple-variant. This has the type of a
|
||||
// `Fn` but with the user-given substitutions.
|
||||
// `Fn` but with the user-given generic parameters.
|
||||
Res::Def(DefKind::Fn, _)
|
||||
| Res::Def(DefKind::AssocFn, _)
|
||||
| Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
|
||||
@ -812,7 +812,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
|
||||
// A unit struct/variant which is used as a value (e.g.,
|
||||
// `None`). This has the type of the enum/struct that defines
|
||||
// this variant -- but with the substitutions given by the
|
||||
// this variant -- but with the generic parameters given by the
|
||||
// user.
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
|
||||
self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new)
|
||||
|
@ -7,7 +7,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
|
||||
fn typeck_results(&self) -> &ty::TypeckResults<'tcx>;
|
||||
|
||||
/// Looks up the type associated with this hir-id and applies the
|
||||
/// user-given substitutions; the hir-id must map to a suitable
|
||||
/// user-given generic parameters; the hir-id must map to a suitable
|
||||
/// type.
|
||||
fn user_args_applied_to_ty_of_hir_id(
|
||||
&self,
|
||||
|
@ -36,10 +36,10 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b
|
||||
ty::Tuple(tys) => {
|
||||
depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx))
|
||||
}
|
||||
ty::Adt(adt, subst) => {
|
||||
ty::Adt(adt, args) => {
|
||||
depth == 0
|
||||
|| adt.variants().iter().any(|v| {
|
||||
v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, subst), depth - 1, tcx))
|
||||
v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, args), depth - 1, tcx))
|
||||
})
|
||||
}
|
||||
// Conservative fallback
|
||||
|
@ -205,8 +205,8 @@ pub fn deduced_param_attrs<'tcx>(
|
||||
|(arg_index, local_decl)| DeducedParamAttrs {
|
||||
read_only: !deduce_read_only.mutable_args.contains(arg_index)
|
||||
// We must normalize here to reveal opaques and normalize
|
||||
// their substs, otherwise we'll see exponential blow-up in
|
||||
// compile times: #113372
|
||||
// their generic parameters, otherwise we'll see exponential
|
||||
// blow-up in compile times: #113372
|
||||
&& tcx
|
||||
.normalize_erasing_regions(param_env, local_decl.ty)
|
||||
.is_freeze(tcx, param_env),
|
||||
|
@ -63,7 +63,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
|
||||
|
||||
impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
||||
/// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the
|
||||
/// function defined by `def_id` with the substitutions `args_ref`.
|
||||
/// function defined by `def_id` with the generic parameters `args_ref`.
|
||||
fn check_bound_args(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
@ -83,11 +83,11 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
||||
for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
|
||||
// If the inner type matches the type bound by `Pointer`
|
||||
if inner_ty == bound_ty {
|
||||
// Do a substitution using the parameters from the callsite
|
||||
let subst_ty =
|
||||
// Do an instantiation using the parameters from the callsite
|
||||
let instantiated_ty =
|
||||
EarlyBinder::bind(inner_ty).instantiate(self.tcx, args_ref);
|
||||
if let Some((fn_id, fn_args)) =
|
||||
FunctionItemRefChecker::is_fn_ref(subst_ty)
|
||||
FunctionItemRefChecker::is_fn_ref(instantiated_ty)
|
||||
{
|
||||
let mut span = self.nth_arg_span(args, arg_num);
|
||||
if span.from_expansion() {
|
||||
|
@ -853,10 +853,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
|
||||
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
|
||||
if let Value::Aggregate(enum_ty, variant, _) = *self.get(place)
|
||||
&& let AggregateTy::Def(enum_did, enum_substs) = enum_ty
|
||||
&& let AggregateTy::Def(enum_did, enum_args) = enum_ty
|
||||
&& let DefKind::Enum = self.tcx.def_kind(enum_did)
|
||||
{
|
||||
let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_substs);
|
||||
let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_args);
|
||||
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?;
|
||||
return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty));
|
||||
}
|
||||
@ -899,13 +899,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
assert!(!fields.is_empty());
|
||||
(AggregateTy::Tuple, FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Closure(did, substs)
|
||||
| AggregateKind::CoroutineClosure(did, substs)
|
||||
| AggregateKind::Coroutine(did, substs) => {
|
||||
(AggregateTy::Def(did, substs), FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Adt(did, variant_index, substs, _, None) => {
|
||||
(AggregateTy::Def(did, substs), variant_index)
|
||||
AggregateKind::Closure(did, args)
|
||||
| AggregateKind::CoroutineClosure(did, args)
|
||||
| AggregateKind::Coroutine(did, args) => (AggregateTy::Def(did, args), FIRST_VARIANT),
|
||||
AggregateKind::Adt(did, variant_index, args, _, None) => {
|
||||
(AggregateTy::Def(did, args), variant_index)
|
||||
}
|
||||
// Do not track unions.
|
||||
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
|
||||
|
@ -80,7 +80,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
||||
}
|
||||
// These have no own callable MIR.
|
||||
InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => continue,
|
||||
// These have MIR and if that MIR is inlined, substituted and then inlining is run
|
||||
// These have MIR and if that MIR is inlined, instantiated and then inlining is run
|
||||
// again, a function item can end up getting inlined. Thus we'll be able to cause
|
||||
// a cycle that way
|
||||
InstanceDef::VTableShim(_)
|
||||
@ -95,7 +95,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
||||
// This shim does not call any other functions, thus there can be no recursion.
|
||||
InstanceDef::FnPtrAddrShim(..) => continue,
|
||||
InstanceDef::DropGlue(..) => {
|
||||
// FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
|
||||
// FIXME: A not fully instantiated drop shim can cause ICEs if one attempts to
|
||||
// have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
|
||||
// needs some more analysis.
|
||||
if callee.has_param() {
|
||||
|
@ -211,7 +211,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
||||
// Only bother looking more if it's easy to know what we're calling
|
||||
let Some((fn_def_id, fn_args)) = func.const_fn_def() else { return };
|
||||
|
||||
// Clone needs one subst, so we can cheaply rule out other stuff
|
||||
// Clone needs one arg, so we can cheaply rule out other stuff
|
||||
if fn_args.len() != 1 {
|
||||
return;
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
||||
//
|
||||
// We manually filter the predicates, skipping anything that's not
|
||||
// "global". We are in a potentially generic context
|
||||
// (e.g. we are evaluating a function without substituting generic
|
||||
// (e.g. we are evaluating a function without instantiating generic
|
||||
// parameters, so this filtering serves two purposes:
|
||||
//
|
||||
// 1. We skip evaluating any predicates that we would
|
||||
@ -576,10 +576,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
&inline::Inline,
|
||||
// Code from other crates may have storage markers, so this needs to happen after inlining.
|
||||
&remove_storage_markers::RemoveStorageMarkers,
|
||||
// Inlining and substitution may introduce ZST and useless drops.
|
||||
// Inlining and instantiation may introduce ZST and useless drops.
|
||||
&remove_zsts::RemoveZsts,
|
||||
&remove_unneeded_drops::RemoveUnneededDrops,
|
||||
// Type substitution may create uninhabited enums.
|
||||
// Type instantiation may create uninhabited enums.
|
||||
&uninhabited_enum_branching::UninhabitedEnumBranching,
|
||||
&unreachable_prop::UnreachablePropagation,
|
||||
&o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching),
|
||||
@ -673,7 +673,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
||||
}
|
||||
|
||||
/// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
|
||||
/// constant evaluation once all substitutions become known.
|
||||
/// constant evaluation once all generic parameters become known.
|
||||
fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
|
||||
if tcx.is_constructor(def.to_def_id()) {
|
||||
return tcx.arena.alloc(IndexVec::new());
|
||||
|
@ -44,7 +44,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
|
||||
///
|
||||
/// # Liveness
|
||||
///
|
||||
/// When performing a substitution, we must take care not to introduce uses of dangling locals.
|
||||
/// When performing an instantiation, we must take care not to introduce uses of dangling locals.
|
||||
/// To ensure this, we walk the body with the `MaybeStorageDead` dataflow analysis:
|
||||
/// - if we want to replace `*x` by reborrow `*y` and `y` may be dead, we allow replacement and
|
||||
/// mark storage statements on `y` for removal;
|
||||
@ -55,7 +55,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
|
||||
///
|
||||
/// For `&mut` borrows, we also need to preserve the uniqueness property:
|
||||
/// we must avoid creating a state where we interleave uses of `*_1` and `_2`.
|
||||
/// To do it, we only perform full substitution of mutable borrows:
|
||||
/// To do it, we only perform full instantiation of mutable borrows:
|
||||
/// we replace either all or none of the occurrences of `*_1`.
|
||||
///
|
||||
/// Some care has to be taken when `_1` is copied in other locals.
|
||||
@ -63,10 +63,10 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
|
||||
/// _3 = *_1;
|
||||
/// _4 = _1
|
||||
/// _5 = *_4
|
||||
/// In such cases, fully substituting `_1` means fully substituting all of the copies.
|
||||
/// In such cases, fully instantiating `_1` means fully instantiating all of the copies.
|
||||
///
|
||||
/// For immutable borrows, we do not need to preserve such uniqueness property,
|
||||
/// so we perform all the possible substitutions without removing the `_1 = &_2` statement.
|
||||
/// so we perform all the possible instantiations without removing the `_1 = &_2` statement.
|
||||
pub struct ReferencePropagation;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for ReferencePropagation {
|
||||
|
@ -477,7 +477,7 @@ struct CloneShimBuilder<'tcx> {
|
||||
|
||||
impl<'tcx> CloneShimBuilder<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
|
||||
// we must subst the self_ty because it's
|
||||
// we must instantiate the self_ty because it's
|
||||
// otherwise going to be TySelf and we can't index
|
||||
// or access fields of a Place of type TySelf.
|
||||
let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]);
|
||||
@ -716,8 +716,8 @@ fn build_call_shim<'tcx>(
|
||||
call_kind: CallKind<'tcx>,
|
||||
) -> Body<'tcx> {
|
||||
// `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
|
||||
// to substitute into the signature of the shim. It is not necessary for users of this
|
||||
// MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`).
|
||||
// to instantiate into the signature of the shim. It is not necessary for users of this
|
||||
// MIR body to perform further instantiations (see `InstanceDef::has_polymorphic_mir_body`).
|
||||
let (sig_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
|
||||
let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
|
||||
|
||||
|
@ -170,7 +170,7 @@ impl SsaLocals {
|
||||
/// _c => _a
|
||||
/// _d => _a // transitively through _c
|
||||
///
|
||||
/// Exception: we do not see through the return place, as it cannot be substituted.
|
||||
/// Exception: we do not see through the return place, as it cannot be instantiated.
|
||||
pub fn copy_classes(&self) -> &IndexSlice<Local, Local> {
|
||||
&self.copy_classes
|
||||
}
|
||||
|
@ -62,7 +62,7 @@
|
||||
//! syntactic items in the source code. We find them by walking the HIR of the
|
||||
//! crate, and whenever we hit upon a public function, method, or static item,
|
||||
//! we create a mono item consisting of the items DefId and, since we only
|
||||
//! consider non-generic items, an empty type-substitution set. (In eager
|
||||
//! consider non-generic items, an empty type-parameters set. (In eager
|
||||
//! collection mode, during incremental compilation, all non-generic functions
|
||||
//! are considered as roots, as well as when the `-Clink-dead-code` option is
|
||||
//! specified. Functions marked `#[no_mangle]` and functions called by inlinable
|
||||
@ -1383,11 +1383,11 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||
// items, we never actually check that the predicates of this impl are satisfied
|
||||
// in a empty reveal-all param env (i.e. with no assumptions).
|
||||
//
|
||||
// Even though this impl has no type or const substitutions, because we don't
|
||||
// Even though this impl has no type or const generic parameters, because we don't
|
||||
// consider higher-ranked predicates such as `for<'a> &'a mut [u8]: Copy` to
|
||||
// be trivially false. We must now check that the impl has no impossible-to-satisfy
|
||||
// predicates.
|
||||
if tcx.subst_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_args)) {
|
||||
if tcx.instantiate_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_args)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1404,7 +1404,7 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||
}
|
||||
|
||||
// As mentioned above, the method is legal to eagerly instantiate if it
|
||||
// only has lifetime substitutions. This is validated by
|
||||
// only has lifetime generic parameters. This is validated by
|
||||
let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params);
|
||||
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args);
|
||||
|
||||
|
@ -90,7 +90,7 @@ fn should_polymorphize<'tcx>(
|
||||
def_id: DefId,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
) -> bool {
|
||||
// If an instance's MIR body is not polymorphic then the modified substitutions that are
|
||||
// If an instance's MIR body is not polymorphic then the modified generic parameters that are
|
||||
// derived from polymorphization's result won't make any difference.
|
||||
if !instance.has_polymorphic_mir_body() {
|
||||
return false;
|
||||
|
@ -263,11 +263,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
|
||||
for &(variant, field) in indices {
|
||||
match current_ty.kind() {
|
||||
ty::Adt(def, subst) => {
|
||||
ty::Adt(def, args) => {
|
||||
let field = &def.variant(variant).fields[field];
|
||||
|
||||
self.insert_def_id(field.did);
|
||||
let field_ty = field.ty(self.tcx, subst);
|
||||
let field_ty = field.ty(self.tcx, args);
|
||||
|
||||
current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
||||
|
||||
variant.fields.iter().enumerate().filter_map(move |(i, field)| {
|
||||
let ty = field.ty(cx.tcx, args);
|
||||
// `field.ty()` doesn't normalize after substituting.
|
||||
// `field.ty()` doesn't normalize after instantiating.
|
||||
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
|
||||
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
|
||||
|
@ -133,7 +133,7 @@ where
|
||||
if V::SHALLOW {
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
assoc_args.iter().try_for_each(|subst| subst.visit_with(self))
|
||||
assoc_args.iter().try_for_each(|arg| arg.visit_with(self))
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ where
|
||||
// Visitors searching for minimal visibility/reachability want to
|
||||
// conservatively approximate associated types like `Type::Alias`
|
||||
// as visible/reachable even if `Type` is private.
|
||||
// Ideally, associated types should be substituted in the same way as
|
||||
// Ideally, associated types should be instantiated in the same way as
|
||||
// free type aliases, but this isn't done yet.
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
@ -230,7 +230,7 @@ where
|
||||
} else if kind == ty::Projection {
|
||||
self.visit_projection_ty(data)
|
||||
} else {
|
||||
data.args.iter().try_for_each(|subst| subst.visit_with(self))
|
||||
data.args.iter().try_for_each(|arg| arg.visit_with(self))
|
||||
};
|
||||
}
|
||||
ty::Dynamic(predicates, ..) => {
|
||||
|
@ -369,7 +369,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
assert!(!instance.has_non_region_param(), "{instance:?} needs further substitution");
|
||||
assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
|
||||
instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables)
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ fn get_symbol_hash<'tcx>(
|
||||
instance: Instance<'tcx>,
|
||||
|
||||
// type of the item, without any generic
|
||||
// parameters substituted; this is
|
||||
// parameters instantiated; this is
|
||||
// included in the hash as a kind of
|
||||
// safeguard.
|
||||
item_type: Ty<'tcx>,
|
||||
|
@ -251,8 +251,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
None => "M",
|
||||
});
|
||||
|
||||
// Encode impl generic params if the substitutions contain parameters (implying
|
||||
// polymorphization is enabled) and this isn't an inherent impl.
|
||||
// Encode impl generic params if the generic parameters contain non-region parameters
|
||||
// (implying polymorphization is enabled) and this isn't an inherent impl.
|
||||
if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
|
||||
self.path_generic_args(
|
||||
|this| {
|
||||
|
@ -576,7 +576,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
||||
assert_eq!(
|
||||
old_ty,
|
||||
None,
|
||||
"{} has two substitutions: {} and {}",
|
||||
"{} has two generic parameters: {} and {}",
|
||||
proj.projection_ty,
|
||||
proj.term,
|
||||
old_ty.unwrap()
|
||||
|
@ -192,11 +192,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
original_values: Vec<ty::GenericArg<'tcx>>,
|
||||
response: CanonicalResponse<'tcx>,
|
||||
) -> Result<(Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
|
||||
let substitution =
|
||||
Self::compute_query_response_substitution(self.infcx, &original_values, &response);
|
||||
let instantiation = Self::compute_query_response_instantiation_values(
|
||||
self.infcx,
|
||||
&original_values,
|
||||
&response,
|
||||
);
|
||||
|
||||
let Response { var_values, external_constraints, certainty } =
|
||||
response.substitute(self.tcx(), &substitution);
|
||||
response.instantiate(self.tcx(), &instantiation);
|
||||
|
||||
let nested_goals =
|
||||
Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values)?;
|
||||
@ -209,10 +212,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
Ok((certainty, nested_goals))
|
||||
}
|
||||
|
||||
/// This returns the substitutions to instantiate the bound variables of
|
||||
/// This returns the canoncial variable values to instantiate the bound variables of
|
||||
/// the canonical response. This depends on the `original_values` for the
|
||||
/// bound variables.
|
||||
fn compute_query_response_substitution<T: ResponseT<'tcx>>(
|
||||
fn compute_query_response_instantiation_values<T: ResponseT<'tcx>>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
original_values: &[ty::GenericArg<'tcx>],
|
||||
response: &Canonical<'tcx, T>,
|
||||
@ -369,10 +372,10 @@ impl<'tcx> inspect::ProofTreeBuilder<'tcx> {
|
||||
original_values: &[ty::GenericArg<'tcx>],
|
||||
state: inspect::CanonicalState<'tcx, T>,
|
||||
) -> Result<(Vec<Goal<'tcx, ty::Predicate<'tcx>>>, T), NoSolution> {
|
||||
let substitution =
|
||||
EvalCtxt::compute_query_response_substitution(infcx, original_values, &state);
|
||||
let instantiation =
|
||||
EvalCtxt::compute_query_response_instantiation_values(infcx, original_values, &state);
|
||||
|
||||
let inspect::State { var_values, data } = state.substitute(infcx.tcx, &substitution);
|
||||
let inspect::State { var_values, data } = state.instantiate(infcx.tcx, &instantiation);
|
||||
|
||||
let nested_goals =
|
||||
EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values)?;
|
||||
|
@ -312,8 +312,8 @@ fn rematch_unsize<'tcx>(
|
||||
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
|
||||
|
||||
// Substitute just the unsizing params from B into A. The type after
|
||||
// this substitution must be equal to B. This is so we don't unsize
|
||||
// Instantiate just the unsizing params from B into A. The type after
|
||||
// this instantiation must be equal to B. This is so we don't unsize
|
||||
// unrelated type parameters.
|
||||
let new_a_args = tcx.mk_args_from_iter(
|
||||
a_args
|
||||
@ -349,7 +349,7 @@ fn rematch_unsize<'tcx>(
|
||||
let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||
let b_last_ty = b_tys.last().unwrap();
|
||||
|
||||
// Substitute just the tail field of B., and require that they're equal.
|
||||
// Instantiate just the tail field of B., and require that they're equal.
|
||||
let unsized_a_ty =
|
||||
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied());
|
||||
nested.extend(
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Computes a normalizes-to (projection) goal for inherent associated types,
|
||||
//! `#![feature(inherent_associated_type)]`. Since astconv already determines
|
||||
//! which impl the IAT is being projected from, we just:
|
||||
//! 1. instantiate substs,
|
||||
//! 1. instantiate generic parameters,
|
||||
//! 2. equate the self type, and
|
||||
//! 3. instantiate and register where clauses.
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
|
||||
@ -19,21 +19,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
|
||||
|
||||
let impl_def_id = tcx.parent(inherent.def_id);
|
||||
let impl_substs = self.fresh_args_for_item(impl_def_id);
|
||||
let impl_args = self.fresh_args_for_item(impl_def_id);
|
||||
|
||||
// Equate impl header and add impl where clauses
|
||||
self.eq(
|
||||
goal.param_env,
|
||||
inherent.self_ty(),
|
||||
tcx.type_of(impl_def_id).instantiate(tcx, impl_substs),
|
||||
tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
|
||||
)?;
|
||||
|
||||
// Equate IAT with the RHS of the project goal
|
||||
let inherent_substs = inherent.rebase_inherent_args_onto_impl(impl_substs, tcx);
|
||||
let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, tcx);
|
||||
self.eq(
|
||||
goal.param_env,
|
||||
expected,
|
||||
tcx.type_of(inherent.def_id).instantiate(tcx, inherent_substs),
|
||||
tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args),
|
||||
)
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
|
||||
@ -46,7 +46,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(inherent.def_id)
|
||||
.instantiate(tcx, inherent_substs)
|
||||
.instantiate(tcx, inherent_args)
|
||||
.into_iter()
|
||||
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||
);
|
||||
|
@ -877,8 +877,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
|
||||
|
||||
// Substitute just the unsizing params from B into A. The type after
|
||||
// this substitution must be equal to B. This is so we don't unsize
|
||||
// Instantiate just the unsizing params from B into A. The type after
|
||||
// this instantiation must be equal to B. This is so we don't unsize
|
||||
// unrelated type parameters.
|
||||
let new_a_args = tcx.mk_args_from_iter(
|
||||
a_args
|
||||
@ -927,7 +927,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||
let &b_last_ty = b_tys.last().unwrap();
|
||||
|
||||
// Substitute just the tail field of B., and require that they're equal.
|
||||
// Instantiate just the tail field of B., and require that they're equal.
|
||||
let unsized_a_ty =
|
||||
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().copied().chain([b_last_ty]));
|
||||
self.eq(goal.param_env, unsized_a_ty, b_ty)?;
|
||||
|
@ -84,7 +84,7 @@ impl TrackAmbiguityCauses {
|
||||
|
||||
/// If there are types that satisfy both impls, returns `Some`
|
||||
/// with a suitably-freshened `ImplHeader` with those types
|
||||
/// substituted. Otherwise, returns `None`.
|
||||
/// instantiated. Otherwise, returns `None`.
|
||||
#[instrument(skip(tcx, skip_leak_check), level = "debug")]
|
||||
pub fn overlapping_impls(
|
||||
tcx: TyCtxt<'_>,
|
||||
@ -561,21 +561,21 @@ pub fn trait_ref_is_knowable<'tcx, E: Debug>(
|
||||
) -> Result<Result<(), Conflict>, E> {
|
||||
if orphan_check_trait_ref(trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() {
|
||||
// A downstream or cousin crate is allowed to implement some
|
||||
// substitution of this trait-ref.
|
||||
// generic parameters of this trait-ref.
|
||||
return Ok(Err(Conflict::Downstream));
|
||||
}
|
||||
|
||||
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
|
||||
// This is a local or fundamental trait, so future-compatibility
|
||||
// is no concern. We know that downstream/cousin crates are not
|
||||
// allowed to implement a substitution of this trait ref, which
|
||||
// means impls could only come from dependencies of this crate,
|
||||
// which we already know about.
|
||||
// allowed to implement a generic parameter of this trait ref,
|
||||
// which means impls could only come from dependencies of this
|
||||
// crate, which we already know about.
|
||||
return Ok(Ok(()));
|
||||
}
|
||||
|
||||
// This is a remote non-fundamental trait, so if another crate
|
||||
// can be the "final owner" of a substitution of this trait-ref,
|
||||
// can be the "final owner" of the generic parameters of this trait-ref,
|
||||
// they are allowed to implement it future-compatibly.
|
||||
//
|
||||
// However, if we are a final owner, then nobody else can be,
|
||||
@ -628,8 +628,8 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
|
||||
///
|
||||
/// The current rule is that a trait-ref orphan checks in a crate C:
|
||||
///
|
||||
/// 1. Order the parameters in the trait-ref in subst order - Self first,
|
||||
/// others linearly (e.g., `<U as Foo<V, W>>` is U < V < W).
|
||||
/// 1. Order the parameters in the trait-ref in generic parameters order
|
||||
/// - Self first, others linearly (e.g., `<U as Foo<V, W>>` is U < V < W).
|
||||
/// 2. Of these type parameters, there is at least one type parameter
|
||||
/// in which, walking the type as a tree, you can reach a type local
|
||||
/// to C where all types in-between are fundamental types. Call the
|
||||
@ -696,7 +696,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
|
||||
///
|
||||
/// Because we never perform negative reasoning generically (coherence does
|
||||
/// not involve type parameters), this can be interpreted as doing the full
|
||||
/// orphan check (using InCrate::Local mode), substituting non-local known
|
||||
/// orphan check (using InCrate::Local mode), instantiating non-local known
|
||||
/// types for all inference variables.
|
||||
///
|
||||
/// This allows for crates to future-compatibly add impls as long as they
|
||||
|
@ -242,7 +242,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
self.tcx.lang_items().fn_once_trait(),
|
||||
] {
|
||||
let Some(trait_def_id) = trait_def_id else { continue };
|
||||
// Make a fresh inference variable so we can determine what the substitutions
|
||||
// Make a fresh inference variable so we can determine what the generic parameters
|
||||
// of the trait are.
|
||||
let var = self.next_ty_var(TypeVariableOrigin {
|
||||
span: DUMMY_SP,
|
||||
|
@ -814,7 +814,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
tcx.dcx(),
|
||||
self.span,
|
||||
E0231,
|
||||
"only named substitution parameters are allowed"
|
||||
"only named generic parameters are allowed"
|
||||
)
|
||||
.emit();
|
||||
result = Err(reported);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user