mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
commit
cb0d74be28
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -696,9 +696,10 @@ 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
|
||||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
.instantiate_from_current_frame_and_normalize_erasing_regions(
|
||||||
)?;
|
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||||
|
)?;
|
||||||
if !mir_assign_valid_types(
|
if !mir_assign_valid_types(
|
||||||
*self.tcx,
|
*self.tcx,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
@ -731,8 +732,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
&Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?,
|
&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
|
||||||
|
@ -542,9 +542,10 @@ 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
|
||||||
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
.instantiate_from_current_frame_and_normalize_erasing_regions(
|
||||||
)?;
|
mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
|
||||||
|
)?;
|
||||||
if !mir_assign_valid_types(
|
if !mir_assign_valid_types(
|
||||||
*self.tcx,
|
*self.tcx,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
|
@ -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)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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| {
|
||||||
|
@ -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.
|
||||||
|
@ -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()
|
||||||
};
|
};
|
||||||
|
@ -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()),
|
||||||
|
@ -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(()),
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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).
|
||||||
|
|
||||||
|
@ -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).
|
||||||
//
|
//
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
|
@ -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>`.
|
||||||
///
|
///
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
///
|
///
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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).
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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).
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
@ -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,
|
||||||
|
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`).
|
||||||
///
|
///
|
||||||
|
@ -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:
|
||||||
//
|
//
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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> {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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; }
|
||||||
|
@ -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)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -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.
|
||||||
|
@ -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(
|
||||||
_,
|
_,
|
||||||
|
@ -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>,
|
||||||
|
@ -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 {
|
||||||
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:?}"),
|
||||||
|
@ -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:
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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),
|
||||||
|
@ -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() {
|
||||||
|
@ -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,
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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, ..) => {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>,
|
||||||
|
@ -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| {
|
||||||
|
@ -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()
|
||||||
|
@ -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)?;
|
||||||
|
@ -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(
|
||||||
|
@ -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)),
|
||||||
);
|
);
|
||||||
|
@ -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)?;
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user