diff options
| author | bors <bors@rust-lang.org> | 2024-03-22 12:29:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-22 12:29:42 +0000 |
| commit | 1447f9d38ca388ca178a544534b3cff72945fa1e (patch) | |
| tree | 51b4cffdfe26ba21cda4793ce8dbe20d5f06c965 | |
| parent | eff958c59e8c07ba0515e164b825c9001b242294 (diff) | |
| parent | a5de4fb2a585d0d69f62abd1f1765fef430786d9 (diff) | |
| download | rust-1447f9d38ca388ca178a544534b3cff72945fa1e.tar.gz rust-1447f9d38ca388ca178a544534b3cff72945fa1e.zip | |
Auto merge of #122869 - matthiaskrgr:rollup-0navj4l, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #121619 (Experimental feature postfix match) - #122370 (Gracefully handle `AnonConst` in `diagnostic_hir_wf_check()`) - #122537 (interpret/allocation: fix aliasing issue in interpreter and refactor getters a bit) - #122542 (coverage: Clean up marker statements that aren't needed later) - #122800 (Add `NonNull::<[T]>::is_empty`.) - #122820 (Stop using `<DefId as Ord>` in various diagnostic situations) - #122847 (Suggest `RUST_MIN_STACK` workaround on overflow) - #122855 (Fix Itanium mangling usizes) - #122863 (add more ice tests ) r? `@ghost` `@rustbot` modify labels: rollup
73 files changed, 1200 insertions, 248 deletions
diff --git a/Cargo.lock b/Cargo.lock index e97d29d57ee..6505aa52c4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4236,6 +4236,7 @@ name = "rustc_middle" version = "0.0.0" dependencies = [ "bitflags 2.4.2", + "derivative", "either", "field-offset", "gsgdt", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ea73f88dacf..915cb386075 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1437,7 +1437,7 @@ pub enum ExprKind { /// `'label: loop { block }` Loop(P<Block>, Option<Label>, Span), /// A `match` block. - Match(P<Expr>, ThinVec<Arm>), + Match(P<Expr>, ThinVec<Arm>, MatchKind), /// A closure (e.g., `move |a, b, c| a + b + c`). Closure(Box<Closure>), /// A block (`'label: { ... }`). @@ -1762,6 +1762,15 @@ pub enum StrStyle { Raw(u8), } +/// The kind of match expression +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)] +pub enum MatchKind { + /// match expr { ... } + Prefix, + /// expr.match { ... } + Postfix, +} + /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 5b22ae5f54b..7337b969242 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1425,7 +1425,7 @@ pub fn noop_visit_expr<T: MutVisitor>( visit_opt(label, |label| vis.visit_label(label)); vis.visit_span(span); } - ExprKind::Match(expr, arms) => { + ExprKind::Match(expr, arms, _kind) => { vis.visit_expr(expr); arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index dedf67e6a94..18986fb7504 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -923,7 +923,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V visit_opt!(visitor, visit_label, opt_label); try_visit!(visitor.visit_block(block)); } - ExprKind::Match(subexpression, arms) => { + ExprKind::Match(subexpression, arms, _kind) => { try_visit!(visitor.visit_expr(subexpression)); walk_list!(visitor, visit_arm, arms); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d802dbbcb9e..389cf4e3132 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -181,10 +181,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }), ExprKind::TryBlock(body) => self.lower_expr_try_block(body), - ExprKind::Match(expr, arms) => hir::ExprKind::Match( + ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match( self.lower_expr(expr), self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), - hir::MatchSource::Normal, + match kind { + MatchKind::Prefix => hir::MatchSource::Normal, + MatchKind::Postfix => hir::MatchSource::Postfix, + }, ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 81065fa3dce..bb83f4c0f0e 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -564,6 +564,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); + gate_all!(postfix_match, "postfix match is experimental"); if !visitor.features.never_patterns { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 433ef03b6e5..8bd8b6ac144 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -1,6 +1,6 @@ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; -use ast::ForLoopKind; +use ast::{ForLoopKind, MatchKind}; use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::token; @@ -589,12 +589,22 @@ impl<'a> State<'a> { self.word_nbsp("loop"); self.print_block_with_attrs(blk, attrs); } - ast::ExprKind::Match(expr, arms) => { + ast::ExprKind::Match(expr, arms, match_kind) => { self.cbox(0); self.ibox(0); - self.word_nbsp("match"); - self.print_expr_as_cond(expr); - self.space(); + + match match_kind { + MatchKind::Prefix => { + self.word_nbsp("match"); + self.print_expr_as_cond(expr); + self.space(); + } + MatchKind::Postfix => { + self.print_expr_as_cond(expr); + self.word_nbsp(".match"); + } + } + self.bopen(); self.print_inner_attributes_no_trailing_hardbreak(attrs); for arm in arms { diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 56c56b2704b..92efeab08eb 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -245,7 +245,7 @@ impl<'cx, 'a> Context<'cx, 'a> { ExprKind::Let(_, local_expr, _, _) => { self.manage_cond_expr(local_expr); } - ExprKind::Match(local_expr, _) => { + ExprKind::Match(local_expr, ..) => { self.manage_cond_expr(local_expr); } ExprKind::MethodCall(call) => { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 6eccd67f8af..60dbdf8b544 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -132,7 +132,7 @@ fn cs_partial_cmp( // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 if !tag_then_data - && let ExprKind::Match(_, arms) = &mut expr1.kind + && let ExprKind::Match(_, arms, _) = &mut expr1.kind && let Some(last) = arms.last_mut() && let PatKind::Wild = last.pat.kind { diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index b11a1b6cda1..108c1078eaa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; -use ast::EnumDef; -use rustc_ast::{self as ast, MetaItem}; +use rustc_ast::{self as ast, EnumDef, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 133084b7c12..54f4bc06340 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -85,14 +85,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let bx = self; - match coverage.kind { - // Marker statements have no effect during codegen, - // so return early and don't create `func_coverage`. - CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => return, - // Match exhaustively to ensure that newly-added kinds are classified correctly. - CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } => {} - } - let Some(function_coverage_info) = bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref() else { @@ -109,7 +101,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let Coverage { kind } = coverage; match *kind { CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( - "unexpected marker statement {kind:?} should have caused an early return" + "marker statement {kind:?} should have been removed by CleanupPostBorrowck" ), CoverageKind::CounterIncrement { id } => { func_coverage.mark_counter_id_seen(id); diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a6ca4b2e0de..9b1d9cf932b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1159,11 +1159,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // Side-step AllocRef and directly access the underlying bytes more efficiently. - // (We are staying inside the bounds here so all is good.) + // (We are staying inside the bounds here and all bytes do get overwritten so all is good.) let alloc_id = alloc_ref.alloc_id; let bytes = alloc_ref .alloc - .get_bytes_mut(&alloc_ref.tcx, alloc_ref.range) + .get_bytes_unchecked_for_overwrite(&alloc_ref.tcx, alloc_ref.range) .map_err(move |e| e.to_interp_error(alloc_id))?; // `zip` would stop when the first iterator ends; we want to definitely // cover all of `bytes`. @@ -1184,6 +1184,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.mem_copy_repeatedly(src, dest, size, 1, nonoverlapping) } + /// Performs `num_copies` many copies of `size` many bytes from `src` to `dest + i*size` (where + /// `i` is the index of the copy). + /// + /// Either `nonoverlapping` must be true or `num_copies` must be 1; doing repeated copies that + /// may overlap is not supported. pub fn mem_copy_repeatedly( &mut self, src: Pointer<Option<M::Provenance>>, @@ -1245,8 +1250,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (dest_alloc_id, dest_prov), dest_range, )?; + // Yes we do overwrite all bytes in `dest_bytes`. let dest_bytes = dest_alloc - .get_bytes_mut_ptr(&tcx, dest_range) + .get_bytes_unchecked_for_overwrite_ptr(&tcx, dest_range) .map_err(|e| e.to_interp_error(dest_alloc_id))? .as_mut_ptr(); @@ -1280,6 +1286,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } + if num_copies > 1 { + assert!(nonoverlapping, "multi-copy only supported in non-overlapping mode"); + } let size_in_bytes = size.bytes_usize(); // For particularly large arrays (where this is perf-sensitive) it's common that @@ -1292,6 +1301,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else if src_alloc_id == dest_alloc_id { let mut dest_ptr = dest_bytes; for _ in 0..num_copies { + // Here we rely on `src` and `dest` being non-overlapping if there is more than + // one copy. ptr::copy(src_bytes, dest_ptr, size_in_bytes); dest_ptr = dest_ptr.add(size_in_bytes); } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 68270dab284..4bc49f90607 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -4,6 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; use rustc_infer::traits::Reveal; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -345,11 +346,21 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, format!("explicit `{kind:?}` is forbidden")); } } + StatementKind::Coverage(coverage) => { + let kind = &coverage.kind; + if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) + && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind + { + self.fail( + location, + format!("{kind:?} should have been removed after analysis"), + ); + } + } StatementKind::Assign(..) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Intrinsic(_) - | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) | StatementKind::Nop => {} diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs index deca1082221..441219eec90 100644 --- a/compiler/rustc_driver_impl/src/signal_handler.rs +++ b/compiler/rustc_driver_impl/src/signal_handler.rs @@ -1,6 +1,7 @@ //! Signal handler for rustc //! Primarily used to extract a backtrace from stack overflow +use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE}; use std::alloc::{alloc, Layout}; use std::{fmt, mem, ptr}; @@ -100,7 +101,10 @@ extern "C" fn print_stack_trace(_: libc::c_int) { written += 1; } raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust"); - written += 1; + // get the current stack size WITHOUT blocking and double it + let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2; + raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}"); + written += 2; if written > 24 { // We probably just scrolled the earlier "we got SIGSEGV" message off the terminal raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal"); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index e71047f94fa..30559871b4e 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -1,6 +1,6 @@ use crate::base::ExtCtxt; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; +use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp}; use rustc_ast::{attr, token, util::literal}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -524,7 +524,7 @@ impl<'a> ExtCtxt<'a> { } pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> { - self.expr(span, ast::ExprKind::Match(arg, arms)) + self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix)) } pub fn expr_if( diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1820e172ea5..8d72f4924d6 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -559,6 +559,8 @@ declare_features! ( (unstable, offset_of_nested, "1.77.0", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), + /// Allows postfix match `expr.match { ... }` + (unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 87e21785c8c..162ec16fabc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2015,6 +2015,8 @@ pub enum LocalSource { pub enum MatchSource { /// A `match _ { .. }`. Normal, + /// A `expr.match { .. }`. + Postfix, /// A desugared `for _ in _ { .. }` loop. ForLoopDesugar, /// A desugared `?` operator. @@ -2031,6 +2033,7 @@ impl MatchSource { use MatchSource::*; match self { Normal => "match", + Postfix => ".match", ForLoopDesugar => "for", TryDesugar(_) => "?", AwaitDesugar => ".await", diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index f932acc5e83..7014b23ff07 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -163,6 +163,16 @@ fn diagnostic_hir_wf_check<'tcx>( kind: hir::GenericParamKind::Type { default: Some(ty), .. }, .. }) => vec![*ty], + hir::Node::AnonConst(_) + if let Some(const_param_id) = + tcx.hir().opt_const_param_default_param_def_id(hir_id) + && let hir::Node::GenericParam(hir::GenericParam { + kind: hir::GenericParamKind::Const { ty, .. }, + .. + }) = tcx.hir_node_by_def_id(const_param_id) => + { + vec![*ty] + } ref node => bug!("Unexpected node {:?}", node), }, WellFormedLoc::Param { function: _, param_idx } => { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 7d48f90db36..d09f8d7d7cf 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -48,12 +48,20 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy } } -const STACK_SIZE: usize = 8 * 1024 * 1024; - -fn get_stack_size() -> Option<usize> { - // FIXME: Hacks on hacks. If the env is trying to override the stack size - // then *don't* set it explicitly. - env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE) +pub static STACK_SIZE: OnceLock<usize> = OnceLock::new(); +pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024; + +fn init_stack_size() -> usize { + // Obey the environment setting or default + *STACK_SIZE.get_or_init(|| { + env::var_os("RUST_MIN_STACK") + .map(|os_str| os_str.to_string_lossy().into_owned()) + // ignore if it is set to nothing + .filter(|s| s.trim() != "") + .map(|s| s.trim().parse::<usize>().unwrap()) + // otherwise pick a consistent default + .unwrap_or(DEFAULT_STACK_SIZE) + }) } pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>( @@ -66,10 +74,7 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>( // the parallel compiler, in particular to ensure there is no accidental // sharing of data between the main thread and the compilation thread // (which might cause problems for the parallel compiler). - let mut builder = thread::Builder::new().name("rustc".to_string()); - if let Some(size) = get_stack_size() { - builder = builder.stack_size(size); - } + let builder = thread::Builder::new().name("rustc".to_string()).stack_size(init_stack_size()); // We build the session globals and run `f` on the spawned thread, because // `SessionGlobals` does not impl `Send` in the non-parallel compiler. @@ -120,7 +125,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( }); } - let mut builder = rayon::ThreadPoolBuilder::new() + let builder = rayon::ThreadPoolBuilder::new() .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) .release_thread_handler(jobserver::release_thread) @@ -144,10 +149,8 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( on_panic.disable(); }) .unwrap(); - }); - if let Some(size) = get_stack_size() { - builder = builder.stack_size(size); - } + }) + .stack_size(init_stack_size()); // We create the session globals on the main thread, then create the thread // pool. Upon creation, each worker thread created gets a copy of the diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index df77181d6f7..0b757f95a99 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -865,7 +865,7 @@ trait UnusedDelimLint { (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true) } - Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { + Match(ref head, ..) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { let left = e.span.lo() + rustc_span::BytePos(5); (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true) } @@ -1133,7 +1133,7 @@ impl EarlyLintPass for UnusedParens { } return; } - ExprKind::Match(ref _expr, ref arm) => { + ExprKind::Match(ref _expr, ref arm, _) => { for a in arm { if let Some(body) = &a.body { self.check_unused_delims_expr( diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 96c58ef411b..9e8ee92b5d9 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +derivative = "2.2.0" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 214297b9869..02185cbeacf 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -456,7 +456,7 @@ impl<'tcx> Const<'tcx> { } /// An unevaluated (potentially generic) constant used in MIR. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 645a417c322..588aa1f40d7 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -88,14 +88,13 @@ pub enum CoverageKind { /// Marks a span that might otherwise not be represented in MIR, so that /// coverage instrumentation can associate it with its enclosing block/BCB. /// - /// Only used by the `InstrumentCoverage` pass, and has no effect during - /// codegen. + /// Should be erased before codegen (at some point after `InstrumentCoverage`). SpanMarker, /// Marks its enclosing basic block with an ID that can be referred to by /// side data in [`BranchInfo`]. /// - /// Has no effect during codegen. + /// Should be erased before codegen (at some point after `InstrumentCoverage`). BlockMarker { id: BlockMarkerId }, /// Marks the point in MIR control flow represented by a coverage counter. diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 4047891d769..00faa211853 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -37,9 +37,16 @@ pub trait AllocBytes: /// Create a zeroed `AllocBytes` of the specified size and alignment. /// Returns `None` if we ran out of memory on the host. fn zeroed(size: Size, _align: Align) -> Option<Self>; + + /// Gives direct access to the raw underlying storage. + /// + /// Crucially this pointer is compatible with: + /// - other pointers retunred by this method, and + /// - references returned from `deref()`, as long as there was no write. + fn as_mut_ptr(&mut self) -> *mut u8; } -// Default `bytes` for `Allocation` is a `Box<[u8]>`. +/// Default `bytes` for `Allocation` is a `Box<u8>`. impl AllocBytes for Box<[u8]> { fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self { Box::<[u8]>::from(slice.into()) @@ -51,6 +58,11 @@ impl AllocBytes for Box<[u8]> { let bytes = unsafe { bytes.assume_init() }; Some(bytes) } + + fn as_mut_ptr(&mut self) -> *mut u8 { + // Carefully avoiding any intermediate references. + ptr::addr_of_mut!(**self).cast() + } } /// This type represents an Allocation in the Miri/CTFE core engine. @@ -399,10 +411,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> /// Byte accessors. impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> { - pub fn base_addr(&self) -> *const u8 { - self.bytes.as_ptr() - } - /// This is the entirely abstraction-violating way to just grab the raw bytes without /// caring about provenance or initialization. /// @@ -452,13 +460,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> Ok(self.get_bytes_unchecked(range)) } - /// Just calling this already marks everything as defined and removes provenance, - /// so be sure to actually put data there! + /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes. + /// Just calling this already marks everything as defined and removes provenance, so be sure to + /// actually overwrite all the data there! /// /// It is the caller's responsibility to check bounds and alignment beforehand. /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods /// on `InterpCx` instead. - pub fn get_bytes_mut( + pub fn get_bytes_unchecked_for_overwrite( &mut self, cx: &impl HasDataLayout, range: AllocRange, @@ -469,8 +478,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()]) } - /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. - pub fn get_bytes_mut_ptr( + /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases + /// into this memory. + pub fn get_bytes_unchecked_for_overwrite_ptr( &mut self, cx: &impl HasDataLayout, range: AllocRange, @@ -479,10 +489,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> self.provenance.clear(range, cx)?; assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check + // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); let len = range.end().bytes_usize() - range.start.bytes_usize(); Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len)) } + + /// This gives direct mutable access to the entire buffer, just exposing their internal state + /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if + /// `OFFSET_IS_ADDR` is true. + pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 { + assert!(Prov::OFFSET_IS_ADDR); + self.bytes.as_mut_ptr() + } } /// Reading and writing. @@ -589,7 +608,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> }; let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, range)?; + // Yes we do overwrite all the bytes in `dst`. + let dst = self.get_bytes_unchecked_for_overwrite(cx, range)?; write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also store some provenance. diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 8bd872c1b19..731e050ca9b 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -284,8 +284,15 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// order of the category, thereby influencing diagnostic output. /// /// See also `rustc_const_eval::borrow_check::constraints`. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] +#[derive(derivative::Derivative)] +#[derivative( + PartialOrd, + Ord, + PartialOrd = "feature_allow_slow_enum", + Ord = "feature_allow_slow_enum" +)] pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, @@ -295,6 +302,7 @@ pub enum ConstraintCategory<'tcx> { Cast { /// Whether this is an unsizing cast and if yes, this contains the target type. /// Region variables are erased to ReErased. + #[derivative(PartialOrd = "ignore", Ord = "ignore")] unsize_to: Option<Ty<'tcx>>, }, @@ -304,7 +312,7 @@ pub enum ConstraintCategory<'tcx> { ClosureBounds, /// Contains the function type if available. - CallArgument(Option<Ty<'tcx>>), + CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option<Ty<'tcx>>), CopyBound, SizedBound, Assignment, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 0ab797134c0..752f5845afb 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -124,6 +124,7 @@ pub enum AnalysisPhase { /// * [`TerminatorKind::FalseEdge`] /// * [`StatementKind::FakeRead`] /// * [`StatementKind::AscribeUserType`] + /// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`] /// * [`Rvalue::Ref`] with `BorrowKind::Fake` /// /// Furthermore, `Deref` projections must be the first projection within any place (if they diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 11fd73c9094..595ef71cc32 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; -use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, @@ -356,21 +356,10 @@ impl<'tcx> SizeSkeleton<'tcx> { .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?; return Ok(SizeSkeleton::Known(Size::from_bytes(size))); } - let len = tcx.expand_abstract_consts(len); - let prev = ty::Const::from_target_usize(tcx, s.bytes()); - let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else { - return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty))); - }; - Ok(SizeSkeleton::Generic(gen_size)) + Err(tcx.arena.alloc(LayoutError::Unknown(ty))) } SizeSkeleton::Pointer { .. } => Err(err), - SizeSkeleton::Generic(g) => { - let len = tcx.expand_abstract_consts(len); - let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else { - return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty))); - }; - Ok(SizeSkeleton::Generic(gen_size)) - } + SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))), } } @@ -468,56 +457,6 @@ impl<'tcx> SizeSkeleton<'tcx> { } } -/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]), -/// to ensure that they have a canonical order and can be compared directly we combine all -/// constants, and sort the other terms. This allows comparison of expressions of sizes, -/// allowing for things like transmuting between types that depend on generic consts. -/// This returns `None` if multiplication of constants overflows. -fn mul_sorted_consts<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, -) -> Option<ty::Const<'tcx>> { - use crate::mir::BinOp::Mul; - - let mut work = vec![a, b]; - let mut done = vec![]; - while let Some(n) = work.pop() { - if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() { - work.push(l); - work.push(r) - } else { - done.push(n); - } - } - let mut k = 1; - let mut overflow = false; - done.retain(|c| { - let Some(c) = c.try_eval_target_usize(tcx, param_env) else { - return true; - }; - let Some(next) = c.checked_mul(k) else { - overflow = true; - return false; - }; - k = next; - false - }); - if overflow { - return None; - } - if k != 1 { - done.push(ty::Const::from_target_usize(tcx, k)); - } else if k == 0 { - return Some(ty::Const::from_target_usize(tcx, 0)); - } - done.sort_unstable(); - - // create a single tree from the buffer - done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty())) -} - pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index cfa853417ca..434ed16d5c6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -481,6 +481,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // when the iterator is an uninhabited type. unreachable_code will trigger instead. hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {} hir::MatchSource::ForLoopDesugar + | hir::MatchSource::Postfix | hir::MatchSource::Normal | hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report), // Unreachable patterns in try and await expressions occur when one of diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 5b4bc4fa134..aaf2035fc21 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -5,15 +5,20 @@ //! - [`AscribeUserType`] //! - [`FakeRead`] //! - [`Assign`] statements with a [`Fake`] borrow +//! - [`Coverage`] statements of kind [`BlockMarker`] or [`SpanMarker`] //! //! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType //! [`Assign`]: rustc_middle::mir::StatementKind::Assign //! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead //! [`Nop`]: rustc_middle::mir::StatementKind::Nop //! [`Fake`]: rustc_middle::mir::BorrowKind::Fake +//! [`Coverage`]: rustc_middle::mir::StatementKind::Coverage +//! [`BlockMarker`]: rustc_middle::mir::coverage::CoverageKind::BlockMarker +//! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker use crate::MirPass; -use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind}; +use rustc_middle::mir::coverage::CoverageKind; +use rustc_middle::mir::{Body, BorrowKind, Coverage, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::TyCtxt; pub struct CleanupPostBorrowck; @@ -25,6 +30,12 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { match statement.kind { StatementKind::AscribeUserType(..) | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _))) + | StatementKind::Coverage(box Coverage { + // These kinds of coverage statements are markers inserted during + // MIR building, and are not needed after InstrumentCoverage. + kind: CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. }, + .. + }) | StatementKind::FakeRead(..) => statement.make_nop(), _ => (), } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d175d1c04c8..fe17eba0d7b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -11,7 +11,7 @@ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; use ast::token::IdentIsRaw; -use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment}; +use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment}; use core::mem; use core::ops::ControlFlow; use rustc_ast::ptr::P; @@ -1379,6 +1379,13 @@ impl<'a> Parser<'a> { return Ok(self.mk_await_expr(self_arg, lo)); } + // Post-fix match + if self.eat_keyword(kw::Match) { + let match_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::postfix_match, match_span); + return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); + } + let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]); @@ -2894,8 +2901,20 @@ impl<'a> Parser<'a> { /// Parses a `match ... { ... }` expression (`match` token already eaten). fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> { let match_span = self.prev_token.span; - let lo = self.prev_token.span; let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; + + self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix) + } + + /// Parses the block of a `match expr { ... }` or a `expr.match { ... }` + /// expression. This is after the match token and scrutinee are eaten + fn parse_match_block( + &mut self, + lo: Span, + match_span: Span, + scrutinee: P<Expr>, + match_kind: MatchKind, + ) -> PResult<'a, P<Expr>> { if let Err(mut e) = self.expect(&token::OpenDelim(Delimiter::Brace)) { if self.token == token::Semi { e.span_suggestion_short( @@ -2938,7 +2957,7 @@ impl<'a> Parser<'a> { }); return Ok(self.mk_expr_with_attrs( span, - ExprKind::Match(scrutinee, arms), + ExprKind::Match(scrutinee, arms, match_kind), attrs, )); } @@ -2946,7 +2965,7 @@ impl<'a> Parser<'a> { } let hi = self.token.span; self.bump(); - Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)) + Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs)) } /// Attempt to recover from match arm body with statements and no surrounding braces. @@ -3955,7 +3974,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::While(_, _, _) | ExprKind::ForLoop { .. } | ExprKind::Loop(_, _, _) - | ExprKind::Match(_, _) + | ExprKind::Match(_, _, _) | ExprKind::Closure(_) | ExprKind::Block(_, _) | ExprKind::Gen(_, _, _) diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 8080216a252..4a1a2049083 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -48,7 +48,7 @@ impl NonConstExpr { Self::Match(TryDesugar(_)) => &[sym::const_try], // All other expressions are allowed. - Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[], + Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[], }; Some(gates) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8530c6072c5..b6c07e8737f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1335,6 +1335,7 @@ symbols! { poll, poll_next, post_dash_lto: "post-lto", + postfix_match, powerpc_target_feature, powf128, powf16, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 76a5d942c66..69b9fc33166 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -525,8 +525,8 @@ fn encode_ty<'tcx>( "{}", &len.try_to_scalar() .unwrap() - .to_u64() - .unwrap_or_else(|_| panic!("failed to convert length to u64")) + .to_target_usize(&tcx.data_layout) + .expect("Array lens are defined in usize") ); s.push_str(&encode_ty(tcx, *ty0, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 9c0236c172a..2ac42e20d43 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1575,6 +1575,25 @@ impl<T> NonNull<[T]> { self.as_ptr().len() } + /// Returns `true` if the non-null raw slice has a length of 0. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_is_empty_nonnull)] + /// use std::ptr::NonNull; + /// + /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); + /// assert!(!slice.is_empty()); + /// ``` + #[unstable(feature = "slice_ptr_is_empty_nonnull", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_is_empty_nonnull", issue = "71146")] + #[must_use] + #[inline] + pub const fn is_empty(self) -> bool { + self.len() == 0 + } + /// Returns a non-null pointer to the slice's buffer. /// /// # Examples diff --git a/src/doc/unstable-book/src/language-features/postfix-match.md b/src/doc/unstable-book/src/language-features/postfix-match.md new file mode 100644 index 00000000000..cd6b6a7442c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/postfix-match.md @@ -0,0 +1,22 @@ +# `postfix-match` + +`postfix-match` adds the feature for matching upon values postfix +the expressions that generate the values. + +```rust,edition2021 +#![feature(postfix_match)] + +enum Foo { + Bar, + Baz +} + +fn get_foo() -> Foo { + Foo::Bar +} + +get_foo().match { + Foo::Bar => {}, + Foo::Baz => panic!(), +} +``` diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs index fb434fb7450..3bdf13dbbea 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_else.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs @@ -105,7 +105,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor { fn visit_expr(&mut self, expr: &'ast Expr) { self.is_break = match expr.kind { ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) => true, - ExprKind::Match(_, ref arms) => arms.iter().all(|arm| + ExprKind::Match(_, ref arms, _) => arms.iter().all(|arm| arm.body.is_none() || arm.body.as_deref().is_some_and(|body| self.check_expr(body)) ), ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els), diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 60e9d262e7e..ab1b3043f0c 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -552,7 +552,7 @@ fn ident_difference_expr_with_base_location( | (Gen(_, _, _), Gen(_, _, _)) | (Block(_, _), Block(_, _)) | (Closure(_), Closure(_)) - | (Match(_, _), Match(_, _)) + | (Match(_, _, _), Match(_, _, _)) | (Loop(_, _, _), Loop(_, _, _)) | (ForLoop { .. }, ForLoop { .. }) | (While(_, _, _), While(_, _, _)) diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3874c1169e4..f7532121aeb 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -198,7 +198,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { }, (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv), (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp), - (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm), + (Match(ls, la, lkind), Match(rs, ra, rkind)) => (lkind == rkind) && eq_expr(ls, rs) && over(la, ra, eq_arm), ( Closure(box ast::Closure { binder: lb, diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index c500b30b998..053afcc52d4 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -3,7 +3,7 @@ use std::cmp::min; use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; -use rustc_ast::{ast, ptr, token, ForLoopKind}; +use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind}; use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; @@ -170,8 +170,8 @@ pub(crate) fn format_expr( } } } - ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) + ast::ExprKind::Match(ref cond, ref arms, kind) => { + rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind) } ast::ExprKind::Path(ref qself, ref path) => { rewrite_path(context, PathContext::Expr, qself, path, shape) @@ -625,7 +625,7 @@ pub(crate) fn rewrite_cond( shape: Shape, ) -> Option<String> { match expr.kind { - ast::ExprKind::Match(ref cond, _) => { + ast::ExprKind::Match(ref cond, _, MatchKind::Prefix) => { // `match `cond` {` let cond_shape = match context.config.indent_style() { IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index 5a00984d4c0..e68903c8715 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -2,7 +2,7 @@ use std::iter::repeat; -use rustc_ast::{ast, ptr}; +use rustc_ast::{ast, ptr, MatchKind}; use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; @@ -72,6 +72,7 @@ pub(crate) fn rewrite_match( shape: Shape, span: Span, attrs: &[ast::Attribute], + match_kind: MatchKind, ) -> Option<String> { // Do not take the rhs overhead from the upper expressions into account // when rewriting match condition. @@ -131,15 +132,27 @@ pub(crate) fn rewrite_match( } } else { let span_after_cond = mk_sp(cond.span.hi(), span.hi()); - Some(format!( - "match {}{}{{\n{}{}{}\n{}}}", - cond_str, - block_sep, - inner_attrs_str, - nested_indent_str, - rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?, - shape.indent.to_string(context.config), - )) + + match match_kind { + MatchKind::Prefix => Some(format!( + "match {}{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + nested_indent_str, + rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?, + shape.indent.to_string(context.config), + )), + MatchKind::Postfix => Some(format!( + "{}.match{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + nested_indent_str, + rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?, + shape.indent.to_string(context.config), + )), + } } } diff --git a/src/tools/rustfmt/tests/source/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/source/postfix-match/pf-match.rs new file mode 100644 index 00000000000..b2366723631 --- /dev/null +++ b/src/tools/rustfmt/tests/source/postfix-match/pf-match.rs @@ -0,0 +1,20 @@ +#![feature(postfix_match)] + +fn main() { + let val = Some(42); + + val.match { + Some(_) => 2, + _ => 1 + }; + + Some(2).match { + Some(_) => true, + None => false + }.match { + false => "ferris is cute", + true => "I turn cats in to petted cats", + }.match { + _ => (), + } +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs new file mode 100644 index 00000000000..f439f272623 --- /dev/null +++ b/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs @@ -0,0 +1,20 @@ +#![feature(postfix_match)] + +fn main() { + let val = Some(42); + + val.match { + Some(_) => 2, + _ => 1, + }; + + Some(2).match { + Some(_) => true, + None => false, + }.match { + false => "ferris is cute", + true => "I turn cats in to petted cats", + }.match { + _ => (), + } +} diff --git a/tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff new file mode 100644 index 00000000000..ff65ca77039 --- /dev/null +++ b/tests/mir-opt/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before CleanupPostBorrowck ++ // MIR for `main` after CleanupPostBorrowck + + fn main() -> () { + let mut _0: (); + let mut _1: bool; + + coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0) + + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; + coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) }; + coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36; + coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39; + coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40; + coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2; + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36; + + bb0: { + Coverage::CounterIncrement(0); +- Coverage::SpanMarker; ++ nop; + StorageLive(_1); + _1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5]; + } + + bb1: { + switchInt(move _1) -> [0: bb3, otherwise: bb2]; + } + + bb2: { + Coverage::CounterIncrement(1); +- Coverage::BlockMarker(1); ++ nop; + _0 = const (); + goto -> bb4; + } + + bb3: { + Coverage::ExpressionUsed(0); +- Coverage::BlockMarker(0); ++ nop; + _0 = const (); + goto -> bb4; + } + + bb4: { + Coverage::ExpressionUsed(1); + StorageDead(_1); + return; + } + + bb5 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff new file mode 100644 index 00000000000..8757559149a --- /dev/null +++ b/tests/mir-opt/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before InstrumentCoverage ++ // MIR for `main` after InstrumentCoverage + + fn main() -> () { + let mut _0: (); + let mut _1: bool; + + coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0) + ++ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; ++ coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) }; ++ coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36; ++ coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39; ++ coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40; ++ coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2; ++ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36; ++ + bb0: { ++ Coverage::CounterIncrement(0); + Coverage::SpanMarker; + StorageLive(_1); + _1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5]; + } + + bb1: { + switchInt(move _1) -> [0: bb3, otherwise: bb2]; + } + + bb2: { ++ Coverage::CounterIncrement(1); + Coverage::BlockMarker(1); + _0 = const (); + goto -> bb4; + } + + bb3: { ++ Coverage::ExpressionUsed(0); + Coverage::BlockMarker(0); + _0 = const (); + goto -> bb4; + } + + bb4: { ++ Coverage::ExpressionUsed(1); + StorageDead(_1); + return; + } + + bb5 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/instrument_coverage_cleanup.rs b/tests/mir-opt/instrument_coverage_cleanup.rs new file mode 100644 index 00000000000..8a2fd67139b --- /dev/null +++ b/tests/mir-opt/instrument_coverage_cleanup.rs @@ -0,0 +1,22 @@ +// Test that CleanupPostBorrowck cleans up the marker statements that are +// inserted during MIR building (after InstrumentCoverage is done with them), +// but leaves the statements that were added by InstrumentCoverage. +// +// Removed statement kinds: BlockMarker, SpanMarker +// Retained statement kinds: CounterIncrement, ExpressionUsed + +//@ unit-test: InstrumentCoverage +//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=branch -Zno-profiler-runtime +//@ compile-flags: --remap-path-prefix={{src-base}}=/the/src + +// EMIT_MIR instrument_coverage_cleanup.main.InstrumentCoverage.diff +// EMIT_MIR instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +fn main() { + if !core::hint::black_box(true) {} +} + +// CHECK-NOT: Coverage::BlockMarker +// CHECK-NOT: Coverage::SpanMarker +// CHECK: Coverage::CounterIncrement +// CHECK-NOT: Coverage::BlockMarker +// CHECK-NOT: Coverage::SpanMarker diff --git a/tests/pretty/postfix-match.rs b/tests/pretty/postfix-match.rs new file mode 100644 index 00000000000..5bb54e15275 --- /dev/null +++ b/tests/pretty/postfix-match.rs @@ -0,0 +1,21 @@ +#![feature(postfix_match)] + +fn main() { + let val = Some(42); + + val.match { + Some(_) => 2, + _ => 1 + }; + + + Some(2).match { + Some(_) => true, + None => false + }.match { + false => "ferris is cute", + true => "I turn cats in to petted cats", + }.match { + _ => (), + } +} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs new file mode 100644 index 00000000000..a2f8c876b5e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.rs @@ -0,0 +1,13 @@ +// test for ICE "no entry found for key" in generics_of.rs #113017 + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub fn foo() +where + for<const N: usize = { || {}; 1 }> ():, + //~^ ERROR only lifetime parameters can be used in this context + //~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders +{} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr new file mode 100644 index 00000000000..edf27f58efd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-generics_of-no-entry-found-for-key-113017.stderr @@ -0,0 +1,19 @@ +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:15 + | +LL | for<const N: usize = { || {}; 1 }> ():, + | ^ + | + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: defaults for generic parameters are not allowed in `for<...>` binders + --> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:9 + | +LL | for<const N: usize = { || {}; 1 }> ():, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs new file mode 100644 index 00000000000..4ba696f4ae0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs @@ -0,0 +1,18 @@ +// test for ICE #119275 "no entry found for key" in predicates_of.rs + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn bug<const N: Nat>(&self) +//~^ ERROR `self` parameter is only allowed in associated functions +//~^^ ERROR cannot find type `Nat` in this scope +where + for<const N: usize = 3, T = u32> [(); COT::BYTES]:, + //~^ ERROR only lifetime parameters can be used in this context + //~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders + //~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders + //~^^^^ ERROR failed to resolve: use of undeclared type `COT` +{ +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr new file mode 100644 index 00000000000..ee0ec38ab06 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr @@ -0,0 +1,46 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:22 + | +LL | fn bug<const N: Nat>(&self) + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0412]: cannot find type `Nat` in this scope + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:17 + | +LL | fn bug<const N: Nat>(&self) + | ^^^ not found in this scope + +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:15 + | +LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:, + | ^ ^ + | + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: defaults for generic parameters are not allowed in `for<...>` binders + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:9 + | +LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:, + | ^^^^^^^^^^^^^^^^^^ + +error: defaults for generic parameters are not allowed in `for<...>` binders + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:29 + | +LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:, + | ^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type `COT` + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:43 + | +LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:, + | ^^^ use of undeclared type `COT` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0412, E0433, E0658. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index d7bf1b47fb5..90afd232534 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -32,4 +32,79 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777 } } +fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn flatten_3d<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [u32; D * W * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn flatten_somewhat<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [[u32; D * W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + +fn transpose_with_const<const W: usize, const H: usize>( + v: [[u32; 2 * H]; W + W] +) -> [[u32; W + W]; 2 * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } +} + fn main() {} diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 397e3be768a..1b0d1ea50d0 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W) - = note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H) + = 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]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fail.rs:16:5 @@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[u32; H]; W]` (generic size 4 * H * W) - = note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W) + = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) + = 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 --> $DIR/transmute-fail.rs:30:5 @@ -34,6 +34,87 @@ LL | std::mem::transmute(v) = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` 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 + --> $DIR/transmute-fail.rs:37:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 + --> $DIR/transmute-fail.rs:50:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) + = 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 + --> $DIR/transmute-fail.rs:57:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u32; H*W]` (this type does not have a fixed size) + = 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 + --> $DIR/transmute-fail.rs:66:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) + = 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 + --> $DIR/transmute-fail.rs:75:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) + = 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 + --> $DIR/transmute-fail.rs:82:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u16; L]` (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 + --> $DIR/transmute-fail.rs:89:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; L * 2]` (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 + --> $DIR/transmute-fail.rs:96:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 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 + --> $DIR/transmute-fail.rs:105:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = 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]) + error[E0308]: mismatched types --> $DIR/transmute-fail.rs:12:53 | @@ -46,7 +127,7 @@ error[E0308]: mismatched types LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { | ^ expected `usize`, found `bool` -error: aborting due to 6 previous errors +error: aborting due to 15 previous errors Some errors have detailed explanations: E0308, E0512. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs index 245fcf5670e..e8ab8637932 100644 --- a/tests/ui/const-generics/transmute.rs +++ b/tests/ui/const-generics/transmute.rs @@ -3,81 +3,12 @@ #![feature(transmute_generic_consts)] #![allow(incomplete_features)] -fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] { - unsafe { - std::mem::transmute(v) - } -} - fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { unsafe { std::mem::transmute(v) } } -fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] { - unsafe { - std::mem::transmute(v) - } -} - -fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] { - unsafe { - std::mem::transmute(v) - } -} - -fn flatten_3d<const W: usize, const H: usize, const D: usize>( - v: [[[u32; D]; H]; W] -) -> [u32; D * W * H] { - unsafe { - std::mem::transmute(v) - } -} - -fn flatten_somewhat<const W: usize, const H: usize, const D: usize>( - v: [[[u32; D]; H]; W] -) -> [[u32; D * W]; H] { - unsafe { - std::mem::transmute(v) - } -} - -fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] { - unsafe { - std::mem::transmute(v) - } -} - -fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] { - unsafe { - std::mem::transmute(v) - } -} - -fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] { - unsafe { - std::mem::transmute(v) - } -} - -fn transpose_with_const<const W: usize, const H: usize>( - v: [[u32; 2 * H]; W + W] -) -> [[u32; W + W]; 2 * H] { - unsafe { - std::mem::transmute(v) - } -} - fn main() { - let _ = transpose([[0; 8]; 16]); - let _ = transpose_with_const::<8,4>([[0; 8]; 16]); let _ = ident([[0; 8]; 16]); - let _ = flatten([[0; 13]; 5]); - let _: [[_; 5]; 13] = coagulate([0; 65]); - let _ = flatten_3d([[[0; 3]; 13]; 5]); - let _ = flatten_somewhat([[[0; 3]; 13]; 5]); - let _ = known_size([16; 13]); - let _: [u16; 5] = condense_bytes([16u8; 10]); - let _ = singleton_each([16; 10]); } diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs new file mode 100644 index 00000000000..dc9782295c1 --- /dev/null +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs @@ -0,0 +1,20 @@ +// test for #112824 ICE type mismatching when copying! + +pub struct Opcode(pub u8); + +pub struct Opcode2(&'a S); +//~^ ERROR use of undeclared lifetime name `'a` +//~^^ ERROR cannot find type `S` in this scope + +impl Opcode2 { + pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); +} + +pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { + move |i| match msg_type { + Opcode2::OP2 => unimplemented!(), + //~^ ERROR could not evaluate constant pattern + } +} + +pub fn main() {} diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr new file mode 100644 index 00000000000..9442eac0cf5 --- /dev/null +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr @@ -0,0 +1,29 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/ice-type-mismatch-when-copying-112824.rs:5:21 + | +LL | pub struct Opcode2(&'a S); + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0412]: cannot find type `S` in this scope + --> $DIR/ice-type-mismatch-when-copying-112824.rs:5:24 + | +LL | pub struct Opcode2(&'a S); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | pub struct Opcode2<S>(&'a S); + | +++ + +error: could not evaluate constant pattern + --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9 + | +LL | Opcode2::OP2 => unimplemented!(), + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0261, E0412. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.rs b/tests/ui/feature-gates/feature-gate-postfix_match.rs new file mode 100644 index 00000000000..dce7e81a9ae --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-postfix_match.rs @@ -0,0 +1,17 @@ +// Testing that postfix match doesn't work without enabling the feature + +fn main() { + let val = Some(42); + + val.match { //~ ERROR postfix match is experimental + Some(42) => "the answer to life, the universe, and everything", + _ => "might be the answer to something" + }; + + // Test that the gate works behind a cfg + #[cfg(FALSE)] + val.match { //~ ERROR postfix match is experimental + Some(42) => "the answer to life, the universe, and everything", + _ => "might be the answer to something" + }; +} diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.stderr b/tests/ui/feature-gates/feature-gate-postfix_match.stderr new file mode 100644 index 00000000000..136838788dd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-postfix_match.stderr @@ -0,0 +1,23 @@ +error[E0658]: postfix match is experimental + --> $DIR/feature-gate-postfix_match.rs:6:9 + | +LL | val.match { + | ^^^^^ + | + = note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information + = help: add `#![feature(postfix_match)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: postfix match is experimental + --> $DIR/feature-gate-postfix_match.rs:13:9 + | +LL | val.match { + | ^^^^^ + | + = note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information + = help: add `#![feature(postfix_match)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs new file mode 100644 index 00000000000..d6fa56663a3 --- /dev/null +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -0,0 +1,30 @@ +// test for ICE #112823 +// Unexpected parameter Type(Repr) when substituting in region + +#![feature(impl_trait_in_assoc_type)] + +use std::future::Future; + +trait Stream {} + +trait X { + type LineStream<'a, Repr> + where + Self: 'a; + type LineStreamFut<'a, Repr> + where + Self: 'a; +} + +struct Y; + +impl X for Y { + type LineStream<'c, 'd> = impl Stream; + //~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter + type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>; + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} + //~^ ERROR `()` is not a future + //~^^ method `line_stream` is not a member of trait `X` +} + +pub fn main() {} diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr new file mode 100644 index 00000000000..28a0f7461e2 --- /dev/null +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr @@ -0,0 +1,31 @@ +error[E0407]: method `line_stream` is not a member of trait `X` + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:5 + | +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` + +error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:22:21 + | +LL | type LineStream<'a, Repr> + | -- ---- + | | + | expected 1 type parameter +... +LL | type LineStream<'c, 'd> = impl Stream; + | ^^ ^^ + | | + | found 0 type parameters + +error[E0277]: `()` is not a future + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:43 + | +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future + | + = help: the trait `Future` is not implemented for `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0049, E0277, E0407. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/match/postfix-match/pf-match-chain.rs b/tests/ui/match/postfix-match/pf-match-chain.rs new file mode 100644 index 00000000000..80546e1963b --- /dev/null +++ b/tests/ui/match/postfix-match/pf-match-chain.rs @@ -0,0 +1,16 @@ +//@ run-pass + +#![feature(postfix_match)] + +fn main() { + 1.match { + 2 => Some(0), + _ => None, + }.match { + None => Ok(true), + Some(_) => Err("nope") + }.match { + Ok(_) => (), + Err(_) => panic!() + } +} diff --git a/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs new file mode 100644 index 00000000000..f4cac46f7cd --- /dev/null +++ b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs @@ -0,0 +1,7 @@ +#![feature(postfix_match)] + +fn main() { + Some(1).match { //~ non-exhaustive patterns + None => {}, + } +} diff --git a/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr b/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr new file mode 100644 index 00000000000..f458218bb5d --- /dev/null +++ b/tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/pf-match-exhaustiveness.rs:4:5 + | +LL | Some(1).match { + | ^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<i32>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<i32>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL ~ Some(_) => todo!(), + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/match/postfix-match/pf-match-types.rs b/tests/ui/match/postfix-match/pf-match-types.rs new file mode 100644 index 00000000000..af205926fb6 --- /dev/null +++ b/tests/ui/match/postfix-match/pf-match-types.rs @@ -0,0 +1,15 @@ +#![feature(postfix_match)] + +fn main() { + Some(10).match { + //~^ NOTE `match` arms have incompatible types + Some(5) => false, + //~^ NOTE this is found to be of type `bool` + Some(2) => true, + //~^ NOTE this is found to be of type `bool` + None => (), + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `bool`, found `()` + _ => true + } +} diff --git a/tests/ui/match/postfix-match/pf-match-types.stderr b/tests/ui/match/postfix-match/pf-match-types.stderr new file mode 100644 index 00000000000..0cfc1363d5f --- /dev/null +++ b/tests/ui/match/postfix-match/pf-match-types.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/pf-match-types.rs:10:20 + | +LL | / Some(10).match { +LL | | +LL | | Some(5) => false, + | | ----- this is found to be of type `bool` +LL | | +LL | | Some(2) => true, + | | ---- this is found to be of type `bool` +LL | | +LL | | None => (), + | | ^^ expected `bool`, found `()` +... | +LL | | _ => true +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/postfix-match/postfix-match.rs b/tests/ui/match/postfix-match/postfix-match.rs new file mode 100644 index 00000000000..03c4e8ab545 --- /dev/null +++ b/tests/ui/match/postfix-match/postfix-match.rs @@ -0,0 +1,62 @@ +//@ run-pass + +#![feature(postfix_match)] + +struct Bar { + foo: u8, + baz: u8, +} + +pub fn main() { + let thing = Some("thing"); + + thing.match { + Some("nothing") => {}, + Some(text) if text.eq_ignore_ascii_case("tapir") => {}, + Some("true") | Some("false") => {}, + Some("thing") => {}, + Some(_) => {}, + None => {} + }; + + let num = 2u8; + + num.match { + 0 => {}, + 1..=5 => {}, + _ => {}, + }; + + let slic = &[1, 2, 3, 4][..]; + + slic.match { + [1] => {}, + [2, _tail @ ..] => {}, + [1, _] => {}, + _ => {}, + }; + + slic[0].match { + 1 => 0, + i => i, + }; + + let out = (1, 2).match { + (1, 3) => 0, + (_, 1) => 0, + (1, i) => i, + _ => 3, + }; + assert!(out == 2); + + let strct = Bar { + foo: 3, + baz: 4 + }; + + strct.match { + Bar { foo: 1, .. } => {}, + Bar { baz: 2, .. } => {}, + _ => (), + }; +} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 9feb2a7320d..d7933a39eaa 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -53,17 +53,16 @@ LL | fn case2() { error[E0597]: `a` does not live long enough --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26 | -LL | let a = 0; - | - binding `a` declared here -LL | let cell = Cell::new(&a); - | ^^ borrowed value does not live long enough +LL | let a = 0; + | - binding `a` declared here +LL | let cell = Cell::new(&a); + | ----------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'static` ... -LL | / foo(cell, |cell_a, cell_x| { -LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error -LL | | }) - | |______- argument requires that `a` is borrowed for `'static` -LL | } - | - `a` dropped here while still borrowed +LL | } + | - `a` dropped here while still borrowed error: aborting due to 2 previous errors diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr index 5b385feeedc..644fc94f730 100644 --- a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr +++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -1,16 +1,17 @@ error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:33:41 | -LL | let c = 66; - | - binding `c` declared here -LL | / combine( -LL | | SomeEnum::SomeVariant(Cell::new(&c)), - | | ^^ borrowed value does not live long enough -LL | | SomeEnum::SomeOtherVariant::<Cell<&'static u32>>, -LL | | ); - | |_____- argument requires that `c` is borrowed for `'static` -LL | } - | - `c` dropped here while still borrowed +LL | let c = 66; + | - binding `c` declared here +LL | combine( +LL | SomeEnum::SomeVariant(Cell::new(&c)), + | ----------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` +... +LL | } + | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:41:41 diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs new file mode 100644 index 00000000000..fc71d0d61ff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs @@ -0,0 +1,52 @@ +// test for #110696 +// failed to resolve instance for <Scope<()> as MyIndex<()>>::my_index +// ignore-tidy-linelength + +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + + +trait MyIndex<T> { + type O; + fn my_index(self) -> Self::O; +} +trait MyFrom<T>: Sized { + type Error; + fn my_from(value: T) -> Result<Self, Self::Error>; +} + + +trait F {} +impl F for () {} +type DummyT<T> = impl F; +fn _dummy_t<T>() -> DummyT<T> {} + +struct Phantom1<T>(PhantomData<T>); +struct Phantom2<T>(PhantomData<T>); +struct Scope<T>(Phantom2<DummyT<T>>); + +impl<T> Scope<T> { + fn new() -> Self { + unimplemented!() + } +} + +impl<T> MyFrom<Phantom2<T>> for Phantom1<T> { + type Error = (); + fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> { + unimplemented!() + } +} + +impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> { + //~^ ERROR the type parameter `T` is not constrained by the impl + type O = T; + fn my_index(self) -> Self::O { + MyFrom::my_from(self.0).ok().unwrap() + } +} + +fn main() { + let _pos: Phantom1<DummyT<()>> = Scope::new().my_index(); +} diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr new file mode 100644 index 00000000000..a39f77ce17f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:42:6 + | +LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> { + | ^ unconstrained type parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs new file mode 100644 index 00000000000..37e0d89efc7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs @@ -0,0 +1,16 @@ +// test for ICE #121472 index out of bounds un_derefer.rs +#![feature(type_alias_impl_trait)] + +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +fn with_positive(fun: impl Fn(Alias<'_>)) {} + +fn main() { + with_positive(|&n| ()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr new file mode 100644 index 00000000000..a224bab0705 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/underef-index-out-of-bounds-121472.rs:14:20 + | +LL | type Alias<'a> = impl T; + | ------ the expected opaque type +... +LL | with_positive(|&n| ()); + | ^^ + | | + | expected opaque type, found `&_` + | expected due to this + | + = note: expected opaque type `Alias<'_>` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs new file mode 100644 index 00000000000..107cfbb9ff6 --- /dev/null +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs @@ -0,0 +1,12 @@ +trait Trait<const N: Trait = bar> { +//~^ ERROR cannot find value `bar` in this scope +//~| ERROR cycle detected when computing type of `Trait::N` +//~| ERROR cycle detected when computing type of `Trait::N` +//~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + fn fnc(&self) { + } +} + +fn main() {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr new file mode 100644 index 00000000000..2d5a0ede962 --- /dev/null +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -0,0 +1,60 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:30 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` on by default +help: if this is an object-safe trait, use `dyn` + | +LL | trait Trait<const N: dyn Trait = bar> { + | +++ + +error[E0391]: cycle detected when computing type of `Trait::N` + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^ + | + = note: ...which immediately requires computing type of `Trait::N` again +note: cycle used when computing explicit predicates of trait `Trait` + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `Trait::N` + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing type of `Trait::N` again +note: cycle used when computing explicit predicates of trait `Trait` + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 + | +LL | trait Trait<const N: Trait = bar> { + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0391, E0425. +For more information about an error, try `rustc --explain E0391`. |
