MGCA: Support tuple expressions as direct const arguments
This commit is contained in:
parent
0aced202c2
commit
af76a2456d
18 changed files with 177 additions and 53 deletions
|
|
@ -2427,6 +2427,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
kind: hir::ConstArgKind::TupleCall(qpath, lowered_args),
|
||||
}
|
||||
}
|
||||
ExprKind::Tup(exprs) => {
|
||||
let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| {
|
||||
let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind {
|
||||
let def_id = self.local_def_id(anon_const.id);
|
||||
let def_kind = self.tcx.def_kind(def_id);
|
||||
assert_eq!(DefKind::AnonConst, def_kind);
|
||||
|
||||
self.lower_anon_const_to_const_arg(anon_const)
|
||||
} else {
|
||||
self.lower_expr_to_const_arg_direct(&expr)
|
||||
};
|
||||
|
||||
&*self.arena.alloc(expr)
|
||||
}));
|
||||
|
||||
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Tup(expr.span, exprs) }
|
||||
}
|
||||
ExprKind::Path(qself, path) => {
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
|
|
@ -2495,6 +2512,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
| ExprKind::Path(..)
|
||||
| ExprKind::Struct(..)
|
||||
| ExprKind::Call(..)
|
||||
| ExprKind::Tup(..)
|
||||
)
|
||||
{
|
||||
return self.lower_expr_to_const_arg_direct(expr);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
|
|||
|
||||
pub fn span(&self) -> Span {
|
||||
match self.kind {
|
||||
ConstArgKind::Tup(span, ..) => span,
|
||||
ConstArgKind::Struct(path, _) => path.span(),
|
||||
ConstArgKind::Path(path) => path.span(),
|
||||
ConstArgKind::TupleCall(path, _) => path.span(),
|
||||
|
|
@ -511,6 +512,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
|
|||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
#[repr(u8, C)]
|
||||
pub enum ConstArgKind<'hir, Unambig = ()> {
|
||||
Tup(Span, &'hir [&'hir ConstArg<'hir, Unambig>]),
|
||||
/// **Note:** Currently this is only used for bare const params
|
||||
/// (`N` where `fn foo<const N: usize>(...)`),
|
||||
/// not paths to any const (`N` where `const N: usize = ...`).
|
||||
|
|
|
|||
|
|
@ -1081,6 +1081,10 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
|
|||
let ConstArg { hir_id, kind } = const_arg;
|
||||
try_visit!(visitor.visit_id(*hir_id));
|
||||
match kind {
|
||||
ConstArgKind::Tup(_, exprs) => {
|
||||
walk_list!(visitor, visit_const_arg, *exprs);
|
||||
V::Result::output()
|
||||
}
|
||||
ConstArgKind::Struct(qpath, field_exprs) => {
|
||||
try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span()));
|
||||
|
||||
|
|
|
|||
|
|
@ -1493,9 +1493,10 @@ fn const_param_default<'tcx>(
|
|||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
let ct = icx
|
||||
.lowerer()
|
||||
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
||||
let ct = icx.lowerer().lower_const_arg(
|
||||
default_ct,
|
||||
FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args),
|
||||
);
|
||||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
|
||||
|
|
@ -1553,7 +1554,7 @@ fn const_of_item<'tcx>(
|
|||
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
let ct = icx
|
||||
.lowerer()
|
||||
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
||||
.lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args));
|
||||
if let Err(e) = icx.check_tainted_by_errors()
|
||||
&& !ct.references_error()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -259,17 +259,26 @@ impl AssocItemQSelf {
|
|||
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
|
||||
/// desired behavior.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FeedConstTy<'a, 'tcx> {
|
||||
/// Feed the type.
|
||||
///
|
||||
pub enum FeedConstTy<'tcx> {
|
||||
/// Feed the type to the (anno) const arg.
|
||||
WithTy(Ty<'tcx>),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
}
|
||||
|
||||
impl<'tcx> FeedConstTy<'tcx> {
|
||||
/// The `DefId` belongs to the const param that we are supplying
|
||||
/// this (anon) const arg to.
|
||||
///
|
||||
/// The list of generic args is used to instantiate the parameters
|
||||
/// used by the type of the const param specified by `DefId`.
|
||||
Param(DefId, &'a [ty::GenericArg<'tcx>]),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
pub fn with_type_of(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
generic_args: &[ty::GenericArg<'tcx>],
|
||||
) -> Self {
|
||||
Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -723,7 +732,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Ambig portions of `ConstArg` are handled in the match arm below
|
||||
.lower_const_arg(
|
||||
ct.as_unambig_ct(),
|
||||
FeedConstTy::Param(param.def_id, preceding_args),
|
||||
FeedConstTy::with_type_of(tcx, param.def_id, preceding_args),
|
||||
)
|
||||
.into(),
|
||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
|
|
@ -2303,15 +2312,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
pub fn lower_const_arg(
|
||||
&self,
|
||||
const_arg: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy<'_, 'tcx>,
|
||||
feed: FeedConstTy<'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let FeedConstTy::Param(param_def_id, args) = feed
|
||||
if let FeedConstTy::WithTy(anon_const_type) = feed
|
||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||
{
|
||||
let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
|
||||
|
||||
// FIXME(generic_const_parameter_types): Ideally we remove these errors below when
|
||||
// we have the ability to intermix typeck of anon const const args with the parent
|
||||
// bodies typeck.
|
||||
|
|
@ -2352,14 +2359,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
return ty::Const::new_error(tcx, e);
|
||||
}
|
||||
|
||||
tcx.feed_anon_const_type(
|
||||
anon.def_id,
|
||||
ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
|
||||
);
|
||||
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type));
|
||||
}
|
||||
|
||||
let hir_id = const_arg.hir_id;
|
||||
match const_arg.kind {
|
||||
hir::ConstArgKind::Tup(span, exprs) => self.lower_const_arg_tup(exprs, feed, span),
|
||||
hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
|
||||
debug!(?maybe_qself, ?path);
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
||||
|
|
@ -2464,7 +2469,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.iter()
|
||||
.zip(args)
|
||||
.map(|(field_def, arg)| {
|
||||
self.lower_const_arg(arg, FeedConstTy::Param(field_def.did, adt_args))
|
||||
self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
@ -2480,6 +2485,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
ty::Const::new_value(tcx, valtree, adt_ty)
|
||||
}
|
||||
|
||||
fn lower_const_arg_tup(
|
||||
&self,
|
||||
exprs: &'tcx [&'tcx hir::ConstArg<'tcx>],
|
||||
feed: FeedConstTy<'tcx>,
|
||||
span: Span,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let FeedConstTy::WithTy(ty) = feed else {
|
||||
return Const::new_error_with_message(tcx, span, "unsupported const tuple");
|
||||
};
|
||||
|
||||
let ty::Tuple(tys) = ty.kind() else {
|
||||
return Const::new_error_with_message(tcx, span, "const tuple must have a tuple type");
|
||||
};
|
||||
|
||||
let exprs = exprs
|
||||
.iter()
|
||||
.zip(tys.iter())
|
||||
.map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let valtree = ty::ValTree::from_branches(tcx, exprs);
|
||||
ty::Const::new_value(tcx, valtree, ty)
|
||||
}
|
||||
|
||||
fn lower_const_arg_struct(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
|
|
@ -2558,7 +2589,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
return ty::Const::new_error(tcx, e);
|
||||
}
|
||||
|
||||
self.lower_const_arg(expr.expr, FeedConstTy::Param(field_def.did, adt_args))
|
||||
self.lower_const_arg(
|
||||
expr.expr,
|
||||
FeedConstTy::with_type_of(tcx, field_def.did, adt_args),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let e = tcx.dcx().span_err(
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
|||
pub fn lower_const_arg_for_rustdoc<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_ct: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy<'_, 'tcx>,
|
||||
feed: FeedConstTy<'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
|
||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
|
||||
|
|
|
|||
|
|
@ -1141,6 +1141,16 @@ impl<'a> State<'a> {
|
|||
|
||||
fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
|
||||
match &const_arg.kind {
|
||||
ConstArgKind::Tup(_, exprs) => {
|
||||
self.popen();
|
||||
self.commasep_cmnt(
|
||||
Inconsistent,
|
||||
exprs,
|
||||
|s, arg| s.print_const_arg(arg),
|
||||
|arg| arg.span(),
|
||||
);
|
||||
self.pclose();
|
||||
}
|
||||
ConstArgKind::Struct(qpath, fields) => self.print_const_struct(qpath, fields),
|
||||
ConstArgKind::TupleCall(qpath, args) => self.print_const_ctor(qpath, args),
|
||||
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pub(crate) fn lower_const_arg(
|
||||
&self,
|
||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy<'_, 'tcx>,
|
||||
feed: FeedConstTy<'tcx>,
|
||||
) -> ty::Const<'tcx> {
|
||||
let ct = self.lowerer().lower_const_arg(const_arg, feed);
|
||||
self.register_wf_obligation(
|
||||
|
|
@ -1228,7 +1228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Ambiguous parts of `ConstArg` are handled in the match arms below
|
||||
.lower_const_arg(
|
||||
ct.as_unambig_ct(),
|
||||
FeedConstTy::Param(param.def_id, preceding_args),
|
||||
FeedConstTy::with_type_of(self.fcx.tcx, param.def_id, preceding_args),
|
||||
)
|
||||
.into(),
|
||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
// We handle the ambig portions of `ConstArg` in the match arms below
|
||||
.lower_const_arg(
|
||||
ct.as_unambig_ct(),
|
||||
FeedConstTy::Param(param.def_id, preceding_args),
|
||||
FeedConstTy::with_type_of(self.cfcx.tcx, param.def_id, preceding_args),
|
||||
)
|
||||
.into(),
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
|
|
|
|||
|
|
@ -1442,6 +1442,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
hir::ConstArgKind::Error(..)
|
||||
| hir::ConstArgKind::Struct(..)
|
||||
| hir::ConstArgKind::TupleCall(..)
|
||||
| hir::ConstArgKind::Tup(..)
|
||||
| hir::ConstArgKind::Path(..)
|
||||
| hir::ConstArgKind::Infer(..) => true,
|
||||
hir::ConstArgKind::Anon(..) => false,
|
||||
|
|
|
|||
|
|
@ -419,7 +419,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
|||
|
||||
// Avoid overwriting `const_arg_context` as we may want to treat const blocks
|
||||
// as being anon consts if we are inside a const argument.
|
||||
ExprKind::Struct(_) | ExprKind::Call(..) => return visit::walk_expr(self, expr),
|
||||
ExprKind::Struct(_) | ExprKind::Call(..) | ExprKind::Tup(..) => {
|
||||
return visit::walk_expr(self, expr);
|
||||
}
|
||||
// FIXME(mgca): we may want to handle block labels in some manner
|
||||
ExprKind::Block(block, _) if let [stmt] = block.stmts.as_slice() => match stmt.kind {
|
||||
// FIXME(mgca): this probably means that mac calls that expand
|
||||
|
|
|
|||
|
|
@ -326,6 +326,10 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind
|
|||
hir::ConstArgKind::TupleCall(..) => {
|
||||
ConstantKind::Path { path: "/* TUPLE CALL */".to_string().into() }
|
||||
}
|
||||
hir::ConstArgKind::Tup(..) => {
|
||||
// FIXME(mgca): proper printing :3
|
||||
ConstantKind::Path { path: "/* TUPLE EXPR */".to_string().into() }
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
|
||||
hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer,
|
||||
}
|
||||
|
|
@ -1809,7 +1813,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||
}
|
||||
hir::ConstArgKind::Struct(..)
|
||||
| hir::ConstArgKind::Path(..)
|
||||
| hir::ConstArgKind::TupleCall(..) => {
|
||||
| hir::ConstArgKind::TupleCall(..)
|
||||
| hir::ConstArgKind::Tup(..) => {
|
||||
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
|
||||
print_const(cx, ct)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: unconstrained generic constant
|
||||
--> $DIR/doesnt_unify_evaluatable.rs:9:11
|
||||
--> $DIR/doesnt_unify_evaluatable.rs:9:13
|
||||
|
|
||||
LL | bar::<{ T::ASSOC }>();
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#![feature(min_generic_const_args, adt_const_params, unsized_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
fn takes_tuple<const A: (u32, u32)>() {}
|
||||
fn takes_nested_tuple<const A: (u32, (u32, u32))>() {}
|
||||
|
||||
fn generic_caller<T: Trait, const N: u32, const N2: u32>() {
|
||||
takes_tuple::<{ (N, N + 1) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block
|
||||
takes_tuple::<{ (N, T::ASSOC + 1) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block
|
||||
|
||||
takes_nested_tuple::<{ (N, (N, N + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block
|
||||
takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>(); //~ ERROR generic parameters may not be used in const operations
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/adt_expr_arg_tuple_expr_complex.rs:13:25
|
||||
|
|
||||
LL | takes_tuple::<{ (N, N + 1) }>();
|
||||
| ^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/adt_expr_arg_tuple_expr_complex.rs:14:25
|
||||
|
|
||||
LL | takes_tuple::<{ (N, T::ASSOC + 1) }>();
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/adt_expr_arg_tuple_expr_complex.rs:16:36
|
||||
|
|
||||
LL | takes_nested_tuple::<{ (N, (N, N + 1)) }>();
|
||||
| ^^^^^
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/adt_expr_arg_tuple_expr_complex.rs:17:44
|
||||
|
|
||||
LL | takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>();
|
||||
| ^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(min_generic_const_args, adt_const_params, unsized_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
fn takes_tuple<const A: (u32, u32)>() {}
|
||||
fn takes_nested_tuple<const A: (u32, (u32, u32))>() {}
|
||||
|
||||
fn generic_caller<T: Trait, const N: u32, const N2: u32>() {
|
||||
takes_tuple::<{ (N, N2) }>();
|
||||
takes_tuple::<{ (N, T::ASSOC) }>();
|
||||
|
||||
takes_nested_tuple::<{ (N, (N, N2)) }>();
|
||||
takes_nested_tuple::<{ (N, (N, T::ASSOC)) }>();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -4,7 +4,6 @@ trait Foo<const N: Bar<2>> {
|
|||
//~^ WARN trait objects without an explicit `dyn` are deprecated
|
||||
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
||||
//~| ERROR cycle detected when computing type of `Foo::N`
|
||||
//~| ERROR cycle detected when computing type of `Foo::N`
|
||||
fn func() {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> {
|
|||
| +++
|
||||
|
||||
warning: trait objects without an explicit `dyn` are deprecated
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:20
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^
|
||||
|
|
@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> {
|
|||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of `Bar::M`...
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
@ -44,26 +44,6 @@ LL | trait Foo<const N: Bar<2>> {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Foo::N`
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:11
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of `Bar::M`...
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires computing type of `Foo::N`, completing the cycle
|
||||
note: cycle used when checking that `Foo` is well-formed
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:1
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
error: aborting due to 1 previous error; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue