mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Auto merge of #79945 - jackh726:existential_trait_ref, r=nikomatsakis
Move binder for dyn to each list item This essentially changes `ty::Binder<&'tcx List<ExistentialTraitRef>>` to `&'tcx List<ty::Binder<ExistentialTraitRef>>`. This is a first step in moving the `dyn Trait` representation closer to Chalk, which we've talked about in `@rust-lang/wg-traits.` r? `@nikomatsakis`
This commit is contained in:
commit
eb4fc71dc9
@ -480,17 +480,19 @@ impl<'tcx> CPlace<'tcx> {
|
||||
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
||||
}
|
||||
(&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => {
|
||||
let from_traits = fx
|
||||
for (from, to) in from_traits.iter().zip(to_traits) {
|
||||
let from = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from_traits);
|
||||
let to_traits = fx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
|
||||
let to = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_traits);
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to);
|
||||
assert_eq!(
|
||||
from_traits, to_traits,
|
||||
from, to,
|
||||
"Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
|
||||
from_traits, to_traits, fx,
|
||||
);
|
||||
}
|
||||
// dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
|
||||
}
|
||||
_ => {
|
||||
|
@ -496,7 +496,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
_predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
Err(NonTrivialPath)
|
||||
}
|
||||
|
@ -786,7 +786,7 @@ impl<'tcx> LateContext<'tcx> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
_predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -218,8 +218,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
}
|
||||
ty::Dynamic(binder, _) => {
|
||||
let mut has_emitted = false;
|
||||
for predicate in binder.skip_binder().iter() {
|
||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
|
||||
for predicate in binder.iter() {
|
||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
|
||||
predicate.skip_binder()
|
||||
{
|
||||
let def_id = trait_ref.def_id;
|
||||
let descr_post =
|
||||
&format!(" trait object{}{}", plural_suffix, descr_post,);
|
||||
|
@ -320,10 +320,14 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
|
||||
for ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>
|
||||
{
|
||||
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
|
||||
let len = decoder.read_usize()?;
|
||||
Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
Ok(decoder
|
||||
.tcx()
|
||||
.mk_poly_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,7 +376,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
|
||||
impl_decodable_via_ref! {
|
||||
&'tcx ty::TypeckResults<'tcx>,
|
||||
&'tcx ty::List<Ty<'tcx>>,
|
||||
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
&'tcx Allocation,
|
||||
&'tcx mir::Body<'tcx>,
|
||||
&'tcx mir::UnsafetyCheckResult,
|
||||
|
@ -87,7 +87,7 @@ pub struct CtxtInterners<'tcx> {
|
||||
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
|
||||
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
|
||||
region: InternedSet<'tcx, RegionKind>,
|
||||
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
|
||||
poly_existential_predicates: InternedSet<'tcx, List<ty::Binder<ExistentialPredicate<'tcx>>>>,
|
||||
predicate: InternedSet<'tcx, PredicateInner<'tcx>>,
|
||||
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
|
||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||
@ -103,7 +103,7 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||
type_list: Default::default(),
|
||||
substs: Default::default(),
|
||||
region: Default::default(),
|
||||
existential_predicates: Default::default(),
|
||||
poly_existential_predicates: Default::default(),
|
||||
canonical_var_infos: Default::default(),
|
||||
predicate: Default::default(),
|
||||
predicates: Default::default(),
|
||||
@ -1623,7 +1623,7 @@ nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
|
||||
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
|
||||
|
||||
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
|
||||
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
|
||||
nop_list_lift! {poly_existential_predicates; ty::Binder<ExistentialPredicate<'a>> => ty::Binder<ExistentialPredicate<'tcx>>}
|
||||
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
|
||||
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
|
||||
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
|
||||
@ -2064,7 +2064,8 @@ slice_interners!(
|
||||
type_list: _intern_type_list(Ty<'tcx>),
|
||||
substs: _intern_substs(GenericArg<'tcx>),
|
||||
canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
|
||||
existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
|
||||
poly_existential_predicates:
|
||||
_intern_poly_existential_predicates(ty::Binder<ExistentialPredicate<'tcx>>),
|
||||
predicates: _intern_predicates(Predicate<'tcx>),
|
||||
projs: _intern_projs(ProjectionKind),
|
||||
place_elems: _intern_place_elems(PlaceElem<'tcx>),
|
||||
@ -2295,7 +2296,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline]
|
||||
pub fn mk_dynamic(
|
||||
self,
|
||||
obj: ty::Binder<&'tcx List<ExistentialPredicate<'tcx>>>,
|
||||
obj: &'tcx List<ty::Binder<ExistentialPredicate<'tcx>>>,
|
||||
reg: ty::Region<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
self.mk_ty(Dynamic(obj, reg))
|
||||
@ -2425,13 +2426,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
Place { local: place.local, projection: self.intern_place_elems(&projection) }
|
||||
}
|
||||
|
||||
pub fn intern_existential_predicates(
|
||||
pub fn intern_poly_existential_predicates(
|
||||
self,
|
||||
eps: &[ExistentialPredicate<'tcx>],
|
||||
) -> &'tcx List<ExistentialPredicate<'tcx>> {
|
||||
eps: &[ty::Binder<ExistentialPredicate<'tcx>>],
|
||||
) -> &'tcx List<ty::Binder<ExistentialPredicate<'tcx>>> {
|
||||
assert!(!eps.is_empty());
|
||||
assert!(eps.array_windows().all(|[a, b]| a.stable_cmp(self, b) != Ordering::Greater));
|
||||
self._intern_existential_predicates(eps)
|
||||
assert!(
|
||||
eps.array_windows()
|
||||
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
|
||||
!= Ordering::Greater)
|
||||
);
|
||||
self._intern_poly_existential_predicates(eps)
|
||||
}
|
||||
|
||||
pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
|
||||
@ -2488,13 +2493,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn mk_existential_predicates<
|
||||
I: InternAs<[ExistentialPredicate<'tcx>], &'tcx List<ExistentialPredicate<'tcx>>>,
|
||||
pub fn mk_poly_existential_predicates<
|
||||
I: InternAs<
|
||||
[ty::Binder<ExistentialPredicate<'tcx>>],
|
||||
&'tcx List<ty::Binder<ExistentialPredicate<'tcx>>>,
|
||||
>,
|
||||
>(
|
||||
self,
|
||||
iter: I,
|
||||
) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_existential_predicates(xs))
|
||||
iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
|
||||
}
|
||||
|
||||
pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], &'tcx List<Predicate<'tcx>>>>(
|
||||
|
@ -58,7 +58,7 @@ pub enum TypeError<'tcx> {
|
||||
CyclicTy(Ty<'tcx>),
|
||||
CyclicConst(&'tcx ty::Const<'tcx>),
|
||||
ProjectionMismatched(ExpectedFound<DefId>),
|
||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>>),
|
||||
ObjectUnsafeCoercion(DefId),
|
||||
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
||||
|
||||
|
@ -160,19 +160,15 @@ impl FlagComputation {
|
||||
}
|
||||
|
||||
&ty::Dynamic(obj, r) => {
|
||||
self.bound_computation(obj, |computation, obj| {
|
||||
for predicate in obj.iter() {
|
||||
match predicate {
|
||||
ty::ExistentialPredicate::Trait(tr) => {
|
||||
computation.add_substs(tr.substs)
|
||||
}
|
||||
self.bound_computation(predicate, |computation, predicate| match predicate {
|
||||
ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
|
||||
ty::ExistentialPredicate::Projection(p) => {
|
||||
computation.add_existential_projection(&p);
|
||||
}
|
||||
ty::ExistentialPredicate::AutoTrait(_) => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.add_region(r);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized {
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error>;
|
||||
|
||||
fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error>;
|
||||
@ -343,7 +343,9 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P>
|
||||
for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>
|
||||
{
|
||||
type Output = P::DynExistential;
|
||||
type Error = P::Error;
|
||||
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
||||
|
@ -209,6 +209,17 @@ pub trait PrettyPrinter<'tcx>:
|
||||
value.as_ref().skip_binder().print(self)
|
||||
}
|
||||
|
||||
fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
|
||||
self,
|
||||
value: &ty::Binder<T>,
|
||||
f: F,
|
||||
) -> Result<Self, Self::Error>
|
||||
where
|
||||
T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
|
||||
{
|
||||
f(value.as_ref().skip_binder(), self)
|
||||
}
|
||||
|
||||
/// Prints comma-separated elements.
|
||||
fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
|
||||
where
|
||||
@ -753,26 +764,26 @@ pub trait PrettyPrinter<'tcx>:
|
||||
|
||||
fn pretty_print_dyn_existential(
|
||||
mut self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
define_scoped_cx!(self);
|
||||
|
||||
// Generate the main trait ref, including associated types.
|
||||
let mut first = true;
|
||||
|
||||
if let Some(principal) = predicates.principal() {
|
||||
self = self.wrap_binder(&principal, |principal, mut cx| {
|
||||
define_scoped_cx!(cx);
|
||||
p!(print_def_path(principal.def_id, &[]));
|
||||
|
||||
let mut resugared = false;
|
||||
|
||||
// Special-case `Fn(...) -> ...` and resugar it.
|
||||
let fn_trait_kind = self.tcx().fn_trait_kind_from_lang_item(principal.def_id);
|
||||
if !self.tcx().sess.verbose() && fn_trait_kind.is_some() {
|
||||
let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id);
|
||||
if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() {
|
||||
if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() {
|
||||
let mut projections = predicates.projection_bounds();
|
||||
if let (Some(proj), None) = (projections.next(), projections.next()) {
|
||||
let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
|
||||
p!(pretty_fn_sig(&tys, false, proj.ty));
|
||||
p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty));
|
||||
resugared = true;
|
||||
}
|
||||
}
|
||||
@ -782,11 +793,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||
// in order to place the projections inside the `<...>`.
|
||||
if !resugared {
|
||||
// Use a type that can't appear in defaults of type parameters.
|
||||
let dummy_self = self.tcx().mk_ty_infer(ty::FreshTy(0));
|
||||
let principal = principal.with_self_ty(self.tcx(), dummy_self);
|
||||
let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
|
||||
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
|
||||
|
||||
let args = self.generic_args_to_print(
|
||||
self.tcx().generics_of(principal.def_id),
|
||||
let args = cx.generic_args_to_print(
|
||||
cx.tcx().generics_of(principal.def_id),
|
||||
principal.substs,
|
||||
);
|
||||
|
||||
@ -816,9 +827,14 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}));
|
||||
}
|
||||
}
|
||||
Ok(cx)
|
||||
})?;
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
define_scoped_cx!(self);
|
||||
|
||||
// Builtin bounds.
|
||||
// FIXME(eddyb) avoid printing twice (needed to ensure
|
||||
// that the auto traits are sorted *and* printed via cx).
|
||||
@ -1391,7 +1407,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
self.pretty_print_dyn_existential(predicates)
|
||||
}
|
||||
@ -1537,6 +1553,17 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
|
||||
self.pretty_in_binder(value)
|
||||
}
|
||||
|
||||
fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
|
||||
self,
|
||||
value: &ty::Binder<T>,
|
||||
f: C,
|
||||
) -> Result<Self, Self::Error>
|
||||
where
|
||||
T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
|
||||
{
|
||||
self.pretty_wrap_binder(value, f)
|
||||
}
|
||||
|
||||
fn typed_value(
|
||||
mut self,
|
||||
f: impl FnOnce(Self) -> Result<Self, Self::Error>,
|
||||
@ -1790,6 +1817,22 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
|
||||
self,
|
||||
value: &ty::Binder<T>,
|
||||
f: C,
|
||||
) -> Result<Self, fmt::Error>
|
||||
where
|
||||
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
|
||||
{
|
||||
let old_region_index = self.region_index;
|
||||
let (new, new_value) = self.name_all_regions(value)?;
|
||||
let mut inner = f(&new_value.0, new)?;
|
||||
inner.region_index = old_region_index;
|
||||
inner.binder_depth -= 1;
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
@ -1906,12 +1949,12 @@ impl ty::Binder<ty::TraitRef<'tcx>> {
|
||||
|
||||
forward_display_to_print! {
|
||||
Ty<'tcx>,
|
||||
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
&'tcx ty::Const<'tcx>,
|
||||
|
||||
// HACK(eddyb) these are exhaustive instead of generic,
|
||||
// because `for<'tcx>` isn't possible yet.
|
||||
ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
|
||||
ty::Binder<ty::ExistentialPredicate<'tcx>>,
|
||||
ty::Binder<ty::TraitRef<'tcx>>,
|
||||
ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
ty::Binder<ty::FnSig<'tcx>>,
|
||||
|
@ -603,7 +603,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||
new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
@ -616,9 +616,10 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
// in `a`.
|
||||
let mut a_v: Vec<_> = a.into_iter().collect();
|
||||
let mut b_v: Vec<_> = b.into_iter().collect();
|
||||
a_v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
||||
// `skip_binder` here is okay because `stable_cmp` doesn't look at binders
|
||||
a_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||
a_v.dedup();
|
||||
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
||||
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||
b_v.dedup();
|
||||
if a_v.len() != b_v.len() {
|
||||
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
|
||||
@ -626,14 +627,18 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
|
||||
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
|
||||
use crate::ty::ExistentialPredicate::*;
|
||||
match (ep_a, ep_b) {
|
||||
(Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
|
||||
(Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
|
||||
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
|
||||
match (ep_a.skip_binder(), ep_b.skip_binder()) {
|
||||
(Trait(a), Trait(b)) => Ok(ty::Binder::bind(Trait(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(Projection(a), Projection(b)) => Ok(ty::Binder::bind(Projection(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))),
|
||||
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
|
||||
}
|
||||
});
|
||||
Ok(tcx.mk_existential_predicates(v)?)
|
||||
Ok(tcx.mk_poly_existential_predicates(v)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,9 +843,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_existential_predicates(v))
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
|
@ -152,7 +152,7 @@ pub enum TyKind<'tcx> {
|
||||
FnPtr(PolyFnSig<'tcx>),
|
||||
|
||||
/// A trait, defined with `trait`.
|
||||
Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
|
||||
Dynamic(&'tcx List<Binder<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
|
||||
|
||||
/// The anonymous type of a closure. Used to represent the type of
|
||||
/// `|a| a`.
|
||||
@ -762,7 +762,7 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> List<ExistentialPredicate<'tcx>> {
|
||||
impl<'tcx> List<ty::Binder<ExistentialPredicate<'tcx>>> {
|
||||
/// Returns the "principal `DefId`" of this set of existential predicates.
|
||||
///
|
||||
/// A Rust trait object type consists (in addition to a lifetime bound)
|
||||
@ -788,64 +788,42 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
|
||||
/// is `{Send, Sync}`, while there is no principal. These trait objects
|
||||
/// have a "trivial" vtable consisting of just the size, alignment,
|
||||
/// and destructor.
|
||||
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
|
||||
match self[0] {
|
||||
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
|
||||
self[0]
|
||||
.map_bound(|this| match this {
|
||||
ExistentialPredicate::Trait(tr) => Some(tr),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
pub fn principal_def_id(&self) -> Option<DefId> {
|
||||
self.principal().map(|trait_ref| trait_ref.def_id)
|
||||
self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn projection_bounds<'a>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = ExistentialProjection<'tcx>> + 'a {
|
||||
self.iter().filter_map(|predicate| match predicate {
|
||||
) -> impl Iterator<Item = ty::Binder<ExistentialProjection<'tcx>>> + 'a {
|
||||
self.iter().filter_map(|predicate| {
|
||||
predicate
|
||||
.map_bound(|pred| match pred {
|
||||
ExistentialPredicate::Projection(projection) => Some(projection),
|
||||
_ => None,
|
||||
})
|
||||
.transpose()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
|
||||
self.iter().filter_map(|predicate| match predicate {
|
||||
self.iter().filter_map(|predicate| match predicate.skip_binder() {
|
||||
ExistentialPredicate::AutoTrait(did) => Some(did),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
|
||||
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
|
||||
self.map_bound(|b| b.principal()).transpose()
|
||||
}
|
||||
|
||||
pub fn principal_def_id(&self) -> Option<DefId> {
|
||||
self.skip_binder().principal_def_id()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn projection_bounds<'a>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = PolyExistentialProjection<'tcx>> + 'a {
|
||||
self.skip_binder().projection_bounds().map(Binder::bind)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
|
||||
self.skip_binder().auto_traits()
|
||||
}
|
||||
|
||||
pub fn iter<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = Binder<ExistentialPredicate<'tcx>>> + 'tcx {
|
||||
self.skip_binder().iter().map(Binder::bind)
|
||||
}
|
||||
}
|
||||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
///
|
||||
|
@ -74,7 +74,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
mut self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
let mut first = true;
|
||||
for p in predicates {
|
||||
|
@ -184,8 +184,8 @@ where
|
||||
ty::Dynamic(predicates, ..) => {
|
||||
// All traits in the list are considered the "primary" part of the type
|
||||
// and are visited by shallow visitors.
|
||||
for predicate in predicates.skip_binder() {
|
||||
let trait_ref = match predicate {
|
||||
for predicate in predicates {
|
||||
let trait_ref = match predicate.skip_binder() {
|
||||
ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
|
||||
ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
|
@ -222,7 +222,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
mut self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
let mut first = true;
|
||||
for p in predicates {
|
||||
|
@ -465,9 +465,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
|
||||
ty::Dynamic(predicates, r) => {
|
||||
self.push("D");
|
||||
self = self.in_binder(&predicates, |cx, predicates| {
|
||||
cx.print_dyn_existential(predicates)
|
||||
})?;
|
||||
self = self.print_dyn_existential(predicates)?;
|
||||
self = r.print(self)?;
|
||||
}
|
||||
|
||||
@ -486,26 +484,29 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
|
||||
fn print_dyn_existential(
|
||||
mut self,
|
||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
for predicate in predicates {
|
||||
self = self.in_binder(&predicate, |mut cx, predicate| {
|
||||
match predicate {
|
||||
ty::ExistentialPredicate::Trait(trait_ref) => {
|
||||
// Use a type that can't appear in defaults of type parameters.
|
||||
let dummy_self = self.tcx.mk_ty_infer(ty::FreshTy(0));
|
||||
let trait_ref = trait_ref.with_self_ty(self.tcx, dummy_self);
|
||||
self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
|
||||
let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0));
|
||||
let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self);
|
||||
cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
|
||||
}
|
||||
ty::ExistentialPredicate::Projection(projection) => {
|
||||
let name = self.tcx.associated_item(projection.item_def_id).ident;
|
||||
self.push("p");
|
||||
self.push_ident(&name.as_str());
|
||||
self = projection.ty.print(self)?;
|
||||
let name = cx.tcx.associated_item(projection.item_def_id).ident;
|
||||
cx.push("p");
|
||||
cx.push_ident(&name.as_str());
|
||||
cx = projection.ty.print(cx)?;
|
||||
}
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
self = self.print_def_path(def_id, &[])?;
|
||||
cx = cx.print_def_path(*def_id, &[])?;
|
||||
}
|
||||
}
|
||||
Ok(cx)
|
||||
})?;
|
||||
}
|
||||
self.push("E");
|
||||
Ok(self)
|
||||
|
@ -219,8 +219,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if let ty::Dynamic(traits, _) = self_ty.kind() {
|
||||
for t in traits.skip_binder() {
|
||||
if let ty::ExistentialPredicate::Trait(trait_ref) = t {
|
||||
for t in traits.iter() {
|
||||
if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
|
||||
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
|
||||
}
|
||||
}
|
||||
|
@ -551,8 +551,9 @@ fn object_ty_for_trait<'tcx>(
|
||||
|
||||
let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
|
||||
|
||||
let trait_predicate =
|
||||
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
|
||||
let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait(
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
|
||||
));
|
||||
|
||||
let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
|
||||
.flat_map(|super_trait_ref| {
|
||||
@ -569,24 +570,19 @@ fn object_ty_for_trait<'tcx>(
|
||||
let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
|
||||
// We *can* get bound lifetimes here in cases like
|
||||
// `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
|
||||
//
|
||||
// binder moved to (*)...
|
||||
let super_trait_ref = super_trait_ref.skip_binder();
|
||||
super_trait_ref.map_bound(|super_trait_ref| {
|
||||
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
|
||||
ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
|
||||
item_def_id: item.def_id,
|
||||
substs: super_trait_ref.substs,
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
let existential_predicates =
|
||||
tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
|
||||
let existential_predicates = tcx
|
||||
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
|
||||
|
||||
let object_ty = tcx.mk_dynamic(
|
||||
// (*) ... binder re-introduced here
|
||||
ty::Binder::bind(existential_predicates),
|
||||
lifetime,
|
||||
);
|
||||
let object_ty = tcx.mk_dynamic(existential_predicates, lifetime);
|
||||
|
||||
debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
|
||||
|
||||
|
@ -375,24 +375,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
|
||||
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
|
||||
let data = match *self_ty.kind() {
|
||||
ty::Dynamic(data, ..) => {
|
||||
self.infcx
|
||||
.replace_bound_vars_with_fresh_vars(
|
||||
obligation.cause.span,
|
||||
HigherRankedType,
|
||||
data,
|
||||
)
|
||||
.0
|
||||
}
|
||||
ty::Dynamic(data, ..) => data,
|
||||
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
|
||||
};
|
||||
|
||||
let object_trait_ref = data
|
||||
.principal()
|
||||
.unwrap_or_else(|| {
|
||||
let object_trait_ref = data.principal().unwrap_or_else(|| {
|
||||
span_bug!(obligation.cause.span, "object candidate with no principal")
|
||||
})
|
||||
.with_self_ty(self.tcx(), self_ty);
|
||||
});
|
||||
let object_trait_ref = self
|
||||
.infcx
|
||||
.replace_bound_vars_with_fresh_vars(
|
||||
obligation.cause.span,
|
||||
HigherRankedType,
|
||||
object_trait_ref,
|
||||
)
|
||||
.0;
|
||||
let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty);
|
||||
|
||||
let mut nested = vec![];
|
||||
|
||||
@ -711,15 +709,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
|
||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||
// See `assemble_candidates_for_unsizing` for more info.
|
||||
let existential_predicates = data_a.map_bound(|data_a| {
|
||||
let iter = data_a
|
||||
.principal()
|
||||
.map(ty::ExistentialPredicate::Trait)
|
||||
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
|
||||
.into_iter()
|
||||
.chain(data_a.projection_bounds().map(ty::ExistentialPredicate::Projection))
|
||||
.chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
|
||||
tcx.mk_existential_predicates(iter)
|
||||
});
|
||||
.chain(
|
||||
data_a
|
||||
.projection_bounds()
|
||||
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
|
||||
)
|
||||
.chain(
|
||||
data_b
|
||||
.auto_traits()
|
||||
.map(ty::ExistentialPredicate::AutoTrait)
|
||||
.map(ty::Binder::dummy),
|
||||
);
|
||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
|
||||
|
||||
// Require that the traits involved in this upcast are **equal**;
|
||||
|
@ -706,7 +706,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
fn from_object_ty(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
|
||||
data: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
region: ty::Region<'tcx>,
|
||||
) {
|
||||
// Imagine a type like this:
|
||||
@ -769,7 +769,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
/// `infer::required_region_bounds`, see that for more information.
|
||||
pub fn object_region_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
|
||||
existential_predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Vec<ty::Region<'tcx>> {
|
||||
// Since we don't actually *know* the self type for an object,
|
||||
// this "open(err)" serves as a kind of dummy standin -- basically
|
||||
|
@ -615,7 +615,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
|
||||
}
|
||||
|
||||
impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>>>
|
||||
for Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
|
||||
for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>
|
||||
{
|
||||
fn lower_into(
|
||||
self,
|
||||
@ -627,16 +627,17 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
|
||||
// Binders<&[Binders<WhereClause<I>>]>
|
||||
// This means that any variables that are escaping `self` need to be
|
||||
// shifted in by one so that they are still escaping.
|
||||
let shifted_predicates = ty::fold::shift_vars(interner.tcx, self, 1);
|
||||
let predicates = ty::fold::shift_vars(interner.tcx, self, 1);
|
||||
|
||||
let (predicates, binders, _named_regions) =
|
||||
collect_bound_vars(interner, interner.tcx, shifted_predicates);
|
||||
let self_ty = interner.tcx.mk_ty(ty::Bound(
|
||||
// This is going to be wrapped in a binder
|
||||
ty::DebruijnIndex::from_usize(1),
|
||||
ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon },
|
||||
));
|
||||
let where_clauses = predicates.into_iter().map(|predicate| match predicate {
|
||||
let where_clauses = predicates.into_iter().map(|predicate| {
|
||||
let (predicate, binders, _named_regions) =
|
||||
collect_bound_vars(interner, interner.tcx, predicate);
|
||||
match predicate {
|
||||
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => {
|
||||
chalk_ir::Binders::new(
|
||||
binders.clone(),
|
||||
@ -666,9 +667,13 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
|
||||
binders.clone(),
|
||||
chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
|
||||
trait_id: chalk_ir::TraitId(def_id),
|
||||
substitution: interner.tcx.mk_substs_trait(self_ty, &[]).lower_into(interner),
|
||||
substitution: interner
|
||||
.tcx
|
||||
.mk_substs_trait(self_ty, &[])
|
||||
.lower_into(interner),
|
||||
}),
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
// Binder for the bound variable representing the concrete underlying type.
|
||||
|
@ -1254,22 +1254,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
})
|
||||
});
|
||||
|
||||
// Calling `skip_binder` is okay because the predicates are re-bound.
|
||||
let regular_trait_predicates = existential_trait_refs
|
||||
.map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
|
||||
let auto_trait_predicates = auto_traits
|
||||
.into_iter()
|
||||
.map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
|
||||
let regular_trait_predicates = existential_trait_refs.map(|trait_ref| {
|
||||
trait_ref.map_bound(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref))
|
||||
});
|
||||
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
|
||||
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
|
||||
});
|
||||
let mut v = regular_trait_predicates
|
||||
.chain(auto_trait_predicates)
|
||||
.chain(
|
||||
existential_projections
|
||||
.map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
|
||||
.map(|x| x.map_bound(|x| ty::ExistentialPredicate::Projection(x))),
|
||||
)
|
||||
.collect::<SmallVec<[_; 8]>>();
|
||||
v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
||||
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||
v.dedup();
|
||||
let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
|
||||
let existential_predicates = tcx.mk_poly_existential_predicates(v.into_iter());
|
||||
|
||||
// Use explicitly-specified region bound.
|
||||
let region_bound = if !lifetime.is_elided() {
|
||||
@ -2331,7 +2331,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
fn compute_object_lifetime_bound(
|
||||
&self,
|
||||
span: Span,
|
||||
existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
|
||||
existential_predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
|
||||
) -> Option<ty::Region<'tcx>> // if None, use the default
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
@ -620,8 +620,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
|
||||
// Point at the trait object that couldn't satisfy the bound.
|
||||
ty::Dynamic(preds, _) => {
|
||||
for pred in preds.skip_binder() {
|
||||
match pred {
|
||||
for pred in preds.iter() {
|
||||
match pred.skip_binder() {
|
||||
ty::ExistentialPredicate::Trait(tr) => {
|
||||
bound_spans.push((def_span(tr.def_id), msg.clone()))
|
||||
}
|
||||
@ -674,9 +674,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.iter()
|
||||
.filter_map(|(pred, parent_pred)| {
|
||||
format_pred(*pred).map(|(p, self_ty)| match parent_pred {
|
||||
None => format!("`{}`", p),
|
||||
None => format!("`{}`", &p),
|
||||
Some(parent_pred) => match format_pred(*parent_pred) {
|
||||
None => format!("`{}`", p),
|
||||
None => format!("`{}`", &p),
|
||||
Some((parent_p, _)) => {
|
||||
collect_type_param_suggestions(self_ty, parent_pred, &p);
|
||||
format!("`{}`\nwhich is required by `{}`", p, parent_p)
|
||||
|
@ -4,5 +4,11 @@ error: higher-ranked subtype error
|
||||
LL | foo(bar);
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-40000.rs:6:9
|
||||
|
|
||||
LL | foo(bar);
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1449,8 +1449,8 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
false
|
||||
},
|
||||
ty::Dynamic(binder, _) => {
|
||||
for predicate in binder.skip_binder().iter() {
|
||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
|
||||
for predicate in binder.iter() {
|
||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
|
||||
if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user