Add term to ExistentialProjection
Also prevent ICE when adding a const in associated const equality.
This commit is contained in:
parent
f396888c4d
commit
1c1ce2fbda
35 changed files with 213 additions and 71 deletions
|
@ -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).
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<AssocConst=3>`.
|
||||
(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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}),
|
||||
|
|
|
@ -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<'_>) {
|
||||
|
|
|
@ -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>),
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -423,7 +423,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
|
|||
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1540,7 +1540,7 @@ impl From<BoundVar> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, &[])?;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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: () }) => {
|
||||
|
|
|
@ -226,6 +226,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
|
|||
for rustc_middle::ty::ProjectionPredicate<'tcx>
|
||||
{
|
||||
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInterner<'tcx>> {
|
||||
// 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::QuantifiedWhereClauses<Ru
|
|||
.mk_substs_trait(self_ty, predicate.substs)
|
||||
.lower_into(interner),
|
||||
}),
|
||||
ty: predicate.ty.lower_into(interner),
|
||||
// FIXME(associated_const_equality): teach chalk about terms for alias eq.
|
||||
ty: predicate.term.ty().unwrap().lower_into(interner),
|
||||
}),
|
||||
),
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1523,7 +1523,7 @@ impl<'tcx> Clean<Type> 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(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// run-pass
|
||||
|
||||
pub trait Foo {
|
||||
const N: usize;
|
||||
}
|
||||
|
@ -14,6 +12,10 @@ const TEST:usize = 3;
|
|||
|
||||
|
||||
fn foo<F: Foo<N=3>>() {}
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
//~| ERROR associated const equality is incomplete
|
||||
fn bar<F: Foo<N={TEST}>>() {}
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
//~| ERROR associated const equality is incomplete
|
||||
|
||||
fn main() {}
|
||||
|
|
33
src/test/ui/associated-consts/assoc-const.stderr
Normal file
33
src/test/ui/associated-consts/assoc-const.stderr
Normal file
|
@ -0,0 +1,33 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/assoc-const.rs:14:15
|
||||
|
|
||||
LL | fn foo<F: Foo<N=3>>() {}
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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<F: Foo<N={TEST}>>() {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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<F: Foo<N=3>>() {}
|
||||
| ^^^ cannot yet relate associated const
|
||||
|
||||
error: associated const equality is incomplete
|
||||
--> $DIR/assoc-const.rs:17:15
|
||||
|
|
||||
LL | fn bar<F: Foo<N={TEST}>>() {}
|
||||
| ^^^^^^^^ cannot yet relate associated const
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -9,6 +9,7 @@ const T: usize = 42;
|
|||
impl Foo<N = 3> 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]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/issue-89013-no-kw.rs:9:10
|
||||
|
|
||||
LL | impl Foo<N = 3> for Bar {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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<N = 3> 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`.
|
||||
|
|
|
@ -10,6 +10,7 @@ impl Foo<N = const 3> 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]
|
||||
}
|
||||
|
|
|
@ -10,6 +10,15 @@ LL - impl Foo<N = const 3> for Bar {
|
|||
LL + impl Foo<N = 3> for Bar {
|
||||
|
|
||||
|
||||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/issue-89013.rs:9:10
|
||||
|
|
||||
LL | impl Foo<N = const 3> for Bar {
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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<N = const 3> 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`.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
pub trait TraitWAssocConst {
|
||||
const A: usize;
|
||||
}
|
||||
pub struct Demo {}
|
||||
|
||||
impl TraitWAssocConst for Demo {
|
||||
const A: usize = 32;
|
||||
}
|
||||
|
||||
fn foo<A: TraitWAssocConst<A=32>>() {}
|
||||
//~^ ERROR associated const equality
|
||||
//~| ERROR associated const equality
|
||||
|
||||
fn main() {
|
||||
foo::<Demo>();
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/feature-gate-associated_const_equality.rs:10:28
|
||||
|
|
||||
LL | fn foo<A: TraitWAssocConst<A=32>>() {}
|
||||
| ^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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<A: TraitWAssocConst<A=32>>() {}
|
||||
| ^^^^ cannot yet relate associated const
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,9 +1,9 @@
|
|||
// run-pass
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
bar::<Item = 42>();
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
bar::<Item = { 42 }>();
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
21
src/test/ui/parser/recover-assoc-const-constraint.stderr
Normal file
21
src/test/ui/parser/recover-assoc-const-constraint.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/recover-assoc-const-constraint.rs:3:11
|
||||
|
|
||||
LL | bar::<Item = 42>();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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::<Item = { 42 }>();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/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`.
|
|
@ -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),
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue