Add ConstArgKind::Path and make ConstArg its own HIR node

This is a very large commit since a lot needs to be changed in order to
make the tests pass. The salient changes are:

- `ConstArgKind` gets a new `Path` variant, and all const params are now
  represented using it. Non-param paths still use `ConstArgKind::Anon`
  to prevent this change from getting too large, but they will soon use
  the `Path` variant too.

- `ConstArg` gets a distinct `hir_id` field and its own variant in
  `hir::Node`. This affected many parts of the compiler that expected
  the parent of an `AnonConst` to be the containing context (e.g., an
  array repeat expression). They have been changed to check the
  "grandparent" where necessary.

- Some `ast::AnonConst`s now have their `DefId`s created in
  rustc_ast_lowering rather than `DefCollector`. This is because in some
  cases they will end up becoming a `ConstArgKind::Path` instead, which
  has no `DefId`. We have to solve this in a hacky way where we guess
  whether the `AnonConst` could end up as a path const since we can't
  know for sure until after name resolution (`N` could refer to a free
  const or a nullary struct). If it has no chance as being a const
  param, then we create a `DefId` in `DefCollector` -- otherwise we
  decide during ast_lowering. This will have to be updated once all path
  consts use `ConstArgKind::Path`.

- We explicitly use `ConstArgHasType` for array lengths, rather than
  implicitly relying on anon const type feeding -- this is due to the
  addition of `ConstArgKind::Path`.

- Some tests have their outputs changed, but the changes are for the
  most part minor (including removing duplicate or almost-duplicate
  errors). One test now ICEs, but it is for an incomplete, unstable
  feature and is now tracked at #127009.
This commit is contained in:
Noah Lev 2024-07-16 19:07:36 -07:00
parent 1c49d406b6
commit 37ed7a4438
61 changed files with 542 additions and 415 deletions

View File

@ -224,6 +224,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Wrap the expression in an AnonConst. // Wrap the expression in an AnonConst.
let parent_def_id = self.current_def_id_parent; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
// HACK(min_generic_const_args): see lower_anon_const
if !expr.is_potential_trivial_const_arg() {
self.create_def( self.create_def(
parent_def_id, parent_def_id,
node_id, node_id,
@ -231,6 +233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
DefKind::AnonConst, DefKind::AnonConst,
*op_sp, *op_sp,
); );
}
let anon_const = AnonConst { id: node_id, value: P(expr) }; let anon_const = AnonConst { id: node_id, value: P(expr) };
hir::InlineAsmOperand::SymFn { hir::InlineAsmOperand::SymFn {
anon_const: self.lower_anon_const_to_anon_const(&anon_const), anon_const: self.lower_anon_const_to_anon_const(&anon_const),

View File

@ -75,10 +75,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let kind = match &e.kind { let kind = match &e.kind {
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
ExprKind::ConstBlock(c) => { ExprKind::ConstBlock(c) => {
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { let c = self.with_new_scopes(c.value.span, |this| {
def_id: this.local_def_id(c.id), let def_id = this.local_def_id(c.id);
hir::ConstBlock {
def_id,
hir_id: this.lower_node_id(c.id), hir_id: this.lower_node_id(c.id),
body: this.lower_const_body(c.value.span, Some(&c.value)), body: this.with_def_id_parent(def_id, |this| {
this.lower_const_body(c.value.span, Some(&c.value))
}),
}
}); });
hir::ExprKind::ConstBlock(c) hir::ExprKind::ConstBlock(c)
} }
@ -380,8 +385,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let parent_def_id = self.current_def_id_parent; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
// HACK(min_generic_const_args): see lower_anon_const
if !arg.is_potential_trivial_const_arg() {
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
}
let anon_const = AnonConst { id: node_id, value: arg }; let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@ -616,6 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
coroutine_source: hir::CoroutineSource, coroutine_source: hir::CoroutineSource,
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let closure_def_id = self.local_def_id(closure_node_id);
let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source); let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
// The `async` desugaring takes a resume argument and maintains a `task_context`, // The `async` desugaring takes a resume argument and maintains a `task_context`,
@ -666,7 +675,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
lifetime_elision_allowed: false, lifetime_elision_allowed: false,
}); });
let body = self.lower_body(move |this| { let body = self.with_def_id_parent(closure_def_id, move |this| {
this.lower_body(move |this| {
this.coroutine_kind = Some(coroutine_kind); this.coroutine_kind = Some(coroutine_kind);
let old_ctx = this.task_context; let old_ctx = this.task_context;
@ -677,11 +687,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.task_context = old_ctx; this.task_context = old_ctx;
(params, res) (params, res)
})
}); });
// `static |<_task_context?>| -> <return_ty> { <body> }`: // `static |<_task_context?>| -> <return_ty> { <body> }`:
hir::ExprKind::Closure(self.arena.alloc(hir::Closure { hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_node_id), def_id: closure_def_id,
binder: hir::ClosureBinder::Default, binder: hir::ClosureBinder::Default,
capture_clause, capture_clause,
bound_generic_params: &[], bound_generic_params: &[],
@ -960,9 +971,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl_span: Span, fn_decl_span: Span,
fn_arg_span: Span, fn_arg_span: Span,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let closure_def_id = self.local_def_id(closure_id);
let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (binder_clause, generic_params) = self.lower_closure_binder(binder);
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
this.with_def_id_parent(closure_def_id, move |this| {
let mut coroutine_kind = if this let mut coroutine_kind = if this
.attrs .attrs
.get(&closure_hir_id.local_id) .get(&closure_hir_id.local_id)
@ -981,6 +994,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let coroutine_option = let coroutine_option =
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
(body_id, coroutine_option) (body_id, coroutine_option)
})
}); });
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
@ -988,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let c = self.arena.alloc(hir::Closure { let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id), def_id: closure_def_id,
binder: binder_clause, binder: binder_clause,
capture_clause, capture_clause,
bound_generic_params, bound_generic_params,
@ -1060,6 +1074,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl_span: Span, fn_decl_span: Span,
fn_arg_span: Span, fn_arg_span: Span,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let closure_def_id = self.local_def_id(closure_id);
let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (binder_clause, generic_params) = self.lower_closure_binder(binder);
assert_matches!( assert_matches!(
@ -1069,6 +1084,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
let body = self.with_new_scopes(fn_decl_span, |this| { let body = self.with_new_scopes(fn_decl_span, |this| {
this.with_def_id_parent(closure_def_id, |this| {
let inner_decl = let inner_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
@ -1090,6 +1106,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(parameters, expr) (parameters, expr)
}); });
body_id body_id
})
}); });
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
@ -1100,7 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let c = self.arena.alloc(hir::Closure { let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id), def_id: closure_def_id,
binder: binder_clause, binder: binder_clause,
capture_clause, capture_clause,
bound_generic_params, bound_generic_params,

View File

@ -229,6 +229,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
} }
fn visit_anon_const(&mut self, constant: &'hir AnonConst) { fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
// FIXME: use real span?
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant)); self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
self.with_parent(constant.hir_id, |this| { self.with_parent(constant.hir_id, |this| {
@ -244,6 +245,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}); });
} }
fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
// FIXME: use real span?
self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
self.with_parent(const_arg.hir_id, |this| {
intravisit::walk_const_arg(this, const_arg);
});
}
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) { fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
self.insert(expr.span, expr.hir_id, Node::Expr(expr)); self.insert(expr.span, expr.hir_id, Node::Expr(expr));

View File

@ -61,7 +61,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
for (def_id, info) in lctx.children { for (def_id, info) in lctx.children {
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
debug_assert!(matches!(owner, hir::MaybeOwner::Phantom)); debug_assert!(
matches!(owner, hir::MaybeOwner::Phantom),
"duplicate copy of {def_id:?} in lctx.children"
);
*owner = info; *owner = info;
} }
} }
@ -1631,8 +1634,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
span, span,
}); });
let default_ct = self.arena.alloc(hir::ConstArg { let default_ct = self.arena.alloc(hir::ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Anon(default_ac), kind: hir::ConstArgKind::Anon(default_ac),
is_desugared_from_effects: true, is_desugared_from_effects: false,
}); });
let param = hir::GenericParam { let param = hir::GenericParam {
def_id, def_id,
@ -1657,6 +1661,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}), }),
)), )),
)), )),
// FIXME(effects) we might not need a default.
default: Some(default_ct), default: Some(default_ct),
is_host_effect: true, is_host_effect: true,
synthetic: true, synthetic: true,

View File

@ -54,7 +54,9 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{self as hir}; use rustc_hir::{self as hir};
use rustc_hir::{GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate}; use rustc_hir::{
ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::span_bug; use rustc_middle::span_bug;
@ -124,7 +126,7 @@ struct LoweringContext<'a, 'hir> {
/// they do get their own DefIds. Some of these DefIds have to be created during /// they do get their own DefIds. Some of these DefIds have to be created during
/// AST lowering, rather than def collection, because we can't tell until after /// AST lowering, rather than def collection, because we can't tell until after
/// name resolution whether an anonymous constant will end up instead being a /// name resolution whether an anonymous constant will end up instead being a
/// [`rustc_hir::ConstArgKind::Path`]. However, to compute which generics are /// [`hir::ConstArgKind::Path`]. However, to compute which generics are
/// available to an anonymous constant nested inside another, we need to make /// available to an anonymous constant nested inside another, we need to make
/// sure that the parent is recorded as the parent anon const, not the enclosing /// sure that the parent is recorded as the parent anon const, not the enclosing
/// item. So we need to track parent defs differently from HIR owners, since they /// item. So we need to track parent defs differently from HIR owners, since they
@ -2349,13 +2351,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
#[instrument(level = "debug", skip(self))]
fn lower_const_path_to_const_arg( fn lower_const_path_to_const_arg(
&mut self, &mut self,
path: &Path, path: &Path,
_res: Res<NodeId>, res: Res<NodeId>,
ty_id: NodeId, ty_id: NodeId,
span: Span, span: Span,
) -> &'hir hir::ConstArg<'hir> { ) -> &'hir hir::ConstArg<'hir> {
let ct_kind = match res {
Res::Def(DefKind::ConstParam, _) => {
let qpath = self.lower_qpath(
ty_id,
&None,
path,
ParamMode::Optional,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::ConstArgKind::Path(qpath)
}
_ => {
// Construct an AnonConst where the expr is the "ty"'s path. // Construct an AnonConst where the expr is the "ty"'s path.
let parent_def_id = self.current_def_id_parent; let parent_def_id = self.current_def_id_parent;
@ -2363,7 +2379,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let span = self.lower_span(span); let span = self.lower_span(span);
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span); let def_id =
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
let hir_id = self.lower_node_id(node_id);
let path_expr = Expr { let path_expr = Expr {
id: ty_id, id: ty_id,
@ -2376,37 +2394,103 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let ct = self.with_new_scopes(span, |this| { let ct = self.with_new_scopes(span, |this| {
self.arena.alloc(hir::AnonConst { self.arena.alloc(hir::AnonConst {
def_id, def_id,
hir_id: this.lower_node_id(node_id), hir_id,
body: this.lower_const_body(path_expr.span, Some(&path_expr)), body: this.with_def_id_parent(def_id, |this| {
this.lower_const_body(path_expr.span, Some(&path_expr))
}),
span, span,
}) })
}); });
hir::ConstArgKind::Anon(ct)
}
};
self.arena.alloc(hir::ConstArg { self.arena.alloc(hir::ConstArg {
kind: hir::ConstArgKind::Anon(ct), hir_id: self.next_id(),
kind: ct_kind,
is_desugared_from_effects: false, is_desugared_from_effects: false,
}) })
} }
/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_anon_const`].
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> { fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon)) self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Path(..) = &expr.kind
{
expr
} else {
&anon.value
};
let maybe_res =
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
debug!("res={:?}", maybe_res);
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
if let Some(res) = maybe_res
&& let Res::Def(DefKind::ConstParam, _) = res
&& let ExprKind::Path(qself, path) = &expr.kind
{
let qpath = self.lower_qpath(
expr.id,
qself,
path,
ParamMode::Optional,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
return ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Path(qpath),
is_desugared_from_effects: false,
};
}
let lowered_anon = self.lower_anon_const_to_anon_const(anon); let lowered_anon = self.lower_anon_const_to_anon_const(anon);
hir::ConstArg { ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Anon(lowered_anon), kind: hir::ConstArgKind::Anon(lowered_anon),
is_desugared_from_effects: false, is_desugared_from_effects: false,
} }
} }
/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_const_arg`].
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst { if c.value.is_potential_trivial_const_arg() {
def_id: this.local_def_id(c.id), // HACK(min_generic_const_args): see DefCollector::visit_anon_const
hir_id: this.lower_node_id(c.id), // Over there, we guess if this is a bare param and only create a def if
body: this.lower_const_body(c.value.span, Some(&c.value)), // we think it's not. However we may can guess wrong (see there for example)
// in which case we have to create the def here.
self.create_def(
self.current_def_id_parent,
c.id,
kw::Empty,
DefKind::AnonConst,
c.value.span,
);
}
self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
let def_id = this.local_def_id(c.id);
let hir_id = this.lower_node_id(c.id);
hir::AnonConst {
def_id,
hir_id,
body: this.with_def_id_parent(def_id, |this| {
this.lower_const_body(c.value.span, Some(&c.value))
}),
span: this.lower_span(c.value.span), span: this.lower_span(c.value.span),
}
})) }))
} }

View File

