Auto merge of #125915 - camelid:const-arg-refactor, r=BoxyUwU
Represent type-level consts with new-and-improved `hir::ConstArg` ### Summary This is a step toward `min_generic_const_exprs`. We now represent all const generic arguments using an enum that differentiates between const *paths* (temporarily just bare const params) and arbitrary anon consts that may perform computations. This will enable us to cleanly implement the `min_generic_const_args` plan of allowing the use of generics in paths used as const args, while disallowing their use in arbitrary anon consts. Here is a summary of the salient aspects of this change: - Add `current_def_id_parent` to `LoweringContext` This is needed to track anon const parents properly once we implement `ConstArgKind::Path` (which requires moving anon const def-creation outside of `DefCollector`). - Create `hir::ConstArgKind` enum with `Path` and `Anon` variants. Use it in the existing `hir::ConstArg` struct, replacing the previous `hir::AnonConst` field. - Use `ConstArg` for all instances of const args. Specifically, use it instead of `AnonConst` for assoc item constraints, array lengths, and const param defaults. - 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 https://github.com/rust-lang/rust/issues/127009. ### Followup items post-merge - Use `ConstArgKind::Path` for all const paths, not just const params. - Fix (no github dont close this issue) #127009 - If a path in generic args doesn't resolve as a type, try to resolve as a const instead (do this in rustc_resolve). Then remove the special-casing from `rustc_ast_lowering`, so that all params will automatically be lowered as `ConstArgKind::Path`. - (?) Consider making `const_evaluatable_unchecked` a hard error, or at least trying it in crater r? `@BoxyUwU`
This commit is contained in:
commit
8c3a94a1c7
72 changed files with 853 additions and 543 deletions
|
@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
hir::InlineAsmOperand::Const {
|
hir::InlineAsmOperand::Const {
|
||||||
anon_const: self.lower_anon_const(anon_const),
|
anon_const: self.lower_anon_const_to_anon_const(anon_const),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineAsmOperand::Sym { sym } => {
|
InlineAsmOperand::Sym { sym } => {
|
||||||
|
@ -222,18 +222,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap the expression in an AnonConst.
|
// Wrap the expression in an AnonConst.
|
||||||
let parent_def_id = self.current_hir_id_owner;
|
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.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(&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)
|
||||||
}
|
}
|
||||||
|
@ -377,17 +382,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let mut generic_args = ThinVec::new();
|
let mut generic_args = ThinVec::new();
|
||||||
for (idx, arg) in args.into_iter().enumerate() {
|
for (idx, arg) in args.into_iter().enumerate() {
|
||||||
if legacy_args_idx.contains(&idx) {
|
if legacy_args_idx.contains(&idx) {
|
||||||
let parent_def_id = self.current_hir_id_owner;
|
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(
|
if !arg.is_potential_trivial_const_arg() {
|
||||||
parent_def_id.def_id,
|
// Add a definition for the in-band const def.
|
||||||
node_id,
|
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
|
||||||
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)));
|
||||||
|
@ -622,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`,
|
||||||
|
@ -672,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: &[],
|
||||||
|
@ -966,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);
|
||||||
|
@ -994,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,
|
||||||
|
@ -1066,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!(
|
||||||
|
@ -1075,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);
|
||||||
|
@ -1106,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,
|
||||||
|
|
|
@ -181,7 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
intravisit::walk_generic_param(self, param);
|
intravisit::walk_generic_param(self, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
|
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) {
|
||||||
self.with_parent(param, |this| {
|
self.with_parent(param, |this| {
|
||||||
intravisit::walk_const_param_default(this, ct);
|
intravisit::walk_const_param_default(this, ct);
|
||||||
})
|
})
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,7 +716,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir_id,
|
hir_id,
|
||||||
def_id: self.local_def_id(v.id),
|
def_id: self.local_def_id(v.id),
|
||||||
data: self.lower_variant_data(hir_id, &v.data),
|
data: self.lower_variant_data(hir_id, &v.data),
|
||||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
|
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
|
||||||
ident: self.lower_ident(v.ident),
|
ident: self.lower_ident(v.ident),
|
||||||
span: self.lower_span(v.span),
|
span: self.lower_span(v.span),
|
||||||
}
|
}
|
||||||
|
@ -1601,7 +1604,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
if let Some((span, hir_id, def_id)) = host_param_parts {
|
if let Some((span, hir_id, def_id)) = host_param_parts {
|
||||||
let const_node_id = self.next_node_id();
|
let const_node_id = self.next_node_id();
|
||||||
let anon_const =
|
let anon_const_did =
|
||||||
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
|
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
|
||||||
|
|
||||||
let const_id = self.next_id();
|
let const_id = self.next_id();
|
||||||
|
@ -1609,7 +1612,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let bool_id = self.next_id();
|
let bool_id = self.next_id();
|
||||||
|
|
||||||
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||||
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
|
self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
|
||||||
|
|
||||||
let const_body = self.lower_body(|this| {
|
let const_body = self.lower_body(|this| {
|
||||||
(
|
(
|
||||||
|
@ -1624,6 +1627,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let default_ac = self.arena.alloc(hir::AnonConst {
|
||||||
|
def_id: anon_const_did,
|
||||||
|
hir_id: const_id,
|
||||||
|
body: const_body,
|
||||||
|
span,
|
||||||
|
});
|
||||||
|
let default_ct = self.arena.alloc(hir::ConstArg {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ConstArgKind::Anon(default_ac),
|
||||||
|
is_desugared_from_effects: false,
|
||||||
|
});
|
||||||
let param = hir::GenericParam {
|
let param = hir::GenericParam {
|
||||||
def_id,
|
def_id,
|
||||||
hir_id,
|
hir_id,
|
||||||
|
@ -1648,12 +1662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
// FIXME(effects) we might not need a default.
|
// FIXME(effects) we might not need a default.
|
||||||
default: Some(self.arena.alloc(hir::AnonConst {
|
default: Some(default_ct),
|
||||||
def_id: anon_const,
|
|
||||||
hir_id: const_id,
|
|
||||||
body: const_body,
|
|
||||||
span,
|
|
||||||
})),
|
|
||||||
is_host_effect: true,
|
is_host_effect: true,
|
||||||
synthetic: true,
|
synthetic: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> {
|
||||||
is_in_dyn_type: bool,
|
is_in_dyn_type: bool,
|
||||||
|
|
||||||
current_hir_id_owner: hir::OwnerId,
|
current_hir_id_owner: hir::OwnerId,
|
||||||
|
/// Why do we need this in addition to [`Self::current_hir_id_owner`]?
|
||||||
|
///
|
||||||
|
/// Currently (as of June 2024), anonymous constants are not HIR owners; however,
|
||||||
|
/// 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
|
||||||
|
/// name resolution whether an anonymous constant will end up instead being a
|
||||||
|
/// [`hir::ConstArgKind::Path`]. However, to compute which generics are
|
||||||
|
/// 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
|
||||||
|
/// item. So we need to track parent defs differently from HIR owners, since they
|
||||||
|
/// will be finer-grained in the case of anon consts.
|
||||||
|
current_def_id_parent: LocalDefId,
|
||||||
item_local_id_counter: hir::ItemLocalId,
|
item_local_id_counter: hir::ItemLocalId,
|
||||||
trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
|
trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
|
||||||
|
|
||||||
|
@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
attrs: SortedMap::default(),
|
attrs: SortedMap::default(),
|
||||||
children: Vec::default(),
|
children: Vec::default(),
|
||||||
current_hir_id_owner: hir::CRATE_OWNER_ID,
|
current_hir_id_owner: hir::CRATE_OWNER_ID,
|
||||||
|
current_def_id_parent: CRATE_DEF_ID,
|
||||||
item_local_id_counter: hir::ItemLocalId::ZERO,
|
item_local_id_counter: hir::ItemLocalId::ZERO,
|
||||||
node_id_to_local_id: Default::default(),
|
node_id_to_local_id: Default::default(),
|
||||||
trait_map: Default::default(),
|
trait_map: Default::default(),
|
||||||
|
@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
|
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
|
||||||
debug_assert_eq!(_old, None);
|
debug_assert_eq!(_old, None);
|
||||||
|
|
||||||
let item = f(self);
|
let item = self.with_def_id_parent(def_id, f);
|
||||||
debug_assert_eq!(def_id, item.def_id().def_id);
|
debug_assert_eq!(def_id, item.def_id().def_id);
|
||||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||||
debug_assert!(self.impl_trait_defs.is_empty());
|
debug_assert!(self.impl_trait_defs.is_empty());
|
||||||
|
@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.children.push((def_id, hir::MaybeOwner::Owner(info)));
|
self.children.push((def_id, hir::MaybeOwner::Owner(info)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||||
|
let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent);
|
||||||
|
let result = f(self);
|
||||||
|
self.current_def_id_parent = current_def_id_parent;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Installs the remapping `remap` in scope while `f` is being executed.
|
/// Installs the remapping `remap` in scope while `f` is being executed.
|
||||||
/// This causes references to the `LocalDefId` keys to be changed to
|
/// This causes references to the `LocalDefId` keys to be changed to
|
||||||
/// refer to the values instead.
|
/// refer to the values instead.
|
||||||
|
@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
LifetimeRes::Fresh { param, kind, .. } => {
|
LifetimeRes::Fresh { param, kind, .. } => {
|
||||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||||
let _def_id = self.create_def(
|
let _def_id = self.create_def(
|
||||||
self.current_hir_id_owner.def_id,
|
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||||
param,
|
param,
|
||||||
kw::UnderscoreLifetime,
|
kw::UnderscoreLifetime,
|
||||||
DefKind::LifetimeParam,
|
DefKind::LifetimeParam,
|
||||||
|
@ -1044,7 +1064,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
AssocItemConstraintKind::Equality { term } => {
|
AssocItemConstraintKind::Equality { term } => {
|
||||||
let term = match term {
|
let term = match term {
|
||||||
Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
|
Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
|
||||||
Term::Const(c) => self.lower_anon_const(c).into(),
|
Term::Const(c) => self.lower_anon_const_to_const_arg(c).into(),
|
||||||
};
|
};
|
||||||
hir::AssocItemConstraintKind::Equality { term }
|
hir::AssocItemConstraintKind::Equality { term }
|
||||||
}
|
}
|
||||||
|
@ -1150,42 +1170,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
ty,
|
ty,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
let ct =
|
||||||
|
self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);
|
||||||
let parent_def_id = self.current_hir_id_owner;
|
return GenericArg::Const(ct);
|
||||||
let node_id = self.next_node_id();
|
|
||||||
let span = self.lower_span(ty.span);
|
|
||||||
|
|
||||||
// Add a definition for the in-band const def.
|
|
||||||
let def_id = self.create_def(
|
|
||||||
parent_def_id.def_id,
|
|
||||||
node_id,
|
|
||||||
kw::Empty,
|
|
||||||
DefKind::AnonConst,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
|
|
||||||
let path_expr = Expr {
|
|
||||||
id: ty.id,
|
|
||||||
kind: ExprKind::Path(None, path.clone()),
|
|
||||||
span,
|
|
||||||
attrs: AttrVec::new(),
|
|
||||||
tokens: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
return GenericArg::Const(ConstArg {
|
|
||||||
value: ct,
|
|
||||||
is_desugared_from_effects: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,10 +1180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
GenericArg::Type(self.lower_ty(ty, itctx))
|
GenericArg::Type(self.lower_ty(ty, itctx))
|
||||||
}
|
}
|
||||||
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
|
ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)),
|
||||||
value: self.lower_anon_const(ct),
|
|
||||||
is_desugared_from_effects: false,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1355,7 +1339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
TyKind::Array(ty, length) => {
|
TyKind::Array(ty, length) => {
|
||||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
||||||
}
|
}
|
||||||
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
|
||||||
TyKind::TraitObject(bounds, kind) => {
|
TyKind::TraitObject(bounds, kind) => {
|
||||||
let mut lifetime_bound = None;
|
let mut lifetime_bound = None;
|
||||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||||
|
@ -1429,7 +1413,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
);
|
);
|
||||||
|
|
||||||
self.create_def(
|
self.create_def(
|
||||||
self.current_hir_id_owner.def_id,
|
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||||
*def_node_id,
|
*def_node_id,
|
||||||
ident.name,
|
ident.name,
|
||||||
DefKind::TyParam,
|
DefKind::TyParam,
|
||||||
|
@ -1637,7 +1621,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
||||||
) -> hir::TyKind<'hir> {
|
) -> hir::TyKind<'hir> {
|
||||||
let opaque_ty_def_id = self.create_def(
|
let opaque_ty_def_id = self.create_def(
|
||||||
self.current_hir_id_owner.def_id,
|
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||||
opaque_ty_node_id,
|
opaque_ty_node_id,
|
||||||
kw::Empty,
|
kw::Empty,
|
||||||
DefKind::OpaqueTy,
|
DefKind::OpaqueTy,
|
||||||
|
@ -2222,7 +2206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|def| self.lower_anon_const(def));
|
.map(|def| self.lower_anon_const_to_const_arg(def));
|
||||||
|
|
||||||
(
|
(
|
||||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||||
|
@ -2360,19 +2344,153 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
"using `_` for array lengths is unstable",
|
"using `_` for array lengths is unstable",
|
||||||
)
|
)
|
||||||
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
|
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
|
||||||
hir::ArrayLen::Body(self.lower_anon_const(c))
|
hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
|
_ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
|
#[instrument(level = "debug", skip(self))]
|
||||||
self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst {
|
fn lower_const_path_to_const_arg(
|
||||||
def_id: this.local_def_id(c.id),
|
&mut self,
|
||||||
hir_id: this.lower_node_id(c.id),
|
path: &Path,
|
||||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
res: Res<NodeId>,
|
||||||
span: this.lower_span(c.value.span),
|
ty_id: NodeId,
|
||||||
|
span: Span,
|
||||||
|
) -> &'hir hir::ConstArg<'hir> {
|
||||||
|
let ct_kind = match res {
|
||||||
|
Res::Def(DefKind::ConstParam, _) => {
|
||||||
|
let qpath = self.lower_qpath(
|
||||||
|
ty_id,
|
||||||
|
&None,
|
||||||
|
path,
|
||||||
|
ParamMode::Optional,
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
hir::ConstArgKind::Path(qpath)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||||
|
|
||||||
|
let parent_def_id = self.current_def_id_parent;
|
||||||
|
let node_id = self.next_node_id();
|
||||||
|
let span = self.lower_span(span);
|
||||||
|
|
||||||
|
// 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 hir_id = self.lower_node_id(node_id);
|
||||||
|
|
||||||
|
let path_expr = Expr {
|
||||||
|
id: ty_id,
|
||||||
|
kind: ExprKind::Path(None, path.clone()),
|
||||||
|
span,
|
||||||
|
attrs: AttrVec::new(),
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.arena.alloc(hir::ConstArg {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: ct_kind,
|
||||||
|
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> {
|
||||||
|
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
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);
|
||||||
|
ConstArg {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ConstArgKind::Anon(lowered_anon),
|
||||||
|
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 {
|
||||||
|
if c.value.is_potential_trivial_const_arg() {
|
||||||
|
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
|
||||||
|
// Over there, we guess if this is a bare param and only create a def if
|
||||||
|
// we think it's not. However we may can guess wrong (see there for example)
|
||||||
|
// in which case we have to create the def here.
|
||||||
|
self.create_def(
|
||||||
|
self.current_def_id_parent,
|
||||||
|
c.id,
|
||||||
|
kw::Empty,
|
||||||
|
DefKind::AnonConst,
|
||||||
|
c.value.span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
|
||||||
|
let def_id = this.local_def_id(c.id);
|
||||||
|
let hir_id = this.lower_node_id(c.id);
|
||||||
|
hir::AnonConst {
|
||||||
|
def_id,
|
||||||
|
hir_id,
|
||||||
|
body: this.with_def_id_parent(def_id, |this| {
|
||||||
|
this.lower_const_body(c.value.span, Some(&c.value))
|
||||||
|
}),
|
||||||
|
span: this.lower_span(c.value.span),
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,13 +228,53 @@ impl<'hir> PathSegment<'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A constant that enters the type system, used for arguments to const generics (e.g. array lengths).
|
||||||
|
///
|
||||||
|
/// These are distinct from [`AnonConst`] as anon consts in the type system are not allowed
|
||||||
|
/// to use any generic parameters, therefore we must represent `N` differently. Additionally
|
||||||
|
/// future designs for supporting generic parameters in const arguments will likely not use
|
||||||
|
/// an anon const based design.
|
||||||
|
///
|
||||||
|
/// 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> {
|
||||||
pub value: &'hir AnonConst,
|
#[stable_hasher(ignore)]
|
||||||
|
pub hir_id: HirId,
|
||||||
|
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> {
|
||||||
|
pub fn anon_const_hir_id(&self) -> Option<HirId> {
|
||||||
|
match self.kind {
|
||||||
|
ConstArgKind::Anon(ac) => Some(ac.hir_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
match self.kind {
|
||||||
|
ConstArgKind::Path(path) => path.span(),
|
||||||
|
ConstArgKind::Anon(anon) => anon.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See [`ConstArg`].
|
||||||
|
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||||
pub struct InferArg {
|
pub struct InferArg {
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
@ -251,7 +291,7 @@ impl InferArg {
|
||||||
pub enum GenericArg<'hir> {
|
pub enum GenericArg<'hir> {
|
||||||
Lifetime(&'hir Lifetime),
|
Lifetime(&'hir Lifetime),
|
||||||
Type(&'hir Ty<'hir>),
|
Type(&'hir Ty<'hir>),
|
||||||
Const(ConstArg<'hir>),
|
Const(&'hir ConstArg<'hir>),
|
||||||
Infer(InferArg),
|
Infer(InferArg),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +300,7 @@ impl GenericArg<'_> {
|
||||||
match self {
|
match self {
|
||||||
GenericArg::Lifetime(l) => l.ident.span,
|
GenericArg::Lifetime(l) => l.ident.span,
|
||||||
GenericArg::Type(t) => t.span,
|
GenericArg::Type(t) => t.span,
|
||||||
GenericArg::Const(c) => c.value.span,
|
GenericArg::Const(c) => c.span(),
|
||||||
GenericArg::Infer(i) => i.span,
|
GenericArg::Infer(i) => i.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,7 +309,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.value.hir_id,
|
GenericArg::Const(c) => c.hir_id,
|
||||||
GenericArg::Infer(i) => i.hir_id,
|
GenericArg::Infer(i) => i.hir_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,7 +564,7 @@ pub enum GenericParamKind<'hir> {
|
||||||
Const {
|
Const {
|
||||||
ty: &'hir Ty<'hir>,
|
ty: &'hir Ty<'hir>,
|
||||||
/// Optional default value for the const generic param
|
/// Optional default value for the const generic param
|
||||||
default: Option<&'hir AnonConst>,
|
default: Option<&'hir ConstArg<'hir>>,
|
||||||
is_host_effect: bool,
|
is_host_effect: bool,
|
||||||
synthetic: bool,
|
synthetic: bool,
|
||||||
},
|
},
|
||||||
|
@ -1598,13 +1638,13 @@ pub type Lit = Spanned<LitKind>;
|
||||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||||
pub enum ArrayLen<'hir> {
|
pub enum ArrayLen<'hir> {
|
||||||
Infer(InferArg),
|
Infer(InferArg),
|
||||||
Body(&'hir AnonConst),
|
Body(&'hir ConstArg<'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, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => {
|
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => {
|
||||||
*hir_id
|
*hir_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2434,7 +2474,7 @@ impl<'hir> AssocItemConstraint<'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the const on the RHS of an assoc const equality constraint if applicable.
|
/// Obtain the const on the RHS of an assoc const equality constraint if applicable.
|
||||||
pub fn ct(self) -> Option<&'hir AnonConst> {
|
pub fn ct(self) -> Option<&'hir ConstArg<'hir>> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
|
AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -2445,7 +2485,7 @@ impl<'hir> AssocItemConstraint<'hir> {
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum Term<'hir> {
|
pub enum Term<'hir> {
|
||||||
Ty(&'hir Ty<'hir>),
|
Ty(&'hir Ty<'hir>),
|
||||||
Const(&'hir AnonConst),
|
Const(&'hir ConstArg<'hir>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
|
impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
|
||||||
|
@ -2454,8 +2494,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> From<&'hir AnonConst> for Term<'hir> {
|
impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> {
|
||||||
fn from(c: &'hir AnonConst) -> Self {
|
fn from(c: &'hir ConstArg<'hir>) -> Self {
|
||||||
Term::Const(c)
|
Term::Const(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3689,6 +3729,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>),
|
||||||
|
@ -3750,6 +3791,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(..)
|
||||||
|
@ -3966,7 +4008,7 @@ mod size_asserts {
|
||||||
static_assert_size!(FnDecl<'_>, 40);
|
static_assert_size!(FnDecl<'_>, 40);
|
||||||
static_assert_size!(ForeignItem<'_>, 72);
|
static_assert_size!(ForeignItem<'_>, 72);
|
||||||
static_assert_size!(ForeignItemKind<'_>, 40);
|
static_assert_size!(ForeignItemKind<'_>, 40);
|
||||||
static_assert_size!(GenericArg<'_>, 24);
|
static_assert_size!(GenericArg<'_>, 16);
|
||||||
static_assert_size!(GenericBound<'_>, 48);
|
static_assert_size!(GenericBound<'_>, 48);
|
||||||
static_assert_size!(Generics<'_>, 56);
|
static_assert_size!(Generics<'_>, 56);
|
||||||
static_assert_size!(Impl<'_>, 80);
|
static_assert_size!(Impl<'_>, 80);
|
||||||
|
|
|
@ -347,6 +347,9 @@ pub trait Visitor<'v>: Sized {
|
||||||
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
|
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
|
||||||
walk_inline_const(self, c)
|
walk_inline_const(self, c)
|
||||||
}
|
}
|
||||||
|
fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
|
||||||
|
walk_const_arg(self, c)
|
||||||
|
}
|
||||||
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
|
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
|
||||||
walk_expr(self, ex)
|
walk_expr(self, ex)
|
||||||
}
|
}
|
||||||
|
@ -364,7 +367,7 @@ pub trait Visitor<'v>: Sized {
|
||||||
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
|
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
|
||||||
walk_generic_param(self, p)
|
walk_generic_param(self, p)
|
||||||
}
|
}
|
||||||
fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result {
|
fn visit_const_param_default(&mut self, _param: HirId, ct: &'v ConstArg<'v>) -> Self::Result {
|
||||||
walk_const_param_default(self, ct)
|
walk_const_param_default(self, ct)
|
||||||
}
|
}
|
||||||
fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
|
fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
|
||||||
|
@ -708,7 +711,7 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>
|
||||||
match len {
|
match len {
|
||||||
// FIXME: Use `visit_infer` here.
|
// FIXME: Use `visit_infer` here.
|
||||||
ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
|
ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
|
||||||
ArrayLen::Body(c) => visitor.visit_anon_const(c),
|
ArrayLen::Body(c) => visitor.visit_const_arg(c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,6 +728,17 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>(
|
||||||
visitor.visit_nested_body(constant.body)
|
visitor.visit_nested_body(constant.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_const_arg<'v, V: Visitor<'v>>(
|
||||||
|
visitor: &mut V,
|
||||||
|
const_arg: &'v ConstArg<'v>,
|
||||||
|
) -> V::Result {
|
||||||
|
try_visit!(visitor.visit_id(const_arg.hir_id));
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
|
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
|
||||||
try_visit!(visitor.visit_id(expression.hir_id));
|
try_visit!(visitor.visit_id(expression.hir_id));
|
||||||
match expression.kind {
|
match expression.kind {
|
||||||
|
@ -928,9 +942,9 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
|
||||||
|
|
||||||
pub fn walk_const_param_default<'v, V: Visitor<'v>>(
|
pub fn walk_const_param_default<'v, V: Visitor<'v>>(
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
ct: &'v AnonConst,
|
ct: &'v ConstArg<'v>,
|
||||||
) -> V::Result {
|
) -> V::Result {
|
||||||
visitor.visit_anon_const(ct)
|
visitor.visit_const_arg(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
|
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
|
||||||
|
@ -1216,7 +1230,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(
|
||||||
match generic_arg {
|
match generic_arg {
|
||||||
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
|
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
|
||||||
GenericArg::Type(ty) => visitor.visit_ty(ty),
|
GenericArg::Type(ty) => visitor.visit_ty(ty),
|
||||||
GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value),
|
GenericArg::Const(ct) => visitor.visit_const_arg(ct),
|
||||||
GenericArg::Infer(inf) => visitor.visit_infer(inf),
|
GenericArg::Infer(inf) => visitor.visit_infer(inf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1278,7 +1292,7 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
|
||||||
match constraint.kind {
|
match constraint.kind {
|
||||||
AssocItemConstraintKind::Equality { ref term } => match term {
|
AssocItemConstraintKind::Equality { ref term } => match term {
|
||||||
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
||||||
Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
|
Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)),
|
||||||
},
|
},
|
||||||
AssocItemConstraintKind::Bound { bounds } => {
|
AssocItemConstraintKind::Bound { bounds } => {
|
||||||
walk_list!(visitor, visit_param_bound, bounds)
|
walk_list!(visitor, visit_param_bound, bounds)
|
||||||
|
|
|
@ -304,7 +304,9 @@ 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
|
||||||
self.tcx.ensure().type_of(default.def_id);
|
if let hir::ConstArgKind::Anon(ac) = default.kind {
|
||||||
|
self.tcx.ensure().type_of(ac.def_id);
|
||||||
|
}
|
||||||
self.tcx.ensure().const_param_default(param.def_id);
|
self.tcx.ensure().const_param_default(param.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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,7 @@ fn const_evaluatable_predicates_of(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
|
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
|
||||||
// Do not look into const param defaults,
|
// Do not look into const param defaults,
|
||||||
// these get checked when they are actually instantiated.
|
// these get checked when they are actually instantiated.
|
||||||
//
|
//
|
||||||
|
|
|
@ -954,7 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
GenericParamKind::Const { ty, default, .. } => {
|
GenericParamKind::Const { ty, default, .. } => {
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
self.visit_body(self.tcx.hir().body(default.body));
|
self.visit_const_arg(default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1594,7 +1594,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
GenericArg::Const(ct) => {
|
GenericArg::Const(ct) => {
|
||||||
self.visit_anon_const(&ct.value);
|
self.visit_const_arg(ct);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
GenericArg::Infer(inf) => {
|
GenericArg::Infer(inf) => {
|
||||||
|
|
|
@ -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.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.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:?}"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -413,12 +413,18 @@ 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(anon_const) = constraint.ct() {
|
if let Some(const_arg) = constraint.ct() {
|
||||||
let ty = alias_term
|
if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
|
||||||
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
let ty = alias_term
|
||||||
let ty =
|
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
||||||
check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
|
let ty = check_assoc_const_binding_type(
|
||||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
self,
|
||||||
|
constraint.ident,
|
||||||
|
ty,
|
||||||
|
constraint.hir_id,
|
||||||
|
);
|
||||||
|
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_term
|
alias_term
|
||||||
|
@ -435,7 +441,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
hir::AssocItemConstraintKind::Equality { term } => {
|
hir::AssocItemConstraintKind::Equality { term } => {
|
||||||
let term = match term {
|
let term = match term {
|
||||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||||
hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
|
hir::Term::Const(ct) => {
|
||||||
|
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find any late-bound regions declared in `ty` that are not
|
// Find any late-bound regions declared in `ty` that are not
|
||||||
|
|
|
@ -340,7 +340,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
{
|
{
|
||||||
let span = match term {
|
let span = match term {
|
||||||
hir::Term::Ty(ty) => ty.span,
|
hir::Term::Ty(ty) => ty.span,
|
||||||
hir::Term::Const(ct) => tcx.def_span(ct.def_id),
|
hir::Term::Const(ct) => ct.span(),
|
||||||
};
|
};
|
||||||
(span, Some(ident.span), assoc_item.kind, assoc_kind)
|
(span, Some(ident.span), assoc_item.kind, assoc_kind)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1294,8 +1294,7 @@ pub fn prohibit_assoc_item_constraint(
|
||||||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
|
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
|
||||||
GenericParamDefKind::Const { .. },
|
GenericParamDefKind::Const { .. },
|
||||||
) => {
|
) => {
|
||||||
let span = tcx.hir().span(c.hir_id);
|
suggest_direct_use(&mut err, c.span());
|
||||||
suggest_direct_use(&mut err, span);
|
|
||||||
}
|
}
|
||||||
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
|
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
|
||||||
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
|
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
|
||||||
|
|
|
@ -113,8 +113,12 @@ fn generic_arg_mismatch_err(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
||||||
let body = tcx.hir().body(cnst.value.body);
|
// FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
|
||||||
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
|
// this should match against that instead of ::Anon
|
||||||
|
if let hir::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)));
|
||||||
|
|
|
@ -471,11 +471,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
handle_ty_args(has_default, &inf.to_ty())
|
handle_ty_args(has_default, &inf.to_ty())
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
let did = ct.value.def_id;
|
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
|
||||||
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
|
.into()
|
||||||
ty::Const::from_anon_const(tcx, did).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!(
|
||||||
|
@ -912,7 +911,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let term: ty::Term<'_> = match term {
|
let term: ty::Term<'_> = match term {
|
||||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||||
hir::Term::Const(ct) => {
|
hir::Term::Const(ct) => {
|
||||||
ty::Const::from_anon_const(tcx, ct.def_id).into()
|
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// FIXME(#97583): This isn't syntactically well-formed!
|
// FIXME(#97583): This isn't syntactically well-formed!
|
||||||
|
@ -2140,7 +2140,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let length = match length {
|
let length = match length {
|
||||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||||
hir::ArrayLen::Body(constant) => {
|
hir::ArrayLen::Body(constant) => {
|
||||||
ty::Const::from_anon_const(tcx, constant.def_id)
|
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,9 @@ use rustc_ast_pretty::pp::{self, Breaks};
|
||||||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
|
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
|
||||||
LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier,
|
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
|
||||||
|
TraitBoundModifier,
|
||||||
};
|
};
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
|
@ -87,6 +88,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),
|
||||||
|
@ -983,7 +985,7 @@ impl<'a> State<'a> {
|
||||||
fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) {
|
fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) {
|
||||||
match len {
|
match len {
|
||||||
hir::ArrayLen::Infer(..) => self.word("_"),
|
hir::ArrayLen::Infer(..) => self.word("_"),
|
||||||
hir::ArrayLen::Body(ct) => self.print_anon_const(ct),
|
hir::ArrayLen::Body(ct) => self.print_const_arg(ct),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,6 +993,13 @@ impl<'a> State<'a> {
|
||||||
self.ann.nested(self, Nested::Body(constant.body))
|
self.ann.nested(self, Nested::Body(constant.body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
|
||||||
|
match &const_arg.kind {
|
||||||
|
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
|
||||||
|
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
|
fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
|
||||||
self.popen();
|
self.popen();
|
||||||
self.commasep_exprs(Inconsistent, args);
|
self.commasep_exprs(Inconsistent, args);
|
||||||
|
@ -1679,7 +1688,7 @@ impl<'a> State<'a> {
|
||||||
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
|
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
|
||||||
GenericArg::Lifetime(_) => {}
|
GenericArg::Lifetime(_) => {}
|
||||||
GenericArg::Type(ty) => s.print_type(ty),
|
GenericArg::Type(ty) => s.print_type(ty),
|
||||||
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
GenericArg::Const(ct) => s.print_const_arg(ct),
|
||||||
GenericArg::Infer(_inf) => s.word("_"),
|
GenericArg::Infer(_inf) => s.word("_"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1720,7 +1729,7 @@ impl<'a> State<'a> {
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
match term {
|
match term {
|
||||||
Term::Ty(ty) => self.print_type(ty),
|
Term::Ty(ty) => self.print_type(ty),
|
||||||
Term::Const(ref c) => self.print_anon_const(c),
|
Term::Const(ref c) => self.print_const_arg(c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::AssocItemConstraintKind::Bound { bounds } => {
|
hir::AssocItemConstraintKind::Bound { bounds } => {
|
||||||
|
@ -2155,7 +2164,7 @@ impl<'a> State<'a> {
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_anon_const(default);
|
self.print_const_arg(default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1439,9 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
|
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
|
||||||
&& let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length
|
&& let hir::ArrayLen::Body(ct) = length
|
||||||
{
|
{
|
||||||
let span = self.tcx.hir().span(hir_id);
|
let span = ct.span();
|
||||||
self.dcx().try_steal_modify_and_emit_err(
|
self.dcx().try_steal_modify_and_emit_err(
|
||||||
span,
|
span,
|
||||||
StashKey::UnderscoreForArrayLengths,
|
StashKey::UnderscoreForArrayLengths,
|
||||||
|
|
|
@ -457,22 +457,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
|
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
|
||||||
match length {
|
match length {
|
||||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||||
hir::ArrayLen::Body(anon_const) => {
|
hir::ArrayLen::Body(const_arg) => {
|
||||||
let span = self.tcx.def_span(anon_const.def_id);
|
let span = const_arg.span();
|
||||||
let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
|
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
|
||||||
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
||||||
self.normalize(span, c)
|
self.normalize(span, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lower_const_arg(&self, hir_ct: &hir::AnonConst, param_def_id: DefId) -> ty::Const<'tcx> {
|
pub fn lower_const_arg(
|
||||||
let did = hir_ct.def_id;
|
&self,
|
||||||
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
|
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, did);
|
param_def_id: DefId,
|
||||||
|
) -> ty::Const<'tcx> {
|
||||||
|
let ct =
|
||||||
|
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
|
||||||
self.register_wf_obligation(
|
self.register_wf_obligation(
|
||||||
ct.into(),
|
ct.into(),
|
||||||
self.tcx.hir().span(hir_ct.hir_id),
|
self.tcx.hir().span(const_arg.hir_id),
|
||||||
ObligationCauseCode::WellFormed(None),
|
ObligationCauseCode::WellFormed(None),
|
||||||
);
|
);
|
||||||
ct
|
ct
|
||||||
|
@ -1298,7 +1301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.fcx.lower_ty(ty).raw.into()
|
self.fcx.lower_ty(ty).raw.into()
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
self.fcx.lower_const_arg(&ct.value, param.def_id).into()
|
self.fcx.lower_const_arg(ct, param.def_id).into()
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||||
self.fcx.ty_infer(Some(param), inf.span).into()
|
self.fcx.ty_infer(Some(param), inf.span).into()
|
||||||
|
|
|
@ -400,7 +400,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
self.cfcx.lower_ty(ty).raw.into()
|
self.cfcx.lower_ty(ty).raw.into()
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
self.cfcx.lower_const_arg(&ct.value, param.def_id).into()
|
self.cfcx.lower_const_arg(ct, param.def_id).into()
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||||
self.cfcx.ty_infer(Some(param), inf.span).into()
|
self.cfcx.ty_infer(Some(param), inf.span).into()
|
||||||
|
|
|
@ -1762,9 +1762,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
if let Some(tykind) = tykind
|
if let Some(tykind) = tykind
|
||||||
&& let hir::TyKind::Array(_, length) = tykind
|
&& let hir::TyKind::Array(_, length) = tykind
|
||||||
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
|
&& let hir::ArrayLen::Body(ct) = length
|
||||||
{
|
{
|
||||||
let span = self.tcx.hir().span(*hir_id);
|
let span = ct.span();
|
||||||
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
|
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
|
||||||
.tcx
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.source_map()
|
.source_map()
|
||||||
.span_to_snippet(c.value.span)
|
.span_to_snippet(c.span())
|
||||||
.unwrap_or_else(|_| "_".into()),
|
.unwrap_or_else(|_| "_".into()),
|
||||||
GenericArg::Infer(_) => String::from("_"),
|
GenericArg::Infer(_) => String::from("_"),
|
||||||
})
|
})
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -4,9 +4,9 @@ use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisita
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_error_messages::MultiSpan;
|
use rustc_error_messages::MultiSpan;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_hir::{self as hir, HirId};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
@ -183,16 +183,55 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||||
|
/// through const generics need to have their type "fed" to them
|
||||||
|
/// using the query system.
|
||||||
|
///
|
||||||
|
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
||||||
|
/// desired behavior.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum FeedConstTy {
|
||||||
|
/// Feed the type.
|
||||||
|
///
|
||||||
|
/// The `DefId` belongs to the const param that we are supplying
|
||||||
|
/// this (anon) const arg to.
|
||||||
|
Param(DefId),
|
||||||
|
/// Don't feed the type.
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
|
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
|
pub fn from_const_arg(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||||
|
feed: FeedConstTy,
|
||||||
|
) -> Self {
|
||||||
|
if let FeedConstTy::Param(param_def_id) = feed
|
||||||
|
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||||
|
{
|
||||||
|
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||||
/// becomes `Unevaluated`.
|
/// becomes `Unevaluated`.
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
||||||
let body_id = match tcx.hir_node_by_def_id(def) {
|
let body_id = match tcx.hir_node_by_def_id(def) {
|
||||||
hir::Node::AnonConst(ac) => ac.body,
|
hir::Node::AnonConst(ac) => ac.body,
|
||||||
_ => span_bug!(
|
node => span_bug!(
|
||||||
tcx.def_span(def.to_def_id()),
|
tcx.def_span(def.to_def_id()),
|
||||||
"from_anon_const can only process anonymous constants"
|
"from_anon_const can only process anonymous constants, not {node:?}"
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,7 +240,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
|
|
||||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||||
|
|
||||||
match Self::try_from_lit_or_param(tcx, ty, expr) {
|
match Self::try_from_lit(tcx, ty, expr) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => ty::Const::new_unevaluated(
|
None => ty::Const::new_unevaluated(
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -213,12 +252,36 @@ impl<'tcx> Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lower a const param to a [`Const`].
|
||||||
|
///
|
||||||
|
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
|
||||||
|
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
|
||||||
|
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
|
||||||
|
qpath
|
||||||
|
else {
|
||||||
|
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
|
||||||
|
};
|
||||||
|
|
||||||
|
match tcx.named_bound_var(hir_id) {
|
||||||
|
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||||
|
// Find the name and index of the const parameter by indexing the generics of
|
||||||
|
// the parent item and construct a `ParamConst`.
|
||||||
|
let item_def_id = tcx.parent(def_id);
|
||||||
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||||
|
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||||
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn try_from_lit_or_param(
|
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
|
||||||
) -> Option<Self> {
|
|
||||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
// 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.
|
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||||
let expr = match &expr.kind {
|
let expr = match &expr.kind {
|
||||||
|
@ -251,34 +314,15 @@ impl<'tcx> Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
if let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
// does not provide the parents generics to anonymous constants. We still allow generic const
|
_,
|
||||||
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
|
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
|
||||||
// ever try to instantiate the generic parameters in their bodies.
|
)) = expr.kind
|
||||||
match expr.kind {
|
{
|
||||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
|
||||||
_,
|
|
||||||
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
|
|
||||||
)) => {
|
|
||||||
match tcx.named_bound_var(expr.hir_id) {
|
|
||||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
|
||||||
// Find the name and index of the const parameter by indexing the generics of
|
|
||||||
// the parent item and construct a `ParamConst`.
|
|
||||||
let item_def_id = tcx.parent(def_id);
|
|
||||||
let generics = tcx.generics_of(item_def_id);
|
|
||||||
let index = generics.param_def_id_to_index[&def_id];
|
|
||||||
let name = tcx.item_name(def_id);
|
|
||||||
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
||||||
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
|
|
||||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -483,15 +527,15 @@ pub fn const_param_default<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||||
let default_def_id = match tcx.hir_node_by_def_id(def_id) {
|
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||||
hir::Node::GenericParam(hir::GenericParam {
|
hir::Node::GenericParam(hir::GenericParam {
|
||||||
kind: hir::GenericParamKind::Const { default: Some(ac), .. },
|
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||||
..
|
..
|
||||||
}) => ac.def_id,
|
}) => ct,
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
tcx.def_span(def_id),
|
tcx.def_span(def_id),
|
||||||
"`const_param_default` expected a generic parameter with a constant"
|
"`const_param_default` expected a generic parameter with a constant"
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
|
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
};
|
};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||||
|
|
|
@ -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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -452,7 +452,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||||
match ga {
|
match ga {
|
||||||
hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||||
hir::GenericArg::Type(ty) => self.visit_ty(ty),
|
hir::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||||
hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
hir::GenericArg::Const(ct) => self.visit_const_arg(ct),
|
||||||
hir::GenericArg::Infer(inf) => self.visit_infer(inf),
|
hir::GenericArg::Infer(inf) => self.visit_infer(inf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, _) => {
|
||||||
|
|
|
@ -285,10 +285,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clean_const<'tcx>(
|
pub(crate) fn clean_const<'tcx>(
|
||||||
constant: &hir::ConstArg<'_>,
|
constant: &hir::ConstArg<'tcx>,
|
||||||
_cx: &mut DocContext<'tcx>,
|
_cx: &mut DocContext<'tcx>,
|
||||||
) -> Constant {
|
) -> Constant {
|
||||||
Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
|
match &constant.kind {
|
||||||
|
hir::ConstArgKind::Path(qpath) => {
|
||||||
|
Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } }
|
||||||
|
}
|
||||||
|
hir::ConstArgKind::Anon(anon) => {
|
||||||
|
Constant { kind: ConstantKind::Anonymous { body: anon.body } }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clean_middle_const<'tcx>(
|
pub(crate) fn clean_middle_const<'tcx>(
|
||||||
|
@ -431,7 +438,7 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
|
||||||
match term {
|
match term {
|
||||||
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
||||||
hir::Term::Const(c) => Term::Constant(clean_middle_const(
|
hir::Term::Const(c) => Term::Constant(clean_middle_const(
|
||||||
ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)),
|
ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
|
||||||
cx,
|
cx,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -633,8 +640,9 @@ fn clean_generic_param<'tcx>(
|
||||||
param.name.ident().name,
|
param.name.ident().name,
|
||||||
GenericParamDefKind::Const {
|
GenericParamDefKind::Const {
|
||||||
ty: Box::new(clean_ty(ty, cx)),
|
ty: Box::new(clean_ty(ty, cx)),
|
||||||
default: default
|
default: default.map(|ct| {
|
||||||
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
|
||||||
|
}),
|
||||||
synthetic,
|
synthetic,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1820,7 +1828,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||||
TyKind::Array(ty, ref length) => {
|
TyKind::Array(ty, ref length) => {
|
||||||
let length = match length {
|
let length = match length {
|
||||||
hir::ArrayLen::Infer(..) => "_".to_string(),
|
hir::ArrayLen::Infer(..) => "_".to_string(),
|
||||||
hir::ArrayLen::Body(anon_const) => {
|
hir::ArrayLen::Body(const_arg) => {
|
||||||
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
|
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
|
||||||
// as we currently do not supply the parent generics to anonymous constants
|
// as we currently do not supply the parent generics to anonymous constants
|
||||||
// but do allow `ConstKind::Param`.
|
// but do allow `ConstKind::Param`.
|
||||||
|
@ -1828,9 +1836,18 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||||
// `const_eval_poly` tries to first substitute generic parameters which
|
// `const_eval_poly` tries to first substitute generic parameters which
|
||||||
// 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_anon_const(cx.tcx, anon_const.def_id);
|
let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
|
||||||
let param_env = cx.tcx.param_env(anon_const.def_id);
|
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
|
||||||
print_const(cx, ct.normalize(cx.tcx, param_env))
|
const_arg.kind
|
||||||
|
{
|
||||||
|
// Only anon consts can implicitly capture params.
|
||||||
|
// FIXME: is this correct behavior?
|
||||||
|
let param_env = cx.tcx.param_env(*def_id);
|
||||||
|
ct.normalize(cx.tcx, param_env)
|
||||||
|
} else {
|
||||||
|
ct
|
||||||
|
};
|
||||||
|
print_const(cx, ct)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
|
||||||
///
|
///
|
||||||
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
|
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
|
||||||
/// correct result.
|
/// correct result.
|
||||||
fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
|
fn repeat_expr_might_be_expanded<'tcx>(expr: &Expr<'tcx>) -> bool {
|
||||||
let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else {
|
let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let len_span = cx.tcx.def_span(anon_const.def_id);
|
!expr.span.contains(len_ct.span())
|
||||||
!expr.span.contains(len_span)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr)
|
expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::has_repr_attr;
|
use clippy_utils::has_repr_attr;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Item, ItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::Const;
|
use rustc_middle::ty::{Const, FeedConstTy};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
|
@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||||
if let ItemKind::Struct(data, _) = &item.kind
|
if let ItemKind::Struct(data, _) = &item.kind
|
||||||
// First check if last field is an array
|
// First check if last field is an array
|
||||||
&& let Some(last_field) = data.fields().last()
|
&& let Some(last_field) = data.fields().last()
|
||||||
&& let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
|
&& let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
|
||||||
|
|
||||||
// Then check if that array is zero-sized
|
// Then check if that array is zero-sized
|
||||||
&& let length = Const::from_anon_const(cx.tcx, length.def_id)
|
&& let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
|
||||||
&& let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
|
&& let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||||
&& let Some(length) = length
|
&& let Some(length) = length
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher};
|
||||||
use rustc_ast::ast::{LitFloatType, LitKind};
|
use rustc_ast::ast::{LitFloatType, LitKind};
|
||||||
use rustc_ast::LitIntType;
|
use rustc_ast::LitIntType;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind,
|
self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
|
||||||
QPath, StmtKind, TyKind,
|
ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
|
@ -270,6 +269,21 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
|
||||||
|
match const_arg.value.kind {
|
||||||
|
ConstArgKind::Path(ref qpath) => {
|
||||||
|
bind!(self, qpath);
|
||||||
|
chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
|
||||||
|
self.qpath(qpath);
|
||||||
|
},
|
||||||
|
ConstArgKind::Anon(anon_const) => {
|
||||||
|
bind!(self, anon_const);
|
||||||
|
chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
|
||||||
|
self.body(field!(anon_const.body));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lit(&self, lit: &Binding<&Lit>) {
|
fn lit(&self, lit: &Binding<&Lit>) {
|
||||||
let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
|
let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
|
||||||
macro_rules! kind {
|
macro_rules! kind {
|
||||||
|
@ -602,10 +616,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
self.expr(value);
|
self.expr(value);
|
||||||
match length.value {
|
match length.value {
|
||||||
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
|
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
|
||||||
ArrayLen::Body(anon_const) => {
|
ArrayLen::Body(const_arg) => {
|
||||||
bind!(self, anon_const);
|
bind!(self, const_arg);
|
||||||
chain!(self, "let ArrayLen::Body({anon_const}) = {length}");
|
chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
|
||||||
self.body(field!(anon_const.body));
|
self.const_arg(const_arg);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::MatchSource::TryDesugar;
|
use rustc_hir::MatchSource::TryDesugar;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy,
|
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
|
||||||
GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField,
|
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
|
||||||
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
|
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{tokenize, TokenKind};
|
use rustc_lexer::{tokenize, TokenKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
|
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
|
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
|
||||||
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body),
|
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
|
||||||
(_, _) => false,
|
(_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
|
|
||||||
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
|
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
|
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
|
||||||
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
||||||
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
||||||
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
|
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
|
||||||
|
@ -419,6 +419,17 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
|
||||||
|
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),
|
||||||
|
// Use explicit match for now since ConstArg is undergoing flux.
|
||||||
|
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
|
||||||
|
false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
||||||
left.res == right.res
|
left.res == right.res
|
||||||
}
|
}
|
||||||
|
@ -1123,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
|
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
|
||||||
match length {
|
match length {
|
||||||
ArrayLen::Infer(..) => {},
|
ArrayLen::Infer(..) => {},
|
||||||
ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
|
ArrayLen::Body(ct) => self.hash_const_arg(ct),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,12 +1145,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
self.maybe_typeck_results = old_maybe_typeck_results;
|
self.maybe_typeck_results = old_maybe_typeck_results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
|
||||||
|
match &const_arg.kind {
|
||||||
|
ConstArgKind::Path(path) => self.hash_qpath(path),
|
||||||
|
ConstArgKind::Anon(anon) => self.hash_body(anon.body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
|
fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
|
||||||
for arg in arg_list {
|
for arg in arg_list {
|
||||||
match *arg {
|
match *arg {
|
||||||
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
||||||
GenericArg::Type(ty) => self.hash_ty(ty),
|
GenericArg::Type(ty) => self.hash_ty(ty),
|
||||||
GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
|
GenericArg::Const(ref ca) => self.hash_const_arg(ca),
|
||||||
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
|
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
|
||||||
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
|
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
|
||||||
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
|
ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
|
||||||
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
|
ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
|
||||||
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
|
Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
|
||||||
TyKind, UnOp,
|
TraitRef, TyKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{tokenize, TokenKind};
|
use rustc_lexer::{tokenize, TokenKind};
|
||||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||||
|
@ -904,7 +904,8 @@ 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)) => {
|
||||||
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
|
if let ConstArgKind::Anon(anon_const) = len.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
|
||||||
&& v <= 32
|
&& v <= 32
|
||||||
&& is_default_equivalent(cx, x)
|
&& is_default_equivalent(cx, x)
|
||||||
|
@ -933,7 +934,8 @@ 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)) => {
|
||||||
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
|
if let ConstArgKind::Anon(anon_const) = len.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
|
||||||
{
|
{
|
||||||
return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
|
return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue