Skip to content

Commit 9613bc3

Browse files
committed
Do not erase late bound regions, replace them with placeholders
1 parent 61a3eea commit 9613bc3

File tree

4 files changed

+115
-120
lines changed

4 files changed

+115
-120
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+102-116
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
2929
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
3030
use rustc_infer::traits::ObligationCause;
3131
use rustc_middle::middle::stability::AllowUnstable;
32+
use rustc_middle::ty::visit::TypeVisitable;
3233
use rustc_middle::ty::GenericParamDefKind;
3334
use rustc_middle::ty::{
3435
self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
@@ -38,9 +39,9 @@ use rustc_span::edit_distance::find_best_match_for_name;
3839
use rustc_span::symbol::{kw, Ident, Symbol};
3940
use rustc_span::{sym, BytePos, Span, DUMMY_SP};
4041
use rustc_target::spec::abi;
42+
use rustc_trait_selection::traits::query::normalize::MaxEscapingBoundVarVisitor;
4143
use rustc_trait_selection::traits::wf::object_region_bounds;
4244
use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
43-
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
4445

4546
use std::fmt::Display;
4647
use std::slice;
@@ -1605,131 +1606,116 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16051606
let cause = ObligationCause::misc(span, block.owner.def_id);
16061607

16071608
let mut fulfillment_errors = Vec::new();
1608-
let mut applicable_candidates: Vec<_> = infcx.probe(|_| {
1609-
// Regions are not considered during selection.
1610-
let self_ty = self_ty
1611-
.fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() });
1612-
1613-
struct BoundVarEraser<'tcx> {
1614-
tcx: TyCtxt<'tcx>,
1615-
universe: ty::UniverseIndex,
1616-
}
1617-
1618-
// FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder.
1619-
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarEraser<'tcx> {
1620-
fn interner(&self) -> TyCtxt<'tcx> {
1621-
self.tcx
1622-
}
1609+
infcx.probe(|_| {
1610+
let mut universes = if self_ty.has_escaping_bound_vars() {
1611+
let mut max_visitor =
1612+
MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
1613+
self_ty.visit_with(&mut max_visitor);
1614+
vec![None; max_visitor.escaping]
1615+
} else {
1616+
vec![]
1617+
};
16231618

1624-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
1625-
if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r }
1626-
}
1619+
crate::traits::project::with_replaced_escaping_bound_vars(
1620+
infcx,
1621+
&mut universes,
1622+
self_ty,
1623+
|self_ty| {
1624+
let InferOk { value: self_ty, obligations } =
1625+
infcx.at(&cause, param_env).normalize(self_ty);
16271626

1628-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1629-
match *ty.kind() {
1630-
ty::Bound(_, bv) => Ty::new_placeholder(
1631-
self.tcx,
1632-
ty::PlaceholderType { universe: self.universe, bound: bv },
1633-
),
1634-
_ => ty.super_fold_with(self),
1635-
}
1636-
}
1627+
let mut applicable_candidates: Vec<_> = candidates
1628+
.iter()
1629+
.copied()
1630+
.filter(|&(impl_, _)| {
1631+
infcx.probe(|_| {
1632+
let ocx = ObligationCtxt::new(&infcx);
1633+
ocx.register_obligations(obligations.clone());
1634+
1635+
let impl_args = infcx.fresh_args_for_item(span, impl_);
1636+
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
1637+
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1638+
1639+
// Check that the self types can be related.
1640+
// FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses
1641+
// `sup` for this situtation, too. What for? To constrain inference variables?
1642+
if ocx
1643+
.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty)
1644+
.is_err()
1645+
{
1646+
return false;
1647+
}
16371648

1638-
fn fold_const(
1639-
&mut self,
1640-
ct: ty::Const<'tcx>,
1641-
) -> <TyCtxt<'tcx> as rustc_type_ir::Interner>::Const {
1642-
assert!(!ct.ty().has_escaping_bound_vars());
1643-
1644-
match ct.kind() {
1645-
ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder(
1646-
self.tcx,
1647-
ty::PlaceholderConst { universe: self.universe, bound: bv },
1648-
ct.ty(),
1649-
),
1650-
_ => ct.super_fold_with(self),
1651-
}
1652-
}
1653-
}
1649+
// Check whether the impl imposes obligations we have to worry about.
1650+
let impl_bounds =
1651+
tcx.predicates_of(impl_).instantiate(tcx, impl_args);
1652+
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
1653+
let impl_obligations = traits::predicates_for_generics(
1654+
|_, _| cause.clone(),
1655+
param_env,
1656+
impl_bounds,
1657+
);
1658+
ocx.register_obligations(impl_obligations);
16541659

1655-
let InferOk { value: self_ty, obligations } =
1656-
infcx.at(&cause, param_env).normalize(self_ty);
1660+
let mut errors = ocx.select_where_possible();
1661+
if !errors.is_empty() {
1662+
fulfillment_errors.append(&mut errors);
1663+
return false;
1664+
}
16571665

1658-
candidates
1659-
.iter()
1660-
.copied()
1661-
.filter(|&(impl_, _)| {
1662-
infcx.probe(|_| {
1663-
let ocx = ObligationCtxt::new(&infcx);
1664-
ocx.register_obligations(obligations.clone());
1665-
1666-
let impl_args = infcx.fresh_args_for_item(span, impl_);
1667-
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
1668-
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1669-
1670-
// Check that the self types can be related.
1671-
// FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses
1672-
// `sup` for this situtation, too. What for? To constrain inference variables?
1673-
if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err()
1674-
{
1675-
return false;
1676-
}
1666+
true
1667+
})
1668+
})
1669+
.collect();
1670+
1671+
if applicable_candidates.len() > 1 {
1672+
return Err(self.complain_about_ambiguous_inherent_assoc_type(
1673+
name,
1674+
applicable_candidates
1675+
.into_iter()
1676+
.map(|(_, (candidate, _))| candidate)
1677+
.collect(),
1678+
span,
1679+
));
1680+
}
16771681

1678-
// Check whether the impl imposes obligations we have to worry about.
1679-
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
1680-
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
1681-
let impl_obligations = traits::predicates_for_generics(
1682-
|_, _| cause.clone(),
1683-
param_env,
1684-
impl_bounds,
1682+
if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
1683+
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
1684+
1685+
// FIXME(fmease): Currently creating throwaway `parent_args` to please
1686+
// `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1687+
// not require the parent args logic.
1688+
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
1689+
let args = self.create_args_for_associated_item(
1690+
span,
1691+
assoc_item,
1692+
segment,
1693+
parent_args,
1694+
);
1695+
let args = tcx.mk_args_from_iter(
1696+
std::iter::once(ty::GenericArg::from(self_ty))
1697+
.chain(args.into_iter().skip(parent_args.len())),
16851698
);
1686-
ocx.register_obligations(impl_obligations);
1687-
1688-
let mut errors = ocx.select_where_possible();
1689-
if !errors.is_empty() {
1690-
fulfillment_errors.append(&mut errors);
1691-
return false;
1692-
}
1693-
1694-
true
1695-
})
1696-
})
1697-
.collect()
1698-
});
1699-
1700-
if applicable_candidates.len() > 1 {
1701-
return Err(self.complain_about_ambiguous_inherent_assoc_type(
1702-
name,
1703-
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
1704-
span,
1705-
));
1706-
}
1707-
1708-
if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
1709-
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
1710-
1711-
// FIXME(fmease): Currently creating throwaway `parent_args` to please
1712-
// `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1713-
// not require the parent args logic.
1714-
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
1715-
let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
1716-
let args = tcx.mk_args_from_iter(
1717-
std::iter::once(ty::GenericArg::from(self_ty))
1718-
.chain(args.into_iter().skip(parent_args.len())),
1719-
);
17201699

1721-
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
1700+
let ty = Ty::new_alias(
1701+
tcx,
1702+
ty::Inherent,
1703+
ty::AliasTy::new(tcx, assoc_item, args),
1704+
);
17221705

1723-
return Ok(Some((ty, assoc_item)));
1724-
}
1706+
return Ok(Some((ty, assoc_item)));
1707+
}
17251708

1726-
Err(self.complain_about_inherent_assoc_type_not_found(
1727-
name,
1728-
self_ty,
1729-
candidates,
1730-
fulfillment_errors,
1731-
span,
1732-
))
1709+
Err(self.complain_about_inherent_assoc_type_not_found(
1710+
name,
1711+
self_ty,
1712+
candidates,
1713+
fulfillment_errors,
1714+
span,
1715+
))
1716+
},
1717+
)
1718+
})
17331719
}
17341720

17351721
fn lookup_assoc_ty(

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
120120
}
121121

122122
// Visitor to find the maximum escaping bound var
123-
struct MaxEscapingBoundVarVisitor {
123+
pub struct MaxEscapingBoundVarVisitor {
124124
// The index which would count as escaping
125-
outer_index: ty::DebruijnIndex,
126-
escaping: usize,
125+
pub outer_index: ty::DebruijnIndex,
126+
pub escaping: usize,
127127
}
128128

129129
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {

tests/ui/associated-inherent-types/issue-111404-1.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ impl<'a> Foo<fn(&'a ())> {
99

1010
fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
1111
//~^ ERROR higher-ranked subtype error
12+
//~| ERROR higher-ranked subtype error
1213

1314
fn main() {}

tests/ui/associated-inherent-types/issue-111404-1.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,13 @@ error: higher-ranked subtype error
44
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: aborting due to previous error
7+
error: higher-ranked subtype error
8+
--> $DIR/issue-111404-1.rs:10:1
9+
|
10+
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
|
13+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
15+
error: aborting due to 2 previous errors
816

0 commit comments

Comments
 (0)