mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 13:54:06 +00:00
Auto merge of #80106 - jackh726:binder-refactor-part-2, r=lcnr
A lot of refactoring to remove more `Binder::bind`s Split out from #76814
This commit is contained in:
commit
8bb302d34d
@ -525,10 +525,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||||||
result_subst: &'a CanonicalVarValues<'tcx>,
|
result_subst: &'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| {
|
unsubstituted_region_constraints.iter().map(move |&constraint| {
|
||||||
let ty::OutlivesPredicate(k1, r2) =
|
let predicate = substitute_value(self.tcx, result_subst, constraint);
|
||||||
substitute_value(self.tcx, result_subst, constraint).skip_binder();
|
let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder();
|
||||||
|
|
||||||
let predicate = match k1.unpack() {
|
let atom = match k1.unpack() {
|
||||||
GenericArgKind::Lifetime(r1) => {
|
GenericArgKind::Lifetime(r1) => {
|
||||||
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
|
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
|
||||||
}
|
}
|
||||||
@ -540,8 +540,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||||||
// encounter this branch.
|
// encounter this branch.
|
||||||
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
|
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
.potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
|
let predicate =
|
||||||
|
predicate.rebind(atom).potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
|
||||||
|
|
||||||
Obligation::new(cause.clone(), param_env, predicate)
|
Obligation::new(cause.clone(), param_env, predicate)
|
||||||
})
|
})
|
||||||
|
@ -551,7 +551,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
where
|
where
|
||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
|
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relate_item_substs(
|
fn relate_item_substs(
|
||||||
@ -833,7 +833,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
|||||||
where
|
where
|
||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
|
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||||
|
@ -1008,6 +1008,6 @@ where
|
|||||||
self.first_free_index.shift_in(1);
|
self.first_free_index.shift_in(1);
|
||||||
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
||||||
self.first_free_index.shift_out(1);
|
self.first_free_index.shift_out(1);
|
||||||
Ok(ty::Binder::bind(result))
|
Ok(a.rebind(result))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,6 @@ impl TypeRelation<'tcx> for Match<'tcx> {
|
|||||||
where
|
where
|
||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
|
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,7 @@ pub struct ResolvedOpaqueTy<'tcx> {
|
|||||||
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
||||||
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
||||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||||
|
#[derive(TypeFoldable)]
|
||||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||||
/// Type of the captured binding.
|
/// Type of the captured binding.
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
@ -423,7 +424,7 @@ pub struct TypeckResults<'tcx> {
|
|||||||
|
|
||||||
/// Stores the type, expression, span and optional scope span of all types
|
/// Stores the type, expression, span and optional scope span of all types
|
||||||
/// that are live across the yield of this generator (if a generator).
|
/// that are live across the yield of this generator (if a generator).
|
||||||
pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
|
pub generator_interior_types: ty::Binder<Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||||
|
|
||||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
/// as `&[u8]`, depending on the pattern in which they are used.
|
||||||
@ -455,7 +456,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||||||
concrete_opaque_types: Default::default(),
|
concrete_opaque_types: Default::default(),
|
||||||
closure_captures: Default::default(),
|
closure_captures: Default::default(),
|
||||||
closure_min_captures: Default::default(),
|
closure_min_captures: Default::default(),
|
||||||
generator_interior_types: Default::default(),
|
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||||
treat_byte_string_as_slice: Default::default(),
|
treat_byte_string_as_slice: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1149,17 +1149,16 @@ pub enum PredicateAtom<'tcx> {
|
|||||||
TypeWellFormedFromEnv(Ty<'tcx>),
|
TypeWellFormedFromEnv(Ty<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PredicateAtom<'tcx> {
|
impl<'tcx> Binder<PredicateAtom<'tcx>> {
|
||||||
/// Wraps `self` with the given qualifier if this predicate has any unbound variables.
|
/// Wraps `self` with the given qualifier if this predicate has any unbound variables.
|
||||||
pub fn potentially_quantified(
|
pub fn potentially_quantified(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
qualifier: impl FnOnce(Binder<PredicateAtom<'tcx>>) -> PredicateKind<'tcx>,
|
qualifier: impl FnOnce(Binder<PredicateAtom<'tcx>>) -> PredicateKind<'tcx>,
|
||||||
) -> Predicate<'tcx> {
|
) -> Predicate<'tcx> {
|
||||||
if self.has_escaping_bound_vars() {
|
match self.no_bound_vars() {
|
||||||
qualifier(Binder::bind(self))
|
Some(atom) => PredicateKind::Atom(atom),
|
||||||
} else {
|
None => qualifier(self),
|
||||||
PredicateKind::Atom(self)
|
|
||||||
}
|
}
|
||||||
.to_predicate(tcx)
|
.to_predicate(tcx)
|
||||||
}
|
}
|
||||||
@ -1252,7 +1251,11 @@ impl<'tcx> Predicate<'tcx> {
|
|||||||
let substs = trait_ref.skip_binder().substs;
|
let substs = trait_ref.skip_binder().substs;
|
||||||
let pred = self.skip_binders();
|
let pred = self.skip_binders();
|
||||||
let new = pred.subst(tcx, substs);
|
let new = pred.subst(tcx, substs);
|
||||||
if new != pred { new.potentially_quantified(tcx, PredicateKind::ForAll) } else { self }
|
if new != pred {
|
||||||
|
ty::Binder::bind(new).potentially_quantified(tcx, PredicateKind::ForAll)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1279,6 +1282,10 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
|||||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||||
self.skip_binder().def_id()
|
self.skip_binder().def_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn self_ty(self) -> ty::Binder<Ty<'tcx>> {
|
||||||
|
self.map_bound(|trait_ref| trait_ref.self_ty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||||
@ -1403,37 +1410,39 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
|
|||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
|
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
PredicateAtom::Trait(self.value.skip_binder(), self.constness)
|
self.value
|
||||||
|
.map_bound(|value| PredicateAtom::Trait(value, self.constness))
|
||||||
.potentially_quantified(tcx, PredicateKind::ForAll)
|
.potentially_quantified(tcx, PredicateKind::ForAll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
PredicateAtom::RegionOutlives(self.skip_binder())
|
self.map_bound(|value| PredicateAtom::RegionOutlives(value))
|
||||||
.potentially_quantified(tcx, PredicateKind::ForAll)
|
.potentially_quantified(tcx, PredicateKind::ForAll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
PredicateAtom::TypeOutlives(self.skip_binder())
|
self.map_bound(|value| PredicateAtom::TypeOutlives(value))
|
||||||
.potentially_quantified(tcx, PredicateKind::ForAll)
|
.potentially_quantified(tcx, PredicateKind::ForAll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
PredicateAtom::Projection(self.skip_binder())
|
self.map_bound(|value| PredicateAtom::Projection(value))
|
||||||
.potentially_quantified(tcx, PredicateKind::ForAll)
|
.potentially_quantified(tcx, PredicateKind::ForAll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Predicate<'tcx> {
|
impl<'tcx> Predicate<'tcx> {
|
||||||
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
|
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
|
||||||
match self.skip_binders() {
|
let predicate = self.bound_atom();
|
||||||
|
match predicate.skip_binder() {
|
||||||
PredicateAtom::Trait(t, constness) => {
|
PredicateAtom::Trait(t, constness) => {
|
||||||
Some(ConstnessAnd { constness, value: ty::Binder::bind(t.trait_ref) })
|
Some(ConstnessAnd { constness, value: predicate.rebind(t.trait_ref) })
|
||||||
}
|
}
|
||||||
PredicateAtom::Projection(..)
|
PredicateAtom::Projection(..)
|
||||||
| PredicateAtom::Subtype(..)
|
| PredicateAtom::Subtype(..)
|
||||||
@ -1449,8 +1458,9 @@ impl<'tcx> Predicate<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
|
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
|
||||||
match self.skip_binders() {
|
let predicate = self.bound_atom();
|
||||||
PredicateAtom::TypeOutlives(data) => Some(ty::Binder::bind(data)),
|
match predicate.skip_binder() {
|
||||||
|
PredicateAtom::TypeOutlives(data) => Some(predicate.rebind(data)),
|
||||||
PredicateAtom::Trait(..)
|
PredicateAtom::Trait(..)
|
||||||
| PredicateAtom::Projection(..)
|
| PredicateAtom::Projection(..)
|
||||||
| PredicateAtom::Subtype(..)
|
| PredicateAtom::Subtype(..)
|
||||||
|
@ -1151,9 +1151,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
) -> DiagnosticBuilder<'tcx> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
crate fn build_fn_sig_string<'tcx>(
|
crate fn build_fn_sig_string<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let inputs = trait_ref.substs.type_at(1);
|
let inputs = trait_ref.skip_binder().substs.type_at(1);
|
||||||
let sig = if let ty::Tuple(inputs) = inputs.kind() {
|
let sig = if let ty::Tuple(inputs) = inputs.kind() {
|
||||||
tcx.mk_fn_sig(
|
tcx.mk_fn_sig(
|
||||||
inputs.iter().map(|k| k.expect_ty()),
|
inputs.iter().map(|k| k.expect_ty()),
|
||||||
@ -1171,7 +1171,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
abi::Abi::Rust,
|
abi::Abi::Rust,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
ty::Binder::bind(sig).to_string()
|
trait_ref.rebind(sig).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
|
let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
|
||||||
@ -1183,17 +1183,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
if argument_is_closure { "closure" } else { "function" }
|
if argument_is_closure { "closure" } else { "function" }
|
||||||
);
|
);
|
||||||
|
|
||||||
let found_str = format!(
|
let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found));
|
||||||
"expected signature of `{}`",
|
|
||||||
build_fn_sig_string(self.tcx, found.skip_binder())
|
|
||||||
);
|
|
||||||
err.span_label(span, found_str);
|
err.span_label(span, found_str);
|
||||||
|
|
||||||
let found_span = found_span.unwrap_or(span);
|
let found_span = found_span.unwrap_or(span);
|
||||||
let expected_str = format!(
|
let expected_str =
|
||||||
"found signature of `{}`",
|
format!("found signature of `{}`", build_fn_sig_string(self.tcx, expected_ref));
|
||||||
build_fn_sig_string(self.tcx, expected_ref.skip_binder())
|
|
||||||
);
|
|
||||||
err.span_label(found_span, expected_str);
|
err.span_label(found_span, expected_str);
|
||||||
|
|
||||||
err
|
err
|
||||||
@ -1422,7 +1417,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
// generator frame. Bound regions are preserved by
|
// generator frame. Bound regions are preserved by
|
||||||
// `erase_regions` and so we must also call
|
// `erase_regions` and so we must also call
|
||||||
// `erase_late_bound_regions`.
|
// `erase_late_bound_regions`.
|
||||||
let ty_erased = self.tcx.erase_late_bound_regions(ty::Binder::bind(ty));
|
let ty_erased = self.tcx.erase_late_bound_regions(ty);
|
||||||
let ty_erased = self.tcx.erase_regions(ty_erased);
|
let ty_erased = self.tcx.erase_regions(ty_erased);
|
||||||
let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
|
let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
|
||||||
debug!(
|
debug!(
|
||||||
@ -1440,7 +1435,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
|
interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
|
||||||
let upvar_ty = typeck_results.node_type(*upvar_id);
|
let upvar_ty = typeck_results.node_type(*upvar_id);
|
||||||
let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
|
let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
|
||||||
if ty_matches(&upvar_ty) {
|
if ty_matches(ty::Binder::dummy(upvar_ty)) {
|
||||||
Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
|
Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -1448,10 +1443,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(cause) = typeck_results
|
// The generator interior types share the same binders
|
||||||
.generator_interior_types
|
if let Some(cause) =
|
||||||
.iter()
|
typeck_results.generator_interior_types.as_ref().skip_binder().iter().find(
|
||||||
.find(|ty::GeneratorInteriorTypeCause { ty, .. }| ty_matches(ty))
|
|ty::GeneratorInteriorTypeCause { ty, .. }| {
|
||||||
|
ty_matches(typeck_results.generator_interior_types.rebind(ty))
|
||||||
|
},
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Check to see if any awaited expressions have the target type.
|
// Check to see if any awaited expressions have the target type.
|
||||||
let from_awaited_ty = visitor
|
let from_awaited_ty = visitor
|
||||||
@ -1464,7 +1462,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
"maybe_note_obligation_cause_for_async_await: await_expr={:?}",
|
"maybe_note_obligation_cause_for_async_await: await_expr={:?}",
|
||||||
await_expr
|
await_expr
|
||||||
);
|
);
|
||||||
ty_matches(ty)
|
ty_matches(ty::Binder::dummy(ty))
|
||||||
})
|
})
|
||||||
.map(|expr| expr.span);
|
.map(|expr| expr.span);
|
||||||
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
|
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
|
||||||
|
@ -418,11 +418,11 @@ fn virtual_call_violation_for_method<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i, &input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
|
for (i, &input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
|
||||||
if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
|
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) {
|
||||||
return Some(MethodViolationCode::ReferencesSelfInput(i));
|
return Some(MethodViolationCode::ReferencesSelfInput(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
|
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
|
||||||
return Some(MethodViolationCode::ReferencesSelfOutput);
|
return Some(MethodViolationCode::ReferencesSelfOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +951,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||||||
|
|
||||||
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||||
let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
|
let poly_trait_ref = ty::Binder::dummy(*obligation_trait_ref);
|
||||||
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
|
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
|
||||||
let _ = selcx.infcx().commit_if_ok(|_| {
|
let _ = selcx.infcx().commit_if_ok(|_| {
|
||||||
let impl_source = match selcx.select(&trait_obligation) {
|
let impl_source = match selcx.select(&trait_obligation) {
|
||||||
@ -1247,7 +1247,9 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
|
|||||||
ty: self_ty.discriminant_ty(tcx),
|
ty: self_ty.discriminant_ty(tcx),
|
||||||
};
|
};
|
||||||
|
|
||||||
confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false)
|
// We get here from `poly_project_and_unify_type` which replaces bound vars
|
||||||
|
// with placeholders, so dummy is okay here.
|
||||||
|
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
||||||
|
@ -259,10 +259,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
|
) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
|
||||||
debug!(?obligation, ?trait_def_id, "confirm_auto_impl_candidate");
|
debug!(?obligation, ?trait_def_id, "confirm_auto_impl_candidate");
|
||||||
|
|
||||||
let types = obligation.predicate.map_bound(|inner| {
|
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
|
||||||
let self_ty = self.infcx.shallow_resolve(inner.self_ty());
|
let types = self.constituent_types_for_ty(self_ty);
|
||||||
self.constituent_types_for_ty(self_ty)
|
|
||||||
});
|
|
||||||
self.vtable_auto_impl(obligation, trait_def_id, types)
|
self.vtable_auto_impl(obligation, trait_def_id, types)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1276,7 +1276,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
// FIXME(generic_associated_types): Compare the whole projections
|
// FIXME(generic_associated_types): Compare the whole projections
|
||||||
let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx()));
|
let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx()));
|
||||||
let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
|
let obligation_poly_trait_ref = ty::Binder::dummy(*obligation_trait_ref);
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
||||||
@ -1648,8 +1648,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
||||||
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
|
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
|
||||||
/// ```
|
/// ```
|
||||||
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
|
fn constituent_types_for_ty(&self, t: ty::Binder<Ty<'tcx>>) -> ty::Binder<Vec<Ty<'tcx>>> {
|
||||||
match *t.kind() {
|
match *t.skip_binder().kind() {
|
||||||
ty::Uint(_)
|
ty::Uint(_)
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
| ty::Bool
|
| ty::Bool
|
||||||
@ -1660,7 +1660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
| ty::Error(_)
|
| ty::Error(_)
|
||||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Char => Vec::new(),
|
| ty::Char => ty::Binder::dummy(Vec::new()),
|
||||||
|
|
||||||
ty::Placeholder(..)
|
ty::Placeholder(..)
|
||||||
| ty::Dynamic(..)
|
| ty::Dynamic(..)
|
||||||
@ -1673,44 +1673,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
|
ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
|
||||||
vec![element_ty]
|
t.rebind(vec![element_ty])
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty],
|
ty::Array(element_ty, _) | ty::Slice(element_ty) => t.rebind(vec![element_ty]),
|
||||||
|
|
||||||
ty::Tuple(ref tys) => {
|
ty::Tuple(ref tys) => {
|
||||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||||
tys.iter().map(|k| k.expect_ty()).collect()
|
t.rebind(tys.iter().map(|k| k.expect_ty()).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Closure(_, ref substs) => {
|
ty::Closure(_, ref substs) => {
|
||||||
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
|
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
|
||||||
vec![ty]
|
t.rebind(vec![ty])
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Generator(_, ref substs, _) => {
|
ty::Generator(_, ref substs, _) => {
|
||||||
let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
|
let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
|
||||||
let witness = substs.as_generator().witness();
|
let witness = substs.as_generator().witness();
|
||||||
vec![ty].into_iter().chain(iter::once(witness)).collect()
|
t.rebind(vec![ty].into_iter().chain(iter::once(witness)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::GeneratorWitness(types) => {
|
ty::GeneratorWitness(types) => {
|
||||||
// This is sound because no regions in the witness can refer to
|
debug_assert!(!types.has_escaping_bound_vars());
|
||||||
// the binder outside the witness. So we'll effectivly reuse
|
types.map_bound(|types| types.to_vec())
|
||||||
// the implicit binder around the witness.
|
|
||||||
types.skip_binder().to_vec()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For `PhantomData<T>`, we pass `T`.
|
// For `PhantomData<T>`, we pass `T`.
|
||||||
ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
|
ty::Adt(def, substs) if def.is_phantom_data() => t.rebind(substs.types().collect()),
|
||||||
|
|
||||||
ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
|
ty::Adt(def, substs) => {
|
||||||
|
t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
|
||||||
|
}
|
||||||
|
|
||||||
ty::Opaque(def_id, substs) => {
|
ty::Opaque(def_id, substs) => {
|
||||||
// We can resolve the `impl Trait` to its concrete type,
|
// We can resolve the `impl Trait` to its concrete type,
|
||||||
// which enforces a DAG between the functions requiring
|
// which enforces a DAG between the functions requiring
|
||||||
// the auto trait bounds in question.
|
// the auto trait bounds in question.
|
||||||
vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]
|
t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1738,10 +1738,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
|
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
|
||||||
|
|
||||||
types
|
types
|
||||||
|
.as_ref()
|
||||||
.skip_binder() // binder moved -\
|
.skip_binder() // binder moved -\
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|ty| {
|
.flat_map(|ty| {
|
||||||
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
|
let ty: ty::Binder<Ty<'tcx>> = types.rebind(ty); // <----/
|
||||||
|
|
||||||
self.infcx.commit_unconditionally(|_| {
|
self.infcx.commit_unconditionally(|_| {
|
||||||
let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty);
|
let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty);
|
||||||
|
@ -6,7 +6,7 @@ use smallvec::SmallVec;
|
|||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
|
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
|
||||||
|
|
||||||
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
||||||
pub use rustc_infer::traits::util::*;
|
pub use rustc_infer::traits::util::*;
|
||||||
@ -333,11 +333,12 @@ pub fn closure_trait_ref_and_return_type(
|
|||||||
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
|
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
|
||||||
TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
|
TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
|
||||||
};
|
};
|
||||||
|
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||||
let trait_ref = ty::TraitRef {
|
let trait_ref = ty::TraitRef {
|
||||||
def_id: fn_trait_def_id,
|
def_id: fn_trait_def_id,
|
||||||
substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
|
substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
|
||||||
};
|
};
|
||||||
ty::Binder::bind((trait_ref, sig.skip_binder().output()))
|
sig.map_bound(|sig| (trait_ref, sig.output()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generator_trait_ref_and_outputs(
|
pub fn generator_trait_ref_and_outputs(
|
||||||
@ -346,11 +347,12 @@ pub fn generator_trait_ref_and_outputs(
|
|||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
sig: ty::PolyGenSig<'tcx>,
|
sig: ty::PolyGenSig<'tcx>,
|
||||||
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
|
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
|
||||||
|
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||||
let trait_ref = ty::TraitRef {
|
let trait_ref = ty::TraitRef {
|
||||||
def_id: fn_trait_def_id,
|
def_id: fn_trait_def_id,
|
||||||
substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
|
substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
|
||||||
};
|
};
|
||||||
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
|
sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
|
pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
|
||||||
|
@ -837,9 +837,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
.instantiate_lang_item_trait_ref(
|
.instantiate_lang_item_trait_ref(
|
||||||
lang_item, span, hir_id, args, param_ty, bounds,
|
lang_item, span, hir_id, args, param_ty, bounds,
|
||||||
),
|
),
|
||||||
hir::GenericBound::Outlives(ref l) => {
|
hir::GenericBound::Outlives(ref l) => bounds
|
||||||
bounds.region_bounds.push((self.ast_region_to_region(l, None), l.span))
|
.region_bounds
|
||||||
}
|
.push((ty::Binder::bind(self.ast_region_to_region(l, None)), l.span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub struct Bounds<'tcx> {
|
|||||||
/// A list of region bounds on the (implicit) self type. So if you
|
/// A list of region bounds on the (implicit) self type. So if you
|
||||||
/// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
|
/// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
|
||||||
/// the `T` is not explicitly included).
|
/// the `T` is not explicitly included).
|
||||||
pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
|
pub region_bounds: Vec<(ty::Binder<ty::Region<'tcx>>, Span)>,
|
||||||
|
|
||||||
/// A list of trait bounds. So if you had `T: Debug` this would be
|
/// A list of trait bounds. So if you had `T: Debug` this would be
|
||||||
/// `T: Debug`. Note that the self-type is explicit here.
|
/// `T: Debug`. Note that the self-type is explicit here.
|
||||||
@ -68,8 +68,12 @@ impl<'tcx> Bounds<'tcx> {
|
|||||||
sized_predicate
|
sized_predicate
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(self.region_bounds.iter().map(|&(region_bound, span)| {
|
.chain(self.region_bounds.iter().map(|&(region_bound, span)| {
|
||||||
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
|
(
|
||||||
(ty::Binder::bind(outlives).to_predicate(tcx), span)
|
region_bound
|
||||||
|
.map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
|
||||||
|
.to_predicate(tcx),
|
||||||
|
span,
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
|
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
|
||||||
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
|
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
|
||||||
|
@ -389,7 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// In that case, we check each argument against "error" in order to
|
// In that case, we check each argument against "error" in order to
|
||||||
// set up all the node type bindings.
|
// set up all the node type bindings.
|
||||||
(
|
(
|
||||||
ty::Binder::bind(self.tcx.mk_fn_sig(
|
ty::Binder::dummy(self.tcx.mk_fn_sig(
|
||||||
self.err_args(arg_exprs.len()).into_iter(),
|
self.err_args(arg_exprs.len()).into_iter(),
|
||||||
self.tcx.ty_error(),
|
self.tcx.ty_error(),
|
||||||
false,
|
false,
|
||||||
|
@ -24,7 +24,7 @@ use std::iter;
|
|||||||
struct ExpectedSig<'tcx> {
|
struct ExpectedSig<'tcx> {
|
||||||
/// Span that gave us this expectation, if we know that.
|
/// Span that gave us this expectation, if we know that.
|
||||||
cause_span: Option<Span>,
|
cause_span: Option<Span>,
|
||||||
sig: ty::FnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClosureSignatures<'tcx> {
|
struct ClosureSignatures<'tcx> {
|
||||||
@ -174,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
|
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
|
||||||
ty::FnPtr(sig) => {
|
ty::FnPtr(sig) => {
|
||||||
let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder() };
|
let expected_sig = ExpectedSig { cause_span: None, sig };
|
||||||
(Some(expected_sig), Some(ty::ClosureKind::Fn))
|
(Some(expected_sig), Some(ty::ClosureKind::Fn))
|
||||||
}
|
}
|
||||||
_ => (None, None),
|
_ => (None, None),
|
||||||
@ -274,13 +274,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
|
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
|
||||||
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
|
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
|
||||||
|
|
||||||
let sig = self.tcx.mk_fn_sig(
|
let sig = projection.rebind(self.tcx.mk_fn_sig(
|
||||||
input_tys.iter(),
|
input_tys.iter(),
|
||||||
&ret_param_ty,
|
&ret_param_ty,
|
||||||
false,
|
false,
|
||||||
hir::Unsafety::Normal,
|
hir::Unsafety::Normal,
|
||||||
Abi::Rust,
|
Abi::Rust,
|
||||||
);
|
));
|
||||||
debug!("deduce_sig_from_projection: sig={:?}", sig);
|
debug!("deduce_sig_from_projection: sig={:?}", sig);
|
||||||
|
|
||||||
Some(ExpectedSig { cause_span, sig })
|
Some(ExpectedSig { cause_span, sig })
|
||||||
@ -374,9 +374,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// Watch out for some surprises and just ignore the
|
// Watch out for some surprises and just ignore the
|
||||||
// expectation if things don't see to match up with what we
|
// expectation if things don't see to match up with what we
|
||||||
// expect.
|
// expect.
|
||||||
if expected_sig.sig.c_variadic != decl.c_variadic {
|
if expected_sig.sig.c_variadic() != decl.c_variadic {
|
||||||
return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
|
return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
|
||||||
} else if expected_sig.sig.inputs_and_output.len() != decl.inputs.len() + 1 {
|
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
|
||||||
return self.sig_of_closure_with_mismatched_number_of_arguments(
|
return self.sig_of_closure_with_mismatched_number_of_arguments(
|
||||||
expr_def_id,
|
expr_def_id,
|
||||||
decl,
|
decl,
|
||||||
@ -388,14 +388,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// Create a `PolyFnSig`. Note the oddity that late bound
|
// Create a `PolyFnSig`. Note the oddity that late bound
|
||||||
// regions appearing free in `expected_sig` are now bound up
|
// regions appearing free in `expected_sig` are now bound up
|
||||||
// in this binder we are creating.
|
// in this binder we are creating.
|
||||||
assert!(!expected_sig.sig.has_vars_bound_above(ty::INNERMOST));
|
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
|
||||||
let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
|
let bound_sig = expected_sig.sig.map_bound(|sig| {
|
||||||
expected_sig.sig.inputs().iter().cloned(),
|
self.tcx.mk_fn_sig(
|
||||||
expected_sig.sig.output(),
|
sig.inputs().iter().cloned(),
|
||||||
decl.c_variadic,
|
sig.output(),
|
||||||
hir::Unsafety::Normal,
|
sig.c_variadic,
|
||||||
Abi::RustCall,
|
hir::Unsafety::Normal,
|
||||||
));
|
Abi::RustCall,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
// `deduce_expectations_from_expected_type` introduces
|
// `deduce_expectations_from_expected_type` introduces
|
||||||
// late-bound lifetimes defined elsewhere, which we now
|
// late-bound lifetimes defined elsewhere, which we now
|
||||||
@ -428,6 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let expr_map_node = hir.get_if_local(expr_def_id).unwrap();
|
let expr_map_node = hir.get_if_local(expr_def_id).unwrap();
|
||||||
let expected_args: Vec<_> = expected_sig
|
let expected_args: Vec<_> = expected_sig
|
||||||
.sig
|
.sig
|
||||||
|
.skip_binder()
|
||||||
.inputs()
|
.inputs()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ty| ArgKind::from_expected_ty(ty, None))
|
.map(|ty| ArgKind::from_expected_ty(ty, None))
|
||||||
@ -500,7 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
|
let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
|
||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
LateBoundRegionConversionTime::FnCall,
|
LateBoundRegionConversionTime::FnCall,
|
||||||
ty::Binder::bind(supplied_ty),
|
supplied_sig.inputs().rebind(supplied_ty),
|
||||||
); // recreated from (*) above
|
); // recreated from (*) above
|
||||||
|
|
||||||
// Check that E' = S'.
|
// Check that E' = S'.
|
||||||
@ -619,12 +622,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// where R is the return type we are expecting. This type `T`
|
// where R is the return type we are expecting. This type `T`
|
||||||
// will be our output.
|
// will be our output.
|
||||||
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
|
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
|
||||||
if let ty::PredicateAtom::Projection(proj_predicate) =
|
let bound_predicate = obligation.predicate.bound_atom();
|
||||||
obligation.predicate.skip_binders()
|
if let ty::PredicateAtom::Projection(proj_predicate) = bound_predicate.skip_binder() {
|
||||||
{
|
|
||||||
self.deduce_future_output_from_projection(
|
self.deduce_future_output_from_projection(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
ty::Binder::bind(proj_predicate),
|
bound_predicate.rebind(proj_predicate),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -704,7 +706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
astconv.ast_ty_to_ty(&output);
|
astconv.ast_ty_to_ty(&output);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = ty::Binder::bind(self.tcx.mk_fn_sig(
|
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
|
||||||
supplied_arguments,
|
supplied_arguments,
|
||||||
self.tcx.ty_error(),
|
self.tcx.ty_error(),
|
||||||
decl.c_variadic,
|
decl.c_variadic,
|
||||||
|
@ -494,12 +494,11 @@ fn compare_self_type<'tcx>(
|
|||||||
ty::ImplContainer(_) => impl_trait_ref.self_ty(),
|
ty::ImplContainer(_) => impl_trait_ref.self_ty(),
|
||||||
ty::TraitContainer(_) => tcx.types.self_param,
|
ty::TraitContainer(_) => tcx.types.self_param,
|
||||||
};
|
};
|
||||||
let self_arg_ty = tcx.fn_sig(method.def_id).input(0).skip_binder();
|
let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
|
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
let self_arg_ty =
|
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
|
||||||
tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_arg_ty));
|
|
||||||
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
|
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
|
||||||
match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
|
match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
|
||||||
ExplicitSelf::ByValue => "self".to_owned(),
|
ExplicitSelf::ByValue => "self".to_owned(),
|
||||||
|
@ -764,12 +764,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.pending_obligations()
|
.pending_obligations()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(move |obligation| {
|
.filter_map(move |obligation| {
|
||||||
match obligation.predicate.skip_binders() {
|
let bound_predicate = obligation.predicate.bound_atom();
|
||||||
|
match bound_predicate.skip_binder() {
|
||||||
ty::PredicateAtom::Projection(data) => {
|
ty::PredicateAtom::Projection(data) => {
|
||||||
Some((ty::Binder::bind(data).to_poly_trait_ref(self.tcx), obligation))
|
Some((bound_predicate.rebind(data).to_poly_trait_ref(self.tcx), obligation))
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::Trait(data, _) => {
|
ty::PredicateAtom::Trait(data, _) => {
|
||||||
Some((ty::Binder::bind(data).to_poly_trait_ref(), obligation))
|
Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation))
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::Subtype(..) => None,
|
ty::PredicateAtom::Subtype(..) => None,
|
||||||
ty::PredicateAtom::RegionOutlives(..) => None,
|
ty::PredicateAtom::RegionOutlives(..) => None,
|
||||||
|
@ -204,7 +204,8 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
|
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
|
||||||
|
|
||||||
// Store the generator types and spans into the typeck results for this generator.
|
// Store the generator types and spans into the typeck results for this generator.
|
||||||
visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types = type_causes;
|
visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types =
|
||||||
|
ty::Binder::bind(type_causes);
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"types in generator after region replacement {:?}, span = {:?}",
|
"types in generator after region replacement {:?}, span = {:?}",
|
||||||
|
@ -12,7 +12,7 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
@ -23,10 +23,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||||||
it: &hir::ForeignItem<'_>,
|
it: &hir::ForeignItem<'_>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
n_tps: usize,
|
n_tps: usize,
|
||||||
abi: Abi,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
safety: hir::Unsafety,
|
|
||||||
inputs: Vec<Ty<'tcx>>,
|
|
||||||
output: Ty<'tcx>,
|
|
||||||
) {
|
) {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ForeignItemKind::Fn(..) => {}
|
hir::ForeignItemKind::Fn(..) => {}
|
||||||
@ -53,13 +50,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
|
let fty = tcx.mk_fn_ptr(sig);
|
||||||
inputs.into_iter(),
|
|
||||||
output,
|
|
||||||
false,
|
|
||||||
safety,
|
|
||||||
abi,
|
|
||||||
)));
|
|
||||||
let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType);
|
let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType);
|
||||||
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
|
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
|
||||||
}
|
}
|
||||||
@ -380,7 +371,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||||||
};
|
};
|
||||||
(n_tps, inputs, output, unsafety)
|
(n_tps, inputs, output, unsafety)
|
||||||
};
|
};
|
||||||
equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
|
let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
|
||||||
|
let sig = ty::Binder::bind(sig);
|
||||||
|
equate_intrinsic_type(tcx, it, def_id, n_tps, sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type-check `extern "platform-intrinsic" { ... }` functions.
|
/// Type-check `extern "platform-intrinsic" { ... }` functions.
|
||||||
@ -466,14 +459,13 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
equate_intrinsic_type(
|
let sig = tcx.mk_fn_sig(
|
||||||
tcx,
|
inputs.into_iter(),
|
||||||
it,
|
|
||||||
def_id,
|
|
||||||
n_tps,
|
|
||||||
Abi::PlatformIntrinsic,
|
|
||||||
hir::Unsafety::Unsafe,
|
|
||||||
inputs,
|
|
||||||
output,
|
output,
|
||||||
)
|
false,
|
||||||
|
hir::Unsafety::Unsafe,
|
||||||
|
Abi::PlatformIntrinsic,
|
||||||
|
);
|
||||||
|
let sig = ty::Binder::dummy(sig);
|
||||||
|
equate_intrinsic_type(tcx, it, def_id, n_tps, sig)
|
||||||
}
|
}
|
||||||
|
@ -1919,10 +1919,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||||||
} else {
|
} else {
|
||||||
let span = bound_pred.bounded_ty.span;
|
let span = bound_pred.bounded_ty.span;
|
||||||
let re_root_empty = tcx.lifetimes.re_root_empty;
|
let re_root_empty = tcx.lifetimes.re_root_empty;
|
||||||
let predicate = ty::OutlivesPredicate(ty, re_root_empty);
|
let predicate = ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
|
||||||
|
ty::OutlivesPredicate(ty, re_root_empty),
|
||||||
|
));
|
||||||
predicates.insert((
|
predicates.insert((
|
||||||
ty::PredicateAtom::TypeOutlives(predicate)
|
predicate.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
||||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -1965,8 +1966,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||||||
&hir::GenericBound::Outlives(ref lifetime) => {
|
&hir::GenericBound::Outlives(ref lifetime) => {
|
||||||
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
|
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
|
||||||
predicates.insert((
|
predicates.insert((
|
||||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region))
|
ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
|
||||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
ty::OutlivesPredicate(ty, region),
|
||||||
|
))
|
||||||
|
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
||||||
lifetime.span,
|
lifetime.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -1983,9 +1986,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||||||
}
|
}
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2));
|
let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
|
||||||
|
.to_predicate(icx.tcx);
|
||||||
|
|
||||||
(pred.potentially_quantified(icx.tcx, ty::PredicateKind::ForAll), span)
|
(pred, span)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2234,7 +2238,7 @@ fn predicates_from_bound<'tcx>(
|
|||||||
hir::GenericBound::Outlives(ref lifetime) => {
|
hir::GenericBound::Outlives(ref lifetime) => {
|
||||||
let region = astconv.ast_region_to_region(lifetime, None);
|
let region = astconv.ast_region_to_region(lifetime, None);
|
||||||
let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
|
let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
|
||||||
.potentially_quantified(astconv.tcx(), ty::PredicateKind::ForAll);
|
.to_predicate(astconv.tcx());
|
||||||
vec![(pred, lifetime.span)]
|
vec![(pred, lifetime.span)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,19 +226,21 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
|
|||||||
let expected_return_type = if tcx.lang_items().termination().is_some() {
|
let expected_return_type = if tcx.lang_items().termination().is_some() {
|
||||||
// we take the return type of the given main function, the real check is done
|
// we take the return type of the given main function, the real check is done
|
||||||
// in `check_fn`
|
// in `check_fn`
|
||||||
actual.output().skip_binder()
|
actual.output()
|
||||||
} else {
|
} else {
|
||||||
// standard () main return type
|
// standard () main return type
|
||||||
tcx.mk_unit()
|
ty::Binder::dummy(tcx.mk_unit())
|
||||||
};
|
};
|
||||||
|
|
||||||
let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
|
let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
|
||||||
iter::empty(),
|
tcx.mk_fn_sig(
|
||||||
expected_return_type,
|
iter::empty(),
|
||||||
false,
|
expected_return_type,
|
||||||
hir::Unsafety::Normal,
|
false,
|
||||||
Abi::Rust,
|
hir::Unsafety::Normal,
|
||||||
)));
|
Abi::Rust,
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
require_same_types(
|
require_same_types(
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -3,7 +3,7 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
|
use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
@ -90,14 +90,14 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredica
|
|||||||
match kind1.unpack() {
|
match kind1.unpack() {
|
||||||
GenericArgKind::Type(ty1) => Some((
|
GenericArgKind::Type(ty1) => Some((
|
||||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
|
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
|
||||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
.to_predicate(tcx),
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
GenericArgKind::Lifetime(region1) => Some((
|
GenericArgKind::Lifetime(region1) => Some((
|
||||||
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
|
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
|
||||||
region1, region2,
|
region1, region2,
|
||||||
))
|
))
|
||||||
.potentially_quantified(tcx, ty::PredicateKind::ForAll),
|
.to_predicate(tcx),
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
GenericArgKind::Const(_) => {
|
GenericArgKind::Const(_) => {
|
||||||
|
@ -469,8 +469,9 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
|
|||||||
|
|
||||||
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
|
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
|
||||||
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
|
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
|
||||||
match self.skip_binders() {
|
let bound_predicate = self.bound_atom();
|
||||||
ty::PredicateAtom::Trait(pred, _) => Some(ty::Binder::bind(pred).clean(cx)),
|
match bound_predicate.skip_binder() {
|
||||||
|
ty::PredicateAtom::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
|
||||||
ty::PredicateAtom::RegionOutlives(pred) => pred.clean(cx),
|
ty::PredicateAtom::RegionOutlives(pred) => pred.clean(cx),
|
||||||
ty::PredicateAtom::TypeOutlives(pred) => pred.clean(cx),
|
ty::PredicateAtom::TypeOutlives(pred) => pred.clean(cx),
|
||||||
ty::PredicateAtom::Projection(pred) => Some(pred.clean(cx)),
|
ty::PredicateAtom::Projection(pred) => Some(pred.clean(cx)),
|
||||||
@ -733,7 +734,8 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
|
|||||||
.flat_map(|(p, _)| {
|
.flat_map(|(p, _)| {
|
||||||
let mut projection = None;
|
let mut projection = None;
|
||||||
let param_idx = (|| {
|
let param_idx = (|| {
|
||||||
match p.skip_binders() {
|
let bound_p = p.bound_atom();
|
||||||
|
match bound_p.skip_binder() {
|
||||||
ty::PredicateAtom::Trait(pred, _constness) => {
|
ty::PredicateAtom::Trait(pred, _constness) => {
|
||||||
if let ty::Param(param) = pred.self_ty().kind() {
|
if let ty::Param(param) = pred.self_ty().kind() {
|
||||||
return Some(param.index);
|
return Some(param.index);
|
||||||
@ -746,7 +748,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
|
|||||||
}
|
}
|
||||||
ty::PredicateAtom::Projection(p) => {
|
ty::PredicateAtom::Projection(p) => {
|
||||||
if let ty::Param(param) = p.projection_ty.self_ty().kind() {
|
if let ty::Param(param) = p.projection_ty.self_ty().kind() {
|
||||||
projection = Some(ty::Binder::bind(p));
|
projection = Some(bound_p.rebind(p));
|
||||||
return Some(param.index);
|
return Some(param.index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1659,12 +1661,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||||||
.filter_map(|bound| {
|
.filter_map(|bound| {
|
||||||
// Note: The substs of opaque types can contain unbound variables,
|
// Note: The substs of opaque types can contain unbound variables,
|
||||||
// meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
|
// meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
|
||||||
let trait_ref = match bound
|
let bound_predicate = bound.bound_atom_with_opt_escaping(cx.tcx);
|
||||||
.bound_atom_with_opt_escaping(cx.tcx)
|
let trait_ref = match bound_predicate.skip_binder() {
|
||||||
.skip_binder()
|
|
||||||
{
|
|
||||||
ty::PredicateAtom::Trait(tr, _constness) => {
|
ty::PredicateAtom::Trait(tr, _constness) => {
|
||||||
ty::Binder::bind(tr.trait_ref)
|
bound_predicate.rebind(tr.trait_ref)
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
|
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
|
||||||
if let Some(r) = reg.clean(cx) {
|
if let Some(r) = reg.clean(cx) {
|
||||||
|
@ -99,7 +99,7 @@ impl LateLintPass<'_> for AwaitHolding {
|
|||||||
};
|
};
|
||||||
let def_id = cx.tcx.hir().body_owner_def_id(body_id);
|
let def_id = cx.tcx.hir().body_owner_def_id(body_id);
|
||||||
let typeck_results = cx.tcx.typeck(def_id);
|
let typeck_results = cx.tcx.typeck(def_id);
|
||||||
check_interior_types(cx, &typeck_results.generator_interior_types, body.value.span);
|
check_interior_types(cx, &typeck_results.generator_interior_types.as_ref().skip_binder(), body.value.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user