From 684e7a5461eda4dee03b9a12d908695ba2f9f27d Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 27 Mar 2023 11:12:47 +0000 Subject: [PATCH 01/10] llvm-wrapper: adapt for LLVM API change Adapts the wrapper for the LLVM commit https://github.com/llvm/llvm-project/commit/377e1311d50c7e5b5aab3db081938e0d0ceebdfc. --- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index e604e44a7157b..f2dec8fe3273e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1158,13 +1158,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // Otherwise, we sometimes lose `static` values -- see #60184. computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing, /* ImportEnabled = */ false); - ComputeCrossModuleImport( - Ret->Index, - Ret->ModuleToDefinedGVSummaries, - Ret->ImportLists, - Ret->ExportLists - ); - // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it // impacts the caching. // @@ -1181,6 +1174,16 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, return true; return Prevailing->second == S; }; + ComputeCrossModuleImport( + Ret->Index, + Ret->ModuleToDefinedGVSummaries, +#if LLVM_VERSION_GE(17, 0) + isPrevailing, +#endif + Ret->ImportLists, + Ret->ExportLists + ); + auto recordNewLinkage = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID, GlobalValue::LinkageTypes NewLinkage) { From 1b3fda4978b691b2601ed862efae2798a82ef957 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 27 Mar 2023 14:42:56 +0200 Subject: [PATCH 02/10] Use span of placeholders in format_args!() expansion. --- compiler/rustc_ast_lowering/src/format.rs | 66 +++++++++++++++-------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 72352b138cbf4..c41bdc440935c 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -2,7 +2,7 @@ use super::LoweringContext; use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_ast::*; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_span::{ sym, @@ -238,7 +238,7 @@ fn make_count<'hir>( ctx: &mut LoweringContext<'_, 'hir>, sp: Span, count: &Option, - argmap: &mut FxIndexSet<(usize, ArgumentType)>, + argmap: &mut FxIndexMap<(usize, ArgumentType), Option>, ) -> hir::Expr<'hir> { match count { Some(FormatCount::Literal(n)) => { @@ -252,7 +252,7 @@ fn make_count<'hir>( } Some(FormatCount::Argument(arg)) => { if let Ok(arg_index) = arg.index { - let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize)); + let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize), arg.span); let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative( sp, hir::LangItem::FormatCount, @@ -291,12 +291,14 @@ fn make_format_spec<'hir>( ctx: &mut LoweringContext<'_, 'hir>, sp: Span, placeholder: &FormatPlaceholder, - argmap: &mut FxIndexSet<(usize, ArgumentType)>, + argmap: &mut FxIndexMap<(usize, ArgumentType), Option>, ) -> hir::Expr<'hir> { let position = match placeholder.argument.index { Ok(arg_index) => { - let (i, _) = - argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait))); + let (i, _) = argmap.insert_full( + (arg_index, ArgumentType::Format(placeholder.format_trait)), + placeholder.span, + ); ctx.expr_usize(sp, i) } Err(_) => ctx.expr( @@ -386,7 +388,7 @@ fn expand_format_args<'hir>( // Create a list of all _unique_ (argument, format trait) combinations. // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)] - let mut argmap = FxIndexSet::default(); + let mut argmap = FxIndexMap::default(); for piece in &fmt.template { let FormatArgsPiece::Placeholder(placeholder) = piece else { continue }; if placeholder.format_options != Default::default() { @@ -394,7 +396,10 @@ fn expand_format_args<'hir>( use_format_options = true; } if let Ok(index) = placeholder.argument.index { - if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) { + if argmap + .insert((index, ArgumentType::Format(placeholder.format_trait)), placeholder.span) + .is_some() + { // Duplicate (argument, format trait) combination, // which we'll only put once in the args array. use_format_options = true; @@ -438,7 +443,7 @@ fn expand_format_args<'hir>( // This is an optimization, speeding up compilation about 1-2% in some cases. // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609 let use_simple_array = argmap.len() == arguments.len() - && argmap.iter().enumerate().all(|(i, &(j, _))| i == j) + && argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j) && arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr)); let args = if use_simple_array { @@ -452,14 +457,19 @@ fn expand_format_args<'hir>( let elements: Vec<_> = arguments .iter() .zip(argmap) - .map(|(arg, (_, ty))| { - let sp = arg.expr.span.with_ctxt(macsp.ctxt()); + .map(|(arg, ((_, ty), placeholder_span))| { + let placeholder_span = + placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt()); + let arg_span = match arg.kind { + FormatArgumentKind::Captured(_) => placeholder_span, + _ => arg.expr.span.with_ctxt(macsp.ctxt()), + }; let arg = ctx.lower_expr(&arg.expr); let ref_arg = ctx.arena.alloc(ctx.expr( - sp, + arg_span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg), )); - make_argument(ctx, sp, ref_arg, ty) + make_argument(ctx, placeholder_span, ref_arg, ty) }) .collect(); ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) @@ -475,16 +485,26 @@ fn expand_format_args<'hir>( // } let args_ident = Ident::new(sym::args, macsp); let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); - let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| { - let arg = &arguments[arg_index]; - let sp = arg.expr.span.with_ctxt(macsp.ctxt()); - let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id); - let arg = ctx.arena.alloc(ctx.expr( - sp, - hir::ExprKind::Field(args_ident_expr, Ident::new(sym::integer(arg_index), macsp)), - )); - make_argument(ctx, sp, arg, ty) - })); + let args = ctx.arena.alloc_from_iter(argmap.iter().map( + |(&(arg_index, ty), &placeholder_span)| { + let arg = &arguments[arg_index]; + let placeholder_span = + placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt()); + let arg_span = match arg.kind { + FormatArgumentKind::Captured(_) => placeholder_span, + _ => arg.expr.span.with_ctxt(macsp.ctxt()), + }; + let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id); + let arg = ctx.arena.alloc(ctx.expr( + arg_span, + hir::ExprKind::Field( + args_ident_expr, + Ident::new(sym::integer(arg_index), macsp), + ), + )); + make_argument(ctx, placeholder_span, arg, ty) + }, + )); let elements: Vec<_> = arguments .iter() .map(|arg| { From 7f395f1effa518708b6b6e30429ba799cf4ba6f6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 27 Mar 2023 14:43:17 +0200 Subject: [PATCH 03/10] Bless UI tests. --- tests/ui/consts/const-eval/format.stderr | 8 ++++---- tests/ui/fmt/ifmt-bad-arg.stderr | 14 ++++++-------- tests/ui/fmt/ifmt-unimpl.stderr | 4 +++- tests/ui/suggestions/issue-97760.stderr | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr index c39920d444def..70a1abb0a9555 100644 --- a/tests/ui/consts/const-eval/format.stderr +++ b/tests/ui/consts/const-eval/format.stderr @@ -1,8 +1,8 @@ error[E0015]: cannot call non-const formatting macro in constant functions - --> $DIR/format.rs:2:20 + --> $DIR/format.rs:2:13 | LL | panic!("{:?}", 0); - | ^ + | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -17,10 +17,10 @@ LL | panic!("{:?}", 0); = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const formatting macro in constant functions - --> $DIR/format.rs:8:22 + --> $DIR/format.rs:8:15 | LL | println!("{:?}", 0); - | ^ + | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/fmt/ifmt-bad-arg.stderr b/tests/ui/fmt/ifmt-bad-arg.stderr index d716bbe51affc..bf18fb315c94d 100644 --- a/tests/ui/fmt/ifmt-bad-arg.stderr +++ b/tests/ui/fmt/ifmt-bad-arg.stderr @@ -300,10 +300,9 @@ error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:78:32 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^^ - | | - | expected `&usize`, found `&{float}` - | arguments to this function are incorrect + | -- ^^^ expected `&usize`, found `&{float}` + | | + | arguments to this function are incorrect | = note: expected reference `&usize` found reference `&{float}` @@ -315,10 +314,9 @@ error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:81:35 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^^ - | | - | expected `&usize`, found `&{float}` - | arguments to this function are incorrect + | -- ^^^ expected `&usize`, found `&{float}` + | | + | arguments to this function are incorrect | = note: expected reference `&usize` found reference `&{float}` diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index 3480a2ec81548..dc2dee3f3415c 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied --> $DIR/ifmt-unimpl.rs:2:21 | LL | format!("{:X}", "3"); - | ^^^ the trait `UpperHex` is not implemented for `str` + | ---- ^^^ the trait `UpperHex` is not implemented for `str` + | | + | required by a bound introduced by this call | = help: the following other types implement trait `UpperHex`: &T diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr index bbcc3693fff5a..5415c247c8fff 100644 --- a/tests/ui/suggestions/issue-97760.stderr +++ b/tests/ui/suggestions/issue-97760.stderr @@ -1,8 +1,8 @@ error[E0277]: `::Item` doesn't implement `std::fmt::Display` - --> $DIR/issue-97760.rs:4:20 + --> $DIR/issue-97760.rs:4:19 | LL | println!("{x}"); - | ^ `::Item` cannot be formatted with the default formatter + | ^^^ `::Item` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `::Item` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead From 769886cc35ce08b76839f4cf72b8af1161c432e1 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 27 Mar 2023 14:56:15 +0200 Subject: [PATCH 04/10] Bless mir-opt tests. (Only the lifetime spans changed.) --- ...mes.foo.ScalarReplacementOfAggregates.diff | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index 225f80ed41b47..f6f2344e82fac 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -19,12 +19,12 @@ let mut _17: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _18: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let _19: [core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 - let mut _21: &std::boxed::Box; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 - let _22: &std::boxed::Box; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22 - let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 - let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 - let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26 + let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23 + let mut _21: &std::boxed::Box; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23 + let _22: &std::boxed::Box; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23 + let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27 + let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27 + let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27 let mut _27: bool; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 let mut _28: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 let mut _29: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2 @@ -108,34 +108,34 @@ StorageLive(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_20); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - StorageLive(_21); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - _22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - _21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - _20 = core::fmt::ArgumentV1::<'_>::new_display::>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 + StorageLive(_20); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + StorageLive(_21); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + _22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + _21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + _20 = core::fmt::ArgumentV1::<'_>::new_display::>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 // mir::Constant - // + span: $DIR/lifetimes.rs:27:21: 27:22 + // + span: $DIR/lifetimes.rs:27:20: 27:23 // + user_ty: UserType(4) // + literal: Const { ty: for<'b> fn(&'b Box) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::>}, val: Value() } } bb3: { - StorageDead(_21); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22 - StorageLive(_23); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 - StorageLive(_24); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 - StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 - _25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 - _24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 - _23 = core::fmt::ArgumentV1::<'_>::new_display::(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + StorageDead(_21); // scope 4 at $DIR/lifetimes.rs:+10:22: +10:23 + StorageLive(_23); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + StorageLive(_24); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + _25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + _24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + _23 = core::fmt::ArgumentV1::<'_>::new_display::(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 // mir::Constant - // + span: $DIR/lifetimes.rs:27:25: 27:26 + // + span: $DIR/lifetimes.rs:27:24: 27:27 // + user_ty: UserType(5) // + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::}, val: Value() } } bb4: { - StorageDead(_24); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26 + StorageDead(_24); // scope 4 at $DIR/lifetimes.rs:+10:26: +10:27 _19 = [move _20, move _23]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_23); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL From 6c72a002a68043f9bc67399c43a66e8ab68ca20b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 27 Mar 2023 14:43:25 +0200 Subject: [PATCH 05/10] Add test for span of implicit format args captures. --- tests/ui/fmt/format-args-argument-span.rs | 22 ++++++++ tests/ui/fmt/format-args-argument-span.stderr | 51 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/ui/fmt/format-args-argument-span.rs create mode 100644 tests/ui/fmt/format-args-argument-span.stderr diff --git a/tests/ui/fmt/format-args-argument-span.rs b/tests/ui/fmt/format-args-argument-span.rs new file mode 100644 index 0000000000000..c7acb08f84b6c --- /dev/null +++ b/tests/ui/fmt/format-args-argument-span.rs @@ -0,0 +1,22 @@ +// check-compile + +struct DisplayOnly; + +impl std::fmt::Display for DisplayOnly { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + unimplemented!() + } +} + +fn main() { + let x = Some(1); + println!("{x:?} {x} {x:?}"); + //~^ ERROR: `Option<{integer}>` doesn't implement `std::fmt::Display` + println!("{x:?} {x} {x:?}", x = Some(1)); + //~^ ERROR: `Option<{integer}>` doesn't implement `std::fmt::Display` + let x = DisplayOnly; + println!("{x} {x:?} {x}"); + //~^ ERROR: `DisplayOnly` doesn't implement `Debug` + println!("{x} {x:?} {x}", x = DisplayOnly); + //~^ ERROR: `DisplayOnly` doesn't implement `Debug` +} diff --git a/tests/ui/fmt/format-args-argument-span.stderr b/tests/ui/fmt/format-args-argument-span.stderr new file mode 100644 index 0000000000000..b060b2cd33930 --- /dev/null +++ b/tests/ui/fmt/format-args-argument-span.stderr @@ -0,0 +1,51 @@ +error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display` + --> $DIR/format-args-argument-span.rs:13:21 + | +LL | println!("{x:?} {x} {x:?}"); + | ^^^ `Option<{integer}>` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display` + --> $DIR/format-args-argument-span.rs:15:37 + | +LL | println!("{x:?} {x} {x:?}", x = Some(1)); + | ^^^^^^^ `Option<{integer}>` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `DisplayOnly` doesn't implement `Debug` + --> $DIR/format-args-argument-span.rs:18:19 + | +LL | println!("{x} {x:?} {x}"); + | ^^^^^ `DisplayOnly` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `DisplayOnly` + = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `DisplayOnly` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error[E0277]: `DisplayOnly` doesn't implement `Debug` + --> $DIR/format-args-argument-span.rs:20:35 + | +LL | println!("{x} {x:?} {x}", x = DisplayOnly); + | ^^^^^^^^^^^ `DisplayOnly` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `DisplayOnly` + = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `DisplayOnly` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. From 52b15b4bf9f3a24b44017fe4b1c114a6d91f1e88 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Mar 2023 18:47:49 +0400 Subject: [PATCH 06/10] rustdoc: Unsupport importing `doc(primitive)` and `doc(keyword)` modules These are internal features used for a specific purpose, and modules without imports are enough for that purpose. --- src/librustdoc/clean/types.rs | 17 ----------------- tests/rustdoc/issue-15318-2.rs | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9019a6c49ecc5..93c2b5e069c4c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -232,14 +232,6 @@ impl ExternalCrate { hir::ItemKind::Mod(_) => { as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } - hir::ItemKind::Use(path, hir::UseKind::Single) - if tcx.visibility(id.owner_id).is_public() => - { - path.res - .iter() - .find_map(|res| as_keyword(res.expect_non_local())) - .map(|(_, prim)| (id.owner_id.to_def_id(), prim)) - } _ => None, } }) @@ -302,15 +294,6 @@ impl ExternalCrate { hir::ItemKind::Mod(_) => { as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } - hir::ItemKind::Use(path, hir::UseKind::Single) - if tcx.visibility(id.owner_id).is_public() => - { - path.res - .iter() - .find_map(|res| as_primitive(res.expect_non_local())) - // Pretend the primitive is local. - .map(|(_, prim)| (id.owner_id.to_def_id(), prim)) - } _ => None, } }) diff --git a/tests/rustdoc/issue-15318-2.rs b/tests/rustdoc/issue-15318-2.rs index f7f5052a36dd3..614f2c1c08e87 100644 --- a/tests/rustdoc/issue-15318-2.rs +++ b/tests/rustdoc/issue-15318-2.rs @@ -6,7 +6,7 @@ extern crate issue_15318; pub use issue_15318::ptr; -// @has issue_15318_2/fn.bar.html \ +// @!has issue_15318_2/fn.bar.html \ // '//*[@href="primitive.pointer.html"]' \ // '*mut T' pub fn bar(ptr: *mut T) {} From be9fd75d32f9af0ebed5aad348891603f2e17ac2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Feb 2023 04:43:15 +0000 Subject: [PATCH 07/10] rustdoc + rustdoc-json support for non_lifetime_binders --- src/librustdoc/clean/mod.rs | 17 ++--------- src/librustdoc/clean/simplify.rs | 6 +--- src/librustdoc/clean/types.rs | 8 ++--- src/librustdoc/html/format.rs | 4 +-- src/librustdoc/json/conversions.rs | 34 +++++++++++++++++++--- tests/rustdoc-json/non_lifetime_binders.rs | 24 +++++++++++++++ tests/rustdoc/non_lifetime_binders.rs | 9 ++++++ 7 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 tests/rustdoc-json/non_lifetime_binders.rs create mode 100644 tests/rustdoc/non_lifetime_binders.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5f5521caf68b9..2d247bd537bdf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -31,7 +31,6 @@ use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; -use std::assert_matches::assert_matches; use std::borrow::Cow; use std::collections::hash_map::Entry; use std::collections::BTreeMap; @@ -270,15 +269,7 @@ fn clean_where_predicate<'tcx>( let bound_params = wbp .bound_generic_params .iter() - .map(|param| { - // Higher-ranked params must be lifetimes. - // Higher-ranked lifetimes can't have bounds. - assert_matches!( - param, - hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. } - ); - Lifetime(param.name.ident().name) - }) + .map(|param| clean_generic_param(cx, None, param)) .collect(); WherePredicate::BoundPredicate { ty: clean_ty(wbp.bounded_ty, cx), @@ -410,7 +401,7 @@ fn clean_projection_predicate<'tcx>( .collect_referenced_late_bound_regions(&pred) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)), + ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)), _ => None, }) .collect(); @@ -508,7 +499,6 @@ fn clean_generic_param_def<'tcx>( ty::GenericParamDefKind::Const { has_default } => ( def.name, GenericParamDefKind::Const { - did: def.def_id, ty: Box::new(clean_middle_ty( ty::Binder::dummy( cx.tcx @@ -578,7 +568,6 @@ fn clean_generic_param<'tcx>( hir::GenericParamKind::Const { ty, default } => ( param.name.ident().name, GenericParamDefKind::Const { - did: param.def_id.to_def_id(), ty: Box::new(clean_ty(ty, cx)), default: default .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())), @@ -831,7 +820,7 @@ fn clean_ty_generics<'tcx>( p.get_bound_params() .into_iter() .flatten() - .map(|param| GenericParamDef::lifetime(param.0)) + .cloned() .collect(), )); } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index dbbc25739aa07..3c72b0bf9f2f6 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -49,11 +49,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec, bound_params: Vec }, + BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: Box, rhs: Box, bound_params: Vec }, + EqPredicate { lhs: Box, rhs: Box, bound_params: Vec }, } impl WherePredicate { @@ -1250,7 +1250,7 @@ impl WherePredicate { } } - pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> { + pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> { match self { Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => { Some(bound_params) @@ -1264,7 +1264,7 @@ impl WherePredicate { pub(crate) enum GenericParamDefKind { Lifetime { outlives: Vec }, Type { did: DefId, bounds: Vec, default: Option>, synthetic: bool }, - Const { did: DefId, ty: Box, default: Option> }, + Const { ty: Box, default: Option> }, } impl GenericParamDefKind { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f2b9c0bcf3ee7..0895bb510d481 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -307,13 +307,13 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( write!( f, "for<{:#}> {ty_cx:#}: {generic_bounds:#}", - comma_sep(bound_params.iter().map(|lt| lt.print()), true) + comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true) ) } else { write!( f, "for<{}> {ty_cx}: {generic_bounds}", - comma_sep(bound_params.iter().map(|lt| lt.print()), true) + comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true) ) } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 18c45fd699155..59d67f27b3006 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -456,7 +456,7 @@ impl FromWithTcx for GenericParamDefKind { default: default.map(|x| (*x).into_tcx(tcx)), synthetic, }, - Const { did: _, ty, default } => GenericParamDefKind::Const { + Const { ty, default } => GenericParamDefKind::Const { type_: (*ty).into_tcx(tcx), default: default.map(|x| *x), }, @@ -473,9 +473,35 @@ impl FromWithTcx for WherePredicate { bounds: bounds.into_tcx(tcx), generic_params: bound_params .into_iter() - .map(|x| GenericParamDef { - name: x.0.to_string(), - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, + .map(|x| { + let name = x.name.to_string(); + let kind = match x.kind { + clean::GenericParamDefKind::Lifetime { outlives } => { + GenericParamDefKind::Lifetime { + outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(), + } + } + clean::GenericParamDefKind::Type { + did: _, + bounds, + default, + synthetic, + } => GenericParamDefKind::Type { + bounds: bounds + .into_iter() + .map(|bound| bound.into_tcx(tcx)) + .collect(), + default: default.map(|ty| (*ty).into_tcx(tcx)), + synthetic, + }, + clean::GenericParamDefKind::Const { ty, default } => { + GenericParamDefKind::Const { + type_: (*ty).into_tcx(tcx), + default: default.map(|d| *d), + } + } + }; + GenericParamDef { name, kind } }) .collect(), }, diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs new file mode 100644 index 0000000000000..ca5a008344af2 --- /dev/null +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -0,0 +1,24 @@ +// ignore-tidy-linelength + +#![feature(non_lifetime_binders)] +#![allow(incomplete_features)] + +#![no_core] +#![feature(lang_items, no_core)] + +#[lang = "sized"] +pub trait Sized {} + +pub trait Trait {} + +#[lang = "phantom_data"] +struct PhantomData; + +pub struct Wrapper(PhantomData); + +// @count "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 +// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" +// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\" +// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }' +pub fn foo() where for<'a, T> &'a Wrapper: Trait {} diff --git a/tests/rustdoc/non_lifetime_binders.rs b/tests/rustdoc/non_lifetime_binders.rs new file mode 100644 index 0000000000000..da9a4e6a84d5a --- /dev/null +++ b/tests/rustdoc/non_lifetime_binders.rs @@ -0,0 +1,9 @@ +#![feature(non_lifetime_binders)] +#![allow(incomplete_features)] + +pub trait Trait {} + +pub struct Wrapper(Box); + +// @has non_lifetime_binders/fn.foo.html '//pre' "fn foo()where for<'a, T> &'a Wrapper: Trait" +pub fn foo() where for<'a, T> &'a Wrapper: Trait {} From ef5f773bffdc2fb28bc833fa6132cbdade1dc549 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Mar 2023 21:48:43 +0000 Subject: [PATCH 08/10] Check for overflow in assemble_candidates_after_normalizing_self_ty --- .../src/solve/assembly.rs | 50 ++++++++++++------- .../src/solve/search_graph/overflow.rs | 21 ++++++++ .../recursive-self-normalization-2.rs | 19 +++++++ .../recursive-self-normalization-2.stderr | 9 ++++ .../recursive-self-normalization.rs | 15 ++++++ .../recursive-self-normalization.stderr | 9 ++++ 6 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.rs create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.stderr create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.rs create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 4fb77d795189d..0f7a0eb337ba6 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -1,5 +1,6 @@ //! Code shared by trait and projection goals for candidate assembly. +use super::search_graph::OverflowHandler; #[cfg(doc)] use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; @@ -279,25 +280,38 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { return }; - self.probe(|ecx| { - let normalized_ty = ecx.next_ty_infer(); - let normalizes_to_goal = goal.with( - tcx, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty, - term: normalized_ty.into(), - }), - ); - ecx.add_goal(normalizes_to_goal); - if let Ok(_) = ecx.try_evaluate_added_goals() { - let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty); - - // NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate. - // This doesn't work as long as we use `CandidateSource` in winnowing. - let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); - candidates.extend(ecx.assemble_and_evaluate_candidates(goal)); - } + let normalized_self_candidates: Result<_, NoSolution> = self.probe(|ecx| { + ecx.with_incremented_depth( + |ecx| { + let result = ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::Maybe(MaybeCause::Overflow), + )?; + Ok(vec![Candidate { source: CandidateSource::BuiltinImpl, result }]) + }, + |ecx| { + let normalized_ty = ecx.next_ty_infer(); + let normalizes_to_goal = goal.with( + tcx, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty, + term: normalized_ty.into(), + }), + ); + ecx.add_goal(normalizes_to_goal); + let _ = ecx.try_evaluate_added_goals()?; + let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty); + // NOTE: Alternatively we could call `evaluate_goal` here and only + // have a `Normalized` candidate. This doesn't work as long as we + // use `CandidateSource` in winnowing. + let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); + Ok(ecx.assemble_and_evaluate_candidates(goal)) + }, + ) }); + + if let Ok(normalized_self_candidates) = normalized_self_candidates { + candidates.extend(normalized_self_candidates); + } } fn assemble_impl_candidates>( diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs index 7c9e63f529b55..574f3e9a5772d 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs @@ -73,6 +73,27 @@ pub(in crate::solve) trait OverflowHandler<'tcx> { self.search_graph().overflow_data.deal_with_overflow(); on_overflow(self) } + + // Increment the `additional_depth` by one and evaluate `body`, or `on_overflow` + // if the depth is overflown. + fn with_incremented_depth( + &mut self, + on_overflow: impl FnOnce(&mut Self) -> T, + body: impl FnOnce(&mut Self) -> T, + ) -> T { + let depth = self.search_graph().stack.len(); + self.search_graph().overflow_data.additional_depth += 1; + + let result = if self.search_graph().overflow_data.has_overflow(depth) { + self.search_graph().overflow_data.deal_with_overflow(); + on_overflow(self) + } else { + body(self) + }; + + self.search_graph().overflow_data.additional_depth -= 1; + result + } } impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx> { diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs new file mode 100644 index 0000000000000..7417d6018a131 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs @@ -0,0 +1,19 @@ +// compile-flags: -Ztrait-solver=next + +trait Foo1 { + type Assoc1; +} + +trait Foo2 { + type Assoc2; +} + +trait Bar {} +fn needs_bar() {} + +fn test::Assoc2> + Foo2::Assoc1>>() { + needs_bar::(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr new file mode 100644 index 0000000000000..29cfa47a1050a --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/recursive-self-normalization-2.rs:15:5 + | +LL | needs_bar::(); + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/recursive-self-normalization.rs new file mode 100644 index 0000000000000..f3e3d71d813e4 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next + +trait Foo { + type Assoc; +} + +trait Bar {} +fn needs_bar() {} + +fn test::Assoc>>() { + needs_bar::(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/recursive-self-normalization.stderr new file mode 100644 index 0000000000000..ba39981893d44 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/recursive-self-normalization.rs:11:5 + | +LL | needs_bar::(); + | ^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From c5da0619d102493ce39bc36554e14191e964c1b4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 28 Mar 2023 20:21:23 -0700 Subject: [PATCH 09/10] Fix mismatched punctuation in Debug impl of AttrId --- compiler/rustc_ast/src/ast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ab8b7f632e8ef..cc0fc7b8358fb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2570,7 +2570,7 @@ pub enum AttrStyle { rustc_index::newtype_index! { #[custom_encodable] - #[debug_format = "AttrId({})]"] + #[debug_format = "AttrId({})"] pub struct AttrId {} } From 843c5e361e1b392f89f71ac26a951f8dfd84e43a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 29 Mar 2023 00:04:14 -0700 Subject: [PATCH 10/10] =?UTF-8?q?Rename=20`IndexVec::last`=20=E2=86=92=20`?= =?UTF-8?q?last=5Findex`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As I've been trying to replace a `Vec` with an `IndexVec`, having `last` exist on both but returning very different types makes the transition a bit awkward -- the errors are later, where you get things like "there's no `ty` method on `mir::Field`" rather than a more localized error like "hey, there's no `last` on `IndexVec`". So I propose renaming `last` to `last_index` to help distinguish `Vec::last`, which returns an element, and `IndexVec::last_index`, which returns an index. (Similarly, `Iterator::last` also returns an element, not an index.) --- compiler/rustc_const_eval/src/transform/promote_consts.rs | 4 ++-- compiler/rustc_index/src/vec.rs | 2 +- compiler/rustc_mir_transform/src/coverage/tests.rs | 2 +- compiler/rustc_trait_selection/src/solve/search_graph/mod.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 648a86d32fcf3..40c848de2beed 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -707,7 +707,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { - let last = self.promoted.basic_blocks.last().unwrap(); + let last = self.promoted.basic_blocks.last_index().unwrap(); let data = &mut self.promoted[last]; data.statements.push(Statement { source_info: SourceInfo::outermost(span), @@ -800,7 +800,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.visit_operand(arg, loc); } - let last = self.promoted.basic_blocks.last().unwrap(); + let last = self.promoted.basic_blocks.last_index().unwrap(); let new_target = self.new_block(); *self.promoted[last].terminator_mut() = Terminator { diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 68cdc6d7711d4..acf883fe90cec 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -216,7 +216,7 @@ impl IndexVec { } #[inline] - pub fn last(&self) -> Option { + pub fn last_index(&self) -> Option { self.len().checked_sub(1).map(I::new) } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index aded8039dc313..59b506e734553 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -65,7 +65,7 @@ impl<'tcx> MockBlocks<'tcx> { } fn push(&mut self, kind: TerminatorKind<'tcx>) -> BasicBlock { - let next_lo = if let Some(last) = self.blocks.last() { + let next_lo = if let Some(last) = self.blocks.last_index() { self.blocks[last].terminator().source_info.span.hi() } else { BytePos(1) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 9773a3eacd6fa..717905e55e573 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -54,7 +54,7 @@ impl<'tcx> SearchGraph<'tcx> { /// Whether we're currently in a cycle. This should only be used /// for debug assertions. pub(super) fn in_cycle(&self) -> bool { - if let Some(stack_depth) = self.stack.last() { + if let Some(stack_depth) = self.stack.last_index() { // Either the current goal on the stack is the root of a cycle... if self.stack[stack_depth].has_been_used { return true;