mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #99600 - tmiasko:subst-folder, r=petrochenkov
Tweak `SubstFolder` implementation
This commit is contained in:
commit
2f320a224e
@ -1122,6 +1122,7 @@ impl<'tcx> TypeVisitable<'tcx> for ty::Predicate<'tcx> {
|
|||||||
visitor.visit_predicate(*self)
|
visitor.visit_predicate(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
|
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||||
self.outer_exclusive_binder() > binder
|
self.outer_exclusive_binder() > binder
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ use rustc_data_structures::intern::{Interned, WithStableHash};
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_serialize::{self, Decodable, Encodable};
|
use rustc_serialize::{self, Decodable, Encodable};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use core::intrinsics;
|
use core::intrinsics;
|
||||||
@ -525,6 +524,7 @@ struct SubstFolder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||||
|
#[inline]
|
||||||
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
@ -540,6 +540,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||||
|
#[cold]
|
||||||
|
#[inline(never)]
|
||||||
|
fn region_param_out_of_range(data: ty::EarlyBoundRegion) -> ! {
|
||||||
|
bug!(
|
||||||
|
"Region parameter out of range when substituting in region {} (index={})",
|
||||||
|
data.name,
|
||||||
|
data.index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// 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 substitution of the bound
|
||||||
@ -550,14 +560,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
|||||||
let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
|
let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
|
||||||
match rk {
|
match rk {
|
||||||
Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
|
Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
|
||||||
_ => {
|
_ => region_param_out_of_range(data),
|
||||||
let msg = format!(
|
|
||||||
"Region parameter out of range \
|
|
||||||
when substituting in region {} (index={})",
|
|
||||||
data.name, data.index
|
|
||||||
);
|
|
||||||
span_bug!(DUMMY_SP, "{}", msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => r,
|
_ => r,
|
||||||
@ -595,67 +598,80 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
|||||||
let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack());
|
let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack());
|
||||||
let ty = match opt_ty {
|
let ty = match opt_ty {
|
||||||
Some(GenericArgKind::Type(ty)) => ty,
|
Some(GenericArgKind::Type(ty)) => ty,
|
||||||
Some(kind) => {
|
Some(kind) => self.type_param_expected(p, source_ty, kind),
|
||||||
span_bug!(
|
None => self.type_param_out_of_range(p, source_ty),
|
||||||
DUMMY_SP,
|
|
||||||
"expected type for `{:?}` ({:?}/{}) but found {:?} \
|
|
||||||
when substituting, substs={:?}",
|
|
||||||
p,
|
|
||||||
source_ty,
|
|
||||||
p.index,
|
|
||||||
kind,
|
|
||||||
self.substs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
span_bug!(
|
|
||||||
DUMMY_SP,
|
|
||||||
"type parameter `{:?}` ({:?}/{}) out of range \
|
|
||||||
when substituting, substs={:?}",
|
|
||||||
p,
|
|
||||||
source_ty,
|
|
||||||
p.index,
|
|
||||||
self.substs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.shift_vars_through_binders(ty)
|
self.shift_vars_through_binders(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
#[inline(never)]
|
||||||
|
fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! {
|
||||||
|
bug!(
|
||||||
|
"expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, substs={:?}",
|
||||||
|
p,
|
||||||
|
ty,
|
||||||
|
p.index,
|
||||||
|
kind,
|
||||||
|
self.substs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
#[inline(never)]
|
||||||
|
fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! {
|
||||||
|
bug!(
|
||||||
|
"type parameter `{:?}` ({:?}/{}) out of range when substituting, substs={:?}",
|
||||||
|
p,
|
||||||
|
ty,
|
||||||
|
p.index,
|
||||||
|
self.substs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
// Look up the const in the substitutions. It really should be in there.
|
// Look up the const in the substitutions. It really should be in there.
|
||||||
let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack());
|
let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack());
|
||||||
let ct = match opt_ct {
|
let ct = match opt_ct {
|
||||||
Some(GenericArgKind::Const(ct)) => ct,
|
Some(GenericArgKind::Const(ct)) => ct,
|
||||||
Some(kind) => {
|
Some(kind) => self.const_param_expected(p, source_ct, kind),
|
||||||
span_bug!(
|
None => self.const_param_out_of_range(p, source_ct),
|
||||||
DUMMY_SP,
|
|
||||||
"expected const for `{:?}` ({:?}/{}) but found {:?} \
|
|
||||||
when substituting substs={:?}",
|
|
||||||
p,
|
|
||||||
source_ct,
|
|
||||||
p.index,
|
|
||||||
kind,
|
|
||||||
self.substs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
span_bug!(
|
|
||||||
DUMMY_SP,
|
|
||||||
"const parameter `{:?}` ({:?}/{}) out of range \
|
|
||||||
when substituting substs={:?}",
|
|
||||||
p,
|
|
||||||
source_ct,
|
|
||||||
p.index,
|
|
||||||
self.substs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.shift_vars_through_binders(ct)
|
self.shift_vars_through_binders(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
#[inline(never)]
|
||||||
|
fn const_param_expected(
|
||||||
|
&self,
|
||||||
|
p: ty::ParamConst,
|
||||||
|
ct: ty::Const<'tcx>,
|
||||||
|
kind: GenericArgKind<'tcx>,
|
||||||
|
) -> ! {
|
||||||
|
bug!(
|
||||||
|
"expected const for `{:?}` ({:?}/{}) but found {:?} when substituting substs={:?}",
|
||||||
|
p,
|
||||||
|
ct,
|
||||||
|
p.index,
|
||||||
|
kind,
|
||||||
|
self.substs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
#[inline(never)]
|
||||||
|
fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! {
|
||||||
|
bug!(
|
||||||
|
"const parameter `{:?}` ({:?}/{}) out of range when substituting substs={:?}",
|
||||||
|
p,
|
||||||
|
ct,
|
||||||
|
p.index,
|
||||||
|
self.substs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// 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 substitution. This occurs
|
||||||
/// when we are substituting a type with escaping bound vars into a context where we have
|
/// when we are substituting 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:
|
||||||
|
@ -310,6 +310,7 @@ impl DebruijnIndex {
|
|||||||
/// for<'a> fn(for<'b> fn(&'a x))
|
/// for<'a> fn(for<'b> fn(&'a x))
|
||||||
///
|
///
|
||||||
/// you would need to shift the index for `'a` into a new binder.
|
/// you would need to shift the index for `'a` into a new binder.
|
||||||
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
|
pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
|
||||||
DebruijnIndex::from_u32(self.as_u32() + amount)
|
DebruijnIndex::from_u32(self.as_u32() + amount)
|
||||||
@ -317,18 +318,21 @@ impl DebruijnIndex {
|
|||||||
|
|
||||||
/// Update this index in place by shifting it "in" through
|
/// Update this index in place by shifting it "in" through
|
||||||
/// `amount` number of binders.
|
/// `amount` number of binders.
|
||||||
|
#[inline]
|
||||||
pub fn shift_in(&mut self, amount: u32) {
|
pub fn shift_in(&mut self, amount: u32) {
|
||||||
*self = self.shifted_in(amount);
|
*self = self.shifted_in(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the resulting index when this value is moved out from
|
/// Returns the resulting index when this value is moved out from
|
||||||
/// `amount` number of new binders.
|
/// `amount` number of new binders.
|
||||||
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
|
pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
|
||||||
DebruijnIndex::from_u32(self.as_u32() - amount)
|
DebruijnIndex::from_u32(self.as_u32() - amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update in place by shifting out from `amount` binders.
|
/// Update in place by shifting out from `amount` binders.
|
||||||
|
#[inline]
|
||||||
pub fn shift_out(&mut self, amount: u32) {
|
pub fn shift_out(&mut self, amount: u32) {
|
||||||
*self = self.shifted_out(amount);
|
*self = self.shifted_out(amount);
|
||||||
}
|
}
|
||||||
@ -353,6 +357,7 @@ impl DebruijnIndex {
|
|||||||
/// If we invoke `shift_out_to_binder` and the region is in fact
|
/// If we invoke `shift_out_to_binder` and the region is in fact
|
||||||
/// bound by one of the binders we are shifting out of, that is an
|
/// bound by one of the binders we are shifting out of, that is an
|
||||||
/// error (and should fail an assertion failure).
|
/// error (and should fail an assertion failure).
|
||||||
|
#[inline]
|
||||||
pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
|
pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
|
||||||
self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
|
self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user