From e3f5cc6c38434a7e32e2f52456b8da6eebf013de Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 23 Dec 2021 10:01:51 +0100 Subject: [PATCH] implement `generic_arg_infer` for array lengths --- compiler/rustc_ast_lowering/src/expr.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 23 ++++++++++++++- compiler/rustc_hir/src/hir.rs | 18 ++++++++++-- compiler/rustc_hir/src/intravisit.rs | 14 ++++++++-- compiler/rustc_hir_pretty/src/lib.rs | 13 +++++++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 9 ++++-- .../rustc_save_analysis/src/dump_visitor.rs | 28 +++++++++++++------ compiler/rustc_save_analysis/src/sig.rs | 8 ++++-- compiler/rustc_typeck/src/astconv/generics.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 10 +++++-- compiler/rustc_typeck/src/check/expr.rs | 4 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 7 +++++ compiler/rustc_typeck/src/collect.rs | 18 ++++++++---- compiler/rustc_typeck/src/collect/type_of.rs | 6 ++-- .../generic_arg_infer/array-in-sig.rs | 12 ++++++++ .../generic_arg_infer/array-in-sig.stderr | 9 ++++++ .../generic_arg_infer/array-repeat-expr.rs | 13 +++++++++ .../generic_arg_infer}/infer-arg-test.rs | 2 -- .../generic_arg_infer}/infer-arg-test.stderr | 14 +--------- 19 files changed, 161 insertions(+), 51 deletions(-) create mode 100644 src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs create mode 100644 src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr create mode 100644 src/test/ui/const-generics/generic_arg_infer/array-repeat-expr.rs rename src/test/ui/{inference => const-generics/generic_arg_infer}/infer-arg-test.rs (86%) rename src/test/ui/{inference => const-generics/generic_arg_infer}/infer-arg-test.stderr (64%) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6ee1dbe4ae3..75f384405bb 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -34,7 +34,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'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)), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 77738b2c5cc..35eb716949a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,6 +56,7 @@ 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 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, '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 @@ fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'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), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 69572807e7c..698472565fb 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1407,6 +1407,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// A literal. pub type Lit = Spanned; +#[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 `). 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`). diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 0fab7cbfeea..d0eee422202 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -383,6 +383,9 @@ fn visit_arm(&mut self, a: &'v Arm<'v>) { 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); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2f5f158856f..54ee553a4f6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -358,7 +358,7 @@ pub fn print_type(&mut self, ty: &hir::Ty<'_>) { 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 @@ pub fn print_if( 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 @@ fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) { 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() } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 092fe131174..bdde6b4a356 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -583,9 +583,12 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'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 } } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index f1a5282b088..23f5b17fa78 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1326,12 +1326,18 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty<'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 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'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. diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index e43344ad6d9..5d0de444199 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -310,9 +310,13 @@ fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext< 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)) } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index caa5c71e21c..956696546da 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -104,7 +104,7 @@ fn generic_arg_mismatch_err( 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(), diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 8db706c3709..8226ffbccc4 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2363,8 +2363,14 @@ fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool 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) } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 096c4fcf472..ea464784509 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1238,12 +1238,12 @@ fn check_expr_const_block( 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() { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 67630fd4e58..1aca2911533 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -498,6 +498,13 @@ pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'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); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e7b728d491b..dc303ad5e04 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -182,7 +182,7 @@ struct CollectItemTypesVisitor<'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 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'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, 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 @@ fn ct_infer( _: 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() { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 99fddcb00ce..04e887bf742 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -13,7 +13,7 @@ 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 fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { 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); diff --git a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs new file mode 100644 index 00000000000..56b88a426a1 --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs @@ -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(); +} diff --git a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr new file mode 100644 index 00000000000..eaa12b4192d --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr @@ -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`. diff --git a/src/test/ui/const-generics/generic_arg_infer/array-repeat-expr.rs b/src/test/ui/const-generics/generic_arg_infer/array-repeat-expr.rs new file mode 100644 index 00000000000..d3e53d7a892 --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/array-repeat-expr.rs @@ -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()); +} diff --git a/src/test/ui/inference/infer-arg-test.rs b/src/test/ui/const-generics/generic_arg_infer/infer-arg-test.rs similarity index 86% rename from src/test/ui/inference/infer-arg-test.rs rename to src/test/ui/const-generics/generic_arg_infer/infer-arg-test.rs index 1b67ccd6c43..29aa0f59d74 100644 --- a/src/test/ui/inference/infer-arg-test.rs +++ b/src/test/ui/const-generics/generic_arg_infer/infer-arg-test.rs @@ -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 } diff --git a/src/test/ui/inference/infer-arg-test.stderr b/src/test/ui/const-generics/generic_arg_infer/infer-arg-test.stderr similarity index 64% rename from src/test/ui/inference/infer-arg-test.stderr rename to src/test/ui/const-generics/generic_arg_infer/infer-arg-test.stderr index 30e171eac21..e6d0c743d01 100644 --- a/src/test/ui/inference/infer-arg-test.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/infer-arg-test.stderr @@ -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`.