mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
implement generic_arg_infer
for array lengths
This commit is contained in:
parent
5aa0239b16
commit
e3f5cc6c38
@ -34,7 +34,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
ExprKind::Repeat(ref expr, ref count) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
let count = self.lower_anon_const(count);
|
||||
let count = self.lower_array_length(count);
|
||||
hir::ExprKind::Repeat(expr, count)
|
||||
}
|
||||
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
||||
|
@ -56,6 +56,7 @@ use rustc_hir::{ConstArg, GenericArg, ParamName};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_session::lint::LintBuffer;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::ExpnId;
|
||||
@ -1248,7 +1249,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
))
|
||||
}
|
||||
TyKind::Array(ref ty, ref length) => {
|
||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length))
|
||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
||||
}
|
||||
TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
||||
TyKind::TraitObject(ref bounds, kind) => {
|
||||
@ -2039,6 +2040,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.expr_block(block, AttrVec::new())
|
||||
}
|
||||
|
||||
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
|
||||
match c.value.kind {
|
||||
ExprKind::Underscore => {
|
||||
if self.sess.features_untracked().generic_arg_infer {
|
||||
hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span)
|
||||
} else {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::generic_arg_infer,
|
||||
c.value.span,
|
||||
"using `_` for array lengths is unstable",
|
||||
)
|
||||
.emit();
|
||||
hir::ArrayLen::Body(self.lower_anon_const(c))
|
||||
}
|
||||
}
|
||||
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
|
||||
self.with_new_scopes(|this| hir::AnonConst {
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
|
@ -1407,6 +1407,20 @@ impl fmt::Display for ConstContext {
|
||||
/// A literal.
|
||||
pub type Lit = Spanned<LitKind>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
|
||||
pub enum ArrayLen {
|
||||
Infer(HirId, Span),
|
||||
Body(AnonConst),
|
||||
}
|
||||
|
||||
impl ArrayLen {
|
||||
pub fn hir_id(&self) -> HirId {
|
||||
match self {
|
||||
&ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A constant (expression) that's not an item or associated item,
|
||||
/// but needs its own `DefId` for type-checking, const-eval, etc.
|
||||
/// These are usually found nested inside types (e.g., array lengths)
|
||||
@ -1756,7 +1770,7 @@ pub enum ExprKind<'hir> {
|
||||
///
|
||||
/// E.g., `[1; 5]`. The first expression is the element
|
||||
/// to be repeated; the second is the number of times to repeat it.
|
||||
Repeat(&'hir Expr<'hir>, AnonConst),
|
||||
Repeat(&'hir Expr<'hir>, ArrayLen),
|
||||
|
||||
/// A suspension point for generators (i.e., `yield <expr>`).
|
||||
Yield(&'hir Expr<'hir>, YieldSource),
|
||||
@ -2266,7 +2280,7 @@ pub enum TyKind<'hir> {
|
||||
/// A variable length slice (i.e., `[T]`).
|
||||
Slice(&'hir Ty<'hir>),
|
||||
/// A fixed length array (i.e., `[T; n]`).
|
||||
Array(&'hir Ty<'hir>, AnonConst),
|
||||
Array(&'hir Ty<'hir>, ArrayLen),
|
||||
/// A raw pointer (i.e., `*const T` or `*mut T`).
|
||||
Ptr(MutTy<'hir>),
|
||||
/// A reference (i.e., `&'a T` or `&'a mut T`).
|
||||
|
@ -383,6 +383,9 @@ pub trait Visitor<'v>: Sized {
|
||||
fn visit_pat(&mut self, p: &'v Pat<'v>) {
|
||||
walk_pat(self, p)
|
||||
}
|
||||
fn visit_array_length(&mut self, len: &'v ArrayLen) {
|
||||
walk_array_len(self, len)
|
||||
}
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) {
|
||||
walk_anon_const(self, c)
|
||||
}
|
||||
@ -753,7 +756,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
||||
}
|
||||
TyKind::Array(ref ty, ref length) => {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_anon_const(length)
|
||||
visitor.visit_array_length(length)
|
||||
}
|
||||
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
|
||||
for bound in bounds {
|
||||
@ -1124,6 +1127,13 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
|
||||
match len {
|
||||
&ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id),
|
||||
ArrayLen::Body(c) => visitor.visit_anon_const(c),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
|
||||
visitor.visit_id(constant.hir_id);
|
||||
visitor.visit_nested_body(constant.body);
|
||||
@ -1147,7 +1157,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||
ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
|
||||
ExprKind::Repeat(ref element, ref count) => {
|
||||
visitor.visit_expr(element);
|
||||
visitor.visit_anon_const(count)
|
||||
visitor.visit_array_length(count)
|
||||
}
|
||||
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
|
||||
visitor.visit_qpath(qpath, expression.hir_id, expression.span);
|
||||
|
@ -358,7 +358,7 @@ impl<'a> State<'a> {
|
||||
self.word("[");
|
||||
self.print_type(&ty);
|
||||
self.word("; ");
|
||||
self.print_anon_const(length);
|
||||
self.print_array_length(length);
|
||||
self.word("]");
|
||||
}
|
||||
hir::TyKind::Typeof(ref e) => {
|
||||
@ -1065,6 +1065,13 @@ impl<'a> State<'a> {
|
||||
self.print_else(elseopt)
|
||||
}
|
||||
|
||||
pub fn print_array_length(&mut self, len: &hir::ArrayLen) {
|
||||
match len {
|
||||
hir::ArrayLen::Infer(_, _) => self.word("_"),
|
||||
hir::ArrayLen::Body(ct) => self.print_anon_const(ct),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
|
||||
self.ann.nested(self, Nested::Body(constant.body))
|
||||
}
|
||||
@ -1140,12 +1147,12 @@ impl<'a> State<'a> {
|
||||
self.end()
|
||||
}
|
||||
|
||||
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) {
|
||||
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word("[");
|
||||
self.print_expr(element);
|
||||
self.word_space(";");
|
||||
self.print_anon_const(count);
|
||||
self.print_array_length(count);
|
||||
self.word("]");
|
||||
self.end()
|
||||
}
|
||||
|
@ -583,9 +583,12 @@ impl<'tcx> Cx<'tcx> {
|
||||
ExprKind::ConstBlock { value }
|
||||
}
|
||||
// Now comes the rote stuff:
|
||||
hir::ExprKind::Repeat(ref v, ref count) => {
|
||||
let count_def_id = self.tcx.hir().local_def_id(count.hir_id);
|
||||
let count = ty::Const::from_anon_const(self.tcx, count_def_id);
|
||||
hir::ExprKind::Repeat(ref v, _) => {
|
||||
let ty = self.typeck_results().expr_ty(expr);
|
||||
let count = match ty.kind() {
|
||||
ty::Array(_, ct) => ct,
|
||||
_ => span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty),
|
||||
};
|
||||
|
||||
ExprKind::Repeat { value: self.mirror_expr(v), count }
|
||||
}
|
||||
|
@ -1326,12 +1326,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
||||
}
|
||||
intravisit::walk_qpath(self, path, t.hir_id, t.span);
|
||||
}
|
||||
hir::TyKind::Array(ref ty, ref anon_const) => {
|
||||
hir::TyKind::Array(ref ty, ref length) => {
|
||||
self.visit_ty(ty);
|
||||
let map = self.tcx.hir();
|
||||
self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||
v.visit_expr(&map.body(anon_const.body).value)
|
||||
});
|
||||
match length {
|
||||
// FIXME(generic_arg_infer): We probably want to
|
||||
// output the inferred type here? :shrug:
|
||||
hir::ArrayLen::Infer(..) => {}
|
||||
hir::ArrayLen::Body(anon_const) => self
|
||||
.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||
v.visit_expr(&map.body(anon_const.body).value)
|
||||
}),
|
||||
}
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||
let item = self.tcx.hir().item(item_id);
|
||||
@ -1390,12 +1396,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
||||
v.visit_expr(&body.value)
|
||||
});
|
||||
}
|
||||
hir::ExprKind::Repeat(ref expr, ref anon_const) => {
|
||||
hir::ExprKind::Repeat(ref expr, ref length) => {
|
||||
self.visit_expr(expr);
|
||||
let map = self.tcx.hir();
|
||||
self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||
v.visit_expr(&map.body(anon_const.body).value)
|
||||
});
|
||||
match length {
|
||||
// FIXME(generic_arg_infer): We probably want to
|
||||
// output the inferred type here? :shrug:
|
||||
hir::ArrayLen::Infer(..) => {}
|
||||
hir::ArrayLen::Body(anon_const) => self
|
||||
.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||
v.visit_expr(&map.body(anon_const.body).value)
|
||||
}),
|
||||
}
|
||||
}
|
||||
// In particular, we take this branch for call and path expressions,
|
||||
// where we'll index the idents involved just by continuing to walk.
|
||||
|
@ -310,9 +310,13 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
||||
let nested = bounds_to_string(&bounds);
|
||||
Ok(text_sig(nested))
|
||||
}
|
||||
hir::TyKind::Array(ref ty, ref anon_const) => {
|
||||
hir::TyKind::Array(ref ty, ref length) => {
|
||||
let nested_ty = ty.make(offset + 1, id, scx)?;
|
||||
let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " ");
|
||||
let hir_id = match length {
|
||||
&hir::ArrayLen::Infer(hir_id, _) => hir_id,
|
||||
hir::ArrayLen::Body(anon_const) => anon_const.hir_id,
|
||||
};
|
||||
let expr = id_to_string(&scx.tcx.hir(), hir_id).replace('\n', " ");
|
||||
let text = format!("[{}; {}]", nested_ty.text, expr);
|
||||
Ok(replace_text(nested_ty, text))
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
||||
GenericParamDefKind::Const { .. },
|
||||
) if tcx.type_of(param.def_id) == tcx.types.usize => {
|
||||
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
|
||||
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
|
||||
if let Ok(snippet) = snippet {
|
||||
err.span_suggestion(
|
||||
arg.span(),
|
||||
|
@ -2363,8 +2363,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
|
||||
}
|
||||
hir::TyKind::Array(ref ty, ref length) => {
|
||||
let length_def_id = tcx.hir().local_def_id(length.hir_id);
|
||||
let length = ty::Const::from_anon_const(tcx, length_def_id);
|
||||
let length = match length {
|
||||
&hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span),
|
||||
hir::ArrayLen::Body(constant) => {
|
||||
let length_def_id = tcx.hir().local_def_id(constant.hir_id);
|
||||
ty::Const::from_anon_const(tcx, length_def_id)
|
||||
}
|
||||
};
|
||||
|
||||
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length));
|
||||
self.normalize_ty(ast_ty.span, array_ty)
|
||||
}
|
||||
|
@ -1238,12 +1238,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fn check_expr_repeat(
|
||||
&self,
|
||||
element: &'tcx hir::Expr<'tcx>,
|
||||
count: &'tcx hir::AnonConst,
|
||||
count: &'tcx hir::ArrayLen,
|
||||
expected: Expectation<'tcx>,
|
||||
_expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let count = self.to_const(count);
|
||||
let count = self.array_length_to_const(count);
|
||||
|
||||
let uty = match expected {
|
||||
ExpectHasType(uty) => match *uty.kind() {
|
||||
|
@ -498,6 +498,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty
|
||||
}
|
||||
|
||||
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> &'tcx ty::Const<'tcx> {
|
||||
match length {
|
||||
&hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span),
|
||||
hir::ArrayLen::Body(anon_const) => self.to_const(anon_const),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
|
||||
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
||||
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
||||
|
@ -182,7 +182,7 @@ crate fn placeholder_type_error<'tcx>(
|
||||
sugg.push((span, format!(", {}", type_name)));
|
||||
}
|
||||
|
||||
let mut err = bad_placeholder_type(tcx, placeholder_types, kind);
|
||||
let mut err = bad_placeholder(tcx, "type", placeholder_types, kind);
|
||||
|
||||
// Suggest, but only if it is not a function in const or static
|
||||
if suggest {
|
||||
@ -314,8 +314,9 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Utility types and common code for the above passes.
|
||||
|
||||
fn bad_placeholder_type<'tcx>(
|
||||
fn bad_placeholder<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
placeholder_kind: &'static str,
|
||||
mut spans: Vec<Span>,
|
||||
kind: &'static str,
|
||||
) -> rustc_errors::DiagnosticBuilder<'tcx> {
|
||||
@ -326,7 +327,8 @@ fn bad_placeholder_type<'tcx>(
|
||||
tcx.sess,
|
||||
spans.clone(),
|
||||
E0121,
|
||||
"the type placeholder `_` is not allowed within types on item signatures for {}",
|
||||
"the {} placeholder `_` is not allowed within types on item signatures for {}",
|
||||
placeholder_kind,
|
||||
kind
|
||||
);
|
||||
for span in spans {
|
||||
@ -393,7 +395,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
_: Option<&ty::GenericParamDef>,
|
||||
span: Span,
|
||||
) -> &'tcx Const<'tcx> {
|
||||
bad_placeholder_type(self.tcx(), vec![span], "generic").emit();
|
||||
bad_placeholder(self.tcx(), "const", vec![span], "generic").emit();
|
||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
|
||||
ty::ReErased => self.tcx.lifetimes.re_static,
|
||||
@ -1482,7 +1484,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
||||
// as they shouldn't be able to cause query cycle errors.
|
||||
Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||
| Node::Variant(Variant { disr_expr: Some(ref constant), .. })
|
||||
if constant.hir_id() == hir_id =>
|
||||
{
|
||||
Some(parent_def_id.to_def_id())
|
||||
}
|
||||
Node::Variant(Variant { disr_expr: Some(ref constant), .. })
|
||||
if constant.hir_id == hir_id =>
|
||||
{
|
||||
Some(parent_def_id.to_def_id())
|
||||
@ -1788,7 +1794,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
||||
|
||||
let mut visitor = PlaceholderHirTyCollector::default();
|
||||
visitor.visit_ty(ty);
|
||||
let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
|
||||
let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type");
|
||||
let ret_ty = fn_sig.skip_binder().output();
|
||||
if !ret_ty.references_error() {
|
||||
if !ret_ty.is_closure() {
|
||||
|
@ -13,7 +13,7 @@ use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use super::ItemCtxt;
|
||||
use super::{bad_placeholder_type, is_suggestable_infer_ty};
|
||||
use super::{bad_placeholder, is_suggestable_infer_ty};
|
||||
|
||||
/// Computes the relevant generic parameter for a potential generic const argument.
|
||||
///
|
||||
@ -490,7 +490,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
match parent_node {
|
||||
Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||
if constant.hir_id == hir_id =>
|
||||
if constant.hir_id() == hir_id =>
|
||||
{
|
||||
tcx.types.usize
|
||||
}
|
||||
@ -788,7 +788,7 @@ fn infer_placeholder_type<'a>(
|
||||
err.emit();
|
||||
}
|
||||
None => {
|
||||
let mut diag = bad_placeholder_type(tcx, vec![span], kind);
|
||||
let mut diag = bad_placeholder(tcx, "type", vec![span], kind);
|
||||
|
||||
if !ty.references_error() {
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
|
12
src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs
Normal file
12
src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// To avoid having to `or` gate `_` as an expr.
|
||||
#![feature(generic_arg_infer)]
|
||||
|
||||
fn foo() -> [u8; _] {
|
||||
//~^ ERROR the const placeholder `_` is not allowed within types on item signatures for generics
|
||||
// FIXME(generic_arg_infer): this error message should say in the return type or sth like that.
|
||||
[0; 3]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
error[E0121]: the const placeholder `_` is not allowed within types on item signatures for generics
|
||||
--> $DIR/array-in-sig.rs:4:18
|
||||
|
|
||||
LL | fn foo() -> [u8; _] {
|
||||
| ^ not allowed in type signatures
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
@ -0,0 +1,13 @@
|
||||
// run-pass
|
||||
|
||||
// To avoid having to `or` gate `_` as an expr.
|
||||
#![feature(generic_arg_infer)]
|
||||
|
||||
fn foo() -> [u8; 3] {
|
||||
let x: [u8; _] = [0; _];
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!([0; _], foo());
|
||||
}
|
@ -18,7 +18,5 @@ fn main() {
|
||||
let a: All<_, _, _>;
|
||||
all_fn();
|
||||
let v: [u8; _];
|
||||
//~^ ERROR in expressions
|
||||
let v: [u8; 10] = [0; _];
|
||||
//~^ ERROR in expressions
|
||||
}
|
@ -10,18 +10,6 @@ error: expected identifier, found reserved identifier `_`
|
||||
LL | fn bad_infer_fn<_>() {}
|
||||
| ^ expected identifier, found reserved identifier
|
||||
|
||||
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||
--> $DIR/infer-arg-test.rs:20:15
|
||||
|
|
||||
LL | let v: [u8; _];
|
||||
| ^ `_` not allowed here
|
||||
|
||||
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||
--> $DIR/infer-arg-test.rs:22:25
|
||||
|
|
||||
LL | let v: [u8; 10] = [0; _];
|
||||
| ^ `_` not allowed here
|
||||
|
||||
error[E0392]: parameter `_` is never used
|
||||
--> $DIR/infer-arg-test.rs:7:17
|
||||
|
|
||||
@ -31,6 +19,6 @@ LL | struct BadInfer<_>;
|
||||
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `_` to be a const parameter, use `const _: usize` instead
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0392`.
|
Loading…
Reference in New Issue
Block a user