Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d215b0b

Browse files
committedOct 18, 2023
Use elaboration to turn ~const bounds into non-const bounds
1 parent 09df610 commit d215b0b

File tree

6 files changed

+71
-107
lines changed

6 files changed

+71
-107
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/mod.rs

+48-42
Original file line numberDiff line numberDiff line change
@@ -1084,15 +1084,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10841084
where
10851085
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
10861086
{
1087-
let mut matching_candidates = all_candidates().filter(|r| {
1088-
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
1089-
});
1090-
let mut const_candidates = all_candidates().filter(|r| {
1091-
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
1092-
});
1087+
let mut matching_candidates = all_candidates()
1088+
.filter(|r| {
1089+
self.trait_defines_associated_item_named(
1090+
r.def_id(),
1091+
ty::AssocKind::Type,
1092+
assoc_name,
1093+
)
1094+
})
1095+
// For the purposes of an associated type, we only care
1096+
// about supertraits where the host effect is set to true.
1097+
.filter(|trait_ref| {
1098+
let tcx = self.tcx();
1099+
let generics = tcx.generics_of(trait_ref.def_id());
1100+
generics.host_effect_index.map_or(true, |idx| {
1101+
trait_ref.skip_binder().args.const_at(idx) == tcx.consts.true_
1102+
})
1103+
});
1104+
let mut const_candidates = all_candidates()
1105+
.filter(|r| {
1106+
self.trait_defines_associated_item_named(
1107+
r.def_id(),
1108+
ty::AssocKind::Const,
1109+
assoc_name,
1110+
)
1111+
})
1112+
// For the purposes of an associated const, we only care
1113+
// about supertraits where the host effect is set to true.
1114+
.filter(|trait_ref| {
1115+
let tcx = self.tcx();
1116+
let generics = tcx.generics_of(trait_ref.def_id());
1117+
generics.host_effect_index.map_or(true, |idx| {
1118+
trait_ref.skip_binder().args.const_at(idx) == tcx.consts.true_
1119+
})
1120+
});
10931121

1094-
let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next())
1095-
{
1122+
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
10961123
(Some(bound), _) => (bound, matching_candidates.next()),
10971124
(None, Some(bound)) => (bound, const_candidates.next()),
10981125
(None, None) => {
@@ -1108,37 +1135,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11081135
};
11091136
debug!(?bound);
11101137

1111-
// look for a candidate that is not the same as our first bound, disregarding
1112-
// whether the bound is const.
1113-
while let Some(mut bound2) = next_cand {
1114-
debug!(?bound2);
1115-
let tcx = self.tcx();
1116-
if bound2.bound_vars() != bound.bound_vars() {
1117-
break;
1118-
}
1119-
1120-
let generics = tcx.generics_of(bound.def_id());
1121-
let Some(host_index) = generics.host_effect_index else { break };
1122-
1123-
// always return the bound that contains the host param.
1124-
if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() {
1125-
(bound, bound2) = (bound2, bound);
1126-
}
1127-
1128-
let unconsted_args = bound
1129-
.skip_binder()
1130-
.args
1131-
.iter()
1132-
.enumerate()
1133-
.map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg });
1134-
1135-
if unconsted_args.eq(bound2.skip_binder().args.iter()) {
1136-
next_cand = matching_candidates.next().or_else(|| const_candidates.next());
1137-
} else {
1138-
break;
1139-
}
1140-
}
1141-
11421138
if let Some(bound2) = next_cand {
11431139
debug!(?bound2);
11441140

@@ -1226,9 +1222,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12261222
assoc_name: Ident,
12271223
span: Span,
12281224
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
1229-
let mut matching_candidates = all_candidates.filter(|r| {
1230-
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
1231-
});
1225+
let mut matching_candidates = all_candidates
1226+
.filter(|r| {
1227+
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
1228+
})
1229+
// For the purposes of an RTN bound, we only care
1230+
// about supertraits where the host effect is set to true.
1231+
.filter(|trait_ref| {
1232+
let tcx = self.tcx();
1233+
let generics = tcx.generics_of(trait_ref.def_id());
1234+
generics.host_effect_index.map_or(true, |idx| {
1235+
trait_ref.skip_binder().args.const_at(idx) == tcx.consts.true_
1236+
})
1237+
});
12321238

12331239
let candidate = match matching_candidates.next() {
12341240
Some(candidate) => candidate,

‎compiler/rustc_hir_analysis/src/bounds.rs

-27
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,6 @@ impl<'tcx> Bounds<'tcx> {
4343
trait_ref: ty::PolyTraitRef<'tcx>,
4444
span: Span,
4545
polarity: ty::ImplPolarity,
46-
) {
47-
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
48-
49-
// if we have a host param, we push an unconst trait bound in addition
50-
// to the const one.
51-
// FIXME(effects) we should find a better way than name matching
52-
if tcx.features().effects && trait_ref.skip_binder().args.host_effect_param().is_some() {
53-
let generics = tcx.generics_of(trait_ref.def_id());
54-
let Some(host_index) = generics.host_effect_index else { return };
55-
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
56-
trait_ref.args =
57-
tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
58-
if host_index == n { tcx.consts.true_.into() } else { arg }
59-
}));
60-
trait_ref
61-
});
62-
63-
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
64-
}
65-
}
66-
67-
fn push_trait_bound_inner(
68-
&mut self,
69-
tcx: TyCtxt<'tcx>,
70-
trait_ref: ty::PolyTraitRef<'tcx>,
71-
span: Span,
72-
polarity: ty::ImplPolarity,
7346
) {
7447
self.clauses.push((
7548
trait_ref

‎compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+5-32
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor};
1111
use rustc_middle::ty::{self, Ty, TyCtxt};
1212
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
1313
use rustc_span::symbol::Ident;
14-
use rustc_span::{sym, Span, DUMMY_SP};
14+
use rustc_span::{Span, DUMMY_SP};
1515

1616
/// Returns a list of all type predicates (explicit and implicit) for the definition with
1717
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -38,38 +38,11 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
3838
// an obligation and instead be skipped. Otherwise we'd use
3939
// `tcx.def_span(def_id);`
4040
let span = rustc_span::DUMMY_SP;
41-
let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
42-
// when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
43-
// because only implementing `Self: Trait<.., false>` is currently not possible.
44-
Some((
45-
ty::TraitRef::new(
46-
tcx,
47-
def_id,
48-
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
49-
if param.is_host_effect() {
50-
tcx.consts.true_.into()
51-
} else {
52-
tcx.mk_param_from_def(param)
53-
}
54-
}),
55-
)
56-
.to_predicate(tcx),
41+
result.predicates =
42+
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
43+
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
5744
span,
58-
))
59-
} else {
60-
None
61-
};
62-
result.predicates = tcx.arena.alloc_from_iter(
63-
result
64-
.predicates
65-
.iter()
66-
.copied()
67-
.chain(std::iter::once((
68-
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
69-
span,
70-
)))
71-
.chain(non_const_bound),
72-
);
45+
))));
7346
}
7447
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
7548
result

