Rollup merge of #120958 - ShoyuVanilla:remove-subst, r=oli-obk

Dejargonize `subst`

In favor of #110793, replace almost every occurence of `subst` and `substitution` from rustc codes, but they still remains in subtrees under `src/tools/` like clippy and test codes (I'd like to replace them after this)
This commit is contained in:
Matthias Krüger 2024-02-12 23:18:54 +01:00 committed by GitHub
commit cb0d74be28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
130 changed files with 576 additions and 543 deletions

View File

@ -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) // 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`. // 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. // borrowed variants in a function body when we see a move error.
let borrow_level = match *ty.kind() { let borrow_level = match *ty.kind() {
ty::Param(_) => tcx ty::Param(_) => tcx

View File

@ -45,7 +45,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// be allowed: /// be allowed:
/// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }` /// `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`, /// `external_name` giving `concrete_type = &'a i32`,
/// `args = ['static, 'a]`. This will then allow /// `args = ['static, 'a]`. This will then allow
/// `infer_opaque_definition_from_instantiation` to determine that /// `infer_opaque_definition_from_instantiation` to determine that
@ -77,9 +77,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let args = opaque_type_key.args; let args = opaque_type_key.args;
debug!(?concrete_type, ?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); trace!(?vid);
let scc = self.constraint_sccs.scc(vid); let scc = self.constraint_sccs.scc(vid);
trace!(?scc); trace!(?scc);
@ -88,11 +88,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}) { }) {
Some(region) => { Some(region) => {
let vid = self.universal_regions.to_region_vid(region); let vid = self.universal_regions.to_region_vid(region);
subst_regions.push(vid); arg_regions.push(vid);
region region
} }
None => { None => {
subst_regions.push(vid); arg_regions.push(vid);
ty::Region::new_error_with_message( ty::Region::new_error_with_message(
infcx.tcx, infcx.tcx,
concrete_type.span, 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. // This will ensure they get precedence when folding the regions in the concrete type.
if let Some(&ci) = member_constraints.get(&opaque_type_key) { if let Some(&ci) = member_constraints.get(&opaque_type_key) {
for &vid in self.member_constraints.choice_regions(ci) { 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 // 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. // in them but are not subject to member constraints, for instance closure args.
@ -119,18 +119,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return region; return region;
} }
let vid = self.to_region_vid(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!(?universal_args);
debug!(?subst_regions); debug!(?arg_regions);
// Deduplicate the set of regions while keeping the chosen order. // Deduplicate the set of regions while keeping the chosen order.
let subst_regions = subst_regions.into_iter().collect::<FxIndexSet<_>>(); let arg_regions = arg_regions.into_iter().collect::<FxIndexSet<_>>();
debug!(?subst_regions); debug!(?arg_regions);
let universal_concrete_type = let universal_concrete_type =
infcx.tcx.fold_regions(concrete_type, |region, _| match *region { infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
ty::ReVar(vid) => subst_regions ty::ReVar(vid) => arg_regions
.iter() .iter()
.find(|ur_vid| self.eval_equal(vid, **ur_vid)) .find(|ur_vid| self.eval_equal(vid, **ur_vid))
.and_then(|ur_vid| self.definitions[*ur_vid].external_name) .and_then(|ur_vid| self.definitions[*ur_vid].external_name)

View File

@ -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 /// 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. /// 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>>, T: TypeFoldable<TyCtxt<'tcx>>,
>( >(
&self, &self,
value: T, value: T,
) -> Result<T, ErrorHandled> { ) -> 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 /// 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. /// 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, &self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>, frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
value: T, 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 layout = from_known_layout(self.tcx, self.param_env, layout, || {
let local_ty = frame.body.local_decls[local].ty; 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) 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). // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
if M::POST_MONO_CHECKS { if M::POST_MONO_CHECKS {
for &const_ in &body.required_consts { for &const_ in &body.required_consts {
let c = let c = self
self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?; .instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| { c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| {
err.emit_note(*self.tcx); err.emit_note(*self.tcx);
err err

View File

@ -696,7 +696,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("eval_place_to_op: got {:?}", op); trace!("eval_place_to_op: got {:?}", op);
// Sanity-check the type we ended up with. // Sanity-check the type we ended up with.
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( let normalized_place_ty = self
.instantiate_from_current_frame_and_normalize_erasing_regions(
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
)?; )?;
if !mir_assign_valid_types( if !mir_assign_valid_types(
@ -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)?, &Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?,
Constant(constant) => { Constant(constant) => {
let c = let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(
self.subst_from_current_frame_and_normalize_erasing_regions(constant.const_)?; constant.const_,
)?;
// This can still fail: // This can still fail:
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all

View File

@ -542,7 +542,8 @@ where
trace!("{:?}", self.dump_place(&place)); trace!("{:?}", self.dump_place(&place));
// Sanity-check the type we ended up with. // Sanity-check the type we ended up with.
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( let normalized_place_ty = self
.instantiate_from_current_frame_and_normalize_erasing_regions(
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
)?; )?;
if !mir_assign_valid_types( if !mir_assign_valid_types(

View File

@ -235,7 +235,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
NullaryOp(ref null_op, ty) => { 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)?; let layout = self.layout_of(ty)?;
if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op
&& layout.is_unsized() && 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) => { Cast(cast_kind, ref operand, cast_ty) => {
let src = self.eval_operand(operand, None)?; let src = self.eval_operand(operand, None)?;
let cast_ty = 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)?; self.cast(&src, cast_kind, cast_ty, &dest)?;
} }

View File

@ -173,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Drop { place, target, unwind, replace: _ } => { Drop { place, target, unwind, replace: _ } => {
let frame = self.frame(); let frame = self.frame();
let ty = place.ty(&frame.body.local_decls, *self.tcx).ty; 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); let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
if let ty::InstanceDef::DropGlue(_, None) = instance.def { 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 // 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 // Construct the destination place for this argument. At this point all
// locals are still dead, so we cannot construct a `PlaceTy`. // locals are still dead, so we cannot construct a `PlaceTy`.
let dest = mir::Place::from(local); let dest = mir::Place::from(local);
// `layout_of_local` does more than just the substitution we need to get the // `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 substitution // type, but the result gets cached so this avoids calling the instantiation
// query *again* the next time this local is accessed. // query *again* the next time this local is accessed.
let ty = self.layout_of_local(self.frame(), local, None)?.ty; let ty = self.layout_of_local(self.frame(), local, None)?.ty;
if Some(local) == body.spread_arg { if Some(local) == body.spread_arg {

View File

@ -19,11 +19,11 @@ where
} }
struct FoundParam; struct FoundParam;
struct UsedParamsNeedSubstVisitor<'tcx> { struct UsedParamsNeedInstantiationVisitor<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedSubstVisitor<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
type BreakTy = FoundParam; type BreakTy = FoundParam;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -39,17 +39,17 @@ where
| ty::FnDef(def_id, args) => { | ty::FnDef(def_id, args) => {
let instance = ty::InstanceDef::Item(def_id); let instance = ty::InstanceDef::Item(def_id);
let unused_params = self.tcx.unused_generic_params(instance); 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 let index = index
.try_into() .try_into()
.expect("more generic parameters than can fit into a `u32`"); .expect("more generic parameters than can fit into a `u32`");
// Only recurse when generic parameters in fns, closures and coroutines // Only recurse when generic parameters in fns, closures and coroutines
// are used and have to be instantiated. // 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. // recurse.
if unused_params.is_used(index) && subst.has_param() { if unused_params.is_used(index) && arg.has_param() {
return subst.visit_with(self); return arg.visit_with(self);
} }
} }
ControlFlow::Continue(()) ControlFlow::Continue(())
@ -66,7 +66,7 @@ where
} }
} }
let mut vis = UsedParamsNeedSubstVisitor { tcx }; let mut vis = UsedParamsNeedInstantiationVisitor { tcx };
if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) {
throw_inval!(TooGeneric); throw_inval!(TooGeneric);
} else { } else {

View File

@ -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 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 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 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 with different type parameter instantiations. It's not possible to check this
_all_ possible types, so `transmute()` simply only accepts types without any for _all_ possible types, so `transmute()` simply only accepts types without any
unsubstituted type parameters. uninstantiated type parameters.
If you need this, there's a good chance you're doing something wrong. Keep in 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 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. 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 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: for example:
``` ```

View File

@ -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`". note saying "the type `bool` cannot be indexed by `u8`".
As you can see, you can specify type parameters in curly braces for 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 instantiation with the actual types (using the regular format string syntax) in
a given situation. Furthermore, `{Self}` will substitute to the type (in this a given situation. Furthermore, `{Self}` will be instantiated to the type (in
case, `bool`) that we tried to use. this case, `bool`) that we tried to use.
This error appears when the curly braces contain an identifier which doesn't 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 match with any of the type parameters or the string `Self`. This might happen

View File

@ -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`". note saying "the type `bool` cannot be indexed by `u8`".
As you can see, you can specify type parameters in curly braces for 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 instantiation with the actual types (using the regular format string syntax) in
a given situation. Furthermore, `{Self}` will substitute to the type (in this a given situation. Furthermore, `{Self}` will be instantiated to the type (in
case, `bool`) that we tried to use. this case, `bool`) that we tried to use.
This error appears when the curly braces do not contain an identifier. Please 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 add one of the same name as a type parameter. If you intended to use literal

View File

@ -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 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. 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 `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 implement `A<bool>`, etc... These types will not share an implementation of a
fully-defined trait; instead they share implementations of a trait with 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 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 disallowed. Making the trait concrete by explicitly specifying the value of the
defaulted parameter will fix this issue. Fixed example: defaulted parameter will fix this issue. Fixed example:

View File

@ -14,7 +14,7 @@ let _ = foo::<'static>;
The type of a concrete instance of a generic function is universally quantified 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 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 matter where the function is called. Consequently, it doesn't make sense to
specify arguments for late-bound lifetime parameters, since they are not specify arguments for late-bound lifetime parameters, since they are not
resolved until the function's call site(s). 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 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`, `'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 lifetime. It is not allowed to explicitly specify early-bound lifetime
arguments when late-bound lifetime parameters are present (as for `bar_fn2`, arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
see [issue #42868](https://github.com/rust-lang/rust/issues/42868)), although see [issue #42868](https://github.com/rust-lang/rust/issues/42868)), although

View File

@ -2536,7 +2536,7 @@ pub struct OpaqueTy<'hir> {
/// lifetimes that are captured from the function signature they originate from. /// 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 /// 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. /// lifetime.
/// ///
/// This mapping associated a captured lifetime (first parameter) with the new /// This mapping associated a captured lifetime (first parameter) with the new

View File

@ -153,6 +153,8 @@ hir_analysis_function_not_have_default_implementation = function doesn't have a
hir_analysis_functions_names_duplicated = functions names are duplicated hir_analysis_functions_names_duplicated = functions names are duplicated
.note = all `#[rustc_must_implement_one_of]` arguments must be unique .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` 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}` .label = cannot specialize default item `{$ident}`
.ok_label = parent `impl` is here .ok_label = parent `impl` is here
@ -387,8 +389,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_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 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 .note = this item must mention the opaque type in its signature in order to be able to register hidden types

View File

@ -336,12 +336,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
let projection_ty = if let ty::AssocKind::Fn = assoc_kind { let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
let mut emitted_bad_param_err = None; 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. // the method's early bound params with suitable late-bound params.
let mut num_bound_vars = candidate.bound_vars().len(); let mut num_bound_vars = candidate.bound_vars().len();
let args = let args =
candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { 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( ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
tcx, tcx,
ty::INNERMOST, ty::INNERMOST,
@ -379,7 +379,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
} }
}; };
num_bound_vars += 1; num_bound_vars += 1;
subst arg
}); });
// Next, we need to check that the return-type notation is being used on // 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 // 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 // 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 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); 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 { } else {
// Append the generic arguments of the associated type to the `trait_ref`. // Append the generic arguments of the associated type to the `trait_ref`.
candidate.map_bound(|trait_ref| { candidate.map_bound(|trait_ref| {

View File

@ -1,6 +1,6 @@
use super::IsMethodCall; use super::IsMethodCall;
use crate::astconv::{ use crate::astconv::{
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound,
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
}; };
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; 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, has_self: bool,
self_ty: Option<Ty<'tcx>>, self_ty: Option<Ty<'tcx>>,
arg_count: &GenericArgCountResult, arg_count: &GenericArgCountResult,
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ctx: &mut impl CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>,
) -> GenericArgsRef<'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 // for parameters throughout the entire path (wherever there are
// generic parameters). // generic parameters).
let mut parent_defs = tcx.generics_of(def_id); 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 // 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. // parameters in lock-step linearly, instead of trying to match each pair.
let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
// Iterate over each segment of the path. // Iterate over each segment of the path.

View File

@ -214,7 +214,7 @@ pub struct GenericArgCountResult {
pub correct: Result<(), GenericArgCountMismatch>, 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 args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
fn provided_kind( fn provided_kind(
@ -366,8 +366,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if generics.has_self { if generics.has_self {
if generics.parent.is_some() { if generics.parent.is_some() {
// The parent is a trait so it should have at least one subst // The parent is a trait so it should have at least one
// for the `Self` type. // generic parameter for the `Self` type.
assert!(!parent_args.is_empty()) assert!(!parent_args.is_empty())
} else { } else {
// This item (presumably a trait) needs a self-type. // 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); return (tcx.mk_args(parent_args), arg_count);
} }
struct SubstsForAstPathCtxt<'a, 'tcx> { struct InstantiationsForAstPathCtxt<'a, 'tcx> {
astconv: &'a (dyn AstConv<'tcx> + 'a), astconv: &'a (dyn AstConv<'tcx> + 'a),
def_id: DefId, def_id: DefId,
generic_args: &'a GenericArgs<'tcx>, generic_args: &'a GenericArgs<'tcx>,
@ -411,7 +411,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
infer_args: bool, 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) { fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
if did == self.def_id { if did == self.def_id {
(Some(self.generic_args), self.infer_args) (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, astconv: self,
def_id, def_id,
span, span,
@ -2412,8 +2414,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let self_ty = self.tcx().type_of(parent).instantiate_identity(); let self_ty = self.tcx().type_of(parent).instantiate_identity();
let generic_self_ty = ty::GenericArg::from(self_ty); let generic_self_ty = ty::GenericArg::from(self_ty);
let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty)); let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
sig.instantiate(self.tcx(), substs) sig.instantiate(self.tcx(), args)
} else { } else {
sig.instantiate_identity() sig.instantiate_identity()
}; };

View File

@ -175,7 +175,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
let pred = bound_predicate.rebind(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. // `trait_object_dummy_self`, so check for that.
let references_self = match pred.skip_binder().term.unpack() { let references_self = match pred.skip_binder().term.unpack() {
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),

View File

@ -1083,7 +1083,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
match t.kind() { match t.kind() {
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
ty::Adt(def, subst) => { ty::Adt(def, args) => {
if !def.did().is_local() { if !def.did().is_local() {
let non_exhaustive = def.is_variant_list_non_exhaustive() let non_exhaustive = def.is_variant_list_non_exhaustive()
|| def || def
@ -1095,13 +1095,13 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
return ControlFlow::Break(( return ControlFlow::Break((
def.descr(), def.descr(),
def.did(), def.did(),
subst, args,
non_exhaustive, non_exhaustive,
)); ));
} }
} }
def.all_fields() def.all_fields()
.map(|field| field.ty(tcx, subst)) .map(|field| field.ty(tcx, args))
.try_for_each(|t| check_non_exhaustive(tcx, t)) .try_for_each(|t| check_non_exhaustive(tcx, t))
} }
_ => ControlFlow::Continue(()), _ => ControlFlow::Continue(()),

View File

@ -125,9 +125,9 @@ fn check_method_is_structurally_compatible<'tcx>(
/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo /// <'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 /// 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 /// `impl_to_placeholder_args`, and also adding a mapping for the method
/// type parameters. We extend the mapping to also include /// type parameters. We extend the mapping to also include
/// the method parameters. /// 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 /// vs `'b`). However, the normal subtyping rules on fn types handle
/// this kind of equivalency just fine. /// this kind of equivalency just fine.
/// ///
/// We now use these substitutions to ensure that all declared bounds are /// We now use these generic parameters to ensure that all declared bounds
/// satisfied by the implementation's method. /// are satisfied by the implementation's method.
/// ///
/// We do this by creating a parameter environment which contains a /// 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 /// `trait_to_placeholder_args` and use it to convert the predicates contained
/// in the `trait_m` generics to the placeholder form. /// 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 = let impl_trait_ref =
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity(); 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`, // 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)?; check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
let trait_to_impl_args = impl_trait_ref.args; 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 // .. 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 // 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 // means that we will use the hidden type to imply the hidden type's own
// well-formedness. // 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 // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
// region args that are synthesized during AST lowering. These are args // region args that are synthesized during AST lowering. These are args
// that are appended to the parent args (trait and trait method). However, // 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 // 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`). // 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. // 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 // 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 // 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, // 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 // since we previously enforce that the trait method and impl method have the

View File

@ -124,14 +124,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); 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 // 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 // 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 // well-formed adt, since that's all we're allowed to assume while proving
// the Drop implementation is not specialized. // the Drop implementation is not specialized.
// //
// We don't need to normalize this param-env or anything, since we're only // 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. // can occur on top of what has been done in the param_env query itself.
let param_env = let param_env =
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);

View File

@ -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 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 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 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 eventually be resolved to some concrete type (which might itself be
a type parameter). a type parameter).

View File

@ -618,7 +618,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// The bounds we that we would require from `to_check` // The bounds we that we would require from `to_check`
let mut bounds = FxHashSet::default(); 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 // 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 // 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 /// `<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 /// the two vectors, `regions` and `types` (depending on their kind). For each
/// parameter `Pi` also track the index `i`. /// parameter `Pi` also track the index `i`.
struct GATSubstCollector<'tcx> { struct GATArgsCollector<'tcx> {
gat: DefId, 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)>, 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)>, types: FxHashSet<(Ty<'tcx>, usize)>,
} }
impl<'tcx> GATSubstCollector<'tcx> { impl<'tcx> GATArgsCollector<'tcx> {
fn visit<T: TypeFoldable<TyCtxt<'tcx>>>( fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(
gat: DefId, gat: DefId,
t: T, t: T,
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) { ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
let mut visitor = let mut visitor =
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() }; GATArgsCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
t.visit_with(&mut visitor); t.visit_with(&mut visitor);
(visitor.regions, visitor.types) (visitor.regions, visitor.types)
} }
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
type BreakTy = !; type BreakTy = !;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() { match t.kind() {
ty::Alias(ty::Projection, p) if p.def_id == self.gat => { ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
for (idx, subst) in p.args.iter().enumerate() { for (idx, arg) in p.args.iter().enumerate() {
match subst.unpack() { match arg.unpack() {
GenericArgKind::Lifetime(lt) if !lt.is_bound() => { GenericArgKind::Lifetime(lt) if !lt.is_bound() => {
self.regions.insert((lt, idx)); 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 // 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>`. // 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 // 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`. // 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, _| { let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
match param.kind { match param.kind {
GenericParamDefKind::Lifetime => { 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(); let default_ty = tcx.type_of(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ... // ... and it's not a dependent default, ...
if !default_ty.has_param() { if !default_ty.has_param() {
// ... then substitute it with the default. // ... then instantiate it with the default.
return default_ty.into(); 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(); let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ... // ... and it's not a dependent default, ...
if !default_ct.has_param() { if !default_ct.has_param() {
// ... then substitute it with the default. // ... then instantiate it with the default.
return default_ct.into(); 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 let default_obligations = predicates
.predicates .predicates
.iter() .iter()
@ -1483,23 +1483,25 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
} }
let mut param_count = CountParams::default(); let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break(); 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) // Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params. // 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 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. // Avoid duplication of predicates that contain no parameters, for example.
None None
} else { } else {
Some((substituted_pred, sp)) Some((instantiated_pred, sp))
} }
}) })
.map(|(pred, sp)| { .map(|(pred, sp)| {
// Convert each of those into an obligation. So if you have // Convert each of those into an obligation. So if you have
// something like `struct Foo<T: Copy = String>`, we would // 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), // (actually that happens in the previous `flat_map` call),
// and then try to prove it (in this case, we'll fail). // and then try to prove it (in this case, we'll fail).
// //

View File

@ -396,7 +396,7 @@ pub fn coerce_unsized_info<'tcx>(
// //
// To check if this impl is legal, we would walk down // To check if this impl is legal, we would walk down
// the fields of `Foo` and consider their types with // 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 // exactly one (non-phantom) field has changed its
// type, which we will expect to be the pointer that // type, which we will expect to be the pointer that
// is becoming fat (we could probably generalize this // is becoming fat (we could probably generalize this

View File

@ -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])`. // 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 // 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. // 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 // We fix this by having this function return the parent's generics ourselves and truncating the

View File

@ -1786,7 +1786,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let bound_predicate = pred.kind(); let bound_predicate = pred.kind();
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {
ty::ClauseKind::Trait(data) => { 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 pred_bound_vars = bound_predicate.bound_vars();
let mut all_bound_vars = bound_vars.clone(); let mut all_bound_vars = bound_vars.clone();
all_bound_vars.extend(pred_bound_vars.iter()); all_bound_vars.extend(pred_bound_vars.iter());

View File

@ -119,7 +119,7 @@ pub fn identify_constrained_generic_params<'tcx>(
/// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate /// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate
/// ///
/// When we, for example, try to go over the trait-reference /// 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 /// variables and match them with the impl trait-ref, so we know that
/// `$U = IntoIter<u32>`. /// `$U = IntoIter<u32>`.
/// ///

View File

@ -424,8 +424,8 @@ pub struct ManualImplementation {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_substs_on_overridden_impl)] #[diag(hir_analysis_generic_args_on_overridden_impl)]
pub struct SubstsOnOverriddenImpl { pub struct GenericArgsOnOverriddenImpl {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }

View File

@ -34,8 +34,8 @@
//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ } //! 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 //! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
//! constrained to be `<I as Iterator>::Item`, so we check only //! `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 //! `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 //! predicates of `impl1` are only `T: Sized`, which is also a predicate of
//! `impl2`. So this specialization is sound. //! `impl2`. So this specialization is sound.
@ -65,7 +65,7 @@
//! cause use after frees with purely safe code in the same way as specializing //! cause use after frees with purely safe code in the same way as specializing
//! on traits with methods can. //! on traits with methods can.
use crate::errors::SubstsOnOverriddenImpl; use crate::errors::GenericArgsOnOverriddenImpl;
use crate::{constrained_generic_params as cgp, errors}; use crate::{constrained_generic_params as cgp, errors};
use rustc_data_structures::fx::FxHashSet; 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 /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
/// substitutions `(S1, S2)` that equate their trait references. The returned /// generic parameters `(S1, S2)` that equate their trait references.
/// types are expressed in terms of the generics of `impl1`. /// The returned types are expressed in terms of the generics of `impl1`.
/// ///
/// Example /// Example
/// ///
@ -228,13 +228,13 @@ fn get_impl_args(
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
let span = tcx.def_span(impl1_def_id); 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); return Err(guar);
}; };
Ok((impl1_args, impl2_args)) 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: /// For example given the impl:
/// ///

View File

@ -229,7 +229,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
/// Here, we should fetch the explicit predicates, which /// Here, we should fetch the explicit predicates, which
/// will give us `U: 'static` and `U: Outer`. The latter we /// will give us `U: 'static` and `U: Outer`. The latter we
/// can ignore, but we will want to process `U: 'static`, /// 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>( fn check_explicit_predicates<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: DefId, def_id: DefId,
@ -316,7 +316,7 @@ fn check_explicit_predicates<'tcx>(
/// Here, when processing the type of field `outer`, we would request the /// Here, when processing the type of field `outer`, we would request the
/// set of implicit predicates computed for `Inner` thus far. This will /// set of implicit predicates computed for `Inner` thus far. This will
/// initially come back empty, but in next round we will get `U: 'b`. /// 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`. /// requirement that `T: 'a` holds for `Outer`.
fn check_inferred_predicates<'tcx>( fn check_inferred_predicates<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
@ -334,7 +334,7 @@ fn check_inferred_predicates<'tcx>(
for (&predicate, &span) in predicates.as_ref().skip_binder() { for (&predicate, &span) in predicates.as_ref().skip_binder() {
// `predicate` is `U: 'b` in the example above. // `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) = let ty::OutlivesPredicate(arg, region) =
predicates.rebind(predicate).instantiate(tcx, args); predicates.rebind(predicate).instantiate(tcx, args);
insert_outlives_predicate(tcx, arg, region, span, required_predicates); insert_outlives_predicate(tcx, arg, region, span, required_predicates);

View File

@ -172,16 +172,16 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
trait_ref: ty::TraitRef { def_id: _, args, .. }, trait_ref: ty::TraitRef { def_id: _, args, .. },
polarity: _, polarity: _,
}) => { }) => {
for subst in &args[1..] { for arg in &args[1..] {
subst.visit_with(&mut collector); arg.visit_with(&mut collector);
} }
} }
ty::ClauseKind::Projection(ty::ProjectionPredicate { ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty: ty::AliasTy { args, .. }, projection_ty: ty::AliasTy { args, .. },
term, term,
}) => { }) => {
for subst in &args[1..] { for arg in &args[1..] {
subst.visit_with(&mut collector); arg.visit_with(&mut collector);
} }
term.visit_with(&mut collector); term.visit_with(&mut collector);
} }

View File

@ -122,7 +122,7 @@ pub(super) fn check_fn<'a, 'tcx>(
if let ty::Dynamic(..) = declared_ret_ty.kind() { if let ty::Dynamic(..) = declared_ret_ty.kind() {
// We have special-cased the case where the function is declared // We have special-cased the case where the function is declared
// `-> dyn Foo` and we don't actually relate it to the // `-> 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 = actual_return_ty =
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }); fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
debug!("actual_return_ty replaced with {:?}", actual_return_ty); debug!("actual_return_ty replaced with {:?}", actual_return_ty);

View File

@ -752,7 +752,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let mut obligations: Vec<_> = predicates let mut obligations: Vec<_> = predicates
.iter() .iter()
.map(|predicate| { .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) // the type of the expression (e.g., `usize` in our example above)
// and then require that the resulting predicate (e.g., `usize: Clone`) // and then require that the resulting predicate (e.g., `usize: Clone`)
// holds (it does). // holds (it does).

View File

@ -1801,7 +1801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// consistency. But they should be merged as much as possible. // consistency. But they should be merged as much as possible.
let fru_tys = if self.tcx.features().type_changing_struct_update { let fru_tys = if self.tcx.features().type_changing_struct_update {
if adt.is_struct() { 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()); let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
// We do subtyping on the FRU fields first, so we can // We do subtyping on the FRU fields first, so we can
// learn exactly what types we expect the base expr // learn exactly what types we expect the base expr

View File

@ -15,7 +15,7 @@ use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_args_for_parent_generic_args, check_generic_arg_count_for_call, create_args_for_parent_generic_args,
}; };
use rustc_hir_analysis::astconv::{ use rustc_hir_analysis::astconv::{
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, AstConv, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, IsMethodCall, PathSeg, GenericArgCountResult, IsMethodCall, PathSeg,
}; };
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
@ -187,8 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
/// Given the args that we just converted from the HIR, try to /// Given the args that we just converted from the HIR, try to
/// canonicalize them and store them as user-given substitutions /// canonicalize them and store them as user-given parameters
/// (i.e., substitutions that must be respected by the NLL check). /// (i.e., parameters that must be respected by the NLL check).
/// ///
/// This should be invoked **before any unifications have /// This should be invoked **before any unifications have
/// occurred**, so that annotations like `Vec<_>` are preserved /// occurred**, so that annotations like `Vec<_>` are preserved
@ -741,7 +741,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Err(TypeError::Mismatch); 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. // produced from the above subtyping unification.
Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect())) Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
}) })
@ -1171,7 +1171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Now we have to compare the types that the user *actually* // Now we have to compare the types that the user *actually*
// provided against the types that were *expected*. If the user // 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 // variables. If the user provided some types, we may still need
// to add defaults. If the user provided *too many* types, that's // to add defaults. If the user provided *too many* types, that's
// a problem. // a problem.
@ -1261,14 +1261,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}, },
}; };
struct CreateCtorSubstsContext<'a, 'tcx> { struct CreateCtorInstantiationsContext<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>, fcx: &'a FnCtxt<'a, 'tcx>,
span: Span, span: Span,
path_segs: &'a [PathSeg], path_segs: &'a [PathSeg],
infer_args_for_err: &'a FxHashSet<usize>, infer_args_for_err: &'a FxHashSet<usize>,
segments: &'tcx [hir::PathSegment<'tcx>], 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( fn args_for_def_id(
&mut self, &mut self,
def_id: DefId, def_id: DefId,
@ -1392,7 +1394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
has_self, has_self,
self_ty.map(|s| s.raw), self_ty.map(|s| s.raw),
&arg_count, &arg_count,
&mut CreateCtorSubstsContext { &mut CreateCtorInstantiationsContext {
fcx: self, fcx: self,
span, span,
path_segs: &path_segs, path_segs: &path_segs,
@ -1410,18 +1412,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.add_required_obligations_for_hir(span, def_id, args, hir_id); 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. // the referenced item.
let ty = tcx.type_of(def_id); let ty = tcx.type_of(def_id);
assert!(!args.has_escaping_bound_vars()); assert!(!args.has_escaping_bound_vars());
assert!(!ty.skip_binder().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 { 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` // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
// is inherent, there is no `Self` parameter; instead, the impl needs // is inherent, there is no `Self` parameter; instead, the impl needs
// type parameters, which we can infer by unifying the provided `Self` // 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. // 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 impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
let self_ty = self.normalize(span, self_ty); let self_ty = self.normalize(span, self_ty);
@ -1442,13 +1444,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); 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( pub(crate) fn add_required_obligations_for_hir(
&self, &self,
span: Span, span: Span,

View File

@ -21,7 +21,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false; return false;
}; };
let Some(unsubstituted_pred) = self let Some(uninstantiated_pred) = self
.tcx .tcx
.predicates_of(def_id) .predicates_of(def_id)
.instantiate_identity(self.tcx) .instantiate_identity(self.tcx)
@ -34,7 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let generics = self.tcx.generics_of(def_id); let generics = self.tcx.generics_of(def_id);
let (predicate_args, predicate_self_type_to_point_at) = 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) => { ty::ClauseKind::Trait(pred) => {
(pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) (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 TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
&& let generics = self.0.tcx.generics_of(self.1) && 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(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) ty::GenericArgs::identity_for_item(self.0.tcx, self.1).get(index as usize)
{ {
ControlFlow::Break(*subst) ControlFlow::Break(*arg)
} else { } else {
ty.super_visit_with(self) ty.super_visit_with(self)
} }

View File

@ -2133,17 +2133,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr_ty: Ty<'tcx>, expr_ty: Ty<'tcx>,
) -> bool { ) -> bool {
let tcx = self.tcx; 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 // 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()) => { ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
let nonzero_type = substs.type_at(0); // Unwrap option type. let nonzero_type = args.type_at(0); // Unwrap option type.
let ty::Adt(adt, substs) = nonzero_type.kind() else { let ty::Adt(adt, args) = nonzero_type.kind() else {
return false; return false;
}; };
(adt, substs, "") (adt, args, "")
} }
// In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types. // 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, _ => return false,
}; };
@ -2165,7 +2165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
("NonZeroI128", tcx.types.i128), ("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)| { 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 } if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None }

View File

@ -7,7 +7,7 @@ use rustc_hir::GenericArg;
use rustc_hir_analysis::astconv::generics::{ use rustc_hir_analysis::astconv::generics::{
check_generic_arg_count_for_call, create_args_for_parent_generic_args, 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_infer::infer::{self, DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; 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. // Adjust the self expression the user provided and obtain the adjusted type.
let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick); 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 rcvr_args = self.fresh_receiver_args(self_ty, pick);
let all_args = self.instantiate_method_args(pick, segment, rcvr_args); let all_args = self.instantiate_method_args(pick, segment, rcvr_args);
@ -246,11 +246,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
target target
} }
/// Returns a set of substitutions for the method *receiver* where all type and region /// Returns a set of generic parameters for the method *receiver* where all type and region
/// parameters are instantiated with fresh variables. This substitution does not include any /// parameters are instantiated with fresh variables. This generic paramters does not include any
/// parameters declared on the method itself. /// 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. /// these are instantiated later in the `instantiate_method_sig` routine.
fn fresh_receiver_args( fn fresh_receiver_args(
&mut self, &mut self,
@ -272,8 +272,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
// The object data has no entry for the Self // The object data has no entry for the Self
// Type. For the purposes of this method call, we // Type. For the purposes of this method call, we
// substitute the object type itself. This // instantiate the object type itself. This
// wouldn't be a sound substitution in all cases, // wouldn't be a sound instantiation in all cases,
// since each instance of the object type is a // since each instance of the object type is a
// different existential and hence could match // different existential and hence could match
// distinct types (e.g., if `Self` appeared as an // distinct types (e.g., if `Self` appeared as an
@ -362,16 +362,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
IsMethodCall::Yes, IsMethodCall::Yes,
); );
// Create subst for early-bound lifetime parameters, combining // Create generic paramters for early-bound lifetime parameters,
// parameters from the type and those from the method. // combining parameters from the type and those from the method.
assert_eq!(generics.parent_count, parent_args.len()); assert_eq!(generics.parent_count, parent_args.len());
struct MethodSubstsCtxt<'a, 'tcx> { struct MethodInstantiationsCtxt<'a, 'tcx> {
cfcx: &'a ConfirmContext<'a, 'tcx>, cfcx: &'a ConfirmContext<'a, 'tcx>,
pick: &'a probe::Pick<'tcx>, pick: &'a probe::Pick<'tcx>,
seg: &'a hir::PathSegment<'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( fn args_for_def_id(
&mut self, &mut self,
def_id: DefId, def_id: DefId,
@ -437,7 +439,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
false, false,
None, None,
&arg_count_correct, &arg_count_correct,
&mut MethodSubstsCtxt { cfcx: self, pick, seg }, &mut MethodInstantiationsCtxt { cfcx: self, pick, seg },
); );
// When the method is confirmed, the `args` includes // 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); debug!("instantiate_method_sig(pick={:?}, all_args={:?})", pick, all_args);
// Instantiate the bounds on the method with the // 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. // be no late-bound regions appearing here.
let def_id = pick.item.def_id; let def_id = pick.item.def_id;
let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_args); 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); 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); let sig = self.instantiate_binder_with_fresh_vars(sig);
debug!("late-bound lifetimes from method instantiated, sig={:?}", sig); debug!("late-bound lifetimes from method instantiated, sig={:?}", sig);

View File

@ -38,7 +38,7 @@ pub struct MethodCallee<'tcx> {
pub args: GenericArgsRef<'tcx>, pub args: GenericArgsRef<'tcx>,
/// Instantiated method signature, i.e., it has been /// 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. /// lifetimes replaced with inference variables.
pub sig: ty::FnSig<'tcx>, pub sig: ty::FnSig<'tcx>,
} }
@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
let mut obligations = vec![]; 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. // parameters into the method type to get the actual method type.
// //
// N.B., instantiate late-bound regions before normalizing the // N.B., instantiate late-bound regions before normalizing the

View File

@ -111,7 +111,7 @@ pub(crate) struct Candidate<'tcx> {
// The way this is handled is through `xform_self_ty`. It contains // The way this is handled is through `xform_self_ty`. It contains
// the receiver type of this candidate, but `xform_self_ty`, // the receiver type of this candidate, but `xform_self_ty`,
// `xform_ret_ty` and `kind` (which contains the predicates) have the // `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". // of inference variables, which acts as some weird sort of "query".
// //
// When we check out a candidate, we require `xform_self_ty` to be // 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 // the `Self` type. An [`ObjectSafetyViolation::SupertraitSelf`] error
// will be reported by `object_safety.rs` if the method refers to the // will be reported by `object_safety.rs` if the method refers to the
// `Self` type anywhere other than the receiver. Here, we use a // `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`. // a `&self` method will wind up with an argument type like `&dyn Trait`.
let trait_ref = principal.with_self_ty(self.tcx, self_ty); let trait_ref = principal.with_self_ty(self.tcx, self_ty);
self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { 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()); assert!(!args.has_escaping_bound_vars());
// It is possible for type parameters or early-bound lifetimes // It is possible for type parameters or early-bound lifetimes
// to appear in the signature of `self`. The substitutions we // to appear in the signature of `self`. The generic parameters
// are given do not include type/lifetime parameters for the // we are given do not include type/lifetime parameters for the
// method yet. So create fresh variables here for those too, // method yet. So create fresh variables here for those too,
// if there are any. // if there are any.
let generics = self.tcx.generics_of(method); 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) 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( fn impl_ty_and_args(
&self, &self,
impl_def_id: DefId, 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 /// 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 /// 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 /// 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. /// so forth.
fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T
where where

View File

@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PlaceOp::Deref => None, PlaceOp::Deref => None,
PlaceOp::Index => { PlaceOp::Index => {
// We would need to recover the `T` used when we resolve `<_ as Index<T>>::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 // 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). // during coercions can cause type of index_expr to differ from `T` (#72002).

View File

@ -1,6 +1,6 @@
// Type resolution: the phase that finds all the types in the AST with // Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their // unresolved type variables and replaces "ty_var" types with their
// substitutions. // generic parameters.
use crate::FnCtxt; use crate::FnCtxt;
use rustc_data_structures::unord::ExtendUnord; use rustc_data_structures::unord::ExtendUnord;
@ -621,7 +621,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
self.write_ty_to_typeck_results(hir_id, n_ty); self.write_ty_to_typeck_results(hir_id, n_ty);
debug!(?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) { if let Some(args) = self.fcx.typeck_results.borrow().node_args_opt(hir_id) {
let args = self.resolve(args, &span); let args = self.resolve(args, &span);
debug!("write_args_to_tcx({:?}, {:?})", hir_id, args); debug!("write_args_to_tcx({:?}, {:?})", hir_id, args);

View File

@ -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>`. //! `Canonical<'tcx, T>`.
//! //!
//! For an overview of what canonicalization is and how it fits into //! 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> { pub trait CanonicalExt<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value /// Instantiate the wrapped value, replacing each canonical value
/// with the value given in `var_values`. /// 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 where
V: TypeFoldable<TyCtxt<'tcx>>; 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 /// `self.value`. Invoke `projection_fn` with `self.value` to get
/// a value V that is expressed in terms of the same canonical /// a value V that is expressed in terms of the same canonical
/// variables bound in `self` (usually this extracts from subset /// 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. /// V, replacing each of the canonical variables.
fn substitute_projected<T>( fn instantiate_projected<T>(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'tcx>, var_values: &CanonicalVarValues<'tcx>,
@ -37,14 +37,14 @@ pub trait CanonicalExt<'tcx, V> {
} }
impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'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 where
V: TypeFoldable<TyCtxt<'tcx>>, 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, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'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()); assert_eq!(self.variables.len(), var_values.len());
let value = projection_fn(&self.value); 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 /// must be values for the set of canonical variables that appear in
/// `value`. /// `value`.
pub(super) fn substitute_value<'tcx, T>( pub(super) fn instantiate_value<'tcx, T>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'tcx>, var_values: &CanonicalVarValues<'tcx>,
value: T, value: T,

View File

@ -30,24 +30,24 @@ use rustc_middle::ty::GenericArg;
use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
pub use instantiate::CanonicalExt;
pub use rustc_middle::infer::canonical::*; pub use rustc_middle::infer::canonical::*;
pub use substitute::CanonicalExt;
mod canonicalizer; mod canonicalizer;
mod instantiate;
pub mod query_response; pub mod query_response;
mod substitute;
impl<'tcx> InferCtxt<'tcx> { 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. /// 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 /// This can be invoked as part of constructing an
/// inference context at the start of a query (see /// inference context at the start of a query (see
/// `InferCtxtBuilder::build_with_canonical`). It basically /// `InferCtxtBuilder::build_with_canonical`). It basically
/// brings the canonical value "into scope" within your new infcx. /// 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 /// canonicalized) then represents the values that you computed
/// for each of the canonical inputs to your query. /// for each of the canonical inputs to your query.
pub fn instantiate_canonical_with_fresh_inference_vars<T>( pub fn instantiate_canonical_with_fresh_inference_vars<T>(
@ -73,14 +73,14 @@ impl<'tcx> InferCtxt<'tcx> {
let canonical_inference_vars = let canonical_inference_vars =
self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]); 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) (result, canonical_inference_vars)
} }
/// Given the "infos" about the canonical variables from some /// Given the "infos" about the canonical variables from some
/// canonical, creates fresh variables with the same /// canonical, creates fresh variables with the same
/// characteristics (see `instantiate_canonical_var` for /// 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. /// canonical variable with these inference variables.
fn instantiate_canonical_vars( fn instantiate_canonical_vars(
&self, &self,

View File

@ -7,7 +7,7 @@
//! //!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html //! [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::{ use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues, Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse, QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
@ -189,18 +189,18 @@ impl<'tcx> InferCtxt<'tcx> {
where where
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{ {
let InferOk { value: result_subst, mut obligations } = let InferOk { value: result_args, mut obligations } =
self.query_response_substitution(cause, param_env, original_values, query_response)?; self.query_response_instantiation(cause, param_env, original_values, query_response)?;
obligations.extend(self.query_outlives_constraints_into_obligations( obligations.extend(self.query_outlives_constraints_into_obligations(
cause, cause,
param_env, param_env,
&query_response.value.region_constraints.outlives, &query_response.value.region_constraints.outlives,
&result_subst, &result_args,
)); ));
let user_result: R = 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 }) Ok(InferOk { value: user_result, obligations })
} }
@ -225,11 +225,11 @@ impl<'tcx> InferCtxt<'tcx> {
/// basic operations as `instantiate_query_response_and_region_obligations` but /// basic operations as `instantiate_query_response_and_region_obligations` but
/// it returns its result differently: /// 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 /// query variables to the values computed in the query
/// result. If any errors arise, they are propagated back as an /// result. If any errors arise, they are propagated back as an
/// `Err` result. /// `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 /// `QueryOutlivesConstraint` values onto the
/// `output_query_region_constraints` vector for the solver to /// `output_query_region_constraints` vector for the solver to
/// use (if an error arises, some values may also be pushed, but /// 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 /// that must be processed. In this case, those subobligations
/// are propagated back in the return value. /// are propagated back in the return value.
/// - Finally, the query result (of type `R`) is propagated back, /// - 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>( pub fn instantiate_nll_query_response_and_region_obligations<R>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
@ -251,8 +251,13 @@ impl<'tcx> InferCtxt<'tcx> {
where where
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{ {
let InferOk { value: result_subst, mut obligations } = self let InferOk { value: result_args, mut obligations } = self
.query_response_substitution_guess(cause, param_env, original_values, query_response)?; .query_response_instantiation_guess(
cause,
param_env,
original_values,
query_response,
)?;
// Compute `QueryOutlivesConstraint` values that unify each of // Compute `QueryOutlivesConstraint` values that unify each of
// the original values `v_o` that was canonicalized into a // 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() { for (index, original_value) in original_values.var_values.iter().enumerate() {
// ...with the value `v_r` of that variable from the query. // ...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)] v.var_values[BoundVar::new(index)]
}); });
match (original_value.unpack(), result_value.unpack()) { 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. // ...also include the other query region constraints from the query.
output_query_region_constraints.outlives.extend( output_query_region_constraints.outlives.extend(
query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| { 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. // Screen out `'a: 'a` cases.
let ty::OutlivesPredicate(k1, r2) = r_c.0; let ty::OutlivesPredicate(k1, r2) = r_c.0;
@ -336,26 +341,26 @@ impl<'tcx> InferCtxt<'tcx> {
.region_constraints .region_constraints
.member_constraints .member_constraints
.iter() .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 = 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 }) Ok(InferOk { value: user_result, obligations })
} }
/// Given the original values and the (canonicalized) result from /// 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 /// to the query result to convert the result back into the
/// original namespace. /// 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 /// that arose from unification; these might occur if (for
/// example) we are doing lazy normalization and the value /// example) we are doing lazy normalization and the value
/// assigned to a type variable is unified with an unnormalized /// assigned to a type variable is unified with an unnormalized
/// projection. /// projection.
fn query_response_substitution<R>( fn query_response_instantiation<R>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
@ -366,11 +371,11 @@ impl<'tcx> InferCtxt<'tcx> {
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{ {
debug!( debug!(
"query_response_substitution(original_values={:#?}, query_response={:#?})", "query_response_instantiation(original_values={:#?}, query_response={:#?})",
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, cause,
param_env, param_env,
original_values, original_values,
@ -378,7 +383,7 @@ impl<'tcx> InferCtxt<'tcx> {
)?; )?;
value.obligations.extend( value.obligations.extend(
self.unify_query_response_substitution_guess( self.unify_query_response_instantiation_guess(
cause, cause,
param_env, param_env,
original_values, original_values,
@ -392,7 +397,7 @@ impl<'tcx> InferCtxt<'tcx> {
} }
/// Given the original values and the (canonicalized) result from /// 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 /// can be applied to the query result to convert the result back
/// into the original namespace. This is called a **guess** /// into the original namespace. This is called a **guess**
/// because it uses a quick heuristic to find the values for each /// 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 /// variable instead. Therefore, the result of this method must be
/// properly unified /// properly unified
#[instrument(level = "debug", skip(self, cause, param_env))] #[instrument(level = "debug", skip(self, cause, param_env))]
fn query_response_substitution_guess<R>( fn query_response_instantiation_guess<R>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
@ -450,7 +455,7 @@ impl<'tcx> InferCtxt<'tcx> {
if let ty::Bound(debruijn, b) = *result_value.kind() { if let ty::Bound(debruijn, b) = *result_value.kind() {
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`. // ...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); assert_eq!(debruijn, ty::INNERMOST);
opt_values[b.var] = Some(*original_value); opt_values[b.var] = Some(*original_value);
} }
@ -460,7 +465,7 @@ impl<'tcx> InferCtxt<'tcx> {
if let ty::ReBound(debruijn, br) = *result_value { if let ty::ReBound(debruijn, br) = *result_value {
// ... in which case we would set `canonical_vars[0]` to `Some('static)`. // ... 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); assert_eq!(debruijn, ty::INNERMOST);
opt_values[br.var] = Some(*original_value); 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() { if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`. // ...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); assert_eq!(debruijn, ty::INNERMOST);
opt_values[b] = Some(*original_value); 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 // given variable in the loop above, use that. Otherwise, use
// a fresh inference variable. // a fresh inference variable.
let result_subst = CanonicalVarValues { let result_args = CanonicalVarValues {
var_values: self.tcx.mk_args_from_iter( var_values: self.tcx.mk_args_from_iter(
query_response.variables.iter().enumerate().map(|(index, info)| { query_response.variables.iter().enumerate().map(|(index, info)| {
if info.universe() != ty::UniverseIndex::ROOT { 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 // Carry all newly resolved opaque types to the caller's scope
for &(a, b) in &query_response.value.opaque_types { for &(a, b) in &query_response.value.opaque_types {
let a = substitute_value(self.tcx, &result_subst, a); let a = instantiate_value(self.tcx, &result_args, a);
let b = substitute_value(self.tcx, &result_subst, b); let b = instantiate_value(self.tcx, &result_args, b);
debug!(?a, ?b, "constrain opaque type"); debug!(?a, ?b, "constrain opaque type");
// We use equate here instead of, for example, just registering the // We use equate here instead of, for example, just registering the
// opaque type's hidden value directly, because we may be instantiating // 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 /// 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 /// query result. Often, but not always, this is a no-op, because
/// we already found the mapping in the "guessing" step. /// we already found the mapping in the "guessing" step.
/// ///
/// See also: `query_response_substitution_guess` /// See also: [`Self::query_response_instantiation_guess`]
fn unify_query_response_substitution_guess<R>( fn unify_query_response_instantiation_guess<R>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>, original_values: &OriginalQueryValues<'tcx>,
result_subst: &CanonicalVarValues<'tcx>, result_args: &CanonicalVarValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, ()> ) -> InferResult<'tcx, ()>
where where
@ -554,15 +559,15 @@ impl<'tcx> InferCtxt<'tcx> {
{ {
// A closure that yields the result value for the given // A closure that yields the result value for the given
// canonical variable; this is taken from // canonical variable; this is taken from
// `query_response.var_values` after applying the substitution // `query_response.var_values` after applying the instantiation
// `result_subst`. // by `result_args`.
let substituted_query_response = |index: BoundVar| -> GenericArg<'tcx> { let instantiated_query_response = |index: BoundVar| -> GenericArg<'tcx> {
query_response.substitute_projected(self.tcx, result_subst, |v| v.var_values[index]) query_response.instantiate_projected(self.tcx, result_args, |v| v.var_values[index])
}; };
// Unify the original value for each variable with the value // Unify the original value for each variable with the value
// taken from `query_response` (after applying `result_subst`). // taken from `query_response` (after applying `result_args`).
self.unify_canonical_vars(cause, param_env, original_values, substituted_query_response) self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response)
} }
/// Converts the region constraints resulting from a query into an /// Converts the region constraints resulting from a query into an
@ -571,11 +576,11 @@ impl<'tcx> InferCtxt<'tcx> {
&'a self, &'a self,
cause: &'a ObligationCause<'tcx>, cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>], uninstantiated_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
result_subst: &'a CanonicalVarValues<'tcx>, result_args: &'a CanonicalVarValues<'tcx>,
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> { ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
unsubstituted_region_constraints.iter().map(move |&constraint| { uninstantiated_region_constraints.iter().map(move |&constraint| {
let predicate = substitute_value(self.tcx, result_subst, constraint); let predicate = instantiate_value(self.tcx, result_args, constraint);
self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env) self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
}) })
} }

View File

@ -679,7 +679,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
/// inference context that contains each of the bound values /// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is /// within instantiated as a fresh variable. The `f` closure is
/// invoked with the new infcx, along with the instantiated value /// 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` /// the bound values in `C` to their instantiated values in `V`
/// (in other words, `S(C) = V`). /// (in other words, `S(C) = V`).
pub fn build_with_canonical<T>( pub fn build_with_canonical<T>(
@ -691,8 +691,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
let infcx = self.build(); let infcx = self.build();
let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
(infcx, value, subst) (infcx, value, args)
} }
pub fn build(&mut self) -> InferCtxt<'tcx> { pub fn build(&mut self) -> InferCtxt<'tcx> {
@ -1194,13 +1194,13 @@ impl<'tcx> InferCtxt<'tcx> {
} }
GenericParamDefKind::Type { .. } => { GenericParamDefKind::Type { .. } => {
// Create a type inference variable for the given // 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 // for actual parameters that may be referred to by
// the default of this type parameter, if it exists. // the default of this type parameter, if it exists.
// e.g., `struct Foo<A, B, C = (A, B)>(...);` when // e.g., `struct Foo<A, B, C = (A, B)>(...);` when
// used in a path such as `Foo::<T, U>::new()` will // used in a path such as `Foo::<T, U>::new()` will
// use an inference variable for `C` with `[T, U]` // 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( let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
self.universe(), self.universe(),
TypeVariableOrigin { TypeVariableOrigin {
@ -1256,7 +1256,7 @@ impl<'tcx> InferCtxt<'tcx> {
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).into() 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. /// type/region parameter to a fresh inference variable.
pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> { 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)) 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>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
if !value.has_infer() { if !value.has_infer() {
return value; // Avoid duplicated subst-folding. return value; // Avoid duplicated type-folding.
} }
let mut r = InferenceLiteralEraser { tcx: self.tcx }; let mut r = InferenceLiteralEraser { tcx: self.tcx };
value.fold_with(&mut r) value.fold_with(&mut r)
@ -1458,7 +1458,7 @@ impl<'tcx> InferCtxt<'tcx> {
// Instantiates the bound variables in a given binder with fresh inference // Instantiates the bound variables in a given binder with fresh inference
// variables in the current universe. // 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`] // 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 // that corresponds to your use case, consider whether or not you should
// use [`InferCtxt::enter_forall`] instead. // use [`InferCtxt::enter_forall`] instead.
@ -1603,10 +1603,10 @@ impl<'tcx> InferCtxt<'tcx> {
/// Resolves and evaluates a constant. /// Resolves and evaluates a constant.
/// ///
/// The constant can be located on a trait like `<A as B>::C`, in which case the given /// 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 /// generic parameters 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 /// 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 /// 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 /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
/// returned. /// returned.
/// ///
@ -1652,7 +1652,7 @@ impl<'tcx> InferCtxt<'tcx> {
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, args: args_erased }; 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 // 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) tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
} }

View File

@ -219,7 +219,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// ``` /// ```
/// ///
/// As indicating in the comments above, each of those references /// 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 /// applied to the type of a suitable `def_id` (which identifies
/// `Foo1` or `Foo2`). /// `Foo1` or `Foo2`).
/// ///

View File

@ -25,7 +25,7 @@ use crate::infer::region_constraints::VerifyIfEq;
/// * `None` if `some_type` cannot be made equal to `test_ty`, /// * `None` if `some_type` cannot be made equal to `test_ty`,
/// no matter the values of the variables in `exists`. /// no matter the values of the variables in `exists`.
/// * `Some(r)` with a suitable bound (typically the value of `bound_region`, modulo /// * `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. /// type under test.
/// ///
/// NB: This function uses a simplistic, syntactic version of type equality. /// NB: This function uses a simplistic, syntactic version of type equality.
@ -59,7 +59,7 @@ pub fn extract_verify_if_eq<'tcx>(
} }
} else { } else {
// The region does not contain any bound variables, so we don't need // The region does not contain any bound variables, so we don't need
// to do any substitution. // to do any instantiation.
// //
// Example: // Example:
// //

View File

@ -277,7 +277,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
/// ``` /// ```
/// ///
/// If we were given the `DefId` of `Foo::Bar`, we would return /// 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 /// projection to convert this into your namespace. This also
/// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on /// 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 /// the trait. In fact, it works by searching for just such a

View File

@ -183,14 +183,14 @@ where
fn relate_item_args( fn relate_item_args(
&mut self, &mut self,
item_def_id: DefId, item_def_id: DefId,
a_subst: ty::GenericArgsRef<'tcx>, a_arg: ty::GenericArgsRef<'tcx>,
b_subst: ty::GenericArgsRef<'tcx>, b_arg: ty::GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> { ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
if self.ambient_variance == ty::Variance::Invariant { if self.ambient_variance == ty::Variance::Invariant {
// Avoid fetching the variance if we are in an invariant // Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles // context; no need, and it can induce dependency cycles
// (e.g., #41849). // (e.g., #41849).
relate::relate_args_invariantly(self, a_subst, b_subst) relate::relate_args_invariantly(self, a_arg, b_arg)
} else { } else {
let tcx = self.tcx(); let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id); let opt_variances = tcx.variances_of(item_def_id);
@ -198,8 +198,8 @@ where
self, self,
item_def_id, item_def_id,
opt_variances, opt_variances,
a_subst, a_arg,
b_subst, b_arg,
false, false,
) )
} }

View File

@ -118,7 +118,7 @@ pub enum TypeVariableOriginKind {
AdjustmentType, AdjustmentType,
/// In type check, when we are type checking a function that /// 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. /// return type for diagnostic purposes.
DynReturnFn, DynReturnFn,
LatticeVariable, LatticeVariable,

View File

@ -285,7 +285,8 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
let obligations = let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause( 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, span,
bound_clause.rebind(data), bound_clause.rebind(data),
index, index,

View File

@ -53,7 +53,7 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
/// A set of values corresponding to the canonical variables from some /// A set of values corresponding to the canonical variables from some
/// `Canonical`. You can give these values to /// `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. /// value at the right places.
/// ///
/// When you canonicalize a value `V`, you get back one of these /// When you canonicalize a value `V`, you get back one of these

View File

@ -11,13 +11,13 @@ use rustc_session::lint;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
impl<'tcx> TyCtxt<'tcx> { 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 /// 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. /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> { 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 // 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 substitutions // 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 // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered. // encountered.
let args = GenericArgs::identity_for_item(self, def_id); let args = GenericArgs::identity_for_item(self, def_id);
@ -29,10 +29,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// Resolves and evaluates a constant. /// Resolves and evaluates a constant.
/// ///
/// The constant can be located on a trait like `<A as B>::C`, in which case the given /// 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 /// generic parameters 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 /// 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 /// 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 /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
/// returned. /// returned.
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -214,13 +214,13 @@ impl<'tcx> TyCtxtAt<'tcx> {
} }
impl<'tcx> TyCtxtEnsure<'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 /// 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. /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub fn const_eval_poly(self, def_id: DefId) { pub fn const_eval_poly(self, def_id: DefId) {
// In some situations def_id will have substitutions within scope, but they aren't allowed // 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 substitutions // 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 // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered. // encountered.
let args = GenericArgs::identity_for_item(self.tcx, def_id); let args = GenericArgs::identity_for_item(self.tcx, def_id);

View File

@ -186,7 +186,7 @@ impl<'tcx> MonoItem<'tcx> {
MonoItem::GlobalAsm(..) => return true, 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> { pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {

View File

@ -2078,9 +2078,9 @@ rustc_queries! {
desc { "normalizing `{:?}`", goal.value.value.value } 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| desc { |tcx|
"checking impossible substituted predicates: `{}`", "checking impossible instantiated predicates: `{}`",
tcx.def_path_str(key.0) tcx.def_path_str(key.0)
} }
} }

View File

@ -721,7 +721,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
} }
/// Identifies a particular impl in the source, along with a set of /// 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 /// `nested` vector corresponds to the nested obligations attached to
/// the impl's type parameters. /// the impl's type parameters.
/// ///

View File

@ -49,7 +49,8 @@ pub type EvaluationCache<'tcx> = Cache<
/// parameters don't unify with regular types, but they *can* unify /// parameters don't unify with regular types, but they *can* unify
/// with variables from blanket impls, and (unless we know its bounds /// with variables from blanket impls, and (unless we know its bounds
/// will always be satisfied) picking the blanket impl will be wrong /// 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 /// ```rust, ignore
/// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; } /// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; }

View File

@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
let super_predicates = let super_predicates =
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|&(pred, _)| { |&(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) self.visited.insert(clause).then_some(clause)
}, },
); );

View File

@ -3,7 +3,7 @@ use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
use crate::ty::{self, InferConst, Ty, TyCtxt}; use crate::ty::{self, InferConst, Ty, TyCtxt};
/// A type "A" *matches* "B" if the fresh types in B could be /// 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 /// intended to be used only on freshened types, and it basically
/// indicates if the non-freshened versions of A and B could have been /// indicates if the non-freshened versions of A and B could have been
/// unified. /// unified.

View File

@ -235,7 +235,7 @@ impl<'tcx> Const<'tcx> {
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics` // 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 // 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 // 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 { match expr.kind {
hir::ExprKind::Path(hir::QPath::Resolved( hir::ExprKind::Path(hir::QPath::Resolved(
_, _,

View File

@ -418,10 +418,10 @@ impl<'tcx> TyCtxt<'tcx> {
// Shifter // Shifter
// //
// Shifts the De Bruijn indices on all escaping bound vars by a // 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 // a binding level that is not intended to capture the existing bound
// vars. See comment on `shift_vars_through_binders` method in // 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> { struct Shifter<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@ -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> { struct ArgFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
args: &'a [GenericArg<'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, binders_passed: u32,
} }
@ -834,7 +834,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
#[inline(never)] #[inline(never)]
fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! { fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! {
bug!( 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.name,
data.index, data.index,
args, args,
@ -845,7 +845,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
#[inline(never)] #[inline(never)]
fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! { fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! {
bug!( bug!(
"Unexpected parameter {:?} when substituting in region {} (index={})", "Unexpected parameter {:?} when instantiating in region {} (index={})",
other, other,
data.name, data.name,
data.index 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 // Note: This routine only handles regions that are bound on
// type declarations and other outer declarations, not those // 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 // regions that appear in a function signature is done using
// the specialized routine `ty::replace_late_regions()`. // the specialized routine `ty::replace_late_regions()`.
match *r { match *r {
@ -913,7 +913,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
#[inline(never)] #[inline(never)]
fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! { fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! {
bug!( bug!(
"expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, args={:?}", "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}",
p, p,
ty, ty,
p.index, p.index,
@ -926,7 +926,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
#[inline(never)] #[inline(never)]
fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! { fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! {
bug!( bug!(
"type parameter `{:?}` ({:?}/{}) out of range when substituting, args={:?}", "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}",
p, p,
ty, ty,
p.index, p.index,
@ -955,7 +955,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
kind: GenericArgKind<'tcx>, kind: GenericArgKind<'tcx>,
) -> ! { ) -> ! {
bug!( bug!(
"expected const for `{:?}` ({:?}/{}) but found {:?} when substituting args={:?}", "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}",
p, p,
ct, ct,
p.index, p.index,
@ -968,7 +968,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
#[inline(never)] #[inline(never)]
fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! { fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! {
bug!( bug!(
"const parameter `{:?}` ({:?}/{}) out of range when substituting args={:?}", "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
p, p,
ct, ct,
p.index, 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 /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs
/// when we are substituting a type with escaping bound vars into a context where we have /// 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: /// 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 /// 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 /// 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 /// 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. /// depth by 1 to account for the binder that we passed through.
/// ///
/// As a second example, consider this twist: /// As a second example, consider this twist:
@ -1015,7 +1015,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
/// // DebruijnIndex of 1 | /// // DebruijnIndex of 1 |
/// // DebruijnIndex of 2 /// // 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 /// 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. /// 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 { fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T {

View File

@ -125,7 +125,7 @@ pub struct GenericParamCount {
/// Information about the formal type/lifetime parameters associated /// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to `hir::Generics`. /// 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... /// `Self` (optionally), `Lifetime` params..., `Type` params...
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct Generics { pub struct Generics {
@ -140,7 +140,7 @@ pub struct Generics {
pub has_self: bool, pub has_self: bool,
pub has_late_bound_regions: Option<Span>, 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>, pub host_effect_index: Option<usize>,
} }

View File

@ -19,7 +19,7 @@ use std::fmt;
/// ///
/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type /// 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 /// 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 /// Note: the `Lift` impl is currently not used by rustc, but is used by
/// rustc_codegen_cranelift when the `jit` feature is enabled. /// rustc_codegen_cranelift when the `jit` feature is enabled.
@ -138,7 +138,7 @@ pub enum InstanceDef<'tcx> {
} }
impl<'tcx> Instance<'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. /// 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> { pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id()); 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 /// 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`). /// `Instance::args_for_mir_body`).
/// ///
/// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR /// 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 { pub fn has_polymorphic_mir_body(&self) -> bool {
match *self { match *self {
InstanceDef::CloneShim(..) InstanceDef::CloneShim(..)
@ -669,13 +669,13 @@ impl<'tcx> Instance<'tcx> {
/// Depending on the kind of `InstanceDef`, the MIR body associated with an /// 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 /// 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. /// cases the MIR body is expressed in terms of the types found in the generic parameter array.
/// In the former case, we want to substitute those generic types and replace them with the /// 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 /// 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 `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. /// codegen.
fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> { fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
self.def.has_polymorphic_mir_body().then_some(self.args) self.def.has_polymorphic_mir_body().then_some(self.args)

View File

@ -728,7 +728,7 @@ impl From<ty::ConstVid> for TermVid {
/// the `GenericPredicates` are expressed in terms of the bound type /// the `GenericPredicates` are expressed in terms of the bound type
/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
/// represented a set of bounds for some particular instantiation, /// 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. /// their values.
/// ///
/// Example: /// Example:
@ -1672,7 +1672,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")] #[instrument(skip(self), level = "debug")]
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
match instance { match instance {

View File

@ -135,7 +135,7 @@ impl<'tcx> TyCtxt<'tcx> {
} }
/// Monomorphizes a type from the AST by first applying the /// 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. /// types.
/// Panics if normalization fails. In case normalization might fail /// Panics if normalization fails. In case normalization might fail
/// use `try_instantiate_and_normalize_erasing_regions` instead. /// use `try_instantiate_and_normalize_erasing_regions` instead.
@ -149,12 +149,12 @@ impl<'tcx> TyCtxt<'tcx> {
where where
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
let substituted = value.instantiate(self, param_args); let instantiated = value.instantiate(self, param_args);
self.normalize_erasing_regions(param_env, substituted) self.normalize_erasing_regions(param_env, instantiated)
} }
/// Monomorphizes a type from the AST by first applying the /// 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 /// types. Contrary to `instantiate_and_normalize_erasing_regions` this does
/// not assume that normalization succeeds. /// not assume that normalization succeeds.
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -167,8 +167,8 @@ impl<'tcx> TyCtxt<'tcx> {
where where
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
let substituted = value.instantiate(self, param_args); let instantiated = value.instantiate(self, param_args);
self.try_normalize_erasing_regions(param_env, substituted) self.try_normalize_erasing_regions(param_env, instantiated)
} }
} }

View File

@ -164,9 +164,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
} }
ty::Param(param) => { 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()) { 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. // opaque type.
Some(GenericArgKind::Type(t1)) => t1, Some(GenericArgKind::Type(t1)) => t1,
Some(u) => panic!("type mapped to unexpected kind: {u:?}"), 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 // Find a const parameter
match ct.kind() { match ct.kind() {
ty::ConstKind::Param(..) => { 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()) { 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. // opaque type.
Some(GenericArgKind::Const(c1)) => c1, Some(GenericArgKind::Const(c1)) => c1,
Some(u) => panic!("const mapped to unexpected kind: {u:?}"), Some(u) => panic!("const mapped to unexpected kind: {u:?}"),

View File

@ -323,7 +323,7 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
/// and `U` as parameter 1. /// and `U` as parameter 1.
/// ///
/// Trait references also appear in object types like `Foo<U>`, but in /// 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(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitRef<'tcx> { pub struct TraitRef<'tcx> {
@ -406,7 +406,7 @@ impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
/// ```ignore (illustrative) /// ```ignore (illustrative)
/// exists T. T: Trait<'a, 'b, X, Y> /// 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). /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
@ -481,8 +481,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
/// reference. /// reference.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
let def_id = tcx.parent(self.def_id); let def_id = tcx.parent(self.def_id);
let subst_count = tcx.generics_of(def_id).count() - 1; let args_count = tcx.generics_of(def_id).count() - 1;
let args = tcx.mk_args(&self.args[..subst_count]); let args = tcx.mk_args(&self.args[..args_count]);
ty::ExistentialTraitRef { def_id, args } ty::ExistentialTraitRef { def_id, args }
} }
@ -534,12 +534,12 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
} }
impl<'tcx> Clause<'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 to supertraits that must hold if that
/// poly-trait-ref holds. This is slightly different from a normal /// 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. /// lengthy comment below for details.
pub fn subst_supertrait( pub fn instantiate_supertrait(
self, self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'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 // 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 // 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 // `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 // 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>` // 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` // - 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>`, // 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. // 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). // `'a => 'x` (where `'x` has a DB index of 1).
// - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an // - 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 // 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>` // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
// just as we wanted. // just as we wanted.
// //
// There is only one catch. If we just apply the substitution `'a // There is only one catch. If we just apply the instantiation `'a
// => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will // => 'x` to `for<'b> Bar1<'a,'b>`, the instantiation code will
// adjust the DB index because we substituting into a binder (it // adjust the DB index because we instantiating into a binder (it
// tries to be so smart...) resulting in `for<'x> for<'b> // tries to be so smart...) resulting in `for<'x> for<'b>
// Bar1<'x,'b>` (we have no syntax for this, so use your // Bar1<'x,'b>` (we have no syntax for this, so use your
// imagination). Basically the 'x will have DB index of 2 and 'b // 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 // 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 // rather than the trait reference itself (put another way, the
// substitution code expects equal binding levels in the values // instantiation code expects equal binding levels in the values
// from the substitution and the value being substituted into, and // from the instantiation and the value being instantiated into, and
// this trick achieves that). // this trick achieves that).
// Working through the second example: // Working through the second example:

View File

@ -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>] { pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
self.split().parent_args 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>] { pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
self.split().parent_args self.split().parent_args
} }
@ -819,7 +819,7 @@ impl<'tcx> UpvarArgs<'tcx> {
/// inherited from the item that defined the inline const, /// inherited from the item that defined the inline const,
/// - R represents the type of the constant. /// - 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 /// 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: /// 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. /// 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>] { pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
self.split().parent_args self.split().parent_args
} }
@ -1105,13 +1105,13 @@ where
pub struct AliasTy<'tcx> { pub struct AliasTy<'tcx> {
/// The parameters of the associated or opaque item. /// The parameters of the associated or opaque item.
/// ///
/// For a projection, these are the substitutions for the trait and the /// For a projection, these are the generic parameters for the trait and the
/// GAT substitutions, if there are any. /// 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. /// 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. /// while for TAIT it is used for the generic parameters of the alias.
pub args: GenericArgsRef<'tcx>, pub args: GenericArgsRef<'tcx>,
@ -1235,15 +1235,15 @@ impl<'tcx> AliasTy<'tcx> {
/// The following methods work only with inherent associated type projections. /// The following methods work only with inherent associated type projections.
impl<'tcx> AliasTy<'tcx> { 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: /// Does the following transformation:
/// ///
/// ```text /// ```text
/// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m] /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
/// ///
/// I_i impl subst /// I_i impl args
/// P_j GAT subst /// P_j GAT args
/// ``` /// ```
pub fn rebase_inherent_args_onto_impl( pub fn rebase_inherent_args_onto_impl(
self, self,
@ -1690,7 +1690,7 @@ impl<'tcx> Ty<'tcx> {
debug_assert_eq!( debug_assert_eq!(
closure_args.len(), closure_args.len(),
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, 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)) Ty::new(tcx, Closure(def_id, closure_args))
} }
@ -1704,7 +1704,7 @@ impl<'tcx> Ty<'tcx> {
debug_assert_eq!( debug_assert_eq!(
closure_args.len(), closure_args.len(),
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, 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)) Ty::new(tcx, CoroutineClosure(def_id, closure_args))
} }
@ -1718,7 +1718,7 @@ impl<'tcx> Ty<'tcx> {
debug_assert_eq!( debug_assert_eq!(
coroutine_args.len(), coroutine_args.len(),
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6, 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)) 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, /// 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 /// things like ADTs and trait objects, sice even if their arguments or
/// nested types may be further simplified, the outermost [`TyKind`] or /// nested types may be further simplified, the outermost [`TyKind`] or
/// type constructor remains the same. /// type constructor remains the same.

View File

@ -55,19 +55,19 @@ pub struct TypeckResults<'tcx> {
/// typeck::check::fn_ctxt for details. /// typeck::check::fn_ctxt for details.
node_types: ItemLocalMap<Ty<'tcx>>, 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 /// of this node. This only applies to nodes that refer to entities
/// parameterized by type parameters, such as generic fns, types, or /// parameterized by type parameters, such as generic fns, types, or
/// other items. /// other items.
node_args: ItemLocalMap<GenericArgsRef<'tcx>>, node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
/// This will either store the canonicalized types provided by the user /// 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 /// to `id`. These will not include any inferred values. The canonical form
/// is used to capture things like `_` or other unspecified values. /// is used to capture things like `_` or other unspecified values.
/// ///
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the /// 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. /// See also `AscribeUserType` statement in MIR.
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>, user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
@ -348,7 +348,7 @@ impl<'tcx> TypeckResults<'tcx> {
} }
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function /// 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 /// [`expr_ty`]: TypeckResults::expr_ty
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> { pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
@ -360,9 +360,9 @@ impl<'tcx> TypeckResults<'tcx> {
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in /// 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 /// some cases, we insert `Adjustment` annotations such as auto-deref or
/// auto-ref. The type returned by this function does not consider such /// 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` /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
/// instead of `fn(ty) -> T with T = isize`. /// instead of `fn(ty) -> T with T = isize`.
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> { pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
@ -627,7 +627,7 @@ pub enum UserType<'tcx> {
Ty(Ty<'tcx>), Ty(Ty<'tcx>),
/// The canonical type is the result of `type_of(def_id)` with the /// The canonical type is the result of `type_of(def_id)` with the
/// given substitutions applied. /// given generic parameters applied.
TypeOf(DefId, UserArgs<'tcx>), TypeOf(DefId, UserArgs<'tcx>),
} }
@ -636,7 +636,7 @@ pub trait IsIdentity {
} }
impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { 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. /// i.e., each thing is mapped to a canonical variable with the same index.
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool {
match self.value { match self.value {
@ -650,7 +650,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
match kind.unpack() { match kind.unpack() {
GenericArgKind::Type(ty) => match ty.kind() { GenericArgKind::Type(ty) => match ty.kind() {
ty::Bound(debruijn, b) => { 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); assert_eq!(*debruijn, ty::INNERMOST);
cvar == b.var cvar == b.var
} }
@ -659,7 +659,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
GenericArgKind::Lifetime(r) => match *r { GenericArgKind::Lifetime(r) => match *r {
ty::ReBound(debruijn, br) => { 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); assert_eq!(debruijn, ty::INNERMOST);
cvar == br.var cvar == br.var
} }
@ -668,7 +668,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
GenericArgKind::Const(ct) => match ct.kind() { GenericArgKind::Const(ct) => match ct.kind() {
ty::ConstKind::Bound(debruijn, b) => { 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); assert_eq!(debruijn, ty::INNERMOST);
cvar == b cvar == b
} }

View File

@ -811,7 +811,7 @@ impl<'tcx> Cx<'tcx> {
let user_provided_type = match res { let user_provided_type = match res {
// A reference to something callable -- e.g., a fn, method, or // A reference to something callable -- e.g., a fn, method, or
// a tuple-struct or tuple-variant. This has the type of a // 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::Fn, _)
| Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocFn, _)
| Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
@ -822,7 +822,7 @@ impl<'tcx> Cx<'tcx> {
// A unit struct/variant which is used as a value (e.g., // A unit struct/variant which is used as a value (e.g.,
// `None`). This has the type of the enum/struct that defines // `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. // user.
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => { Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new) self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new)

View File

@ -7,7 +7,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
fn typeck_results(&self) -> &ty::TypeckResults<'tcx>; fn typeck_results(&self) -> &ty::TypeckResults<'tcx>;
/// Looks up the type associated with this hir-id and applies the /// 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. /// type.
fn user_args_applied_to_ty_of_hir_id( fn user_args_applied_to_ty_of_hir_id(
&self, &self,

View File

@ -36,10 +36,10 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b
ty::Tuple(tys) => { ty::Tuple(tys) => {
depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx)) depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx))
} }
ty::Adt(adt, subst) => { ty::Adt(adt, args) => {
depth == 0 depth == 0
|| adt.variants().iter().any(|v| { || 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 // Conservative fallback

View File

@ -205,8 +205,8 @@ pub fn deduced_param_attrs<'tcx>(
|(arg_index, local_decl)| DeducedParamAttrs { |(arg_index, local_decl)| DeducedParamAttrs {
read_only: !deduce_read_only.mutable_args.contains(arg_index) read_only: !deduce_read_only.mutable_args.contains(arg_index)
// We must normalize here to reveal opaques and normalize // We must normalize here to reveal opaques and normalize
// their substs, otherwise we'll see exponential blow-up in // their generic parameters, otherwise we'll see exponential
// compile times: #113372 // blow-up in compile times: #113372
&& tcx && tcx
.normalize_erasing_regions(param_env, local_decl.ty) .normalize_erasing_regions(param_env, local_decl.ty)
.is_freeze(tcx, param_env), .is_freeze(tcx, param_env),

View File

@ -63,7 +63,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
/// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the /// 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( fn check_bound_args(
&self, &self,
def_id: DefId, def_id: DefId,
@ -83,11 +83,11 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) { for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
// If the inner type matches the type bound by `Pointer` // If the inner type matches the type bound by `Pointer`
if inner_ty == bound_ty { if inner_ty == bound_ty {
// Do a substitution using the parameters from the callsite // Do an instantiation using the parameters from the callsite
let subst_ty = let instantiated_ty =
EarlyBinder::bind(inner_ty).instantiate(self.tcx, args_ref); EarlyBinder::bind(inner_ty).instantiate(self.tcx, args_ref);
if let Some((fn_id, fn_args)) = 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); let mut span = self.nth_arg_span(args, arg_num);
if span.from_expansion() { if span.from_expansion() {

View File

@ -853,10 +853,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> { fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
if let Value::Aggregate(enum_ty, variant, _) = *self.get(place) 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 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()?; let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?;
return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty)); 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()); assert!(!fields.is_empty());
(AggregateTy::Tuple, FIRST_VARIANT) (AggregateTy::Tuple, FIRST_VARIANT)
} }
AggregateKind::Closure(did, substs) AggregateKind::Closure(did, args)
| AggregateKind::CoroutineClosure(did, substs) | AggregateKind::CoroutineClosure(did, args)
| AggregateKind::Coroutine(did, substs) => { | AggregateKind::Coroutine(did, args) => (AggregateTy::Def(did, args), FIRST_VARIANT),
(AggregateTy::Def(did, substs), FIRST_VARIANT) AggregateKind::Adt(did, variant_index, args, _, None) => {
} (AggregateTy::Def(did, args), variant_index)
AggregateKind::Adt(did, variant_index, substs, _, None) => {
(AggregateTy::Def(did, substs), variant_index)
} }
// Do not track unions. // Do not track unions.
AggregateKind::Adt(_, _, _, _, Some(_)) => return None, AggregateKind::Adt(_, _, _, _, Some(_)) => return None,

View File

@ -80,7 +80,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
} }
// These have no own callable MIR. // These have no own callable MIR.
InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => continue, 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 // again, a function item can end up getting inlined. Thus we'll be able to cause
// a cycle that way // a cycle that way
InstanceDef::VTableShim(_) 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. // This shim does not call any other functions, thus there can be no recursion.
InstanceDef::FnPtrAddrShim(..) => continue, InstanceDef::FnPtrAddrShim(..) => continue,
InstanceDef::DropGlue(..) => { 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 // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
// needs some more analysis. // needs some more analysis.
if callee.has_param() { if callee.has_param() {

View File

@ -208,7 +208,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
// Only bother looking more if it's easy to know what we're calling // 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 }; 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 { if fn_args.len() != 1 {
return; return;
} }

View File

@ -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 // We manually filter the predicates, skipping anything that's not
// "global". We are in a potentially generic context // "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: // parameters, so this filtering serves two purposes:
// //
// 1. We skip evaluating any predicates that we would // 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, &inline::Inline,
// Code from other crates may have storage markers, so this needs to happen after inlining. // Code from other crates may have storage markers, so this needs to happen after inlining.
&remove_storage_markers::RemoveStorageMarkers, &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_zsts::RemoveZsts,
&remove_unneeded_drops::RemoveUnneededDrops, &remove_unneeded_drops::RemoveUnneededDrops,
// Type substitution may create uninhabited enums. // Type instantiation may create uninhabited enums.
&uninhabited_enum_branching::UninhabitedEnumBranching, &uninhabited_enum_branching::UninhabitedEnumBranching,
&unreachable_prop::UnreachablePropagation, &unreachable_prop::UnreachablePropagation,
&o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching), &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 /// 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<'_>> { fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
if tcx.is_constructor(def.to_def_id()) { if tcx.is_constructor(def.to_def_id()) {
return tcx.arena.alloc(IndexVec::new()); return tcx.arena.alloc(IndexVec::new());

View File

@ -44,7 +44,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
/// ///
/// # Liveness /// # 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: /// 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 /// - 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; /// 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: /// 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`. /// 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`. /// we replace either all or none of the occurrences of `*_1`.
/// ///
/// Some care has to be taken when `_1` is copied in other locals. /// Some care has to be taken when `_1` is copied in other locals.
@ -63,10 +63,10 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
/// _3 = *_1; /// _3 = *_1;
/// _4 = _1 /// _4 = _1
/// _5 = *_4 /// _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, /// 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; pub struct ReferencePropagation;
impl<'tcx> MirPass<'tcx> for ReferencePropagation { impl<'tcx> MirPass<'tcx> for ReferencePropagation {

View File

@ -477,7 +477,7 @@ struct CloneShimBuilder<'tcx> {
impl<'tcx> CloneShimBuilder<'tcx> { impl<'tcx> CloneShimBuilder<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self { 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 // otherwise going to be TySelf and we can't index
// or access fields of a Place of type TySelf. // or access fields of a Place of type TySelf.
let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]); 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>, call_kind: CallKind<'tcx>,
) -> Body<'tcx> { ) -> Body<'tcx> {
// `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used // `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 // to instantiate 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`). // 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_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx)); let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));

View File

@ -170,7 +170,7 @@ impl SsaLocals {
/// _c => _a /// _c => _a
/// _d => _a // transitively through _c /// _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> { pub fn copy_classes(&self) -> &IndexSlice<Local, Local> {
&self.copy_classes &self.copy_classes
} }

View File

@ -62,7 +62,7 @@
//! syntactic items in the source code. We find them by walking the HIR of the //! 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, //! 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 //! 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 //! collection mode, during incremental compilation, all non-generic functions
//! are considered as roots, as well as when the `-Clink-dead-code` option is //! are considered as roots, as well as when the `-Clink-dead-code` option is
//! specified. Functions marked `#[no_mangle]` and functions called by inlinable //! 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 // 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). // 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 // 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 // be trivially false. We must now check that the impl has no impossible-to-satisfy
// predicates. // 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; 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 // 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 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); let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args);

View File

@ -90,7 +90,7 @@ fn should_polymorphize<'tcx>(
def_id: DefId, def_id: DefId,
instance: ty::InstanceDef<'tcx>, instance: ty::InstanceDef<'tcx>,
) -> bool { ) -> 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. // derived from polymorphization's result won't make any difference.
if !instance.has_polymorphic_mir_body() { if !instance.has_polymorphic_mir_body() {
return false; return false;

View File

@ -263,11 +263,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
for &(variant, field) in indices { for &(variant, field) in indices {
match current_ty.kind() { match current_ty.kind() {
ty::Adt(def, subst) => { ty::Adt(def, args) => {
let field = &def.variant(variant).fields[field]; let field = &def.variant(variant).fields[field];
self.insert_def_id(field.did); 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); current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
} }

View File

@ -173,7 +173,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
variant.fields.iter().enumerate().filter_map(move |(i, field)| { variant.fields.iter().enumerate().filter_map(move |(i, field)| {
let ty = field.ty(cx.tcx, args); 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 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_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
let is_uninhabited = (cx.tcx.features().exhaustive_patterns let is_uninhabited = (cx.tcx.features().exhaustive_patterns

View File

@ -133,7 +133,7 @@ where
if V::SHALLOW { if V::SHALLOW {
ControlFlow::Continue(()) ControlFlow::Continue(())
} else { } 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 // Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `Type::Alias` // conservatively approximate associated types like `Type::Alias`
// as visible/reachable even if `Type` is private. // 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. // free type aliases, but this isn't done yet.
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
@ -230,7 +230,7 @@ where
} else if kind == ty::Projection { } else if kind == ty::Projection {
self.visit_projection_ty(data) self.visit_projection_ty(data)
} else { } 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, ..) => { ty::Dynamic(predicates, ..) => {

View File

@ -369,7 +369,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut(); let mut tables = self.0.borrow_mut();
let instance = tables.instances[def]; 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) instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables)
} }

View File

@ -99,7 +99,7 @@ fn get_symbol_hash<'tcx>(
instance: Instance<'tcx>, instance: Instance<'tcx>,
// type of the item, without any generic // type of the item, without any generic
// parameters substituted; this is // parameters instantiated; this is
// included in the hash as a kind of // included in the hash as a kind of
// safeguard. // safeguard.
item_type: Ty<'tcx>, item_type: Ty<'tcx>,

View File

@ -251,8 +251,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
None => "M", None => "M",
}); });
// Encode impl generic params if the substitutions contain parameters (implying // Encode impl generic params if the generic parameters contain non-region parameters
// polymorphization is enabled) and this isn't an inherent impl. // (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()) { if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
self.path_generic_args( self.path_generic_args(
|this| { |this| {

View File

@ -576,7 +576,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
assert_eq!( assert_eq!(
old_ty, old_ty,
None, None,
"{} has two substitutions: {} and {}", "{} has two generic parameters: {} and {}",
proj.projection_ty, proj.projection_ty,
proj.term, proj.term,
old_ty.unwrap() old_ty.unwrap()

View File

@ -192,11 +192,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
original_values: Vec<ty::GenericArg<'tcx>>, original_values: Vec<ty::GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>, response: CanonicalResponse<'tcx>,
) -> Result<(Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> { ) -> Result<(Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
let substitution = let instantiation = Self::compute_query_response_instantiation_values(
Self::compute_query_response_substitution(self.infcx, &original_values, &response); self.infcx,
&original_values,
&response,
);
let Response { var_values, external_constraints, certainty } = let Response { var_values, external_constraints, certainty } =
response.substitute(self.tcx(), &substitution); response.instantiate(self.tcx(), &instantiation);
let nested_goals = let nested_goals =
Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values)?; 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)) 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 /// the canonical response. This depends on the `original_values` for the
/// bound variables. /// bound variables.
fn compute_query_response_substitution<T: ResponseT<'tcx>>( fn compute_query_response_instantiation_values<T: ResponseT<'tcx>>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
original_values: &[ty::GenericArg<'tcx>], original_values: &[ty::GenericArg<'tcx>],
response: &Canonical<'tcx, T>, response: &Canonical<'tcx, T>,
@ -369,10 +372,10 @@ impl<'tcx> inspect::ProofTreeBuilder<'tcx> {
original_values: &[ty::GenericArg<'tcx>], original_values: &[ty::GenericArg<'tcx>],
state: inspect::CanonicalState<'tcx, T>, state: inspect::CanonicalState<'tcx, T>,
) -> Result<(Vec<Goal<'tcx, ty::Predicate<'tcx>>>, T), NoSolution> { ) -> Result<(Vec<Goal<'tcx, ty::Predicate<'tcx>>>, T), NoSolution> {
let substitution = let instantiation =
EvalCtxt::compute_query_response_substitution(infcx, original_values, &state); 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 = let nested_goals =
EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values)?; EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values)?;

View File

@ -312,8 +312,8 @@ fn rematch_unsize<'tcx>(
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
// Substitute just the unsizing params from B into A. The type after // Instantiate 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 // this instantiation must be equal to B. This is so we don't unsize
// unrelated type parameters. // unrelated type parameters.
let new_a_args = tcx.mk_args_from_iter( let new_a_args = tcx.mk_args_from_iter(
a_args a_args
@ -349,7 +349,7 @@ fn rematch_unsize<'tcx>(
let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
let b_last_ty = b_tys.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 = let unsized_a_ty =
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied()); Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied());
nested.extend( nested.extend(

View File

@ -1,7 +1,7 @@
//! Computes a normalizes-to (projection) goal for inherent associated types, //! Computes a normalizes-to (projection) goal for inherent associated types,
//! `#![feature(inherent_associated_type)]`. Since astconv already determines //! `#![feature(inherent_associated_type)]`. Since astconv already determines
//! which impl the IAT is being projected from, we just: //! which impl the IAT is being projected from, we just:
//! 1. instantiate substs, //! 1. instantiate generic parameters,
//! 2. equate the self type, and //! 2. equate the self type, and
//! 3. instantiate and register where clauses. //! 3. instantiate and register where clauses.
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult}; 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 expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
let impl_def_id = tcx.parent(inherent.def_id); 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 // Equate impl header and add impl where clauses
self.eq( self.eq(
goal.param_env, goal.param_env,
inherent.self_ty(), 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 // 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( self.eq(
goal.param_env, goal.param_env,
expected, 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"); .expect("expected goal term to be fully unconstrained");
@ -46,7 +46,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
self.add_goals( self.add_goals(
GoalSource::Misc, GoalSource::Misc,
tcx.predicates_of(inherent.def_id) tcx.predicates_of(inherent.def_id)
.instantiate(tcx, inherent_substs) .instantiate(tcx, inherent_args)
.into_iter() .into_iter()
.map(|(pred, _)| goal.with(tcx, pred)), .map(|(pred, _)| goal.with(tcx, pred)),
); );

View File

@ -877,8 +877,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
// Substitute just the unsizing params from B into A. The type after // Instantiate 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 // this instantiation must be equal to B. This is so we don't unsize
// unrelated type parameters. // unrelated type parameters.
let new_a_args = tcx.mk_args_from_iter( let new_a_args = tcx.mk_args_from_iter(
a_args a_args
@ -927,7 +927,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
let &b_last_ty = b_tys.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 = let unsized_a_ty =
Ty::new_tup_from_iter(tcx, a_rest_tys.iter().copied().chain([b_last_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)?; self.eq(goal.param_env, unsized_a_ty, b_ty)?;

View File

@ -84,7 +84,7 @@ impl TrackAmbiguityCauses {
/// If there are types that satisfy both impls, returns `Some` /// If there are types that satisfy both impls, returns `Some`
/// with a suitably-freshened `ImplHeader` with those types /// with a suitably-freshened `ImplHeader` with those types
/// substituted. Otherwise, returns `None`. /// instantiated. Otherwise, returns `None`.
#[instrument(skip(tcx, skip_leak_check), level = "debug")] #[instrument(skip(tcx, skip_leak_check), level = "debug")]
pub fn overlapping_impls( pub fn overlapping_impls(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
@ -561,21 +561,21 @@ pub fn trait_ref_is_knowable<'tcx, E: Debug>(
) -> Result<Result<(), Conflict>, E> { ) -> Result<Result<(), Conflict>, E> {
if orphan_check_trait_ref(trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() { 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 // 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)); return Ok(Err(Conflict::Downstream));
} }
if trait_ref_is_local_or_fundamental(tcx, trait_ref) { if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
// This is a local or fundamental trait, so future-compatibility // This is a local or fundamental trait, so future-compatibility
// is no concern. We know that downstream/cousin crates are not // is no concern. We know that downstream/cousin crates are not
// allowed to implement a substitution of this trait ref, which // allowed to implement a generic parameter of this trait ref,
// means impls could only come from dependencies of this crate, // which means impls could only come from dependencies of this
// which we already know about. // crate, which we already know about.
return Ok(Ok(())); return Ok(Ok(()));
} }
// This is a remote non-fundamental trait, so if another crate // 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. // they are allowed to implement it future-compatibly.
// //
// However, if we are a final owner, then nobody else can be, // 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: /// 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, /// 1. Order the parameters in the trait-ref in generic parameters order
/// others linearly (e.g., `<U as Foo<V, W>>` is U < V < W). /// - 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 /// 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 /// 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 /// 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 /// Because we never perform negative reasoning generically (coherence does
/// not involve type parameters), this can be interpreted as doing the full /// 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. /// types for all inference variables.
/// ///
/// This allows for crates to future-compatibly add impls as long as they /// This allows for crates to future-compatibly add impls as long as they

View File

@ -242,7 +242,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
self.tcx.lang_items().fn_once_trait(), self.tcx.lang_items().fn_once_trait(),
] { ] {
let Some(trait_def_id) = trait_def_id else { continue }; 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. // of the trait are.
let var = self.next_ty_var(TypeVariableOrigin { let var = self.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP, span: DUMMY_SP,

View File

@ -814,7 +814,7 @@ impl<'tcx> OnUnimplementedFormatString {
tcx.dcx(), tcx.dcx(),
self.span, self.span,
E0231, E0231,
"only named substitution parameters are allowed" "only named generic parameters are allowed"
) )
.emit(); .emit();
result = Err(reported); result = Err(reported);

Some files were not shown because too many files have changed in this diff Show More