diff options
501 files changed, 4840 insertions, 3523 deletions
diff --git a/Cargo.lock b/Cargo.lock index d2b8e747cd1..f2120495e43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -537,7 +537,7 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.76" +version = "0.1.77" dependencies = [ "anstream", "clippy_config", @@ -565,7 +565,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.76" +version = "0.1.77" dependencies = [ "rustc-semver", "serde", @@ -588,7 +588,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.76" +version = "0.1.77" dependencies = [ "arrayvec", "cargo_metadata 0.15.4", @@ -613,7 +613,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.76" +version = "0.1.77" dependencies = [ "arrayvec", "clippy_config", @@ -984,7 +984,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.76" +version = "0.1.77" dependencies = [ "itertools", "quote", diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index ccc6644923a..e568da9bbc0 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -183,14 +183,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), hir::MatchSource::Normal, ), - ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr( - *capture_clause, - e.id, - None, - e.span, - hir::CoroutineSource::Block, - |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), - ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { binder, @@ -226,6 +218,22 @@ impl<'hir> LoweringContext<'_, 'hir> { *fn_arg_span, ), }, + ExprKind::Gen(capture_clause, block, genblock_kind) => { + let desugaring_kind = match genblock_kind { + GenBlockKind::Async => hir::CoroutineDesugaring::Async, + GenBlockKind::Gen => hir::CoroutineDesugaring::Gen, + GenBlockKind::AsyncGen => hir::CoroutineDesugaring::AsyncGen, + }; + self.make_desugared_coroutine_expr( + *capture_clause, + e.id, + None, + e.span, + desugaring_kind, + hir::CoroutineSource::Block, + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), + ) + } ExprKind::Block(blk, opt_label) => { let opt_label = self.lower_label(*opt_label); hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) @@ -313,23 +321,6 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr( - *capture_clause, - e.id, - None, - e.span, - hir::CoroutineSource::Block, - |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), - ), - ExprKind::Gen(capture_clause, block, GenBlockKind::AsyncGen) => self - .make_async_gen_expr( - *capture_clause, - e.id, - None, - e.span, - hir::CoroutineSource::Block, - |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), - ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => { hir::ExprKind::Err(self.dcx().span_delayed_bug(e.span, "lowered ExprKind::Err")) @@ -612,213 +603,91 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Arm { hir_id, pat, guard, body, span } } - /// Lower an `async` construct to a coroutine that implements `Future`. + /// Lower/desugar a coroutine construct. /// - /// This results in: - /// - /// ```text - /// static move? |_task_context| -> <ret_ty> { - /// <body> - /// } - /// ``` - pub(super) fn make_async_expr( - &mut self, - capture_clause: CaptureBy, - closure_node_id: NodeId, - ret_ty: Option<hir::FnRetTy<'hir>>, - span: Span, - async_coroutine_source: hir::CoroutineSource, - body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, - ) -> hir::ExprKind<'hir> { - let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); - - // Resume argument type: `ResumeTy` - let unstable_span = self.mark_span_with_reason( - DesugaringKind::Async, - self.lower_span(span), - Some(self.allow_gen_future.clone()), - ); - let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span); - let input_ty = hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::Path(resume_ty), - span: unstable_span, - }; - - // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`. - let fn_decl = self.arena.alloc(hir::FnDecl { - inputs: arena_vec![self; input_ty], - output, - c_variadic: false, - implicit_self: hir::ImplicitSelfKind::None, - lifetime_elision_allowed: false, - }); - - // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. - let (pat, task_context_hid) = self.pat_ident_binding_mode( - span, - Ident::with_dummy_span(sym::_task_context), - hir::BindingAnnotation::MUT, - ); - let param = hir::Param { - hir_id: self.next_id(), - pat, - ty_span: self.lower_span(span), - span: self.lower_span(span), - }; - let params = arena_vec![self; param]; - - let coroutine_kind = - hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, async_coroutine_source); - let body = self.lower_body(move |this| { - this.coroutine_kind = Some(coroutine_kind); - - let old_ctx = this.task_context; - this.task_context = Some(task_context_hid); - let res = body(this); - this.task_context = old_ctx; - (params, res) - }); - - // `static |_task_context| -> <ret_ty> { body }`: - hir::ExprKind::Closure(self.arena.alloc(hir::Closure { - def_id: self.local_def_id(closure_node_id), - binder: hir::ClosureBinder::Default, - capture_clause, - bound_generic_params: &[], - fn_decl, - body, - fn_decl_span: self.lower_span(span), - fn_arg_span: None, - kind: hir::ClosureKind::Coroutine(coroutine_kind), - constness: hir::Constness::NotConst, - })) - } - - /// Lower a `gen` construct to a generator that implements `Iterator`. + /// In particular, this creates the correct async resume argument and `_task_context`. /// /// This results in: /// /// ```text - /// static move? |()| -> () { + /// static move? |<_task_context?>| -> <return_ty> { /// <body> /// } /// ``` - pub(super) fn make_gen_expr( + pub(super) fn make_desugared_coroutine_expr( &mut self, capture_clause: CaptureBy, closure_node_id: NodeId, - _yield_ty: Option<hir::FnRetTy<'hir>>, + return_ty: Option<hir::FnRetTy<'hir>>, span: Span, + desugaring_kind: hir::CoroutineDesugaring, coroutine_source: hir::CoroutineSource, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { - let output = hir::FnRetTy::DefaultReturn(self.lower_span(span)); - - // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. - let fn_decl = self.arena.alloc(hir::FnDecl { - inputs: &[], - output, - c_variadic: false, - implicit_self: hir::ImplicitSelfKind::None, - lifetime_elision_allowed: false, - }); - - let coroutine_kind = - hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, coroutine_source); - let body = self.lower_body(move |this| { - this.coroutine_kind = Some(coroutine_kind); - - let res = body(this); - (&[], res) - }); - - // `static |()| -> () { body }`: - hir::ExprKind::Closure(self.arena.alloc(hir::Closure { - def_id: self.local_def_id(closure_node_id), - binder: hir::ClosureBinder::Default, - capture_clause, - bound_generic_params: &[], - fn_decl, - body, - fn_decl_span: self.lower_span(span), - fn_arg_span: None, - kind: hir::ClosureKind::Coroutine(coroutine_kind), - constness: hir::Constness::NotConst, - })) - } + let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source); + + // The `async` desugaring takes a resume argument and maintains a `task_context`, + // whereas a generator does not. + let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind { + hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => { + // Resume argument type: `ResumeTy` + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + self.lower_span(span), + Some(self.allow_gen_future.clone()), + ); + let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span); + let input_ty = hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::Path(resume_ty), + span: unstable_span, + }; + let inputs = arena_vec![self; input_ty]; - /// Lower a `async gen` construct to a generator that implements `AsyncIterator`. - /// - /// This results in: - /// - /// ```text - /// static move? |_task_context| -> () { - /// <body> - /// } - /// ``` - pub(super) fn make_async_gen_expr( - &mut self, - capture_clause: CaptureBy, - closure_node_id: NodeId, - _yield_ty: Option<hir::FnRetTy<'hir>>, - span: Span, - async_coroutine_source: hir::CoroutineSource, - body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, - ) -> hir::ExprKind<'hir> { - let output = hir::FnRetTy::DefaultReturn(self.lower_span(span)); + // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. + let (pat, task_context_hid) = self.pat_ident_binding_mode( + span, + Ident::with_dummy_span(sym::_task_context), + hir::BindingAnnotation::MUT, + ); + let param = hir::Param { + hir_id: self.next_id(), + pat, + ty_span: self.lower_span(span), + span: self.lower_span(span), + }; + let params = arena_vec![self; param]; - // Resume argument type: `ResumeTy` - let unstable_span = self.mark_span_with_reason( - DesugaringKind::Async, - self.lower_span(span), - Some(self.allow_gen_future.clone()), - ); - let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span); - let input_ty = hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::Path(resume_ty), - span: unstable_span, + (inputs, params, Some(task_context_hid)) + } + hir::CoroutineDesugaring::Gen => (&[], &[], None), }; - // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`. + let output = + return_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); + let fn_decl = self.arena.alloc(hir::FnDecl { - inputs: arena_vec![self; input_ty], + inputs, output, c_variadic: false, implicit_self: hir::ImplicitSelfKind::None, lifetime_elision_allowed: false, }); - // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. - let (pat, task_context_hid) = self.pat_ident_binding_mode( - span, - Ident::with_dummy_span(sym::_task_context), - hir::BindingAnnotation::MUT, - ); - let param = hir::Param { - hir_id: self.next_id(), - pat, - ty_span: self.lower_span(span), - span: self.lower_span(span), - }; - let params = arena_vec![self; param]; - - let coroutine_kind = hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - async_coroutine_source, - ); let body = self.lower_body(move |this| { this.coroutine_kind = Some(coroutine_kind); let old_ctx = this.task_context; - this.task_context = Some(task_context_hid); + if task_context.is_some() { + this.task_context = task_context; + } let res = body(this); this.task_context = old_ctx; + (params, res) }); - // `static |_task_context| -> <ret_ty> { body }`: + // `static |<_task_context?>| -> <return_ty> { <body> }`: hir::ExprKind::Closure(self.arena.alloc(hir::Closure { def_id: self.local_def_id(closure_node_id), binder: hir::ClosureBinder::Default, @@ -1203,11 +1072,12 @@ impl<'hir> LoweringContext<'_, 'hir> { None }; - let async_body = this.make_async_expr( + let async_body = this.make_desugared_coroutine_expr( capture_clause, inner_closure_id, async_ret_ty, body.span, + hir::CoroutineDesugaring::Async, hir::CoroutineSource::Closure, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), ); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3848f3b7782..45357aca533 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1209,33 +1209,20 @@ impl<'hir> LoweringContext<'_, 'hir> { this.expr_block(body) }; - // FIXME(gen_blocks): Consider unifying the `make_*_expr` functions. - let coroutine_expr = match coroutine_kind { - CoroutineKind::Async { .. } => this.make_async_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - hir::CoroutineSource::Fn, - mkbody, - ), - CoroutineKind::Gen { .. } => this.make_gen_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - hir::CoroutineSource::Fn, - mkbody, - ), - CoroutineKind::AsyncGen { .. } => this.make_async_gen_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - hir::CoroutineSource::Fn, - mkbody, - ), + let desugaring_kind = match coroutine_kind { + CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, + CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, + CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen, }; + let coroutine_expr = this.make_desugared_coroutine_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + desugaring_kind, + hir::CoroutineSource::Fn, + mkbody, + ); let hir_id = this.lower_node_id(closure_id); this.maybe_forward_track_caller(body.span, fn_id, hir_id); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c14a05bd145..b31325485db 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -370,7 +370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => { self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } - ty::Closure(def_id, _) | ty::Coroutine(def_id, _, _) => { + ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. // @@ -792,8 +792,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind - && let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) = - **kind + && let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) = **kind { debug!("move_spans: def_id={:?} places={:?}", def_id, places); let def_id = def_id.expect_local(); @@ -928,7 +927,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind { let (&def_id, is_coroutine) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), - box AggregateKind::Coroutine(def_id, _, _) => (def_id, true), + box AggregateKind::Coroutine(def_id, _) => (def_id, true), _ => continue, }; let def_id = def_id.expect_local(); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index af21847cffd..495b255583c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -274,11 +274,12 @@ fn do_mir_borrowck<'tcx>( // The first argument is the coroutine type passed by value if let Some(local) = body.local_decls.raw.get(1) // Get the interior types and args which typeck computed - && let ty::Coroutine(_, _, hir::Movability::Static) = local.ty.kind() + && let ty::Coroutine(def_id, _) = *local.ty.kind() + && tcx.coroutine_movability(def_id) == hir::Movability::Movable { - false - } else { true + } else { + false }; for (idx, move_data) in promoted_move_data { @@ -1306,7 +1307,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. match **aggregate_kind { - AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) => { + AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let BorrowCheckResult { used_mut_upvars, .. } = self.infcx.tcx.mir_borrowck(def_id); @@ -1612,7 +1613,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) @@ -1636,7 +1637,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } } - ty::Closure(_, _) | ty::Coroutine(_, _, _) | ty::Tuple(_) => (), + ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8a862953fba..80575e30a8d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -762,7 +762,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let (variant, args) = match base_ty { PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() { ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args), - ty::Coroutine(def_id, args, _) => { + ty::Coroutine(def_id, args) => { let mut variants = args.as_coroutine().state_tys(def_id, tcx); let Some(mut variant) = variants.nth(variant_index.into()) else { bug!( @@ -790,7 +790,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }), }; } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. return match args.as_coroutine().prefix_tys().get(field.index()) { @@ -1784,7 +1784,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }), } } - AggregateKind::Coroutine(_, args, _) => { + AggregateKind::Coroutine(_, args) => { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. @@ -2392,7 +2392,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { AggregateKind::Array(_) => None, AggregateKind::Tuple => None, AggregateKind::Closure(_, _) => None, - AggregateKind::Coroutine(_, _, _) => None, + AggregateKind::Coroutine(_, _) => None, }, } } @@ -2620,7 +2620,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args, _) => { + AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => { (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location)) } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 2b83c787139..a02304a2f8b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -14,7 +14,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; @@ -94,7 +93,7 @@ pub enum DefiningTy<'tcx> { /// The MIR is a coroutine. The signature is that coroutines take /// no parameters and return the result of /// `ClosureArgs::coroutine_return_ty`. - Coroutine(DefId, GenericArgsRef<'tcx>, hir::Movability), + Coroutine(DefId, GenericArgsRef<'tcx>), /// The MIR is a fn item with the given `DefId` and args. The signature /// of the function can be bound then with the `fn_sig` query. @@ -118,7 +117,7 @@ impl<'tcx> DefiningTy<'tcx> { pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> { match self { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), - DefiningTy::Coroutine(_, args, _) => args.as_coroutine().upvar_tys(), + DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { ty::List::empty() } @@ -354,7 +353,7 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(format!("late-bound region is {:?}", self.to_region_vid(r))); }); } - DefiningTy::Coroutine(def_id, args, _) => { + DefiningTy::Coroutine(def_id, args) => { let v = with_no_trimmed_paths!( args[tcx.generics_of(def_id).parent_count..] .iter() @@ -527,7 +526,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { debug!("build: local regions = {}..{}", first_local_index, num_universals); let yield_ty = match defining_ty { - DefiningTy::Coroutine(_, args, _) => Some(args.as_coroutine().yield_ty()), + DefiningTy::Coroutine(_, args) => Some(args.as_coroutine().yield_ty()), _ => None, }; @@ -562,9 +561,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match *defining_ty.kind() { ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args), - ty::Coroutine(def_id, args, movability) => { - DefiningTy::Coroutine(def_id, args, movability) - } + ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args), ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args), _ => span_bug!( tcx.def_span(self.mir_def), @@ -620,7 +617,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); let fr_args = match defining_ty { DefiningTy::Closure(_, args) - | DefiningTy::Coroutine(_, args, _) + | DefiningTy::Coroutine(_, args) | DefiningTy::InlineConst(_, args) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureArgs are @@ -685,11 +682,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ) } - DefiningTy::Coroutine(def_id, args, movability) => { + DefiningTy::Coroutine(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); let resume_ty = args.as_coroutine().resume_ty(); let output = args.as_coroutine().return_ty(); - let coroutine_ty = Ty::new_coroutine(tcx, def_id, args, movability); + let coroutine_ty = Ty::new_coroutine(tcx, def_id, args); let inputs_and_output = self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]); ty::Binder::dummy(inputs_and_output) diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 838c73fa213..f016e6950d4 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -974,8 +974,8 @@ pub(crate) fn assert_assignable<'tcx>( } } } - (&ty::Coroutine(def_id_a, args_a, mov_a), &ty::Coroutine(def_id_b, args_b, mov_b)) - if def_id_a == def_id_b && mov_a == mov_b => + (&ty::Coroutine(def_id_a, args_a), &ty::Coroutine(def_id_b, args_b)) + if def_id_a == def_id_b => { let mut types_a = args_a.types(); let mut types_b = args_b.types(); diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index b8a8c144dc9..42e61b3ccb5 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1296,7 +1296,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } // Atomic Operations - fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { + fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> (RValue<'gcc>, RValue<'gcc>) { let expected = self.current_func().new_local(None, cmp.get_type(), "expected"); self.llbb().add_assignment(None, expected, cmp); // NOTE: gcc doesn't support a failure memory model that is stronger than the success @@ -1310,20 +1310,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }; let success = self.compare_exchange(dst, expected, src, order, failure_order, weak); - let pair_type = self.cx.type_struct(&[src.get_type(), self.bool_type], false); - let result = self.current_func().new_local(None, pair_type, "atomic_cmpxchg_result"); - let align = Align::from_bits(64).expect("align"); // TODO(antoyo): use good align. + // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before + // expected so that we store expected after the call. + let success_var = self.current_func().new_local(None, self.bool_type, "success"); + self.llbb().add_assignment(None, success_var, success); - let value_type = result.to_rvalue().get_type(); - if let Some(struct_type) = value_type.is_struct() { - self.store(success, result.access_field(None, struct_type.get_field(1)).get_address(None), align); - // NOTE: since success contains the call to the intrinsic, it must be stored before - // expected so that we store expected after the call. - self.store(expected.to_rvalue(), result.access_field(None, struct_type.get_field(0)).get_address(None), align); - } - // TODO(antoyo): handle when value is not a struct. - - result.to_rvalue() + (expected.to_rvalue(), success_var.to_rvalue()) } fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 479a814788a..e5c0b2de4ca 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -98,7 +98,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8f60175a603..4e5fe290bb1 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1072,7 +1072,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { order: rustc_codegen_ssa::common::AtomicOrdering, failure_order: rustc_codegen_ssa::common::AtomicOrdering, weak: bool, - ) -> &'ll Value { + ) -> (&'ll Value, &'ll Value) { let weak = if weak { llvm::True } else { llvm::False }; unsafe { let value = llvm::LLVMBuildAtomicCmpXchg( @@ -1085,7 +1085,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { llvm::False, // SingleThreaded ); llvm::LLVMSetWeak(value, weak); - value + let val = self.extract_value(value, 0); + let success = self.extract_value(value, 1); + (val, success) } } fn atomic_rmw( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 59c075a3d3e..76c9ac6614a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1066,7 +1066,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( closure_or_coroutine_di_node: &'ll DIType, ) -> SmallVec<&'ll DIType> { let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() { - ty::Coroutine(def_id, args, _) => (def_id, args.as_coroutine().prefix_tys()), + ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()), ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), _ => { bug!( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 4a2861af44c..4792b0798df 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -679,7 +679,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( }; let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() { - &ty::Coroutine(def_id, args, _) => (def_id, args.as_coroutine()), + &ty::Coroutine(def_id, args) => (def_id, args.as_coroutine()), _ => unreachable!(), }; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index eef8dbb33b4..7f671d1d061 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -336,7 +336,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( let variant_layout = coroutine_type_and_layout.for_variant(cx, variant_index); let coroutine_args = match coroutine_type_and_layout.ty.kind() { - ty::Coroutine(_, args, _) => args.as_coroutine(), + ty::Coroutine(_, args) => args.as_coroutine(), _ => unreachable!(), }; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index cba4e3811d5..3dbe820b8ff 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -135,7 +135,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let coroutine_type = unique_type_id.expect_ty(); - let &ty::Coroutine(coroutine_def_id, _, _) = coroutine_type.kind() else { + let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else { bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) }; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 624ce6d8813..57b46382c96 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -54,7 +54,7 @@ fn uncached_llvm_type<'a, 'tcx>( write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 533803ea7ff..8530bf9e2b3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cmp = bx.ptrtoint(cmp, bx.type_isize()); src = bx.ptrtoint(src, bx.type_isize()); } - let pair = bx.atomic_cmpxchg( + let (val, success) = bx.atomic_cmpxchg( dst, cmp, src, @@ -343,8 +343,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { parse_ordering(bx, failure), weak, ); - let val = bx.extract_value(pair, 0); - let success = bx.extract_value(pair, 1); let val = bx.from_immediate(val); let success = bx.from_immediate(success); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index aa411f002a0..1c5c78e6ca2 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -296,7 +296,7 @@ pub trait BuilderMethods<'a, 'tcx>: order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool, - ) -> Self::Value; + ) -> (Self::Value, Self::Value); fn atomic_rmw( &mut self, op: AtomicRmwBinOp, diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index d9f583c1d1f..bb8c17cf779 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -171,7 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Adt(adt, _) => { adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits) } - ty::Coroutine(def_id, args, _) => { + ty::Coroutine(def_id, args) => { let args = args.as_coroutine(); args.discriminants(def_id, *self.tcx).find(|(_, var)| var.val == discr_bits) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c29f23b913f..1e9e7d94596 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -85,7 +85,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 07500f74477..8b44b87647d 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -217,7 +217,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Now we know we are projecting to a field, so figure out which one. match layout.ty.kind() { // coroutines and closures. - ty::Closure(def_id, _) | ty::Coroutine(def_id, _, _) => { + ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { let mut name = None; // FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar // https://github.com/rust-lang/project-rfc-2229/issues/46 diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 68ded1d324f..b249ffb84b3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -694,7 +694,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; check_equal(self, location, f_ty); } - &ty::Coroutine(def_id, args, _) => { + &ty::Coroutine(def_id, args) => { let f_ty = if let Some(var) = parent_ty.variant_index { let gen_body = if def_id == self.body.source.def_id() { self.body diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index a82b65b19a8..976e42ad768 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -51,7 +51,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) - | ty::Coroutine(def_id, args, _) => self.print_def_path(def_id, args), + | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"), diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index ad068cdbc98..291ee5bbe26 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -25,7 +25,7 @@ impl Hash64 { pub const ZERO: Hash64 = Hash64 { inner: 0 }; #[inline] - pub(crate) fn new(n: u64) -> Self { + pub fn new(n: u64) -> Self { Self { inner: n } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0453.md b/compiler/rustc_error_codes/src/error_codes/E0453.md index 11789db8f36..86ca0d9eca9 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0453.md +++ b/compiler/rustc_error_codes/src/error_codes/E0453.md @@ -8,8 +8,8 @@ Example of erroneous code: #[allow(non_snake_case)] fn main() { - let MyNumber = 2; // error: allow(non_snake_case) overruled by outer - // forbid(non_snake_case) + // error: allow(non_snake_case) incompatible with previous forbid + let MyNumber = 2; } ``` diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs index 8bfb47af26f..9a6dee1e511 100644 --- a/compiler/rustc_hir/src/def_path_hash_map.rs +++ b/compiler/rustc_hir/src/def_path_hash_map.rs @@ -1,21 +1,22 @@ -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_span::def_id::{DefIndex, DefPathHash}; +use rustc_data_structures::stable_hasher::Hash64; +use rustc_span::def_id::DefIndex; #[derive(Clone, Default)] pub struct Config; impl odht::Config for Config { - type Key = DefPathHash; + // This hash-map is single-crate, so we only need to key by the local hash. + type Key = Hash64; type Value = DefIndex; - type EncodedKey = [u8; 16]; + type EncodedKey = [u8; 8]; type EncodedValue = [u8; 4]; type H = odht::UnHashFn; #[inline] - fn encode_key(k: &DefPathHash) -> [u8; 16] { - k.0.to_le_bytes() + fn encode_key(k: &Hash64) -> [u8; 8] { + k.as_u64().to_le_bytes() } #[inline] @@ -24,8 +25,8 @@ impl odht::Config for Config { } #[inline] - fn decode_key(k: &[u8; 16]) -> DefPathHash { - DefPathHash(Fingerprint::from_le_bytes(*k)) + fn decode_key(k: &[u8; 8]) -> Hash64 { + Hash64::new(u64::from_le_bytes(*k)) } #[inline] diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 2ab9a6ef32c..9fb1fc19bf4 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -20,27 +20,42 @@ use std::hash::Hash; /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` /// stores the `DefIndex` of its parent. /// There is one `DefPathTable` for each crate. -#[derive(Clone, Default, Debug)] +#[derive(Debug)] pub struct DefPathTable { + stable_crate_id: StableCrateId, index_to_key: IndexVec<DefIndex, DefKey>, - def_path_hashes: IndexVec<DefIndex, DefPathHash>, + // We do only store the local hash, as all the definitions are from the current crate. + def_path_hashes: IndexVec<DefIndex, Hash64>, def_path_hash_to_index: DefPathHashMap, } impl DefPathTable { + fn new(stable_crate_id: StableCrateId) -> DefPathTable { + DefPathTable { + stable_crate_id, + index_to_key: Default::default(), + def_path_hashes: Default::default(), + def_path_hash_to_index: Default::default(), + } + } + fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex { + // Assert that all DefPathHashes correctly contain the local crate's StableCrateId. + debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id()); + let local_hash = def_path_hash.local_hash(); + let index = { let index = DefIndex::from(self.index_to_key.len()); debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); self.index_to_key.push(key); index }; - self.def_path_hashes.push(def_path_hash); + self.def_path_hashes.push(local_hash); debug_assert!(self.def_path_hashes.len() == self.index_to_key.len()); // Check for hash collisions of DefPathHashes. These should be // exceedingly rare. - if let Some(existing) = self.def_path_hash_to_index.insert(&def_path_hash, &index) { + if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) { let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx)); let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx)); @@ -58,13 +73,6 @@ impl DefPathTable { ); } - // Assert that all DefPathHashes correctly contain the local crate's - // StableCrateId - #[cfg(debug_assertions)] - if let Some(root) = self.def_path_hashes.get(CRATE_DEF_INDEX) { - assert!(def_path_hash.stable_crate_id() == root.stable_crate_id()); - } - index } @@ -73,19 +81,19 @@ impl DefPathTable { self.index_to_key[index] } + #[instrument(level = "trace", skip(self), ret)] #[inline(always)] pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { let hash = self.def_path_hashes[index]; - debug!("def_path_hash({:?}) = {:?}", index, hash); - hash + DefPathHash::new(self.stable_crate_id, hash) } pub fn enumerated_keys_and_path_hashes( &self, - ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + ExactSizeIterator + '_ { + ) -> impl Iterator<Item = (DefIndex, &DefKey, DefPathHash)> + ExactSizeIterator + '_ { self.index_to_key .iter_enumerated() - .map(move |(index, key)| (index, key, &self.def_path_hashes[index])) + .map(move |(index, key)| (index, key, self.def_path_hash(index))) } } @@ -96,9 +104,6 @@ impl DefPathTable { pub struct Definitions { table: DefPathTable, next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>, - - /// The [StableCrateId] of the local crate. - stable_crate_id: StableCrateId, } /// A unique identifier that we can use to lookup a definition @@ -329,11 +334,11 @@ impl Definitions { let def_path_hash = key.compute_stable_hash(parent_hash); // Create the root definition. - let mut table = DefPathTable::default(); + let mut table = DefPathTable::new(stable_crate_id); let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) }; assert_eq!(root.local_def_index, CRATE_DEF_INDEX); - Definitions { table, next_disambiguator: Default::default(), stable_crate_id } + Definitions { table, next_disambiguator: Default::default() } } /// Adds a definition with a parent definition. @@ -375,10 +380,10 @@ impl Definitions { hash: DefPathHash, err: &mut dyn FnMut() -> !, ) -> LocalDefId { - debug_assert!(hash.stable_crate_id() == self.stable_crate_id); + debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id); self.table .def_path_hash_to_index - .get(&hash) + .get(&hash.local_hash()) .map(|local_def_index| LocalDefId { local_def_index }) .unwrap_or_else(|| err()) } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 984c2829c81..0ca0f7d2daf 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -160,12 +160,7 @@ pub(super) fn check_fn<'a, 'tcx>( )); let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap(); - Some(CoroutineTypes { - resume_ty, - yield_ty, - interior, - movability: coroutine_kind.movability(), - }) + Some(CoroutineTypes { resume_ty, yield_ty, interior }) } else { None }; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index c29ef375ce4..bf6fda20df8 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -105,8 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: self.tcx.def_span(expr_def_id), }); - if let Some(CoroutineTypes { resume_ty, yield_ty, interior, movability }) = coroutine_types - { + if let Some(CoroutineTypes { resume_ty, yield_ty, interior }) = coroutine_types { let coroutine_args = ty::CoroutineArgs::new( self.tcx, ty::CoroutineArgsParts { @@ -119,12 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ); - return Ty::new_coroutine( - self.tcx, - expr_def_id.to_def_id(), - coroutine_args.args, - movability, - ); + return Ty::new_coroutine(self.tcx, expr_def_id.to_def_id(), coroutine_args.args); } // Tuple up the arguments and insert the resulting function type into diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d9106439420..da9a2bde783 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -304,9 +304,6 @@ struct CoroutineTypes<'tcx> { /// Types that are captured (see `CoroutineInterior` for more). interior: Ty<'tcx>, - - /// Indicates if the coroutine is movable or static (immovable). - movability: hir::Movability, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6530d828b3b..47fdd64796e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3306,6 +3306,7 @@ fn print_disambiguation_help<'tcx>( span: Span, item: ty::AssocItem, ) -> Option<String> { + let trait_impl_type = trait_ref.self_ty().peel_refs(); let trait_ref = if item.fn_has_self_parameter { trait_ref.print_only_trait_name().to_string() } else { @@ -3318,27 +3319,34 @@ fn print_disambiguation_help<'tcx>( { let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id); let item_name = item.ident(tcx); - let rcvr_ref = tcx - .fn_sig(item.def_id) - .skip_binder() - .skip_binder() - .inputs() - .get(0) - .and_then(|ty| ty.ref_mutability()) - .map_or("", |mutbl| mutbl.ref_prefix_str()); - let args = format!( - "({}{})", - rcvr_ref, - std::iter::once(receiver) - .chain(args.iter()) - .map(|arg| tcx - .sess - .source_map() - .span_to_snippet(arg.span) - .unwrap_or_else(|_| { "_".to_owned() })) - .collect::<Vec<_>>() - .join(", "), + let first_input = + tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0); + let (first_arg_type, rcvr_ref) = ( + first_input.map(|first| first.peel_refs()), + first_input + .and_then(|ty| ty.ref_mutability()) + .map_or("", |mutbl| mutbl.ref_prefix_str()), ); + + // If the type of first arg of this assoc function is `Self` or current trait impl type or `arbitrary_self_types`, we need to take the receiver as args. Otherwise, we don't. + let args = if let Some(first_arg_type) = first_arg_type + && (first_arg_type == tcx.types.self_param + || first_arg_type == trait_impl_type + || item.fn_has_self_parameter) + { + Some(receiver) + } else { + None + } + .into_iter() + .chain(args) + .map(|arg| { + tcx.sess.source_map().span_to_snippet(arg.span).unwrap_or_else(|_| "_".to_owned()) + }) + .collect::<Vec<_>>() + .join(", "); + + let args = format!("({}{})", rcvr_ref, args); err.span_suggestion_verbose( span, format!( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index fc525a0fd4e..47b9d5f6503 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.node_ty(closure_hir_id); let (closure_def_id, args) = match *ty.kind() { ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)), - ty::Coroutine(def_id, args, _) => (def_id, UpvarArgs::Coroutine(args)), + ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args)), ty::Error(_) => { // #51714: skip analysis when we have already encountered type errors return; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 2656fd529cd..11b5b437eff 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -456,7 +456,7 @@ where args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 47038cfd468..fc3d8375873 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -103,7 +103,7 @@ fn compute_components<'tcx>( compute_components(tcx, tupled_ty, out, visited); } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { // Same as the closure case let tupled_ty = args.as_coroutine().tupled_upvars_ty(); compute_components(tcx, tupled_ty, out, visited); diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 4d8c691ea3d..27d37fd9369 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -1,6 +1,7 @@ use std::mem; use rustc_data_structures::sso::SsoHashMap; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::ty::error::TypeError; @@ -215,7 +216,9 @@ where let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); debug!(?self.ambient_variance, "new ambient variance"); - let r = self.relate(a, b)?; + // Recursive calls to `relate` can overflow the stack. For example a deeper version of + // `ui/associated-consts/issue-93775.rs`. + let r = ensure_sufficient_stack(|| self.relate(a, b))?; self.ambient_variance = old_ambient_variance; Ok(r) } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 40b70ba4e04..39c965e75d6 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1069,7 +1069,7 @@ impl<'a> EarlyContext<'a> { pub(crate) fn new( sess: &'a Session, features: &'a Features, - warn_about_weird_lints: bool, + lint_added_lints: bool, lint_store: &'a LintStore, registered_tools: &'a RegisteredTools, buffered: LintBuffer, @@ -1078,7 +1078,7 @@ impl<'a> EarlyContext<'a> { builder: LintLevelsBuilder::new( sess, features, - warn_about_weird_lints, + lint_added_lints, lint_store, registered_tools, ), diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 17c56f1ca58..c229728cb79 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -135,7 +135,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp unstable_to_stable_ids: FxHashMap::default(), empty: FxHashMap::default(), }, - warn_about_weird_lints: false, + lint_added_lints: false, store, registered_tools: tcx.registered_tools(()), }; @@ -164,7 +164,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe empty: FxHashMap::default(), attrs, }, - warn_about_weird_lints: false, + lint_added_lints: false, store, registered_tools: tcx.registered_tools(()), }; @@ -451,7 +451,7 @@ pub struct LintLevelsBuilder<'s, P> { sess: &'s Session, features: &'s Features, provider: P, - warn_about_weird_lints: bool, + lint_added_lints: bool, store: &'s LintStore, registered_tools: &'s RegisteredTools, } @@ -464,7 +464,7 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { pub(crate) fn new( sess: &'s Session, features: &'s Features, - warn_about_weird_lints: bool, + lint_added_lints: bool, store: &'s LintStore, registered_tools: &'s RegisteredTools, ) -> Self { @@ -472,7 +472,7 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { sess, features, provider: TopDown { sets: LintLevelSets::new(), cur: COMMAND_LINE }, - warn_about_weird_lints, + lint_added_lints, store, registered_tools, }; @@ -642,7 +642,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // // This means that this only errors if we're truly lowering the lint // level from forbid. - if level != Level::Forbid { + if self.lint_added_lints && level != Level::Forbid { if let Level::Forbid = old_level { // Backwards compatibility check: // @@ -968,7 +968,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - _ if !self.warn_about_weird_lints => {} + _ if !self.lint_added_lints => {} CheckLintNameResult::Renamed(ref replace) => { let suggestion = @@ -1029,7 +1029,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } } - if !is_crate_node { + if self.lint_added_lints && !is_crate_node { for (id, &(level, ref src)) in self.current_specs().iter() { if !id.lint.crate_level_only { continue; @@ -1054,33 +1054,33 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Checks if the lint is gated on a feature that is not enabled. /// /// Returns `true` if the lint's feature is enabled. - // FIXME only emit this once for each attribute, instead of repeating it 4 times for - // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`. #[track_caller] fn check_gated_lint(&self, lint_id: LintId, span: Span, lint_from_cli: bool) -> bool { if let Some(feature) = lint_id.lint.feature_gate { if !self.features.active(feature) { - let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); - struct_lint_level( - self.sess, - lint, - level, - src, - Some(span.into()), - fluent::lint_unknown_gated_lint, - |lint| { - lint.set_arg("name", lint_id.lint.name_lower()); - lint.note(fluent::lint_note); - rustc_session::parse::add_feature_diagnostics_for_issue( - lint, - &self.sess.parse_sess, - feature, - GateIssue::Language, - lint_from_cli, - ); - }, - ); + if self.lint_added_lints { + let lint = builtin::UNKNOWN_LINTS; + let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); + struct_lint_level( + self.sess, + lint, + level, + src, + Some(span.into()), + fluent::lint_unknown_gated_lint, + |lint| { + lint.set_arg("name", lint_id.lint.name_lower()); + lint.note(fluent::lint_note); + rustc_session::parse::add_feature_diagnostics_for_issue( + lint, + &self.sess.parse_sess, + feature, + GateIssue::Language, + lint_from_cli, + ); + }, + ); + } return false; } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ae4a0e15fab..2de29db9e5c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -508,21 +508,19 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span { let start = decoder.position(); - let mode = SpanEncodingMode::decode(decoder); - let data = match mode { - SpanEncodingMode::Direct => SpanData::decode(decoder), - SpanEncodingMode::RelativeOffset(offset) => { - decoder.with_position(start - offset, |decoder| { - let mode = SpanEncodingMode::decode(decoder); - debug_assert!(matches!(mode, SpanEncodingMode::Direct)); - SpanData::decode(decoder) - }) - } - SpanEncodingMode::AbsoluteOffset(addr) => decoder.with_position(addr, |decoder| { - let mode = SpanEncodingMode::decode(decoder); - debug_assert!(matches!(mode, SpanEncodingMode::Direct)); - SpanData::decode(decoder) - }), + let tag = SpanTag(decoder.peek_byte()); + let data = if tag.kind() == SpanKind::Indirect { + // Skip past the tag we just peek'd. + decoder.read_u8(); + let offset_or_position = decoder.read_usize(); + let position = if tag.is_relative_offset() { + start - offset_or_position + } else { + offset_or_position + }; + decoder.with_position(position, SpanData::decode) + } else { + SpanData::decode(decoder) }; Span::new(data.lo, data.hi, data.ctxt, data.parent) } @@ -530,17 +528,17 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData { - let ctxt = SyntaxContext::decode(decoder); - let tag = u8::decode(decoder); + let tag = SpanTag::decode(decoder); + let ctxt = tag.context().unwrap_or_else(|| SyntaxContext::decode(decoder)); - if tag == TAG_PARTIAL_SPAN { + if tag.kind() == SpanKind::Partial { return DUMMY_SP.with_ctxt(ctxt).data(); } - debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); + debug_assert!(tag.kind() == SpanKind::Local || tag.kind() == SpanKind::Foreign); let lo = BytePos::decode(decoder); - let len = BytePos::decode(decoder); + let len = tag.length().unwrap_or_else(|| BytePos::decode(decoder)); let hi = lo + len; let Some(sess) = decoder.sess else { @@ -581,7 +579,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData { // treat the 'local' and 'foreign' cases almost identically during deserialization: // we can call `imported_source_file` for the proper crate, and binary search // through the returned slice using our span. - let source_file = if tag == TAG_VALID_SPAN_LOCAL { + let source_file = if tag.kind() == SpanKind::Local { decoder.cdata().imported_source_file(metadata_index, sess) } else { // When we encode a proc-macro crate, all `Span`s should be encoded diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 4f280bb9d80..9950bc1c31f 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -19,7 +19,9 @@ impl DefPathHashMapRef<'_> { #[inline] pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { match *self { - DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(def_path_hash).unwrap(), + DefPathHashMapRef::OwnedFromMetadata(ref map) => { + map.get(&def_path_hash.local_hash()).unwrap() + } DefPathHashMapRef::BorrowedFromTcx(_) => { panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization") } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f322588e365..aca7a66596e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -177,15 +177,17 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { // previously saved offset must be smaller than the current position. let offset = s.opaque.position() - last_location; if offset < last_location { - SpanEncodingMode::RelativeOffset(offset).encode(s) + SpanTag::indirect(true).encode(s); + offset.encode(s); } else { - SpanEncodingMode::AbsoluteOffset(last_location).encode(s) + SpanTag::indirect(false).encode(s); + last_location.encode(s); } } Entry::Vacant(v) => { let position = s.opaque.position(); v.insert(position); - SpanEncodingMode::Direct.encode(s); + // Data is encoded with a SpanTag prefix (see below). self.data().encode(s); } } @@ -225,14 +227,15 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { // IMPORTANT: If this is ever changed, be sure to update // `rustc_span::hygiene::raw_encode_expn_id` to handle // encoding `ExpnData` for proc-macro crates. - if s.is_proc_macro { - SyntaxContext::root().encode(s); - } else { - self.ctxt.encode(s); - } + let ctxt = if s.is_proc_macro { SyntaxContext::root() } else { self.ctxt }; if self.is_dummy() { - return TAG_PARTIAL_SPAN.encode(s); + let tag = SpanTag::new(SpanKind::Partial, ctxt, 0); + tag.encode(s); + if tag.context().is_none() { + ctxt.encode(s); + } + return; } // The Span infrastructure should make sure that this invariant holds: @@ -250,7 +253,12 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { if !source_file.contains(self.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_PARTIAL_SPAN.encode(s); + let tag = SpanTag::new(SpanKind::Partial, ctxt, 0); + tag.encode(s); + if tag.context().is_none() { + ctxt.encode(s); + } + return; } // There are two possible cases here: @@ -269,7 +277,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { // if we're a proc-macro crate. // This allows us to avoid loading the dependencies of proc-macro crates: all of // the information we need to decode `Span`s is stored in the proc-macro crate. - let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { + let (kind, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { // To simplify deserialization, we 'rebase' this span onto the crate it originally came // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' // values are relative to the source map information for the 'foreign' crate whose @@ -287,7 +295,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { } }; - (TAG_VALID_SPAN_FOREIGN, metadata_index) + (SpanKind::Foreign, metadata_index) } else { // Record the fact that we need to encode the data for this `SourceFile` let source_files = @@ -296,7 +304,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { let metadata_index: u32 = metadata_index.try_into().expect("cannot export more than U32_MAX files"); - (TAG_VALID_SPAN_LOCAL, metadata_index) + (SpanKind::Local, metadata_index) }; // Encode the start position relative to the file start, so we profit more from the @@ -307,14 +315,20 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData { // from the variable-length integer encoding that we use. let len = self.hi - self.lo; + let tag = SpanTag::new(kind, ctxt, len.0 as usize); tag.encode(s); + if tag.context().is_none() { + ctxt.encode(s); + } lo.encode(s); - len.encode(s); + if tag.length().is_none() { + len.encode(s); + } // Encode the index of the `SourceFile` for the span, in order to make decoding faster. metadata_index.encode(s); - if tag == TAG_VALID_SPAN_FOREIGN { + if kind == SpanKind::Foreign { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` let cnum = s.source_file_cache.0.cnum; @@ -1444,7 +1458,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind == DefKind::Closure && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { - self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)); + self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)) } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { self.encode_info_for_adt(local_id); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index bafd3f0b84d..54ee50c2358 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -66,13 +66,6 @@ const METADATA_VERSION: u8 = 9; /// unsigned integer, and further followed by the rustc version string. pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; -#[derive(Encodable, Decodable)] -enum SpanEncodingMode { - RelativeOffset(usize), - AbsoluteOffset(usize), - Direct, -} - /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. /// @@ -488,10 +481,88 @@ bitflags::bitflags! { } } -// Tags used for encoding Spans: -const TAG_VALID_SPAN_LOCAL: u8 = 0; -const TAG_VALID_SPAN_FOREIGN: u8 = 1; -const TAG_PARTIAL_SPAN: u8 = 2; +/// A span tag byte encodes a bunch of data, so that we can cut out a few extra bytes from span +/// encodings (which are very common, for example, libcore has ~650,000 unique spans and over 1.1 +/// million references to prior-written spans). +/// +/// The byte format is split into several parts: +/// +/// [ a a a a a c d d ] +/// +/// `a` bits represent the span length. We have 5 bits, so we can store lengths up to 30 inline, with +/// an all-1s pattern representing that the length is stored separately. +/// +/// `c` represents whether the span context is zero (and then it is not stored as a separate varint) +/// for direct span encodings, and whether the offset is absolute or relative otherwise (zero for +/// absolute). +/// +/// d bits represent the kind of span we are storing (local, foreign, partial, indirect). +#[derive(Encodable, Decodable, Copy, Clone)] +struct SpanTag(u8); + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum SpanKind { + Local = 0b00, + Foreign = 0b01, + Partial = 0b10, + // Indicates the actual span contents are elsewhere. + // If this is the kind, then the span context bit represents whether it is a relative or + // absolute offset. + Indirect = 0b11, +} + +impl SpanTag { + fn new(kind: SpanKind, context: rustc_span::SyntaxContext, length: usize) -> SpanTag { + let mut data = 0u8; + data |= kind as u8; + if context.is_root() { + data |= 0b100; + } + let all_1s_len = (0xffu8 << 3) >> 3; + // strictly less than - all 1s pattern is a sentinel for storage being out of band. + if length < all_1s_len as usize { + data |= (length as u8) << 3; + } else { + data |= all_1s_len << 3; + } + + SpanTag(data) + } + + fn indirect(relative: bool) -> SpanTag { + let mut tag = SpanTag(SpanKind::Indirect as u8); + if relative { + tag.0 |= 0b100; + } + tag + } + + fn kind(self) -> SpanKind { + let masked = self.0 & 0b11; + match masked { + 0b00 => SpanKind::Local, + 0b01 => SpanKind::Foreign, + 0b10 => SpanKind::Partial, + 0b11 => SpanKind::Indirect, + _ => unreachable!(), + } + } + + fn is_relative_offset(self) -> bool { + debug_assert_eq!(self.kind(), SpanKind::Indirect); + self.0 & 0b100 != 0 + } + + fn context(self) -> Option<rustc_span::SyntaxContext> { + if self.0 & 0b100 != 0 { Some(rustc_span::SyntaxContext::root()) } else { None } + } + + fn length(self) -> Option<rustc_span::BytePos> { + let all_1s_len = (0xffu8 << 3) >> 3; + let len = self.0 >> 3; + if len != all_1s_len { Some(rustc_span::BytePos(u32::from(len))) } else { None } + } +} // Tags for encoding Symbol's const SYMBOL_STR: u8 = 0; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index b995f622388..8e7aaee065f 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1049,7 +1049,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { struct_fmt.finish() }), - AggregateKind::Coroutine(def_id, _, _) => ty::tls::with(|tcx| { + AggregateKind::Coroutine(def_id, _) => ty::tls::with(|tcx| { let name = format!("{{coroutine@{:?}}}", tcx.def_span(def_id)); let mut struct_fmt = fmt.debug_struct(&name); @@ -1304,11 +1304,11 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { self.push(&format!("+ args: {args:#?}")); } - AggregateKind::Coroutine(def_id, args, movability) => { + AggregateKind::Coroutine(def_id, args) => { self.push("coroutine"); self.push(&format!("+ def_id: {def_id:?}")); self.push(&format!("+ args: {args:#?}")); - self.push(&format!("+ movability: {movability:?}")); + self.push(&format!("+ kind: {:?}", self.tcx.coroutine_kind(def_id))); } AggregateKind::Adt(_, _, _, Some(user_ty), _) => { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 8cf9e55f0b6..462076d750f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -14,7 +14,6 @@ use crate::ty::{Region, UserTypeAnnotationIndex}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; use rustc_hir::{self, CoroutineKind}; use rustc_index::IndexVec; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -1344,7 +1343,7 @@ pub enum AggregateKind<'tcx> { Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), Closure(DefId, GenericArgsRef<'tcx>), - Coroutine(DefId, GenericArgsRef<'tcx>, hir::Movability), + Coroutine(DefId, GenericArgsRef<'tcx>), } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index f9b2a6ee8aa..234ccee5546 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -201,9 +201,7 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), - AggregateKind::Coroutine(did, args, movability) => { - Ty::new_coroutine(tcx, did, args, movability) - } + AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args), }, Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 9059936f495..132ecf91af1 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -736,7 +736,6 @@ macro_rules! make_mir_visitor { AggregateKind::Coroutine( _, coroutine_args, - _movability, ) => { self.visit_args(coroutine_args, location); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 17691de630f..6807eacb7f1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -847,6 +847,12 @@ impl<'tcx> TyCtxt<'tcx> { self.coroutine_kind(def_id).is_some() } + /// Returns the movability of the coroutine of `def_id`, or panics + /// if given a `def_id` that is not a coroutine. + pub fn coroutine_movability(self, def_id: DefId) -> hir::Movability { + self.coroutine_kind(def_id).expect("expected a coroutine").movability() + } + /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct. pub fn coroutine_is_async(self, def_id: DefId) -> bool { matches!( diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 38a9cabca97..6ed68f90eb3 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -128,7 +128,7 @@ pub fn simplify_type<'tcx>( }, ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), - ty::Coroutine(def_id, _, _) => Some(SimplifiedType::Coroutine(def_id)), + ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id)), ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)), ty::Never => Some(SimplifiedType::Never), ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index f9a2385b100..0c1d1091414 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -96,7 +96,7 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { let args = args.as_coroutine(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 1c7a7545e2b..1b6d59ab257 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -689,13 +689,13 @@ fn polymorphize<'tcx>( Ty::new_closure(self.tcx, def_id, polymorphized_args) } } - ty::Coroutine(def_id, args, movability) => { + ty::Coroutine(def_id, args) => { let polymorphized_args = polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args); if args == polymorphized_args { ty } else { - Ty::new_coroutine(self.tcx, def_id, polymorphized_args, movability) + Ty::new_coroutine(self.tcx, def_id, polymorphized_args) } } _ => ty.super_fold_with(self), diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8a02914b435..5cc0ce87c9b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -906,7 +906,7 @@ where i, ), - ty::Coroutine(def_id, args, _) => match this.variants { + ty::Coroutine(def_id, args) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() .state_tys(def_id, tcx) diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 71fe7d15a6c..fc4d4c9a3d2 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -153,9 +153,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { Ty::new_closure(self.tcx, def_id, args) } - ty::Coroutine(def_id, args, movability) => { + ty::Coroutine(def_id, args) => { let args = self.fold_closure_args(def_id, args); - Ty::new_coroutine(self.tcx, def_id, args, movability) + Ty::new_coroutine(self.tcx, def_id, args) } ty::CoroutineWitness(def_id, args) => { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 5e09154789a..f32b7b0852a 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -259,7 +259,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::FnDef(def_id, _) | ty::Closure(def_id, _) - | ty::Coroutine(def_id, _, _) + | ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f7900d883ad..99384e34222 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -783,14 +783,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } ty::Str => p!("str"), - ty::Coroutine(did, args, movability) => { + ty::Coroutine(did, args) => { p!(write("{{")); let coroutine_kind = self.tcx().coroutine_kind(did).unwrap(); let should_print_movability = self.should_print_verbose() || matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)); if should_print_movability { - match movability { + match coroutine_kind.movability() { hir::Movability::Movable => {} hir::Movability::Static => p!("static "), } @@ -1055,7 +1055,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && assoc.trait_container(tcx) == tcx.lang_items().coroutine_trait() && assoc.name == rustc_span::sym::Return { - if let ty::Coroutine(_, args, _) = args.type_at(0).kind() { + if let ty::Coroutine(_, args) = args.type_at(0).kind() { let return_ty = args.as_coroutine().return_ty(); if !return_ty.is_ty_var() { return_ty.into() diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9d92f81db0b..8543bd0bbdd 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -455,14 +455,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } - (&ty::Coroutine(a_id, a_args, movability), &ty::Coroutine(b_id, b_args, _)) - if a_id == b_id => - { + (&ty::Coroutine(a_id, a_args), &ty::Coroutine(b_id, b_args)) if a_id == b_id => { // All Coroutine types with the same id represent // the (anonymous) type of the same coroutine expression. So // all of their regions should be equated. let args = relate_args_invariantly(relation, a_args, b_args)?; - Ok(Ty::new_coroutine(tcx, a_id, args, movability)) + Ok(Ty::new_coroutine(tcx, a_id, args)) } (&ty::CoroutineWitness(a_id, a_args), &ty::CoroutineWitness(b_id, b_args)) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 1c75d73e552..7c869adbd83 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -578,9 +578,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> { ty::Ref(r, ty, mutbl) => { ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } - ty::Coroutine(did, args, movability) => { - ty::Coroutine(did, args.try_fold_with(folder)?, movability) - } + ty::Coroutine(did, args) => ty::Coroutine(did, args.try_fold_with(folder)?), ty::CoroutineWitness(did, args) => { ty::CoroutineWitness(did, args.try_fold_with(folder)?) } @@ -630,7 +628,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> { r.visit_with(visitor)?; ty.visit_with(visitor) } - ty::Coroutine(_did, ref args, _) => args.visit_with(visitor), + ty::Coroutine(_did, ref args) => args.visit_with(visitor), ty::CoroutineWitness(_did, ref args) => args.visit_with(visitor), ty::Closure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5b9dff8e3f2..38bf39bff90 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -241,38 +241,36 @@ pub struct ClosureArgs<'tcx> { } /// Struct returned by `split()`. -pub struct ClosureArgsParts<'tcx, T> { +pub struct ClosureArgsParts<'tcx> { pub parent_args: &'tcx [GenericArg<'tcx>], - pub closure_kind_ty: T, - pub closure_sig_as_fn_ptr_ty: T, - pub tupled_upvars_ty: T, + pub closure_kind_ty: Ty<'tcx>, + pub closure_sig_as_fn_ptr_ty: Ty<'tcx>, + pub tupled_upvars_ty: Ty<'tcx>, } impl<'tcx> ClosureArgs<'tcx> { /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args` /// for the closure parent, alongside additional closure-specific components. - pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx, Ty<'tcx>>) -> ClosureArgs<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx>) -> ClosureArgs<'tcx> { ClosureArgs { - args: tcx.mk_args_from_iter( - parts.parent_args.iter().copied().chain( - [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty] - .iter() - .map(|&ty| ty.into()), - ), - ), + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.closure_kind_ty.into(), + parts.closure_sig_as_fn_ptr_ty.into(), + parts.tupled_upvars_ty.into(), + ])), } } /// Divides the closure args into their respective components. /// The ordering assumed here must match that used by `ClosureArgs::new` above. - fn split(self) -> ClosureArgsParts<'tcx, GenericArg<'tcx>> { + fn split(self) -> ClosureArgsParts<'tcx> { match self.args[..] { [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { ClosureArgsParts { parent_args, - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, + closure_kind_ty: closure_kind_ty.expect_ty(), + closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), } } _ => bug!("closure args missing synthetics"), @@ -285,7 +283,7 @@ impl<'tcx> ClosureArgs<'tcx> { /// Used primarily by `ty::print::pretty` to be able to handle closure /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.args.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) + self.args.len() >= 3 && matches!(self.split().tupled_upvars_ty.kind(), Tuple(_)) } /// Returns the substitutions of the closure's parent. @@ -309,14 +307,14 @@ impl<'tcx> ClosureArgs<'tcx> { /// Returns the tuple type representing the upvars for this closure. #[inline] pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty.expect_ty() + self.split().tupled_upvars_ty } /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during /// inference, use `infcx.closure_kind(args)`. pub fn kind_ty(self) -> Ty<'tcx> { - self.split().closure_kind_ty.expect_ty() + self.split().closure_kind_ty } /// Returns the `fn` pointer type representing the closure signature for this @@ -325,7 +323,7 @@ impl<'tcx> ClosureArgs<'tcx> { // type is known at the time of the creation of `ClosureArgs`, // see `rustc_hir_analysis::check::closure`. pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { - self.split().closure_sig_as_fn_ptr_ty.expect_ty() + self.split().closure_sig_as_fn_ptr_ty } /// Returns the closure kind for this closure; only usable outside @@ -357,51 +355,42 @@ pub struct CoroutineArgs<'tcx> { pub args: GenericArgsRef<'tcx>, } -pub struct CoroutineArgsParts<'tcx, T> { +pub struct CoroutineArgsParts<'tcx> { pub parent_args: &'tcx [GenericArg<'tcx>], - pub resume_ty: T, - pub yield_ty: T, - pub return_ty: T, - pub witness: T, - pub tupled_upvars_ty: T, + pub resume_ty: Ty<'tcx>, + pub yield_ty: Ty<'tcx>, + pub return_ty: Ty<'tcx>, + pub witness: Ty<'tcx>, + pub tupled_upvars_ty: Ty<'tcx>, } impl<'tcx> CoroutineArgs<'tcx> { /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args` /// for the coroutine parent, alongside additional coroutine-specific components. - pub fn new( - tcx: TyCtxt<'tcx>, - parts: CoroutineArgsParts<'tcx, Ty<'tcx>>, - ) -> CoroutineArgs<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> { CoroutineArgs { - args: tcx.mk_args_from_iter( - parts.parent_args.iter().copied().chain( - [ - parts.resume_ty, - parts.yield_ty, - parts.return_ty, - parts.witness, - parts.tupled_upvars_ty, - ] - .iter() - .map(|&ty| ty.into()), - ), - ), + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.resume_ty.into(), + parts.yield_ty.into(), + parts.return_ty.into(), + parts.witness.into(), + parts.tupled_upvars_ty.into(), + ])), } } /// Divides the coroutine args into their respective components. /// The ordering assumed here must match that used by `CoroutineArgs::new` above. - fn split(self) -> CoroutineArgsParts<'tcx, GenericArg<'tcx>> { + fn split(self) -> CoroutineArgsParts<'tcx> { match self.args[..] { [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { CoroutineArgsParts { parent_args, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + witness: witness.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), } } _ => bug!("coroutine args missing synthetics"), @@ -414,7 +403,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// Used primarily by `ty::print::pretty` to be able to handle coroutine /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) + self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.kind(), Tuple(_)) } /// Returns the substitutions of the coroutine's parent. @@ -428,7 +417,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The state transformation MIR pass may only produce layouts which mention types /// in this tuple. Upvars are not counted here. pub fn witness(self) -> Ty<'tcx> { - self.split().witness.expect_ty() + self.split().witness } /// Returns an iterator over the list of types of captured paths by the coroutine. @@ -447,31 +436,32 @@ impl<'tcx> CoroutineArgs<'tcx> { /// Returns the tuple type representing the upvars for this coroutine. #[inline] pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty.expect_ty() + self.split().tupled_upvars_ty } /// Returns the type representing the resume type of the coroutine. pub fn resume_ty(self) -> Ty<'tcx> { - self.split().resume_ty.expect_ty() + self.split().resume_ty } /// Returns the type representing the yield type of the coroutine. pub fn yield_ty(self) -> Ty<'tcx> { - self.split().yield_ty.expect_ty() + self.split().yield_ty } /// Returns the type representing the return type of the coroutine. pub fn return_ty(self) -> Ty<'tcx> { - self.split().return_ty.expect_ty() + self.split().return_ty } /// Returns the "coroutine signature", which consists of its resume, yield /// and return types. pub fn sig(self) -> GenSig<'tcx> { + let parts = self.split(); ty::GenSig { - resume_ty: self.resume_ty(), - yield_ty: self.yield_ty(), - return_ty: self.return_ty(), + resume_ty: parts.resume_ty, + yield_ty: parts.yield_ty, + return_ty: parts.return_ty, } } } @@ -2168,14 +2158,13 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, def_id: DefId, coroutine_args: GenericArgsRef<'tcx>, - movability: hir::Movability, ) -> Ty<'tcx> { debug_assert_eq!( coroutine_args.len(), tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, "coroutine constructed with incorrect number of substitutions" ); - Ty::new(tcx, Coroutine(def_id, coroutine_args, movability)) + Ty::new(tcx, Coroutine(def_id, coroutine_args)) } #[inline] @@ -2656,7 +2645,7 @@ impl<'tcx> Ty<'tcx> { pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> { match self.kind() { TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Coroutine(def_id, args, _) => { + TyKind::Coroutine(def_id, args) => { Some(args.as_coroutine().variant_range(*def_id, tcx)) } _ => None, @@ -2677,7 +2666,7 @@ impl<'tcx> Ty<'tcx> { TyKind::Adt(adt, _) if adt.is_enum() => { Some(adt.discriminant_for_variant(tcx, variant_index)) } - TyKind::Coroutine(def_id, args, _) => { + TyKind::Coroutine(def_id, args) => { Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index)) } _ => None, @@ -2688,7 +2677,7 @@ impl<'tcx> Ty<'tcx> { pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx), - ty::Coroutine(_, args, _) => args.as_coroutine().discr_ty(tcx), + ty::Coroutine(_, args) => args.as_coroutine().discr_ty(tcx), ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx.associated_item_def_ids( @@ -2983,7 +2972,7 @@ impl<'tcx> Ty<'tcx> { | FnPtr(_) | Dynamic(_, _, _) | Closure(_, _) - | Coroutine(_, _, _) + | Coroutine(_, _) | CoroutineWitness(..) | Never | Tuple(_) => true, diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 20bdbcb5b7b..9050716db9d 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -189,7 +189,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } ty::Adt(_, args) | ty::Closure(_, args) - | ty::Coroutine(_, args, _) + | ty::Coroutine(_, args) | ty::CoroutineWitness(_, args) | ty::FnDef(_, args) => { stack.extend(args.iter().rev()); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 04dcc6854c7..f799be165ec 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -387,8 +387,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { closure_id, args, ref upvars, - movability, ref fake_reads, + movability: _, }) => { // Convert the closure fake reads, if any, from `ExprRef` to mir `Place` // and push the fake reads. @@ -474,10 +474,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let result = match args { UpvarArgs::Coroutine(args) => { - // We implicitly set the discriminant to 0. See - // librustc_mir/transform/deaggregator.rs for details. - let movability = movability.unwrap(); - Box::new(AggregateKind::Coroutine(closure_id.to_def_id(), args, movability)) + Box::new(AggregateKind::Coroutine(closure_id.to_def_id(), args)) } UpvarArgs::Closure(args) => { Box::new(AggregateKind::Closure(closure_id.to_def_id(), args)) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index a6336ec63b2..e0199fb8767 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -646,7 +646,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - } DefKind::Closure if coroutine_kind.is_some() => { let coroutine_ty = tcx.type_of(def_id).instantiate_identity(); - let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { + let ty::Coroutine(_, args) = coroutine_ty.kind() else { bug!("expected type of coroutine-like closure to be a coroutine") }; let args = args.as_coroutine(); @@ -813,7 +813,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let upvar_args = match closure_ty.kind() { ty::Closure(_, args) => ty::UpvarArgs::Closure(args), - ty::Coroutine(_, args, _) => ty::UpvarArgs::Coroutine(args), + ty::Coroutine(_, args) => ty::UpvarArgs::Coroutine(args), _ => return, }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 01f4678fa09..8ec70c58c46 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -552,8 +552,8 @@ impl<'tcx> Cx<'tcx> { let closure_ty = self.typeck_results().expr_ty(expr); let (def_id, args, movability) = match *closure_ty.kind() { ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None), - ty::Coroutine(def_id, args, movability) => { - (def_id, UpvarArgs::Coroutine(args), Some(movability)) + ty::Coroutine(def_id, args) => { + (def_id, UpvarArgs::Coroutine(args), Some(tcx.coroutine_movability(def_id))) } _ => { span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 958fa0d17cd..c9930565186 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -862,7 +862,7 @@ where // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the coroutine transformation runs. // See librustc_body/transform/coroutine.rs for more details. - ty::Coroutine(_, args, _) => self.open_drop_for_tuple(args.as_coroutine().upvar_tys()), + ty::Coroutine(_, args) => self.open_drop_for_tuple(args.as_coroutine().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index ccf3dc7941f..cae35765308 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -155,7 +155,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) @@ -177,7 +177,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { union_path.get_or_insert(base); } } - ty::Closure(_, _) | ty::Coroutine(_, _, _) | ty::Tuple(_) => (), + ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 23726e49f4d..d94d96c1115 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -128,7 +128,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { ), } } - &AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _, _) => { + &AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.unsafety_check_result(def_id); diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index e66d5e0a9f9..c5824c30770 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -1,29 +1,22 @@ //! Propagates constants for early reporting of statically known //! assertion failures -use either::Right; -use rustc_const_eval::ReportErrorExt; +use rustc_const_eval::interpret::{ + self, compile_time_machine, AllocId, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, + InterpResult, OpTy, PlaceTy, Pointer, +}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; -use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::mir::visit::{ - MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, -}; +use rustc_index::IndexVec; +use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; -use rustc_middle::ty::{self, GenericArgs, Instance, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{def_id::DefId, Span}; -use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout}; +use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{self, ParamEnv, TyCtxt}; +use rustc_span::def_id::DefId; +use rustc_target::abi::Size; use rustc_target::spec::abi::Abi as CallAbi; -use crate::dataflow_const_prop::Patch; -use rustc_const_eval::interpret::{ - self, compile_time_machine, AllocId, ConstAllocation, FnArg, Frame, ImmTy, Immediate, InterpCx, - InterpResult, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, StackPopCleanup, -}; - /// The maximum number of bytes that we'll allocate space for a local or the return value. /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just /// Severely regress performance. @@ -56,62 +49,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{ throw_machine_stop!(Zst) }} -pub struct ConstProp; - -impl<'tcx> MirPass<'tcx> for ConstProp { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 - } - - #[instrument(skip(self, tcx), level = "debug")] - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // will be evaluated by miri and produce its errors there - if body.source.promoted.is_some() { - return; - } - - let def_id = body.source.def_id().expect_local(); - let def_kind = tcx.def_kind(def_id); - let is_fn_like = def_kind.is_fn_like(); - let is_assoc_const = def_kind == DefKind::AssocConst; - - // Only run const prop on functions, methods, closures and associated constants - if !is_fn_like && !is_assoc_const { - // skip anon_const/statics/consts because they'll be evaluated by miri anyway - trace!("ConstProp skipped for {:?}", def_id); - return; - } - - // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles - // computing their layout. - if tcx.is_coroutine(def_id.to_def_id()) { - trace!("ConstProp skipped for coroutine {:?}", def_id); - return; - } - - trace!("ConstProp starting for {:?}", def_id); - - // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold - // constants, instead of just checking for const-folding succeeding. - // That would require a uniform one-def no-mutation analysis - // and RPO (or recursing when needing the value of a local). - let mut optimization_finder = ConstPropagator::new(body, tcx); - - // Traverse the body in reverse post-order, to ensure that `FullConstProp` locals are - // assigned before being read. - for &bb in body.basic_blocks.reverse_postorder() { - let data = &body.basic_blocks[bb]; - optimization_finder.visit_basic_block_data(bb, data); - } - - let mut patch = optimization_finder.patch; - patch.visit_body_preserves_cfg(body); - - trace!("ConstProp done for {:?}", def_id); - } -} - -pub struct ConstPropMachine<'mir, 'tcx> { +pub(crate) struct ConstPropMachine<'mir, 'tcx> { /// The virtual call stack. stack: Vec<Frame<'mir, 'tcx>>, pub written_only_inside_own_block_locals: FxHashSet<Local>, @@ -267,297 +205,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } } -/// Finds optimization opportunities on the MIR. -struct ConstPropagator<'mir, 'tcx> { - ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - local_decls: &'mir IndexSlice<Local, LocalDecl<'tcx>>, - patch: Patch<'tcx>, -} - -impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> { - type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>; - - #[inline] - fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { - err - } -} - -impl HasDataLayout for ConstPropagator<'_, '_> { - #[inline] - fn data_layout(&self) -> &TargetDataLayout { - &self.tcx.data_layout - } -} - -impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> { - #[inline] - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } -} - -impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { - #[inline] - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env - } -} - -impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { - fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> { - let def_id = body.source.def_id(); - let args = &GenericArgs::identity_for_item(tcx, def_id); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - - let can_const_prop = CanConstProp::check(tcx, param_env, body); - let mut ecx = InterpCx::new( - tcx, - tcx.def_span(def_id), - param_env, - ConstPropMachine::new(can_const_prop), - ); - - let ret_layout = ecx - .layout_of(body.bound_return_ty().instantiate(tcx, args)) - .ok() - // Don't bother allocating memory for large values. - // I don't know how return types can seem to be unsized but this happens in the - // `type/type-unsatisfiable.rs` test. - .filter(|ret_layout| { - ret_layout.is_sized() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) - }) - .unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap()); - - let ret = ecx - .allocate(ret_layout, MemoryKind::Stack) - .expect("couldn't perform small allocation") - .into(); - - ecx.push_stack_frame( - Instance::new(def_id, args), - body, - &ret, - StackPopCleanup::Root { cleanup: false }, - ) - .expect("failed to push initial stack frame"); - - for local in body.local_decls.indices() { - // Mark everything initially live. - // This is somewhat dicey since some of them might be unsized and it is incoherent to - // mark those as live... We rely on `local_to_place`/`local_to_op` in the interpreter - // stopping us before those unsized immediates can cause issues deeper in the - // interpreter. - ecx.frame_mut().locals[local].make_live_uninit(); - } - - let patch = Patch::new(tcx); - ConstPropagator { ecx, tcx, param_env, local_decls: &body.local_decls, patch } - } - - fn get_const(&self, place: Place<'tcx>) -> Option<OpTy<'tcx>> { - let op = match self.ecx.eval_place_to_op(place, None) { - Ok(op) => { - if op - .as_mplace_or_imm() - .right() - .is_some_and(|imm| matches!(*imm, Immediate::Uninit)) - { - // Make sure nobody accidentally uses this value. - return None; - } - op - } - Err(e) => { - trace!("get_const failed: {:?}", e.into_kind().debug()); - return None; - } - }; - - // Try to read the local as an immediate so that if it is representable as a scalar, we can - // handle it as such, but otherwise, just return the value as is. - Some(match self.ecx.read_immediate_raw(&op) { - Ok(Right(imm)) => imm.into(), - _ => op, - }) - } - - /// Remove `local` from the pool of `Locals`. Allows writing to them, - /// but not reading from them anymore. - fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) { - ecx.frame_mut().locals[local].make_live_uninit(); - ecx.machine.written_only_inside_own_block_locals.remove(&local); - } - - fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Option<()> { - // Perform any special handling for specific Rvalue types. - // Generally, checks here fall into one of two categories: - // 1. Additional checking to provide useful lints to the user - // - In this case, we will do some validation and then fall through to the - // end of the function which evals the assignment. - // 2. Working around bugs in other parts of the compiler - // - In this case, we'll return `None` from this function to stop evaluation. - match rvalue { - // Do not try creating references (#67862) - Rvalue::AddressOf(_, place) | Rvalue::Ref(_, _, place) => { - trace!("skipping AddressOf | Ref for {:?}", place); - - // This may be creating mutable references or immutable references to cells. - // If that happens, the pointed to value could be mutated via that reference. - // Since we aren't tracking references, the const propagator loses track of what - // value the local has right now. - // Thus, all locals that have their reference taken - // must not take part in propagation. - Self::remove_const(&mut self.ecx, place.local); - - return None; - } - Rvalue::ThreadLocalRef(def_id) => { - trace!("skipping ThreadLocalRef({:?})", def_id); - - return None; - } - // There's no other checking to do at this time. - Rvalue::Aggregate(..) - | Rvalue::Use(..) - | Rvalue::CopyForDeref(..) - | Rvalue::Repeat(..) - | Rvalue::Len(..) - | Rvalue::Cast(..) - | Rvalue::ShallowInitBox(..) - | Rvalue::Discriminant(..) - | Rvalue::NullaryOp(..) - | Rvalue::UnaryOp(..) - | Rvalue::BinaryOp(..) - | Rvalue::CheckedBinaryOp(..) => {} - } - - // FIXME we need to revisit this for #67176 - if rvalue.has_param() { - trace!("skipping, has param"); - return None; - } - if !rvalue - .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(*self.ecx.tcx, self.param_env) - { - // the interpreter doesn't support unsized locals (only unsized arguments), - // but rustc does (in a kinda broken way), so we have to skip them here - return None; - } - - Some(()) - } - - // Attempt to use algebraic identities to eliminate constant expressions - fn eval_rvalue_with_identities( - &mut self, - rvalue: &Rvalue<'tcx>, - place: Place<'tcx>, - ) -> Option<()> { - match rvalue { - Rvalue::BinaryOp(op, box (left, right)) - | Rvalue::CheckedBinaryOp(op, box (left, right)) => { - let l = self.ecx.eval_operand(left, None).and_then(|x| self.ecx.read_immediate(&x)); - let r = - self.ecx.eval_operand(right, None).and_then(|x| self.ecx.read_immediate(&x)); - - let const_arg = match (l, r) { - (Ok(x), Err(_)) | (Err(_), Ok(x)) => x, // exactly one side is known - (Err(_), Err(_)) => return None, // neither side is known - (Ok(_), Ok(_)) => return self.ecx.eval_rvalue_into_place(rvalue, place).ok(), // both sides are known - }; - - if !matches!(const_arg.layout.abi, abi::Abi::Scalar(..)) { - // We cannot handle Scalar Pair stuff. - // No point in calling `eval_rvalue_into_place`, since only one side is known - return None; - } - - let arg_value = const_arg.to_scalar().to_bits(const_arg.layout.size).ok()?; - let dest = self.ecx.eval_place(place).ok()?; - - match op { - BinOp::BitAnd if arg_value == 0 => { - self.ecx.write_immediate(*const_arg, &dest).ok() - } - BinOp::BitOr - if arg_value == const_arg.layout.size.truncate(u128::MAX) - || (const_arg.layout.ty.is_bool() && arg_value == 1) => - { - self.ecx.write_immediate(*const_arg, &dest).ok() - } - BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => { - if let Rvalue::CheckedBinaryOp(_, _) = rvalue { - let val = Immediate::ScalarPair( - const_arg.to_scalar(), - Scalar::from_bool(false), - ); - self.ecx.write_immediate(val, &dest).ok() - } else { - self.ecx.write_immediate(*const_arg, &dest).ok() - } - } - _ => None, - } - } - _ => self.ecx.eval_rvalue_into_place(rvalue, place).ok(), - } - } - - fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<Const<'tcx>> { - // This will return None if the above `const_prop` invocation only "wrote" a - // type whose creation requires no write. E.g. a coroutine whose initial state - // consists solely of uninitialized memory (so it doesn't capture any locals). - let value = self.get_const(place)?; - if !self.tcx.consider_optimizing(|| format!("ConstantPropagation - {value:?}")) { - return None; - } - trace!("replacing {:?} with {:?}", place, value); - - // FIXME: figure out what to do when read_immediate_raw fails - let imm = self.ecx.read_immediate_raw(&value).ok()?; - - let Right(imm) = imm else { return None }; - match *imm { - Immediate::Scalar(scalar) if scalar.try_to_int().is_ok() => { - Some(Const::from_scalar(self.tcx, scalar, value.layout.ty)) - } - Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => { - let alloc_id = self - .ecx - .intern_with_temp_alloc(value.layout, |ecx, dest| { - ecx.write_immediate(*imm, dest) - }) - .ok()?; - - Some(Const::Val( - ConstValue::Indirect { alloc_id, offset: Size::ZERO }, - value.layout.ty, - )) - } - // Scalars or scalar pairs that contain undef values are assumed to not have - // successfully evaluated and are thus not propagated. - _ => None, - } - } - - fn ensure_not_propagated(&self, local: Local) { - if cfg!(debug_assertions) { - assert!( - self.get_const(local.into()).is_none() - || self - .layout_of(self.local_decls[local].ty) - .map_or(true, |layout| layout.is_zst()), - "failed to remove values for `{local:?}`, value={:?}", - self.get_const(local.into()), - ) - } - } -} - /// The mode that `ConstProp` is allowed to run in for a given `Local`. #[derive(Clone, Copy, Debug, PartialEq)] pub enum ConstPropMode { @@ -677,154 +324,3 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { } } } - -impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { - fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { - self.super_operand(operand, location); - if let Some(place) = operand.place() - && let Some(value) = self.replace_with_const(place) - { - self.patch.before_effect.insert((location, place), value); - } - } - - fn visit_projection_elem( - &mut self, - _: PlaceRef<'tcx>, - elem: PlaceElem<'tcx>, - _: PlaceContext, - location: Location, - ) { - if let PlaceElem::Index(local) = elem - && let Some(value) = self.replace_with_const(local.into()) - { - self.patch.before_effect.insert((location, local.into()), value); - } - } - - fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { - self.super_assign(place, rvalue, location); - - let Some(()) = self.check_rvalue(rvalue) else { - trace!("rvalue check failed, removing const"); - Self::remove_const(&mut self.ecx, place.local); - return; - }; - - match self.ecx.machine.can_const_prop[place.local] { - // Do nothing if the place is indirect. - _ if place.is_indirect() => {} - ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), - ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => { - if let Some(()) = self.eval_rvalue_with_identities(rvalue, *place) { - // If this was already an evaluated constant, keep it. - if let Rvalue::Use(Operand::Constant(c)) = rvalue - && let Const::Val(..) = c.const_ - { - trace!( - "skipping replace of Rvalue::Use({:?} because it is already a const", - c - ); - } else if let Some(operand) = self.replace_with_const(*place) { - self.patch.assignments.insert(location, operand); - } - } else { - // Const prop failed, so erase the destination, ensuring that whatever happens - // from here on, does not know about the previous value. - // This is important in case we have - // ```rust - // let mut x = 42; - // x = SOME_MUTABLE_STATIC; - // // x must now be uninit - // ``` - // FIXME: we overzealously erase the entire local, because that's easier to - // implement. - trace!( - "propagation into {:?} failed. - Nuking the entire site from orbit, it's the only way to be sure", - place, - ); - Self::remove_const(&mut self.ecx, place.local); - } - } - } - } - - fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - trace!("visit_statement: {:?}", statement); - - // We want to evaluate operands before any change to the assigned-to value, - // so we recurse first. - self.super_statement(statement, location); - - match statement.kind { - StatementKind::SetDiscriminant { ref place, .. } => { - match self.ecx.machine.can_const_prop[place.local] { - // Do nothing if the place is indirect. - _ if place.is_indirect() => {} - ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), - ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => { - if self.ecx.statement(statement).is_ok() { - trace!("propped discriminant into {:?}", place); - } else { - Self::remove_const(&mut self.ecx, place.local); - } - } - } - } - StatementKind::StorageLive(local) => { - Self::remove_const(&mut self.ecx, local); - } - // We do not need to mark dead locals as such. For `FullConstProp` locals, - // this allows to propagate the single assigned value in this case: - // ``` - // let x = SOME_CONST; - // if a { - // f(copy x); - // StorageDead(x); - // } else { - // g(copy x); - // StorageDead(x); - // } - // ``` - // - // This may propagate a constant where the local would be uninit or dead. - // In both cases, this does not matter, as those reads would be UB anyway. - _ => {} - } - } - - fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { - self.super_basic_block_data(block, data); - - // We remove all Locals which are restricted in propagation to their containing blocks and - // which were modified in the current block. - // Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`. - let mut written_only_inside_own_block_locals = - std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals); - - // This loop can get very hot for some bodies: it check each local in each bb. - // To avoid this quadratic behaviour, we only clear the locals that were modified inside - // the current block. - for local in written_only_inside_own_block_locals.drain() { - debug_assert_eq!( - self.ecx.machine.can_const_prop[local], - ConstPropMode::OnlyInsideOwnBlock - ); - Self::remove_const(&mut self.ecx, local); - } - self.ecx.machine.written_only_inside_own_block_locals = - written_only_inside_own_block_locals; - - if cfg!(debug_assertions) { - for (local, &mode) in self.ecx.machine.can_const_prop.iter_enumerated() { - match mode { - ConstPropMode::FullConstProp => {} - ConstPropMode::NoPropagation | ConstPropMode::OnlyInsideOwnBlock => { - self.ensure_not_propagated(local); - } - } - } - } - } -} diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 05d8d842b58..ce1a36cf670 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1417,20 +1417,18 @@ fn create_coroutine_resume_function<'tcx>( cases.insert(0, (UNRESUMED, START_BLOCK)); // Panic when resumed on the returned or poisoned state - let coroutine_kind = body.coroutine_kind().unwrap(); - if can_unwind { cases.insert( 1, - (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(coroutine_kind))), + (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(transform.coroutine_kind))), ); } if can_return { - let block = match coroutine_kind { + let block = match transform.coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) | CoroutineKind::Coroutine(_) => { - insert_panic_block(tcx, body, ResumedAfterReturn(coroutine_kind)) + insert_panic_block(tcx, body, ResumedAfterReturn(transform.coroutine_kind)) } CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) | CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { @@ -1444,7 +1442,7 @@ fn create_coroutine_resume_function<'tcx>( make_coroutine_state_argument_indirect(tcx, body); - match coroutine_kind { + match transform.coroutine_kind { // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {} @@ -1565,7 +1563,7 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; let movable = match *coroutine_ty.kind() { - ty::Coroutine(_, _, movability) => movability == hir::Movability::Movable, + ty::Coroutine(def_id, _) => tcx.coroutine_movability(def_id) == hir::Movability::Movable, ty::Error(_) => return None, _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty), }; @@ -1597,12 +1595,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // The first argument is the coroutine type passed by value let coroutine_ty = body.local_decls.raw[1].ty; + let coroutine_kind = body.coroutine_kind().unwrap(); // Get the discriminant type and args which typeck computed let (discr_ty, movable) = match *coroutine_ty.kind() { - ty::Coroutine(_, args, movability) => { + ty::Coroutine(_, args) => { let args = args.as_coroutine(); - (args.discr_ty(tcx), movability == hir::Movability::Movable) + (args.discr_ty(tcx), coroutine_kind.movability() == hir::Movability::Movable) } _ => { tcx.dcx().span_delayed_bug( @@ -1613,19 +1612,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { } }; - let is_async_kind = matches!( - body.coroutine_kind(), - Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) - ); - let is_async_gen_kind = matches!( - body.coroutine_kind(), - Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) - ); - let is_gen_kind = matches!( - body.coroutine_kind(), - Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) - ); - let new_ret_ty = match body.coroutine_kind().unwrap() { + let new_ret_ty = match coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { // Compute Poll<return_ty> let poll_did = tcx.require_lang_item(LangItem::Poll, None); @@ -1658,7 +1645,10 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let old_ret_local = replace_local(RETURN_PLACE, new_ret_ty, body, tcx); // Replace all occurrences of `ResumeTy` with `&mut Context<'_>` within async bodies. - if is_async_kind || is_async_gen_kind { + if matches!( + coroutine_kind, + CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) + ) { transform_async_context(tcx, body); } @@ -1667,11 +1657,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // case there is no `Assign` to it that the transform can turn into a store to the coroutine // state. After the yield the slot in the coroutine state would then be uninitialized. let resume_local = Local::new(2); - let resume_ty = if is_async_kind { - Ty::new_task_context(tcx) - } else { - body.local_decls[resume_local].ty - }; + let resume_ty = body.local_decls[resume_local].ty; let old_resume_local = replace_local(resume_local, resume_ty, body, tcx); // When first entering the coroutine, move the resume argument into its old local @@ -1714,11 +1700,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Run the transformation which converts Places from Local to coroutine struct // accesses for locals in `remap`. // It also rewrites `return x` and `yield y` as writing a new coroutine state and returning - // either CoroutineState::Complete(x) and CoroutineState::Yielded(y), - // or Poll::Ready(x) and Poll::Pending respectively depending on `is_async_kind`. + // either `CoroutineState::Complete(x)` and `CoroutineState::Yielded(y)`, + // or `Poll::Ready(x)` and `Poll::Pending` respectively depending on the coroutine kind. let mut transform = TransformVisitor { tcx, - coroutine_kind: body.coroutine_kind().unwrap(), + coroutine_kind, remap, storage_liveness, always_live_locals, @@ -1735,7 +1721,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { body.spread_arg = None; // Remove the context argument within generator bodies. - if is_gen_kind { + if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) { transform_gen_context(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 604589e5b96..d995d562521 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -47,7 +47,10 @@ pub(super) struct CoverageCounters { bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>, /// Coverage counters/expressions that are associated with the control-flow /// edge between two BCBs. - bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, + /// + /// The iteration order of this map can affect the precise contents of MIR, + /// so we use `FxIndexMap` to avoid query stability hazards. + bcb_edge_counters: FxIndexMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, /// Tracks which BCBs have a counter associated with some incoming edge. /// Only used by assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). @@ -64,7 +67,7 @@ impl CoverageCounters { Self { next_counter_id: CounterId::START, bcb_counters: IndexVec::from_elem_n(None, num_bcbs), - bcb_edge_counters: FxHashMap::default(), + bcb_edge_counters: FxIndexMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), expressions: IndexVec::new(), } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 474cb205d13..ff6545e9d25 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -91,7 +91,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( fn is_closure(statement: &Statement<'_>) -> bool { match statement.kind { StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind { - AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _, _) => true, + AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) => true, _ => false, }, _ => false, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 3b8adf7e86b..2551c8aca88 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -109,7 +109,7 @@ pub struct GVN; impl<'tcx> MirPass<'tcx> for GVN { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 4 + sess.mir_opt_level() >= 2 } #[instrument(level = "trace", skip(self, tcx, body))] @@ -850,7 +850,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { assert!(!fields.is_empty()); (AggregateTy::Tuple, FIRST_VARIANT) } - AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs, _) => { + AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs) => { (AggregateTy::Def(did, substs), FIRST_VARIANT) } AggregateKind::Adt(did, variant_index, substs, _, None) => { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9d03bab4844..5562ae7f3bd 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -588,7 +588,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // destroy the SSA property. It should still happen before const-propagation, so the // latter pass will leverage the created opportunities. &separate_const_switch::SeparateConstSwitch, - &const_prop::ConstProp, &gvn::GVN, &simplify::SimplifyLocals::AfterGVN, &dataflow_const_prop::DataflowConstProp, diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index fba73d5195b..f6b820bfcd0 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -69,7 +69,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' ty::InstanceDef::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? - if let Some(ty::Coroutine(coroutine_def_id, args, _)) = ty.map(Ty::kind) { + if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { let body = tcx.optimized_mir(*coroutine_def_id).coroutine_drop().unwrap(); let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); @@ -394,7 +394,8 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - _ if is_copy => builder.copy_shim(), ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()), ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()), - ty::Coroutine(coroutine_def_id, args, hir::Movability::Movable) => { + ty::Coroutine(coroutine_def_id, args) => { + assert_eq!(tcx.coroutine_movability(*coroutine_def_id), hir::Movability::Movable); builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine()) } _ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty), diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index ac2e8960b06..db1aee11903 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -333,7 +333,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index b4493df57e2..77bca2f138a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -450,37 +450,39 @@ impl<'a> Parser<'a> { let mut expected = edible .iter() - .map(|x| TokenType::Token(x.clone())) - .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) + .chain(inedible) + .cloned() + .map(TokenType::Token) .chain(self.expected_tokens.iter().cloned()) - .filter_map(|token| { - // filter out suggestions which suggest the same token which was found and deemed incorrect + .filter(|token| { + // Filter out suggestions that suggest the same token which was found and deemed incorrect. fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { - if let TokenKind::Ident(current_sym, _) = found { - if let TokenType::Keyword(suggested_sym) = expected { - return current_sym == suggested_sym; - } + if let TokenKind::Ident(current_sym, _) = found + && let TokenType::Keyword(suggested_sym) = expected + { + return current_sym == suggested_sym; } false } - if token != parser::TokenType::Token(self.token.kind.clone()) { + + if *token != parser::TokenType::Token(self.token.kind.clone()) { let eq = is_ident_eq_keyword(&self.token.kind, &token); - // if the suggestion is a keyword and the found token is an ident, + // If the suggestion is a keyword and the found token is an ident, // the content of which are equal to the suggestion's content, - // we can remove that suggestion (see the return None statement below) + // we can remove that suggestion (see the `return false` below). - // if this isn't the case however, and the suggestion is a token the - // content of which is the same as the found token's, we remove it as well + // If this isn't the case however, and the suggestion is a token the + // content of which is the same as the found token's, we remove it as well. if !eq { if let TokenType::Token(kind) = &token { if kind == &self.token.kind { - return None; + return false; } } - return Some(token); + return true; } } - return None; + false }) .collect::<Vec<_>>(); expected.sort_by_cached_key(|x| x.to_string()); @@ -488,10 +490,10 @@ impl<'a> Parser<'a> { let sm = self.sess.source_map(); - // Special-case "expected `;`" errors + // Special-case "expected `;`" errors. if expected.contains(&TokenType::Token(token::Semi)) { // If the user is trying to write a ternary expression, recover it and - // return an Err to prevent a cascade of irrelevant diagnostics + // return an Err to prevent a cascade of irrelevant diagnostics. if self.prev_token == token::Question && let Err(e) = self.maybe_recover_from_ternary_operator() { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 73bd19f34c1..bf6151b64d3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2937,7 +2937,13 @@ impl<'a> Parser<'a> { let is_almost_fat_arrow = TokenKind::FatArrow .similar_tokens() .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)); - let mut result = if !is_fat_arrow && !is_almost_fat_arrow { + + // this avoids the compiler saying that a `,` or `}` was expected even though + // the pattern isn't a never pattern (and thus an arm body is required) + let armless = (!is_fat_arrow && !is_almost_fat_arrow && pat.could_be_never_pattern()) + || matches!(this.token.kind, token::Comma | token::CloseDelim(Delimiter::Brace)); + + let mut result = if armless { // A pattern without a body, allowed for never patterns. arm_body = None; this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]).map( diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1598fd19f6d..19226f37abe 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -320,9 +320,15 @@ impl TokenType { } } +/// Used by [`Parser::expect_any_with_type`]. #[derive(Copy, Clone, Debug)] enum TokenExpectType { + /// Unencountered tokens are inserted into [`Parser::expected_tokens`]. + /// See [`Parser::check`]. Expect, + + /// Unencountered tokens are not inserted into [`Parser::expected_tokens`]. + /// See [`Parser::check_noexpect`]. NoExpect, } @@ -504,18 +510,10 @@ impl<'a> Parser<'a> { } fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, /* is_raw */ bool)> { - let result = self.token.ident().ok_or_else(|| self.expected_ident_found(recover)); - - let (ident, is_raw) = match result { - Ok(ident) => ident, - Err(err) => match err { - // we recovered! - Ok(ident) => ident, - Err(err) => return Err(err), - }, - }; - - Ok((ident, is_raw)) + match self.token.ident() { + Some(ident) => Ok(ident), + None => self.expected_ident_found(recover), + } } /// Checks if the next token is `tok`, and returns `true` if so. @@ -766,13 +764,17 @@ impl<'a> Parser<'a> { } } + /// Checks if the next token is contained within `kets`, and returns `true` if so. fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool { kets.iter().any(|k| match expect { TokenExpectType::Expect => self.check(k), - TokenExpectType::NoExpect => self.token == **k, + TokenExpectType::NoExpect => self.check_noexpect(k), }) } + /// Parses a sequence until the specified delimiters. The function + /// `f` must consume tokens until reaching the next separator or + /// closing bracket. fn parse_seq_to_before_tokens<T>( &mut self, kets: &[&TokenKind], @@ -791,13 +793,15 @@ impl<'a> Parser<'a> { } if let Some(t) = &sep.sep { if first { + // no separator for the first element first = false; } else { + // check for separator match self.expect(t) { - Ok(false) => { + Ok(false) /* not recovered */ => { self.current_closure.take(); } - Ok(true) => { + Ok(true) /* recovered */ => { self.current_closure.take(); recovered = true; break; @@ -965,7 +969,7 @@ impl<'a> Parser<'a> { Ok(()) } - /// Parses a sequence, not including the closing delimiter. The function + /// Parses a sequence, not including the delimiters. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. fn parse_seq_to_before_end<T>( @@ -973,11 +977,11 @@ impl<'a> Parser<'a> { ket: &TokenKind, sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, - ) -> PResult<'a, (ThinVec<T>, bool, bool)> { + ) -> PResult<'a, (ThinVec<T>, bool /* trailing */, bool /* recovered */)> { self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f) } - /// Parses a sequence, including the closing delimiter. The function + /// Parses a sequence, including only the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. fn parse_seq_to_end<T>( @@ -993,7 +997,7 @@ impl<'a> Parser<'a> { Ok((val, trailing)) } - /// Parses a sequence, including the closing delimiter. The function + /// Parses a sequence, including both delimiters. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. fn parse_unspanned_seq<T>( @@ -1002,16 +1006,19 @@ impl<'a> Parser<'a> { ket: &TokenKind, sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, - ) -> PResult<'a, (ThinVec<T>, bool)> { + ) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> { self.expect(bra)?; self.parse_seq_to_end(ket, sep, f) } + /// Parses a comma-separated sequence, including both delimiters. + /// The function `f` must consume tokens until reaching the next separator or + /// closing bracket. fn parse_delim_comma_seq<T>( &mut self, delim: Delimiter, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, - ) -> PResult<'a, (ThinVec<T>, bool)> { + ) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> { self.parse_unspanned_seq( &token::OpenDelim(delim), &token::CloseDelim(delim), @@ -1020,10 +1027,13 @@ impl<'a> Parser<'a> { ) } + /// Parses a comma-separated sequence delimited by parentheses (e.g. `(x, y)`). + /// The function `f` must consume tokens until reaching the next separator or + /// closing bracket. fn parse_paren_comma_seq<T>( &mut self, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, - ) -> PResult<'a, (ThinVec<T>, bool)> { + ) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> { self.parse_delim_comma_seq(Delimiter::Parenthesis, f) } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 6be01e0d88f..cfe829f170f 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -101,7 +101,6 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::DUMMY_SP; use rustc_span::{BytePos, Span}; -use std::collections::VecDeque; use std::io; use std::io::prelude::*; use std::rc::Rc; @@ -317,35 +316,13 @@ impl<'tcx> IrMaps<'tcx> { // For struct patterns, take note of which fields used shorthand // (`x` rather than `x: x`). let mut shorthand_field_ids = HirIdSet::default(); - let mut pats = VecDeque::new(); - pats.push_back(pat); - - while let Some(pat) = pats.pop_front() { - use rustc_hir::PatKind::*; - match &pat.kind { - Binding(.., inner_pat) => { - pats.extend(inner_pat.iter()); - } - Struct(_, fields, _) => { - let (short, not_short): (Vec<hir::PatField<'_>>, _) = - fields.iter().partition(|f| f.is_shorthand); - shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id)); - pats.extend(not_short.iter().map(|f| f.pat)); - } - Ref(inner_pat, _) | Box(inner_pat) => { - pats.push_back(inner_pat); - } - TupleStruct(_, inner_pats, _) | Tuple(inner_pats, _) | Or(inner_pats) => { - pats.extend(inner_pats.iter()); - } - Slice(pre_pats, inner_pat, post_pats) => { - pats.extend(pre_pats.iter()); - pats.extend(inner_pat.iter()); - pats.extend(post_pats.iter()); - } - _ => {} + + pat.walk_always(|pat| { + if let hir::PatKind::Struct(_, fields, _) = pat.kind { + let short = fields.iter().filter(|f| f.is_shorthand); + shorthand_field_ids.extend(short.map(|f| f.pat.hir_id)); } - } + }); shorthand_field_ids } @@ -1351,6 +1328,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { self.check_unused_vars_in_pat(arm.pat, None, None, |_, _, _, _| {}); + if let Some(hir::Guard::IfLet(let_expr)) = arm.guard { + self.check_unused_vars_in_pat(let_expr.pat, None, None, |_, _, _, _| {}); + } intravisit::walk_arm(self, arm); } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 3c1bdfd910e..b09d565f076 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -366,7 +366,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::Alias(_, _) | ty::Param(_) | ty::Error(_) => ConstructorSet::Unlistable, diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index bbc98af45c0..17162d0de25 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -104,11 +104,9 @@ impl<'tcx> RustcInternal<'tcx> for RigidTy { RigidTy::Closure(def, args) => { rustc_ty::TyKind::Closure(def.0.internal(tables), args.internal(tables)) } - RigidTy::Coroutine(def, args, mov) => rustc_ty::TyKind::Coroutine( - def.0.internal(tables), - args.internal(tables), - mov.internal(tables), - ), + RigidTy::Coroutine(def, args, _mov) => { + rustc_ty::TyKind::Coroutine(def.0.internal(tables), args.internal(tables)) + } RigidTy::CoroutineWitness(def, args) => { rustc_ty::TyKind::CoroutineWitness(def.0.internal(tables), args.internal(tables)) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 49bf2192f82..c5fb6f7a26f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -531,11 +531,11 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { generic_arg.stable(tables), ) } - mir::AggregateKind::Coroutine(def_id, generic_arg, movability) => { + mir::AggregateKind::Coroutine(def_id, generic_arg) => { stable_mir::mir::AggregateKind::Coroutine( tables.coroutine_def(*def_id), generic_arg.stable(tables), - movability.stable(tables), + tables.tcx.coroutine_movability(*def_id).stable(tables), ) } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index cbdddc30072..f0f1d798d44 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -386,10 +386,10 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { tables.closure_def(*def_id), generic_args.stable(tables), )), - ty::Coroutine(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Coroutine( + ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( tables.coroutine_def(*def_id), generic_args.stable(tables), - movability.stable(tables), + tables.tcx.coroutine_movability(*def_id).stable(tables), )), ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => { diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index a273a412146..4a5f58443bc 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -211,7 +211,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) - | ty::Coroutine(def_id, args, _) => self.print_def_path(def_id, args), + | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), // The `pretty_print_type` formatting of array size depends on // -Zverbose-internals flag, so we cannot reuse it here. 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 d2962b2968b..0cc82ac7506 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 @@ -895,8 +895,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options)); } - ty::Coroutine(def_id, args, movability) => { - ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options), *movability); + ty::Coroutine(def_id, args) => { + ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options)); } ty::Ref(region, ty0, ..) => { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e002e345ae6..e89a640767f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -427,7 +427,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) - | ty::Coroutine(def_id, args, _) => { + | ty::Coroutine(def_id, args) => { self.print_def_path(def_id, args)?; } ty::Foreign(def_id) => { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 81a766f24b0..caf9470b4c6 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -432,7 +432,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::Never | ty::Tuple(_) => { let simp = diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index f442e2a08a8..274a75a125c 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -57,7 +57,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]) } @@ -177,7 +177,6 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::Dynamic(..) | ty::Str | ty::Slice(_) - | ty::Coroutine(_, _, Movability::Static) | ty::Foreign(..) | ty::Ref(_, _, Mutability::Mut) | ty::Adt(_, _) @@ -194,14 +193,17 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), - ty::Coroutine(_, args, Movability::Movable) => { - if ecx.tcx().features().coroutine_clone { - let coroutine = args.as_coroutine(); - Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]) - } else { - Err(NoSolution) + ty::Coroutine(def_id, args) => match ecx.tcx().coroutine_movability(def_id) { + Movability::Static => Err(NoSolution), + Movability::Movable => { + if ecx.tcx().features().coroutine_clone { + let coroutine = args.as_coroutine(); + Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]) + } else { + Err(NoSolution) + } } - } + }, ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() @@ -278,7 +280,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::Dynamic(_, _, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index bac08f6588f..ccee6f8eb29 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -468,7 +468,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); }; @@ -499,7 +499,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); }; @@ -530,7 +530,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); }; @@ -564,7 +564,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); }; diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index ac3ffd2d6c2..be079275684 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -337,7 +337,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -361,7 +361,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -385,7 +385,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -410,7 +410,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); }; @@ -927,10 +927,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // Coroutines have one special built-in candidate, `Unpin`, which // takes precedence over the structural auto trait candidate being // assembled. - ty::Coroutine(_, _, movability) + ty::Coroutine(def_id, _) if Some(goal.predicate.def_id()) == self.tcx().lang_items().unpin_trait() => { - match movability { + match self.tcx().coroutine_movability(def_id) { Movability::Static => Some(Err(NoSolution)), Movability::Movable => { Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) @@ -959,7 +959,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1143b9d3360..f63314081d6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3406,7 +3406,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } err.note(msg.trim_end_matches(", ").to_string()) } - ty::Coroutine(def_id, _, _) => { + ty::Coroutine(def_id, _) => { let sp = self.tcx.def_span(def_id); // Special-case this to say "async block" instead of `[static coroutine]`. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d32b4adbefc..dd4e69efe37 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2083,7 +2083,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); - let ty::Coroutine(_, args, _) = self_ty.kind() else { + let ty::Coroutine(_, args) = self_ty.kind() else { unreachable!( "expected coroutine self type for built-in coroutine candidate, found {self_ty}" ) @@ -2138,7 +2138,7 @@ fn confirm_future_candidate<'cx, 'tcx>( nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); - let ty::Coroutine(_, args, _) = self_ty.kind() else { + let ty::Coroutine(_, args) = self_ty.kind() else { unreachable!( "expected coroutine self type for built-in async future candidate, found {self_ty}" ) @@ -2182,7 +2182,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); - let ty::Coroutine(_, args, _) = self_ty.kind() else { + let ty::Coroutine(_, args) = self_ty.kind() else { unreachable!("expected coroutine self type for built-in gen candidate, found {self_ty}") }; let gen_sig = args.as_coroutine().sig(); @@ -2223,8 +2223,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let ty::Coroutine(_, args, _) = - selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() else { unreachable!() }; diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index f9c8f3d14c3..138bc6129f7 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -259,7 +259,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( })? } - ty::Coroutine(_, args, _movability) => { + ty::Coroutine(_, args) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when coroutine yields // (and is subsequently dropped). diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3a37bc518ef..54b91ab1d4d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -263,7 +263,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { let self_ty = obligation.self_ty().skip_binder(); - if let ty::Coroutine(did, args, _) = *self_ty.kind() { + if let ty::Coroutine(did, args) = *self_ty.kind() { // gen constructs get lowered to a special kind of coroutine that // should directly `impl AsyncIterator`. if self.tcx().coroutine_is_async_gen(did) { @@ -486,7 +486,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) @@ -529,7 +529,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let def_id = obligation.predicate.def_id(); if self.tcx().trait_is_auto(def_id) { - match self_ty.kind() { + match *self_ty.kind() { ty::Dynamic(..) => { // For object types, we don't know what the closed // over types are. This means we conservatively @@ -564,10 +564,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The auto impl might apply; we don't know. candidates.ambiguous = true; } - ty::Coroutine(_, _, movability) + ty::Coroutine(coroutine_def_id, _) if self.tcx().lang_items().unpin_trait() == Some(def_id) => { - match movability { + match self.tcx().coroutine_movability(coroutine_def_id) { hir::Movability::Static => { // Immovable coroutines are never `Unpin`, so // suppress the normal auto-impl candidate for it. @@ -1023,7 +1023,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) - | ty::Coroutine(_, _, _) + | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::Alias(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f1da1c046d4..e20bb06d777 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -730,7 +730,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -768,7 +768,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -797,7 +797,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -826,7 +826,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else { + let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -1298,7 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Closure(_, args) => { stack.push(args.as_closure().tupled_upvars_ty()); } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { let coroutine = args.as_coroutine(); stack.extend([coroutine.tupled_upvars_ty(), coroutine.witness()]); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 336c0c5299f..c45925295ee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2176,7 +2176,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Dynamic(..) | ty::Str | ty::Slice(..) - | ty::Coroutine(_, _, hir::Movability::Static) | ty::Foreign(..) | ty::Ref(_, _, hir::Mutability::Mut) => None, @@ -2185,26 +2184,31 @@ impl<'tcx> SelectionContext<'_, 'tcx> { Where(obligation.predicate.rebind(tys.iter().collect())) } - ty::Coroutine(_, args, hir::Movability::Movable) => { - if self.tcx().features().coroutine_clone { - let resolved_upvars = - self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let resolved_witness = - self.infcx.shallow_resolve(args.as_coroutine().witness()); - if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() { - // Not yet resolved. - Ambiguous - } else { - let all = args - .as_coroutine() - .upvar_tys() - .iter() - .chain([args.as_coroutine().witness()]) - .collect::<Vec<_>>(); - Where(obligation.predicate.rebind(all)) + ty::Coroutine(coroutine_def_id, args) => { + match self.tcx().coroutine_movability(coroutine_def_id) { + hir::Movability::Static => None, + hir::Movability::Movable => { + if self.tcx().features().coroutine_clone { + let resolved_upvars = + self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); + let resolved_witness = + self.infcx.shallow_resolve(args.as_coroutine().witness()); + if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() { + // Not yet resolved. + Ambiguous + } else { + let all = args + .as_coroutine() + .upvar_tys() + .iter() + .chain([args.as_coroutine().witness()]) + .collect::<Vec<_>>(); + Where(obligation.predicate.rebind(all)) + } + } else { + None + } } - } else { - None } } @@ -2307,7 +2311,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { t.rebind(vec![ty]) } - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); let witness = args.as_coroutine().witness(); t.rebind([ty].into_iter().chain(iter::once(witness)).collect()) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 4756a45a447..2772831e731 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -97,7 +97,7 @@ fn fn_sig_for_fn_abi<'tcx>( bound_vars, ) } - ty::Coroutine(did, args, _) => { + ty::Coroutine(did, args) => { let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 42db43caf9f..81d5304b812 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -246,7 +246,7 @@ fn resolve_associated_item<'tcx>( }) } } else if Some(trait_ref.def_id) == lang_items.future_trait() { - let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else { + let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else { bug!() }; if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { @@ -259,7 +259,7 @@ fn resolve_associated_item<'tcx>( Some(Instance::new(trait_item_id, rcvr_args)) } } else if Some(trait_ref.def_id) == lang_items.iterator_trait() { - let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else { + let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else { bug!() }; if Some(trait_item_id) == tcx.lang_items().next_fn() { @@ -272,7 +272,7 @@ fn resolve_associated_item<'tcx>( Some(Instance::new(trait_item_id, rcvr_args)) } } else if Some(trait_ref.def_id) == lang_items.async_iterator_trait() { - let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else { + let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else { bug!() }; @@ -287,7 +287,7 @@ fn resolve_associated_item<'tcx>( // `AsyncIterator::poll_next` is generated by the compiler. Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) } else if Some(trait_ref.def_id) == lang_items.coroutine_trait() { - let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else { + let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else { bug!() }; if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index d39377a1acb..db89fba2a89 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -316,7 +316,7 @@ fn layout_of_uncached<'tcx>( tcx.mk_layout(unit) } - ty::Coroutine(def_id, args, _) => coroutine_layout(cx, ty, def_id, args)?, + ty::Coroutine(def_id, args) => coroutine_layout(cx, ty, def_id, args)?, ty::Closure(_, args) => { let tys = args.as_closure().upvar_tys(); @@ -961,7 +961,7 @@ fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: T record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos); } - ty::Coroutine(def_id, args, _) => { + ty::Coroutine(def_id, args) => { debug!("print-type-size t: `{:?}` record coroutine", layout.ty); // Coroutines always have a begin/poisoned/end state with additional suspend points let (variant_infos, opt_discr_size) = diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 8d118e6dfef..08e5476ae43 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -145,7 +145,7 @@ where // for the coroutine witness and check whether any of the contained types // need to be dropped, and only require the captured types to be live // if they do. - ty::Coroutine(_, args, _) => { + ty::Coroutine(_, args) => { if self.reveal_coroutine_witnesses { queue_type(self, args.as_coroutine().witness()); } else { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 70adfbee2ed..859000fb6cb 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -207,7 +207,7 @@ pub enum TyKind<I: Interner> { /// /// For more info about coroutine args, visit the documentation for /// `CoroutineArgs`. - Coroutine(I::DefId, I::GenericArgs, Movability), + Coroutine(I::DefId, I::GenericArgs), /// A type representing the types stored inside a coroutine. /// This should only appear as part of the `CoroutineArgs`. @@ -317,7 +317,7 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize { FnPtr(_) => 13, Dynamic(..) => 14, Closure(_, _) => 15, - Coroutine(_, _, _) => 16, + Coroutine(_, _) => 16, CoroutineWitness(_, _) => 17, Never => 18, Tuple(_) => 19, @@ -356,9 +356,7 @@ impl<I: Interner> PartialEq for TyKind<I> { a_p == b_p && a_r == b_r && a_repr == b_repr } (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s, - (Coroutine(a_d, a_s, a_m), Coroutine(b_d, b_s, b_m)) => { - a_d == b_d && a_s == b_s && a_m == b_m - } + (Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s, (CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s, (Tuple(a_t), Tuple(b_t)) => a_t == b_t, (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p, @@ -432,9 +430,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> { } }, Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(), - Coroutine(d, s, m) => { - f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).field(m).finish() - } + Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).finish(), CoroutineWitness(d, s) => { f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish() } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 5871600bece..72227a04bf1 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -662,6 +662,7 @@ pub enum AggregateKind { Tuple, Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), Closure(ClosureDef, GenericArgs), + // FIXME(stable_mir): Movability here is redundant Coroutine(CoroutineDef, GenericArgs, Movability), } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 1d4d7b6d352..9e6ecbe8315 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -460,6 +460,7 @@ pub enum RigidTy { FnDef(FnDef, GenericArgs), FnPtr(PolyFnSig), Closure(ClosureDef, GenericArgs), + // FIXME(stable_mir): Movability here is redundant Coroutine(CoroutineDef, GenericArgs, Movability), Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind), Never, diff --git a/config.example.toml b/config.example.toml index dacc61a3e4c..f1ea6bac3ca 100644 --- a/config.example.toml +++ b/config.example.toml @@ -661,7 +661,7 @@ # Indicates whether some LLVM tools, like llvm-objdump, will be made available in the # sysroot. -#llvm-tools = false +#llvm-tools = true # Whether to deny warnings in crates #deny-warnings = true diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 99ec68f5aa5..74fa30456eb 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -284,7 +284,7 @@ impl<T, A: Allocator> RawVec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Aborts /// @@ -342,7 +342,7 @@ impl<T, A: Allocator> RawVec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Aborts /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 85df491636a..1fc6fe631ab 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2917,20 +2917,17 @@ impl<T: ?Sized, A: Allocator + Clone> Clone for Weak<T, A> { /// ``` #[inline] fn clone(&self) -> Weak<T, A> { - let inner = if let Some(inner) = self.inner() { - inner - } else { - return Weak { ptr: self.ptr, alloc: self.alloc.clone() }; - }; - // See comments in Arc::clone() for why this is relaxed. This can use a - // fetch_add (ignoring the lock) because the weak count is only locked - // where are *no other* weak pointers in existence. (So we can't be - // running this code in that case). - let old_size = inner.weak.fetch_add(1, Relaxed); - - // See comments in Arc::clone() for why we do this (for mem::forget). - if old_size > MAX_REFCOUNT { - abort(); + if let Some(inner) = self.inner() { + // See comments in Arc::clone() for why this is relaxed. This can use a + // fetch_add (ignoring the lock) because the weak count is only locked + // where are *no other* weak pointers in existence. (So we can't be + // running this code in that case). + let old_size = inner.weak.fetch_add(1, Relaxed); + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } } Weak { ptr: self.ptr, alloc: self.alloc.clone() } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fca85c6123b..e8a096cac86 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -445,7 +445,7 @@ impl<T> Vec<T> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// @@ -633,7 +633,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// @@ -896,7 +896,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// @@ -926,7 +926,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// @@ -1900,7 +1900,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// @@ -2003,7 +2003,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Panics /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. /// /// # Examples /// diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 544a42d9ada..d34c19a47e3 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -55,7 +55,6 @@ o("profiler", "build.profiler", "build the profiler runtime") o("full-tools", None, "enable all tools") o("lld", "rust.lld", "build lld") o("clang", "llvm.clang", "build clang") -o("missing-tools", "dist.missing-tools", "allow failures when building tools") o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains") diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index df4d1a43dab..dbb64583d56 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1738,7 +1738,7 @@ impl Step for Assemble { if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) { let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target: target_compiler.host }); - if !builder.config.dry_run() { + if !builder.config.dry_run() && builder.config.llvm_tools_enabled { let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir")); let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 98e267713da..d87651cb367 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1110,9 +1110,7 @@ impl Step for Rls { let compiler = self.compiler; let target = self.target; - let rls = builder - .ensure(tool::Rls { compiler, target, extra_features: Vec::new() }) - .expect("rls expected to build"); + let rls = builder.ensure(tool::Rls { compiler, target, extra_features: Vec::new() }); let mut tarball = Tarball::new(builder, "rls", &target.triple); tarball.set_overlay(OverlayKind::RLS); @@ -1154,9 +1152,7 @@ impl Step for RustAnalyzer { let compiler = self.compiler; let target = self.target; - let rust_analyzer = builder - .ensure(tool::RustAnalyzer { compiler, target }) - .expect("rust-analyzer always builds"); + let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target }); let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple); tarball.set_overlay(OverlayKind::RustAnalyzer); @@ -1201,12 +1197,9 @@ impl Step for Clippy { // Prepare the image directory // We expect clippy to build, because we've exited this step above if tool // state for clippy isn't testing. - let clippy = builder - .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() }) - .expect("clippy expected to build - essential tool"); - let cargoclippy = builder - .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() }) - .expect("clippy expected to build - essential tool"); + let clippy = builder.ensure(tool::Clippy { compiler, target, extra_features: Vec::new() }); + let cargoclippy = + builder.ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() }); let mut tarball = Tarball::new(builder, "clippy", &target.triple); tarball.set_overlay(OverlayKind::Clippy); @@ -1255,9 +1248,9 @@ impl Step for Miri { let compiler = self.compiler; let target = self.target; - let miri = builder.ensure(tool::Miri { compiler, target, extra_features: Vec::new() })?; + let miri = builder.ensure(tool::Miri { compiler, target, extra_features: Vec::new() }); let cargomiri = - builder.ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })?; + builder.ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() }); let mut tarball = Tarball::new(builder, "miri", &target.triple); tarball.set_overlay(OverlayKind::Miri); @@ -1396,12 +1389,10 @@ impl Step for Rustfmt { let compiler = self.compiler; let target = self.target; - let rustfmt = builder - .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() }) - .expect("rustfmt expected to build - essential tool"); - let cargofmt = builder - .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() }) - .expect("cargo fmt expected to build - essential tool"); + let rustfmt = + builder.ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() }); + let cargofmt = + builder.ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() }); let mut tarball = Tarball::new(builder, "rustfmt", &target.triple); tarball.set_overlay(OverlayKind::Rustfmt); tarball.is_preview(true); @@ -1455,9 +1446,8 @@ impl Step for RustDemangler { return None; } - let rust_demangler = builder - .ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }) - .expect("rust-demangler expected to build - in-tree tool"); + let rust_demangler = + builder.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }); // Prepare the image directory let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple); @@ -2157,12 +2147,14 @@ impl Step for LlvmTools { tarball.set_overlay(OverlayKind::LLVM); tarball.is_preview(true); - // Prepare the image directory - let src_bindir = builder.llvm_out(target).join("bin"); - let dst_bindir = format!("lib/rustlib/{}/bin", target.triple); - for tool in LLVM_TOOLS { - let exe = src_bindir.join(exe(tool, target)); - tarball.add_file(&exe, &dst_bindir, 0o755); + if builder.config.llvm_tools_enabled { + // Prepare the image directory + let src_bindir = builder.llvm_out(target).join("bin"); + let dst_bindir = format!("lib/rustlib/{}/bin", target.triple); + for tool in LLVM_TOOLS { + let exe = src_bindir.join(exe(tool, target)); + tarball.add_file(&exe, &dst_bindir, 0o755); + } } // Copy libLLVM.so to the target lib dir as well, so the RPATH like diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index d1d6b7e869e..d9e0da14a70 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -148,9 +148,8 @@ impl Step for Miri { let target = self.target; let compiler = builder.compiler(stage, host); - let miri = builder - .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); + let miri = + builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }); let miri_sysroot = test::Miri::build_miri_sysroot(builder, compiler, &miri, target); // # Run miri. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index d0f36f99342..92140b00da8 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -427,9 +427,7 @@ impl Step for Rustfmt { let host = self.host; let compiler = builder.compiler(stage, host); - builder - .ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); + builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() }); let mut cargo = tool::prepare_tool_cargo( builder, @@ -476,9 +474,11 @@ impl Step for RustDemangler { let host = self.host; let compiler = builder.compiler(stage, host); - let rust_demangler = builder - .ensure(tool::RustDemangler { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); + let rust_demangler = builder.ensure(tool::RustDemangler { + compiler, + target: self.host, + extra_features: Vec::new(), + }); let mut cargo = tool::prepare_tool_cargo( builder, compiler, @@ -609,12 +609,13 @@ impl Step for Miri { // Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage. let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host); - let miri = builder - .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); - let _cargo_miri = builder - .ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); + let miri = + builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() }); + let _cargo_miri = builder.ensure(tool::CargoMiri { + compiler, + target: self.host, + extra_features: Vec::new(), + }); // The stdlib we need might be at a different stage. And just asking for the // sysroot does not seem to populate it, so we do that first. builder.ensure(compile::Std::new(compiler_std, host)); @@ -788,9 +789,7 @@ impl Step for Clippy { let host = self.host; let compiler = builder.compiler(stage, host); - builder - .ensure(tool::Clippy { compiler, target: self.host, extra_features: Vec::new() }) - .expect("in-tree tool"); + builder.ensure(tool::Clippy { compiler, target: self.host, extra_features: Vec::new() }); let mut cargo = tool::prepare_tool_cargo( builder, compiler, @@ -1668,13 +1667,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the if mode == "coverage-run" { // The demangler doesn't need the current compiler, so we can avoid // unnecessary rebuilds by using the bootstrap compiler instead. - let rust_demangler = builder - .ensure(tool::RustDemangler { - compiler: compiler.with_stage(0), - target: compiler.host, - extra_features: Vec::new(), - }) - .expect("in-tree tool"); + let rust_demangler = builder.ensure(tool::RustDemangler { + compiler: compiler.with_stage(0), + target: compiler.host, + extra_features: Vec::new(), + }); cmd.arg("--rust-demangler-path").arg(rust_demangler); } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 8e3941dbeda..2cd42dd8081 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -27,7 +27,6 @@ struct ToolBuild { tool: &'static str, path: &'static str, mode: Mode, - is_optional_tool: bool, source_type: SourceType, extra_features: Vec<String>, /// Nightly-only features that are allowed (comma-separated list). @@ -60,7 +59,7 @@ impl Builder<'_> { } impl Step for ToolBuild { - type Output = Option<PathBuf>; + type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() @@ -70,12 +69,11 @@ impl Step for ToolBuild { /// /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. - fn run(self, builder: &Builder<'_>) -> Option<PathBuf> { + fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let target = self.target; let mut tool = self.tool; let path = self.path; - let is_optional_tool = self.is_optional_tool; match self.mode { Mode::ToolRustc => { @@ -109,20 +107,16 @@ impl Step for ToolBuild { ); let mut cargo = Command::from(cargo); - // we check this in `is_optional_tool` in a second - let is_expected = builder.run_cmd(BootstrapCommand::from(&mut cargo).allow_failure()); + // we check this below + let build_success = builder.run_cmd(BootstrapCommand::from(&mut cargo).allow_failure()); builder.save_toolstate( tool, - if is_expected { ToolState::TestFail } else { ToolState::BuildFail }, + if build_success { ToolState::TestFail } else { ToolState::BuildFail }, ); - if !is_expected { - if !is_optional_tool { - crate::exit!(1); - } else { - None - } + if !build_success { + crate::exit!(1); } else { // HACK(#82501): on Windows, the tools directory gets added to PATH when running tests, and // compiletest confuses HTML tidy with the in-tree tidy. Name the in-tree tidy something @@ -133,7 +127,7 @@ impl Step for ToolBuild { let cargo_out = builder.cargo_out(compiler, self.mode, target).join(exe(tool, target)); let bin = builder.tools_dir(compiler).join(exe(tool, target)); builder.copy(&cargo_out, &bin); - Some(bin) + bin } } } @@ -278,7 +272,6 @@ macro_rules! bootstrap_tool { Mode::ToolBootstrap }, path: $path, - is_optional_tool: false, source_type: if false $(|| $external)* { SourceType::Submodule } else { @@ -286,7 +279,7 @@ macro_rules! bootstrap_tool { }, extra_features: vec![], allow_features: concat!($($allow_features)*), - }).expect("expected to build -- essential tool") + }) } } )+ @@ -361,19 +354,16 @@ impl Step for ErrorIndex { } fn run(self, builder: &Builder<'_>) -> PathBuf { - builder - .ensure(ToolBuild { - compiler: self.compiler, - target: self.compiler.host, - tool: "error_index_generator", - mode: Mode::ToolRustc, - path: "src/tools/error_index_generator", - is_optional_tool: false, - source_type: SourceType::InTree, - extra_features: Vec::new(), - allow_features: "", - }) - .expect("expected to build -- essential tool") + builder.ensure(ToolBuild { + compiler: self.compiler, + target: self.compiler.host, + tool: "error_index_generator", + mode: Mode::ToolRustc, + path: "src/tools/error_index_generator", + source_type: SourceType::InTree, + extra_features: Vec::new(), + allow_features: "", + }) } } @@ -398,19 +388,16 @@ impl Step for RemoteTestServer { } fn run(self, builder: &Builder<'_>) -> PathBuf { - builder - .ensure(ToolBuild { - compiler: self.compiler, - target: self.target, - tool: "remote-test-server", - mode: Mode::ToolStd, - path: "src/tools/remote-test-server", - is_optional_tool: false, - source_type: SourceType::InTree, - extra_features: Vec::new(), - allow_features: "", - }) - .expect("expected to build -- essential tool") + builder.ensure(ToolBuild { + compiler: self.compiler, + target: self.target, + tool: "remote-test-server", + mode: Mode::ToolStd, + path: "src/tools/remote-test-server", + source_type: SourceType::InTree, + extra_features: Vec::new(), + allow_features: "", + }) } } @@ -557,19 +544,16 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - let cargo_bin_path = builder - .ensure(ToolBuild { - compiler: self.compiler, - target: self.target, - tool: "cargo", - mode: Mode::ToolRustc, - path: "src/tools/cargo", - is_optional_tool: false, - source_type: SourceType::Submodule, - extra_features: Vec::new(), - allow_features: "", - }) - .expect("expected to build -- essential tool"); + let cargo_bin_path = builder.ensure(ToolBuild { + compiler: self.compiler, + target: self.target, + tool: "cargo", + mode: Mode::ToolRustc, + path: "src/tools/cargo", + source_type: SourceType::Submodule, + extra_features: Vec::new(), + allow_features: "", + }); cargo_bin_path } } @@ -588,19 +572,16 @@ impl Step for LldWrapper { } fn run(self, builder: &Builder<'_>) -> PathBuf { - let src_exe = builder - .ensure(ToolBuild { - compiler: self.compiler, - target: self.target, - tool: "lld-wrapper", - mode: Mode::ToolStd, - path: "src/tools/lld-wrapper", - is_optional_tool: false, - source_type: SourceType::InTree, - extra_features: Vec::new(), - allow_features: "", - }) - .expect("expected to build -- essential tool"); + let src_exe = builder.ensure(ToolBuild { + compiler: self.compiler, + target: self.target, + tool: "lld-wrapper", + mode: Mode::ToolStd, + path: "src/tools/lld-wrapper", + source_type: SourceType::InTree, + extra_features: Vec::new(), + allow_features: "", + }); src_exe } @@ -617,7 +598,7 @@ impl RustAnalyzer { } impl Step for RustAnalyzer { - type Output = Option<PathBuf>; + type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -640,7 +621,7 @@ impl Step for RustAnalyzer { }); } - fn run(self, builder: &Builder<'_>) -> Option<PathBuf> { + fn run(self, builder: &Builder<'_>) -> PathBuf { builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, @@ -648,7 +629,6 @@ impl Step for RustAnalyzer { mode: Mode::ToolRustc, path: "src/tools/rust-analyzer", extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()], - is_optional_tool: false, source_type: SourceType::InTree, allow_features: RustAnalyzer::ALLOW_FEATURES, }) @@ -696,10 +676,9 @@ impl Step for RustAnalyzerProcMacroSrv { mode: Mode::ToolStd, path: "src/tools/rust-analyzer/crates/proc-macro-srv-cli", extra_features: vec!["sysroot-abi".to_owned()], - is_optional_tool: false, source_type: SourceType::InTree, allow_features: RustAnalyzer::ALLOW_FEATURES, - })?; + }); // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/` // so that r-a can use it. @@ -730,7 +709,7 @@ macro_rules! tool_extended { } impl Step for $name { - type Output = Option<PathBuf>; + type Output = PathBuf; const DEFAULT: bool = true; // Overwritten below const ONLY_HOSTS: bool = true; @@ -761,7 +740,7 @@ macro_rules! tool_extended { } #[allow(unused_mut)] - fn run(mut $sel, $builder: &Builder<'_>) -> Option<PathBuf> { + fn run(mut $sel, $builder: &Builder<'_>) -> PathBuf { let tool = $builder.ensure(ToolBuild { compiler: $sel.compiler, target: $sel.target, @@ -769,10 +748,9 @@ macro_rules! tool_extended { mode: if false $(|| $tool_std)? { Mode::ToolStd } else { Mode::ToolRustc }, path: $path, extra_features: $sel.extra_features, - is_optional_tool: true, source_type: SourceType::InTree, allow_features: concat!($($allow_features)*), - })?; + }); if (false $(|| !$add_bins_to_sysroot.is_empty())?) && $sel.compiler.stage > 0 { let bindir = $builder.sysroot($sel.compiler).join("bin"); @@ -789,9 +767,9 @@ macro_rules! tool_extended { })? let tool = bindir.join(exe($tool_name, $sel.compiler.host)); - Some(tool) + tool } else { - Some(tool) + tool } } } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 753b41abaf4..e85753a3512 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1198,7 +1198,7 @@ impl<'a> Builder<'a> { let mut dylib_path = helpers::dylib_path(); dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); - let mut cmd = Command::new(cargo_clippy.unwrap()); + let mut cmd = Command::new(cargo_clippy); cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); cmd.env("PATH", path); cmd diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f1e1b89d9ba..c6bf71c8837 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -305,7 +305,7 @@ pub struct Config { pub save_toolstates: Option<PathBuf>, pub print_step_timings: bool, pub print_step_rusage: bool, - pub missing_tools: bool, + pub missing_tools: bool, // FIXME: Deprecated field. Remove it at 2024. // Fallback musl-root for all targets pub musl_root: Option<PathBuf>, @@ -1630,7 +1630,7 @@ impl Config { ); } - set(&mut config.llvm_tools_enabled, llvm_tools); + config.llvm_tools_enabled = llvm_tools.unwrap_or(true); config.rustc_parallel = parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly"); config.rustc_default_linker = default_linker; diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 1eadc036b5e..25efa5079c8 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -101,4 +101,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "rust-analyzer-proc-macro-srv is no longer enabled by default. To build it, you must either enable it in the configuration or explicitly invoke it with x.py.", }, + ChangeInfo { + change_id: 119373, + severity: ChangeSeverity::Info, + summary: "The dist.missing-tools config option was deprecated, as it was unused. If you are using it, remove it from your config, it will be removed soon.", + }, ]; diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile index b546f571f66..7081d9527f0 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile @@ -26,5 +26,5 @@ ENV \ ENV HOSTS=powerpc-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs +ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/run.sh b/src/ci/run.sh index 5700172fd3e..e48fac1a087 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -153,10 +153,6 @@ else fi fi -if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools" -fi - # Unless we're using an older version of LLVM, check that all LLVM components # used by tests are available. if [ "$IS_NOT_LATEST_LLVM" = "" ]; then diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index e824a1fd4bd..e6263db3283 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1805,11 +1805,20 @@ function initSearch(rawSearchIndex) { return unifyFunctionTypes([row], [elem], whereClause, mgens); } - function checkPath(contains, ty, maxEditDistance) { + /** + * Compute an "edit distance" that ignores missing path elements. + * @param {string[]} contains search query path + * @param {Row} ty indexed item + * @returns {null|number} edit distance + */ + function checkPath(contains, ty) { if (contains.length === 0) { return 0; } - let ret_dist = maxEditDistance + 1; + const maxPathEditDistance = Math.floor( + contains.reduce((acc, next) => acc + next.length, 0) / 3 + ); + let ret_dist = maxPathEditDistance + 1; const path = ty.path.split("::"); if (ty.parent && ty.parent.name) { @@ -1821,15 +1830,23 @@ function initSearch(rawSearchIndex) { pathiter: for (let i = length - clength; i >= 0; i -= 1) { let dist_total = 0; for (let x = 0; x < clength; ++x) { - const dist = editDistance(path[i + x], contains[x], maxEditDistance); - if (dist > maxEditDistance) { - continue pathiter; + const [p, c] = [path[i + x], contains[x]]; + if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance && + p.indexOf(c) !== -1 + ) { + // discount distance on substring match + dist_total += Math.floor((p.length - c.length) / 3); + } else { + const dist = editDistance(p, c, maxPathEditDistance); + if (dist > maxPathEditDistance) { + continue pathiter; + } + dist_total += dist; } - dist_total += dist; } ret_dist = Math.min(ret_dist, Math.round(dist_total / clength)); } - return ret_dist; + return ret_dist > maxPathEditDistance ? null : ret_dist; } function typePassesFilter(filter, type) { @@ -2030,8 +2047,8 @@ function initSearch(rawSearchIndex) { } if (elem.fullPath.length > 1) { - path_dist = checkPath(elem.pathWithoutLast, row, maxEditDistance); - if (path_dist > maxEditDistance) { + path_dist = checkPath(elem.pathWithoutLast, row); + if (path_dist === null) { return; } } @@ -2045,7 +2062,7 @@ function initSearch(rawSearchIndex) { const dist = editDistance(row.normalizedName, elem.normalizedPathLast, maxEditDistance); - if (index === -1 && dist + path_dist > maxEditDistance) { + if (index === -1 && dist > maxEditDistance) { return; } @@ -2100,13 +2117,9 @@ function initSearch(rawSearchIndex) { } function innerRunQuery() { - let queryLen = 0; - for (const elem of parsedQuery.elems) { - queryLen += elem.name.length; - } - for (const elem of parsedQuery.returned) { - queryLen += elem.name.length; - } + const queryLen = + parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) + + parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0); const maxEditDistance = Math.floor(queryLen / 3); /** diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 70aff7f60e0..f82421a687b 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,68 @@ document. ## Unreleased / Beta / In Rust Nightly -[7671c283...master](https://github.com/rust-lang/rust-clippy/compare/7671c283...master) +[09ac14c9...master](https://github.com/rust-lang/rust-clippy/compare/09ac14c9...master) + +## Rust 1.75 + +Current stable, released 2023-12-28 + +[View all 69 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-09-25T11%3A47%3A47Z..2023-11-02T16%3A41%3A59Z+base%3Amaster) + +### New Lints + +* [`unused_enumerate_index`] + [#10404](https://github.com/rust-lang/rust-clippy/pull/10404) +* [`unnecessary_fallible_conversions`] + [#11669](https://github.com/rust-lang/rust-clippy/pull/11669) +* [`waker_clone_wake`] + [#11698](https://github.com/rust-lang/rust-clippy/pull/11698) +* [`struct_field_names`] + [#11496](https://github.com/rust-lang/rust-clippy/pull/11496) +* [`into_iter_without_iter`] + [#11587](https://github.com/rust-lang/rust-clippy/pull/11587) +* [`iter_without_into_iter`] + [#11527](https://github.com/rust-lang/rust-clippy/pull/11527) +* [`manual_hash_one`] + [#11556](https://github.com/rust-lang/rust-clippy/pull/11556) + + +### Moves and Deprecations + +* Moved [`read_zero_byte_vec`] to `nursery` (Now allow-by-default) + [#11727](https://github.com/rust-lang/rust-clippy/pull/11727) +* Moved [`missing_enforced_import_renames`] to `style` (Now warn-by-default) + [#11539](https://github.com/rust-lang/rust-clippy/pull/11539) +* Moved [`needless_raw_string_hashes`] to `pedantic` (Now allow-by-default) + [#11415](https://github.com/rust-lang/rust-clippy/pull/11415) +* Moved [`needless_pass_by_ref_mut`] to `nursery` (Now allow-by-default) + [#11596](https://github.com/rust-lang/rust-clippy/pull/11596) + +### Enhancements + +* [`declare_interior_mutable_const`] and [`borrow_interior_mutable_const`]: Now check the + [`ignore-interior-mutability`] config value + [#11678](https://github.com/rust-lang/rust-clippy/pull/11678) + +### Suggestion Fixes/Improvements + +* [`items_after_test_module`]: The suggestion is now machine-applicable + [#11611](https://github.com/rust-lang/rust-clippy/pull/11611) + +### ICE Fixes + +* [`redundant_locals`]: No longer crashes if variables are rebound above macros + [#11623](https://github.com/rust-lang/rust-clippy/pull/11623) +* [`implicit_hasher`]: No longer lints inside macros, which could cause ICEs + [#11593](https://github.com/rust-lang/rust-clippy/pull/11593) + +### Documentation Improvements + +* `cargo clippy --help` now uses colors for readability :tada: ## Rust 1.74 -Current stable, released 2023-11-16 +Released 2023-11-16 [View all 94 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-08-11T15%3A29%3A18Z..2023-09-25T08%3A48%3A22Z+base%3Amaster) @@ -51,7 +108,7 @@ Current stable, released 2023-11-16 ### Enhancements * [`undocumented_unsafe_blocks`]: The config values [`accept-comment-above-statement`] and - [`accept-comment-above-attributes`] to `true` by default + [`accept-comment-above-attributes`] are now `true` by default [#11170](https://github.com/rust-lang/rust-clippy/pull/11170) * [`explicit_iter_loop`]: Added [`enforce-iter-loop-reborrow`] to disable reborrow linting by default [#11418](https://github.com/rust-lang/rust-clippy/pull/11418) @@ -5044,6 +5101,7 @@ Released 2018-09-13 [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec +[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum @@ -5177,6 +5235,8 @@ Released 2018-09-13 [`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module [`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect [`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count +[`iter_filter_is_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_filter_is_ok +[`iter_filter_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_filter_is_some [`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map [`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop [`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice @@ -5470,6 +5530,7 @@ Released 2018-09-13 [`reserve_after_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#reserve_after_initialization [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used +[`result_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_filter_map [`result_large_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err [`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn @@ -5582,6 +5643,7 @@ Released 2018-09-13 [`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_id_on_box [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction +[`unconditional_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#unconditional_recursion [`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks [`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops [`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index f6084a46272..eda20531e40 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.76" +version = "0.1.77" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 2bb89321cef..7c9a8eb1bfb 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -212,7 +212,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index 20f31320127..74b8e5eaa1c 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.76" +version = "0.1.77" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 3cf4377002a..a4f368397ce 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -27,7 +27,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", - "WebGL", + "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", @@ -640,7 +640,8 @@ impl Conf { } }, Err(error) => { - sess.dcx().err(format!("error finding Clippy's configuration file: {error}")); + sess.dcx() + .err(format!("error finding Clippy's configuration file: {error}")); }, } diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 13e61e5a032..471ad73e207 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -41,6 +41,7 @@ msrv_aliases! { 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } + 1,29,0 { ITER_FLATTEN } 1,28,0 { FROM_BOOL } 1,27,0 { ITERATOR_TRY_FOLD } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN } @@ -106,7 +107,8 @@ impl Msrv { if let Some(msrv_attr) = msrv_attrs.next() { if let Some(duplicate) = msrv_attrs.last() { - sess.dcx().struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") + sess.dcx() + .struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") .span_note(msrv_attr.span, "first definition found here") .emit(); } @@ -116,7 +118,8 @@ impl Msrv { return Some(version); } - sess.dcx().span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust version")); + sess.dcx() + .span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust version")); } else { sess.dcx().span_err(msrv_attr.span, "bad clippy attribute"); } diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index ad8b7ded46b..8cba35f3d87 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.76" +version = "0.1.77" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index a15ec199a28..1e327f7a6df 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -1,7 +1,7 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{constant_with_source, Constant, ConstantSource}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn}; -use rustc_hir::Expr; +use rustc_hir::{Expr, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -42,9 +42,18 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return; }; - let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { + let Some((Constant::Bool(val), source)) = constant_with_source(cx, cx.typeck_results(), condition) else { return; }; + if let ConstantSource::Constant = source + && let Some(node) = cx.tcx.hir().find_parent(e.hir_id) + && let Node::Item(Item { + kind: ItemKind::Const(..), + .. + }) = node + { + return; + } if val { span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index c965341d3fd..bb08ac7508b 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -2,9 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; -use rustc_hir::{ - Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, QPath, -}; +use rustc_hir::{Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 1220eb89013..eae9dfac064 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -369,6 +369,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::ITERATOR_STEP_BY_ZERO_INFO, crate::methods::ITER_CLONED_COLLECT_INFO, crate::methods::ITER_COUNT_INFO, + crate::methods::ITER_FILTER_IS_OK_INFO, + crate::methods::ITER_FILTER_IS_SOME_INFO, crate::methods::ITER_KV_MAP_INFO, crate::methods::ITER_NEXT_SLICE_INFO, crate::methods::ITER_NTH_INFO, @@ -419,6 +421,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::READ_LINE_WITHOUT_TRIM_INFO, crate::methods::REDUNDANT_AS_STR_INFO, crate::methods::REPEAT_ONCE_INFO, + crate::methods::RESULT_FILTER_MAP_INFO, crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO, crate::methods::SEARCH_IS_SOME_INFO, crate::methods::SEEK_FROM_CURRENT_INFO, @@ -650,6 +653,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO, crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO, crate::transmute::CROSSPOINTER_TRANSMUTE_INFO, + crate::transmute::EAGER_TRANSMUTE_INFO, crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO, crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO, crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO, @@ -676,6 +680,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::types::REDUNDANT_ALLOCATION_INFO, crate::types::TYPE_COMPLEXITY_INFO, crate::types::VEC_BOX_INFO, + crate::unconditional_recursion::UNCONDITIONAL_RECURSION_INFO, crate::undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS_INFO, crate::undocumented_unsafe_blocks::UNNECESSARY_SAFETY_COMMENT_INFO, crate::unicode::INVISIBLE_CHARACTERS_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs index 9ce5acfbcc2..71e1a25c2bc 100644 --- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs +++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs @@ -42,7 +42,7 @@ declare_clippy_lint! { #[clippy::version = "1.71.0"] pub DEFAULT_CONSTRUCTED_UNIT_STRUCTS, complexity, - "unit structs can be contructed without calling `default`" + "unit structs can be constructed without calling `default`" } declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]); diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs index 4cbfa97a8a3..26f120cb33f 100644 --- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs +++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs @@ -72,7 +72,7 @@ pub fn check( && let body = cx.tcx.hir().body(body_id) && let ret_ty = typeck.expr_ty(body.value) && implements_trait(cx, ret_ty, future, &[]) - && let ty::Coroutine(_, subs, _) = ret_ty.kind() + && let ty::Coroutine(_, subs) = ret_ty.kind() && is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result) { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs index 3901dd984f9..2b08437d827 100644 --- a/src/tools/clippy/clippy_lints/src/format_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs @@ -57,7 +57,7 @@ fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { Some(higher::IfLetOrMatch::Match(_, arms, MatchSource::Normal)) => { arms.iter().any(|arm| is_format(cx, arm.body)) }, - Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => { + Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else, _)) => { is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e)) }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 0f5a9ea5d84..fab8ffedb94 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -158,7 +158,7 @@ fn try_resolve_type<'tcx>( /// This function tries to, for all generic type parameters in a supertrait predicate `trait ...<U>: /// GenericTrait<U>`, check if the substituted type in the implied-by bound matches with what's -/// subtituted in the implied bound. +/// substituted in the implied bound. /// /// Consider this example. /// ```rust,ignore diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 0ae03d101ab..391db0b0df7 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -170,7 +170,23 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { return; } // Index is a constant uint. - if constant(cx, cx.typeck_results(), index).is_some() { + if let Some(constant) = constant(cx, cx.typeck_results(), index) { + // only `usize` index is legal in rust array index + // leave other type to rustc + if let Constant::Int(off) = constant + && let ty::Uint(utype) = cx.typeck_results().expr_ty(index).kind() + && *utype == ty::UintTy::Usize + && let ty::Array(_, s) = ty.kind() + && let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) + { + // get constant offset and check whether it is in bounds + let off = usize::try_from(off).unwrap(); + let size = usize::try_from(size).unwrap(); + + if off >= size { + span_lint(cx, OUT_OF_BOUNDS_INDEXING, expr.span, "index is out of bounds"); + } + } // Let rustc's `const_err` lint handle constant `usize` indexing on arrays. return; } diff --git a/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs b/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs index 955f90d4262..af5b1f95739 100644 --- a/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs +++ b/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs @@ -16,7 +16,7 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// `.append(true)` already enables `write(true)`, making this one - /// superflous. + /// superfluous. /// /// ### Example /// ```no_run diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 3a5756482a1..c9dc48668f2 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -49,7 +49,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.75.0"] pub ITER_WITHOUT_INTO_ITER, pedantic, "implementing `iter(_mut)` without an associated `IntoIterator for (&|&mut) Type` impl" @@ -101,7 +101,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.75.0"] pub INTO_ITER_WITHOUT_ITER, pedantic, "implementing `IntoIterator for (&|&mut) Type` without an inherent `iter(_mut)` method" diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 8c032b17023..c09d3d1862b 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -8,8 +8,8 @@ use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::{ AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, - ImplicitSelfKind, Item, ItemKind, Mutability, Node, PatKind, PathSegment, PrimTy, QPath, TraitItemRef, - TyKind, TypeBindingKind, OpaqueTyOrigin, + ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath, + TraitItemRef, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 7758d6a58e6..755a4ff525d 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -22,6 +22,7 @@ // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate pulldown_cmark; +extern crate rustc_abi; extern crate rustc_arena; extern crate rustc_ast; extern crate rustc_ast_pretty; @@ -327,6 +328,7 @@ mod trait_bounds; mod transmute; mod tuple_array_conversions; mod types; +mod unconditional_recursion; mod undocumented_unsafe_blocks; mod unicode; mod uninhabited_references; @@ -1078,6 +1080,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity)); store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences)); store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions)); + store.register_late_pass(|_| Box::new(unconditional_recursion::UnconditionalRecursion)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs index 9b88dd76e5c..5e099f1e76f 100644 --- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs @@ -49,7 +49,7 @@ pub(super) fn check<'tcx>( if let FnRetTy::DefaultReturn(ret_span) = parent_fn_ret { diag.span_suggestion( ret_span, - "if this is intentional, consider specifing `!` as function return", + "if this is intentional, consider specifying `!` as function return", " -> !", Applicability::MaybeIncorrect, ); diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs index a726b116956..36de9021f49 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs @@ -20,7 +20,7 @@ pub(super) fn check<'tcx>( span: Span, ) { let inner_expr = peel_blocks_with_stmt(body); - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None }) + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None, .. }) = higher::IfLet::hir(cx, inner_expr) // Ensure match_expr in `if let` statement is the same as the pat from the for-loop && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 21b9efba54c..d070ee74985 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -14,7 +14,7 @@ use rustc_span::symbol::sym; use rustc_span::Symbol; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr) + if let Some(higher::WhileLet { if_then, let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) // check for `Some(..)` pattern && let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome) diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 9ba1d3afcbe..4cd5f3b81e5 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -3,9 +3,9 @@ use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, Body, Closure, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, FnRetTy, - GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, - TypeBindingKind, ClosureKind, + Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, + FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, + TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -172,23 +172,13 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt)) } -fn desugared_async_block<'tcx>( - cx: &LateContext<'tcx>, - block: &'tcx Block<'tcx>, -) -> Option<&'tcx Body<'tcx>> { +fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { if let Some(Expr { - kind: - ExprKind::Closure(&Closure { - kind: - ClosureKind::Coroutine(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - CoroutineSource::Block, - )), - body, - .. - }), + kind: ExprKind::Closure(&Closure { kind, body, .. }), .. }) = block.expr + && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) = + kind { return Some(cx.tcx.hir().body(body)); } diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index 252b3a83a18..73687fbbe54 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { /// /// let hash = s.hash_one(&value); /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.75.0"] pub MANUAL_HASH_ONE, complexity, "manual implementations of `BuildHasher::hash_one`" diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 92dc4d57ab1..fdf8fa4e277 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -61,7 +61,7 @@ impl<'tcx> QuestionMark { && let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) { match if_let_or_match { - IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => { + IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else, ..) => { if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then) && let Some(if_else) = if_else && is_never_expr(cx, if_else).is_some() diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 48fc5746b3c..91e6ca7fa8b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -41,7 +41,7 @@ fn check_arm<'tcx>( let inner_expr = peel_blocks_with_stmt(outer_then_body); if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr) && let Some((inner_scrutinee, inner_then_pat, inner_else_body)) = match inner { - IfLetOrMatch::IfLet(scrutinee, pat, _, els) => Some((scrutinee, pat, els)), + IfLetOrMatch::IfLet(scrutinee, pat, _, els, _) => Some((scrutinee, pat, els)), IfLetOrMatch::Match(scrutinee, arms, ..) => if arms.len() == 2 && arms.iter().all(|a| a.guard.is_none()) // if there are more than two arms, collapsing would be non-trivial // one of the arms must be "wild-like" @@ -75,7 +75,7 @@ fn check_arm<'tcx>( ) // ...or anywhere in the inner expression && match inner { - IfLetOrMatch::IfLet(_, _, body, els) => { + IfLetOrMatch::IfLet(_, _, body, els, _) => { !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id)) }, IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)), diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 0627e458dfe..152aba99ce9 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -63,9 +63,7 @@ where return None; } - let Some(some_expr) = get_some_expr_fn(cx, some_pat, some_expr, expr_ctxt) else { - return None; - }; + let some_expr = get_some_expr_fn(cx, some_pat, some_expr, expr_ctxt)?; // These two lints will go back and forth with each other. if cx.typeck_results().expr_ty(some_expr.expr) == cx.tcx.types.unit diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 4c7568f39b4..50494f4819f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -469,15 +469,15 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Lint for redundant pattern matching over `Result`, `Option`, - /// `std::task::Poll` or `std::net::IpAddr` + /// `std::task::Poll`, `std::net::IpAddr` or `bool`s /// /// ### Why is this bad? /// It's more concise and clear to just use the proper - /// utility function + /// utility function or using the condition directly /// /// ### Known problems - /// This will change the drop order for the matched type. Both `if let` and - /// `while let` will drop the value at the end of the block, both `if` and `while` will drop the + /// For suggestions involving bindings in patterns, this will change the drop order for the matched type. + /// Both `if let` and `while let` will drop the value at the end of the block, both `if` and `while` will drop the /// value before entering the block. For most types this change will not matter, but for a few /// types this will not be an acceptable change (e.g. locks). See the /// [reference](https://doc.rust-lang.org/reference/destructors.html#drop-scopes) for more about @@ -499,6 +499,10 @@ declare_clippy_lint! { /// Ok(_) => true, /// Err(_) => false, /// }; + /// + /// let cond = true; + /// if let true = cond {} + /// matches!(cond, true); /// ``` /// /// The more idiomatic use would be: @@ -515,6 +519,10 @@ declare_clippy_lint! { /// if IpAddr::V4(Ipv4Addr::LOCALHOST).is_ipv4() {} /// if IpAddr::V6(Ipv6Addr::LOCALHOST).is_ipv6() {} /// Ok::<i32, i32>(42).is_ok(); + /// + /// let cond = true; + /// if cond {} + /// cond; /// ``` #[clippy::version = "1.31.0"] pub REDUNDANT_PATTERN_MATCHING, @@ -1019,8 +1027,11 @@ impl<'tcx> LateLintPass<'tcx> for Matches { let from_expansion = expr.span.from_expansion(); if let ExprKind::Match(ex, arms, source) = expr.kind { - if is_direct_expn_of(expr.span, "matches").is_some() { + if is_direct_expn_of(expr.span, "matches").is_some() + && let [arm, _] = arms + { redundant_pattern_match::check_match(cx, expr, ex, arms); + redundant_pattern_match::check_matches_true(cx, expr, arm, ex); } if source == MatchSource::Normal && !is_span_match(cx, expr.span) { @@ -1104,6 +1115,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if_let.let_pat, if_let.let_expr, if_let.if_else.is_some(), + if_let.let_span, ); needless_match::check_if_let(cx, expr, &if_let); } diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 2582f7edcf6..a4acdfb1db4 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -1,7 +1,7 @@ use super::REDUNDANT_PATTERN_MATCHING; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, walk_span_to_context}; -use clippy_utils::sugg::Sugg; +use clippy_utils::sugg::{make_unop, Sugg}; use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop}; use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr}; use clippy_utils::{higher, is_expn_of, is_trait_method}; @@ -12,13 +12,20 @@ use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, use rustc_hir::{Arm, Expr, ExprKind, Guard, Node, Pat, PatKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::{self, GenericArgKind, Ty}; -use rustc_span::{sym, Symbol}; +use rustc_span::{sym, Span, Symbol}; use std::fmt::Write; use std::ops::ControlFlow; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) { - find_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false); + if let Some(higher::WhileLet { + let_pat, + let_expr, + let_span, + .. + }) = higher::WhileLet::hir(expr) + { + find_method_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false); + find_if_let_true(cx, let_pat, let_expr, let_span); } } @@ -28,8 +35,73 @@ pub(super) fn check_if_let<'tcx>( pat: &'tcx Pat<'_>, scrutinee: &'tcx Expr<'_>, has_else: bool, + let_span: Span, +) { + find_if_let_true(cx, pat, scrutinee, let_span); + find_method_sugg_for_if_let(cx, expr, pat, scrutinee, "if", has_else); +} + +/// Looks for: +/// * `matches!(expr, true)` +pub fn check_matches_true<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + arm: &'tcx Arm<'_>, + scrutinee: &'tcx Expr<'_>, +) { + find_match_true( + cx, + arm.pat, + scrutinee, + expr.span.source_callsite(), + "using `matches!` to pattern match a bool", + ); +} + +/// Looks for any of: +/// * `if let true = ...` +/// * `if let false = ...` +/// * `while let true = ...` +fn find_if_let_true<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, scrutinee: &'tcx Expr<'_>, let_span: Span) { + find_match_true(cx, pat, scrutinee, let_span, "using `if let` to pattern match a bool"); +} + +/// Common logic between `find_if_let_true` and `check_matches_true` +fn find_match_true<'tcx>( + cx: &LateContext<'tcx>, + pat: &'tcx Pat<'_>, + scrutinee: &'tcx Expr<'_>, + span: Span, + message: &str, ) { - find_sugg_for_if_let(cx, expr, pat, scrutinee, "if", has_else); + if let PatKind::Lit(lit) = pat.kind + && let ExprKind::Lit(lit) = lit.kind + && let LitKind::Bool(pat_is_true) = lit.node + { + let mut applicability = Applicability::MachineApplicable; + + let mut sugg = Sugg::hir_with_context( + cx, + scrutinee, + scrutinee.span.source_callsite().ctxt(), + "..", + &mut applicability, + ); + + if !pat_is_true { + sugg = make_unop("!", sugg); + } + + span_lint_and_sugg( + cx, + REDUNDANT_PATTERN_MATCHING, + span, + message, + "consider using the condition directly", + sugg.to_string(), + applicability, + ); + } } // Extract the generic arguments out of a type @@ -56,9 +128,7 @@ fn find_method_and_type<'tcx>( if is_wildcard || is_rest { let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id); - let Some(id) = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) else { - return None; - }; + let id = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id))?; let lang_items = cx.tcx.lang_items(); if Some(id) == lang_items.result_ok_variant() { Some(("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty))) @@ -100,7 +170,7 @@ fn find_method_and_type<'tcx>( } } -fn find_sugg_for_if_let<'tcx>( +fn find_method_sugg_for_if_let<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, let_pat: &Pat<'_>, @@ -341,31 +411,25 @@ fn get_good_method<'tcx>( path_left: &QPath<'_>, ) -> Option<(&'static str, Option<&'tcx Guard<'tcx>>)> { if let Some(name) = get_ident(path_left) { - return match name.as_str() { - "Ok" => { - find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultOk), "is_ok()", "is_err()") - }, - "Err" => { - find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultErr), "is_err()", "is_ok()") - }, - "Some" => find_good_method_for_matches_macro( - cx, - arms, - path_left, - Item::Lang(OptionSome), - "is_some()", - "is_none()", - ), - "None" => find_good_method_for_matches_macro( - cx, - arms, - path_left, - Item::Lang(OptionNone), - "is_none()", - "is_some()", - ), - _ => None, + let (expected_item_left, should_be_left, should_be_right) = match name.as_str() { + "Ok" => (Item::Lang(ResultOk), "is_ok()", "is_err()"), + "Err" => (Item::Lang(ResultErr), "is_err()", "is_ok()"), + "Some" => (Item::Lang(OptionSome), "is_some()", "is_none()"), + "None" => (Item::Lang(OptionNone), "is_none()", "is_some()"), + "Ready" => (Item::Lang(PollReady), "is_ready()", "is_pending()"), + "Pending" => (Item::Lang(PollPending), "is_pending()", "is_ready()"), + "V4" => (Item::Diag(sym::IpAddr, sym!(V4)), "is_ipv4()", "is_ipv6()"), + "V6" => (Item::Diag(sym::IpAddr, sym!(V6)), "is_ipv6()", "is_ipv4()"), + _ => return None, }; + return find_good_method_for_matches_macro( + cx, + arms, + path_left, + expected_item_left, + should_be_left, + should_be_right, + ); } None } diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 844ab40cab1..7cfd3d346b6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -14,7 +14,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use std::borrow::Cow; -use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP}; +use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP}; fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { match &expr.kind { @@ -22,6 +22,7 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> hir::ExprKind::Path(QPath::Resolved(_, segments)) => { segments.segments.last().unwrap().ident.name == method_name }, + hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(body.value); @@ -46,6 +47,9 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool { is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some)) } +fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool { + is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_ok)) +} #[derive(Debug, Copy, Clone)] enum OffendingFilterExpr<'tcx> { @@ -186,7 +190,7 @@ impl<'tcx> OffendingFilterExpr<'tcx> { match higher::IfLetOrMatch::parse(cx, map_body.value) { // For `if let` we want to check that the variant matching arm references the local created by // its pattern - Some(higher::IfLetOrMatch::IfLet(sc, pat, then, Some(else_))) + Some(higher::IfLetOrMatch::IfLet(sc, pat, then, Some(else_), ..)) if let Some((ident, span)) = expr_uses_local(pat, then) => { (sc, else_, ident, span) @@ -273,6 +277,18 @@ fn is_filter_some_map_unwrap( (iterator || option) && is_option_filter_map(cx, filter_arg, map_arg) } +/// is `filter(|x| x.is_ok()).map(|x| x.unwrap())` +fn is_filter_ok_map_unwrap( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + filter_arg: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, +) -> bool { + // result has no filter, so we only check for iterators + let iterator = is_trait_method(cx, expr, sym::Iterator); + iterator && is_ok_filter_map(cx, filter_arg, map_arg) +} + /// lint use of `filter().map()` or `find().map()` for `Iterators` #[allow(clippy::too_many_arguments)] pub(super) fn check( @@ -300,30 +316,21 @@ pub(super) fn check( return; } - if is_trait_method(cx, map_recv, sym::Iterator) - - // filter(|x| ...is_some())... - && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind - && let filter_body = cx.tcx.hir().body(filter_body_id) - && let [filter_param] = filter_body.params - // optional ref pattern: `filter(|&x| ..)` - && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { - (ref_pat, true) - } else { - (filter_param.pat, false) - } - - && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind - && let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id) + if is_filter_ok_map_unwrap(cx, expr, filter_arg, map_arg) { + span_lint_and_sugg( + cx, + RESULT_FILTER_MAP, + filter_span.with_hi(expr.span.hi()), + "`filter` for `Ok` followed by `unwrap`", + "consider using `flatten` instead", + reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, map_span)).into_owned(), + Applicability::MachineApplicable, + ); - && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind - && let map_body = cx.tcx.hir().body(map_body_id) - && let [map_param] = map_body.params - && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind + return; + } - && let Some(check_result) = - offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref) - { + if let Some((map_param_ident, check_result)) = is_find_or_filter(cx, map_recv, filter_arg, map_arg) { let span = filter_span.with_hi(expr.span.hi()); let (filter_name, lint) = if is_find { ("find", MANUAL_FIND_MAP) @@ -395,6 +402,40 @@ pub(super) fn check( } } +fn is_find_or_filter<'a>( + cx: &LateContext<'a>, + map_recv: &hir::Expr<'_>, + filter_arg: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, +) -> Option<(Ident, CheckResult<'a>)> { + if is_trait_method(cx, map_recv, sym::Iterator) + // filter(|x| ...is_some())... + && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind + && let filter_body = cx.tcx.hir().body(filter_body_id) + && let [filter_param] = filter_body.params + // optional ref pattern: `filter(|&x| ..)` + && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { + (ref_pat, true) + } else { + (filter_param.pat, false) + } + + && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind + && let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id) + + && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind + && let map_body = cx.tcx.hir().body(map_body_id) + && let [map_param] = map_body.params + && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind + + && let Some(check_result) = + offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref) + { + return Some((map_param_ident, check_result)); + } + None +} + fn acceptable_methods(method: &PathSegment<'_>) -> bool { let methods: [Symbol; 8] = [ sym::clone, diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs new file mode 100644 index 00000000000..ade8e3155fa --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs @@ -0,0 +1,87 @@ +use rustc_lint::{LateContext, LintContext}; + +use super::{ITER_FILTER_IS_OK, ITER_FILTER_IS_SOME}; + +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{indent_of, reindent_multiline}; +use clippy_utils::{is_trait_method, peel_blocks, span_contains_comment}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::QPath; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; +use std::borrow::Cow; + +fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { + match &expr.kind { + hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, + hir::ExprKind::Path(QPath::Resolved(_, segments)) => { + segments.segments.last().unwrap().ident.name == method_name + }, + hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, + hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + let body = cx.tcx.hir().body(body); + let closure_expr = peel_blocks(body.value); + let arg_id = body.params[0].pat.hir_id; + match closure_expr.kind { + hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { + if ident.name == method_name + && let hir::ExprKind::Path(path) = &receiver.kind + && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) + { + return arg_id == *local; + } + false + }, + _ => false, + } + }, + _ => false, + } +} + +fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + if let hir::Node::Expr(parent_expr) = cx.tcx.hir().get_parent(expr.hir_id) { + is_method(cx, parent_expr, rustc_span::sym::map) + } else { + false + } +} + +#[allow(clippy::too_many_arguments)] +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir::Expr<'_>, filter_span: Span) { + let is_iterator = is_trait_method(cx, expr, sym::Iterator); + let parent_is_not_map = !parent_is_map(cx, expr); + + if is_iterator + && parent_is_not_map + && is_method(cx, filter_arg, sym!(is_some)) + && !span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi())) + { + span_lint_and_sugg( + cx, + ITER_FILTER_IS_SOME, + filter_span.with_hi(expr.span.hi()), + "`filter` for `is_some` on iterator over `Option`", + "consider using `flatten` instead", + reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(), + Applicability::HasPlaceholders, + ); + } + if is_iterator + && parent_is_not_map + && is_method(cx, filter_arg, sym!(is_ok)) + && !span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi())) + { + span_lint_and_sugg( + cx, + ITER_FILTER_IS_OK, + filter_span.with_hi(expr.span.hi()), + "`filter` for `is_ok` on iterator over `Result`s", + "consider using `flatten` instead", + reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(), + Applicability::HasPlaceholders, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index b4f60ffadd7..25b1ea526e2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -38,6 +38,7 @@ mod into_iter_on_ref; mod is_digit_ascii_radix; mod iter_cloned_collect; mod iter_count; +mod iter_filter; mod iter_kv_map; mod iter_next_slice; mod iter_nth; @@ -1175,7 +1176,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for indirect collection of populated `Option` + /// Checks for iterators of `Option`s using `.filter(Option::is_some).map(Option::unwrap)` that may + /// be replaced with a `.flatten()` call. /// /// ### Why is this bad? /// `Option` is like a collection of 0-1 things, so `flatten` @@ -3752,6 +3754,81 @@ declare_clippy_lint! { "using `Option.map_or(Err(_), Ok)`, which is more succinctly expressed as `Option.ok_or(_)`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for iterators of `Result`s using `.filter(Result::is_ok).map(Result::unwrap)` that may + /// be replaced with a `.flatten()` call. + /// + /// ### Why is this bad? + /// `Result` implements `IntoIterator<Item = T>`. This means that `Result` can be flattened + /// automatically without suspicious-looking `unwrap` calls. + /// + /// ### Example + /// ```no_run + /// let _ = std::iter::empty::<Result<i32, ()>>().filter(Result::is_ok).map(Result::unwrap); + /// ``` + /// Use instead: + /// ```no_run + /// let _ = std::iter::empty::<Result<i32, ()>>().flatten(); + /// ``` + #[clippy::version = "1.76.0"] + pub RESULT_FILTER_MAP, + complexity, + "filtering `Result` for `Ok` then force-unwrapping, which can be one type-safe operation" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `.filter(Option::is_some)` that may be replaced with a `.flatten()` call. + /// This lint will require additional changes to the follow-up calls as it appects the type. + /// + /// ### Why is this bad? + /// This pattern is often followed by manual unwrapping of the `Option`. The simplification + /// results in more readable and succint code without the need for manual unwrapping. + /// + /// ### Example + /// ```no_run + /// // example code where clippy issues a warning + /// vec![Some(1)].into_iter().filter(Option::is_some); + /// + /// ``` + /// Use instead: + /// ```no_run + /// // example code which does not raise clippy warning + /// vec![Some(1)].into_iter().flatten(); + /// ``` + #[clippy::version = "1.76.0"] + pub ITER_FILTER_IS_SOME, + pedantic, + "filtering an iterator over `Option`s for `Some` can be achieved with `flatten`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `.filter(Result::is_ok)` that may be replaced with a `.flatten()` call. + /// This lint will require additional changes to the follow-up calls as it appects the type. + /// + /// ### Why is this bad? + /// This pattern is often followed by manual unwrapping of `Result`. The simplification + /// results in more readable and succint code without the need for manual unwrapping. + /// + /// ### Example + /// ```no_run + /// // example code where clippy issues a warning + /// vec![Ok::<i32, String>(1)].into_iter().filter(Result::is_ok); + /// + /// ``` + /// Use instead: + /// ```no_run + /// // example code which does not raise clippy warning + /// vec![Ok::<i32, String>(1)].into_iter().flatten(); + /// ``` + #[clippy::version = "1.76.0"] + pub ITER_FILTER_IS_OK, + pedantic, + "filtering an iterator over `Result`s for `Ok` can be achieved with `flatten`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3903,6 +3980,9 @@ impl_lint_pass!(Methods => [ UNNECESSARY_FALLIBLE_CONVERSIONS, JOIN_ABSOLUTE_PATHS, OPTION_MAP_OR_ERR_OK, + RESULT_FILTER_MAP, + ITER_FILTER_IS_SOME, + ITER_FILTER_IS_OK, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4232,7 +4312,24 @@ impl Methods { string_extend_chars::check(cx, expr, recv, arg); extend_with_drain::check(cx, expr, recv, arg); }, - (name @ ("filter" | "find"), [arg]) => { + ("filter", [arg]) => { + if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) { + // if `arg` has side-effect, the semantic will change + iter_overeager_cloned::check( + cx, + expr, + recv, + recv2, + iter_overeager_cloned::Op::FixClosure(name, arg), + false, + ); + } + if self.msrv.meets(msrvs::ITER_FLATTEN) { + // use the sourcemap to get the span of the closure + iter_filter::check(cx, expr, arg, span); + } + }, + ("find", [arg]) => { if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) { // if `arg` has side-effect, the semantic will change iter_overeager_cloned::check( diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index c4775b6bd04..637368e9361 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -7,6 +7,7 @@ use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, Node}; use rustc_hir_typeck::{FnCtxt, Inherited}; @@ -37,6 +38,9 @@ pub fn check<'tcx>( if is_cloned_or_copied(cx, method_name, method_def_id) { unnecessary_iter_cloned::check(cx, expr, method_name, receiver); } else if is_to_owned_like(cx, expr, method_name, method_def_id) { + if check_split_call_arg(cx, expr, method_name, receiver) { + return; + } // At this point, we know the call is of a `to_owned`-like function. The functions // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary // based on its context, that is, whether it is a referent in an `AddrOf` expression, an @@ -233,6 +237,58 @@ fn check_into_iter_call_arg( false } +/// Checks whether `expr` is an argument in an `into_iter` call and, if so, determines whether its +/// call of a `to_owned`-like function is unnecessary. +fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>) -> bool { + if let Some(parent) = get_parent_expr(cx, expr) + && let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent) + && fn_name.as_str() == "split" + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(arg_snippet) = snippet_opt(cx, argument_expr.span) + { + // The next suggestion may be incorrect because the removal of the `to_owned`-like + // function could cause the iterator to hold a reference to a resource that is used + // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148. + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + parent.span, + &format!("unnecessary use of `{method_name}`"), + "use", + format!("{receiver_snippet}.split({arg_snippet})"), + Applicability::MaybeIncorrect, + ); + return true; + } + false +} + +fn get_fn_name_and_arg<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(Symbol, Expr<'tcx>)> { + match &expr.kind { + ExprKind::MethodCall(path, _, [arg_expr], ..) => Some((path.ident.name, *arg_expr)), + ExprKind::Call( + Expr { + kind: ExprKind::Path(qpath), + hir_id: path_hir_id, + .. + }, + [arg_expr], + ) => { + // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or + // deref to fn pointers, dyn Fn, impl Fn - #8850 + if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, def_id) = + cx.typeck_results().qpath_res(qpath, *path_hir_id) + && let Some(fn_name) = cx.tcx.opt_item_name(def_id) + { + Some((fn_name, *arg_expr)) + } else { + None + } + }, + _ => None, + } +} + /// Checks whether `expr` is an argument in a function call and, if so, determines whether its call /// of a `to_owned`-like function is unnecessary. fn check_other_call_arg<'tcx>( diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 218ca5e80f3..bf27adb45af 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -340,6 +340,12 @@ fn check_comparison<'a, 'tcx>( } if l_ty.is_bool() && r_ty.is_bool() { let mut applicability = Applicability::MachineApplicable; + // Eliminate parentheses in `e` by using the lo pos of lhs and hi pos of rhs, + // calling `source_callsite` make sure macros are handled correctly, see issue #9907 + let binop_span = left_side + .span + .source_callsite() + .with_hi(right_side.span.source_callsite().hi()); if op.node == BinOpKind::Eq { let expression_info = one_side_is_unary_not(left_side, right_side); @@ -347,13 +353,23 @@ fn check_comparison<'a, 'tcx>( span_lint_and_sugg( cx, BOOL_COMPARISON, - e.span, + binop_span, "this comparison might be written more concisely", "try simplifying it as shown", format!( "{} != {}", - snippet_with_applicability(cx, expression_info.left_span, "..", &mut applicability), - snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability) + snippet_with_applicability( + cx, + expression_info.left_span.source_callsite(), + "..", + &mut applicability + ), + snippet_with_applicability( + cx, + expression_info.right_span.source_callsite(), + "..", + &mut applicability + ) ), applicability, ); @@ -362,16 +378,16 @@ fn check_comparison<'a, 'tcx>( match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Some(true), None) => left_true.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, right_side, applicability, m, h); + suggest_bool_comparison(cx, binop_span, right_side, applicability, m, h); }), (None, Some(true)) => right_true.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, left_side, applicability, m, h); + suggest_bool_comparison(cx, binop_span, left_side, applicability, m, h); }), (Some(false), None) => left_false.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, right_side, applicability, m, h); + suggest_bool_comparison(cx, binop_span, right_side, applicability, m, h); }), (None, Some(false)) => right_false.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, left_side, applicability, m, h); + suggest_bool_comparison(cx, binop_span, left_side, applicability, m, h); }), (None, None) => no_literal.map_or((), |(h, m)| { let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability); @@ -379,7 +395,7 @@ fn check_comparison<'a, 'tcx>( span_lint_and_sugg( cx, BOOL_COMPARISON, - e.span, + binop_span, m, "try simplifying it as shown", h(left_side, right_side).to_string(), @@ -394,17 +410,17 @@ fn check_comparison<'a, 'tcx>( fn suggest_bool_comparison<'a, 'tcx>( cx: &LateContext<'tcx>, - e: &'tcx Expr<'_>, + span: Span, expr: &Expr<'_>, mut app: Applicability, message: &str, conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>, ) { - let hint = Sugg::hir_with_context(cx, expr, e.span.ctxt(), "..", &mut app); + let hint = Sugg::hir_with_context(cx, expr, span.ctxt(), "..", &mut app); span_lint_and_sugg( cx, BOOL_COMPARISON, - e.span, + span, message, "try simplifying it as shown", conv_hint(hint).to_string(), diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs index 89e4e3c740d..556c493d36c 100644 --- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs @@ -238,6 +238,7 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> let_expr, if_then, if_else: Some(if_else), + .. }) = higher::IfLet::hir(cx, expr) && !cx.typeck_results().expr_ty(expr).is_unit() && !is_else_clause(cx.tcx, expr) diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index fc5835408a9..509d9483e1d 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -8,7 +8,7 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ eq_expr_value, get_parent_node, higher, in_constant, is_else_clause, is_lint_allowed, is_path_lang_item, is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, - peel_blocks_with_stmt, + peel_blocks_with_stmt, span_contains_comment, }; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -96,6 +96,24 @@ enum IfBlockType<'hir> { ), } +fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir Expr<'hir>> { + if let Block { + stmts: &[], + expr: Some(els), + .. + } = block + { + Some(els) + } else if let [stmt] = block.stmts + && let StmtKind::Semi(expr) = stmt.kind + && let ExprKind::Ret(..) = expr.kind + { + Some(expr) + } else { + None + } +} + fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { if let StmtKind::Local(Local { pat, @@ -103,12 +121,9 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { els: Some(els), .. }) = stmt.kind - && let Block { - stmts: &[], - expr: Some(els), - .. - } = els - && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, els) + && let Some(ret) = find_let_else_ret_expression(els) + && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, ret) + && !span_contains_comment(cx.tcx.sess.source_map(), els.span) { let mut applicability = Applicability::MaybeIncorrect; let init_expr_str = snippet_with_applicability(cx, init_expr.span, "..", &mut applicability); @@ -256,6 +271,7 @@ impl QuestionMark { let_expr, if_then, if_else, + .. }) = higher::IfLet::hir(cx, expr) && !is_else_clause(cx.tcx, expr) && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index b50141f048c..0ed957f1f2f 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -3,9 +3,12 @@ use std::ops::ControlFlow; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, walk_span_to_context}; +use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr; use rustc_errors::Applicability; -use rustc_hir::{Closure, ClosureKind, CoroutineKind, CoroutineSource, CoroutineDesugaring, Expr, ExprKind, MatchSource}; +use rustc_hir::{ + Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; @@ -49,6 +52,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. expr.span.eq_ctxt(body_expr.span) && + // The await prefix must implement Future, as implementing IntoFuture is not enough. + let Some(future_trait) = cx.tcx.lang_items().future_trait() && + implements_trait(cx, cx.typeck_results().expr_ty(expr), future_trait, &[]) && // An async block does not have immediate side-effects from a `.await` point-of-view. (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) @@ -71,7 +77,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if let ExprKind::Closure(Closure { body, def_id, kind, .. }) = expr.kind && let body = cx.tcx.hir().body(*body) - && matches!(kind, ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block))) + && matches!( + kind, + ClosureKind::Coroutine(CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Block + )) + ) { cx.typeck_results() .closure_min_captures diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 16c929edb92..cde08dfcc74 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, CoroutineDesugaring, Node, ClosureKind}; +use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -66,7 +66,8 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor { fn is_async_closure(body: &hir::Body<'_>) -> bool { if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind // checks whether it is `async || whatever_expression` - && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) = innermost_closure_generated_by_desugar.kind + && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) + = innermost_closure_generated_by_desugar.kind { true } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs new file mode 100644 index 00000000000..01a23c515f5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs @@ -0,0 +1,74 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_normalizable; +use clippy_utils::{path_to_local, path_to_local_id}; +use rustc_abi::WrappingRange; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Node}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; + +use super::EAGER_TRANSMUTE; + +fn peel_parent_unsafe_blocks<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + for (_, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + match parent { + Node::Block(_) => {}, + Node::Expr(e) if let ExprKind::Block(..) = e.kind => {}, + Node::Expr(e) => return Some(e), + _ => break, + } + } + None +} + +fn range_fully_contained(from: WrappingRange, to: WrappingRange) -> bool { + to.contains(from.start) && to.contains(from.end) +} + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + transmutable: &'tcx Expr<'tcx>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, +) -> bool { + if let Some(then_some_call) = peel_parent_unsafe_blocks(cx, expr) + && let ExprKind::MethodCall(path, receiver, [arg], _) = then_some_call.kind + && cx.typeck_results().expr_ty(receiver).is_bool() + && path.ident.name == sym!(then_some) + && let ExprKind::Binary(_, lhs, rhs) = receiver.kind + && let Some(local_id) = path_to_local(transmutable) + && (path_to_local_id(lhs, local_id) || path_to_local_id(rhs, local_id)) + && is_normalizable(cx, cx.param_env, from_ty) + && is_normalizable(cx, cx.param_env, to_ty) + // we only want to lint if the target type has a niche that is larger than the one of the source type + // e.g. `u8` to `NonZeroU8` should lint, but `NonZeroU8` to `u8` should not + && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty)) + && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty)) + && match (from_layout.largest_niche, to_layout.largest_niche) { + (Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range), + (None, Some(_)) => true, + (_, None) => false, + } + { + span_lint_and_then( + cx, + EAGER_TRANSMUTE, + expr.span, + "this transmute is always evaluated eagerly, even if the condition is false", + |diag| { + diag.multipart_suggestion( + "consider using `bool::then` to only transmute if the condition holds", + vec![ + (path.ident.span, "then".into()), + (arg.span.shrink_to_lo(), "|| ".into()), + ], + Applicability::MaybeIncorrect, + ); + }, + ); + true + } else { + false + } +} diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 95a92afea66..06de7a11031 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -1,4 +1,5 @@ mod crosspointer_transmute; +mod eager_transmute; mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; @@ -463,6 +464,62 @@ declare_clippy_lint! { "transmute results in a null function pointer, which is undefined behavior" } +declare_clippy_lint! { + /// ### What it does + /// Checks for integer validity checks, followed by a transmute that is (incorrectly) evaluated + /// eagerly (e.g. using `bool::then_some`). + /// + /// ### Why is this bad? + /// Eager evaluation means that the `transmute` call is executed regardless of whether the condition is true or false. + /// This can introduce unsoundness and other subtle bugs. + /// + /// ### Example + /// Consider the following function which is meant to convert an unsigned integer to its enum equivalent via transmute. + /// + /// ```no_run + /// #[repr(u8)] + /// enum Opcode { + /// Add = 0, + /// Sub = 1, + /// Mul = 2, + /// Div = 3 + /// } + /// + /// fn int_to_opcode(op: u8) -> Option<Opcode> { + /// (op < 4).then_some(unsafe { std::mem::transmute(op) }) + /// } + /// ``` + /// This may appear fine at first given that it checks that the `u8` is within the validity range of the enum, + /// *however* the transmute is evaluated eagerly, meaning that it executes even if `op >= 4`! + /// + /// This makes the function unsound, because it is possible for the caller to cause undefined behavior + /// (creating an enum with an invalid bitpattern) entirely in safe code only by passing an incorrect value, + /// which is normally only a bug that is possible in unsafe code. + /// + /// One possible way in which this can go wrong practically is that the compiler sees it as: + /// ```rust,ignore (illustrative) + /// let temp: Foo = unsafe { std::mem::transmute(op) }; + /// (0 < 4).then_some(temp) + /// ``` + /// and optimizes away the `(0 < 4)` check based on the assumption that since a `Foo` was created from `op` with the validity range `0..3`, + /// it is **impossible** for this condition to be false. + /// + /// In short, it is possible for this function to be optimized in a way that makes it [never return `None`](https://godbolt.org/z/ocrcenevq), + /// even if passed the value `4`. + /// + /// This can be avoided by instead using lazy evaluation. For the example above, this should be written: + /// ```rust,ignore (illustrative) + /// fn int_to_opcode(op: u8) -> Option<Opcode> { + /// (op < 4).then(|| unsafe { std::mem::transmute(op) }) + /// ^^^^ ^^ `bool::then` only executes the closure if the condition is true! + /// } + /// ``` + #[clippy::version = "1.76.0"] + pub EAGER_TRANSMUTE, + correctness, + "eager evaluation of `transmute`" +} + pub struct Transmute { msrv: Msrv, } @@ -484,6 +541,7 @@ impl_lint_pass!(Transmute => [ TRANSMUTE_UNDEFINED_REPR, TRANSMUTING_NULL, TRANSMUTE_NULL_TO_FN, + EAGER_TRANSMUTE, ]); impl Transmute { #[must_use] @@ -530,7 +588,8 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) | (unsound_collection_transmute::check(cx, e, from_ty, to_ty) - || transmute_undefined_repr::check(cx, e, from_ty, to_ty)); + || transmute_undefined_repr::check(cx, e, from_ty, to_ty)) + | (eager_transmute::check(cx, e, arg, from_ty, to_ty)); if !linted { transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg); diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs new file mode 100644 index 00000000000..b1fa30aa068 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -0,0 +1,134 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{get_trait_def_id, path_res}; +use rustc_ast::BinOpKind; +use rustc_hir::def::Res; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, Item, ItemKind, Node}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; +use rustc_session::declare_lint_pass; +use rustc_span::{sym, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Checks that there isn't an infinite recursion in `PartialEq` trait + /// implementation. + /// + /// ### Why is this bad? + /// This is a hard to find infinite recursion which will crashing any code + /// using it. + /// + /// ### Example + /// ```no_run + /// enum Foo { + /// A, + /// B, + /// } + /// + /// impl PartialEq for Foo { + /// fn eq(&self, other: &Self) -> bool { + /// self == other // bad! + /// } + /// } + /// ``` + /// Use instead: + /// + /// In such cases, either use `#[derive(PartialEq)]` or don't implement it. + #[clippy::version = "1.76.0"] + pub UNCONDITIONAL_RECURSION, + suspicious, + "detect unconditional recursion in some traits implementation" +} + +declare_lint_pass!(UnconditionalRecursion => [UNCONDITIONAL_RECURSION]); + +fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> { + match ty.peel_refs().kind() { + ty::Adt(adt, _) => Some(adt.did()), + ty::Foreign(def_id) => Some(*def_id), + _ => None, + } +} + +fn is_local(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!(path_res(cx, expr), Res::Local(_)) +} + +impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion { + #[allow(clippy::unnecessary_def_path)] + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _decl: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + method_span: Span, + def_id: LocalDefId, + ) { + // If the function is a method... + if let FnKind::Method(name, _) = kind + // That has two arguments. + && let [self_arg, other_arg] = cx + .tcx + .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder()) + .inputs() + && let Some(self_arg) = get_ty_def_id(*self_arg) + && let Some(other_arg) = get_ty_def_id(*other_arg) + // The two arguments are of the same type. + && self_arg == other_arg + && let hir_id = cx.tcx.local_def_id_to_hir_id(def_id) + && let Some(( + _, + Node::Item(Item { + kind: ItemKind::Impl(impl_), + owner_id, + .. + }), + )) = cx.tcx.hir().parent_iter(hir_id).next() + // We exclude `impl` blocks generated from rustc's proc macros. + && !cx.tcx.has_attr(*owner_id, sym::automatically_derived) + // It is a implementation of a trait. + && let Some(trait_) = impl_.of_trait + && let Some(trait_def_id) = trait_.trait_def_id() + // The trait is `PartialEq`. + && Some(trait_def_id) == get_trait_def_id(cx, &["core", "cmp", "PartialEq"]) + { + let to_check_op = if name.name == sym::eq { + BinOpKind::Eq + } else { + BinOpKind::Ne + }; + let expr = body.value.peel_blocks(); + let is_bad = match expr.kind { + ExprKind::Binary(op, left, right) if op.node == to_check_op => { + is_local(cx, left) && is_local(cx, right) + }, + ExprKind::MethodCall(segment, receiver, &[arg], _) if segment.ident.name == name.name => { + if is_local(cx, receiver) + && is_local(cx, &arg) + && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(trait_id) = cx.tcx.trait_of_item(fn_id) + && trait_id == trait_def_id + { + true + } else { + false + } + }, + _ => false, + }; + if is_bad { + span_lint_and_then( + cx, + UNCONDITIONAL_RECURSION, + method_span, + "function cannot return without recursing", + |diag| { + diag.span_note(expr.span, "recursive call site"); + }, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 7a6549a7c54..e5bc3b5a25f 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -680,9 +680,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos }) .filter(|(_, text)| !text.is_empty()); - let Some((line_start, line)) = lines.next() else { - return None; - }; + let (line_start, line) = lines.next()?; // Check for a sequence of line comments. if line.starts_with("//") { let (mut line, mut line_start) = (line, line_start); diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index d41576cadad..903593ecfd7 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -32,7 +32,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.76.0"] pub UNINHABITED_REFERENCES, - suspicious, + nursery, "reference to uninhabited type" } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index df715b12dea..8817e46b3c8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -351,6 +351,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { let_pat, let_expr, if_then, + .. }) = higher::WhileLet::hir(expr.value) { bind!(self, let_pat, let_expr, if_then); diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 5d23326cec8..b8869eedf52 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.76" +version = "0.1.77" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 7fe76b946a4..adc35bd82ae 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -134,6 +134,7 @@ pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { } } +#[allow(clippy::too_many_lines)] // Just a big match statement pub fn eq_expr(l: &Expr, r: &Expr) -> bool { use ExprKind::*; if !over(&l.attrs, &r.attrs, eq_attr) { diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 46c96fad884..db80e07ca1c 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -76,12 +76,14 @@ pub fn get_attr<'a>( }) .map_or_else( || { - sess.dcx().span_err(attr_segments[1].ident.span, "usage of unknown attribute"); + sess.dcx() + .span_err(attr_segments[1].ident.span, "usage of unknown attribute"); false }, |deprecation_status| { - let mut diag = - sess.dcx().struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); + let mut diag = sess + .dcx() + .struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); match *deprecation_status { DeprecationStatus::Deprecated => { diag.emit(); @@ -132,7 +134,8 @@ pub fn get_unique_attr<'a>( let mut unique_attr: Option<&ast::Attribute> = None; for attr in get_attr(sess, attrs, name) { if let Some(duplicate) = unique_attr { - sess.dcx().struct_span_err(attr.span, format!("`{name}` is defined multiple times")) + sess.dcx() + .struct_span_err(attr.span, format!("`{name}` is defined multiple times")) .span_note(duplicate.span, "first definition found here") .emit(); } else { diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 3135a033648..ba682813dad 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -91,6 +91,9 @@ pub struct IfLet<'hir> { pub if_then: &'hir Expr<'hir>, /// `if let` else expression pub if_else: Option<&'hir Expr<'hir>>, + /// `if let PAT = EXPR` + /// ^^^^^^^^^^^^^^ + pub let_span: Span, } impl<'hir> IfLet<'hir> { @@ -99,9 +102,10 @@ impl<'hir> IfLet<'hir> { if let ExprKind::If( Expr { kind: - ExprKind::Let(hir::Let { + ExprKind::Let(&hir::Let { pat: let_pat, init: let_expr, + span: let_span, .. }), .. @@ -129,6 +133,7 @@ impl<'hir> IfLet<'hir> { let_expr, if_then, if_else, + let_span, }); } None @@ -146,6 +151,9 @@ pub enum IfLetOrMatch<'hir> { &'hir Pat<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>, + /// `if let PAT = EXPR` + /// ^^^^^^^^^^^^^^ + Span, ), } @@ -160,7 +168,8 @@ impl<'hir> IfLetOrMatch<'hir> { let_pat, if_then, if_else, - }| { Self::IfLet(let_expr, let_pat, if_then, if_else) }, + let_span, + }| { Self::IfLet(let_expr, let_pat, if_then, if_else, let_span) }, ), } } @@ -353,6 +362,9 @@ pub struct WhileLet<'hir> { pub let_expr: &'hir Expr<'hir>, /// `while let` loop body pub if_then: &'hir Expr<'hir>, + /// `while let PAT = EXPR` + /// ^^^^^^^^^^^^^^ + pub let_span: Span, } impl<'hir> WhileLet<'hir> { @@ -367,9 +379,10 @@ impl<'hir> WhileLet<'hir> { ExprKind::If( Expr { kind: - ExprKind::Let(hir::Let { + ExprKind::Let(&hir::Let { pat: let_pat, init: let_expr, + span: let_span, .. }), .. @@ -390,6 +403,7 @@ impl<'hir> WhileLet<'hir> { let_pat, let_expr, if_then, + let_span, }); } None diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index d752fe7d97e..ebc38e531fe 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -316,10 +316,7 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> is_const: bool, } impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } + type NestedFilter = rustc_hir::intravisit::nested_filter::None; fn visit_expr(&mut self, e: &'tcx Expr<'_>) { if !self.is_const { diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index af123e107d5..5aaafb41721 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.76" +version = "0.1.77" edition = "2021" publish = false diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index d575da6dece..5a2526fd267 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-12-16" +channel = "nightly-2023-12-28" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs index 3155c0235ff..c81d54918cb 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs +++ b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs @@ -11,7 +11,7 @@ use rustc_lint::{Lint, LintContext}; use rustc_middle::ty::TyCtxt; pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { - cx.struct_span_lint(lint, span, msg, |b| b); + cx.struct_span_lint(lint, span, msg, |_| {}); } pub fn b( @@ -21,7 +21,7 @@ pub fn b( span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, ) { - tcx.struct_span_lint_hir(lint, hir_id, span, msg, |b| b); + tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {}); } fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr index 76c487fb135..7d424124f2b 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr @@ -1,8 +1,8 @@ error: use of a disallowed method `rustc_lint::context::LintContext::struct_span_lint` --> $DIR/disallow_struct_span_lint.rs:14:5 | -LL | cx.struct_span_lint(lint, span, msg, |b| b); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | cx.struct_span_lint(lint, span, msg, |_| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::disallowed-methods` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` @@ -10,8 +10,8 @@ LL | cx.struct_span_lint(lint, span, msg, |b| b); error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::struct_span_lint_hir` --> $DIR/disallow_struct_span_lint.rs:24:5 | -LL | tcx.struct_span_lint_hir(lint, hir_id, span, msg, |b| b); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs index 17c1b03d88c..3edb3a10b76 100644 --- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs @@ -7,7 +7,8 @@ unconditional_panic, clippy::no_effect, clippy::unnecessary_operation, - clippy::useless_vec + clippy::useless_vec, + clippy::out_of_bounds_indexing )] const ARR: [i32; 2] = [1, 2]; diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr index f8ace799593..84e7eff4557 100644 --- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -1,17 +1,17 @@ error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/test.rs:37:14 + --> $DIR/test.rs:38:14 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant encountered - --> $DIR/test.rs:37:5 + --> $DIR/test.rs:38:5 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/test.rs:28:5 + --> $DIR/test.rs:29:5 | LL | x[index]; | ^^^^^^^^ @@ -21,7 +21,7 @@ LL | x[index]; = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error: indexing may panic - --> $DIR/test.rs:46:5 + --> $DIR/test.rs:47:5 | LL | v[0]; | ^^^^ @@ -29,7 +29,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:47:5 + --> $DIR/test.rs:48:5 | LL | v[10]; | ^^^^^ @@ -37,7 +37,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:48:5 + --> $DIR/test.rs:49:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -45,7 +45,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:54:5 + --> $DIR/test.rs:55:5 | LL | v[N]; | ^^^^ @@ -53,7 +53,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:55:5 + --> $DIR/test.rs:56:5 | LL | v[M]; | ^^^^ @@ -61,7 +61,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed - --> $DIR/test.rs:15:24 + --> $DIR/test.rs:16:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.rs b/src/tools/clippy/tests/ui/assertions_on_constants.rs index 10809a6d247..1309ae45d0a 100644 --- a/src/tools/clippy/tests/ui/assertions_on_constants.rs +++ b/src/tools/clippy/tests/ui/assertions_on_constants.rs @@ -45,4 +45,11 @@ fn main() { const CFG_FLAG: &bool = &cfg!(feature = "hey"); assert!(!CFG_FLAG); + + const _: () = assert!(true); + //~^ ERROR: `assert!(true)` will be optimized out by the compiler + + // Don't lint if the value is dependent on a defined constant: + const N: usize = 1024; + const _: () = assert!(N.is_power_of_two()); } diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.stderr b/src/tools/clippy/tests/ui/assertions_on_constants.stderr index 780d1fe1c8a..099be4ed355 100644 --- a/src/tools/clippy/tests/ui/assertions_on_constants.stderr +++ b/src/tools/clippy/tests/ui/assertions_on_constants.stderr @@ -72,5 +72,13 @@ LL | debug_assert!(true); | = help: remove it -error: aborting due to 9 previous errors +error: `assert!(true)` will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:49:19 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = help: remove it + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/author/loop.rs b/src/tools/clippy/tests/ui/author/loop.rs index d6de21631e2..ff5b6100117 100644 --- a/src/tools/clippy/tests/ui/author/loop.rs +++ b/src/tools/clippy/tests/ui/author/loop.rs @@ -1,5 +1,9 @@ #![feature(stmt_expr_attributes)] -#![allow(clippy::never_loop, clippy::while_immutable_condition)] +#![allow( + clippy::never_loop, + clippy::while_immutable_condition, + clippy::redundant_pattern_matching +)] fn main() { #[clippy::author] diff --git a/src/tools/clippy/tests/ui/bool_comparison.fixed b/src/tools/clippy/tests/ui/bool_comparison.fixed index e3f2ca72d1c..02f1d09b833 100644 --- a/src/tools/clippy/tests/ui/bool_comparison.fixed +++ b/src/tools/clippy/tests/ui/bool_comparison.fixed @@ -165,3 +165,12 @@ fn issue3973() { if is_debug == m!(func) {} if m!(func) == is_debug {} } + +#[allow(clippy::unnecessary_cast)] +fn issue9907() { + let _ = (1 >= 2) as usize; + let _ = (!m!(func)) as usize; + // This is not part of the issue, but an unexpected found when fixing the issue, + // the provided span was inside of macro rather than the macro callsite. + let _ = ((1 < 2) != m!(func)) as usize; +} diff --git a/src/tools/clippy/tests/ui/bool_comparison.rs b/src/tools/clippy/tests/ui/bool_comparison.rs index d1bc20d6831..5ef696d855e 100644 --- a/src/tools/clippy/tests/ui/bool_comparison.rs +++ b/src/tools/clippy/tests/ui/bool_comparison.rs @@ -165,3 +165,12 @@ fn issue3973() { if is_debug == m!(func) {} if m!(func) == is_debug {} } + +#[allow(clippy::unnecessary_cast)] +fn issue9907() { + let _ = ((1 < 2) == false) as usize; + let _ = (false == m!(func)) as usize; + // This is not part of the issue, but an unexpected found when fixing the issue, + // the provided span was inside of macro rather than the macro callsite. + let _ = ((1 < 2) == !m!(func)) as usize; +} diff --git a/src/tools/clippy/tests/ui/bool_comparison.stderr b/src/tools/clippy/tests/ui/bool_comparison.stderr index 4560df6d4cd..6907dc0523f 100644 --- a/src/tools/clippy/tests/ui/bool_comparison.stderr +++ b/src/tools/clippy/tests/ui/bool_comparison.stderr @@ -133,5 +133,23 @@ error: equality checks against true are unnecessary LL | if m!(func) == true {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` -error: aborting due to 22 previous errors +error: equality checks against false can be replaced by a negation + --> $DIR/bool_comparison.rs:171:14 + | +LL | let _ = ((1 < 2) == false) as usize; + | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `1 >= 2` + +error: equality checks against false can be replaced by a negation + --> $DIR/bool_comparison.rs:172:14 + | +LL | let _ = (false == m!(func)) as usize; + | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` + +error: this comparison might be written more concisely + --> $DIR/bool_comparison.rs:175:14 + | +LL | let _ = ((1 < 2) == !m!(func)) as usize; + | ^^^^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `(1 < 2) != m!(func)` + +error: aborting due to 25 previous errors diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs index d102efa7a58..549908b8770 100644 --- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs @@ -1,6 +1,10 @@ #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] -#![allow(dead_code)] -#![allow(clippy::equatable_if_let, clippy::uninlined_format_args)] +#![allow( + clippy::equatable_if_let, + clippy::uninlined_format_args, + clippy::redundant_pattern_matching, + dead_code +)] //@no-rustfix // This tests the branches_sharing_code lint at the end of blocks diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr index d00717befc1..8223df0fe7b 100644 --- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr @@ -1,5 +1,5 @@ error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:31:5 + --> $DIR/shared_at_bottom.rs:35:5 | LL | / let result = false; LL | | @@ -26,7 +26,7 @@ LL ~ result; | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:51:5 + --> $DIR/shared_at_bottom.rs:55:5 | LL | / println!("Same end of block"); LL | | @@ -40,7 +40,7 @@ LL + println!("Same end of block"); | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:69:5 + --> $DIR/shared_at_bottom.rs:73:5 | LL | / println!( LL | | @@ -61,7 +61,7 @@ LL + ); | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:82:9 + --> $DIR/shared_at_bottom.rs:86:9 | LL | / println!("Hello World"); LL | | @@ -75,7 +75,7 @@ LL + println!("Hello World"); | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:99:5 + --> $DIR/shared_at_bottom.rs:103:5 | LL | / let later_used_value = "A string value"; LL | | @@ -94,7 +94,7 @@ LL + println!("{}", later_used_value); | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:113:5 + --> $DIR/shared_at_bottom.rs:117:5 | LL | / let simple_examples = "I now identify as a &str :)"; LL | | @@ -112,7 +112,7 @@ LL + println!("This is the new simple_example: {}", simple_examples); | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:179:5 + --> $DIR/shared_at_bottom.rs:183:5 | LL | / x << 2 LL | | @@ -128,7 +128,7 @@ LL ~ x << 2; | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:188:5 + --> $DIR/shared_at_bottom.rs:192:5 | LL | / x * 4 LL | | @@ -144,7 +144,7 @@ LL + x * 4 | error: all if blocks contain the same code at the end - --> $DIR/shared_at_bottom.rs:202:44 + --> $DIR/shared_at_bottom.rs:206:44 | LL | if x == 17 { b = 1; a = 0x99; } else { a = 0x99; } | ^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed index fff6bfcc753..44b0b6e7391 100644 --- a/src/tools/clippy/tests/ui/collapsible_if.fixed +++ b/src/tools/clippy/tests/ui/collapsible_if.fixed @@ -3,7 +3,8 @@ clippy::equatable_if_let, clippy::needless_if, clippy::nonminimal_bool, - clippy::eq_op + clippy::eq_op, + clippy::redundant_pattern_matching )] #[rustfmt::skip] diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs index 70bfea231ae..563a273dcdd 100644 --- a/src/tools/clippy/tests/ui/collapsible_if.rs +++ b/src/tools/clippy/tests/ui/collapsible_if.rs @@ -3,7 +3,8 @@ clippy::equatable_if_let, clippy::needless_if, clippy::nonminimal_bool, - clippy::eq_op + clippy::eq_op, + clippy::redundant_pattern_matching )] #[rustfmt::skip] diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr index e8a36bf48f1..16df3e433db 100644 --- a/src/tools/clippy/tests/ui/collapsible_if.stderr +++ b/src/tools/clippy/tests/ui/collapsible_if.stderr @@ -1,5 +1,5 @@ error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:14:5 + --> $DIR/collapsible_if.rs:15:5 | LL | / if x == "hello" { LL | | if y == "world" { @@ -18,7 +18,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:20:5 + --> $DIR/collapsible_if.rs:21:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -35,7 +35,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:26:5 + --> $DIR/collapsible_if.rs:27:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -52,7 +52,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:32:5 + --> $DIR/collapsible_if.rs:33:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -69,7 +69,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:38:5 + --> $DIR/collapsible_if.rs:39:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -86,7 +86,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:44:5 + --> $DIR/collapsible_if.rs:45:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -103,7 +103,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:100:5 + --> $DIR/collapsible_if.rs:101:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible @@ -120,7 +120,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:159:5 + --> $DIR/collapsible_if.rs:160:5 | LL | / if matches!(true, true) { LL | | if matches!(true, true) {} @@ -128,7 +128,7 @@ LL | | } | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:164:5 + --> $DIR/collapsible_if.rs:165:5 | LL | / if matches!(true, true) && truth() { LL | | if matches!(true, true) {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-11939.rs b/src/tools/clippy/tests/ui/crashes/ice-11939.rs new file mode 100644 index 00000000000..5e7193b6826 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11939.rs @@ -0,0 +1,14 @@ +#![allow(clippy::unit_arg, clippy::no_effect)] + +const fn v(_: ()) {} + +fn main() { + if true { + v({ + [0; 1 + 1]; + }); + Some(()) + } else { + None + }; +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-5497.rs b/src/tools/clippy/tests/ui/crashes/ice-5497.rs index f77f691c192..fe8d640c470 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5497.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-5497.rs @@ -1,4 +1,6 @@ // reduced from rustc issue-69020-assoc-const-arith-overflow.rs +#![allow(clippy::out_of_bounds_indexing)] + pub fn main() {} pub trait Foo { diff --git a/src/tools/clippy/tests/ui/crashes/ice-5497.stderr b/src/tools/clippy/tests/ui/crashes/ice-5497.stderr index ee69f3379b6..3efaf05827e 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5497.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-5497.stderr @@ -1,5 +1,5 @@ error: this operation will panic at runtime - --> $DIR/ice-5497.rs:9:22 + --> $DIR/ice-5497.rs:11:22 | LL | const OOB: i32 = [1][1] + T::OOB; | ^^^^^^ index out of bounds: the length is 1 but the index is 1 diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index 708ac666675..bff46e55722 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -65,7 +65,7 @@ fn test_units() { /// OAuth GraphQL /// OCaml /// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS -/// WebGL +/// WebGL WebGL2 WebGPU /// TensorFlow /// TrueType /// iOS macOS FreeBSD diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index 040d6352c52..4e162a97dee 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -65,7 +65,7 @@ fn test_units() { /// OAuth GraphQL /// OCaml /// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS -/// WebGL +/// WebGL WebGL2 WebGPU /// TensorFlow /// TrueType /// iOS macOS FreeBSD diff --git a/src/tools/clippy/tests/ui/eager_transmute.fixed b/src/tools/clippy/tests/ui/eager_transmute.fixed new file mode 100644 index 00000000000..e06aa2cc9fd --- /dev/null +++ b/src/tools/clippy/tests/ui/eager_transmute.fixed @@ -0,0 +1,72 @@ +#![feature(rustc_attrs)] +#![warn(clippy::eager_transmute)] +#![allow(clippy::transmute_int_to_non_zero)] + +use std::num::NonZeroU8; + +#[repr(u8)] +enum Opcode { + Add = 0, + Sub = 1, + Mul = 2, + Div = 3, +} + +fn int_to_opcode(op: u8) -> Option<Opcode> { + (op < 4).then(|| unsafe { std::mem::transmute(op) }) +} + +fn f(op: u8, unrelated: u8) { + true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); +} + +unsafe fn f2(op: u8) { + (op < 4).then(|| std::mem::transmute::<_, Opcode>(op)); +} + +#[rustc_layout_scalar_valid_range_end(254)] +struct NonMaxU8(u8); +#[rustc_layout_scalar_valid_range_end(254)] +#[rustc_layout_scalar_valid_range_start(1)] +struct NonZeroNonMaxU8(u8); + +macro_rules! impls { + ($($t:ty),*) => { + $( + impl PartialEq<u8> for $t { + fn eq(&self, other: &u8) -> bool { + self.0 == *other + } + } + impl PartialOrd<u8> for $t { + fn partial_cmp(&self, other: &u8) -> Option<std::cmp::Ordering> { + self.0.partial_cmp(other) + } + } + )* + }; +} +impls!(NonMaxU8, NonZeroNonMaxU8); + +fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) { + // u8 -> NonZeroU8, do lint + let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) }); + + // NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range + let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + + // NonZeroU8 -> NonMaxU8, do lint, different niche + let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); + + // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity + let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) }); + + // NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity + let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/eager_transmute.rs b/src/tools/clippy/tests/ui/eager_transmute.rs new file mode 100644 index 00000000000..89ccdf583f3 --- /dev/null +++ b/src/tools/clippy/tests/ui/eager_transmute.rs @@ -0,0 +1,72 @@ +#![feature(rustc_attrs)] +#![warn(clippy::eager_transmute)] +#![allow(clippy::transmute_int_to_non_zero)] + +use std::num::NonZeroU8; + +#[repr(u8)] +enum Opcode { + Add = 0, + Sub = 1, + Mul = 2, + Div = 3, +} + +fn int_to_opcode(op: u8) -> Option<Opcode> { + (op < 4).then_some(unsafe { std::mem::transmute(op) }) +} + +fn f(op: u8, unrelated: u8) { + true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); +} + +unsafe fn f2(op: u8) { + (op < 4).then_some(std::mem::transmute::<_, Opcode>(op)); +} + +#[rustc_layout_scalar_valid_range_end(254)] +struct NonMaxU8(u8); +#[rustc_layout_scalar_valid_range_end(254)] +#[rustc_layout_scalar_valid_range_start(1)] +struct NonZeroNonMaxU8(u8); + +macro_rules! impls { + ($($t:ty),*) => { + $( + impl PartialEq<u8> for $t { + fn eq(&self, other: &u8) -> bool { + self.0 == *other + } + } + impl PartialOrd<u8> for $t { + fn partial_cmp(&self, other: &u8) -> Option<std::cmp::Ordering> { + self.0.partial_cmp(other) + } + } + )* + }; +} +impls!(NonMaxU8, NonZeroNonMaxU8); + +fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) { + // u8 -> NonZeroU8, do lint + let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) }); + + // NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range + let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + + // NonZeroU8 -> NonMaxU8, do lint, different niche + let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + + // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity + let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) }); + + // NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity + let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/eager_transmute.stderr b/src/tools/clippy/tests/ui/eager_transmute.stderr new file mode 100644 index 00000000000..5eb163c5fcb --- /dev/null +++ b/src/tools/clippy/tests/ui/eager_transmute.stderr @@ -0,0 +1,92 @@ +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:16:33 + | +LL | (op < 4).then_some(unsafe { std::mem::transmute(op) }) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::eager-transmute` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::eager_transmute)]` +help: consider using `bool::then` to only transmute if the condition holds + | +LL | (op < 4).then(|| unsafe { std::mem::transmute(op) }) + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:22:33 + | +LL | (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:23:33 + | +LL | (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:24:34 + | +LL | (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:28:24 + | +LL | (op < 4).then_some(std::mem::transmute::<_, Opcode>(op)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | (op < 4).then(|| std::mem::transmute::<_, Opcode>(op)); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:57:60 + | +LL | let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) }); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) }); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:63:86 + | +LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); + | ~~~~ ++ + +error: this transmute is always evaluated eagerly, even if the condition is false + --> $DIR/eager_transmute.rs:69:93 + | +LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `bool::then` to only transmute if the condition holds + | +LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); + | ~~~~ ++ + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/get_unwrap.fixed b/src/tools/clippy/tests/ui/get_unwrap.fixed index d5a4309db59..62beb195939 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.fixed +++ b/src/tools/clippy/tests/ui/get_unwrap.fixed @@ -2,7 +2,8 @@ unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first, - clippy::useless_vec + clippy::useless_vec, + clippy::out_of_bounds_indexing )] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] diff --git a/src/tools/clippy/tests/ui/get_unwrap.rs b/src/tools/clippy/tests/ui/get_unwrap.rs index 5a9ad204f70..1e09ff5c67e 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.rs +++ b/src/tools/clippy/tests/ui/get_unwrap.rs @@ -2,7 +2,8 @@ unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first, - clippy::useless_vec + clippy::useless_vec, + clippy::out_of_bounds_indexing )] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr index 384860ea116..700f3cfec4e 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.stderr +++ b/src/tools/clippy/tests/ui/get_unwrap.stderr @@ -1,17 +1,17 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:37:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]` | note: the lint level is defined here - --> $DIR/get_unwrap.rs:8:9 + --> $DIR/get_unwrap.rs:9:9 | LL | #![deny(clippy::get_unwrap)] | ^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:37:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,13 +22,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:38:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:38:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,13 +37,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:39:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:39:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,13 +52,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,13 +67,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,13 +82,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:41:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,13 +97,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:45:21 + --> $DIR/get_unwrap.rs:46:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:45:22 + --> $DIR/get_unwrap.rs:46:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,13 +112,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:50:9 + --> $DIR/get_unwrap.rs:51:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:50:10 + --> $DIR/get_unwrap.rs:51:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,13 +127,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:51:9 + --> $DIR/get_unwrap.rs:52:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:51:10 + --> $DIR/get_unwrap.rs:52:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,13 +142,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:52:9 + --> $DIR/get_unwrap.rs:53:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:52:10 + --> $DIR/get_unwrap.rs:53:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,13 +157,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:53:9 + --> $DIR/get_unwrap.rs:54:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:53:10 + --> $DIR/get_unwrap.rs:54:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,13 +172,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:66:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:66:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,13 +187,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:66:17 + --> $DIR/get_unwrap.rs:67:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:66:17 + --> $DIR/get_unwrap.rs:67:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -202,25 +202,25 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:76:24 + --> $DIR/get_unwrap.rs:77:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:79:18 + --> $DIR/get_unwrap.rs:80:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:82:18 + --> $DIR/get_unwrap.rs:83:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]` error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:99:33 + --> $DIR/get_unwrap.rs:100:33 | LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs index 77abd663e0a..abc92459148 100644 --- a/src/tools/clippy/tests/ui/if_then_some_else_none.rs +++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs @@ -1,4 +1,5 @@ #![warn(clippy::if_then_some_else_none)] +#![allow(clippy::redundant_pattern_matching)] fn main() { // Should issue an error. diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr index 5c97b06da15..9b3d65cc803 100644 --- a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr +++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr @@ -1,5 +1,5 @@ error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:5:13 + --> $DIR/if_then_some_else_none.rs:6:13 | LL | let _ = if foo() { | _____________^ @@ -16,7 +16,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]` error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:14:13 + --> $DIR/if_then_some_else_none.rs:15:13 | LL | let _ = if matches!(true, true) { | _____________^ @@ -31,7 +31,7 @@ LL | | }; = help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })` error: this could be simplified with `bool::then_some` - --> $DIR/if_then_some_else_none.rs:24:28 + --> $DIR/if_then_some_else_none.rs:25:28 | LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); = help: consider using `bool::then_some` like: `(o < 32).then_some(o)` error: this could be simplified with `bool::then_some` - --> $DIR/if_then_some_else_none.rs:29:13 + --> $DIR/if_then_some_else_none.rs:30:13 | LL | let _ = if !x { Some(0) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | let _ = if !x { Some(0) } else { None }; = help: consider using `bool::then_some` like: `(!x).then_some(0)` error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:85:13 + --> $DIR/if_then_some_else_none.rs:86:13 | LL | let _ = if foo() { | _____________^ diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs index f0da5dfc60b..1ac0bb11014 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs @@ -74,4 +74,7 @@ fn main() { //~^ ERROR: indexing may panic v[M]; //~^ ERROR: indexing may panic + + let slice = &x; + let _ = x[4]; } diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr index 1c34875d2b8..6d64fa1e6cf 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr @@ -38,6 +38,21 @@ LL | x[index]; | = help: consider using `.get(n)` or `.get_mut(n)` instead +error: index is out of bounds + --> $DIR/indexing_slicing_index.rs:32:5 + | +LL | x[4]; + | ^^^^ + | + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` + +error: index is out of bounds + --> $DIR/indexing_slicing_index.rs:34:5 + | +LL | x[1 << 3]; + | ^^^^^^^^^ + error: indexing may panic --> $DIR/indexing_slicing_index.rs:45:14 | @@ -56,6 +71,12 @@ LL | const { &ARR[idx4()] }; = help: consider using `.get(n)` or `.get_mut(n)` instead = note: the suggestion might not be applicable in constant blocks +error: index is out of bounds + --> $DIR/indexing_slicing_index.rs:55:5 + | +LL | y[4]; + | ^^^^ + error: indexing may panic --> $DIR/indexing_slicing_index.rs:58:5 | @@ -80,6 +101,12 @@ LL | v[1 << 3]; | = help: consider using `.get(n)` or `.get_mut(n)` instead +error: index is out of bounds + --> $DIR/indexing_slicing_index.rs:70:5 + | +LL | x[N]; + | ^^^^ + error: indexing may panic --> $DIR/indexing_slicing_index.rs:73:5 | @@ -96,12 +123,18 @@ LL | v[M]; | = help: consider using `.get(n)` or `.get_mut(n)` instead +error: index is out of bounds + --> $DIR/indexing_slicing_index.rs:79:13 + | +LL | let _ = x[4]; + | ^^^^ + error[E0080]: evaluation of constant value failed --> $DIR/indexing_slicing_index.rs:16:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 -error: aborting due to 12 previous errors +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/tools/clippy/tests/ui/infinite_loops.stderr b/src/tools/clippy/tests/ui/infinite_loops.stderr index f58b3cebbc3..771fbfa44ee 100644 --- a/src/tools/clippy/tests/ui/infinite_loops.stderr +++ b/src/tools/clippy/tests/ui/infinite_loops.stderr @@ -9,7 +9,7 @@ LL | | } | = note: `-D clippy::infinite-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::infinite_loop)]` -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn no_break() -> ! { | ++++ @@ -26,7 +26,7 @@ LL | | do_something(); LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { | ++++ @@ -43,7 +43,7 @@ LL | | } LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { | ++++ @@ -57,7 +57,7 @@ LL | | do_something(); LL | | } | |_____________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn all_inf() -> ! { | ++++ @@ -84,7 +84,7 @@ LL | | do_something(); LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn no_break_never_ret_noise() -> ! { | ++++ @@ -101,7 +101,7 @@ LL | | } LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn break_inner_but_not_outer_1(cond: bool) -> ! { | ++++ @@ -118,7 +118,7 @@ LL | | } LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn break_inner_but_not_outer_2(cond: bool) -> ! { | ++++ @@ -132,7 +132,7 @@ LL | | do_something(); LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn break_outer_but_not_inner() -> ! { | ++++ @@ -149,7 +149,7 @@ LL | | } LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn break_wrong_loop(cond: bool) -> ! { | ++++ @@ -166,7 +166,7 @@ LL | | } LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn match_like() -> ! { | ++++ @@ -180,7 +180,7 @@ LL | | let _x = matches!(result, Ok(v) if v != 0).then_some(0); LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn match_like() -> ! { | ++++ @@ -197,7 +197,7 @@ LL | | }); LL | | } | |_____^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn match_like() -> ! { | ++++ @@ -211,7 +211,7 @@ LL | | do_something(); LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn problematic_trait_method() -> ! { | ++++ @@ -225,7 +225,7 @@ LL | | do_something(); LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | fn could_be_problematic() -> ! { | ++++ @@ -239,7 +239,7 @@ LL | | do_something(); LL | | } | |_________^ | -help: if this is intentional, consider specifing `!` as function return +help: if this is intentional, consider specifying `!` as function return | LL | let _loop_forever = || -> ! { | ++++ diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed b/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed new file mode 100644 index 00000000000..a5ca41528af --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed @@ -0,0 +1,26 @@ +#![warn(clippy::iter_filter_is_ok)] + +fn main() { + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + + #[rustfmt::skip] + let _ = vec![Ok(1), Err(2)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + + // Don't lint below + let mut counter = 0; + let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { + counter += 1; + o.is_ok() + }); + let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { + // Roses are red, + // Violets are blue, + // `Err` is not an `Option`, + // and this doesn't ryme + o.is_ok() + }); +} diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.rs b/src/tools/clippy/tests/ui/iter_filter_is_ok.rs new file mode 100644 index 00000000000..e4e73f5ada1 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.rs @@ -0,0 +1,26 @@ +#![warn(clippy::iter_filter_is_ok)] + +fn main() { + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok); + //~^ HELP: consider using `flatten` instead + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok()); + //~^ HELP: consider using `flatten` instead + + #[rustfmt::skip] + let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() }); + //~^ HELP: consider using `flatten` instead + + // Don't lint below + let mut counter = 0; + let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { + counter += 1; + o.is_ok() + }); + let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { + // Roses are red, + // Violets are blue, + // `Err` is not an `Option`, + // and this doesn't ryme + o.is_ok() + }); +} diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr b/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr new file mode 100644 index 00000000000..f3acbe38d8a --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr @@ -0,0 +1,23 @@ +error: `filter` for `is_ok` on iterator over `Result`s + --> $DIR/iter_filter_is_ok.rs:4:52 + | +LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + | + = note: `-D clippy::iter-filter-is-ok` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_ok)]` + +error: `filter` for `is_ok` on iterator over `Result`s + --> $DIR/iter_filter_is_ok.rs:6:52 + | +LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok()); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `is_ok` on iterator over `Result`s + --> $DIR/iter_filter_is_ok.rs:10:45 + | +LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.fixed b/src/tools/clippy/tests/ui/iter_filter_is_some.fixed new file mode 100644 index 00000000000..c3fa93f0ab2 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_some.fixed @@ -0,0 +1,27 @@ +#![warn(clippy::iter_filter_is_some)] + +fn main() { + let _ = vec![Some(1)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + let _ = vec![Some(1)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + + #[rustfmt::skip] + let _ = vec![Some(1)].into_iter().flatten(); + //~^ HELP: consider using `flatten` instead + + // Don't lint below + let mut counter = 0; + let _ = vec![Some(1)].into_iter().filter(|o| { + counter += 1; + o.is_some() + }); + + let _ = vec![Some(1)].into_iter().filter(|o| { + // Roses are red, + // Violets are blue, + // `Err` is not an `Option`, + // and this doesn't ryme + o.is_some() + }); +} diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.rs b/src/tools/clippy/tests/ui/iter_filter_is_some.rs new file mode 100644 index 00000000000..b023776abe4 --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_some.rs @@ -0,0 +1,27 @@ +#![warn(clippy::iter_filter_is_some)] + +fn main() { + let _ = vec![Some(1)].into_iter().filter(Option::is_some); + //~^ HELP: consider using `flatten` instead + let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()); + //~^ HELP: consider using `flatten` instead + + #[rustfmt::skip] + let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() }); + //~^ HELP: consider using `flatten` instead + + // Don't lint below + let mut counter = 0; + let _ = vec![Some(1)].into_iter().filter(|o| { + counter += 1; + o.is_some() + }); + + let _ = vec![Some(1)].into_iter().filter(|o| { + // Roses are red, + // Violets are blue, + // `Err` is not an `Option`, + // and this doesn't ryme + o.is_some() + }); +} diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.stderr b/src/tools/clippy/tests/ui/iter_filter_is_some.stderr new file mode 100644 index 00000000000..1f2b10036fe --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_filter_is_some.stderr @@ -0,0 +1,23 @@ +error: `filter` for `is_some` on iterator over `Option` + --> $DIR/iter_filter_is_some.rs:4:39 + | +LL | let _ = vec![Some(1)].into_iter().filter(Option::is_some); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + | + = note: `-D clippy::iter-filter-is-some` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_some)]` + +error: `filter` for `is_some` on iterator over `Option` + --> $DIR/iter_filter_is_some.rs:6:39 + | +LL | let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `is_some` on iterator over `Option` + --> $DIR/iter_filter_is_some.rs:10:39 + | +LL | let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_let_else_question_mark.fixed b/src/tools/clippy/tests/ui/manual_let_else_question_mark.fixed index b555186cc22..6b29ce75985 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_question_mark.fixed +++ b/src/tools/clippy/tests/ui/manual_let_else_question_mark.fixed @@ -60,3 +60,24 @@ fn foo() -> Option<()> { Some(()) } + +// lint not just `return None`, but also `return None;` (note the semicolon) +fn issue11993(y: Option<i32>) -> Option<i32> { + let x = y?; + + // don't lint: more than one statement in the else body + let Some(x) = y else { + todo!(); + return None; + }; + + let Some(x) = y else { + // Roses are red, + // violets are blue, + // please keep this comment, + // it's art, you know? + return None; + }; + + None +} diff --git a/src/tools/clippy/tests/ui/manual_let_else_question_mark.rs b/src/tools/clippy/tests/ui/manual_let_else_question_mark.rs index 5852c7094a4..e92c4c1375e 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_question_mark.rs +++ b/src/tools/clippy/tests/ui/manual_let_else_question_mark.rs @@ -65,3 +65,26 @@ fn foo() -> Option<()> { Some(()) } + +// lint not just `return None`, but also `return None;` (note the semicolon) +fn issue11993(y: Option<i32>) -> Option<i32> { + let Some(x) = y else { + return None; + }; + + // don't lint: more than one statement in the else body + let Some(x) = y else { + todo!(); + return None; + }; + + let Some(x) = y else { + // Roses are red, + // violets are blue, + // please keep this comment, + // it's art, you know? + return None; + }; + + None +} diff --git a/src/tools/clippy/tests/ui/manual_let_else_question_mark.stderr b/src/tools/clippy/tests/ui/manual_let_else_question_mark.stderr index bf0b1bbf0dd..dec6947697a 100644 --- a/src/tools/clippy/tests/ui/manual_let_else_question_mark.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else_question_mark.stderr @@ -53,5 +53,13 @@ error: this could be rewritten as `let...else` LL | let v = if let Some(v_some) = g() { v_some } else { return None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return None };` -error: aborting due to 6 previous errors +error: this `let...else` may be rewritten with the `?` operator + --> $DIR/manual_let_else_question_mark.rs:71:5 + | +LL | / let Some(x) = y else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x = y?;` + +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/needless_if.fixed b/src/tools/clippy/tests/ui/needless_if.fixed index 1086ae2c984..79e33a7218b 100644 --- a/src/tools/clippy/tests/ui/needless_if.fixed +++ b/src/tools/clippy/tests/ui/needless_if.fixed @@ -10,6 +10,7 @@ clippy::nonminimal_bool, clippy::short_circuit_statement, clippy::unnecessary_operation, + clippy::redundant_pattern_matching, unused )] #![warn(clippy::needless_if)] diff --git a/src/tools/clippy/tests/ui/needless_if.rs b/src/tools/clippy/tests/ui/needless_if.rs index 131cceaf712..2c135fb22bf 100644 --- a/src/tools/clippy/tests/ui/needless_if.rs +++ b/src/tools/clippy/tests/ui/needless_if.rs @@ -10,6 +10,7 @@ clippy::nonminimal_bool, clippy::short_circuit_statement, clippy::unnecessary_operation, + clippy::redundant_pattern_matching, unused )] #![warn(clippy::needless_if)] diff --git a/src/tools/clippy/tests/ui/needless_if.stderr b/src/tools/clippy/tests/ui/needless_if.stderr index c3e83c0f1f5..9a911b4dbac 100644 --- a/src/tools/clippy/tests/ui/needless_if.stderr +++ b/src/tools/clippy/tests/ui/needless_if.stderr @@ -1,5 +1,5 @@ error: this `if` branch is empty - --> $DIR/needless_if.rs:26:5 + --> $DIR/needless_if.rs:27:5 | LL | if (true) {} | ^^^^^^^^^^^^ help: you can remove it @@ -8,13 +8,13 @@ LL | if (true) {} = help: to override `-D warnings` add `#[allow(clippy::needless_if)]` error: this `if` branch is empty - --> $DIR/needless_if.rs:28:5 + --> $DIR/needless_if.rs:29:5 | LL | if maybe_side_effect() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` error: this `if` branch is empty - --> $DIR/needless_if.rs:33:5 + --> $DIR/needless_if.rs:34:5 | LL | / if { LL | | return; @@ -29,7 +29,7 @@ LL + }); | error: this `if` branch is empty - --> $DIR/needless_if.rs:49:5 + --> $DIR/needless_if.rs:50:5 | LL | / if { LL | | if let true = true @@ -54,19 +54,19 @@ LL + } && true); | error: this `if` branch is empty - --> $DIR/needless_if.rs:93:5 + --> $DIR/needless_if.rs:94:5 | LL | if { maybe_side_effect() } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });` error: this `if` branch is empty - --> $DIR/needless_if.rs:95:5 + --> $DIR/needless_if.rs:96:5 | LL | if { maybe_side_effect() } && true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);` error: this `if` branch is empty - --> $DIR/needless_if.rs:99:5 + --> $DIR/needless_if.rs:100:5 | LL | if true {} | ^^^^^^^^^^ help: you can remove it: `true;` diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index da7876e772e..4d48ef14d31 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -1,6 +1,11 @@ //@no-rustfix: overlapping suggestions #![feature(lint_reasons)] -#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] +#![allow( + unused, + clippy::diverging_sub_expression, + clippy::needless_if, + clippy::redundant_pattern_matching +)] #![warn(clippy::nonminimal_bool)] #![allow(clippy::useless_vec)] diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index deae389dbef..fd1568d94e3 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:13:13 + --> $DIR/nonminimal_bool.rs:18:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -8,43 +8,43 @@ LL | let _ = !true; = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:16:13 + --> $DIR/nonminimal_bool.rs:21:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:18:13 + --> $DIR/nonminimal_bool.rs:23:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:20:13 + --> $DIR/nonminimal_bool.rs:25:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:25:13 + --> $DIR/nonminimal_bool.rs:30:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:27:13 + --> $DIR/nonminimal_bool.rs:32:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:29:13 + --> $DIR/nonminimal_bool.rs:34:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:38:13 + --> $DIR/nonminimal_bool.rs:43:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:40:13 + --> $DIR/nonminimal_bool.rs:45:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:42:13 + --> $DIR/nonminimal_bool.rs:47:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:44:13 + --> $DIR/nonminimal_bool.rs:49:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:46:13 + --> $DIR/nonminimal_bool.rs:51:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | let _ = a != b && c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:77:8 + --> $DIR/nonminimal_bool.rs:82:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` diff --git a/src/tools/clippy/tests/ui/option_filter_map.fixed b/src/tools/clippy/tests/ui/option_filter_map.fixed index ee004c0e194..b1c3cfa48a4 100644 --- a/src/tools/clippy/tests/ui/option_filter_map.fixed +++ b/src/tools/clippy/tests/ui/option_filter_map.fixed @@ -3,12 +3,18 @@ fn main() { let _ = Some(Some(1)).flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(Some(1)).flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(1).map(odds_out).flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(1).map(odds_out).flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![Some(1)].into_iter().flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![Some(1)].into_iter().flatten(); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![1] .into_iter() .map(odds_out) diff --git a/src/tools/clippy/tests/ui/option_filter_map.rs b/src/tools/clippy/tests/ui/option_filter_map.rs index eae2fa176a8..2550b9cd2b3 100644 --- a/src/tools/clippy/tests/ui/option_filter_map.rs +++ b/src/tools/clippy/tests/ui/option_filter_map.rs @@ -3,21 +3,29 @@ fn main() { let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); + //~^ ERROR: `filter` for `Some` followed by `unwrap` let _ = vec![1] .into_iter() .map(odds_out) .filter(Option::is_some) + //~^ ERROR: `filter` for `Some` followed by `unwrap` .map(Option::unwrap); let _ = vec![1] .into_iter() .map(odds_out) .filter(|o| o.is_some()) + //~^ ERROR: `filter` for `Some` followed by `unwrap` .map(|o| o.unwrap()); } diff --git a/src/tools/clippy/tests/ui/option_filter_map.stderr b/src/tools/clippy/tests/ui/option_filter_map.stderr index 148f9d02f5e..6a0fc10822b 100644 --- a/src/tools/clippy/tests/ui/option_filter_map.stderr +++ b/src/tools/clippy/tests/ui/option_filter_map.stderr @@ -8,48 +8,50 @@ LL | let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); = help: to override `-D warnings` add `#[allow(clippy::option_filter_map)]` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:6:27 + --> $DIR/option_filter_map.rs:7:27 | LL | let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:7:35 + --> $DIR/option_filter_map.rs:9:35 | LL | let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:8:35 + --> $DIR/option_filter_map.rs:11:35 | LL | let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:10:39 + --> $DIR/option_filter_map.rs:14:39 | LL | let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:11:39 + --> $DIR/option_filter_map.rs:16:39 | LL | let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:15:10 + --> $DIR/option_filter_map.rs:21:10 | LL | .filter(Option::is_some) | __________^ +LL | | LL | | .map(Option::unwrap); | |____________________________^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> $DIR/option_filter_map.rs:20:10 + --> $DIR/option_filter_map.rs:27:10 | LL | .filter(|o| o.is_some()) | __________^ +LL | | LL | | .map(|o| o.unwrap()); | |____________________________^ help: consider using `flatten` instead: `flatten()` diff --git a/src/tools/clippy/tests/ui/redundant_async_block.fixed b/src/tools/clippy/tests/ui/redundant_async_block.fixed index d492ea1be75..a1875c1c06e 100644 --- a/src/tools/clippy/tests/ui/redundant_async_block.fixed +++ b/src/tools/clippy/tests/ui/redundant_async_block.fixed @@ -1,7 +1,7 @@ #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] -use std::future::Future; +use std::future::{Future, IntoFuture}; async fn func1(n: usize) -> usize { n + 1 @@ -189,3 +189,9 @@ fn await_from_macro_deep() -> impl Future<Output = u32> { // or return different things depending on its argument async { mac!(async { 42 }) } } + +// Issue 11959 +fn from_into_future(a: impl IntoFuture<Output = u32>) -> impl Future<Output = u32> { + // Do not lint: `a` is not equivalent to this expression + async { a.await } +} diff --git a/src/tools/clippy/tests/ui/redundant_async_block.rs b/src/tools/clippy/tests/ui/redundant_async_block.rs index dd96e141006..bb43403a043 100644 --- a/src/tools/clippy/tests/ui/redundant_async_block.rs +++ b/src/tools/clippy/tests/ui/redundant_async_block.rs @@ -1,7 +1,7 @@ #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] -use std::future::Future; +use std::future::{Future, IntoFuture}; async fn func1(n: usize) -> usize { n + 1 @@ -189,3 +189,9 @@ fn await_from_macro_deep() -> impl Future<Output = u32> { // or return different things depending on its argument async { mac!(async { 42 }) } } + +// Issue 11959 +fn from_into_future(a: impl IntoFuture<Output = u32>) -> impl Future<Output = u32> { + // Do not lint: `a` is not equivalent to this expression + async { a.await } +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.fixed new file mode 100644 index 00000000000..6d910678934 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.fixed @@ -0,0 +1,38 @@ +#![warn(clippy::redundant_pattern_matching)] +#![allow(clippy::needless_if, clippy::no_effect, clippy::nonminimal_bool)] + +macro_rules! condition { + () => { + true + }; +} + +macro_rules! lettrue { + (if) => { + if let true = true {} + }; + (while) => { + while let true = true {} + }; +} + +fn main() { + let mut k = 5; + + if k > 1 {} + if !(k > 5) {} + if k > 1 {} + if let (true, true) = (k > 1, k > 2) {} + while k > 1 { + k += 1; + } + while condition!() { + k += 1; + } + + k > 5; + !(k > 5); + // Whole loop is from a macro expansion, don't lint: + lettrue!(if); + lettrue!(while); +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.rs new file mode 100644 index 00000000000..a82e673982a --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.rs @@ -0,0 +1,38 @@ +#![warn(clippy::redundant_pattern_matching)] +#![allow(clippy::needless_if, clippy::no_effect, clippy::nonminimal_bool)] + +macro_rules! condition { + () => { + true + }; +} + +macro_rules! lettrue { + (if) => { + if let true = true {} + }; + (while) => { + while let true = true {} + }; +} + +fn main() { + let mut k = 5; + + if let true = k > 1 {} + if let false = k > 5 {} + if let (true) = k > 1 {} + if let (true, true) = (k > 1, k > 2) {} + while let true = k > 1 { + k += 1; + } + while let true = condition!() { + k += 1; + } + + matches!(k > 5, true); + matches!(k > 5, false); + // Whole loop is from a macro expansion, don't lint: + lettrue!(if); + lettrue!(while); +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.stderr new file mode 100644 index 00000000000..211a332d79a --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_if_let_true.stderr @@ -0,0 +1,47 @@ +error: using `if let` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:22:8 + | +LL | if let true = k > 1 {} + | ^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 1` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` + +error: using `if let` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:23:8 + | +LL | if let false = k > 5 {} + | ^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `!(k > 5)` + +error: using `if let` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:24:8 + | +LL | if let (true) = k > 1 {} + | ^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 1` + +error: using `if let` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:26:11 + | +LL | while let true = k > 1 { + | ^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 1` + +error: using `if let` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:29:11 + | +LL | while let true = condition!() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `condition!()` + +error: using `matches!` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:33:5 + | +LL | matches!(k > 5, true); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 5` + +error: using `matches!` to pattern match a bool + --> $DIR/redundant_pattern_matching_if_let_true.rs:34:5 + | +LL | matches!(k > 5, false); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `!(k > 5)` + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed index 70dd9fc250f..429d33118a5 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -18,6 +18,12 @@ fn main() { if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + // Issue 6459 + if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + + // Issue 6459 + if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + while V4(Ipv4Addr::LOCALHOST).is_ipv4() {} while V6(Ipv6Addr::LOCALHOST).is_ipv6() {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs index 6e2a2f7b6d2..e7136b72c20 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -18,6 +18,12 @@ fn main() { if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + // Issue 6459 + if matches!(V4(Ipv4Addr::LOCALHOST), V4(_)) {} + + // Issue 6459 + if matches!(V6(Ipv6Addr::LOCALHOST), V6(_)) {} + while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr index d36129a2bee..54cefa5e82b 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -20,19 +20,31 @@ LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:21:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:22:8 + | +LL | if matches!(V4(Ipv4Addr::LOCALHOST), V4(_)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` + +error: redundant pattern matching, consider using `is_ipv6()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:25:8 + | +LL | if matches!(V6(Ipv6Addr::LOCALHOST), V6(_)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` + +error: redundant pattern matching, consider using `is_ipv4()` + --> $DIR/redundant_pattern_matching_ipaddr.rs:27:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:23:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:29:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:33:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:39:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -41,7 +53,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:38:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:44:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => false, @@ -50,7 +62,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:43:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:49:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, @@ -59,7 +71,7 @@ LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:48:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:54:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => true, @@ -68,49 +80,49 @@ LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:53:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:59:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:61:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:67:20 | LL | let _ = if let V4(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:63:19 + --> $DIR/redundant_pattern_matching_ipaddr.rs:69:19 | LL | } else if let V6(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:75:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:81:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:77:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:83:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:79:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:85:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:81:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:87:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:83:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:89:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -119,7 +131,7 @@ LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:88:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:94:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, @@ -127,5 +139,5 @@ LL | | V6(_) => true, LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` -error: aborting due to 18 previous errors +error: aborting due to 20 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed index 718c2f8ea3d..08d83f87e4c 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed @@ -22,6 +22,12 @@ fn main() { bar(); } + // Issue 6459 + if Ready(42).is_ready() {} + + // Issue 6459 + if Pending::<()>.is_pending() {} + while Ready(42).is_ready() {} while Ready(42).is_pending() {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs index daa4761aff5..7bc2b3be4d3 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs @@ -22,6 +22,12 @@ fn main() { bar(); } + // Issue 6459 + if matches!(Ready(42), Ready(_)) {} + + // Issue 6459 + if matches!(Pending::<()>, Pending) {} + while let Ready(_) = Ready(42) {} while let Pending = Ready(42) {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr index c010c3c4437..de64331b4e8 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr @@ -20,25 +20,37 @@ LL | if let Ready(_) = Ready(42) { | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:25:15 + --> $DIR/redundant_pattern_matching_poll.rs:26:8 + | +LL | if matches!(Ready(42), Ready(_)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ready(42).is_ready()` + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_poll.rs:29:8 + | +LL | if matches!(Pending::<()>, Pending) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Pending::<()>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_poll.rs:31:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:27:15 + --> $DIR/redundant_pattern_matching_poll.rs:33:15 | LL | while let Pending = Ready(42) {} | ----------^^^^^^^------------ help: try: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:29:15 + --> $DIR/redundant_pattern_matching_poll.rs:35:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:35:5 + --> $DIR/redundant_pattern_matching_poll.rs:41:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -47,7 +59,7 @@ LL | | }; | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:40:5 + --> $DIR/redundant_pattern_matching_poll.rs:46:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, @@ -56,7 +68,7 @@ LL | | }; | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:45:13 + --> $DIR/redundant_pattern_matching_poll.rs:51:13 | LL | let _ = match Pending::<()> { | _____________^ @@ -66,49 +78,49 @@ LL | | }; | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:51:20 + --> $DIR/redundant_pattern_matching_poll.rs:57:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; | -------^^^^^^^^------- help: try: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:55:20 + --> $DIR/redundant_pattern_matching_poll.rs:61:20 | LL | let _ = if let Ready(_) = gen_poll() { | -------^^^^^^^^------------- help: try: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:57:19 + --> $DIR/redundant_pattern_matching_poll.rs:63:19 | LL | } else if let Pending = gen_poll() { | -------^^^^^^^------------- help: try: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:73:12 + --> $DIR/redundant_pattern_matching_poll.rs:79:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:75:12 + --> $DIR/redundant_pattern_matching_poll.rs:81:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:77:15 + --> $DIR/redundant_pattern_matching_poll.rs:83:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:79:15 + --> $DIR/redundant_pattern_matching_poll.rs:85:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:81:5 + --> $DIR/redundant_pattern_matching_poll.rs:87:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -117,7 +129,7 @@ LL | | }; | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:86:5 + --> $DIR/redundant_pattern_matching_poll.rs:92:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, @@ -125,5 +137,5 @@ LL | | Pending => true, LL | | }; | |_____^ help: try: `Pending::<()>.is_pending()` -error: aborting due to 18 previous errors +error: aborting due to 20 previous errors diff --git a/src/tools/clippy/tests/ui/result_filter_map.fixed b/src/tools/clippy/tests/ui/result_filter_map.fixed new file mode 100644 index 00000000000..e8943dbc72d --- /dev/null +++ b/src/tools/clippy/tests/ui/result_filter_map.fixed @@ -0,0 +1,27 @@ +#![warn(clippy::result_filter_map)] +#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] + +fn odds_out(x: i32) -> Result<i32, ()> { + if x % 2 == 0 { Ok(x) } else { Err(()) } +} + +fn main() { + // Unlike the Option version, Result does not have a filter operation => we will check for iterators + // only + let _ = vec![Ok(1) as Result<i32, ()>] + .into_iter() + .flatten(); + + let _ = vec![Ok(1) as Result<i32, ()>] + .into_iter() + .flatten(); + + let _ = vec![1] + .into_iter() + .map(odds_out) + .flatten(); + let _ = vec![1] + .into_iter() + .map(odds_out) + .flatten(); +} diff --git a/src/tools/clippy/tests/ui/result_filter_map.rs b/src/tools/clippy/tests/ui/result_filter_map.rs new file mode 100644 index 00000000000..bfe47ffcf38 --- /dev/null +++ b/src/tools/clippy/tests/ui/result_filter_map.rs @@ -0,0 +1,35 @@ +#![warn(clippy::result_filter_map)] +#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] + +fn odds_out(x: i32) -> Result<i32, ()> { + if x % 2 == 0 { Ok(x) } else { Err(()) } +} + +fn main() { + // Unlike the Option version, Result does not have a filter operation => we will check for iterators + // only + let _ = vec![Ok(1) as Result<i32, ()>] + .into_iter() + .filter(Result::is_ok) + //~^ ERROR: `filter` for `Ok` followed by `unwrap` + .map(Result::unwrap); + + let _ = vec![Ok(1) as Result<i32, ()>] + .into_iter() + .filter(|o| o.is_ok()) + //~^ ERROR: `filter` for `Ok` followed by `unwrap` + .map(|o| o.unwrap()); + + let _ = vec![1] + .into_iter() + .map(odds_out) + .filter(Result::is_ok) + //~^ ERROR: `filter` for `Ok` followed by `unwrap` + .map(Result::unwrap); + let _ = vec![1] + .into_iter() + .map(odds_out) + .filter(|o| o.is_ok()) + //~^ ERROR: `filter` for `Ok` followed by `unwrap` + .map(|o| o.unwrap()); +} diff --git a/src/tools/clippy/tests/ui/result_filter_map.stderr b/src/tools/clippy/tests/ui/result_filter_map.stderr new file mode 100644 index 00000000000..4687794949d --- /dev/null +++ b/src/tools/clippy/tests/ui/result_filter_map.stderr @@ -0,0 +1,41 @@ +error: `filter` for `Ok` followed by `unwrap` + --> $DIR/result_filter_map.rs:13:10 + | +LL | .filter(Result::is_ok) + | __________^ +LL | | +LL | | .map(Result::unwrap); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + | + = note: `-D clippy::result-filter-map` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::result_filter_map)]` + +error: `filter` for `Ok` followed by `unwrap` + --> $DIR/result_filter_map.rs:19:10 + | +LL | .filter(|o| o.is_ok()) + | __________^ +LL | | +LL | | .map(|o| o.unwrap()); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Ok` followed by `unwrap` + --> $DIR/result_filter_map.rs:26:10 + | +LL | .filter(Result::is_ok) + | __________^ +LL | | +LL | | .map(Result::unwrap); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Ok` followed by `unwrap` + --> $DIR/result_filter_map.rs:32:10 + | +LL | .filter(|o| o.is_ok()) + | __________^ +LL | | +LL | | .map(|o| o.unwrap()); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.rs b/src/tools/clippy/tests/ui/unconditional_recursion.rs new file mode 100644 index 00000000000..1169118de83 --- /dev/null +++ b/src/tools/clippy/tests/ui/unconditional_recursion.rs @@ -0,0 +1,163 @@ +//@no-rustfix + +#![warn(clippy::unconditional_recursion)] +#![allow(clippy::partialeq_ne_impl)] + +enum Foo { + A, + B, +} + +impl PartialEq for Foo { + fn ne(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self != other + } + fn eq(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self == other + } +} + +enum Foo2 { + A, + B, +} + +impl PartialEq for Foo2 { + fn ne(&self, other: &Self) -> bool { + self != &Foo2::B // no error here + } + fn eq(&self, other: &Self) -> bool { + self == &Foo2::B // no error here + } +} + +enum Foo3 { + A, + B, +} + +impl PartialEq for Foo3 { + fn ne(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self.ne(other) + } + fn eq(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self.eq(other) + } +} + +enum Foo4 { + A, + B, +} + +impl PartialEq for Foo4 { + fn ne(&self, other: &Self) -> bool { + self.eq(other) // no error + } + fn eq(&self, other: &Self) -> bool { + self.ne(other) // no error + } +} + +enum Foo5 { + A, + B, +} + +impl Foo5 { + fn a(&self) -> bool { + true + } +} + +impl PartialEq for Foo5 { + fn ne(&self, other: &Self) -> bool { + self.a() // no error + } + fn eq(&self, other: &Self) -> bool { + self.a() // no error + } +} + +struct S; + +// Check the order doesn't matter. +impl PartialEq for S { + fn ne(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + other != self + } + fn eq(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + other == self + } +} + +struct S2; + +// Check that if the same element is compared, it's also triggering the lint. +impl PartialEq for S2 { + fn ne(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + other != other + } + fn eq(&self, other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + other == other + } +} + +struct S3; + +impl PartialEq for S3 { + fn ne(&self, _other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self != self + } + fn eq(&self, _other: &Self) -> bool { + //~^ ERROR: function cannot return without recursing + self == self + } +} + +// There should be no warning here! +#[derive(PartialEq)] +enum E { + A, + B, +} + +#[derive(PartialEq)] +struct Bar<T: PartialEq>(T); + +struct S4; + +impl PartialEq for S4 { + fn eq(&self, other: &Self) -> bool { + // No warning here. + Bar(self) == Bar(other) + } +} + +macro_rules! impl_partial_eq { + ($ty:ident) => { + impl PartialEq for $ty { + fn eq(&self, other: &Self) -> bool { + self == other + } + } + }; +} + +struct S5; + +impl_partial_eq!(S5); +//~^ ERROR: function cannot return without recursing + +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr new file mode 100644 index 00000000000..1fb01c00f19 --- /dev/null +++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr @@ -0,0 +1,251 @@ +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:42:5 + | +LL | fn ne(&self, other: &Self) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | self.ne(other) + | -------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `-D unconditional-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unconditional_recursion)]` + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:46:5 + | +LL | fn eq(&self, other: &Self) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | self.eq(other) + | -------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:12:5 + | +LL | / fn ne(&self, other: &Self) -> bool { +LL | | +LL | | self != other +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:14:9 + | +LL | self != other + | ^^^^^^^^^^^^^ + = note: `-D clippy::unconditional-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unconditional_recursion)]` + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:16:5 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | +LL | | self == other +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:18:9 + | +LL | self == other + | ^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:42:5 + | +LL | / fn ne(&self, other: &Self) -> bool { +LL | | +LL | | self.ne(other) +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:44:9 + | +LL | self.ne(other) + | ^^^^^^^^^^^^^^ + +error: parameter is only used in recursion + --> $DIR/unconditional_recursion.rs:42:18 + | +LL | fn ne(&self, other: &Self) -> bool { + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_other` + | +note: parameter used here + --> $DIR/unconditional_recursion.rs:44:17 + | +LL | self.ne(other) + | ^^^^^ + = note: `-D clippy::only-used-in-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::only_used_in_recursion)]` + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:46:5 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | +LL | | self.eq(other) +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:48:9 + | +LL | self.eq(other) + | ^^^^^^^^^^^^^^ + +error: parameter is only used in recursion + --> $DIR/unconditional_recursion.rs:46:18 + | +LL | fn eq(&self, other: &Self) -> bool { + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_other` + | +note: parameter used here + --> $DIR/unconditional_recursion.rs:48:17 + | +LL | self.eq(other) + | ^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:90:5 + | +LL | / fn ne(&self, other: &Self) -> bool { +LL | | +LL | | other != self +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:92:9 + | +LL | other != self + | ^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:94:5 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | +LL | | other == self +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:96:9 + | +LL | other == self + | ^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:104:5 + | +LL | / fn ne(&self, other: &Self) -> bool { +LL | | +LL | | other != other +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:106:9 + | +LL | other != other + | ^^^^^^^^^^^^^^ + +error: equal expressions as operands to `!=` + --> $DIR/unconditional_recursion.rs:106:9 + | +LL | other != other + | ^^^^^^^^^^^^^^ + | + = note: `#[deny(clippy::eq_op)]` on by default + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:108:5 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | +LL | | other == other +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:110:9 + | +LL | other == other + | ^^^^^^^^^^^^^^ + +error: equal expressions as operands to `==` + --> $DIR/unconditional_recursion.rs:110:9 + | +LL | other == other + | ^^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:117:5 + | +LL | / fn ne(&self, _other: &Self) -> bool { +LL | | +LL | | self != self +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:119:9 + | +LL | self != self + | ^^^^^^^^^^^^ + +error: equal expressions as operands to `!=` + --> $DIR/unconditional_recursion.rs:119:9 + | +LL | self != self + | ^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:121:5 + | +LL | / fn eq(&self, _other: &Self) -> bool { +LL | | +LL | | self == self +LL | | } + | |_____^ + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:123:9 + | +LL | self == self + | ^^^^^^^^^^^^ + +error: equal expressions as operands to `==` + --> $DIR/unconditional_recursion.rs:123:9 + | +LL | self == self + | ^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/unconditional_recursion.rs:149:13 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | self == other +LL | | } + | |_____________^ +... +LL | impl_partial_eq!(S5); + | -------------------- in this macro invocation + | +note: recursive call site + --> $DIR/unconditional_recursion.rs:150:17 + | +LL | self == other + | ^^^^^^^^^^^^^ +... +LL | impl_partial_eq!(S5); + | -------------------- in this macro invocation + = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 19 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed new file mode 100644 index 00000000000..53dc3c43e2f --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed @@ -0,0 +1,21 @@ +#[allow(clippy::single_char_pattern)] + +fn main() { + let _ = "a".split('a').next().unwrap(); + //~^ ERROR: unnecessary use of `to_string` + let _ = "a".split("a").next().unwrap(); + //~^ ERROR: unnecessary use of `to_string` + let _ = "a".split('a').next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + let _ = "a".split("a").next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + + let _ = [1].split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_vec` + let _ = [1].split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_vec` + let _ = [1].split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + let _ = [1].split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs new file mode 100644 index 00000000000..62400e7eee1 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs @@ -0,0 +1,21 @@ +#[allow(clippy::single_char_pattern)] + +fn main() { + let _ = "a".to_string().split('a').next().unwrap(); + //~^ ERROR: unnecessary use of `to_string` + let _ = "a".to_string().split("a").next().unwrap(); + //~^ ERROR: unnecessary use of `to_string` + let _ = "a".to_owned().split('a').next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + let _ = "a".to_owned().split("a").next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + + let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_vec` + let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_vec` + let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` + let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); + //~^ ERROR: unnecessary use of `to_owned` +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr new file mode 100644 index 00000000000..cfb3766d15e --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr @@ -0,0 +1,53 @@ +error: unnecessary use of `to_string` + --> $DIR/unnecessary_to_owned_on_split.rs:4:13 + | +LL | let _ = "a".to_string().split('a').next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')` + | + = note: `-D clippy::unnecessary-to-owned` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` + +error: unnecessary use of `to_string` + --> $DIR/unnecessary_to_owned_on_split.rs:6:13 + | +LL | let _ = "a".to_string().split("a").next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` + +error: unnecessary use of `to_owned` + --> $DIR/unnecessary_to_owned_on_split.rs:8:13 + | +LL | let _ = "a".to_owned().split('a').next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')` + +error: unnecessary use of `to_owned` + --> $DIR/unnecessary_to_owned_on_split.rs:10:13 + | +LL | let _ = "a".to_owned().split("a").next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` + +error: unnecessary use of `to_vec` + --> $DIR/unnecessary_to_owned_on_split.rs:13:13 + | +LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` + +error: unnecessary use of `to_vec` + --> $DIR/unnecessary_to_owned_on_split.rs:15:13 + | +LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` + +error: unnecessary use of `to_owned` + --> $DIR/unnecessary_to_owned_on_split.rs:17:13 + | +LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` + +error: unnecessary use of `to_owned` + --> $DIR/unnecessary_to_owned_on_split.rs:19:13 + | +LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html index 99e211654d1..a5274eeb349 100644 --- a/src/tools/clippy/util/gh-pages/index.html +++ b/src/tools/clippy/util/gh-pages/index.html @@ -566,8 +566,74 @@ Otherwise, have a great day =^.^= </div> </div> - <a href="https://github.com/rust-lang/rust-clippy"> - <img style="position: absolute; top: 0; right: 0; border: 0; clip-path: polygon(0% 0%, 100% 0%, 100% 100%);" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"/> + <a + aria-label="View source on GitHub" + class="github-corner" + href="https://github.com/rust-lang/rust-clippy" + rel="noopener noreferrer" + target="_blank" + > + <svg + width="80" + height="80" + viewBox="0 0 250 250" + style="position: absolute; top: 0; border: 0; right: 0" + aria-hidden="true" + > + <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" fill="var(--theme-color)"></path> + <path + d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" + fill="currentColor" + style="transform-origin: 130px 106px" + class="octo-arm" + ></path> + <path + d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" + fill="currentColor" + class="octo-body" + ></path> + </svg> + <style> + :root { + --theme-background-color: black; + --theme-foreground-color: white; + } + @media (prefers-color-scheme: dark) { + :root { + --theme-background-color: white; + --theme-foreground-color: black; + } + } + .github-corner svg { + fill: var(--theme-background-color); + color: var(--theme-foreground-color); + } + .github-corner:hover .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + @keyframes octocat-wave { + 0%, + 100% { + transform: rotate(0); + } + 20%, + 60% { + transform: rotate(-25deg); + } + 40%, + 80% { + transform: rotate(10deg); + } + } + @media (max-width: 500px) { + .github-corner:hover .octo-arm { + animation: none; + } + .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + } + </style> </a> <script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/12.3.2/markdown-it.min.js"></script> diff --git a/tests/codegen/inherit_overflow.rs b/tests/codegen/inherit_overflow.rs index 39909d7abfd..fa9ee0ae12a 100644 --- a/tests/codegen/inherit_overflow.rs +++ b/tests/codegen/inherit_overflow.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zmir-enable-passes=+Inline,+ConstProp --crate-type lib +// compile-flags: -Zmir-enable-passes=+Inline,+GVN --crate-type lib // revisions: ASSERT NOASSERT //[ASSERT] compile-flags: -Coverflow-checks=on //[NOASSERT] compile-flags: -Coverflow-checks=off diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index b120e28c464..28f319bfb80 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -7,19 +7,17 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 13, 1) to (start + 0, 23) Function name: async2::async_func::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0d, 17, 03, 09, 05, 03, 0a, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 05, 00, 04, 01, 0d, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 03, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of expressions: 1 +- expression 0 operands: lhs = Counter(1), rhs = Zero Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 13, 23) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - c1) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) - = (c1 + (c0 - c1)) +- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + Zero) Function name: async2::async_func_just_println Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 24] diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 3549116db7a..3a803e3c18f 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -25,18 +25,18 @@ Number of file 0 mappings: 2 - Code(Zero) at (prev + 0, 32) to (start + 0, 33) Function name: <partial_eq::Version as core::cmp::PartialOrd>::partial_cmp -Raw bytes (22): 0x[01, 01, 04, 07, 0b, 05, 09, 0f, 15, 0d, 11, 02, 01, 04, 27, 00, 28, 03, 00, 30, 00, 31] +Raw bytes (22): 0x[01, 01, 04, 07, 0b, 00, 09, 0f, 15, 00, 11, 02, 01, 04, 27, 00, 28, 03, 00, 30, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 - expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) -- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Zero, rhs = Counter(2) - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) -- expression 3 operands: lhs = Counter(3), rhs = Counter(4) +- expression 3 operands: lhs = Zero, rhs = Counter(4) Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 39) to (start + 0, 40) - Code(Expression(0, Add)) at (prev + 0, 48) to (start + 0, 49) - = ((c1 + c2) + ((c3 + c4) + c5)) + = ((Zero + c2) + ((Zero + c4) + c5)) Function name: <partial_eq::Version as core::fmt::Debug>::fmt Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 11, 00, 16] diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs index 98c762e4097..84a04ff913b 100644 --- a/tests/incremental/hashes/for_loops.rs +++ b/tests/incremental/hashes/for_loops.rs @@ -103,9 +103,9 @@ pub fn change_iterable() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iterable() { let mut _x = 0; diff --git a/tests/incremental/string_constant.rs b/tests/incremental/string_constant.rs index e15a8d18f85..47cd100b136 100644 --- a/tests/incremental/string_constant.rs +++ b/tests/incremental/string_constant.rs @@ -1,5 +1,5 @@ // revisions: cfail1 cfail2 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Copt-level=0 // build-pass (FIXME(62277): could be check-pass?) #![allow(warnings)] diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 59e27512464..3a9c80caa1e 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -11,7 +11,6 @@ CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), (), ], - Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:16:5: 16:14 (#9), @@ -29,7 +28,6 @@ CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), (), ], - Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:17:5: 17:14 (#11), diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir index 9cc4c7c4d76..f089c6741fe 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC9: &&[(Option<i32>, &[&str])]}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir index faa9d20f2d5..9cbbaf302be 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC9: &&[(Option<i32>, &[&str])]}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation.rs b/tests/mir-opt/const_allocation.rs index 577c61aeb7d..5b5fb524fdb 100644 --- a/tests/mir-opt/const_allocation.rs +++ b/tests/mir-opt/const_allocation.rs @@ -1,11 +1,11 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH static FOO: &[(Option<i32>, &[&str])] = &[(None, &[]), (None, &["foo", "bar"]), (Some(42), &["meh", "mop", "möp"])]; -// EMIT_MIR const_allocation.main.ConstProp.after.mir +// EMIT_MIR const_allocation.main.GVN.after.mir fn main() { FOO; } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir index 898835b46e4..dfa2d808128 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC9: &&[(Option<i32>, &[&u8])]}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir index f5352c2aebb..02b66987169 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC9: &&[(Option<i32>, &[&u8])]}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.rs b/tests/mir-opt/const_allocation2.rs index 0fcfaad842c..171592889d5 100644 --- a/tests/mir-opt/const_allocation2.rs +++ b/tests/mir-opt/const_allocation2.rs @@ -1,8 +1,8 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR const_allocation2.main.ConstProp.after.mir +// EMIT_MIR const_allocation2.main.GVN.after.mir fn main() { FOO; } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir index 624047f5b6f..386a55ee6fa 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC4: &&Packed}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir index cdd4758e153..b9e98f8cd4c 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after ConstProp +// MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - StorageLive(_2); + nop; _2 = const {ALLOC2: &&Packed}; _1 = (*_2); - StorageDead(_2); + nop; StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.rs b/tests/mir-opt/const_allocation3.rs index b8c9f50977e..91a30f0587b 100644 --- a/tests/mir-opt/const_allocation3.rs +++ b/tests/mir-opt/const_allocation3.rs @@ -1,8 +1,8 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR const_allocation3.main.ConstProp.after.mir +// EMIT_MIR const_allocation3.main.GVN.after.mir fn main() { FOO; } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 87c07279552..c1529dbee13 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -34,7 +34,8 @@ debug f => _10; let _11: std::option::Option<u16>; scope 7 { - debug o => _11; +- debug o => _11; ++ debug o => const Option::<u16>::Some(99_u16); let _12: Point; scope 8 { - debug p => _12; @@ -54,11 +55,11 @@ } bb0: { - StorageLive(_1); + nop; _1 = const 1_u8; - StorageLive(_2); + nop; _2 = const 2_u8; - StorageLive(_3); + nop; _3 = const 3_u8; StorageLive(_4); StorageLive(_5); @@ -79,17 +80,17 @@ StorageLive(_10); _10 = (const true, const false, const 123_u32); StorageLive(_11); - _11 = Option::<u16>::Some(const 99_u16); + _11 = const Option::<u16>::Some(99_u16); StorageLive(_12); _12 = const Point {{ x: 32_u32, y: 32_u32 }}; StorageLive(_13); - StorageLive(_14); + nop; _14 = const 32_u32; StorageLive(_15); _15 = const 32_u32; _13 = const 64_u32; StorageDead(_15); - StorageDead(_14); + nop; _0 = const (); StorageDead(_13); StorageDead(_12); @@ -97,9 +98,9 @@ StorageDead(_10); StorageDead(_9); StorageDead(_4); - StorageDead(_3); - StorageDead(_2); - StorageDead(_1); + nop; + nop; + nop; return; } } @@ -108,3 +109,7 @@ 20 00 00 00 20 00 00 00 │ ... ... } + ALLOC1 (size: 4, align: 2) { + 01 00 63 00 │ ..c. + } + diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs index 0e5ac4b8bd6..db0c5dbb28f 100644 --- a/tests/mir-opt/const_debuginfo.rs +++ b/tests/mir-opt/const_debuginfo.rs @@ -1,5 +1,5 @@ // unit-test: ConstDebugInfo -// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+ConstProp +// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+GVN struct Point { x: u32, @@ -15,7 +15,7 @@ fn main() { // CHECK: debug sum => const 6_u8; // CHECK: debug s => const "hello, world!"; // CHECK: debug f => {{_.*}}; - // CHECK: debug o => {{_.*}}; + // CHECK: debug o => const Option::<u16>::Some(99_u16); // CHECK: debug p => const Point // CHECK: debug a => const 64_u32; let x = 1u8; diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index 6b96c24d460..2285962fad1 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.ConstProp.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `fn0` before ConstProp -+ // MIR for `fn0` after ConstProp +- // MIR for `fn0` before GVN ++ // MIR for `fn0` after GVN fn fn0() -> bool { let mut _0: bool; @@ -23,24 +23,34 @@ bb0: { StorageLive(_2); - _2 = (const 1_i32, const false); - StorageLive(_3); +- _2 = (const 1_i32, const false); +- StorageLive(_3); ++ _2 = const (1_i32, false); ++ nop; _3 = &raw mut (_2.1: bool); - _2 = (const 1_i32, const false); +- _2 = (const 1_i32, const false); ++ _2 = const (1_i32, false); StorageLive(_4); (*_3) = const true; _4 = const (); StorageDead(_4); - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); _6 = (_2.1: bool); _5 = Not(move _6); StorageDead(_6); _0 = _5; - StorageDead(_5); - StorageDead(_3); +- StorageDead(_5); +- StorageDead(_3); ++ nop; ++ nop; StorageDead(_2); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 01 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs index 730ebe2ca63..1ab8a602823 100644 --- a/tests/mir-opt/const_prop/address_of_pair.rs +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -1,6 +1,6 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR address_of_pair.fn0.ConstProp.diff +// EMIT_MIR address_of_pair.fn0.GVN.diff pub fn fn0() -> bool { // CHECK-LABEL: fn fn0( // CHECK: debug pair => [[pair:_.*]]; diff --git a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff index 5e2db148de8..4f0f7fa8fa2 100644 --- a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `foo` before ConstProp -+ // MIR for `foo` after ConstProp +- // MIR for `foo` before GVN ++ // MIR for `foo` after GVN fn foo(_1: u8) -> () { debug x => _1; @@ -25,7 +25,8 @@ StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = (const 0_i32, move _5); +- _4 = (const 0_i32, move _5); ++ _4 = (const 0_i32, _1); StorageDead(_5); - _3 = (_4.0: i32); - _2 = Add(move _3, const 1_i32); @@ -38,7 +39,8 @@ StorageLive(_8); StorageLive(_9); _9 = _1; - _8 = (move _9, const 1_i32); +- _8 = (move _9, const 1_i32); ++ _8 = (_1, const 1_i32); StorageDead(_9); - _7 = (_8.1: i32); - _6 = Add(move _7, const 2_i32); diff --git a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff index 5e2db148de8..4f0f7fa8fa2 100644 --- a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `foo` before ConstProp -+ // MIR for `foo` after ConstProp +- // MIR for `foo` before GVN ++ // MIR for `foo` after GVN fn foo(_1: u8) -> () { debug x => _1; @@ -25,7 +25,8 @@ StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = (const 0_i32, move _5); +- _4 = (const 0_i32, move _5); ++ _4 = (const 0_i32, _1); StorageDead(_5); - _3 = (_4.0: i32); - _2 = Add(move _3, const 1_i32); @@ -38,7 +39,8 @@ StorageLive(_8); StorageLive(_9); _9 = _1; - _8 = (move _9, const 1_i32); +- _8 = (move _9, const 1_i32); ++ _8 = (_1, const 1_i32); StorageDead(_9); - _7 = (_8.1: i32); - _6 = Add(move _7, const 2_i32); diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff index a4911a6d48a..854e27445af 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,7 +13,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); StorageLive(_3); _3 = (const 0_i32, const 1_u8, const 2_i32); @@ -35,7 +36,8 @@ StorageDead(_5); StorageDead(_4); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff index b8b9fa5cc1c..f6c4b2c9240 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,7 +13,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); StorageLive(_3); _3 = (const 0_i32, const 1_u8, const 2_i32); @@ -35,7 +36,8 @@ StorageDead(_5); StorageDead(_4); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs index fa716b0843d..3dd37b5910e 100644 --- a/tests/mir-opt/const_prop/aggregate.rs +++ b/tests/mir-opt/const_prop/aggregate.rs @@ -1,8 +1,8 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -O -// EMIT_MIR aggregate.main.ConstProp.diff +// EMIT_MIR aggregate.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; @@ -15,7 +15,7 @@ fn main() { } // Verify that we still propagate if part of the aggregate is not known. -// EMIT_MIR aggregate.foo.ConstProp.diff +// EMIT_MIR aggregate.foo.GVN.diff fn foo(x: u8) { // CHECK-LABEL: fn foo( // CHECK: debug first => [[first:_.*]]; diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff index b2f58f8f771..f9537661e8c 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,12 +18,11 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff index f9e3f8f171a..07886779fea 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,12 +18,11 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff index b2f58f8f771..f9537661e8c 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,12 +18,11 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index f9e3f8f171a..07886779fea 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,12 +18,11 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs index c4c46d78f75..2ae5087751f 100644 --- a/tests/mir-opt/const_prop/array_index.rs +++ b/tests/mir-opt/const_prop/array_index.rs @@ -1,8 +1,8 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR array_index.main.ConstProp.diff +// EMIT_MIR array_index.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff index cead70110dc..4838efba6f9 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,7 +18,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 0_i32; StorageLive(_2); StorageLive(_3); @@ -47,7 +48,8 @@ StorageDead(_3); _0 = const (); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff index c9c4ba8548c..7f403d6efc1 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,7 +18,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 0_i32; StorageLive(_2); StorageLive(_3); @@ -47,7 +48,8 @@ StorageDead(_3); _0 = const (); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs index 0e8765a0771..2ba53a80c43 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs @@ -1,7 +1,7 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff +// EMIT_MIR bad_op_div_by_zero.main.GVN.diff #[allow(unconditional_panic)] fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff index 2666fd9eb91..59f2eb86f50 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,7 +18,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 0_i32; StorageLive(_2); StorageLive(_3); @@ -47,7 +48,8 @@ StorageDead(_3); _0 = const (); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff index 679df90f16f..9b866082788 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,7 +18,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 0_i32; StorageLive(_2); StorageLive(_3); @@ -47,7 +48,8 @@ StorageDead(_3); _0 = const (); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs index d895d9e2155..9ab57750de0 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs @@ -1,7 +1,7 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff +// EMIT_MIR bad_op_mod_by_zero.main.GVN.diff #[allow(unconditional_panic)] fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index e443c8991f9..a42f9291324 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,15 +22,18 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -47,7 +50,8 @@ StorageDead(_6); _0 = const (); StorageDead(_5); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index 592f43f4739..f2d6de6621b 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,15 +22,18 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -47,7 +50,8 @@ StorageDead(_6); _0 = const (); StorageDead(_5); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index e443c8991f9..a42f9291324 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,15 +22,18 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -47,7 +50,8 @@ StorageDead(_6); _0 = const (); StorageDead(_5); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index 592f43f4739..f2d6de6621b 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,15 +22,18 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -47,7 +50,8 @@ StorageDead(_6); _0 = const (); StorageDead(_5); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs index 266105c11f2..c6d63f0bf18 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs @@ -1,8 +1,8 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff +// EMIT_MIR bad_op_unsafe_oob_for_slices.main.GVN.diff #[allow(unconditional_panic)] fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/boolean_identities.rs b/tests/mir-opt/const_prop/boolean_identities.rs index 2aa038034d8..f6575ac8e54 100644 --- a/tests/mir-opt/const_prop/boolean_identities.rs +++ b/tests/mir-opt/const_prop/boolean_identities.rs @@ -1,13 +1,14 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR boolean_identities.test.ConstProp.diff +// EMIT_MIR boolean_identities.test.GVN.diff pub fn test(x: bool, y: bool) -> bool { // CHECK-LABEL: fn test( // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; - // CHECK: [[a]] = const true; - // CHECK: [[b]] = const false; - // CHECK: _0 = const false; + // FIXME(cjgillot) simplify algebraic identity + // CHECK-NOT: [[a]] = const true; + // CHECK-NOT: [[b]] = const false; + // CHECK-NOT: _0 = const false; let a = (y | true); let b = (x & false); a & b diff --git a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff index 41e1acdff59..eca87af7527 100644 --- a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff +++ b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `test` before ConstProp -+ // MIR for `test` after ConstProp +- // MIR for `test` before GVN ++ // MIR for `test` after GVN fn test(_1: bool, _2: bool) -> bool { debug x => _1; @@ -19,30 +19,32 @@ } bb0: { - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_4); _4 = _2; - _3 = BitOr(move _4, const true); -+ _3 = const true; ++ _3 = BitOr(_2, const true); StorageDead(_4); - StorageLive(_5); +- StorageLive(_5); ++ nop; StorageLive(_6); _6 = _1; - _5 = BitAnd(move _6, const false); -+ _5 = const false; ++ _5 = BitAnd(_1, const false); StorageDead(_6); StorageLive(_7); -- _7 = _3; -+ _7 = const true; + _7 = _3; StorageLive(_8); -- _8 = _5; + _8 = _5; - _0 = BitAnd(move _7, move _8); -+ _8 = const false; -+ _0 = const false; ++ _0 = BitAnd(_3, _5); StorageDead(_8); StorageDead(_7); - StorageDead(_5); - StorageDead(_3); +- StorageDead(_5); +- StorageDead(_3); ++ nop; ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff index c9670a5ee43..b3fdaa5ee82 100644 --- a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff index 64fe72be5c8..d0350c97253 100644 --- a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs index 90a8e33e823..5227d7b8b8b 100644 --- a/tests/mir-opt/const_prop/boxes.rs +++ b/tests/mir-opt/const_prop/boxes.rs @@ -1,4 +1,4 @@ -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -O // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -6,7 +6,7 @@ // Note: this test verifies that we, in fact, do not const prop `#[rustc_box]` -// EMIT_MIR boxes.main.ConstProp.diff +// EMIT_MIR boxes.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/cast.main.ConstProp.diff b/tests/mir-opt/const_prop/cast.main.GVN.diff index c63adcf1191..bc442c4e446 100644 --- a/tests/mir-opt/const_prop/cast.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/cast.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/cast.rs b/tests/mir-opt/const_prop/cast.rs index b81c2740a73..00a8bcd1adb 100644 --- a/tests/mir-opt/const_prop/cast.rs +++ b/tests/mir-opt/const_prop/cast.rs @@ -1,5 +1,5 @@ -// unit-test: ConstProp -// EMIT_MIR cast.main.ConstProp.diff +// unit-test: GVN +// EMIT_MIR cast.main.GVN.diff fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff index 5a958cc7a47..d5117b2f638 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff index ab48186aed9..2118d37672c 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/checked_add.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs index 571a5cc4e4d..0abcb5dd3d4 100644 --- a/tests/mir-opt/const_prop/checked_add.rs +++ b/tests/mir-opt/const_prop/checked_add.rs @@ -1,8 +1,8 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -C overflow-checks=on -// EMIT_MIR checked_add.main.ConstProp.diff +// EMIT_MIR checked_add.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff index ba2e89f0a74..803e1d711de 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `hello` before ConstProp -+ // MIR for `hello` after ConstProp +- // MIR for `hello` before GVN ++ // MIR for `hello` after GVN fn hello() -> () { let mut _0: (); @@ -8,9 +8,8 @@ bb0: { StorageLive(_1); -- _1 = const _; + _1 = const _; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; -+ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff index e0a610f60a7..f40eb38c634 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `hello` before ConstProp -+ // MIR for `hello` after ConstProp +- // MIR for `hello` before GVN ++ // MIR for `hello` after GVN fn hello() -> () { let mut _0: (); @@ -8,9 +8,8 @@ bb0: { StorageLive(_1); -- _1 = const _; + _1 = const _; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; -+ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs index 5fc13e20275..3cb9a4911a9 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.rs +++ b/tests/mir-opt/const_prop/control_flow_simplification.rs @@ -1,6 +1,6 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -Zmir-opt-level=1 trait NeedsDrop: Sized { @@ -9,7 +9,7 @@ trait NeedsDrop: Sized { impl<This> NeedsDrop for This {} -// EMIT_MIR control_flow_simplification.hello.ConstProp.diff +// EMIT_MIR control_flow_simplification.hello.GVN.diff // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir fn hello<T>(){ if <bool>::NEEDS { diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff index e02e7f320b8..70c3c3fe7e4 100644 --- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff index e02e7f320b8..70c3c3fe7e4 100644 --- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/discriminant.rs b/tests/mir-opt/const_prop/discriminant.rs index 0ed683d629c..53874e9528e 100644 --- a/tests/mir-opt/const_prop/discriminant.rs +++ b/tests/mir-opt/const_prop/discriminant.rs @@ -1,4 +1,4 @@ -// unit-test: ConstProp +// unit-test: GVN // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with // `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect` @@ -6,7 +6,7 @@ // Fixing either of those will allow us to const-prop this away. // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR discriminant.main.ConstProp.diff +// EMIT_MIR discriminant.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: bb0: { diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff index 530cfc6539a..8301a4c1aa8 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/indirect.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff index 08cf72e47a9..8dcbfd2c2c1 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/indirect.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs index d3c42e3eb0b..d089418e898 100644 --- a/tests/mir-opt/const_prop/indirect.rs +++ b/tests/mir-opt/const_prop/indirect.rs @@ -1,8 +1,8 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -C overflow-checks=on -// EMIT_MIR indirect.main.ConstProp.diff +// EMIT_MIR indirect.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff index 4eafb8d0917..7dd80d64360 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `bar` before ConstProp -+ // MIR for `bar` after ConstProp +- // MIR for `bar` before GVN ++ // MIR for `bar` after GVN fn bar() -> () { let mut _0: (); @@ -19,12 +19,15 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32,); +- _1 = (const 1_i32,); ++ _1 = const (1_i32,); StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _3 = &raw mut (_1.0: i32); (*_3) = const 5_i32; - StorageDead(_3); +- StorageDead(_3); ++ nop; _2 = const (); StorageDead(_2); StorageLive(_4); diff --git a/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff index 445d9895d6a..c4b647d9d2d 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `foo` before ConstProp -+ // MIR for `foo` after ConstProp +- // MIR for `foo` before GVN ++ // MIR for `foo` after GVN fn foo() -> () { let mut _0: (); @@ -16,11 +16,14 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32,); - StorageLive(_2); +- _1 = (const 1_i32,); +- StorageLive(_2); ++ _1 = const (1_i32,); ++ nop; _2 = &mut (_1.0: i32); (*_2) = const 5_i32; - StorageDead(_2); +- StorageDead(_2); ++ nop; StorageLive(_3); StorageLive(_4); _4 = (_1.0: i32); diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs index ec9da6e8e5c..a4236060c81 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.rs +++ b/tests/mir-opt/const_prop/indirect_mutation.rs @@ -1,13 +1,13 @@ -// unit-test: ConstProp +// unit-test: GVN // Check that we do not propagate past an indirect mutation. #![feature(raw_ref_op)] -// EMIT_MIR indirect_mutation.foo.ConstProp.diff +// EMIT_MIR indirect_mutation.foo.GVN.diff fn foo() { // CHECK-LABEL: fn foo( // CHECK: debug u => _1; // CHECK: debug y => _3; - // CHECK: _1 = (const 1_i32,); + // CHECK: _1 = const (1_i32,); // CHECK: _2 = &mut (_1.0: i32); // CHECK: (*_2) = const 5_i32; // CHECK: _4 = (_1.0: i32); @@ -18,7 +18,7 @@ fn foo() { let y = { u.0 } == 5; } -// EMIT_MIR indirect_mutation.bar.ConstProp.diff +// EMIT_MIR indirect_mutation.bar.GVN.diff fn bar() { // CHECK-LABEL: fn bar( // CHECK: debug v => _1; diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff index 11cdf9e09db..4c2df228eb8 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff index 181a2f287d6..c4e666b489e 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs index 5b561ae14ad..c5b1dbe37a9 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.rs +++ b/tests/mir-opt/const_prop/inherit_overflow.rs @@ -1,10 +1,10 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -Zmir-enable-passes=+Inline // After inlining, this will contain a `CheckedBinaryOp`. // Propagating the overflow is ok as codegen will just skip emitting the panic. -// EMIT_MIR inherit_overflow.main.ConstProp.diff +// EMIT_MIR inherit_overflow.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: {{_.*}} = const (0_u8, true); diff --git a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff index 10e978a683a..da5bf1cf42c 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -35,17 +35,14 @@ StorageLive(_1); StorageLive(_2); _2 = InvalidChar { int: const 1114113_u32 }; -- _1 = (_2.1: char); -+ _1 = const {transmute(0x00110001): char}; + _1 = (_2.1: char); StorageDead(_2); StorageLive(_3); StorageLive(_4); StorageLive(_5); _5 = InvalidTag { int: const 4_u32 }; -- _4 = (_5.1: E); -- _3 = [move _4]; -+ _4 = const Scalar(0x00000004): E; -+ _3 = [const Scalar(0x00000004): E]; + _4 = (_5.1: E); + _3 = [move _4]; StorageDead(_4); StorageDead(_5); nop; diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs index ff6b31a1ee2..142f148d064 100644 --- a/tests/mir-opt/const_prop/invalid_constant.rs +++ b/tests/mir-opt/const_prop/invalid_constant.rs @@ -1,5 +1,5 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -Zmir-enable-passes=+RemoveZsts // Verify that we can pretty print invalid constants. @@ -15,7 +15,7 @@ enum E { A, B, C } enum Empty {} // EMIT_MIR invalid_constant.main.RemoveZsts.diff -// EMIT_MIR invalid_constant.main.ConstProp.diff +// EMIT_MIR invalid_constant.main.GVN.diff fn main() { // An invalid char. union InvalidChar { diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_66971.main.GVN.panic-abort.diff index ff93c85e586..30e8916e2d0 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,8 +11,9 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = (); +- _3 = (); - _2 = (move _3, const 0_u8, const 0_u8); ++ _3 = const (); + _2 = const ((), 0_u8, 0_u8); StorageDead(_3); - _1 = encode(move _2) -> [return: bb1, unwind unreachable]; @@ -29,9 +30,5 @@ + + ALLOC0 (size: 2, align: 1) { + 00 00 │ .. -+ } -+ -+ ALLOC1 (size: 2, align: 1) { -+ 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.GVN.panic-unwind.diff index 8790aad4559..4eb29b174a9 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,8 +11,9 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = (); +- _3 = (); - _2 = (move _3, const 0_u8, const 0_u8); ++ _3 = const (); + _2 = const ((), 0_u8, 0_u8); StorageDead(_3); - _1 = encode(move _2) -> [return: bb1, unwind continue]; @@ -29,9 +30,5 @@ + + ALLOC0 (size: 2, align: 1) { + 00 00 │ .. -+ } -+ -+ ALLOC1 (size: 2, align: 1) { -+ 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs index 49d598ff230..30f8ea1606a 100644 --- a/tests/mir-opt/const_prop/issue_66971.rs +++ b/tests/mir-opt/const_prop/issue_66971.rs @@ -1,8 +1,8 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected -// outputs below, after ConstProp this is how _2 would look like with the bug: +// outputs below, after GVN this is how _2 would look like with the bug: // // _2 = (const Scalar(0x00) : (), const 0u8); // @@ -12,7 +12,7 @@ fn encode(this: ((), u8, u8)) { assert!(this.2 == 0); } -// EMIT_MIR issue_66971.main.ConstProp.diff +// EMIT_MIR issue_66971.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: = encode(const ((), 0_u8, 0_u8)) diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff index 3de9cdd79bc..fc0c8afd4cf 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff index 72cf48b5cba..cf4089598e7 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs index f0a09e6e852..e589ed4edcc 100644 --- a/tests/mir-opt/const_prop/issue_67019.rs +++ b/tests/mir-opt/const_prop/issue_67019.rs @@ -1,5 +1,5 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN // This used to ICE in const-prop @@ -7,7 +7,7 @@ fn test(this: ((u8, u8),)) { assert!((this.0).0 == 1); } -// EMIT_MIR issue_67019.main.ConstProp.diff +// EMIT_MIR issue_67019.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: = test(const ((1_u8, 2_u8),)) diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff index 20e2ee32698..cf36109fdcb 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,17 +18,16 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = _2[_3]; -+ _1 = _2[2 of 3]; ++ _1 = const 0_u8; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff index 1bdbbbf7863..40ed9697180 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,17 +18,16 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = _2[_3]; -+ _1 = _2[2 of 3]; ++ _1 = const 0_u8; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff index 20e2ee32698..cf36109fdcb 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,17 +18,16 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = _2[_3]; -+ _1 = _2[2 of 3]; ++ _1 = const 0_u8; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff index 1bdbbbf7863..40ed9697180 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,17 +18,16 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); + _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = Lt(const 2_usize, _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = _2[_3]; -+ _1 = _2[2 of 3]; ++ _1 = const 0_u8; StorageDead(_3); StorageDead(_2); _0 = const (); diff --git a/tests/mir-opt/const_prop/large_array_index.rs b/tests/mir-opt/const_prop/large_array_index.rs index d98d166ff7c..12507b9434f 100644 --- a/tests/mir-opt/const_prop/large_array_index.rs +++ b/tests/mir-opt/const_prop/large_array_index.rs @@ -1,9 +1,9 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR large_array_index.main.ConstProp.diff +// EMIT_MIR large_array_index.main.GVN.diff fn main() { // check that we don't propagate this, because it's too large let x: u8 = [0_u8; 5000][2]; diff --git a/tests/mir-opt/const_prop/mult_by_zero.rs b/tests/mir-opt/const_prop/mult_by_zero.rs index 2e9c63a1ca1..2fdb75c3100 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.rs +++ b/tests/mir-opt/const_prop/mult_by_zero.rs @@ -1,9 +1,10 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mult_by_zero.test.ConstProp.diff +// EMIT_MIR mult_by_zero.test.GVN.diff fn test(x: i32) -> i32 { // CHECK: fn test( - // CHECK: _0 = const 0_i32; + // FIXME(cjgillot) simplify algebraic identity + // CHECK-NOT: _0 = const 0_i32; x * 0 } diff --git a/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff index 73b1da06423..e9fb34749c1 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff +++ b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `test` before ConstProp -+ // MIR for `test` after ConstProp +- // MIR for `test` before GVN ++ // MIR for `test` after GVN fn test(_1: i32) -> i32 { debug x => _1; @@ -10,7 +10,7 @@ StorageLive(_2); _2 = _1; - _0 = Mul(move _2, const 0_i32); -+ _0 = const 0_i32; ++ _0 = Mul(_1, const 0_i32); StorageDead(_2); return; } diff --git a/tests/mir-opt/const_prop/mutable_variable.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff index ad8d9ddb074..11464e32400 100644 --- a/tests/mir-opt/const_prop/mutable_variable.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -17,8 +17,7 @@ _1 = const 42_i32; _1 = const 99_i32; StorageLive(_2); -- _2 = _1; -+ _2 = const 99_i32; + _2 = _1; _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable.rs b/tests/mir-opt/const_prop/mutable_variable.rs index 6c74ea5b9f4..194f39f826e 100644 --- a/tests/mir-opt/const_prop/mutable_variable.rs +++ b/tests/mir-opt/const_prop/mutable_variable.rs @@ -1,13 +1,13 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mutable_variable.main.ConstProp.diff +// EMIT_MIR mutable_variable.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: [[x]] = const 42_i32; // CHECK: [[x]] = const 99_i32; - // CHECK: [[y]] = const 99_i32; + // CHECK: [[y]] = [[x]]; let mut x = 42; x = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff index c3ace9687e6..b6ff7b0fc23 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,8 +18,7 @@ + _1 = const (42_i32, 43_i32); (_1.1: i32) = const 99_i32; StorageLive(_2); -- _2 = _1; -+ _2 = const (42_i32, 99_i32); + _2 = _1; _0 = const (); StorageDead(_2); StorageDead(_1); @@ -28,10 +27,6 @@ + } + + ALLOC0 (size: 8, align: 4) { -+ 2a 00 00 00 63 00 00 00 │ *...c... -+ } -+ -+ ALLOC1 (size: 8, align: 4) { + 2a 00 00 00 2b 00 00 00 │ *...+... } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs index a3829650290..b59132007aa 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -1,13 +1,13 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff +// EMIT_MIR mutable_variable_aggregate.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: [[x]] = const (42_i32, 43_i32); // CHECK: ([[x]].1: i32) = const 99_i32; - // CHECK: [[y]] = const (42_i32, 99_i32); + // CHECK: [[y]] = [[x]]; let mut x = (42, 43); x.1 = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff index 106e27f8f27..bc60546cd19 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,17 +18,24 @@ bb0: { StorageLive(_1); - _1 = (const 42_i32, const 43_i32); - StorageLive(_2); +- _1 = (const 42_i32, const 43_i32); +- StorageLive(_2); ++ _1 = const (42_i32, 43_i32); ++ nop; _2 = &mut _1; ((*_2).1: i32) = const 99_i32; StorageLive(_3); _3 = _1; _0 = const (); StorageDead(_3); - StorageDead(_2); +- StorageDead(_2); ++ nop; StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 2a 00 00 00 2b 00 00 00 │ *...+... } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs index 60f414ae286..1867f7300bd 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -1,12 +1,12 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff +// EMIT_MIR mutable_variable_aggregate_mut_ref.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; // CHECK: debug z => [[z:_.*]]; // CHECK: debug y => [[y:_.*]]; - // CHECK: [[x]] = (const 42_i32, const 43_i32); + // CHECK: [[x]] = const (42_i32, 43_i32); // CHECK: [[z]] = &mut [[x]]; // CHECK: ((*[[z]]).1: i32) = const 99_i32; // CHECK: [[y]] = [[x]]; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff index 34288c62fee..6480e480f8c 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -21,8 +21,7 @@ (_1.1: i32) = const 99_i32; (_1.0: i32) = const 42_i32; StorageLive(_2); -- _2 = (_1.1: i32); -+ _2 = const 99_i32; + _2 = (_1.1: i32); _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff index 7ba2b483dc3..fb757801082 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -21,8 +21,7 @@ (_1.1: i32) = const 99_i32; (_1.0: i32) = const 42_i32; StorageLive(_2); -- _2 = (_1.1: i32); -+ _2 = const 99_i32; + _2 = (_1.1: i32); _0 = const (); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs index 888fcde2de6..d0a44d8f4a0 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -1,7 +1,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff +// EMIT_MIR mutable_variable_aggregate_partial_read.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; @@ -9,7 +9,7 @@ fn main() { // CHECK: [[x]] = foo() // CHECK: ([[x]].1: i32) = const 99_i32; // CHECK: ([[x]].0: i32) = const 42_i32; - // CHECK: [[y]] = const 99_i32; + // CHECK: [[y]] = ([[x]].1: i32); let mut x: (i32, i32) = foo(); x.1 = 99; x.0 = 42; diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff index 1f74bdcfd03..d02c392f6bd 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,12 +22,14 @@ _1 = const 42_u32; StorageLive(_2); StorageLive(_3); - StorageLive(_4); +- StorageLive(_4); ++ nop; _4 = const {ALLOC0: *mut u32}; _3 = (*_4); _1 = move _3; StorageDead(_3); - StorageDead(_4); +- StorageDead(_4); ++ nop; _2 = const (); StorageDead(_2); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs index 49e9a701581..180e194928e 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -1,9 +1,9 @@ -// unit-test: ConstProp +// unit-test: GVN // Verify that we do not propagate the contents of this mutable static. static mut STATIC: u32 = 0x42424242; -// EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff +// EMIT_MIR mutable_variable_no_prop.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff index 85bd2b6e722..d1d23675bfd 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,7 +22,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = foo() -> [return: bb1, unwind unreachable]; } @@ -32,18 +33,19 @@ + _2 = const (1_i32, 2_i32); StorageLive(_3); _3 = _1; - (_2.1: i32) = move _3; +- (_2.1: i32) = move _3; ++ (_2.1: i32) = _1; StorageDead(_3); StorageLive(_4); _4 = (_2.1: i32); StorageLive(_5); -- _5 = (_2.0: i32); -+ _5 = const 1_i32; + _5 = (_2.0: i32); _0 = const (); StorageDead(_5); StorageDead(_4); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } + } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff index 06e96e57a62..4d69c9ce2ef 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -22,7 +22,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = foo() -> [return: bb1, unwind continue]; } @@ -32,18 +33,19 @@ + _2 = const (1_i32, 2_i32); StorageLive(_3); _3 = _1; - (_2.1: i32) = move _3; +- (_2.1: i32) = move _3; ++ (_2.1: i32) = _1; StorageDead(_3); StorageLive(_4); _4 = (_2.1: i32); StorageLive(_5); -- _5 = (_2.0: i32); -+ _5 = const 1_i32; + _5 = (_2.0: i32); _0 = const (); StorageDead(_5); StorageDead(_4); StorageDead(_2); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } + } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs index 04e347fc03d..585363572a5 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -1,7 +1,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff +// EMIT_MIR mutable_variable_unprop_assign.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; @@ -10,10 +10,9 @@ fn main() { // CHECK: debug z => [[z:_.*]]; // CHECK: [[a]] = foo() // CHECK: [[x]] = const (1_i32, 2_i32); - // CHECK: [[tmp:_.*]] = [[a]]; - // CHECK: ([[x]].1: i32) = move [[tmp]]; + // CHECK: ([[x]].1: i32) = [[a]]; // CHECK: [[y]] = ([[x]].1: i32); - // CHECK: [[z]] = const 1_i32; + // CHECK: [[z]] = ([[x]].0: i32); let a = foo(); let mut x: (i32, i32) = (1, 2); x.1 = a; diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff index 711db3d21dd..5d94797905d 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `concrete` before ConstProp -+ // MIR for `concrete` after ConstProp +- // MIR for `concrete` before GVN ++ // MIR for `concrete` after GVN fn concrete() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff index 49458145415..4d890742ee9 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `concrete` before ConstProp -+ // MIR for `concrete` after ConstProp +- // MIR for `concrete` before GVN ++ // MIR for `concrete` after GVN fn concrete() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff index 768970a7250..025241dd1bf 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `generic` before ConstProp -+ // MIR for `generic` after ConstProp +- // MIR for `generic` before GVN ++ // MIR for `generic` after GVN fn generic() -> () { let mut _0: (); @@ -58,16 +58,20 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = OffsetOf(Delta<T>, [(0, 1)]); - _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; +- _6 = OffsetOf(Delta<T>, [(0, 1)]); +- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; ++ _6 = const 0_usize; ++ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind unreachable]; } bb3: { StorageDead(_6); StorageLive(_7); StorageLive(_8); - _8 = OffsetOf(Delta<T>, [(0, 2)]); - _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; +- _8 = OffsetOf(Delta<T>, [(0, 2)]); +- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; ++ _8 = const 2_usize; ++ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff index 04ccd2b36e0..27f2b2f7355 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `generic` before ConstProp -+ // MIR for `generic` after ConstProp +- // MIR for `generic` before GVN ++ // MIR for `generic` after GVN fn generic() -> () { let mut _0: (); @@ -58,16 +58,20 @@ StorageDead(_4); StorageLive(_5); StorageLive(_6); - _6 = OffsetOf(Delta<T>, [(0, 1)]); - _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; +- _6 = OffsetOf(Delta<T>, [(0, 1)]); +- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; ++ _6 = const 0_usize; ++ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind continue]; } bb3: { StorageDead(_6); StorageLive(_7); StorageLive(_8); - _8 = OffsetOf(Delta<T>, [(0, 2)]); - _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; +- _8 = OffsetOf(Delta<T>, [(0, 2)]); +- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; ++ _8 = const 2_usize; ++ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 2571c3856f4..43ecbbed186 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -1,5 +1,5 @@ // skip-filecheck -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![feature(offset_of, offset_of_enum)] @@ -39,7 +39,7 @@ enum Zeta<T> { B(char), } -// EMIT_MIR offset_of.concrete.ConstProp.diff +// EMIT_MIR offset_of.concrete.GVN.diff fn concrete() { let x = offset_of!(Alpha, x); let y = offset_of!(Alpha, y); @@ -50,7 +50,7 @@ fn concrete() { let eC = offset_of!(Epsilon, C.c); } -// EMIT_MIR offset_of.generic.ConstProp.diff +// EMIT_MIR offset_of.generic.GVN.diff fn generic<T>() { let gx = offset_of!(Gamma<T>, x); let gy = offset_of!(Gamma<T>, y); diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs index 4cf6d7c1396..2a3499bf2fe 100644 --- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs @@ -1,4 +1,4 @@ -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -O // Regression test for https://github.com/rust-lang/rust/issues/118328 @@ -10,7 +10,7 @@ impl<T> SizeOfConst<T> { const SIZE: usize = std::mem::size_of::<T>(); } -// EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff +// EMIT_MIR overwrite_with_const_with_params.size_of.GVN.diff fn size_of<T>() -> usize { // CHECK-LABEL: fn size_of( // CHECK: _1 = const 0_usize; diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.ConstProp.diff b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff index ad8318832d6..caa78b7316e 100644 --- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.ConstProp.diff +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `size_of` before ConstProp -+ // MIR for `size_of` after ConstProp +- // MIR for `size_of` before GVN ++ // MIR for `size_of` after GVN fn size_of() -> usize { let mut _0: usize; diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff index bd1de7476a2..425bc3ff6c1 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,25 +13,30 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = read(move _5) -> [return: bb1, unwind unreachable]; +- _4 = read(move _5) -> [return: bb1, unwind unreachable]; ++ _4 = read(_1) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_5); StorageDead(_4); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff index 850b743feb1..e9360ab8d62 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,25 +13,30 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); - StorageDead(_3); +- StorageDead(_3); ++ nop; StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = read(move _5) -> [return: bb1, unwind continue]; +- _4 = read(move _5) -> [return: bb1, unwind continue]; ++ _4 = read(_1) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_5); StorageDead(_4); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/pointer_expose_address.rs b/tests/mir-opt/const_prop/pointer_expose_address.rs index 631aac901b9..8944232f71e 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.rs +++ b/tests/mir-opt/const_prop/pointer_expose_address.rs @@ -1,17 +1,16 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp +// unit-test: GVN #[inline(never)] fn read(_: usize) { } -// EMIT_MIR pointer_expose_address.main.ConstProp.diff +// EMIT_MIR pointer_expose_address.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: [[ptr:_.*]] = const _; // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]); // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress); - // CHECK: [[arg:_.*]] = [[x]]; - // CHECK: = read(move [[arg]]) + // CHECK: = read([[x]]) const FOO: &i32 = &1; let x = FOO as *const i32 as usize; read(x); diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index e193c82d2c0..38f23505230 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); - StorageLive(_2); - StorageLive(_3); +- StorageLive(_2); +- StorageLive(_3); ++ nop; ++ nop; _3 = const {ALLOC0: &u8}; - _2 = (*_3); + _2 = const 2_u8; @@ -27,9 +29,11 @@ + _4 = const 2_u8; + _1 = const 4_u8; StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; StorageDead(_5); - StorageDead(_3); +- StorageDead(_3); ++ nop; _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index 0fa18dd101a..a3d8fee65d7 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -1,8 +1,8 @@ -// unit-test: ConstProp +// unit-test: GVN static FOO: u8 = 2; -// EMIT_MIR read_immutable_static.main.ConstProp.diff +// EMIT_MIR read_immutable_static.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index a54ae8d2fdd..8f9aa20524d 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,11 +13,14 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; _4 = const _; _2 = &(*_4); - _1 = (*_2); - StorageDead(_2); +- _1 = (*_2); +- StorageDead(_2); ++ _1 = const 4_i32; ++ nop; _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/ref_deref.rs b/tests/mir-opt/const_prop/ref_deref.rs index 5bceae749ff..67de110d8bb 100644 --- a/tests/mir-opt/const_prop/ref_deref.rs +++ b/tests/mir-opt/const_prop/ref_deref.rs @@ -1,9 +1,9 @@ -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR ref_deref.main.ConstProp.diff +// EMIT_MIR ref_deref.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: [[a]] = (*{{_.*}}); + // CHECK: [[a]] = const 4_i32; let a = *(&4); } diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index 05a4e17742d..8d38888b7d6 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -13,11 +13,14 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; _4 = const _; _2 = &((*_4).1: i32); - _1 = (*_2); - StorageDead(_2); +- _1 = (*_2); +- StorageDead(_2); ++ _1 = const 5_i32; ++ nop; _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 4b5c6730316..0f706b91b38 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -1,10 +1,10 @@ // This does not currently propagate (#67862) -// unit-test: ConstProp +// unit-test: GVN -// EMIT_MIR ref_deref_project.main.ConstProp.diff +// EMIT_MIR ref_deref_project.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: [[a]] = (*{{_.*}}); + // CHECK: [[a]] = const 5_i32; let a = *(&(4, 5).1); } diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff index e7aa015d078..cde0cb32f75 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/reify_fn_ptr.main.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.rs b/tests/mir-opt/const_prop/reify_fn_ptr.rs index 33fdd4142c1..96077d5b773 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.rs +++ b/tests/mir-opt/const_prop/reify_fn_ptr.rs @@ -1,5 +1,5 @@ -// unit-test: ConstProp -// EMIT_MIR reify_fn_ptr.main.ConstProp.diff +// unit-test: GVN +// EMIT_MIR reify_fn_ptr.main.GVN.diff fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff index a55bd029e99..a52e6e35483 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -20,12 +20,11 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); + _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _6 = Lt(const 2_usize, _5); ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff index d49ef2e0179..fe0acee71eb 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -20,12 +20,11 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); + _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _6 = Lt(const 2_usize, _5); ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff index a55bd029e99..a52e6e35483 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -20,12 +20,11 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); + _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _6 = Lt(const 2_usize, _5); ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff index d49ef2e0179..fe0acee71eb 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -20,12 +20,11 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); + _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; ++ _6 = Lt(const 2_usize, _5); ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs index 9f688bbb53e..2c8717d25bb 100644 --- a/tests/mir-opt/const_prop/repeat.rs +++ b/tests/mir-opt/const_prop/repeat.rs @@ -1,8 +1,8 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR repeat.main.ConstProp.diff +// EMIT_MIR repeat.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff index 974a42e5078..51f8227c36b 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/return_place.add.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `add` before ConstProp -+ // MIR for `add` after ConstProp +- // MIR for `add` before GVN ++ // MIR for `add` after GVN fn add() -> u32 { let mut _0: u32; diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff index 55dbc700285..8174b4edea6 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/return_place.add.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `add` before ConstProp -+ // MIR for `add` after ConstProp +- // MIR for `add` before GVN ++ // MIR for `add` after GVN fn add() -> u32 { let mut _0: u32; diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs index 286543abb99..c207bcbdd62 100644 --- a/tests/mir-opt/const_prop/return_place.rs +++ b/tests/mir-opt/const_prop/return_place.rs @@ -1,8 +1,8 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -C overflow-checks=on -// EMIT_MIR return_place.add.ConstProp.diff +// EMIT_MIR return_place.add.GVN.diff // EMIT_MIR return_place.add.PreCodegen.before.mir fn add() -> u32 { // CHECK-LABEL: fn add( diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff index c5c09c8edd7..0a20fb0e59e 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,7 +11,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 1_u32; StorageLive(_2); StorageLive(_3); @@ -25,7 +26,8 @@ StorageDead(_3); StorageDead(_2); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff index b256c56765e..8b9519d3adc 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,7 +11,8 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); ++ nop; _1 = const 1_u32; StorageLive(_2); StorageLive(_3); @@ -25,7 +26,8 @@ StorageDead(_3); StorageDead(_2); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs index 782cd35d422..70d0eb53591 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs @@ -1,7 +1,7 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// EMIT_MIR scalar_literal_propagation.main.ConstProp.diff +// EMIT_MIR scalar_literal_propagation.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: = consume(const 1_u32) diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 7d5d036f460..8b2411e50ab 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,33 +18,41 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); StorageLive(_4); _9 = const _; - _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); +- _4 = _9; +- _3 = _4; +- _2 = move _3 as &[u32] (PointerCoercion(Unsize)); ++ _4 = const {ALLOC0<imm>: &[u32; 3]}; ++ _3 = const {ALLOC0<imm>: &[u32; 3]}; ++ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 1_usize, _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; _0 = const (); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 12, align: 4) { ++ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index fa4c5a71be5..9b20d243f87 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,33 +18,41 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); StorageLive(_4); _9 = const _; - _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); +- _4 = _9; +- _3 = _4; +- _2 = move _3 as &[u32] (PointerCoercion(Unsize)); ++ _4 = const {ALLOC0<imm>: &[u32; 3]}; ++ _3 = const {ALLOC0<imm>: &[u32; 3]}; ++ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 1_usize, _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; _0 = const (); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 12, align: 4) { ++ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 7d5d036f460..8b2411e50ab 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,33 +18,41 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); StorageLive(_4); _9 = const _; - _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); +- _4 = _9; +- _3 = _4; +- _2 = move _3 as &[u32] (PointerCoercion(Unsize)); ++ _4 = const {ALLOC0<imm>: &[u32; 3]}; ++ _3 = const {ALLOC0<imm>: &[u32; 3]}; ++ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 1_usize, _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; _0 = const (); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 12, align: 4) { ++ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index fa4c5a71be5..9b20d243f87 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -18,33 +18,41 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); StorageLive(_4); _9 = const _; - _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); +- _4 = _9; +- _3 = _4; +- _2 = move _3 as &[u32] (PointerCoercion(Unsize)); ++ _4 = const {ALLOC0<imm>: &[u32; 3]}; ++ _3 = const {ALLOC0<imm>: &[u32; 3]}; ++ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 1_usize, _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; _0 = const (); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 12, align: 4) { ++ 01 00 00 00 02 00 00 00 03 00 00 00 │ ............ } diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 0bf44272698..79cd926df21 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -1,13 +1,16 @@ -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -Zmir-enable-passes=+InstSimplify // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR slice_len.main.ConstProp.diff +// EMIT_MIR slice_len.main.GVN.diff fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: assert(const true, - // CHECK: [[a]] = const 2_u32; + // CHECK: [[slice:_.*]] = const {{.*}} as &[u32] (PointerCoercion(Unsize)); + // FIXME(cjgillot) simplify Len and projection into unsized slice. + // CHECK-NOT: assert(const true, + // CHECK: [[a]] = (*[[slice]])[1 of 2]; + // CHECK-NOT: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff index 508cc15732c..ee9f2d5c7f5 100644 --- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff index 1ce28e979a5..143d04ac984 100644 --- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/switch_int.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs index d1cbaae49aa..c81b574d150 100644 --- a/tests/mir-opt/const_prop/switch_int.rs +++ b/tests/mir-opt/const_prop/switch_int.rs @@ -1,11 +1,11 @@ -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -Zmir-enable-passes=+SimplifyConstCondition-after-const-prop // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #[inline(never)] fn foo(_: i32) { } -// EMIT_MIR switch_int.main.ConstProp.diff +// EMIT_MIR switch_int.main.GVN.diff // EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/transmute.from_char.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff index febfebc8534..47dfb421ebc 100644 --- a/tests/mir-opt/const_prop/transmute.from_char.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.from_char.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `from_char` before ConstProp -+ // MIR for `from_char` after ConstProp +- // MIR for `from_char` before GVN ++ // MIR for `from_char` after GVN fn from_char() -> i32 { let mut _0: i32; diff --git a/tests/mir-opt/const_prop/transmute.from_char.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff index febfebc8534..47dfb421ebc 100644 --- a/tests/mir-opt/const_prop/transmute.from_char.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.from_char.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `from_char` before ConstProp -+ // MIR for `from_char` after ConstProp +- // MIR for `from_char` before GVN ++ // MIR for `from_char` after GVN fn from_char() -> i32 { let mut _0: i32; diff --git a/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff index 38a1eb5a15b..f0c6f55f775 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `invalid_bool` before ConstProp -+ // MIR for `invalid_bool` after ConstProp +- // MIR for `invalid_bool` before GVN ++ // MIR for `invalid_bool` after GVN fn invalid_bool() -> bool { let mut _0: bool; diff --git a/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff index 38a1eb5a15b..f0c6f55f775 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_bool.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `invalid_bool` before ConstProp -+ // MIR for `invalid_bool` after ConstProp +- // MIR for `invalid_bool` before GVN ++ // MIR for `invalid_bool` after GVN fn invalid_bool() -> bool { let mut _0: bool; diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff index 2c0998f77ea..a9e32d4d925 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `invalid_char` before ConstProp -+ // MIR for `invalid_char` after ConstProp +- // MIR for `invalid_char` before GVN ++ // MIR for `invalid_char` after GVN fn invalid_char() -> char { let mut _0: char; diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff index 2c0998f77ea..a9e32d4d925 100644 --- a/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `invalid_char` before ConstProp -+ // MIR for `invalid_char` after ConstProp +- // MIR for `invalid_char` before GVN ++ // MIR for `invalid_char` after GVN fn invalid_char() -> char { let mut _0: char; diff --git a/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff index 7ac7bed8a5f..5e0c076b981 100644 --- a/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `less_as_i8` before ConstProp -+ // MIR for `less_as_i8` after ConstProp +- // MIR for `less_as_i8` before GVN ++ // MIR for `less_as_i8` after GVN fn less_as_i8() -> i8 { let mut _0: i8; diff --git a/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff index 7ac7bed8a5f..5e0c076b981 100644 --- a/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.less_as_i8.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `less_as_i8` before ConstProp -+ // MIR for `less_as_i8` after ConstProp +- // MIR for `less_as_i8` before GVN ++ // MIR for `less_as_i8` after GVN fn less_as_i8() -> i8 { let mut _0: i8; diff --git a/tests/mir-opt/const_prop/transmute.rs b/tests/mir-opt/const_prop/transmute.rs index 99988d05994..6ff0ba422f4 100644 --- a/tests/mir-opt/const_prop/transmute.rs +++ b/tests/mir-opt/const_prop/transmute.rs @@ -1,46 +1,46 @@ -// unit-test: ConstProp +// unit-test: GVN // compile-flags: -O --crate-type=lib // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH use std::mem::transmute; -// EMIT_MIR transmute.less_as_i8.ConstProp.diff +// EMIT_MIR transmute.less_as_i8.GVN.diff pub fn less_as_i8() -> i8 { // CHECK-LABEL: fn less_as_i8( // CHECK: _0 = const -1_i8; unsafe { transmute(std::cmp::Ordering::Less) } } -// EMIT_MIR transmute.from_char.ConstProp.diff +// EMIT_MIR transmute.from_char.GVN.diff pub fn from_char() -> i32 { // CHECK-LABEL: fn from_char( // CHECK: _0 = const 82_i32; unsafe { transmute('R') } } -// EMIT_MIR transmute.valid_char.ConstProp.diff +// EMIT_MIR transmute.valid_char.GVN.diff pub fn valid_char() -> char { // CHECK-LABEL: fn valid_char( // CHECK: _0 = const 'R'; unsafe { transmute(0x52_u32) } } -// EMIT_MIR transmute.invalid_char.ConstProp.diff +// EMIT_MIR transmute.invalid_char.GVN.diff pub unsafe fn invalid_char() -> char { // CHECK-LABEL: fn invalid_char( // CHECK: _0 = const {transmute(0x7fffffff): char}; unsafe { transmute(i32::MAX) } } -// EMIT_MIR transmute.invalid_bool.ConstProp.diff +// EMIT_MIR transmute.invalid_bool.GVN.diff pub unsafe fn invalid_bool() -> bool { // CHECK-LABEL: fn invalid_bool( // CHECK: _0 = const {transmute(0xff): bool}; unsafe { transmute(-1_i8) } } -// EMIT_MIR transmute.undef_union_as_integer.ConstProp.diff +// EMIT_MIR transmute.undef_union_as_integer.GVN.diff pub unsafe fn undef_union_as_integer() -> u32 { // CHECK-LABEL: fn undef_union_as_integer( // CHECK: _1 = Union32 { @@ -49,16 +49,16 @@ pub unsafe fn undef_union_as_integer() -> u32 { unsafe { transmute(Union32 { unit: () }) } } -// EMIT_MIR transmute.unreachable_direct.ConstProp.diff +// EMIT_MIR transmute.unreachable_direct.GVN.diff pub unsafe fn unreachable_direct() -> ! { // CHECK-LABEL: fn unreachable_direct( - // CHECK: [[unit:_.*]] = (); - // CHECK: move [[unit]] as Never (Transmute); + // CHECK: = const (); + // CHECK: = const () as Never (Transmute); let x: Never = unsafe { transmute(()) }; match x {} } -// EMIT_MIR transmute.unreachable_ref.ConstProp.diff +// EMIT_MIR transmute.unreachable_ref.GVN.diff pub unsafe fn unreachable_ref() -> ! { // CHECK-LABEL: fn unreachable_ref( // CHECK: = const {0x1 as &Never}; @@ -66,7 +66,7 @@ pub unsafe fn unreachable_ref() -> ! { match *x {} } -// EMIT_MIR transmute.unreachable_mut.ConstProp.diff +// EMIT_MIR transmute.unreachable_mut.GVN.diff pub unsafe fn unreachable_mut() -> ! { // CHECK-LABEL: fn unreachable_mut( // CHECK: = const {0x1 as &mut Never}; @@ -74,7 +74,7 @@ pub unsafe fn unreachable_mut() -> ! { match *x {} } -// EMIT_MIR transmute.unreachable_box.ConstProp.diff +// EMIT_MIR transmute.unreachable_box.GVN.diff pub unsafe fn unreachable_box() -> ! { // CHECK-LABEL: fn unreachable_box( // CHECK: = const Box::<Never>( diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff index afedf2a3061..c6a428019d8 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `undef_union_as_integer` before ConstProp -+ // MIR for `undef_union_as_integer` after ConstProp +- // MIR for `undef_union_as_integer` before GVN ++ // MIR for `undef_union_as_integer` after GVN fn undef_union_as_integer() -> u32 { let mut _0: u32; @@ -11,7 +11,8 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); +- _2 = (); ++ _2 = const (); _1 = Union32 { value: move _2 }; StorageDead(_2); _0 = move _1 as u32 (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff index afedf2a3061..c6a428019d8 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `undef_union_as_integer` before ConstProp -+ // MIR for `undef_union_as_integer` after ConstProp +- // MIR for `undef_union_as_integer` before GVN ++ // MIR for `undef_union_as_integer` after GVN fn undef_union_as_integer() -> u32 { let mut _0: u32; @@ -11,7 +11,8 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); +- _2 = (); ++ _2 = const (); _1 = Union32 { value: move _2 }; StorageDead(_2); _0 = move _1 as u32 (Transmute); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index 16519749b82..2ef83abfac0 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_box` before ConstProp -+ // MIR for `unreachable_box` after ConstProp +- // MIR for `unreachable_box` before GVN ++ // MIR for `unreachable_box` after GVN fn unreachable_box() -> ! { let mut _0: !; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index 16519749b82..2ef83abfac0 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_box` before ConstProp -+ // MIR for `unreachable_box` after ConstProp +- // MIR for `unreachable_box` before GVN ++ // MIR for `unreachable_box` after GVN fn unreachable_box() -> ! { let mut _0: !; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff index 896608e7eff..b2e91014625 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_direct` before ConstProp -+ // MIR for `unreachable_direct` after ConstProp +- // MIR for `unreachable_direct` before GVN ++ // MIR for `unreachable_direct` after GVN fn unreachable_direct() -> ! { let mut _0: !; @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const () as Never (Transmute); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff index 896608e7eff..b2e91014625 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_direct` before ConstProp -+ // MIR for `unreachable_direct` after ConstProp +- // MIR for `unreachable_direct` before GVN ++ // MIR for `unreachable_direct` after GVN fn unreachable_direct() -> ! { let mut _0: !; @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const () as Never (Transmute); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff index c9d5ccf0bfd..93dfef96cf1 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_mut` before ConstProp -+ // MIR for `unreachable_mut` after ConstProp +- // MIR for `unreachable_mut` before GVN ++ // MIR for `unreachable_mut` after GVN fn unreachable_mut() -> ! { let mut _0: !; @@ -13,11 +13,13 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); ++ nop; + _2 = const {0x1 as &mut Never}; _1 = &mut (*_2); - StorageDead(_2); +- StorageDead(_2); ++ nop; unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff index c9d5ccf0bfd..93dfef96cf1 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_mut` before ConstProp -+ // MIR for `unreachable_mut` after ConstProp +- // MIR for `unreachable_mut` before GVN ++ // MIR for `unreachable_mut` after GVN fn unreachable_mut() -> ! { let mut _0: !; @@ -13,11 +13,13 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); ++ nop; + _2 = const {0x1 as &mut Never}; _1 = &mut (*_2); - StorageDead(_2); +- StorageDead(_2); ++ nop; unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff index b684ba34c69..430d16c97a6 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_ref` before ConstProp -+ // MIR for `unreachable_ref` after ConstProp +- // MIR for `unreachable_ref` before GVN ++ // MIR for `unreachable_ref` after GVN fn unreachable_ref() -> ! { let mut _0: !; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff index b684ba34c69..430d16c97a6 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `unreachable_ref` before ConstProp -+ // MIR for `unreachable_ref` after ConstProp +- // MIR for `unreachable_ref` before GVN ++ // MIR for `unreachable_ref` after GVN fn unreachable_ref() -> ! { let mut _0: !; diff --git a/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff index f215b3ca398..f9d002f96ab 100644 --- a/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.valid_char.GVN.32bit.diff @@ -1,5 +1,5 @@ -- // MIR for `valid_char` before ConstProp -+ // MIR for `valid_char` after ConstProp +- // MIR for `valid_char` before GVN ++ // MIR for `valid_char` after GVN fn valid_char() -> char { let mut _0: char; diff --git a/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff index f215b3ca398..f9d002f96ab 100644 --- a/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.valid_char.GVN.64bit.diff @@ -1,5 +1,5 @@ -- // MIR for `valid_char` before ConstProp -+ // MIR for `valid_char` after ConstProp +- // MIR for `valid_char` before GVN ++ // MIR for `valid_char` after GVN fn valid_char() -> char { let mut _0: char; diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff index f19650d5a83..c2f3fb1b3b5 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,8 +11,9 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); - _1 = (const 1_u32, const 2_u32); ++ nop; + _1 = const (1_u32, 2_u32); StorageLive(_2); StorageLive(_3); @@ -26,20 +27,13 @@ StorageDead(_3); StorageDead(_2); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } + } + + ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ -+ } -+ -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ -+ } -+ -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff index 67307c42331..55d9a3b0cac 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -11,8 +11,9 @@ } bb0: { - StorageLive(_1); +- StorageLive(_1); - _1 = (const 1_u32, const 2_u32); ++ nop; + _1 = const (1_u32, 2_u32); StorageLive(_2); StorageLive(_3); @@ -26,20 +27,13 @@ StorageDead(_3); StorageDead(_2); _0 = const (); - StorageDead(_1); +- StorageDead(_1); ++ nop; return; } + } + + ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ -+ } -+ -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ -+ } -+ -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs index dfc4a6f3fbb..6803612f0a5 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs @@ -1,6 +1,6 @@ -// unit-test: ConstProp +// unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// EMIT_MIR tuple_literal_propagation.main.ConstProp.diff +// EMIT_MIR tuple_literal_propagation.main.GVN.diff fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.ConstProp.diff b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff index f54908b4a38..9548afc9d40 100644 --- a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.ConstProp.diff +++ b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff @@ -1,5 +1,5 @@ -- // MIR for `change_loop_body` before ConstProp -+ // MIR for `change_loop_body` after ConstProp +- // MIR for `change_loop_body` before GVN ++ // MIR for `change_loop_body` after GVN fn change_loop_body() -> () { let mut _0: (); @@ -21,15 +21,17 @@ StorageLive(_1); _1 = const 0_i32; StorageLive(_3); - _3 = Option::<u32>::None; +- _3 = Option::<u32>::None; - _4 = discriminant(_3); - switchInt(move _4) -> [1: bb1, otherwise: bb3]; ++ _3 = const Option::<u32>::None; + _4 = const 0_isize; + switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; } bb1: { - switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; +- switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; ++ switchInt(const Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: u32) -> [0: bb2, otherwise: bb3]; } bb2: { @@ -50,5 +52,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 __ __ __ __ │ ....░░░░ } diff --git a/tests/mir-opt/const_prop/while_let_loops.rs b/tests/mir-opt/const_prop/while_let_loops.rs index 8b2a73438d6..d6527552bb0 100644 --- a/tests/mir-opt/const_prop/while_let_loops.rs +++ b/tests/mir-opt/const_prop/while_let_loops.rs @@ -1,5 +1,5 @@ -// unit-test: ConstProp -// EMIT_MIR while_let_loops.change_loop_body.ConstProp.diff +// unit-test: GVN +// EMIT_MIR while_let_loops.change_loop_body.GVN.diff pub fn change_loop_body() { // CHECK-LABEL: fn change_loop_body( diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index ddfe2e8c831..6925fdb1e70 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -74,18 +74,18 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _8 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,3 @@ } } - ALLOC2 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - - ALLOC1 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 861295faa5a..82ad842505c 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -74,18 +74,18 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _8 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,3 @@ } } - ALLOC2 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - - ALLOC1 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - - ALLOC0 (size: 8, align: 4) { - 01 00 00 00 00 00 00 00 │ ........ - } - diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index cbb639edc53..6925fdb1e70 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -74,18 +74,18 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _8 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,3 @@ } } - ALLOC2 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - - ALLOC1 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - - ALLOC0 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 656846e9f97..82ad842505c 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -74,18 +74,18 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); - _8 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,3 @@ } } - ALLOC2 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - - ALLOC1 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - - ALLOC0 (size: 16, align: 8) { - 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - } - diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 8363783e64e..13545aa464a 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -77,23 +77,18 @@ StorageLive(_8); StorageLive(_9); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -- _5 = NonNull::<[bool; 0]> { pointer: _8 }; -+ _8 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; ++ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); -- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); -- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); -- _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -103,17 +98,5 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } -+ -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index 19326b6a933..bf326915381 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -77,23 +77,18 @@ StorageLive(_8); StorageLive(_9); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -- _5 = NonNull::<[bool; 0]> { pointer: _8 }; -+ _8 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; ++ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); -- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); -- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); -- _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -107,17 +102,5 @@ bb2 (cleanup): { resume; } -+ } -+ -+ ALLOC2 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } -+ -+ ALLOC1 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ -+ } -+ -+ ALLOC0 (size: 8, align: 4) { -+ 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 0d1e2430ce3..13545aa464a 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -77,23 +77,18 @@ StorageLive(_8); StorageLive(_9); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -- _5 = NonNull::<[bool; 0]> { pointer: _8 }; -+ _8 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; ++ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); -- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); -- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); -- _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -103,17 +98,5 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC2 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } -+ -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 35f1e5ba796..bf326915381 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); @@ -77,23 +77,18 @@ StorageLive(_8); StorageLive(_9); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -- _5 = NonNull::<[bool; 0]> { pointer: _8 }; -+ _8 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; ++ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _8 }; StorageDead(_9); StorageDead(_8); StorageDead(_6); -- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); -- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); -- _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = Box::<[bool]>(_3, const std::alloc::Global); StorageDead(_3); -- _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -107,17 +102,5 @@ bb2 (cleanup): { resume; } -+ } -+ -+ ALLOC2 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } -+ -+ ALLOC1 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ -+ } -+ -+ ALLOC0 (size: 16, align: 8) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 1bb052736c0..8006bd510e1 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -1,6 +1,6 @@ // skip-filecheck // unit-test: DataflowConstProp -// compile-flags: -Zmir-enable-passes=+ConstProp,+Inline +// compile-flags: -Zmir-enable-passes=+GVN,+Inline // ignore-debug assertions change the output MIR // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -9,7 +9,7 @@ struct A { foo: Box<[bool]>, } -// EMIT_MIR default_boxed_slice.main.ConstProp.diff +// EMIT_MIR default_boxed_slice.main.GVN.diff // EMIT_MIR default_boxed_slice.main.DataflowConstProp.diff fn main() { // ConstProp will create a constant of type `Box<[bool]>`. diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 142e08f4d6c..993e0f1d1a6 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -4,12 +4,13 @@ fn main() -> () { let mut _0: (); let _1: main::Un; + let mut _2: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::<u32>) { - debug _x => const 1_u32; + debug _x => _2; } } scope 3 (inlined val) { @@ -18,6 +19,9 @@ bb0: { StorageLive(_1); _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = (_1.0: u32); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 142e08f4d6c..993e0f1d1a6 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -4,12 +4,13 @@ fn main() -> () { let mut _0: (); let _1: main::Un; + let mut _2: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::<u32>) { - debug _x => const 1_u32; + debug _x => _2; } } scope 3 (inlined val) { @@ -18,6 +19,9 @@ bb0: { StorageLive(_1); _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = (_1.0: u32); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff index 97ca825092e..80b5681ad06 100644 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff @@ -33,8 +33,8 @@ - StorageLive(_5); - _5 = _1; - StorageLive(_6); -- _6 = _2; -- _4 = g::<T>(move _5, move _6) -> [return: bb2, unwind unreachable]; +- _6 = _1; +- _4 = g::<T>(_1, _1) -> [return: bb2, unwind unreachable]; - } - - bb2: { @@ -48,20 +48,22 @@ - bb3: { StorageLive(_7); - StorageLive(_8); -- _8 = _2; +- _8 = _1; +- StorageLive(_9); +- _9 = _1; +- _7 = g::<T>(_1, _1) -> [return: bb4, unwind unreachable]; + nop; + nop; - StorageLive(_9); -- _9 = _2; -- _7 = g::<T>(move _8, move _9) -> [return: bb4, unwind unreachable]; -+ _9 = _1; -+ _7 = g::<T>(move _1, move _9) -> [return: bb2, unwind unreachable]; ++ nop; ++ nop; ++ _7 = g::<T>(_1, _1) -> [return: bb2, unwind unreachable]; } - bb4: { -+ bb2: { - StorageDead(_9); +- StorageDead(_9); - StorageDead(_8); ++ bb2: { ++ nop; + nop; StorageDead(_7); _0 = const (); diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff index 7f730a77b06..eae7dd17b48 100644 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff @@ -33,8 +33,8 @@ - StorageLive(_5); - _5 = _1; - StorageLive(_6); -- _6 = _2; -- _4 = g::<T>(move _5, move _6) -> [return: bb2, unwind continue]; +- _6 = _1; +- _4 = g::<T>(_1, _1) -> [return: bb2, unwind continue]; - } - - bb2: { @@ -48,20 +48,22 @@ - bb3: { StorageLive(_7); - StorageLive(_8); -- _8 = _2; +- _8 = _1; +- StorageLive(_9); +- _9 = _1; +- _7 = g::<T>(_1, _1) -> [return: bb4, unwind continue]; + nop; + nop; - StorageLive(_9); -- _9 = _2; -- _7 = g::<T>(move _8, move _9) -> [return: bb4, unwind continue]; -+ _9 = _1; -+ _7 = g::<T>(move _1, move _9) -> [return: bb2, unwind continue]; ++ nop; ++ nop; ++ _7 = g::<T>(_1, _1) -> [return: bb2, unwind continue]; } - bb4: { -+ bb2: { - StorageDead(_9); +- StorageDead(_9); - StorageDead(_8); ++ bb2: { ++ nop; + nop; StorageDead(_7); _0 = const (); diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs index a47d2a0c8e2..0bde157ff61 100644 --- a/tests/mir-opt/dest-prop/unreachable.rs +++ b/tests/mir-opt/dest-prop/unreachable.rs @@ -4,7 +4,7 @@ // Regression test for issue #105428. // // compile-flags: --crate-type=lib -Zmir-opt-level=0 -// compile-flags: -Zmir-enable-passes=+ConstProp,+SimplifyConstCondition-after-const-prop,+DestinationPropagation +// compile-flags: -Zmir-enable-passes=+GVN,+SimplifyConstCondition-after-const-prop,+DestinationPropagation // EMIT_MIR unreachable.f.DestinationPropagation.diff pub fn f<T: Copy>(a: T) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 298a6084899..0ba1bac0a03 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `float_to_exponential_common` before ConstProp -+ // MIR for `float_to_exponential_common` after ConstProp +- // MIR for `float_to_exponential_common` before GVN ++ // MIR for `float_to_exponential_common` after GVN fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> { debug fmt => _1; diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 037f4f7cfac..27ea43ef12b 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `float_to_exponential_common` before ConstProp -+ // MIR for `float_to_exponential_common` after ConstProp +- // MIR for `float_to_exponential_common` before GVN ++ // MIR for `float_to_exponential_common` after GVN fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> { debug fmt => _1; diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs index 14aad039946..eae158f9f77 100644 --- a/tests/mir-opt/funky_arms.rs +++ b/tests/mir-opt/funky_arms.rs @@ -9,7 +9,7 @@ extern crate core; use core::num::flt2dec; use std::fmt::{Formatter, Result}; -// EMIT_MIR funky_arms.float_to_exponential_common.ConstProp.diff +// EMIT_MIR funky_arms.float_to_exponential_common.GVN.diff pub fn float_to_exponential_common<T>(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result where T: flt2dec::DecodableFloat, diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 62d7e839f5a..408cc5bb341 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -19,7 +19,7 @@ fn b(_1: &mut Box<T>) -> &mut T { _4 = &mut (*_1); StorageLive(_5); StorageLive(_6); - _5 = deref_copy (*_4); + _5 = (*_4); _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); _3 = &mut (*_6); StorageDead(_6); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index bc0aa06a752..4d20f6c4419 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -17,7 +17,7 @@ fn d(_1: &Box<T>) -> &T { _3 = &(*_1); StorageLive(_4); StorageLive(_5); - _4 = deref_copy (*_3); + _4 = (*_3); _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); _2 = &(*_5); StorageDead(_5); diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index 3748d148380..d2db8f61916 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `inner` before ConstProp -+ // MIR for `inner` after ConstProp +- // MIR for `inner` before GVN ++ // MIR for `inner` after GVN fn inner(_1: u32) -> i64 { debug fields => _1; diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index 9dab4233c56..514183b3bc0 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `inner` before ConstProp -+ // MIR for `inner` after ConstProp +- // MIR for `inner` before GVN ++ // MIR for `inner` after GVN fn inner(_1: u32) -> i64 { debug fields => _1; diff --git a/tests/mir-opt/issue_101973.rs b/tests/mir-opt/issue_101973.rs index 3de325bc170..83a4dfb20b5 100644 --- a/tests/mir-opt/issue_101973.rs +++ b/tests/mir-opt/issue_101973.rs @@ -1,7 +1,7 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -O -C debug-assertions=on -// This needs inlining followed by ConstProp to reproduce, so we cannot use "unit-test". +// This needs inlining followed by GVN to reproduce, so we cannot use "unit-test". #[inline] pub fn imm8(x: u32) -> u32 { @@ -10,7 +10,7 @@ pub fn imm8(x: u32) -> u32 { out } -// EMIT_MIR issue_101973.inner.ConstProp.diff +// EMIT_MIR issue_101973.inner.GVN.diff #[inline(never)] pub fn inner(fields: u32) -> i64 { imm8(fields).rotate_right(((fields >> 8) & 0xf) << 1) as i32 as i64 diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir index 8304cb45b35..9c6c30214aa 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir @@ -55,7 +55,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> { } bb3: { - _0 = Option::<u32>::None; + _0 = const Option::<u32>::None; goto -> bb4; } @@ -66,3 +66,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> { return; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index d5628dc7a6e..5cb528c0d5f 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -55,8 +55,10 @@ - _2 = Option::<Layout>::None; + _2 = const Option::<Layout>::None; StorageLive(_10); - _10 = const 0_isize; - switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; +- _10 = discriminant(_2); +- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ _10 = const 0_isize; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index d28059458ae..1e1585f20ae 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -40,8 +40,10 @@ - _2 = Option::<Layout>::None; + _2 = const Option::<Layout>::None; StorageLive(_10); - _10 = const 0_isize; - switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; +- _10 = discriminant(_2); +- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; ++ _10 = const 0_isize; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index d139fc73e21..e655af559a1 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -55,8 +55,10 @@ - _2 = Option::<Layout>::None; + _2 = const Option::<Layout>::None; StorageLive(_10); - _10 = const 0_isize; - switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; +- _10 = discriminant(_2); +- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ _10 = const 0_isize; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index 63db9553b37..a6658713a02 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -40,8 +40,10 @@ - _2 = Option::<Layout>::None; + _2 = const Option::<Layout>::None; StorageLive(_10); - _10 = const 0_isize; - switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; +- _10 = discriminant(_2); +- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; ++ _10 = const 0_isize; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 73a3be7f301..42c7eb3c6aa 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -72,7 +72,7 @@ fn int_range(_1: usize, _2: usize) -> () { bb2: { StorageDead(_7); StorageDead(_6); - _11 = Option::<usize>::None; + _11 = const Option::<usize>::None; goto -> bb5; } @@ -118,3 +118,7 @@ fn int_range(_1: usize, _2: usize) -> () { unreachable; } } + +ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ +} diff --git a/tests/mir-opt/pre-codegen/loops.rs b/tests/mir-opt/pre-codegen/loops.rs index 7f9c26f4fff..9412c3f234e 100644 --- a/tests/mir-opt/pre-codegen/loops.rs +++ b/tests/mir-opt/pre-codegen/loops.rs @@ -1,6 +1,7 @@ // skip-filecheck // compile-flags: -O -Zmir-opt-level=2 -g // needs-unwind +// only-64bit #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index bddd961c933..4e34233a979 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index 297ebd79fad..275f17e52ae 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index bddd961c933..4e34233a979 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index 297ebd79fad..275f17e52ae 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs index bb089ea4455..fb634ca85ef 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs @@ -9,7 +9,7 @@ struct Point { // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR optimizes_into_variable.main.ScalarReplacementOfAggregates.diff -// EMIT_MIR optimizes_into_variable.main.ConstProp.diff +// EMIT_MIR optimizes_into_variable.main.GVN.diff // EMIT_MIR optimizes_into_variable.main.SimplifyLocals-final.after.mir // EMIT_MIR optimizes_into_variable.main.PreCodegen.after.mir fn main() { diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index cd734b10fea..e5940bd8201 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -75,7 +75,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::<u32>::None; + _12 = const Option::<u32>::None; goto -> bb5; } @@ -131,3 +131,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { unreachable; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 3342da545ae..87e7485cb36 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -75,7 +75,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::<u32>::None; + _12 = const Option::<u32>::None; goto -> bb5; } @@ -139,3 +139,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { resume; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index 6ed3d73b11d..f674f6a3009 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -46,7 +46,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { bb1: { StorageDead(_3); StorageDead(_2); - _0 = Option::<u32>::None; + _0 = const Option::<u32>::None; goto -> bb4; } @@ -71,3 +71,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { return; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index a030647deae..a5029dcad3a 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -46,7 +46,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { bb1: { StorageDead(_3); StorageDead(_2); - _0 = Option::<u32>::None; + _0 = const Option::<u32>::None; goto -> bb4; } @@ -71,3 +71,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { return; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index af5d385a979..718dba21a95 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -24,7 +24,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> { } bb1: { - _0 = Option::<i32>::None; + _0 = const Option::<i32>::None; goto -> bb3; } @@ -46,3 +46,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> { unreachable; } } + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 05f16cdacce..cc009e45e7e 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -4,239 +4,217 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: &usize; - let mut _5: &(usize, usize, usize, usize); + let _5: &usize; let _6: &usize; - let mut _7: &(usize, usize, usize, usize); - let _8: &usize; - let mut _9: &(usize, usize, usize, usize); - let _10: &usize; - let mut _11: &&usize; - let _12: &usize; - let mut _13: &&usize; - let mut _18: bool; - let mut _19: &&usize; - let _20: &usize; - let mut _21: &&usize; - let mut _26: bool; - let mut _27: &&usize; - let _28: &usize; - let mut _29: &&usize; - let mut _34: bool; - let mut _35: &&usize; - let _36: &usize; - let mut _37: &&usize; + let _7: &usize; + let mut _8: &&usize; + let _9: &usize; + let mut _10: &&usize; + let mut _15: bool; + let mut _16: &&usize; + let _17: &usize; + let mut _18: &&usize; + let mut _23: bool; + let mut _24: &&usize; + let _25: &usize; + let mut _26: &&usize; + let mut _31: bool; + let mut _32: &&usize; + let _33: &usize; + let mut _34: &&usize; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _11; - debug other => _13; - let mut _14: &usize; - let mut _15: &usize; + debug self => _8; + debug other => _10; + let mut _11: &usize; + let mut _12: &usize; scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _14; - debug other => _15; - let mut _16: usize; - let mut _17: usize; + debug self => _11; + debug other => _12; + let mut _13: usize; + let mut _14: usize; } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _19; - debug other => _21; - let mut _22: &usize; - let mut _23: &usize; + debug self => _16; + debug other => _18; + let mut _19: &usize; + let mut _20: &usize; scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _22; - debug other => _23; - let mut _24: usize; - let mut _25: usize; + debug self => _19; + debug other => _20; + let mut _21: usize; + let mut _22: usize; } } scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _27; - debug other => _29; - let mut _30: &usize; - let mut _31: &usize; + debug self => _24; + debug other => _26; + let mut _27: &usize; + let mut _28: &usize; scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _30; - debug other => _31; - let mut _32: usize; - let mut _33: usize; + debug self => _27; + debug other => _28; + let mut _29: usize; + let mut _30: usize; } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _35; - debug other => _37; - let mut _38: &usize; - let mut _39: &usize; + debug self => _32; + debug other => _34; + let mut _35: &usize; + let mut _36: &usize; scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _38; - debug other => _39; - let mut _40: usize; - let mut _41: usize; + debug self => _35; + debug other => _36; + let mut _37: usize; + let mut _38: usize; } } } bb0: { StorageLive(_4); - _3 = deref_copy (*_2); + _3 = (*_2); _4 = &((*_3).0: usize); + StorageLive(_5); + _5 = &((*_3).1: usize); StorageLive(_6); - _5 = deref_copy (*_2); - _6 = &((*_5).1: usize); + _6 = &((*_3).2: usize); + StorageLive(_7); + _7 = &((*_3).3: usize); + StorageLive(_15); StorageLive(_8); - _7 = deref_copy (*_2); - _8 = &((*_7).2: usize); + _8 = &_4; StorageLive(_10); - _9 = deref_copy (*_2); - _10 = &((*_9).3: usize); - StorageLive(_18); - StorageLive(_11); - _11 = &_4; + StorageLive(_9); + _9 = _6; + _10 = &_9; + _11 = _4; + _12 = _9; StorageLive(_13); - StorageLive(_12); - _12 = _8; - _13 = &_12; + _13 = (*_11); StorageLive(_14); - StorageLive(_15); - _14 = deref_copy _4; - _15 = deref_copy _12; - StorageLive(_16); - _16 = (*_14); - StorageLive(_17); - _17 = (*_15); - _18 = Le(move _16, move _17); - StorageDead(_17); - StorageDead(_16); - StorageDead(_15); + _14 = (*_12); + _15 = Le(move _13, move _14); StorageDead(_14); - switchInt(move _18) -> [0: bb1, otherwise: bb2]; + StorageDead(_13); + switchInt(move _15) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); goto -> bb4; } bb2: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); - StorageLive(_26); - StorageLive(_19); - _19 = &_10; + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); + StorageLive(_23); + StorageLive(_16); + _16 = &_7; + StorageLive(_18); + StorageLive(_17); + _17 = _5; + _18 = &_17; + _19 = _7; + _20 = _17; StorageLive(_21); - StorageLive(_20); - _20 = _6; - _21 = &_20; + _21 = (*_19); StorageLive(_22); - StorageLive(_23); - _22 = deref_copy _10; - _23 = deref_copy _20; - StorageLive(_24); - _24 = (*_22); - StorageLive(_25); - _25 = (*_23); - _26 = Le(move _24, move _25); - StorageDead(_25); - StorageDead(_24); - StorageDead(_23); + _22 = (*_20); + _23 = Le(move _21, move _22); StorageDead(_22); - switchInt(move _26) -> [0: bb3, otherwise: bb8]; + StorageDead(_21); + switchInt(move _23) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_20); - StorageDead(_21); - StorageDead(_19); + StorageDead(_17); + StorageDead(_18); + StorageDead(_16); goto -> bb4; } bb4: { - StorageLive(_34); - StorageLive(_27); - _27 = &_8; + StorageLive(_31); + StorageLive(_24); + _24 = &_6; + StorageLive(_26); + StorageLive(_25); + _25 = _4; + _26 = &_25; + _27 = _6; + _28 = _25; StorageLive(_29); - StorageLive(_28); - _28 = _4; - _29 = &_28; + _29 = (*_27); StorageLive(_30); - StorageLive(_31); - _30 = deref_copy _8; - _31 = deref_copy _28; - StorageLive(_32); - _32 = (*_30); - StorageLive(_33); - _33 = (*_31); - _34 = Le(move _32, move _33); - StorageDead(_33); - StorageDead(_32); - StorageDead(_31); + _30 = (*_28); + _31 = Le(move _29, move _30); StorageDead(_30); - switchInt(move _34) -> [0: bb5, otherwise: bb6]; + StorageDead(_29); + switchInt(move _31) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_28); - StorageDead(_29); - StorageDead(_27); + StorageDead(_25); + StorageDead(_26); + StorageDead(_24); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_28); - StorageDead(_29); - StorageDead(_27); - StorageLive(_35); - _35 = &_6; + StorageDead(_25); + StorageDead(_26); + StorageDead(_24); + StorageLive(_32); + _32 = &_5; + StorageLive(_34); + StorageLive(_33); + _33 = _7; + _34 = &_33; + _35 = _5; + _36 = _33; StorageLive(_37); - StorageLive(_36); - _36 = _10; - _37 = &_36; + _37 = (*_35); StorageLive(_38); - StorageLive(_39); - _38 = deref_copy _6; - _39 = deref_copy _36; - StorageLive(_40); - _40 = (*_38); - StorageLive(_41); - _41 = (*_39); - _0 = Le(move _40, move _41); - StorageDead(_41); - StorageDead(_40); - StorageDead(_39); + _38 = (*_36); + _0 = Le(move _37, move _38); StorageDead(_38); - StorageDead(_36); StorageDead(_37); - StorageDead(_35); + StorageDead(_33); + StorageDead(_34); + StorageDead(_32); goto -> bb7; } bb7: { - StorageDead(_34); + StorageDead(_31); goto -> bb9; } bb8: { - StorageDead(_20); - StorageDead(_21); - StorageDead(_19); + StorageDead(_17); + StorageDead(_18); + StorageDead(_16); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_26); - StorageDead(_18); - StorageDead(_10); - StorageDead(_8); + StorageDead(_23); + StorageDead(_15); + StorageDead(_7); StorageDead(_6); + StorageDead(_5); StorageDead(_4); return; } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index e2ed1d101dc..5477796512c 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,46 +4,40 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:12:25: 12:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let mut _5: &(usize, usize, usize, usize); + let _5: usize; let _6: usize; - let mut _7: &(usize, usize, usize, usize); - let _8: usize; - let mut _9: &(usize, usize, usize, usize); - let _10: usize; - let mut _11: bool; - let mut _12: bool; - let mut _13: bool; + let _7: usize; + let mut _8: bool; + let mut _9: bool; + let mut _10: bool; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; } bb0: { - _3 = deref_copy (*_2); + _3 = (*_2); _4 = ((*_3).0: usize); - _5 = deref_copy (*_2); - _6 = ((*_5).1: usize); - _7 = deref_copy (*_2); - _8 = ((*_7).2: usize); - _9 = deref_copy (*_2); - _10 = ((*_9).3: usize); - StorageLive(_11); - _11 = Le(_4, _8); - switchInt(move _11) -> [0: bb2, otherwise: bb1]; + _5 = ((*_3).1: usize); + _6 = ((*_3).2: usize); + _7 = ((*_3).3: usize); + StorageLive(_8); + _8 = Le(_4, _6); + switchInt(move _8) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_12); - _12 = Le(_10, _6); - switchInt(move _12) -> [0: bb2, otherwise: bb6]; + StorageLive(_9); + _9 = Le(_7, _5); + switchInt(move _9) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_13); - _13 = Le(_8, _4); - switchInt(move _13) -> [0: bb3, otherwise: bb4]; + StorageLive(_10); + _10 = Le(_6, _4); + switchInt(move _10) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -52,12 +46,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:12:25: 12:41}, } bb4: { - _0 = Le(_6, _10); + _0 = Le(_5, _7); goto -> bb5; } bb5: { - StorageDead(_13); + StorageDead(_10); goto -> bb7; } @@ -67,8 +61,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:12:25: 12:41}, } bb7: { - StorageDead(_12); - StorageDead(_11); + StorageDead(_9); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index e4d9060d4cf..a12411a0413 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -50,7 +50,6 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { - StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -86,7 +85,6 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); - StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index e4d9060d4cf..a12411a0413 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -50,7 +50,6 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { - StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -86,7 +85,6 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); - StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index db6922968ae..6a99f15774f 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -84,7 +84,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::<usize>::None; + _12 = const Option::<usize>::None; goto -> bb5; } @@ -147,3 +147,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { unreachable; } } + +ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ +} diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 81d1832eebb..4f028fa0a64 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -84,7 +84,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::<usize>::None; + _12 = const Option::<usize>::None; goto -> bb5; } @@ -155,3 +155,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { resume; } } + +ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ +} diff --git a/tests/mir-opt/simplify_match.main.ConstProp.panic-abort.diff b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff index 6025abb7382..825babe7994 100644 --- a/tests/mir-opt/simplify_match.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff index c881dec28c7..24ab6c39788 100644 --- a/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before ConstProp -+ // MIR for `main` after ConstProp +- // MIR for `main` before GVN ++ // MIR for `main` after GVN fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs index eb385005cd9..2eac93edbb8 100644 --- a/tests/mir-opt/simplify_match.rs +++ b/tests/mir-opt/simplify_match.rs @@ -3,7 +3,7 @@ #[inline(never)] fn noop() {} -// EMIT_MIR simplify_match.main.ConstProp.diff +// EMIT_MIR simplify_match.main.GVN.diff fn main() { match { let x = false; x } { true => noop(), diff --git a/tests/rustdoc-js-std/asrawfd.js b/tests/rustdoc-js-std/asrawfd.js index 5b3cfeabbcd..5dbc4ba95d9 100644 --- a/tests/rustdoc-js-std/asrawfd.js +++ b/tests/rustdoc-js-std/asrawfd.js @@ -7,7 +7,6 @@ const EXPECTED = { // Validate that type alias methods get the correct path. { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' }, ], }; diff --git a/tests/rustdoc-js-std/path-maxeditdistance.js b/tests/rustdoc-js-std/path-maxeditdistance.js new file mode 100644 index 00000000000..822389aaa4f --- /dev/null +++ b/tests/rustdoc-js-std/path-maxeditdistance.js @@ -0,0 +1,42 @@ +// exact-check +const FILTER_CRATE = "std"; +const EXPECTED = [ + { + query: 'vec::intoiterator', + others: [ + // trait std::iter::IntoIterator is not the first result + { 'path': 'std::vec', 'name': 'IntoIter' }, + { 'path': 'std::vec::Vec', 'name': 'into_iter' }, + { 'path': 'std::vec::Drain', 'name': 'into_iter' }, + { 'path': 'std::vec::IntoIter', 'name': 'into_iter' }, + { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, + { 'path': 'std::vec::Splice', 'name': 'into_iter' }, + { 'path': 'std::collections::VecDeque', 'name': 'into_iter' }, + ], + }, + { + query: 'vec::iter', + others: [ + // std::net::ToSocketAttrs::iter should not show up here + { 'path': 'std::vec', 'name': 'IntoIter' }, + { 'path': 'std::vec::Vec', 'name': 'from_iter' }, + { 'path': 'std::vec::Vec', 'name': 'into_iter' }, + { 'path': 'std::vec::Drain', 'name': 'into_iter' }, + { 'path': 'std::vec::IntoIter', 'name': 'into_iter' }, + { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, + { 'path': 'std::vec::Splice', 'name': 'into_iter' }, + { 'path': 'std::collections::VecDeque', 'name': 'iter' }, + { 'path': 'std::collections::VecDeque', 'name': 'iter_mut' }, + { 'path': 'std::collections::VecDeque', 'name': 'from_iter' }, + { 'path': 'std::collections::VecDeque', 'name': 'into_iter' }, + ], + }, + { + query: 'slice::itermut', + others: [ + // std::collections::btree_map::itermut should not show up here + { 'path': 'std::slice', 'name': 'IterMut' }, + { 'path': 'std::slice', 'name': 'iter_mut' }, + ], + }, +]; diff --git a/tests/rustdoc-js-std/path-ordering.js b/tests/rustdoc-js-std/path-ordering.js index c3d61d238cc..e6b7bfab1e5 100644 --- a/tests/rustdoc-js-std/path-ordering.js +++ b/tests/rustdoc-js-std/path-ordering.js @@ -1,11 +1,20 @@ -const EXPECTED = { - query: 'hashset::insert', - others: [ - // ensure hashset::insert comes first - { 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' }, - { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert' }, - { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_with' }, - { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_owned' }, - { 'path': 'std::collections::hash_map::HashMap', 'name': 'insert' }, - ], -}; +const EXPECTED = [ + { + query: 'hashset::insert', + others: [ + // ensure hashset::insert comes first + { 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' }, + { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert' }, + { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_with' }, + { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_owned' }, + ], + }, + { + query: 'hash::insert', + others: [ + // ensure hashset/hashmap::insert come first + { 'path': 'std::collections::hash_map::HashMap', 'name': 'insert' }, + { 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' }, + ], + }, +]; diff --git a/tests/rustdoc-js/exact-match.js b/tests/rustdoc-js/exact-match.js index ce3a76f9b7d..9e47d27490b 100644 --- a/tests/rustdoc-js/exact-match.js +++ b/tests/rustdoc-js/exact-match.js @@ -3,6 +3,5 @@ const EXPECTED = { 'others': [ { 'path': 'exact_match::Si', 'name': 'pc' }, { 'path': 'exact_match::Psi', 'name': 'pc' }, - { 'path': 'exact_match::Si', 'name': 'pa' }, ], }; diff --git a/tests/rustdoc-js/module-substring.js b/tests/rustdoc-js/module-substring.js index 7a10397ebc6..74c421d7f0b 100644 --- a/tests/rustdoc-js/module-substring.js +++ b/tests/rustdoc-js/module-substring.js @@ -1,7 +1,15 @@ -const EXPECTED = { - 'query': 'ig::pc', - 'others': [ - { 'path': 'module_substring::Sig', 'name': 'pc' }, - { 'path': 'module_substring::Si', 'name': 'pc' }, - ], -}; +const EXPECTED = [ + { + 'query': 'ig::pc', + 'others': [ + { 'path': 'module_substring::Sig', 'name': 'pc' }, + ], + }, + { + 'query': 'si::pc', + 'others': [ + { 'path': 'module_substring::Si', 'name': 'pc' }, + { 'path': 'module_substring::Sig', 'name': 'pc' }, + ], + }, +]; diff --git a/tests/rustdoc-js/path-maxeditdistance.js b/tests/rustdoc-js/path-maxeditdistance.js new file mode 100644 index 00000000000..73b24a6dddf --- /dev/null +++ b/tests/rustdoc-js/path-maxeditdistance.js @@ -0,0 +1,35 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'xxxxxxxxxxx::hocuspocusprestidigitation', + // do not match abracadabra::hocuspocusprestidigitation + 'others': [], + }, + { + // exact match + 'query': 'abracadabra::hocuspocusprestidigitation', + 'others': [ + { 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' }, + ], + }, + { + // swap br/rb; that's edit distance 2, where maxPathEditDistance = 3 (11 / 3) + 'query': 'arbacadarba::hocuspocusprestidigitation', + 'others': [ + { 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' }, + ], + }, + { + // truncate 5 chars, where maxEditDistance = 7 (21 / 3) + 'query': 'abracadarba::hocusprestidigitation', + 'others': [ + { 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' }, + ], + }, + { + // truncate 9 chars, where maxEditDistance = 5 (17 / 3) + 'query': 'abracadarba::hprestidigitation', + 'others': [], + }, +]; diff --git a/tests/rustdoc-js/path-maxeditdistance.rs b/tests/rustdoc-js/path-maxeditdistance.rs new file mode 100644 index 00000000000..3861280d59b --- /dev/null +++ b/tests/rustdoc-js/path-maxeditdistance.rs @@ -0,0 +1,3 @@ +#![crate_name="abracadabra"] + +pub struct HocusPocusPrestidigitation; diff --git a/tests/rustdoc-js/path-ordering.js b/tests/rustdoc-js/path-ordering.js index f2e6fe2fa61..73d3f4b2755 100644 --- a/tests/rustdoc-js/path-ordering.js +++ b/tests/rustdoc-js/path-ordering.js @@ -1,13 +1,13 @@ // exact-check const EXPECTED = { - 'query': 'b::ccccccc', + 'query': 'bbbbbb::ccccccc', 'others': [ // `ccccccc` is an exact match for all three of these. // However `b` is a closer match for `bb` than for any // of the others, so it ought to go first. - { 'path': 'path_ordering::bb', 'name': 'Ccccccc' }, - { 'path': 'path_ordering::aa', 'name': 'Ccccccc' }, - { 'path': 'path_ordering::dd', 'name': 'Ccccccc' }, + { 'path': 'path_ordering::bbbbbb', 'name': 'Ccccccc' }, + { 'path': 'path_ordering::abbbbb', 'name': 'Ccccccc' }, + { 'path': 'path_ordering::dbbbbb', 'name': 'Ccccccc' }, ], }; diff --git a/tests/rustdoc-js/path-ordering.rs b/tests/rustdoc-js/path-ordering.rs index 7843cf7f9dc..71e24923ed1 100644 --- a/tests/rustdoc-js/path-ordering.rs +++ b/tests/rustdoc-js/path-ordering.rs @@ -1,9 +1,9 @@ -pub mod dd { +pub mod dbbbbb { pub struct Ccccccc; } -pub mod aa { +pub mod abbbbb { pub struct Ccccccc; } -pub mod bb { +pub mod bbbbbb { pub struct Ccccccc; } diff --git a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr index f3ec3200f94..7e764ca7239 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr @@ -10,12 +10,6 @@ note: erroneous constant encountered LL | &<A<T> as Foo<T>>::BAR | ^^^^^^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/issue-50814-2.rs:20:5 - | -LL | &<A<T> as Foo<T>>::BAR - | ^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0453.rs b/tests/ui/error-codes/E0453.rs index ca9573c5b46..8ed724dd3fc 100644 --- a/tests/ui/error-codes/E0453.rs +++ b/tests/ui/error-codes/E0453.rs @@ -2,6 +2,5 @@ #[allow(non_snake_case)] //~^ ERROR allow(non_snake_case) incompatible -//~| ERROR allow(non_snake_case) incompatible fn main() { } diff --git a/tests/ui/error-codes/E0453.stderr b/tests/ui/error-codes/E0453.stderr index bb2c39298c0..9a89f0d41e4 100644 --- a/tests/ui/error-codes/E0453.stderr +++ b/tests/ui/error-codes/E0453.stderr @@ -7,17 +7,6 @@ LL | LL | #[allow(non_snake_case)] | ^^^^^^^^^^^^^^ overruled by previous forbid -error[E0453]: allow(non_snake_case) incompatible with previous forbid - --> $DIR/E0453.rs:3:9 - | -LL | #![forbid(non_snake_case)] - | -------------- `forbid` level set here -LL | -LL | #[allow(non_snake_case)] - | ^^^^^^^^^^^^^^ overruled by previous forbid - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs index 0467dea621b..4e296b96ca9 100644 --- a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs +++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs @@ -2,11 +2,7 @@ #![deny(multiple_supertrait_upcastable)] //~^ WARNING unknown lint: `multiple_supertrait_upcastable` -//~| WARNING unknown lint: `multiple_supertrait_upcastable` -//~| WARNING unknown lint: `multiple_supertrait_upcastable` #![warn(multiple_supertrait_upcastable)] //~^ WARNING unknown lint: `multiple_supertrait_upcastable` -//~| WARNING unknown lint: `multiple_supertrait_upcastable` -//~| WARNING unknown lint: `multiple_supertrait_upcastable` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr index 5e14bf6397f..f6fcf4ee3ed 100644 --- a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr +++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr @@ -9,7 +9,7 @@ LL | #![deny(multiple_supertrait_upcastable)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1 + --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:5:1 | LL | #![warn(multiple_supertrait_upcastable)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,45 +17,5 @@ LL | #![warn(multiple_supertrait_upcastable)] = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable -warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1 - | -LL | #![deny(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `multiple_supertrait_upcastable` lint is unstable - = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1 - | -LL | #![warn(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `multiple_supertrait_upcastable` lint is unstable - = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1 - | -LL | #![deny(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `multiple_supertrait_upcastable` lint is unstable - = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1 - | -LL | #![warn(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `multiple_supertrait_upcastable` lint is unstable - = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 6 warnings emitted +warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs index 1922bfb4913..1db3c2ccdde 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -2,12 +2,8 @@ #![deny(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` #![allow(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` fn main() { enum Foo { @@ -19,9 +15,6 @@ fn main() { #[allow(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` match Foo::A { //~^ ERROR non-exhaustive patterns: `Foo::C` not covered Foo::A => {} @@ -31,9 +24,6 @@ fn main() { #[warn(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` match Foo::A { Foo::A => {} Foo::B => {} diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index a5333713977..955d7fe3f3e 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -10,7 +10,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:5:1 | LL | #![allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:5 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,73 +51,7 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 - | -LL | #![deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 - | -LL | #![allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:5 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,13 +62,13 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0004]: non-exhaustive patterns: `Foo::C` not covered - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:25:11 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:18:11 | LL | match Foo::A { | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:10 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:9:10 | LL | enum Foo { | ^^^ @@ -148,50 +82,6 @@ LL ~ Foo::B => {}, LL + Foo::C => todo!() | -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 - | -LL | #![deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 - | -LL | #![allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 1 previous error; 16 warnings emitted +error: aborting due to 1 previous error; 6 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.rs b/tests/ui/feature-gates/feature-gate-strict_provenance.rs index 75d0ee5700d..24b8369b3d8 100644 --- a/tests/ui/feature-gates/feature-gate-strict_provenance.rs +++ b/tests/ui/feature-gates/feature-gate-strict_provenance.rs @@ -2,12 +2,8 @@ #![deny(fuzzy_provenance_casts)] //~^ WARNING unknown lint: `fuzzy_provenance_casts` -//~| WARNING unknown lint: `fuzzy_provenance_casts` -//~| WARNING unknown lint: `fuzzy_provenance_casts` #![deny(lossy_provenance_casts)] //~^ WARNING unknown lint: `lossy_provenance_casts` -//~| WARNING unknown lint: `lossy_provenance_casts` -//~| WARNING unknown lint: `lossy_provenance_casts` fn main() { // no warnings emitted since the lints are not activated diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr index 1e6d762a540..36224ee864b 100644 --- a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr +++ b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr @@ -10,7 +10,7 @@ LL | #![deny(fuzzy_provenance_casts)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `lossy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:7:1 + --> $DIR/feature-gate-strict_provenance.rs:5:1 | LL | #![deny(lossy_provenance_casts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,49 +19,5 @@ LL | #![deny(lossy_provenance_casts)] = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information = help: add `#![feature(strict_provenance)]` to the crate attributes to enable -warning: unknown lint: `fuzzy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:3:1 - | -LL | #![deny(fuzzy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `fuzzy_provenance_casts` lint is unstable - = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `lossy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:7:1 - | -LL | #![deny(lossy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `lossy_provenance_casts` lint is unstable - = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `fuzzy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:3:1 - | -LL | #![deny(fuzzy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `fuzzy_provenance_casts` lint is unstable - = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `lossy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:7:1 - | -LL | #![deny(lossy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `lossy_provenance_casts` lint is unstable - = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 6 warnings emitted +warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs b/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs index c398394cbe1..3882ba9a227 100644 --- a/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs @@ -3,7 +3,5 @@ // `test_unstable_lint` is for testing and should never be stabilized. #![allow(test_unstable_lint)] //~^ WARNING unknown lint: `test_unstable_lint` -//~| WARNING unknown lint: `test_unstable_lint` -//~| WARNING unknown lint: `test_unstable_lint` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr index 562aa478a93..aec32ac4abb 100644 --- a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr @@ -8,25 +8,5 @@ LL | #![allow(test_unstable_lint)] = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable = note: `#[warn(unknown_lints)]` on by default -warning: unknown lint: `test_unstable_lint` - --> $DIR/feature-gate-test_unstable_lint.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `test_unstable_lint` - --> $DIR/feature-gate-test_unstable_lint.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs b/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs index 8bb9736f1b4..80e51b265db 100644 --- a/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs +++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs @@ -1,6 +1,4 @@ // check-pass #![warn(unnameable_types)] //~ WARN unknown lint - //~| WARN unknown lint - //~| WARN unknown lint fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr index 2614f2b3c35..5cc30de9c57 100644 --- a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr +++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr @@ -9,27 +9,5 @@ LL | #![warn(unnameable_types)] = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable = note: `#[warn(unknown_lints)]` on by default -warning: unknown lint: `unnameable_types` - --> $DIR/feature-gate-type_privacy_lints.rs:3:1 - | -LL | #![warn(unnameable_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `unnameable_types` lint is unstable - = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information - = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `unnameable_types` - --> $DIR/feature-gate-type_privacy_lints.rs:3:1 - | -LL | #![warn(unnameable_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `unnameable_types` lint is unstable - = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information - = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs index 9ffc2190d20..55353999b67 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -17,7 +17,7 @@ fn main() { } match x as i32 { 0..5+1 => errors_only.push(x), - //~^ error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` + //~^ error: expected one of `=>`, `if`, or `|`, found `+` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index 05235c9b922..19ebcaf0f36 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` +error: expected one of `=>`, `if`, or `|`, found `+` --> $DIR/range_pat_interactions1.rs:19:17 | LL | 0..5+1 => errors_only.push(x), - | ^ expected one of `,`, `=>`, `if`, `|`, or `}` + | ^ expected one of `=>`, `if`, or `|` error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs index b212bfbe093..4615ebd688a 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -9,7 +9,7 @@ fn main() { match x as i32 { 0..=(5+1) => errors_only.push(x), //~^ error: inclusive range with no end - //~| error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` + //~| error: expected one of `=>`, `if`, or `|`, found `(` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index 0129f927e34..13a5542a474 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -6,11 +6,11 @@ LL | 0..=(5+1) => errors_only.push(x), | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` +error: expected one of `=>`, `if`, or `|`, found `(` --> $DIR/range_pat_interactions2.rs:10:17 | LL | 0..=(5+1) => errors_only.push(x), - | ^ expected one of `,`, `=>`, `if`, `|`, or `}` + | ^ expected one of `=>`, `if`, or `|` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/associated-impl-trait-type-issue-114325.rs b/tests/ui/impl-trait/associated-impl-trait-type-issue-114325.rs new file mode 100644 index 00000000000..8173f8df11b --- /dev/null +++ b/tests/ui/impl-trait/associated-impl-trait-type-issue-114325.rs @@ -0,0 +1,55 @@ +// This is a non-regression test for issue #114325: an "unexpected unsized tail" ICE happened during +// codegen, and was fixed by MIR drop tracking #107421. + +// edition: 2021 +// build-pass: ICEd during codegen. + +#![feature(impl_trait_in_assoc_type)] + +use std::future::Future; + +fn main() { + RuntimeRef::spawn_local(actor_fn(http_actor)); +} + +async fn http_actor() { + async fn respond(body: impl Body) { + body.write_message().await; + } + + respond(&()).await; +} + +trait Body { + type WriteFuture: Future; + + fn write_message(self) -> Self::WriteFuture; +} + +impl Body for &'static () { + type WriteFuture = impl Future<Output = ()>; + + fn write_message(self) -> Self::WriteFuture { + async {} + } +} + +trait NewActor { + type RuntimeAccess; +} + +fn actor_fn<T, A>(_d: T) -> (T, A) { + loop {} +} + +impl<F: FnMut() -> A, A> NewActor for (F, A) { + type RuntimeAccess = RuntimeRef; +} +struct RuntimeRef(Vec<()>); + +impl RuntimeRef { + fn spawn_local<NA: NewActor<RuntimeAccess = RuntimeRef>>(_f: NA) { + struct ActorFuture<NA: NewActor>(NA::RuntimeAccess); + (ActorFuture::<NA>(RuntimeRef(vec![])), _f); + } +} diff --git a/tests/ui/impl-trait/not_general_enough_regression_106630.rs b/tests/ui/impl-trait/not_general_enough_regression_106630.rs new file mode 100644 index 00000000000..439973950f3 --- /dev/null +++ b/tests/ui/impl-trait/not_general_enough_regression_106630.rs @@ -0,0 +1,33 @@ +// edition:2018 +// run-pass + +use std::future::Future; + +trait AsyncCallback<'a> { + type Out; +} + +impl<'a, Fut, T, F> AsyncCallback<'a> for F +where + F: FnOnce(&'a mut ()) -> Fut, + Fut: Future<Output = T> + Send + 'a, +{ + type Out = T; +} + +trait CallbackMarker {} + +impl<F, T> CallbackMarker for F +where + T: 'static, + for<'a> F: AsyncCallback<'a, Out = T> + Send, +{ +} + +fn do_sth<F: CallbackMarker>(_: F) {} + +async fn callback(_: &mut ()) -> impl Send {} + +fn main() { + do_sth(callback); +} diff --git a/tests/ui/lint/crate_level_only_lint.rs b/tests/ui/lint/crate_level_only_lint.rs index d9673faa214..6679cc0862f 100644 --- a/tests/ui/lint/crate_level_only_lint.rs +++ b/tests/ui/lint/crate_level_only_lint.rs @@ -3,20 +3,14 @@ mod foo { #![allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] #[allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] const BAR: f64 = 0.000001; } #[allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] -//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] fn main() { } diff --git a/tests/ui/lint/crate_level_only_lint.stderr b/tests/ui/lint/crate_level_only_lint.stderr index fbb1ec381c8..34d27f873f6 100644 --- a/tests/ui/lint/crate_level_only_lint.stderr +++ b/tests/ui/lint/crate_level_only_lint.stderr @@ -11,64 +11,16 @@ LL | #![deny(uncommon_codepoints, unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:9:9 + --> $DIR/crate_level_only_lint.rs:7:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:17:9 + --> $DIR/crate_level_only_lint.rs:13:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:4:10 - | -LL | #![allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:9:9 - | -LL | #[allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:17:9 - | -LL | #[allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:4:10 - | -LL | #![allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:9:9 - | -LL | #[allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:17:9 - | -LL | #[allow(uncommon_codepoints)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 9 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/lint/forbid-group-group-2.rs b/tests/ui/lint/forbid-group-group-2.rs index b12fd72da74..b3d3e30fb8d 100644 --- a/tests/ui/lint/forbid-group-group-2.rs +++ b/tests/ui/lint/forbid-group-group-2.rs @@ -11,16 +11,4 @@ //~| WARNING previously accepted by the compiler //~| ERROR incompatible with previous //~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler -//~| ERROR incompatible with previous -//~| WARNING previously accepted by the compiler fn main() {} diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr index 4a2c8fbd68a..80e2f566eb8 100644 --- a/tests/ui/lint/forbid-group-group-2.stderr +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -41,83 +41,5 @@ LL | #[allow(nonstandard_style)] = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/forbid-group-group-2.rs:7:9 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -... -LL | #[allow(nonstandard_style)] - | ^^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 9 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/lint/forbid-group-member.rs b/tests/ui/lint/forbid-group-member.rs index 664edeaa8b4..d03e858438b 100644 --- a/tests/ui/lint/forbid-group-member.rs +++ b/tests/ui/lint/forbid-group-member.rs @@ -8,10 +8,6 @@ #[allow(unused_variables)] //~^ WARNING incompatible with previous forbid //~| WARNING previously accepted -//~| WARNING incompatible with previous forbid -//~| WARNING previously accepted -//~| WARNING incompatible with previous forbid -//~| WARNING previously accepted fn main() { let a: (); } diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr index ddaaafa12ec..8794591bd31 100644 --- a/tests/ui/lint/forbid-group-member.stderr +++ b/tests/ui/lint/forbid-group-member.stderr @@ -11,31 +11,5 @@ LL | #[allow(unused_variables)] = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> = note: `#[warn(forbidden_lint_groups)]` on by default -warning: allow(unused_variables) incompatible with previous forbid - --> $DIR/forbid-group-member.rs:8:9 - | -LL | #![forbid(unused)] - | ------ `forbid` level set here -LL | -LL | #[allow(unused_variables)] - | ^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: allow(unused_variables) incompatible with previous forbid - --> $DIR/forbid-group-member.rs:8:9 - | -LL | #![forbid(unused)] - | ------ `forbid` level set here -LL | -LL | #[allow(unused_variables)] - | ^^^^^^^^^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/forbid-member-group.rs b/tests/ui/lint/forbid-member-group.rs index e2f76825a2d..d1874aa81a5 100644 --- a/tests/ui/lint/forbid-member-group.rs +++ b/tests/ui/lint/forbid-member-group.rs @@ -5,7 +5,6 @@ #[allow(unused)] //~^ ERROR incompatible with previous forbid -//~| ERROR incompatible with previous forbid fn main() { let a: (); } diff --git a/tests/ui/lint/forbid-member-group.stderr b/tests/ui/lint/forbid-member-group.stderr index 612dccd8d6c..9b32c00a3c3 100644 --- a/tests/ui/lint/forbid-member-group.stderr +++ b/tests/ui/lint/forbid-member-group.stderr @@ -7,17 +7,6 @@ LL | LL | #[allow(unused)] | ^^^^^^ overruled by previous forbid -error[E0453]: allow(unused) incompatible with previous forbid - --> $DIR/forbid-member-group.rs:6:9 - | -LL | #![forbid(unused_variables)] - | ---------------- `forbid` level set here -LL | -LL | #[allow(unused)] - | ^^^^^^ overruled by previous forbid - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/issue-80988.rs b/tests/ui/lint/issue-80988.rs index 1e116206f7b..5b910f1d8df 100644 --- a/tests/ui/lint/issue-80988.rs +++ b/tests/ui/lint/issue-80988.rs @@ -7,8 +7,4 @@ #[deny(warnings)] //~^ WARNING incompatible with previous forbid //~| WARNING being phased out -//~| WARNING incompatible with previous forbid -//~| WARNING being phased out -//~| WARNING incompatible with previous forbid -//~| WARNING being phased out fn main() {} diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr index 7a65881b5ed..afc93fcfeef 100644 --- a/tests/ui/lint/issue-80988.stderr +++ b/tests/ui/lint/issue-80988.stderr @@ -11,31 +11,5 @@ LL | #[deny(warnings)] = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> = note: `#[warn(forbidden_lint_groups)]` on by default -warning: deny(warnings) incompatible with previous forbid - --> $DIR/issue-80988.rs:7:8 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -LL | -LL | #[deny(warnings)] - | ^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: deny(warnings) incompatible with previous forbid - --> $DIR/issue-80988.rs:7:8 - | -LL | #![forbid(warnings)] - | -------- `forbid` level set here -LL | -LL | #[deny(warnings)] - | ^^^^^^^^ overruled by previous forbid - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/lint-forbid-attr.rs b/tests/ui/lint/lint-forbid-attr.rs index 6d4cfd83424..270a379c2f8 100644 --- a/tests/ui/lint/lint-forbid-attr.rs +++ b/tests/ui/lint/lint-forbid-attr.rs @@ -2,6 +2,5 @@ #[allow(deprecated)] //~^ ERROR allow(deprecated) incompatible -//~| ERROR allow(deprecated) incompatible fn main() { } diff --git a/tests/ui/lint/lint-forbid-attr.stderr b/tests/ui/lint/lint-forbid-attr.stderr index bd476a0e362..fa7106b5e11 100644 --- a/tests/ui/lint/lint-forbid-attr.stderr +++ b/tests/ui/lint/lint-forbid-attr.stderr @@ -7,17 +7,6 @@ LL | LL | #[allow(deprecated)] | ^^^^^^^^^^ overruled by previous forbid -error[E0453]: allow(deprecated) incompatible with previous forbid - --> $DIR/lint-forbid-attr.rs:3:9 - | -LL | #![forbid(deprecated)] - | ---------- `forbid` level set here -LL | -LL | #[allow(deprecated)] - | ^^^^^^^^^^ overruled by previous forbid - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/lint-forbid-cmdline.rs b/tests/ui/lint/lint-forbid-cmdline.rs index 5246ccb57a6..32a92e09b14 100644 --- a/tests/ui/lint/lint-forbid-cmdline.rs +++ b/tests/ui/lint/lint-forbid-cmdline.rs @@ -1,6 +1,5 @@ // compile-flags: -F deprecated #[allow(deprecated)] //~ ERROR allow(deprecated) incompatible - //~| ERROR allow(deprecated) incompatible fn main() { } diff --git a/tests/ui/lint/lint-forbid-cmdline.stderr b/tests/ui/lint/lint-forbid-cmdline.stderr index ed49a2cb427..3920a742976 100644 --- a/tests/ui/lint/lint-forbid-cmdline.stderr +++ b/tests/ui/lint/lint-forbid-cmdline.stderr @@ -6,15 +6,6 @@ LL | #[allow(deprecated)] | = note: `forbid` lint level was set on command line -error[E0453]: allow(deprecated) incompatible with previous forbid - --> $DIR/lint-forbid-cmdline.rs:3:9 - | -LL | #[allow(deprecated)] - | ^^^^^^^^^^ overruled by previous forbid - | - = note: `forbid` lint level was set on command line - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/must_not_suspend/gated.rs b/tests/ui/lint/must_not_suspend/gated.rs index b73a7655529..fe8192b0eaa 100644 --- a/tests/ui/lint/must_not_suspend/gated.rs +++ b/tests/ui/lint/must_not_suspend/gated.rs @@ -3,8 +3,6 @@ // edition:2018 #![deny(must_not_suspend)] //~^ WARNING unknown lint: `must_not_suspend` -//~| WARNING unknown lint: `must_not_suspend` -//~| WARNING unknown lint: `must_not_suspend` async fn other() {} diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr index f0d2117d42b..c238c1f3351 100644 --- a/tests/ui/lint/must_not_suspend/gated.stderr +++ b/tests/ui/lint/must_not_suspend/gated.stderr @@ -9,27 +9,5 @@ LL | #![deny(must_not_suspend)] = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable = note: `#[warn(unknown_lints)]` on by default -warning: unknown lint: `must_not_suspend` - --> $DIR/gated.rs:4:1 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `must_not_suspend` lint is unstable - = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information - = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `must_not_suspend` - --> $DIR/gated.rs:4:1 - | -LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `must_not_suspend` lint is unstable - = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information - = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/unused/issue-119383-if-let-guard.rs b/tests/ui/lint/unused/issue-119383-if-let-guard.rs new file mode 100644 index 00000000000..71197444f45 --- /dev/null +++ b/tests/ui/lint/unused/issue-119383-if-let-guard.rs @@ -0,0 +1,9 @@ +#![feature(if_let_guard)] +#![deny(unused_variables)] + +fn main() { + match () { + () if let Some(b) = Some(()) => {} //~ ERROR unused variable: `b` + _ => {} + } +} diff --git a/tests/ui/lint/unused/issue-119383-if-let-guard.stderr b/tests/ui/lint/unused/issue-119383-if-let-guard.stderr new file mode 100644 index 00000000000..5bf48bb80a8 --- /dev/null +++ b/tests/ui/lint/unused/issue-119383-if-let-guard.stderr @@ -0,0 +1,14 @@ +error: unused variable: `b` + --> $DIR/issue-119383-if-let-guard.rs:6:24 + | +LL | () if let Some(b) = Some(()) => {} + | ^ help: if this is intentional, prefix it with an underscore: `_b` + | +note: the lint level is defined here + --> $DIR/issue-119383-if-let-guard.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/methods/disambiguate-associated-function-first-arg.rs b/tests/ui/methods/disambiguate-associated-function-first-arg.rs new file mode 100644 index 00000000000..4c8192fc14b --- /dev/null +++ b/tests/ui/methods/disambiguate-associated-function-first-arg.rs @@ -0,0 +1,49 @@ +struct A {} + +fn main() { + let _a = A {}; + _a.new(1); + //~^ ERROR no method named `new` found for struct `A` in the current scope +} + +trait M { + fn new(_a: i32); +} +impl M for A { + fn new(_a: i32) {} +} + +trait N { + fn new(_a: Self, _b: i32); +} +impl N for A { + fn new(_a: Self, _b: i32) {} +} + +trait O { + fn new(_a: Self, _b: i32); +} +impl O for A { + fn new(_a: A, _b: i32) {} +} + +struct S; + +trait TraitA { + fn f(self); +} +trait TraitB { + fn f(self); +} + +impl<T> TraitA for T { + fn f(self) {} +} +impl<T> TraitB for T { + fn f(self) {} +} + +fn test() { + S.f(); + //~^ multiple applicable items in scope +} diff --git a/tests/ui/methods/disambiguate-associated-function-first-arg.stderr b/tests/ui/methods/disambiguate-associated-function-first-arg.stderr new file mode 100644 index 00000000000..341b7a91003 --- /dev/null +++ b/tests/ui/methods/disambiguate-associated-function-first-arg.stderr @@ -0,0 +1,67 @@ +error[E0599]: no method named `new` found for struct `A` in the current scope + --> $DIR/disambiguate-associated-function-first-arg.rs:5:8 + | +LL | struct A {} + | -------- method `new` not found for this struct +... +LL | _a.new(1); + | ^^^ this is an associated function, not a method + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: candidate #1 is defined in the trait `M` + --> $DIR/disambiguate-associated-function-first-arg.rs:10:5 + | +LL | fn new(_a: i32); + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `N` + --> $DIR/disambiguate-associated-function-first-arg.rs:17:5 + | +LL | fn new(_a: Self, _b: i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #3 is defined in the trait `O` + --> $DIR/disambiguate-associated-function-first-arg.rs:24:5 + | +LL | fn new(_a: Self, _b: i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | <A as M>::new(1); + | ~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | <A as N>::new(_a, 1); + | ~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #3 + | +LL | <A as O>::new(_a, 1); + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-associated-function-first-arg.rs:47:7 + | +LL | S.f(); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl of the trait `TraitA` for the type `T` + --> $DIR/disambiguate-associated-function-first-arg.rs:40:5 + | +LL | fn f(self) {} + | ^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `TraitB` for the type `T` + --> $DIR/disambiguate-associated-function-first-arg.rs:43:5 + | +LL | fn f(self) {} + | ^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | TraitA::f(S); + | ~~~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | TraitB::f(S); + | ~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0034, E0599. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambiguity-no-rcvr.stderr b/tests/ui/methods/method-ambiguity-no-rcvr.stderr index 73f6043f256..3b6eb07393a 100644 --- a/tests/ui/methods/method-ambiguity-no-rcvr.stderr +++ b/tests/ui/methods/method-ambiguity-no-rcvr.stderr @@ -20,12 +20,12 @@ LL | fn foo() {} | ^^^^^^^^ help: disambiguate the associated function for candidate #1 | -LL | <Qux as Foo>::foo(Qux); - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | <Qux as Foo>::foo(); + | ~~~~~~~~~~~~~~~~~~~ help: disambiguate the associated function for candidate #2 | -LL | <Qux as FooBar>::foo(Qux); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | <Qux as FooBar>::foo(); + | ~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs index 2c402e4c65e..d1950087c4c 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs @@ -84,15 +84,15 @@ fn main() {} #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } //~^ ERROR unexpected token: `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } //~^ ERROR unexpected token: `#` diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index a0e95c5c1ed..e46c591080d 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -365,11 +365,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:85:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } - | ^ expected one of `,`, `=>`, `if`, `|`, or `}` + | ^ expected one of `=>`, `if`, or `|` error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 @@ -379,11 +379,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:88:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } - | ^ expected one of `,`, `=>`, `if`, `|`, or `}` + | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:91:39 @@ -399,11 +399,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` +error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:93:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } - | ^ expected one of `,`, `=>`, `if`, `|`, or `}` + | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:97:34 diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs index 8d1bc579e7b..1d128d33e4f 100644 --- a/tests/ui/parser/issues/issue-24375.rs +++ b/tests/ui/parser/issues/issue-24375.rs @@ -3,7 +3,7 @@ static tmp : [&'static str; 2] = ["hello", "he"]; fn main() { let z = "hello"; match z { - tmp[0] => {} //~ ERROR expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` + tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[` _ => {} } } diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index 2b980a5520f..bb1e19e9e6d 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` +error: expected one of `=>`, `@`, `if`, or `|`, found `[` --> $DIR/issue-24375.rs:6:12 | LL | tmp[0] => {} - | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` + | ^ expected one of `=>`, `@`, `if`, or `|` error: aborting due to 1 previous error diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr index d98c7ec2826..a3f7e32c177 100644 --- a/tests/ui/parser/match-arm-without-body.stderr +++ b/tests/ui/parser/match-arm-without-body.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `=>`, `if`, `|`, or `}`, found reserved identifier `_` +error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` --> $DIR/match-arm-without-body.rs:13:9 | LL | Some(_) - | - expected one of `,`, `=>`, `if`, `|`, or `}` + | - expected one of `=>`, `if`, or `|` LL | _ => {} | ^ unexpected token @@ -44,11 +44,11 @@ LL + LL ~ _ => {} | -error: expected one of `,`, `.`, `=>`, `?`, `}`, or an operator, found reserved identifier `_` +error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` --> $DIR/match-arm-without-body.rs:36:9 | LL | Some(_) if true - | - expected one of `,`, `.`, `=>`, `?`, `}`, or an operator + | - expected one of `.`, `=>`, `?`, or an operator LL | _ => {} | ^ unexpected token diff --git a/tests/ui/parser/pat-lt-bracket-1.rs b/tests/ui/parser/pat-lt-bracket-1.rs index 33da15adb9e..2e2001434f2 100644 --- a/tests/ui/parser/pat-lt-bracket-1.rs +++ b/tests/ui/parser/pat-lt-bracket-1.rs @@ -1,7 +1,7 @@ fn main() { match 42 { x < 7 => (), - //~^ error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` + //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` _ => () } } diff --git a/tests/ui/parser/pat-lt-bracket-1.stderr b/tests/ui/parser/pat-lt-bracket-1.stderr index f39487052ad..14e679bbee0 100644 --- a/tests/ui/parser/pat-lt-bracket-1.stderr +++ b/tests/ui/parser/pat-lt-bracket-1.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` +error: expected one of `=>`, `@`, `if`, or `|`, found `<` --> $DIR/pat-lt-bracket-1.rs:3:7 | LL | x < 7 => (), - | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` + | ^ expected one of `=>`, `@`, `if`, or `|` error: aborting due to 1 previous error diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr index f0450aea49a..df83c103084 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr @@ -4,17 +4,5 @@ error: unknown lint: `test_unstable_lint` = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable = note: requested on the command line with `-D unknown-lints` -error: unknown lint: `test_unstable_lint` - | - = note: the `test_unstable_lint` lint is unstable - = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unknown lint: `test_unstable_lint` - | - = note: the `test_unstable_lint` lint is unstable - = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs index c6c60b12d83..29c6547abc1 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs @@ -3,7 +3,5 @@ #![deny(unknown_lints)] #![allow(test_unstable_lint)] //~^ ERROR unknown lint: `test_unstable_lint` -//~| ERROR unknown lint: `test_unstable_lint` -//~| ERROR unknown lint: `test_unstable_lint` fn main() {} diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr index 20a36b28dc6..0afe3d55c98 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr @@ -12,25 +12,5 @@ note: the lint level is defined here LL | #![deny(unknown_lints)] | ^^^^^^^^^^^^^ -error: unknown lint: `test_unstable_lint` - --> $DIR/deny-unstable-lint-inline.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unknown lint: `test_unstable_lint` - --> $DIR/deny-unstable-lint-inline.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr index a2deecf1caf..c133b880ebd 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr @@ -4,17 +4,5 @@ warning: unknown lint: `test_unstable_lint` = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable = note: requested on the command line with `-W unknown-lints` -warning: unknown lint: `test_unstable_lint` - | - = note: the `test_unstable_lint` lint is unstable - = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `test_unstable_lint` - | - = note: the `test_unstable_lint` lint is unstable - = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs index f4247e4569e..89db84e69f6 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs @@ -3,7 +3,5 @@ #![warn(unknown_lints)] #![allow(test_unstable_lint)] //~^ WARNING unknown lint: `test_unstable_lint` -//~| WARNING unknown lint: `test_unstable_lint` -//~| WARNING unknown lint: `test_unstable_lint` fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr index 12afb2e294a..48c83b49e29 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr @@ -12,25 +12,5 @@ note: the lint level is defined here LL | #![warn(unknown_lints)] | ^^^^^^^^^^^^^ -warning: unknown lint: `test_unstable_lint` - --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unknown lint: `test_unstable_lint` - --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 - | -LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `test_unstable_lint` lint is unstable - = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted |
