mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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:
parent
1c49d406b6
commit
37ed7a4438
@ -224,13 +224,16 @@ 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();
|
||||||
self.create_def(
|
// HACK(min_generic_const_args): see lower_anon_const
|
||||||
parent_def_id,
|
if !expr.is_potential_trivial_const_arg() {
|
||||||
node_id,
|
self.create_def(
|
||||||
kw::Empty,
|
parent_def_id,
|
||||||
DefKind::AnonConst,
|
node_id,
|
||||||
*op_sp,
|
kw::Empty,
|
||||||
);
|
DefKind::AnonConst,
|
||||||
|
*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),
|
||||||
|
@ -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_id: this.lower_node_id(c.id),
|
hir::ConstBlock {
|
||||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
def_id,
|
||||||
|
hir_id: this.lower_node_id(c.id),
|
||||||
|
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();
|
||||||
|
|
||||||
// Add a definition for the in-band const def.
|
// HACK(min_generic_const_args): see lower_anon_const
|
||||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
|
if !arg.is_potential_trivial_const_arg() {
|
||||||
|
// Add a definition for the in-band const def.
|
||||||
|
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,22 +675,24 @@ 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.coroutine_kind = Some(coroutine_kind);
|
this.lower_body(move |this| {
|
||||||
|
this.coroutine_kind = Some(coroutine_kind);
|
||||||
|
|
||||||
let old_ctx = this.task_context;
|
let old_ctx = this.task_context;
|
||||||
if task_context.is_some() {
|
if task_context.is_some() {
|
||||||
this.task_context = task_context;
|
this.task_context = task_context;
|
||||||
}
|
}
|
||||||
let res = body(this);
|
let res = body(this);
|
||||||
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,27 +971,30 @@ 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| {
|
||||||
let mut coroutine_kind = if this
|
this.with_def_id_parent(closure_def_id, move |this| {
|
||||||
.attrs
|
let mut coroutine_kind = if this
|
||||||
.get(&closure_hir_id.local_id)
|
.attrs
|
||||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
.get(&closure_hir_id.local_id)
|
||||||
{
|
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
{
|
||||||
} else {
|
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||||
None
|
} else {
|
||||||
};
|
None
|
||||||
let body_id = this.lower_fn_body(decl, |this| {
|
};
|
||||||
this.coroutine_kind = coroutine_kind;
|
let body_id = this.lower_fn_body(decl, |this| {
|
||||||
let e = this.lower_expr_mut(body);
|
this.coroutine_kind = coroutine_kind;
|
||||||
coroutine_kind = this.coroutine_kind;
|
let e = this.lower_expr_mut(body);
|
||||||
e
|
coroutine_kind = this.coroutine_kind;
|
||||||
});
|
e
|
||||||
let coroutine_option =
|
});
|
||||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
let coroutine_option =
|
||||||
(body_id, coroutine_option)
|
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||||
|
(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,27 +1084,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let body = self.with_new_scopes(fn_decl_span, |this| {
|
let body = self.with_new_scopes(fn_decl_span, |this| {
|
||||||
let inner_decl =
|
this.with_def_id_parent(closure_def_id, |this| {
|
||||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
let inner_decl =
|
||||||
|
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||||
|
|
||||||
// Transform `async |x: u8| -> X { ... }` into
|
// Transform `async |x: u8| -> X { ... }` into
|
||||||
// `|x: u8| || -> X { ... }`.
|
// `|x: u8| || -> X { ... }`.
|
||||||
let body_id = this.lower_body(|this| {
|
let body_id = this.lower_body(|this| {
|
||||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||||
&inner_decl,
|
&inner_decl,
|
||||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||||
fn_decl_span,
|
fn_decl_span,
|
||||||
body.span,
|
body.span,
|
||||||
coroutine_kind,
|
coroutine_kind,
|
||||||
hir::CoroutineSource::Closure,
|
hir::CoroutineSource::Closure,
|
||||||
);
|
);
|
||||||
|
|
||||||
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||||
|
|
||||||
(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,
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,64 +2351,146 @@ 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> {
|
||||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
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.
|
||||||
|
|
||||||
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();
|
||||||
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,
|
||||||
kind: ExprKind::Path(None, path.clone()),
|
kind: ExprKind::Path(None, path.clone()),
|
||||||
span,
|
span,
|
||||||
attrs: AttrVec::new(),
|
attrs: AttrVec::new(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ct = self.with_new_scopes(span, |this| {
|
||||||
|
self.arena.alloc(hir::AnonConst {
|
||||||
|
def_id,
|
||||||
|
hir_id,
|
||||||
|
body: this.with_def_id_parent(def_id, |this| {
|
||||||
|
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||||
|
}),
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
hir::ConstArgKind::Anon(ct)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ct = self.with_new_scopes(span, |this| {
|
|
||||||
self.arena.alloc(hir::AnonConst {
|
|
||||||
def_id,
|
|
||||||
hir_id: this.lower_node_id(node_id),
|
|
||||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
|
||||||
span,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
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)
|
||||||
span: this.lower_span(c.value.span),
|
// 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),
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 span(&self) -> Span {
|
pub fn anon_const_hir_id(&self) -> Option<HirId> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ConstArgKind::Anon(anon) => anon.span,
|
ConstArgKind::Anon(ac) => Some(ac.hir_id),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: convert to field, where ConstArg has its own HirId
|
pub fn span(&self) -> Span {
|
||||||
pub fn hir_id(&self) -> HirId {
|
|
||||||
self.anon_const_hir_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn anon_const_hir_id(&self) -> HirId {
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ConstArgKind::Anon(anon) => anon.hir_id,
|
ConstArgKind::Path(path) => path.span(),
|
||||||
|
ConstArgKind::Anon(anon) => anon.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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(..)
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
),
|
||||||
}) =>
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.typeck(def_id).node_type(hir_id);
|
return tcx.types.usize;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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:?}"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
|
@ -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)));
|
||||||
|
@ -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!(
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,22 +468,17 @@ 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.register_wf_obligation(
|
||||||
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
|
ct.into(),
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, did);
|
self.tcx.hir().span(const_arg.hir_id),
|
||||||
self.register_wf_obligation(
|
ObligationCauseCode::WellFormed(None),
|
||||||
ct.into(),
|
);
|
||||||
self.tcx.hir().span(anon.hir_id),
|
ct
|
||||||
ObligationCauseCode::WellFormed(None),
|
|
||||||
);
|
|
||||||
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
|
||||||
|
@ -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"),
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +312,19 @@ 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
|
||||||
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
// 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
|
@ -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, _) => {
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
11
tests/crashes/127009.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//@ known-bug: #127009
|
||||||
|
|
||||||
|
#![feature(non_lifetime_binders)]
|
||||||
|
|
||||||
|
fn b()
|
||||||
|
where
|
||||||
|
for<const C: usize> [(); C]: Copy,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -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.
|
||||||
|
@ -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() {}
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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`
|
||||||
|
@ -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.
|
||||||
|
@ -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: () }
|
||||||
|
@ -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> {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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() {}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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() {}
|
||||||
|
@ -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`.
|
||||||
|
@ -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
|
||||||
|
|
|
|
||||||
|
@ -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() {}
|
||||||
|
@ -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`.
|
||||||
|
@ -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
|
||||||
|
@ -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() {}
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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<_>`
|
||||||
|
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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
|
||||||
|
@ -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() {}
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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,
|
||||||
|
@ -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`.
|
|
||||||
|
@ -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 {}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user