Skip to content

Commit 1c1ce2f

Browse files
committed
Add term to ExistentialProjection
Also prevent ICE when adding a const in associated const equality.
1 parent f396888 commit 1c1ce2f

File tree

35 files changed

+213
-71
lines changed

35 files changed

+213
-71
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
724724
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
725725
gate_all!(inline_const, "inline-const is experimental");
726726
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
727+
gate_all!(associated_const_equality, "associated const equality is incomplete");
727728

728729
// All uses of `gate_all!` below this point were added in #65742,
729730
// and subsequently disabled (with the non-early gating readded).

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,9 @@ fn push_debuginfo_type_name<'tcx>(
203203
let projection_bounds: SmallVec<[_; 4]> = trait_data
204204
.projection_bounds()
205205
.map(|bound| {
206-
let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder();
207-
(item_def_id, ty)
206+
let ExistentialProjection { item_def_id, term, .. } = bound.skip_binder();
207+
// FIXME(associated_const_equality): allow for consts here
208+
(item_def_id, term.ty().unwrap())
208209
})
209210
.collect();
210211

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ declare_features! (
288288
(active, asm_sym, "1.58.0", Some(72016), None),
289289
/// Allows the `may_unwind` option in inline assembly.
290290
(active, asm_unwind, "1.58.0", Some(72016), None),
291+
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
292+
(active, associated_const_equality, "1.58.0", Some(92827), None),
291293
/// Allows the user of associated type bounds.
292294
(active, associated_type_bounds, "1.34.0", Some(52662), None),
293295
/// Allows associated type defaults.

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError;
6969
use rustc_middle::ty::{
7070
self,
7171
subst::{GenericArgKind, Subst, SubstsRef},
72-
Region, Term, Ty, TyCtxt, TypeFoldable,
72+
Region, Ty, TyCtxt, TypeFoldable,
7373
};
7474
use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
7575
use rustc_target::spec::abi;
@@ -1780,11 +1780,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17801780
{
17811781
if projection_predicate.projection_ty.item_def_id == item_def_id {
17821782
// We don't account for multiple `Future::Output = Ty` contraints.
1783-
match projection_predicate.term {
1784-
Term::Ty(ty) => return Some(ty),
1785-
// Can return None, but not sure if that makes sense?
1786-
Term::Const(_c) => todo!(),
1787-
}
1783+
return projection_predicate.term.ty();
17881784
}
17891785
}
17901786
}

compiler/rustc_middle/src/ty/diagnostics.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind};
44
use crate::ty::TyKind::*;
55
use crate::ty::{
66
ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy,
7-
ProjectionTy, TyCtxt, TyS, TypeAndMut,
7+
ProjectionTy, Term, TyCtxt, TyS, TypeAndMut,
88
};
99

1010
use rustc_errors::{Applicability, DiagnosticBuilder};
@@ -105,8 +105,14 @@ impl<'tcx> TyS<'tcx> {
105105
ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => {
106106
substs.iter().all(generic_arg_is_suggestible)
107107
}
108-
ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => {
109-
ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible)
108+
ExistentialPredicate::Projection(ExistentialProjection {
109+
substs, term, ..
110+
}) => {
111+
let term_is_suggestable = match term {
112+
Term::Ty(ty) => ty.is_suggestable(),
113+
Term::Const(c) => const_is_suggestable(c.val),
114+
};
115+
term_is_suggestable && substs.iter().all(generic_arg_is_suggestible)
110116
}
111117
_ => true,
112118
}),

compiler/rustc_middle/src/ty/flags.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,10 @@ impl FlagComputation {
320320

321321
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
322322
self.add_substs(projection.substs);
323-
self.add_ty(projection.ty);
323+
match projection.term {
324+
ty::Term::Ty(ty) => self.add_ty(ty),
325+
ty::Term::Const(ct) => self.add_const(ct),
326+
}
324327
}
325328

326329
fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ pub struct CoercePredicate<'tcx> {
795795
}
796796
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
797797

