diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0cc74a1ac0b..89671788255 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -724,6 +724,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); + gate_all!(associated_const_equality, "associated const equality is incomplete"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 61322a6e556..9687fd09a53 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -203,8 +203,9 @@ fn push_debuginfo_type_name<'tcx>( let projection_bounds: SmallVec<[_; 4]> = trait_data .projection_bounds() .map(|bound| { - let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder(); - (item_def_id, ty) + let ExistentialProjection { item_def_id, term, .. } = bound.skip_binder(); + // FIXME(associated_const_equality): allow for consts here + (item_def_id, term.ty().unwrap()) }) .collect(); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index ebd12d6ab4e..47010ea3ab6 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -288,6 +288,8 @@ declare_features! ( (active, asm_sym, "1.58.0", Some(72016), None), /// Allows the `may_unwind` option in inline assembly. (active, asm_unwind, "1.58.0", Some(72016), None), + /// Allows users to enforce equality of associated constants `TraitImpl`. + (active, associated_const_equality, "1.58.0", Some(92827), None), /// Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f1e99faba01..e98b9c3b03c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, subst::{GenericArgKind, Subst, SubstsRef}, - Region, Term, Ty, TyCtxt, TypeFoldable, + Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1780,11 +1780,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { if projection_predicate.projection_ty.item_def_id == item_def_id { // We don't account for multiple `Future::Output = Ty` contraints. - match projection_predicate.term { - Term::Ty(ty) => return Some(ty), - // Can return None, but not sure if that makes sense? - Term::Const(_c) => todo!(), - } + return projection_predicate.term.ty(); } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index ee00f6c62f3..b4c9cc7782c 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -4,7 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::TyKind::*; use crate::ty::{ ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, - ProjectionTy, TyCtxt, TyS, TypeAndMut, + ProjectionTy, Term, TyCtxt, TyS, TypeAndMut, }; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -105,8 +105,14 @@ impl<'tcx> TyS<'tcx> { ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { substs.iter().all(generic_arg_is_suggestible) } - ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => { - ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible) + ExistentialPredicate::Projection(ExistentialProjection { + substs, term, .. + }) => { + let term_is_suggestable = match term { + Term::Ty(ty) => ty.is_suggestable(), + Term::Const(c) => const_is_suggestable(c.val), + }; + term_is_suggestable && substs.iter().all(generic_arg_is_suggestible) } _ => true, }), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index be9021dc619..f06a1b09cd8 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -320,7 +320,10 @@ impl FlagComputation { fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); - self.add_ty(projection.ty); + match projection.term { + ty::Term::Ty(ty) => self.add_ty(ty), + ty::Term::Const(ct) => self.add_const(ct), + } } fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 42e6f3f6ef5..4bc3e23f4a5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -795,7 +795,7 @@ pub struct CoercePredicate<'tcx> { } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] pub enum Term<'tcx> { Ty(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c6b03739927..bbdaf248a9e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -905,29 +905,27 @@ pub trait PrettyPrinter<'tcx>: } for (assoc_item_def_id, term) in assoc_items { - let ty = match term.skip_binder() { - Term::Ty(ty) => ty, - Term::Const(c) => { - p!(print(c)); - continue; - } - }; if !first { p!(", "); } p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks - match ty.kind() { - ty::Projection(ty::ProjectionTy { item_def_id, .. }) - if Some(*item_def_id) == self.tcx().lang_items().generator_return() => - { - p!("[async output]") + match term.skip_binder() { + Term::Ty(ty) => { + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks + if matches!( + ty.kind(), ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if Some(*item_def_id) == self.tcx().lang_items().generator_return() + ) { + p!("[async output]") + } else { + p!(print(ty)) + } } - _ => { - p!(print(ty)) + Term::Const(c) => { + p!(print(c)); } - } + }; first = false; } @@ -1031,7 +1029,11 @@ pub trait PrettyPrinter<'tcx>: 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.skip_binder().ty)); + p!(pretty_fn_sig( + &tys, + false, + proj.skip_binder().term.ty().expect("Return type was a const") + )); resugared = true; } } @@ -2454,7 +2456,7 @@ define_print_and_forward_display! { ty::ExistentialProjection<'tcx> { let name = cx.tcx().associated_item(self.item_def_id).ident; - p!(write("{} = ", name), print(self.ty)) + p!(write("{} = ", name), print(self.term)) } ty::ExistentialPredicate<'tcx> { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index bd6c24445ef..bb040acd270 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -291,11 +291,11 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { b.item_def_id, ))) } else { - let ty = relation.relate_with_variance( + let term = relation.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), - a.ty, - b.ty, + a.term, + b.term, )?; let substs = relation.relate_with_variance( ty::Invariant, @@ -303,7 +303,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { a.substs, b.substs, )?; - Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }) + Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term }) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 3cbea92ae67..1c5bc7860db 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { tcx.lift(self.substs).map(|substs| ty::ExistentialProjection { substs, - ty: tcx.lift(self.ty).expect("type must lift when substs do"), + term: tcx.lift(self.term).expect("type must lift when substs do"), item_def_id: self.item_def_id, }) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ffc339f3588..20db25f7899 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1540,7 +1540,7 @@ impl From for BoundTy { pub struct ExistentialProjection<'tcx> { pub item_def_id: DefId, pub substs: SubstsRef<'tcx>, - pub ty: Ty<'tcx>, + pub term: Term<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; @@ -1570,7 +1570,7 @@ impl<'tcx> ExistentialProjection<'tcx> { item_def_id: self.item_def_id, substs: tcx.mk_substs_trait(self_ty, self.substs), }, - term: self.ty.into(), + term: self.term, } } @@ -1580,15 +1580,11 @@ impl<'tcx> ExistentialProjection<'tcx> { ) -> Self { // Assert there is a Self. projection_predicate.projection_ty.substs.type_at(0); - let ty = match projection_predicate.term { - Term::Ty(ty) => ty, - Term::Const(_c) => unimplemented!(), - }; Self { item_def_id: projection_predicate.projection_ty.item_def_id, substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]), - ty, + term: projection_predicate.term, } } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 6808316a230..38aa7633385 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -157,7 +157,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), - ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), + ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator { @@ -165,7 +165,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } }; - substs.iter().rev().chain(opt_ty.map(|ty| ty.into())) + substs.iter().rev().chain(opt_ty.map(|term| match term { + ty::Term::Ty(ty) => ty.into(), + ty::Term::Const(ct) => ct.into(), + })) })); } ty::Adt(_, substs) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 531cac1f57e..4e60b7593c6 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -505,7 +505,10 @@ impl<'a> Parser<'a> { let span = ident.span.to(self.prev_token.span); let term = match arg { Some(GenericArg::Type(ty)) => ty.into(), - Some(GenericArg::Const(c)) => c.into(), + Some(GenericArg::Const(c)) => { + self.sess.gated_spans.gate(sym::associated_const_equality, span); + c.into() + } Some(GenericArg::Lifetime(lt)) => { self.struct_span_err(span, "associated lifetimes are not supported") .span_label(lt.ident.span, "the lifetime is given here") diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8020893e166..2ff888bfb48 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -343,6 +343,7 @@ symbols! { assert_receiver_is_total_eq, assert_uninit_valid, assert_zero_valid, + associated_const_equality, associated_consts, associated_type_bounds, associated_type_defaults, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 14e12bed59e..809b9732529 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -559,7 +559,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { 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)?; + cx = match projection.term { + ty::Term::Ty(ty) => ty.print(cx), + ty::Term::Const(c) => c.print(cx), + }?; } ty::ExistentialPredicate::AutoTrait(def_id) => { cx = cx.print_def_path(*def_id, &[])?; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 8a33d26fa86..e2afea76b77 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -756,8 +756,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // when we started out trying to unify // some inference variables. See the comment above // for more infomration - if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types()) - { + if p.term().skip_binder().ty().has_infer_types() { if !self.evaluate_nested_obligations( ty, v.into_iter(), @@ -779,7 +778,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // However, we should always make progress (either by generating // subobligations or getting an error) when we started off with // inference variables - if p.term().skip_binder().ty().has_infer_types() { + if p.term().skip_binder().has_infer_types() { panic!("Unexpected result when selecting {:?} {:?}", ty, obligation) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 43a961c5c91..65385851d05 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1314,7 +1314,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::OpaqueType ); - // FIXME(...): Handle Consts here + // FIXME(associated_const_equality): Handle Consts here let data_ty = data.term.ty().unwrap(); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( is_normalized_ty_expected, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 185d64eab70..7bfedecbdc7 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -571,7 +571,7 @@ fn object_ty_for_trait<'tcx>( // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`. super_trait_ref.map_bound(|super_trait_ref| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { - ty: tcx.mk_projection(item.def_id, super_trait_ref.substs), + term: tcx.mk_projection(item.def_id, super_trait_ref.substs).into(), item_def_id: item.def_id, substs: super_trait_ref.substs, }) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4b53b624c72..2bbdb72a4fb 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -212,7 +212,7 @@ fn project_and_unify_type<'cx, 'tcx>( debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); let infcx = selcx.infcx(); - // FIXME(...): Handle consts here as well as types. + // FIXME(associated_const_equality): Handle consts here as well as types. let obligation_pred_ty = obligation.predicate.term.ty().unwrap(); match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index dd98e4ae81b..67d0ba39667 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -226,6 +226,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> for rustc_middle::ty::ProjectionPredicate<'tcx> { fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { + // FIXME(associated_const_equality): teach chalk about terms for alias eq. chalk_ir::AliasEq { ty: self.term.ty().unwrap().lower_into(interner), alias: self.projection_ty.lower_into(interner), @@ -663,7 +664,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders chalk_ir::Binders::new( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index a13eaa6f178..a1f1adb8058 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1136,9 +1136,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) .find(|i| { - i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident + (i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const) + && i.ident.normalize_to_macros_2_0() == assoc_ident }) .expect("missing associated type"); + // FIXME(associated_const_equality): need to handle assoc_consts here as well. + if assoc_ty.kind == ty::AssocKind::Const { + tcx.sess + .struct_span_err(path_span, &format!("associated const equality is incomplete")) + .span_label(path_span, "cannot yet relate associated const") + .emit(); + return Err(ErrorReported); + } if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { tcx.sess diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index b2b607a2ffc..7c504a0d89c 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -308,11 +308,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } for projection in data.projection_bounds() { - self.add_constraints_from_ty( - current, - projection.skip_binder().ty, - self.invariant, - ); + match projection.skip_binder().term { + ty::Term::Ty(ty) => { + self.add_constraints_from_ty(current, ty, self.invariant); + } + ty::Term::Const(c) => { + self.add_constraints_from_const(current, c, self.invariant) + } + } } } diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index 7ed317c778f..de1717b3f3f 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -83,7 +83,9 @@ def check_type(ty): check_type(arg["const"]["type"]) for binding in args["angle_bracketed"]["bindings"]: if "equality" in binding["binding"]: - check_type(binding["binding"]["equality"]) + term = binding["binding"]["equality"] + if "type" in term: check_type(term["type"]) + elif "const" in term: check_type(term["const"]) elif "constraint" in binding["binding"]: for bound in binding["binding"]["constraint"]: check_generic_bound(bound) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6a3cdcc2c20..e759baa0458 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1523,7 +1523,7 @@ impl<'tcx> Clean for Ty<'tcx> { bindings.push(TypeBinding { name: cx.tcx.associated_item(pb.item_def_id()).ident.name, kind: TypeBindingKind::Equality { - term: pb.skip_binder().ty.clean(cx).into(), + term: pb.skip_binder().term.clean(cx).into(), }, }); } diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs index 582d0a69229..9e6bfa346ec 100644 --- a/src/test/ui/associated-consts/assoc-const.rs +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -1,5 +1,3 @@ -// run-pass - pub trait Foo { const N: usize; } @@ -14,6 +12,10 @@ const TEST:usize = 3; fn foo>() {} +//~^ ERROR associated const equality is incomplete +//~| ERROR associated const equality is incomplete fn bar>() {} +//~^ ERROR associated const equality is incomplete +//~| ERROR associated const equality is incomplete fn main() {} diff --git a/src/test/ui/associated-consts/assoc-const.stderr b/src/test/ui/associated-consts/assoc-const.stderr new file mode 100644 index 00000000000..07da190bc8f --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const.stderr @@ -0,0 +1,33 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/assoc-const.rs:14:15 + | +LL | fn foo>() {} + | ^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/assoc-const.rs:17:15 + | +LL | fn bar>() {} + | ^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:14:15 + | +LL | fn foo>() {} + | ^^^ cannot yet relate associated const + +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:17:15 + | +LL | fn bar>() {} + | ^^^^^^^^ cannot yet relate associated const + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs index 32b08fb97f2..b126b24853f 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -9,6 +9,7 @@ const T: usize = 42; impl Foo for Bar { //~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied //~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] } diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index 455f6f61aad..59ba054aa11 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -1,3 +1,12 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/issue-89013-no-kw.rs:9:6 | @@ -20,7 +29,7 @@ error[E0229]: associated type bindings are not allowed here LL | impl Foo for Bar { | ^^^^^ associated type not allowed here -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0229. +Some errors have detailed explanations: E0107, E0229, E0658. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs index 97c22fa7862..9431779faf8 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -10,6 +10,7 @@ impl Foo for Bar { //~^ ERROR expected lifetime, type, or constant, found keyword `const` //~| ERROR this trait takes 1 generic //~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] } diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr index 57108d718cf..9d473992670 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -10,6 +10,15 @@ LL - impl Foo for Bar { LL + impl Foo for Bar { | +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/issue-89013.rs:9:6 | @@ -32,7 +41,7 @@ error[E0229]: associated type bindings are not allowed here LL | impl Foo for Bar { | ^^^^^^^^^^^ associated type not allowed here -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0107, E0229. +Some errors have detailed explanations: E0107, E0229, E0658. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs new file mode 100644 index 00000000000..b51ead2a188 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs @@ -0,0 +1,16 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for Demo { + const A: usize = 32; +} + +fn foo>() {} +//~^ ERROR associated const equality +//~| ERROR associated const equality + +fn main() { + foo::(); +} diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr new file mode 100644 index 00000000000..f4db49c4af8 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -0,0 +1,18 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/feature-gate-associated_const_equality.rs:10:28 + | +LL | fn foo>() {} + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: associated const equality is incomplete + --> $DIR/feature-gate-associated_const_equality.rs:10:28 + | +LL | fn foo>() {} + | ^^^^ cannot yet relate associated const + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/recover-assoc-const-constraint.rs b/src/test/ui/parser/recover-assoc-const-constraint.rs index 3f7423dcb8e..1453e6cb5cd 100644 --- a/src/test/ui/parser/recover-assoc-const-constraint.rs +++ b/src/test/ui/parser/recover-assoc-const-constraint.rs @@ -1,9 +1,9 @@ -// run-pass - #[cfg(FALSE)] fn syntax() { bar::(); + //~^ ERROR associated const equality is incomplete bar::(); + //~^ ERROR associated const equality is incomplete } fn main() {} diff --git a/src/test/ui/parser/recover-assoc-const-constraint.stderr b/src/test/ui/parser/recover-assoc-const-constraint.stderr new file mode 100644 index 00000000000..2d36ce4e986 --- /dev/null +++ b/src/test/ui/parser/recover-assoc-const-constraint.stderr @@ -0,0 +1,21 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:3:11 + | +LL | bar::(); + | ^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:5:11 + | +LL | bar::(); + | ^^^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 9d5f790e809..5de30129266 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -211,7 +211,7 @@ impl Rewrite for ast::AssocConstraintKind { match self { ast::AssocConstraintKind::Equality { term } => match term { Term::Ty(ty) => ty.rewrite(context, shape), - Term::Const(c) => c.rewrite(context,shape), + Term::Const(c) => c.rewrite(context, shape), }, ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), }