‎compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
221221
let item_def_id = tcx.hir().ty_param_owner(def_id);
222222
let generics = tcx.generics_of(item_def_id);
223223
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
224-
// HACK(eddyb) should get the original `Span`.
225-
let span = tcx.def_span(def_id);
226224
ty::GenericPredicates {
227225
parent: None,
228226
predicates: tcx.arena.alloc_from_iter(
229227
self.param_env.caller_bounds().iter().filter_map(|predicate| {
230228
match predicate.kind().skip_binder() {
231229
ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => {
230+
// HACK(eddyb) should get the original `Span`.
231+
let span = tcx.def_span(def_id);
232232
Some((predicate, span))
233233
}
234234
_ => None,

‎compiler/rustc_infer/src/traits/util.rs

+16
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,22 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
274274
});
275275
debug!(?data, ?obligations, "super_predicates");
276276
self.extend_deduped(obligations);
277+
278+
// Also elaborate `~const Trait` into `Trait`.
279+
let generics = tcx.generics_of(data.def_id());
280+
if let Some(host_param_idx) = generics.host_effect_index
281+
&& data.trait_ref.args.const_at(host_param_idx) != tcx.consts.true_
282+
{
283+
let mut trait_predicate_with_host = data;
284+
trait_predicate_with_host.trait_ref.args = tcx.mk_args_from_iter(
285+
data.trait_ref.args.iter().enumerate().map(|(idx, arg)| {
286+
if idx == host_param_idx { tcx.consts.true_.into() } else { arg }
287+
}),
288+
);
289+
self.extend_deduped([
290+
elaboratable.child(trait_predicate_with_host.to_predicate(tcx))
291+
]);
292+
}
277293
}
278294
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => {
279295
// Currently, we do not elaborate WF predicates,

‎compiler/rustc_middle/src/ty/generics.rs

-4
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ impl GenericParamDef {
7979
}
8080
}
8181

82-
pub fn is_host_effect(&self) -> bool {
83-
matches!(self.kind, GenericParamDefKind::Const { is_host_effect: true, .. })
84-
}
85-
8682
pub fn default_value<'tcx>(
8783
&self,
8884
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)
Please sign in to comment.