798-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
798+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
799799
#[derive(HashStable, TypeFoldable)]
800800
pub enum Term<'tcx> {
801801
Ty(Ty<'tcx>),

compiler/rustc_middle/src/ty/print/pretty.rs

+20-18
Original file line numberDiff line numberDiff line change
@@ -905,29 +905,27 @@ pub trait PrettyPrinter<'tcx>:
905905
}
906906

907907
for (assoc_item_def_id, term) in assoc_items {
908-
let ty = match term.skip_binder() {
909-
Term::Ty(ty) => ty,
910-
Term::Const(c) => {
911-
p!(print(c));
912-
continue;
913-
}
914-
};
915908
if !first {
916909
p!(", ");
917910
}
918911
p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident));
919912

920-
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
921-
match ty.kind() {
922-
ty::Projection(ty::ProjectionTy { item_def_id, .. })
923-
if Some(*item_def_id) == self.tcx().lang_items().generator_return() =>
924-
{
925-
p!("[async output]")
913+
match term.skip_binder() {
914+
Term::Ty(ty) => {
915+
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
916+
if matches!(
917+
ty.kind(), ty::Projection(ty::ProjectionTy { item_def_id, .. })
918+
if Some(*item_def_id) == self.tcx().lang_items().generator_return()
919+
) {
920+
p!("[async output]")
921+
} else {
922+
p!(print(ty))
923+
}
926924
}
927-
_ => {
928-
p!(print(ty))
925+
Term::Const(c) => {
926+
p!(print(c));
929927
}
930-
}
928+
};
931929

932930
first = false;
933931
}
@@ -1031,7 +1029,11 @@ pub trait PrettyPrinter<'tcx>:
10311029
let mut projections = predicates.projection_bounds();
10321030
if let (Some(proj), None) = (projections.next(), projections.next()) {
10331031
let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
1034-
p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty));
1032+
p!(pretty_fn_sig(
1033+
&tys,
1034+
false,
1035+
proj.skip_binder().term.ty().expect("Return type was a const")
1036+
));
10351037
resugared = true;
10361038
}
10371039
}
@@ -2454,7 +2456,7 @@ define_print_and_forward_display! {
24542456

24552457
ty::ExistentialProjection<'tcx> {
24562458
let name = cx.tcx().associated_item(self.item_def_id).ident;
2457-
p!(write("{} = ", name), print(self.ty))
2459+
p!(write("{} = ", name), print(self.term))
24582460
}
24592461

24602462
ty::ExistentialPredicate<'tcx> {

compiler/rustc_middle/src/ty/relate.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -291,19 +291,19 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
291291
b.item_def_id,
292292
)))
293293
} else {
294-
let ty = relation.relate_with_variance(
294+
let term = relation.relate_with_variance(
295295
ty::Invariant,
296296
ty::VarianceDiagInfo::default(),
297-
a.ty,
298-
b.ty,
297+
a.term,
298+
b.term,
299299
)?;
300300
let substs = relation.relate_with_variance(
301301
ty::Invariant,
302302
ty::VarianceDiagInfo::default(),
303303
a.substs,
304304
b.substs,
305305
)?;
306-
Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
306+
Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
307307
}
308308
}
309309
}

compiler/rustc_middle/src/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
423423
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
424424
tcx.lift(self.substs).map(|substs| ty::ExistentialProjection {
425425
substs,
426-
ty: tcx.lift(self.ty).expect("type must lift when substs do"),
426+
term: tcx.lift(self.term).expect("type must lift when substs do"),
427427
item_def_id: self.item_def_id,
428428
})
429429
}

compiler/rustc_middle/src/ty/sty.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ impl From<BoundVar> for BoundTy {
15401540
pub struct ExistentialProjection<'tcx> {
15411541
pub item_def_id: DefId,
15421542
pub substs: SubstsRef<'tcx>,
1543-
pub ty: Ty<'tcx>,
1543+
pub term: Term<'tcx>,
15441544
}
15451545

15461546
pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>;
@@ -1570,7 +1570,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
15701570
item_def_id: self.item_def_id,
15711571
substs: tcx.mk_substs_trait(self_ty, self.substs),
15721572
},
1573-
term: self.ty.into(),
1573+
term: self.term,
15741574
}
15751575
}
15761576

@@ -1580,15 +1580,11 @@ impl<'tcx> ExistentialProjection<'tcx> {
15801580
) -> Self {
15811581
// Assert there is a Self.
15821582
projection_predicate.projection_ty.substs.type_at(0);
1583-
let ty = match projection_predicate.term {
1584-
Term::Ty(ty) => ty,
1585-
Term::Const(_c) => unimplemented!(),
1586-
};
15871583

15881584
Self {
15891585
item_def_id: projection_predicate.projection_ty.item_def_id,
15901586
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
1591-
ty,
1587+
term: projection_predicate.term,
15921588
}
15931589
}
15941590
}

compiler/rustc_middle/src/ty/walk.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,18 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
157157
stack.extend(obj.iter().rev().flat_map(|predicate| {
158158
let (substs, opt_ty) = match predicate.skip_binder() {
159159
ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
160-
ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)),
160+
ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)),
161161
ty::ExistentialPredicate::AutoTrait(_) =>
162162
// Empty iterator
163163
{
164164
(ty::InternalSubsts::empty(), None)
165165
}
166166
};
167167

168-
substs.iter().rev().chain(opt_ty.map(|ty| ty.into()))
168+
substs.iter().rev().chain(opt_ty.map(|term| match term {
169+
ty::Term::Ty(ty) => ty.into(),
170+
ty::Term::Const(ct) => ct.into(),
171+
}))
169172
}));
170173
}
171174
ty::Adt(_, substs)

compiler/rustc_parse/src/parser/path.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,10 @@ impl<'a> Parser<'a> {
505505
let span = ident.span.to(self.prev_token.span);
506506
let term = match arg {
507507
Some(GenericArg::Type(ty)) => ty.into(),
508-
Some(GenericArg::Const(c)) => c.into(),
508+
Some(GenericArg::Const(c)) => {
509+
self.sess.gated_spans.gate(sym::associated_const_equality, span);
510+
c.into()
511+
}
509512
Some(GenericArg::Lifetime(lt)) => {
510513
self.struct_span_err(span, "associated lifetimes are not supported")
511514
.span_label(lt.ident.span, "the lifetime is given here")

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ symbols! {
343343
assert_receiver_is_total_eq,
344344
assert_uninit_valid,
345345
assert_zero_valid,
346+
associated_const_equality,
346347
associated_consts,
347348
associated_type_bounds,
348349
associated_type_defaults,

compiler/rustc_symbol_mangling/src/v0.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
559559
let name = cx.tcx.associated_item(projection.item_def_id).ident;
560560
cx.push("p");
561561
cx.push_ident(name.as_str());
562-
cx = projection.ty.print(cx)?;
562+
cx = match projection.term {
563+
ty::Term::Ty(ty) => ty.print(cx),
564+
ty::Term::Const(c) => c.print(cx),
565+
}?;
563566
}
564567
ty::ExistentialPredicate::AutoTrait(def_id) => {
565568
cx = cx.print_def_path(*def_id, &[])?;

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
756756
// when we started out trying to unify
757757
// some inference variables. See the comment above
758758
// for more infomration
759-
if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types())
760-
{
759+
if p.term().skip_binder().ty().has_infer_types() {
761760
if !self.evaluate_nested_obligations(
762761
ty,
763762
v.into_iter(),
@@ -779,7 +778,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
779778
// However, we should always make progress (either by generating
780779
// subobligations or getting an error) when we started off with
781780
// inference variables
782-
if p.term().skip_binder().ty().has_infer_types() {
781+
if p.term().skip_binder().has_infer_types() {
783782
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
784783
}
785784
}

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
13141314
| ObligationCauseCode::ObjectCastObligation(_)
13151315
| ObligationCauseCode::OpaqueType
13161316
);
1317-
// FIXME(...): Handle Consts here
1317+
// FIXME(associated_const_equality): Handle Consts here
13181318
let data_ty = data.term.ty().unwrap();
13191319
if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
13201320
is_normalized_ty_expected,

compiler/rustc_trait_selection/src/traits/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ fn object_ty_for_trait<'tcx>(
571571
// `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
572572
super_trait_ref.map_bound(|super_trait_ref| {
573573
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
574-
ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
574+
term: tcx.mk_projection(item.def_id, super_trait_ref.substs).into(),
575575
item_def_id: item.def_id,
576576
substs: super_trait_ref.substs,
577577
})

compiler/rustc_trait_selection/src/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ fn project_and_unify_type<'cx, 'tcx>(
212212
debug!(?normalized_ty, ?obligations, "project_and_unify_type result");
213213

214214
let infcx = selcx.infcx();
215-
// FIXME(...): Handle consts here as well as types.
215+
// FIXME(associated_const_equality): Handle consts here as well as types.
216216
let obligation_pred_ty = obligation.predicate.term.ty().unwrap();
217217
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) {
218218
Ok(InferOk { obligations: inferred_obligations, value: () }) => {

compiler/rustc_traits/src/chalk/lowering.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
226226
for rustc_middle::ty::ProjectionPredicate<'tcx>
227227
{
228228
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInterner<'tcx>> {
229+
// FIXME(associated_const_equality): teach chalk about terms for alias eq.
229230
chalk_ir::AliasEq {
230231
ty: self.term.ty().unwrap().lower_into(interner),
231232
alias: self.projection_ty.lower_into(interner),
@@ -663,7 +664,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
663664
.mk_substs_trait(self_ty, predicate.substs)
664665
.lower_into(interner),
665666
}),
666-
ty: predicate.ty.lower_into(interner),
667+
// FIXME(associated_const_equality): teach chalk about terms for alias eq.
668+
ty: predicate.term.ty().unwrap().lower_into(interner),
667669
}),
668670
),
669671
ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new(

compiler/rustc_typeck/src/astconv/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1136,9 +1136,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11361136
.associated_items(candidate.def_id())
11371137
.filter_by_name_unhygienic(assoc_ident.name)
11381138
.find(|i| {
1139-
i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident
1139+
(i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const)
1140+
&& i.ident.normalize_to_macros_2_0() == assoc_ident
11401141
})
11411142
.expect("missing associated type");
1143+
// FIXME(associated_const_equality): need to handle assoc_consts here as well.
1144+
if assoc_ty.kind == ty::AssocKind::Const {
1145+
tcx.sess
1146+
.struct_span_err(path_span, &format!("associated const equality is incomplete"))
1147+
.span_label(path_span, "cannot yet relate associated const")
1148+
.emit();
1149+
return Err(ErrorReported);
1150+
}
11421151

11431152
if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
11441153
tcx.sess

compiler/rustc_typeck/src/variance/constraints.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
308308
}
309309

310310
for projection in data.projection_bounds() {
311-
self.add_constraints_from_ty(
312-
current,
313-
projection.skip_binder().ty,
314-
self.invariant,
315-
);
311+
match projection.skip_binder().term {
312+
ty::Term::Ty(ty) => {
313+
self.add_constraints_from_ty(current, ty, self.invariant);
314+
}
315+
ty::Term::Const(c) => {
316+
self.add_constraints_from_const(current, c, self.invariant)
317+
}
318+
}
316319
}
317320
}
318321

src/etc/check_missing_items.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ def check_type(ty):
8383
check_type(arg["const"]["type"])
8484
for binding in args["angle_bracketed"]["bindings"]:
8585
if "equality" in binding["binding"]:
86-
check_type(binding["binding"]["equality"])
86+
term = binding["binding"]["equality"]
87+
if "type" in term: check_type(term["type"])
88+
elif "const" in term: check_type(term["const"])
8789
elif "constraint" in binding["binding"]:
8890
for bound in binding["binding"]["constraint"]:
8991
check_generic_bound(bound)

0 commit comments

Comments
 (0)