@ -228,34 +228,51 @@ impl<'hir> PathSegment<'hir> {
} }
} }
/// A constant that enters the type system, e.g. through const generics or even
/// array lengths.
///
/// These are distinct from [`AnonConst`] in part because with the plan for
/// `min_generic_const_args`, arbitrary anonymous constants (like `Foo<{N + 1}>`)
/// will *not* be allowed to use generic parameters. Instead, it will be necessary
/// to add indirection using a free constant that itself has const parameters.
///
/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args
/// that are [just paths](ConstArgKind::Path) (currently just bare const params)
/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3}`).
#[derive(Clone, Copy, Debug, HashStable_Generic)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArg<'hir> { pub struct ConstArg<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub kind: ConstArgKind<'hir>, pub kind: ConstArgKind<'hir>,
/// Indicates whether this comes from a `~const` desugaring. /// Indicates whether this comes from a `~const` desugaring.
pub is_desugared_from_effects: bool, pub is_desugared_from_effects: bool,
} }
impl<'hir> ConstArg<'hir> { impl<'hir> ConstArg<'hir> {
pub fn anon_const_hir_id(&self) -> Option<HirId> {
match self.kind {
ConstArgKind::Anon(ac) => Some(ac.hir_id),
_ => None,
}
}
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
match self.kind { match self.kind {
ConstArgKind::Path(path) => path.span(),
ConstArgKind::Anon(anon) => anon.span, ConstArgKind::Anon(anon) => anon.span,
} }
} }
// FIXME: convert to field, where ConstArg has its own HirId
pub fn hir_id(&self) -> HirId {
self.anon_const_hir_id()
}
pub fn anon_const_hir_id(&self) -> HirId {
match self.kind {
ConstArgKind::Anon(anon) => anon.hir_id,
}
}
} }
/// See [`ConstArg`].
#[derive(Clone, Copy, Debug, HashStable_Generic)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
pub enum ConstArgKind<'hir> { pub enum ConstArgKind<'hir> {
/// **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 = ...`).
///
/// However, in the future, we'll be using it for all of those.
Path(QPath<'hir>),
Anon(&'hir AnonConst), Anon(&'hir AnonConst),
} }
@ -293,7 +310,7 @@ impl GenericArg<'_> {
match self { match self {
GenericArg::Lifetime(l) => l.hir_id, GenericArg::Lifetime(l) => l.hir_id,
GenericArg::Type(t) => t.hir_id, GenericArg::Type(t) => t.hir_id,
GenericArg::Const(c) => c.hir_id(), GenericArg::Const(c) => c.hir_id,
GenericArg::Infer(i) => i.hir_id, GenericArg::Infer(i) => i.hir_id,
} }
} }
@ -1628,8 +1645,9 @@ pub enum ArrayLen<'hir> {
impl ArrayLen<'_> { impl ArrayLen<'_> {
pub fn hir_id(&self) -> HirId { pub fn hir_id(&self) -> HirId {
match self { match self {
ArrayLen::Infer(InferArg { hir_id, .. }) => *hir_id, ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => {
ArrayLen::Body(ct) => ct.hir_id(), *hir_id
}
} }
} }
} }
@ -3712,6 +3730,7 @@ pub enum Node<'hir> {
Field(&'hir FieldDef<'hir>), Field(&'hir FieldDef<'hir>),
AnonConst(&'hir AnonConst), AnonConst(&'hir AnonConst),
ConstBlock(&'hir ConstBlock), ConstBlock(&'hir ConstBlock),
ConstArg(&'hir ConstArg<'hir>),
Expr(&'hir Expr<'hir>), Expr(&'hir Expr<'hir>),
ExprField(&'hir ExprField<'hir>), ExprField(&'hir ExprField<'hir>),
Stmt(&'hir Stmt<'hir>), Stmt(&'hir Stmt<'hir>),
@ -3773,6 +3792,7 @@ impl<'hir> Node<'hir> {
Node::Param(..) Node::Param(..)
| Node::AnonConst(..) | Node::AnonConst(..)
| Node::ConstBlock(..) | Node::ConstBlock(..)
| Node::ConstArg(..)
| Node::Expr(..) | Node::Expr(..)
| Node::Stmt(..) | Node::Stmt(..)
| Node::Block(..) | Node::Block(..)

View File

@ -732,8 +732,10 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
visitor: &mut V, visitor: &mut V,
const_arg: &'v ConstArg<'v>, const_arg: &'v ConstArg<'v>,
) -> V::Result { ) -> V::Result {
match const_arg.kind { try_visit!(visitor.visit_id(const_arg.hir_id));
ConstArgKind::Anon(anon) => visitor.visit_anon_const(anon), match &const_arg.kind {
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
} }
} }

View File

@ -304,7 +304,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
self.tcx.ensure().type_of(param.def_id); self.tcx.ensure().type_of(param.def_id);
if let Some(default) = default { if let Some(default) = default {
// need to store default and type of default // need to store default and type of default
#[allow(irrefutable_let_patterns)] // FIXME
if let hir::ConstArgKind::Anon(ac) = default.kind { if let hir::ConstArgKind::Anon(ac) = default.kind {
self.tcx.ensure().type_of(ac.def_id); self.tcx.ensure().type_of(ac.def_id);
} }

View File

@ -13,7 +13,7 @@ use rustc_session::lint;
use rustc_span::symbol::{kw, Symbol}; use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span; use rustc_span::Span;
#[instrument(level = "debug", skip(tcx))] #[instrument(level = "debug", skip(tcx), ret)]
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*; use rustc_hir::*;
@ -102,6 +102,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
None None
} else if tcx.features().generic_const_exprs { } else if tcx.features().generic_const_exprs {
let parent_node = tcx.parent_hir_node(hir_id); let parent_node = tcx.parent_hir_node(hir_id);
debug!(?parent_node);
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
&& constant.hir_id == hir_id && constant.hir_id == hir_id
{ {
@ -164,13 +165,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
} }
} else { } else {
let parent_node = tcx.parent_hir_node(hir_id); let parent_node = tcx.parent_hir_node(hir_id);
let parent_node = match parent_node {
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
_ => parent_node,
};
match parent_node { match parent_node {
// HACK(eddyb) this provides the correct generics for repeat // HACK(eddyb) this provides the correct generics for repeat
// expressions' count (i.e. `N` in `[x; N]`), and explicit // expressions' count (i.e. `N` in `[x; N]`), and explicit
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
// as they shouldn't be able to cause query cycle errors. // as they shouldn't be able to cause query cycle errors.
Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. }) Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. })
if constant.hir_id() == hir_id => if ct.anon_const_hir_id() == Some(hir_id) =>
{ {
Some(parent_did) Some(parent_did)
} }

View File

@ -35,16 +35,32 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node_id = tcx.parent_hir_id(hir_id);
let parent_node = tcx.hir_node(parent_node_id); let parent_node = tcx.hir_node(parent_node_id);
let (generics, arg_idx) = match parent_node { match parent_node {
// Easy case: arrays repeat expressions. // Anon consts "inside" the type system.
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) Node::ConstArg(&ConstArg {
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) hir_id: arg_hir_id,
if constant.hir_id() == hir_id => kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
..
}) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
// Anon consts outside the type system.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const }
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
_ => false,
}) =>
{ {
return tcx.types.usize; tcx.typeck(def_id).node_type(hir_id)
} }
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
}
// Sort of affects the type system, but only for the purpose of diagnostics
// so no need for ConstArg.
Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
let ty = tcx.typeck(def_id).node_type(e.hir_id); let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
let ty = tcx.fold_regions(ty, |r, _| { let ty = tcx.fold_regions(ty, |r, _| {
if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
}); });
@ -56,24 +72,35 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
return ty; return ty;
} }
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) _ => Ty::new_error_with_message(
if asm.operands.iter().any(|(op, _op_sp)| match op { tcx,
hir::InlineAsmOperand::Const { anon_const } span,
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, format!("unexpected anon const parent in type_of(): {parent_node:?}"),
_ => false, ),
}) =>
{
return tcx.typeck(def_id).node_type(hir_id);
} }
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { }
return tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx);
fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
use hir::*;
use rustc_middle::ty::Ty;
let parent_node_id = tcx.parent_hir_id(arg_hir_id);
let parent_node = tcx.hir_node(parent_node_id);
let (generics, arg_idx) = match parent_node {
// Easy case: arrays repeat expressions.
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id() == arg_hir_id =>
{
return tcx.types.usize;
} }
Node::GenericParam(&GenericParam { Node::GenericParam(&GenericParam {
def_id: param_def_id, def_id: param_def_id,
kind: GenericParamKind::Const { default: Some(ct), .. }, kind: GenericParamKind::Const { default: Some(ct), .. },
.. ..
}) if ct.anon_const_hir_id() == hir_id => { }) if ct.hir_id == arg_hir_id => {
return tcx return tcx
.type_of(param_def_id) .type_of(param_def_id)
.no_bound_vars() .no_bound_vars()
@ -104,7 +131,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`). // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
let item_def_id = tcx let item_def_id = tcx
.hir() .hir()
.parent_owner_iter(hir_id) .parent_owner_iter(arg_hir_id)
.find(|(_, node)| matches!(node, OwnerNode::Item(_))) .find(|(_, node)| matches!(node, OwnerNode::Item(_)))
.unwrap() .unwrap()
.0 .0
@ -124,7 +151,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
args.args args.args
.iter() .iter()
.filter(|arg| arg.is_ty_or_const()) .filter(|arg| arg.is_ty_or_const())
.position(|arg| arg.hir_id() == hir_id) .position(|arg| arg.hir_id() == arg_hir_id)
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment"); bug!("no arg matching AnonConst in segment");
@ -145,7 +172,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)), ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
.. ..
}) => { }) => {
let body_owner = tcx.hir().enclosing_body_owner(hir_id); let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
let tables = tcx.typeck(body_owner); let tables = tcx.typeck(body_owner);
// This may fail in case the method/path does not actually exist. // This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return // As there is no relevant param for `def_id`, we simply return
@ -163,10 +190,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
args.args args.args
.iter() .iter()
.filter(|arg| arg.is_ty_or_const()) .filter(|arg| arg.is_ty_or_const())
.position(|arg| arg.hir_id() == hir_id) .position(|arg| arg.hir_id() == arg_hir_id)
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment"); bug!("no arg matching ConstArg in segment");
}); });
(tcx.generics_of(type_dependent_def), idx) (tcx.generics_of(type_dependent_def), idx)
@ -185,18 +212,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
| ExprKind::Struct(&QPath::Resolved(_, path), ..), | ExprKind::Struct(&QPath::Resolved(_, path), ..),
.. ..
}) => { }) => {
let body_owner = tcx.hir().enclosing_body_owner(hir_id); let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
let _tables = tcx.typeck(body_owner); let _tables = tcx.typeck(body_owner);
&*path &*path
} }
Node::Pat(pat) => { Node::Pat(pat) => {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
path path
} else { } else {
return Ty::new_error_with_message( return Ty::new_error_with_message(
tcx, tcx,
span, span,
format!("unable to find const parent for {hir_id} in pat {pat:?}"), format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
); );
} }
} }
@ -217,14 +244,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
args.args args.args
.iter() .iter()
.filter(|arg| arg.is_ty_or_const()) .filter(|arg| arg.is_ty_or_const())
.position(|arg| arg.hir_id() == hir_id) .position(|arg| arg.hir_id() == arg_hir_id)
.map(|index| (index, seg)) .map(|index| (index, seg))
.or_else(|| { .or_else(|| {
args.constraints args.constraints
.iter() .iter()
.copied() .copied()
.filter_map(AssocItemConstraint::ct) .filter_map(AssocItemConstraint::ct)
.position(|ct| ct.anon_const_hir_id() == hir_id) .position(|ct| ct.hir_id == arg_hir_id)
.map(|idx| (idx, seg)) .map(|idx| (idx, seg))
}) })
}) else { }) else {
@ -249,7 +276,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
return Ty::new_error_with_message( return Ty::new_error_with_message(
tcx, tcx,
span, span,
format!("unexpected const parent in type_of(): {parent_node:?}"), format!("unexpected const arg parent in type_of(): {parent_node:?}"),
); );
} }
}; };

View File

@ -414,7 +414,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Provide the resolved type of the associated constant to `type_of(AnonConst)`. // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
if let Some(const_arg) = constraint.ct() { if let Some(const_arg) = constraint.ct() {
#[allow(irrefutable_let_patterns)] // FIXME
if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind { if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
let ty = alias_term let ty = alias_term
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));

View File

@ -10,8 +10,8 @@ use rustc_errors::{
}; };
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg; use rustc_hir::{self as hir};
use rustc_hir::{self as hir, ConstArgKind}; use rustc_hir::{ConstArgKind, GenericArg};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty,
}; };
@ -113,9 +113,12 @@ fn generic_arg_mismatch_err(
} }
} }
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
let ConstArgKind::Anon(anon) = cnst.kind; // FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
let body = tcx.hir().body(anon.body); // this should match against that instead of ::Anon
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind if let ConstArgKind::Anon(anon) = cnst.kind
&& let body = tcx.hir().body(anon.body)
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
body.value.kind
{ {
if let Res::Def(DefKind::Fn { .. }, id) = path.res { if let Res::Def(DefKind::Fn { .. }, id) = path.res {
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id))); err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));

View File

@ -474,7 +474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id)) ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
.into() .into()
} }
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.lowerer.ct_infer(Some(param), inf.span).into() self.lowerer.ct_infer(Some(param), inf.span).into()
} }
(kind, arg) => span_bug!( (kind, arg) => span_bug!(

View File

@ -87,6 +87,7 @@ impl<'a> State<'a> {
Node::Variant(a) => self.print_variant(a), Node::Variant(a) => self.print_variant(a),
Node::AnonConst(a) => self.print_anon_const(a), Node::AnonConst(a) => self.print_anon_const(a),
Node::ConstBlock(a) => self.print_inline_const(a), Node::ConstBlock(a) => self.print_inline_const(a),
Node::ConstArg(a) => self.print_const_arg(a),
Node::Expr(a) => self.print_expr(a), Node::Expr(a) => self.print_expr(a),
Node::ExprField(a) => self.print_expr_field(a), Node::ExprField(a) => self.print_expr_field(a),
Node::Stmt(a) => self.print_stmt(a), Node::Stmt(a) => self.print_stmt(a),
@ -993,6 +994,7 @@ impl<'a> State<'a> {
fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) { fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
match &const_arg.kind { match &const_arg.kind {
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
ConstArgKind::Anon(anon) => self.print_anon_const(anon), ConstArgKind::Anon(anon) => self.print_anon_const(anon),
} }
} }

View File

@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir, ConstArg, ConstArgKind}; use rustc_hir::{self as hir};
use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath};
use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
use rustc_hir_analysis::hir_ty_lowering::generics::{ use rustc_hir_analysis::hir_ty_lowering::generics::{
@ -468,23 +468,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn lower_const_arg( pub fn lower_const_arg(
&self, &self,
const_arg: &ConstArg<'tcx>, const_arg: &'tcx hir::ConstArg<'tcx>,
param_def_id: DefId, param_def_id: DefId,
) -> ty::Const<'tcx> { ) -> ty::Const<'tcx> {
match &const_arg.kind { let ct =
ConstArgKind::Anon(anon) => { ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
let did = anon.def_id;
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
let ct = ty::Const::from_anon_const(self.tcx, did);
self.register_wf_obligation( self.register_wf_obligation(
ct.into(), ct.into(),
self.tcx.hir().span(anon.hir_id), self.tcx.hir().span(const_arg.hir_id),
ObligationCauseCode::WellFormed(None), ObligationCauseCode::WellFormed(None),
); );
ct ct
} }
}
}
// If the type given by the user has free regions, save it for later, since // If the type given by the user has free regions, save it for later, since
// NLL would like to enforce those. Also pass in types that involve // NLL would like to enforce those. Also pass in types that involve

View File

@ -912,6 +912,7 @@ impl<'hir> Map<'hir> {
Node::Field(field) => field.span, Node::Field(field) => field.span,
Node::AnonConst(constant) => constant.span, Node::AnonConst(constant) => constant.span,
Node::ConstBlock(constant) => self.body(constant.body).value.span, Node::ConstBlock(constant) => self.body(constant.body).value.span,
Node::ConstArg(const_arg) => const_arg.span(),
Node::Expr(expr) => expr.span, Node::Expr(expr) => expr.span,
Node::ExprField(field) => field.span, Node::ExprField(field) => field.span,
Node::Stmt(stmt) => stmt.span, Node::Stmt(stmt) => stmt.span,
@ -962,7 +963,8 @@ impl<'hir> Map<'hir> {
/// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
/// called with the HirId for the `{ ... }` anon const /// called with the HirId for the `{ ... }` anon const
pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> { pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
match self.tcx.parent_hir_node(anon_const) { let const_arg = self.tcx.parent_hir_id(anon_const);
match self.tcx.parent_hir_node(const_arg) {
Node::GenericParam(GenericParam { Node::GenericParam(GenericParam {
def_id: param_id, def_id: param_id,
kind: GenericParamKind::Const { .. }, kind: GenericParamKind::Const { .. },
@ -1182,6 +1184,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
} }
Node::AnonConst(_) => node_str("const"), Node::AnonConst(_) => node_str("const"),
Node::ConstBlock(_) => node_str("const"), Node::ConstBlock(_) => node_str("const"),
Node::ConstArg(_) => node_str("const"),
Node::Expr(_) => node_str("expr"), Node::Expr(_) => node_str("expr"),
Node::ExprField(_) => node_str("expr field"), Node::ExprField(_) => node_str("expr field"),
Node::Stmt(_) => node_str("stmt"), Node::Stmt(_) => node_str("stmt"),

View File

@ -202,7 +202,6 @@ pub enum FeedConstTy {
impl<'tcx> Const<'tcx> { impl<'tcx> Const<'tcx> {
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self). /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
#[allow(irrefutable_let_patterns)]
pub fn from_const_arg( pub fn from_const_arg(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
const_arg: &'tcx hir::ConstArg<'tcx>, const_arg: &'tcx hir::ConstArg<'tcx>,
@ -215,6 +214,10 @@ impl<'tcx> Const<'tcx> {
} }
match const_arg.kind { match const_arg.kind {
hir::ConstArgKind::Path(qpath) => {
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
Self::from_param(tcx, qpath, const_arg.hir_id)
}
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id), hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
} }
} }
@ -310,16 +313,12 @@ impl<'tcx> Const<'tcx> {
} }
} }
if let hir::ExprKind::Path( if let hir::ExprKind::Path(hir::QPath::Resolved(
qpath @ hir::QPath::Resolved(
_, _,
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
), )) = expr.kind
) = expr.kind
{ {
// FIXME: once ConstArgKind::Path added, uncomment span_bug and delete return span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
// span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
return Some(Self::from_param(tcx, qpath, expr.hir_id));
} }
None None

View File

@ -607,7 +607,9 @@ impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
type Output = V; type Output = V;
fn index(&self, key: HirId) -> &V { fn index(&self, key: HirId) -> &V {
self.get(key).expect("LocalTableInContext: key not found") self.get(key).unwrap_or_else(|| {
bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
})
} }
} }

View File

@ -312,9 +312,20 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
} }
fn visit_anon_const(&mut self, constant: &'a AnonConst) { fn visit_anon_const(&mut self, constant: &'a AnonConst) {
let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); // HACK(min_generic_const_args): don't create defs for anon consts if we think they will
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
// may accidentally identify a construction of a unit struct as a param and not create a
// def. we'll then create a def later in ast lowering in this case. the parent of nested
// items will be messed up, but that's ok because there can't be any if we're just looking
// for bare idents.
if constant.value.is_potential_trivial_const_arg() {
visit::walk_anon_const(self, constant)
} else {
let def =
self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
self.with_parent(def, |this| visit::walk_anon_const(this, constant)); self.with_parent(def, |this| visit::walk_anon_const(this, constant));
} }
}
fn visit_expr(&mut self, expr: &'a Expr) { fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = match expr.kind { let parent_def = match expr.kind {

View File

@ -672,9 +672,21 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem); self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
} }
ty::Array(subty, _) => { ty::Array(subty, len) => {
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem); self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
// Note that we handle the len is implicitly checked while walking `arg`. // Note that the len being WF is implicitly checked while visiting.
// Here we just check that it's of type usize.
let cause = self.cause(ObligationCauseCode::Misc);
self.out.push(traits::Obligation::with_depth(
tcx,
cause,
self.recursion_depth,
self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
len,
tcx.types.usize,
))),
));
} }
ty::Pat(subty, _) => { ty::Pat(subty, _) => {

View File

@ -289,6 +289,9 @@ pub(crate) fn clean_const<'tcx>(
_cx: &mut DocContext<'tcx>, _cx: &mut DocContext<'tcx>,
) -> Constant { ) -> Constant {
match &constant.kind { match &constant.kind {
ConstArgKind::Path(qpath) => {
Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } }
}
ConstArgKind::Anon(anon) => Constant { kind: ConstantKind::Anonymous { body: anon.body } }, ConstArgKind::Anon(anon) => Constant { kind: ConstantKind::Anonymous { body: anon.body } },
} }
} }
@ -1832,7 +1835,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
// results in an ICE while manually constructing the constant and using `eval` // results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`. // does nothing for `ConstKind::Param`.
let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No); let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
#[allow(irrefutable_let_patterns)] // FIXME
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
const_arg.kind const_arg.kind
{ {

View File

@ -2395,6 +2395,9 @@ pub(crate) enum ConstantKind {
/// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
/// by a DefId. So this field must be different from `Extern`. /// by a DefId. So this field must be different from `Extern`.
TyConst { expr: Box<str> }, TyConst { expr: Box<str> },
/// A constant that is just a path (i.e., referring to a const param, free const, etc.).
// FIXME: this is an unfortunate representation. rustdoc's logic around consts needs to be improved.
Path { path: Box<str> },
/// A constant (expression) that's not an item or associated item. These are usually found /// A constant (expression) that's not an item or associated item. These are usually found
/// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
/// used to define explicit discriminant values for enum variants. /// used to define explicit discriminant values for enum variants.
@ -2423,6 +2426,7 @@ impl ConstantKind {
pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String { pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
match *self { match *self {
ConstantKind::TyConst { ref expr } => expr.to_string(), ConstantKind::TyConst { ref expr } => expr.to_string(),
ConstantKind::Path { ref path } => path.to_string(),
ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
@ -2432,7 +2436,9 @@ impl ConstantKind {
pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> { pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
match *self { match *self {
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None, ConstantKind::TyConst { .. }
| ConstantKind::Path { .. }
| ConstantKind::Anonymous { .. } => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
print_evaluated_const(tcx, def_id, true, true) print_evaluated_const(tcx, def_id, true, true)
} }
@ -2441,7 +2447,9 @@ impl ConstantKind {
pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool { pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
match *self { match *self {
ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } => false, ConstantKind::TyConst { .. }
| ConstantKind::Extern { .. }
| ConstantKind::Path { .. } => false,
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
is_literal_expr(tcx, body.hir_id) is_literal_expr(tcx, body.hir_id)
} }

View File

@ -271,15 +271,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) { fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
match const_arg.value.kind { match const_arg.value.kind {
// FIXME: uncomment for ConstArgKind::Path ConstArgKind::Path(ref qpath) => {
// ConstArgKind::Path(ref qpath) => { bind!(self, qpath);
// bind!(self, qpath); chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
// chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind"); self.qpath(qpath);
// self.qpath(qpath); },
// },
ConstArgKind::Anon(anon_const) => { ConstArgKind::Anon(anon_const) => {
bind!(self, anon_const); bind!(self, anon_const);
chain!(self, "let ConstArgKind::({anon_const}) = {const_arg}.kind"); chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
self.body(field!(anon_const.body)); self.body(field!(anon_const.body));
}, },
} }

View File

@ -421,7 +421,12 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool { fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
match (&left.kind, &right.kind) { match (&left.kind, &right.kind) {
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
(ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
// Use explicit match for now since ConstArg is undergoing flux.
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
false
},
} }
} }
@ -1142,6 +1147,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) { fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
match &const_arg.kind { match &const_arg.kind {
ConstArgKind::Path(path) => self.hash_qpath(path),
ConstArgKind::Anon(anon) => self.hash_body(anon.body), ConstArgKind::Anon(anon) => self.hash_body(anon.body),
} }
} }

View File

@ -904,7 +904,6 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
}, },
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
ExprKind::Repeat(x, ArrayLen::Body(len)) => { ExprKind::Repeat(x, ArrayLen::Body(len)) => {
#[allow(irrefutable_let_patterns)] // FIXME
if let ConstArgKind::Anon(anon_const) = len.kind if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && let LitKind::Int(v, _) = const_lit.node
@ -935,7 +934,6 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => { ExprKind::Repeat(_, ArrayLen::Body(len)) => {
#[allow(irrefutable_let_patterns)] // FIXME
if let ConstArgKind::Anon(anon_const) = len.kind if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && let LitKind::Int(v, _) = const_lit.node

View File

@ -1,7 +1,8 @@
if let ExprKind::Repeat(value, length) = expr.kind if let ExprKind::Repeat(value, length) = expr.kind
&& let ExprKind::Lit(ref lit) = value.kind && let ExprKind::Lit(ref lit) = value.kind
&& let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
&& let ArrayLen::Body(anon_const) = length && let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& expr1 = &cx.tcx.hir().body(anon_const.body).value && expr1 = &cx.tcx.hir().body(anon_const.body).value
&& let ExprKind::Lit(ref lit1) = expr1.kind && let ExprKind::Lit(ref lit1) = expr1.kind
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node

View File

@ -193,5 +193,11 @@ error: this ident consists of a single char
LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
| ^ | ^
error: aborting due to 32 previous errors error: this ident consists of a single char
--> tests/ui/min_ident_chars.rs:93:41
|
LL | struct Array<T, const N: usize>([T; N]);
| ^
error: aborting due to 33 previous errors

11
tests/crashes/127009.rs Normal file
View File

@ -0,0 +1,11 @@
//@ known-bug: #127009
#![feature(non_lifetime_binders)]
fn b()
where
for<const C: usize> [(); C]: Copy,
{
}
fn main() {}

View File

@ -33,7 +33,7 @@ fn test_stable_mir() -> ControlFlow<()> {
// Get all items and split generic vs monomorphic items. // Get all items and split generic vs monomorphic items.
let (generic, mono): (Vec<_>, Vec<_>) = let (generic, mono): (Vec<_>, Vec<_>) =
items.into_iter().partition(|item| item.requires_monomorphization()); items.into_iter().partition(|item| item.requires_monomorphization());
assert_eq!(mono.len(), 4, "Expected 2 mono functions and one constant"); assert_eq!(mono.len(), 3, "Expected 3 mono functions");
assert_eq!(generic.len(), 2, "Expected 2 generic functions"); assert_eq!(generic.len(), 2, "Expected 2 generic functions");
// For all monomorphic items, get the correspondent instances. // For all monomorphic items, get the correspondent instances.

View File

@ -5,9 +5,7 @@
#![feature(with_negative_coherence)] #![feature(with_negative_coherence)]
trait Trait {} trait Trait {}
impl<const N: u8> Trait for [(); N] {} impl<const N: u8> Trait for [(); N] {}
//~^ ERROR: mismatched types
impl<const N: i8> Trait for [(); N] {} impl<const N: i8> Trait for [(); N] {}
//~^ ERROR: mismatched types //~^ ERROR: conflicting implementations of trait `Trait`
//~| ERROR: conflicting implementations of trait `Trait`
fn main() {} fn main() {}

View File

@ -1,25 +1,11 @@
error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]`
--> $DIR/generic_const_type_mismatch.rs:9:1 --> $DIR/generic_const_type_mismatch.rs:8:1
| |
LL | impl<const N: u8> Trait for [(); N] {} LL | impl<const N: u8> Trait for [(); N] {}
| ----------------------------------- first implementation here | ----------------------------------- first implementation here
LL |
LL | impl<const N: i8> Trait for [(); N] {} LL | impl<const N: i8> Trait for [(); N] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]`
error[E0308]: mismatched types error: aborting due to 1 previous error
--> $DIR/generic_const_type_mismatch.rs:7:34
|
LL | impl<const N: u8> Trait for [(); N] {}
| ^ expected `usize`, found `u8`
error[E0308]: mismatched types For more information about this error, try `rustc --explain E0119`.
--> $DIR/generic_const_type_mismatch.rs:9:34
|
LL | impl<const N: i8> Trait for [(); N] {}
| ^ expected `usize`, found `i8`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0119, E0308.
For more information about an error, try `rustc --explain E0119`.

View File

@ -6,7 +6,7 @@ trait Q {
} }
impl<const N: u64> Q for [u8; N] { impl<const N: u64> Q for [u8; N] {
//~^ ERROR mismatched types //~^ ERROR: the constant `N` is not of type `usize`
const ASSOC: usize = 1; const ASSOC: usize = 1;
} }

View File

@ -1,3 +1,9 @@
error: the constant `N` is not of type `usize`
--> $DIR/bad-subst-const-kind.rs:8:26
|
LL | impl<const N: u64> Q for [u8; N] {
| ^^^^^^^ expected `usize`, found `u64`
error: the constant `13` is not of type `u64` error: the constant `13` is not of type `u64`
--> $DIR/bad-subst-const-kind.rs:13:24 --> $DIR/bad-subst-const-kind.rs:13:24
| |
@ -12,12 +18,5 @@ LL | impl<const N: u64> Q for [u8; N] {
| | | |
| unsatisfied trait bound introduced here | unsatisfied trait bound introduced here
error[E0308]: mismatched types
--> $DIR/bad-subst-const-kind.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {
| ^ expected `usize`, found `u64`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -7,7 +7,7 @@ trait Q {
impl<const N: u64> Q for [u8; N] {} impl<const N: u64> Q for [u8; N] {}
//~^ ERROR not all trait items implemented //~^ ERROR not all trait items implemented
//~| ERROR mismatched types //~| ERROR the constant `N` is not of type `usize`
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
//~^ ERROR the constant `13` is not of type `u64` //~^ ERROR the constant `13` is not of type `u64`

View File

@ -1,3 +1,9 @@
error: the constant `N` is not of type `usize`
--> $DIR/type_mismatch.rs:8:26
|
LL | impl<const N: u64> Q for [u8; N] {}
| ^^^^^^^ expected `usize`, found `u64`
error[E0046]: not all trait items implemented, missing: `ASSOC` error[E0046]: not all trait items implemented, missing: `ASSOC`
--> $DIR/type_mismatch.rs:8:1 --> $DIR/type_mismatch.rs:8:1
| |
@ -29,12 +35,6 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
| | | |
| implicitly returns `()` as its body has no tail or `return` expression | implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {}
| ^ expected `usize`, found `u64`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors
Some errors have detailed explanations: E0046, E0308. Some errors have detailed explanations: E0046, E0308.

View File

@ -25,8 +25,8 @@ mod v20 {
} }
impl<const v10: usize> v17<v10, v2> { impl<const v10: usize> v17<v10, v2> {
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} //~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} //~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
pub const fn v21() -> v18 { pub const fn v21() -> v18 {
//~^ ERROR cannot find type `v18` in this scope //~^ ERROR cannot find type `v18` in this scope
v18 { _p: () } v18 { _p: () }

View File

@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)] LL + #![feature(adt_const_params)]
| |
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:27:37 --> $DIR/unevaluated-const-ice-119731.rs:27:37
| |
LL | impl<const v10: usize> v17<v10, v2> { LL | impl<const v10: usize> v17<v10, v2> {
| ^^ | ^^
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:27:37 --> $DIR/unevaluated-const-ice-119731.rs:27:37
| |
LL | impl<const v10: usize> v17<v10, v2> { LL | impl<const v10: usize> v17<v10, v2> {

View File

@ -1,26 +1,32 @@
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated` error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}`
--> $DIR/issue-88119.rs:21:5 --> $DIR/issue-88119.rs:19:49
| |
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^ cannot normalize `<&T as ConstName>::{constant#0}`
|
note: required for `&T` to implement `ConstName`
--> $DIR/issue-88119.rs:19:35
|
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^^^^^^^^ ^^
LL | where
LL | [(); name_len::<T>()]:, LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated` | --------------------- unsatisfied trait bound introduced here
|
note: required by a bound in `<&T as ConstName>`
--> $DIR/issue-88119.rs:21:10
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated` error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
--> $DIR/issue-88119.rs:28:5 --> $DIR/issue-88119.rs:26:49
| |
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
|
note: required for `&mut T` to implement `ConstName`
--> $DIR/issue-88119.rs:26:35
|
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^^^^ ^^^^^^
LL | where
LL | [(); name_len::<T>()]:, LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated` | --------------------- unsatisfied trait bound introduced here
|
note: required by a bound in `<&mut T as ConstName>`
--> $DIR/issue-88119.rs:28:10
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -19,6 +19,8 @@ fn bar<const N: usize>() {}
fn foo<const N: usize>() { fn foo<const N: usize>() {
bar::<{ [1; N] }>(); bar::<{ [1; N] }>();
//~^ ERROR: generic parameters may not be used in const operations //~^ ERROR: generic parameters may not be used in const operations
bar::<{ [1; { N + 1 }] }>();
//~^ ERROR: generic parameters may not be used in const operations
} }
fn main() {} fn main() {}

View File

@ -7,5 +7,14 @@ LL | bar::<{ [1; N] }>();
= help: const parameters may only be used as standalone arguments, i.e. `N` = help: const parameters may only be used as standalone arguments, i.e. `N`
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
error: aborting due to 1 previous error error: generic parameters may not be used in const operations
--> $DIR/repeat_expr_hack_gives_right_generics.rs:22:19
|
LL | bar::<{ [1; { N + 1 }] }>();
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
error: aborting due to 2 previous errors

View File

@ -10,11 +10,10 @@ fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] {
} }
fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
//~^ ERROR mismatched types //~^ ERROR the constant `W` is not of type `usize`
//~| ERROR mismatched types
unsafe { unsafe {
std::mem::transmute(v) std::mem::transmute(v)
//~^ ERROR cannot transmute between types //~^ ERROR the constant `W` is not of type `usize`
} }
} }

View File

@ -1,3 +1,9 @@
error: the constant `W` is not of type `usize`
--> $DIR/transmute-fail.rs:12:42
|
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
| ^^^^^^^^^^^^^ expected `usize`, found `bool`
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:7:5 --> $DIR/transmute-fail.rs:7:5
| |
@ -7,17 +13,14 @@ LL | std::mem::transmute(v)
= note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1]) = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
= note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1]) = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error: the constant `W` is not of type `usize`
--> $DIR/transmute-fail.rs:16:5 --> $DIR/transmute-fail.rs:15:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:23:5 --> $DIR/transmute-fail.rs:22:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -26,7 +29,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; W * H * H]` (this type does not have a fixed size) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:30:5 --> $DIR/transmute-fail.rs:29:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -35,7 +38,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:37:5 --> $DIR/transmute-fail.rs:36:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -44,7 +47,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:50:5 --> $DIR/transmute-fail.rs:49:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -53,7 +56,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; W * H]` (this type does not have a fixed size) = note: target type: `[u32; W * H]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:57:5 --> $DIR/transmute-fail.rs:56:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -62,7 +65,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:66:5 --> $DIR/transmute-fail.rs:65:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -71,7 +74,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:75:5 --> $DIR/transmute-fail.rs:74:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -80,7 +83,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:82:5 --> $DIR/transmute-fail.rs:81:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -89,7 +92,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u8; L * 2]` (this type does not have a fixed size) = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:89:5 --> $DIR/transmute-fail.rs:88:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -98,7 +101,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u16; L]` (this type does not have a fixed size) = note: target type: `[u16; L]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:96:5 --> $DIR/transmute-fail.rs:95:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -107,7 +110,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:105:5 --> $DIR/transmute-fail.rs:104:5
| |
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -115,19 +118,6 @@ LL | std::mem::transmute(v)
= note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
= note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
error[E0308]: mismatched types error: aborting due to 14 previous errors
--> $DIR/transmute-fail.rs:12:53
|
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
| ^ expected `usize`, found `bool`
error[E0308]: mismatched types For more information about this error, try `rustc --explain E0512`.
--> $DIR/transmute-fail.rs:12:67
|
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
| ^ expected `usize`, found `bool`
error: aborting due to 15 previous errors
Some errors have detailed explanations: E0308, E0512.
For more information about an error, try `rustc --explain E0308`.

View File

@ -1,10 +1,10 @@
fn foo<const N: usize>() -> [u8; N] { fn foo<const N: usize>() -> [u8; N] {
bar::<N>() //~ ERROR mismatched types bar::<N>()
//~^ ERROR the constant `N` is not of type `u8` //~^ ERROR the constant `N` is not of type `u8`
} }
fn bar<const N: u8>() -> [u8; N] {} fn bar<const N: u8>() -> [u8; N] {}
//~^ ERROR mismatched types //~^ ERROR the constant `N` is not of type `usize`
//~| ERROR mismatched types //~| ERROR mismatched types
fn main() {} fn main() {}

View File

@ -1,3 +1,9 @@
error: the constant `N` is not of type `usize`
--> $DIR/type_mismatch.rs:6:26
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| ^^^^^^^ expected `usize`, found `u8`
error: the constant `N` is not of type `u8` error: the constant `N` is not of type `u8`
--> $DIR/type_mismatch.rs:2:11 --> $DIR/type_mismatch.rs:2:11
| |
@ -18,18 +24,6 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
| | | |
| implicitly returns `()` as its body has no tail or `return` expression | implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types error: aborting due to 3 previous errors
--> $DIR/type_mismatch.rs:2:11
|
LL | bar::<N>()
| ^ expected `u8`, found `usize`
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:6:31
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| ^ expected `usize`, found `u8`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View File

@ -1,10 +1,10 @@
error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}`
--> $DIR/issue-36163.rs:4:9 --> $DIR/issue-36163.rs:4:9
| |
LL | B = A, LL | B = A,
| ^ | ^
| |
note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... note: ...which requires const-evaluating + checking `Foo::{constant#0}`...
--> $DIR/issue-36163.rs:4:9 --> $DIR/issue-36163.rs:4:9
| |
LL | B = A, LL | B = A,
@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`...
| |
LL | const A: isize = Foo::B as isize; LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle
note: cycle used when checking that `Foo` is well-formed note: cycle used when checking that `Foo` is well-formed
--> $DIR/issue-36163.rs:3:1 --> $DIR/issue-36163.rs:3:1
| |

View File

@ -9,6 +9,5 @@ impl Fn(&isize) for Error {
//~^ ERROR associated function in `impl` without body //~^ ERROR associated function in `impl` without body
//~^^ ERROR method `foo` is not a member of trait `Fn` [E0407] //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407]
//~^^^ ERROR associated type `B` not found for `Self` [E0220] //~^^^ ERROR associated type `B` not found for `Self` [E0220]
//~| ERROR associated type `B` not found for `Self` [E0220]
} }
fn main() {} fn main() {}

View File

@ -56,15 +56,7 @@ error[E0220]: associated type `B` not found for `Self`
LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>; LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>;
| ^ help: `Self` has the following associated type: `Output` | ^ help: `Self` has the following associated type: `Output`
error[E0220]: associated type `B` not found for `Self` error: aborting due to 7 previous errors
--> $DIR/issue-95023.rs:8:44
|
LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>;
| ^ help: `Self` has the following associated type: `Output`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407. Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407.
For more information about an error, try `rustc --explain E0046`. For more information about an error, try `rustc --explain E0046`.

View File

@ -4,20 +4,11 @@ error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#0
LL | fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] { LL | fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] {
| ^^^^^^^^^^^^^^^^ cannot normalize `process<T>::{constant#0}` | ^^^^^^^^^^^^^^^^ cannot normalize `process<T>::{constant#0}`
error[E0284]: type annotations needed: cannot satisfy `the constant `T::make(P)` can be evaluated` error[E0284]: type annotations needed: cannot normalize `Struct<T, P>::field::{constant#0}`
--> $DIR/const-trait-bounds.rs:18:5 --> $DIR/const-trait-bounds.rs:20:12
| |
LL | [u32; T::make(P)]:, LL | field: [u32; T::make(P)],
| ^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `T::make(P)` can be evaluated` | ^^^^^^^^^^^^^^^^^ cannot normalize `Struct<T, P>::field::{constant#0}`
|
note: required by a bound in `Struct`
--> $DIR/const-trait-bounds.rs:18:11
|
LL | struct Struct<T: const Trait, const P: usize>
| ------ required by a bound in this struct
LL | where
LL | [u32; T::make(P)]:,
| ^^^^^^^^^^ required by this bound in `Struct`
error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#1}` error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#1}`
--> $DIR/const-trait-bounds.rs:13:5 --> $DIR/const-trait-bounds.rs:13:5

View File

@ -14,6 +14,5 @@ struct Wrapper<const C: <i32 as Trait>::Type> {}
impl<const C: usize> Wrapper<C> {} impl<const C: usize> Wrapper<C> {}
//~^ ERROR the constant `C` is not of type `<i32 as Trait>::Type` //~^ ERROR the constant `C` is not of type `<i32 as Trait>::Type`
//~^^ ERROR mismatched types
fn main() {} fn main() {}

View File

@ -20,17 +20,5 @@ note: required by a const generic parameter in `Wrapper`
LL | struct Wrapper<const C: <i32 as Trait>::Type> {} LL | struct Wrapper<const C: <i32 as Trait>::Type> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper`
error[E0308]: mismatched types error: aborting due to 2 previous errors
--> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30
|
LL | impl<const C: usize> Wrapper<C> {}
| ^ expected associated type, found `usize`
|
= note: expected associated type `<i32 as Trait>::Type`
found type `usize`
= help: consider constraining the associated type `<i32 as Trait>::Type` to `usize`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -6,7 +6,6 @@
struct S<const L: usize>; struct S<const L: usize>;
impl<const N: i32> Copy for S<N> {} impl<const N: i32> Copy for S<N> {}
//~^ ERROR: mismatched types
impl<const M: usize> Copy for S<M> {} impl<const M: usize> Copy for S<M> {}
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`

View File

@ -1,19 +1,11 @@
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
--> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
| |
LL | impl<const N: i32> Copy for S<N> {} LL | impl<const N: i32> Copy for S<N> {}
| -------------------------------- first implementation here | -------------------------------- first implementation here
LL |
LL | impl<const M: usize> Copy for S<M> {} LL | impl<const M: usize> Copy for S<M> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
error[E0308]: mismatched types error: aborting due to 1 previous error
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:31
|
LL | impl<const N: i32> Copy for S<N> {}
| ^ expected `usize`, found `i32`
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`.
Some errors have detailed explanations: E0119, E0308.
For more information about an error, try `rustc --explain E0119`.

View File

@ -123,15 +123,15 @@ hir-stats Lifetime 24 ( 0.3%) 1 24
hir-stats Mod 32 ( 0.4%) 1 32 hir-stats Mod 32 ( 0.4%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40 hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats TraitItemRef 56 ( 0.6%) 2 28
hir-stats GenericArg 64 ( 0.7%) 4 16
hir-stats - Type 16 ( 0.2%) 1
hir-stats - Lifetime 48 ( 0.5%) 3
hir-stats Local 64 ( 0.7%) 1 64 hir-stats Local 64 ( 0.7%) 1 64
hir-stats Param 64 ( 0.7%) 2 32 hir-stats Param 64 ( 0.7%) 2 32
hir-stats Body 72 ( 0.8%) 3 24 hir-stats Body 72 ( 0.8%) 3 24
hir-stats InlineAsm 72 ( 0.8%) 1 72 hir-stats InlineAsm 72 ( 0.8%) 1 72
hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats ImplItemRef 72 ( 0.8%) 2 36
hir-stats Arm 80 ( 0.9%) 2 40 hir-stats Arm 80 ( 0.9%) 2 40
hir-stats GenericArg 96 ( 1.1%) 4 24
hir-stats - Type 24 ( 0.3%) 1
hir-stats - Lifetime 72 ( 0.8%) 3
hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats FieldDef 96 ( 1.1%) 2 48
hir-stats Stmt 96 ( 1.1%) 3 32 hir-stats Stmt 96 ( 1.1%) 3 32
hir-stats - Let 32 ( 0.4%) 1 hir-stats - Let 32 ( 0.4%) 1
@ -155,8 +155,8 @@ hir-stats Generics 560 ( 6.2%) 10 56
hir-stats Ty 720 ( 8.0%) 15 48 hir-stats Ty 720 ( 8.0%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1
hir-stats - Path 624 ( 6.9%) 13 hir-stats - Path 624 ( 7.0%) 13
hir-stats Expr 768 ( 8.5%) 12 64 hir-stats Expr 768 ( 8.6%) 12 64
hir-stats - Path 64 ( 0.7%) 1 hir-stats - Path 64 ( 0.7%) 1
hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1
hir-stats - Match 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1
@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4
hir-stats Path 1_240 (13.8%) 31 40 hir-stats Path 1_240 (13.8%) 31 40
hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats PathSegment 1_920 (21.4%) 40 48
hir-stats ---------------------------------------------------------------- hir-stats ----------------------------------------------------------------
hir-stats Total 8_992 hir-stats Total 8_960
hir-stats hir-stats

View File

@ -1,11 +0,0 @@
#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete
fn b()
where
for<const C: usize> [(); C]: Copy,
//~^ ERROR cannot capture late-bound const parameter in constant
{
}
fn main() {}

View File

@ -1,19 +0,0 @@
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/capture-late-ct-in-anon.rs:1:12
|
LL | #![feature(non_lifetime_binders)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
= note: `#[warn(incomplete_features)]` on by default
error: cannot capture late-bound const parameter in constant
--> $DIR/capture-late-ct-in-anon.rs:6:30
|
LL | for<const C: usize> [(); C]: Copy,
| -------------- ^
| |
| parameter defined here
error: aborting due to 1 previous error; 1 warning emitted

View File

@ -7,7 +7,6 @@ mod assert {
where where
Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
//~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume` //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
//~| ERROR: mismatched types
{ {
} }
} }

View File

@ -13,13 +13,6 @@ LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
note: required by a const generic parameter in `BikeshedIntrinsicFrom` note: required by a const generic parameter in `BikeshedIntrinsicFrom`
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
error[E0308]: mismatched types error: aborting due to 2 previous errors
--> $DIR/issue-101739-1.rs:8:41
|
LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0412`.
Some errors have detailed explanations: E0308, E0412.
For more information about an error, try `rustc --explain E0308`.

View File

@ -16,7 +16,7 @@ mod assert {
where where
Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied
Src, Src,
ASSUME_ALIGNMENT, //~ ERROR: mismatched types ASSUME_ALIGNMENT,
ASSUME_LIFETIMES, ASSUME_LIFETIMES,
ASSUME_VALIDITY, ASSUME_VALIDITY,
ASSUME_VISIBILITY, ASSUME_VISIBILITY,

View File

@ -9,13 +9,6 @@ LL | | ASSUME_VALIDITY,
LL | | ASSUME_VISIBILITY, LL | | ASSUME_VISIBILITY,
| |_____________________________- help: remove these generic arguments | |_____________________________- help: remove these generic arguments
error[E0308]: mismatched types error: aborting due to 1 previous error
--> $DIR/issue-101739-2.rs:19:13
|
LL | ASSUME_ALIGNMENT,
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0107`.
Some errors have detailed explanations: E0107, E0308.
For more information about an error, try `rustc --explain E0107`.

View File

@ -5,7 +5,7 @@
trait Trait { trait Trait {
fn func<const N: u32>() -> [ (); N ]; //~ ERROR mismatched types fn func<const N: u32>() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize`
} }
struct S {} struct S {}

View File

@ -4,11 +4,11 @@ error[E0308]: mismatched types
LL | fn func<const N: u32>() -> [ (); { () }] { LL | fn func<const N: u32>() -> [ (); { () }] {
| ^^ expected `usize`, found `()` | ^^ expected `usize`, found `()`
error[E0308]: mismatched types error: the constant `N` is not of type `usize`
--> $DIR/const-in-impl-fn-return-type.rs:8:38 --> $DIR/const-in-impl-fn-return-type.rs:8:32
| |
LL | fn func<const N: u32>() -> [ (); N ]; LL | fn func<const N: u32>() -> [ (); N ];
| ^ expected `usize`, found `u32` | ^^^^^^^^^ expected `usize`, found `u32`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors