Auto merge of #116756 - fee1-dead-contrib:dupe-those-bounds, r=oli-obk
Duplicate `~const` bounds with a non-const one in effects desugaring This should unblock #116058. r? `@oli-obk`
This commit is contained in:
commit
616e37919c
10 changed files with 661 additions and 40 deletions
|
@ -1091,7 +1091,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
|
||||
});
|
||||
|
||||
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
|
||||
let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next())
|
||||
{
|
||||
(Some(bound), _) => (bound, matching_candidates.next()),
|
||||
(None, Some(bound)) => (bound, const_candidates.next()),
|
||||
(None, None) => {
|
||||
|
@ -1107,6 +1108,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
};
|
||||
debug!(?bound);
|
||||
|
||||
// look for a candidate that is not the same as our first bound, disregarding
|
||||
// whether the bound is const.
|
||||
while let Some(mut bound2) = next_cand {
|
||||
debug!(?bound2);
|
||||
let tcx = self.tcx();
|
||||
if bound2.bound_vars() != bound.bound_vars() {
|
||||
break;
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(bound.def_id());
|
||||
let Some(host_index) = generics.host_effect_index else { break };
|
||||
|
||||
// always return the bound that contains the host param.
|
||||
if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() {
|
||||
(bound, bound2) = (bound2, bound);
|
||||
}
|
||||
|
||||
let unconsted_args = bound
|
||||
.skip_binder()
|
||||
.args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg });
|
||||
|
||||
if unconsted_args.eq(bound2.skip_binder().args.iter()) {
|
||||
next_cand = matching_candidates.next().or_else(|| const_candidates.next());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(bound2) = next_cand {
|
||||
debug!(?bound2);
|
||||
|
||||
|
|
|
@ -43,6 +43,33 @@ impl<'tcx> Bounds<'tcx> {
|
|||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::ImplPolarity,
|
||||
) {
|
||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||
|
||||
// if we have a host param, we push an unconst trait bound in addition
|
||||
// to the const one.
|
||||
// FIXME(effects) we should find a better way than name matching
|
||||
if tcx.features().effects && trait_ref.skip_binder().args.host_effect_param().is_some() {
|
||||
let generics = tcx.generics_of(trait_ref.def_id());
|
||||
let Some(host_index) = generics.host_effect_index else { return };
|
||||
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
|
||||
trait_ref.args =
|
||||
tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
|
||||
if host_index == n { tcx.consts.true_.into() } else { arg }
|
||||
}));
|
||||
trait_ref
|
||||
});
|
||||
|
||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_trait_bound_inner(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::ImplPolarity,
|
||||
) {
|
||||
self.clauses.push((
|
||||
trait_ref
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{sym, Span, DUMMY_SP};
|
||||
|
||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
||||
|
@ -38,11 +38,38 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
|||
// an obligation and instead be skipped. Otherwise we'd use
|
||||
// `tcx.def_span(def_id);`
|
||||
let span = rustc_span::DUMMY_SP;
|
||||
result.predicates =
|
||||
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
|
||||
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
||||
let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
|
||||
// when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
|
||||
// because only implementing `Self: Trait<.., false>` is currently not possible.
|
||||
Some((
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
def_id,
|
||||
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
||||
if param.is_host_effect() {
|
||||
tcx.consts.true_.into()
|
||||
} else {
|
||||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
span,
|
||||
))));
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
result.predicates = tcx.arena.alloc_from_iter(
|
||||
result
|
||||
.predicates
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(std::iter::once((
|
||||
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
||||
span,
|
||||
)))
|
||||
.chain(non_const_bound),
|
||||
);
|
||||
}
|
||||
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
|
||||
result
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue