From b899251f2dfe3a9849f844418e0d11e2073c2423 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 2 Apr 2022 14:22:35 -0700 Subject: [PATCH 01/16] Fix late-bound ICE in unsized return suggestion --- .../src/traits/error_reporting/suggestions.rs | 134 +++++++++++------- ...n-trait-return-should-be-impl-trait.stderr | 30 ++-- ...type-err-cause-on-impl-trait-return.stderr | 49 ++++--- src/test/ui/issues/issue-18107.stderr | 2 +- src/test/ui/unsized/box-instead-of-dyn-fn.rs | 15 ++ .../ui/unsized/box-instead-of-dyn-fn.stderr | 39 +++++ src/test/ui/unsized/issue-91801.rs | 19 +++ src/test/ui/unsized/issue-91801.stderr | 15 ++ src/test/ui/unsized/issue-91803.rs | 8 ++ src/test/ui/unsized/issue-91803.stderr | 15 ++ 10 files changed, 242 insertions(+), 84 deletions(-) create mode 100644 src/test/ui/unsized/box-instead-of-dyn-fn.rs create mode 100644 src/test/ui/unsized/box-instead-of-dyn-fn.stderr create mode 100644 src/test/ui/unsized/issue-91801.rs create mode 100644 src/test/ui/unsized/issue-91801.stderr create mode 100644 src/test/ui/unsized/issue-91803.rs create mode 100644 src/test/ui/unsized/issue-91803.stderr 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 b49a5f6578f75..ac17b0d68657e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1045,8 +1045,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let hir = self.tcx.hir(); - let parent_node = hir.get_parent_node(obligation.cause.body_id); - let node = hir.find(parent_node); + let fn_hir_id = hir.get_parent_node(obligation.cause.body_id); + let node = hir.find(fn_hir_id); let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. @@ -1084,16 +1084,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { visitor.visit_body(&body); let typeck_results = self.in_progress_typeck_results.map(|t| t.borrow()).unwrap(); + let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id) else { return false; }; - let mut ret_types = visitor + let ret_types = visitor .returns .iter() - .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id)) - .map(|ty| self.resolve_vars_if_possible(ty)); + .filter_map(|expr| Some((expr.span, typeck_results.node_type_opt(expr.hir_id)?))) + .map(|(expr_span, ty)| (expr_span, self.resolve_vars_if_possible(ty))); let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold( (None, true, true), |(last_ty, mut same, only_never_return): (std::option::Option>, bool, bool), - ty| { + (_, ty)| { let ty = self.resolve_vars_if_possible(ty); same &= !matches!(ty.kind(), ty::Error(_)) @@ -1114,39 +1115,60 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { (Some(ty), same, only_never_return && matches!(ty.kind(), ty::Never)) }, ); - let all_returns_conform_to_trait = - if let Some(ty_ret_ty) = typeck_results.node_type_opt(ret_ty.hir_id) { - match ty_ret_ty.kind() { - ty::Dynamic(predicates, _) => { - let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id); - let param_env = ty::ParamEnv::empty(); - only_never_return - || ret_types.all(|returned_ty| { - predicates.iter().all(|predicate| { - let pred = predicate.with_self_ty(self.tcx, returned_ty); - let obl = Obligation::new(cause.clone(), param_env, pred); - self.predicate_may_hold(&obl) - }) + let mut spans_and_needs_box = vec![]; + + match liberated_sig.output().kind() { + ty::Dynamic(predicates, _) => { + let cause = ObligationCause::misc(ret_ty.span, fn_hir_id); + let param_env = ty::ParamEnv::empty(); + + if !only_never_return { + for (expr_span, return_ty) in ret_types { + let self_ty_satisfies_dyn_predicates = |self_ty| { + predicates.iter().all(|predicate| { + let pred = predicate.with_self_ty(self.tcx, self_ty); + let obl = Obligation::new(cause.clone(), param_env, pred); + self.predicate_may_hold(&obl) }) + }; + + if let ty::Adt(def, substs) = return_ty.kind() + && def.is_box() + && self_ty_satisfies_dyn_predicates(substs.type_at(0)) + { + spans_and_needs_box.push((expr_span, false)); + } else if self_ty_satisfies_dyn_predicates(return_ty) { + spans_and_needs_box.push((expr_span, true)); + } else { + return false; + } } - _ => false, } - } else { - true - }; + } + _ => return false, + }; let sm = self.tcx.sess.source_map(); - let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = ( - // Verify that we're dealing with a return `dyn Trait` - ret_ty.span.overlaps(span), - &ret_ty.kind, - sm.span_to_snippet(ret_ty.span), - // If any of the return types does not conform to the trait, then we can't - // suggest `impl Trait` nor trait objects: it is a type mismatch error. - all_returns_conform_to_trait, - ) else { + if !ret_ty.span.overlaps(span) { return false; + } + let snippet = if let hir::TyKind::TraitObject(..) = ret_ty.kind { + if let Ok(snippet) = sm.span_to_snippet(ret_ty.span) { + snippet + } else { + return false; + } + } else { + // Substitute the type, so we can print a fixup given `type Alias = dyn Trait` + let name = liberated_sig.output().to_string(); + let name = + name.strip_prefix('(').and_then(|name| name.strip_suffix(')')).unwrap_or(&name); + if !name.starts_with("dyn ") { + return false; + } + name.to_owned() }; + err.code(error_code!(E0746)); err.set_primary_message("return type cannot have an unboxed trait object"); err.children.clear(); @@ -1156,6 +1178,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let trait_obj_msg = "for information on trait objects, see \ "; + let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn"); let trait_obj = if has_dyn { &snippet[4..] } else { &snippet }; if only_never_return { @@ -1183,26 +1206,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else { if is_object_safe { // Suggest `-> Box` and `Box::new(returned_value)`. - // Get all the return values and collect their span and suggestion. - let mut suggestions: Vec<_> = visitor - .returns - .iter() - .flat_map(|expr| { - [ - (expr.span.shrink_to_lo(), "Box::new(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ] - .into_iter() - }) - .collect(); - if !suggestions.is_empty() { - // Add the suggestion for the return type. - suggestions.push((ret_ty.span, format!("Box", trait_obj))); - err.multipart_suggestion( - "return a boxed trait object instead", - suggestions, - Applicability::MaybeIncorrect, - ); + err.multipart_suggestion( + "return a boxed trait object instead", + vec![ + (ret_ty.span.shrink_to_lo(), "Box<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MaybeIncorrect, + ); + for (span, needs_box) in spans_and_needs_box { + if needs_box { + err.multipart_suggestion( + "... and box this value", + vec![ + (span.shrink_to_lo(), "Box::new(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } } } else { // This is currently not possible to trigger because E0038 takes precedence, but @@ -2677,13 +2699,15 @@ fn suggest_trait_object_return_type_alternatives( Applicability::MaybeIncorrect, ); if is_object_safe { - err.span_suggestion( - ret_ty, + err.multipart_suggestion( &format!( "use a boxed trait object if all return paths implement trait `{}`", trait_obj, ), - format!("Box", trait_obj), + vec![ + (ret_ty.shrink_to_lo(), "Box<".to_string()), + (ret_ty.shrink_to_hi(), ">".to_string()), + ], Applicability::MaybeIncorrect, ); } diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 0d4f82bfc153f..f90399b6b9458 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -81,7 +81,7 @@ LL | fn bak() -> impl Trait { unimplemented!() } help: use a boxed trait object if all return paths implement trait `Trait` | LL | fn bak() -> Box { unimplemented!() } - | ~~~~~~~~~~~~~~ + | ++++ + error[E0746]: return type cannot have an unboxed trait object --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 @@ -95,12 +95,16 @@ LL | fn bal() -> dyn Trait { = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn bal() -> Box { -LL | if true { -LL ~ return Box::new(Struct); -LL | } -LL ~ Box::new(42) +LL | fn bal() -> Box { + | ++++ + +help: ... and box this value + | +LL | return Box::new(Struct); + | +++++++++ + +help: ... and box this value | +LL | Box::new(42) + | +++++++++ + error[E0308]: `if` and `else` have incompatible types --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9 @@ -126,12 +130,16 @@ LL | fn bax() -> dyn Trait { = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn bax() -> Box { -LL | if true { -LL ~ Box::new(Struct) -LL | } else { -LL ~ Box::new(42) +LL | fn bax() -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(Struct) + | +++++++++ + +help: ... and box this value | +LL | Box::new(42) + | +++++++++ + error[E0308]: mismatched types --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16 diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 0c595f441ba8e..10510c1754eda 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -103,13 +103,16 @@ LL | fn hat() -> dyn std::fmt::Display { = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn hat() -> Box { -LL | match 13 { -LL | 0 => { -LL ~ return Box::new(0i32); -LL | } -LL | _ => { - ... +LL | fn hat() -> Box { + | ++++ + +help: ... and box this value + | +LL | return Box::new(0i32); + | +++++++++ + +help: ... and box this value + | +LL | Box::new(1u32) + | +++++++++ + error[E0308]: `match` arms have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14 @@ -135,12 +138,20 @@ LL | fn pug() -> dyn std::fmt::Display { = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn pug() -> Box { -LL | match 13 { -LL ~ 0 => Box::new(0i32), -LL ~ 1 => Box::new(1u32), -LL ~ _ => Box::new(2u32), +LL | fn pug() -> Box { + | ++++ + +help: ... and box this value + | +LL | 0 => Box::new(0i32), + | +++++++++ + +help: ... and box this value | +LL | 1 => Box::new(1u32), + | +++++++++ + +help: ... and box this value + | +LL | _ => Box::new(2u32), + | +++++++++ + error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9 @@ -166,12 +177,16 @@ LL | fn man() -> dyn std::fmt::Display { = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn man() -> Box { -LL | if false { -LL ~ Box::new(0i32) -LL | } else { -LL ~ Box::new(1u32) +LL | fn man() -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(0i32) + | +++++++++ + +help: ... and box this value | +LL | Box::new(1u32) + | +++++++++ + error: aborting due to 14 previous errors diff --git a/src/test/ui/issues/issue-18107.stderr b/src/test/ui/issues/issue-18107.stderr index 1eb6822b8a11a..28478457b296d 100644 --- a/src/test/ui/issues/issue-18107.stderr +++ b/src/test/ui/issues/issue-18107.stderr @@ -15,7 +15,7 @@ LL | impl AbstractRenderer help: use a boxed trait object if all return paths implement trait `AbstractRenderer` | LL | Box - | + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.rs b/src/test/ui/unsized/box-instead-of-dyn-fn.rs new file mode 100644 index 0000000000000..2fa741bc1c50b --- /dev/null +++ b/src/test/ui/unsized/box-instead-of-dyn-fn.rs @@ -0,0 +1,15 @@ +use std::fmt::Debug; + +// Test to suggest boxing the return type, and the closure branch of the `if` + +fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + //~^ ERROR return type cannot have an unboxed trait object + if a % 2 == 0 { + move || println!("{a}") + } else { + Box::new(move || println!("{}", b)) + //~^ ERROR `if` and `else` have incompatible types + } +} + +fn main() {} diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.stderr b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr new file mode 100644 index 0000000000000..80f61cb3eae11 --- /dev/null +++ b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr @@ -0,0 +1,39 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/box-instead-of-dyn-fn.rs:10:9 + | +LL | / if a % 2 == 0 { +LL | | move || println!("{a}") + | | ----------------------- expected because of this +LL | | } else { +LL | | Box::new(move || println!("{}", b)) + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box` +LL | | +LL | | } + | |_____- `if` and `else` have incompatible types + | + = note: expected type `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:32]` + found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:43]>` + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/box-instead-of-dyn-fn.rs:5:56 + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(move || println!("{a}")) + | +++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0746. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/unsized/issue-91801.rs b/src/test/ui/unsized/issue-91801.rs new file mode 100644 index 0000000000000..096b1a93574fc --- /dev/null +++ b/src/test/ui/unsized/issue-91801.rs @@ -0,0 +1,19 @@ +pub struct Something; + +type Validator<'a> = dyn 'a + Send + Sync + Fn(&'a Something) -> Result<(), ()>; + +pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] = + &[("validate that credits and debits balance", &validate_something)]; + +fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(move |something: &'_ Something| -> Result<(), ()> { + first(something).or_else(|_| second(something)) + }); +} + +fn validate_something(_: &Something) -> Result<(), ()> { + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/unsized/issue-91801.stderr b/src/test/ui/unsized/issue-91801.stderr new file mode 100644 index 0000000000000..e854514958629 --- /dev/null +++ b/src/test/ui/unsized/issue-91801.stderr @@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91801.rs:8:77 + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 12:6]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`. diff --git a/src/test/ui/unsized/issue-91803.rs b/src/test/ui/unsized/issue-91803.rs new file mode 100644 index 0000000000000..c74897cc4bc50 --- /dev/null +++ b/src/test/ui/unsized/issue-91803.rs @@ -0,0 +1,8 @@ +trait Foo<'a> {} + +fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(panic!()); +} + +fn main() {} diff --git a/src/test/ui/unsized/issue-91803.stderr b/src/test/ui/unsized/issue-91803.stderr new file mode 100644 index 0000000000000..2dad9e8929421 --- /dev/null +++ b/src/test/ui/unsized/issue-91803.stderr @@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91803.rs:3:43 + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>` + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`. From f0ec783bf94a4950f6b55cb91b043ec6ff0a4b03 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Apr 2022 13:05:49 -0400 Subject: [PATCH 02/16] interpret: remove MemoryExtra in favor of giving access to the Machine --- .../src/const_eval/eval_queries.rs | 8 +- .../src/const_eval/machine.rs | 23 +- .../rustc_const_eval/src/interpret/cast.rs | 8 +- .../src/interpret/eval_context.rs | 60 +---- .../src/interpret/intrinsics.rs | 16 +- .../rustc_const_eval/src/interpret/machine.rs | 45 ++-- .../rustc_const_eval/src/interpret/memory.rs | 207 +++++++++--------- .../rustc_const_eval/src/interpret/operand.rs | 4 +- .../rustc_const_eval/src/interpret/place.rs | 23 +- .../rustc_const_eval/src/interpret/step.rs | 4 +- .../src/interpret/terminator.rs | 2 +- .../rustc_const_eval/src/interpret/traits.rs | 18 +- .../src/interpret/validity.rs | 12 +- .../rustc_mir_transform/src/const_prop.rs | 5 +- .../src/const_prop_lint.rs | 5 +- 15 files changed, 194 insertions(+), 246 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 946546263ea72..b81a4bfe149dc 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,4 +1,4 @@ -use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra}; +use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, @@ -100,8 +100,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( tcx, root_span, param_env, - CompileTimeInterpreter::new(tcx.const_eval_limit()), - MemoryExtra { can_access_statics }, + CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics), ) } @@ -285,10 +284,9 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx, tcx.def_span(def.did), key.param_env, - CompileTimeInterpreter::new(tcx.const_eval_limit()), // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. - MemoryExtra { can_access_statics: is_static }, + CompileTimeInterpreter::new(tcx.const_eval_limit(), /*can_access_statics:*/ is_static), ); let res = ecx.load_mir(cid.instance.def, cid.promoted); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 2b58c1e8233c1..eea43c62ef0ca 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -93,10 +93,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// The virtual call stack. pub(crate) stack: Vec>, -} -#[derive(Copy, Clone, Debug)] -pub struct MemoryExtra { /// We need to make sure consts never point to anything mutable, even recursively. That is /// relied on for pattern matching on consts with references. /// To achieve this, two pieces have to work together: @@ -107,8 +104,12 @@ pub struct MemoryExtra { } impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { - pub(super) fn new(const_eval_limit: Limit) -> Self { - CompileTimeInterpreter { steps_remaining: const_eval_limit.0, stack: Vec::new() } + pub(super) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self { + CompileTimeInterpreter { + steps_remaining: const_eval_limit.0, + stack: Vec::new(), + can_access_statics, + } } } @@ -233,8 +234,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryKind = MemoryKind; - type MemoryExtra = MemoryExtra; - const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error fn load_mir( @@ -345,7 +344,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(err) => throw_ub_format!("align has to be a power of 2, {}", err), }; - let ptr = ecx.memory.allocate( + let ptr = ecx.allocate_ptr( Size::from_bytes(size as u64), align, interpret::MemoryKind::Machine(MemoryKind::Heap), @@ -365,14 +364,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // If an allocation is created in an another const, // we don't deallocate it. - let (alloc_id, _, _) = ecx.memory.ptr_get_alloc(ptr)?; + let (alloc_id, _, _) = ecx.ptr_get_alloc(ptr)?; let is_allocated_in_another_const = matches!( ecx.tcx.get_global_alloc(alloc_id), Some(interpret::GlobalAlloc::Memory(_)) ); if !is_allocated_in_another_const { - ecx.memory.deallocate( + ecx.deallocate_ptr( ptr, Some((size, align)), interpret::MemoryKind::Machine(MemoryKind::Heap), @@ -472,7 +471,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn before_access_global( - memory_extra: &MemoryExtra, + machine: &Self, alloc_id: AllocId, alloc: ConstAllocation<'tcx>, static_def_id: Option, @@ -488,7 +487,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } else { // Read access. These are usually allowed, with some exceptions. - if memory_extra.can_access_statics { + if machine.can_access_statics { // Machine configuration allows us read from anything (e.g., `static` initializer). Ok(()) } else if static_def_id.is_some() { diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 5be0a183cf6b4..a244b79ed0754 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -56,7 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) .ok_or_else(|| err_inval!(TooGeneric))?; - let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); + let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), @@ -87,7 +87,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { substs, ty::ClosureKind::FnOnce, ); - let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); + let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), @@ -153,8 +153,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(**src); } else { // Casting the metadata away from a fat ptr. - assert_eq!(src.layout.size, 2 * self.memory.pointer_size()); - assert_eq!(dest_layout.size, self.memory.pointer_size()); + assert_eq!(src.layout.size, 2 * self.pointer_size()); + assert_eq!(dest_layout.size, self.pointer_size()); assert!(src.layout.ty.is_unsafe_ptr()); return match **src { Immediate::ScalarPair(data, _) => Ok(data.into()), diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 1b8186b5aadba..a2ea0f516bfa4 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -22,9 +22,9 @@ use rustc_span::{Pos, Span}; use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocCheck, AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, - MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, - PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, StackPopJump, + AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, + MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance, + Scalar, ScalarMaybeUninit, StackPopJump, }; use crate::transform::validate::equal_up_to_regions; @@ -413,13 +413,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { root_span: Span, param_env: ty::ParamEnv<'tcx>, machine: M, - memory_extra: M::MemoryExtra, ) -> Self { InterpCx { machine, tcx: tcx.at(root_span), param_env, - memory: Memory::new(tcx, memory_extra), + memory: Memory::new(), recursion_limit: tcx.recursion_limit(), } } @@ -433,49 +432,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .map_or(self.tcx.span, |f| f.current_span()) } - #[inline(always)] - pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { - self.memory.scalar_to_ptr(scalar) - } - - /// Test if this value might be null. - /// If the machine does not support ptr-to-int casts, this is conservative. - pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { - match scalar.try_to_int() { - Ok(int) => int.is_null(), - Err(_) => { - // Can only happen during CTFE. - let ptr = self.scalar_to_ptr(scalar); - match self.memory.ptr_try_get_alloc(ptr) { - Ok((alloc_id, offset, _)) => { - let (size, _align) = self - .memory - .get_size_and_align(alloc_id, AllocCheck::MaybeDead) - .expect("alloc info with MaybeDead cannot fail"); - // If the pointer is out-of-bounds, it may be null. - // Note that one-past-the-end (offset == size) is still inbounds, and never null. - offset > size - } - Err(_offset) => bug!("a non-int scalar is always a pointer"), - } - } - } - } - - /// Call this to turn untagged "global" pointers (obtained via `tcx`) into - /// the machine pointer to the allocation. Must never be used - /// for any other pointers, nor for TLS statics. - /// - /// Using the resulting pointer represents a *direct* access to that memory - /// (e.g. by directly using a `static`), - /// as opposed to access through a pointer that was created by the program. - /// - /// This function can fail only if `ptr` points to an `extern static`. - #[inline(always)] - pub fn global_base_pointer(&self, ptr: Pointer) -> InterpResult<'tcx, Pointer> { - self.memory.global_base_pointer(ptr) - } - #[inline(always)] pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] { M::stack(self) @@ -949,9 +905,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!( "deallocating local {:?}: {:?}", local, - self.memory.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) + self.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) ); - self.memory.deallocate(ptr, None, MemoryKind::Stack)?; + self.deallocate_ptr(ptr, None, MemoryKind::Stack)?; }; Ok(()) } @@ -1057,7 +1013,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug } } - write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs)) + write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs)) } Place::Ptr(mplace) => match mplace.ptr.provenance.map(Provenance::get_alloc_id) { Some(alloc_id) => write!( @@ -1065,7 +1021,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug "by align({}) ref {:?}: {:?}", mplace.align.bytes(), mplace.ptr, - self.ecx.memory.dump_alloc(alloc_id) + self.ecx.dump_alloc(alloc_id) ), ptr => write!(fmt, " integral by ref: {:?}", ptr), }, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c80d7d7178742..3d70ad87cb44e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -318,7 +318,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // exception from the exception.) // This is the dual to the special exception for offset-by-0 // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below). - match (self.memory.ptr_try_get_alloc(a), self.memory.ptr_try_get_alloc(b)) { + match (self.ptr_try_get_alloc(a), self.ptr_try_get_alloc(b)) { (Err(a), Err(b)) if a == b && a != 0 => { // Both are the same non-null integer. self.write_scalar(Scalar::from_machine_isize(0, self), dest)?; @@ -335,13 +335,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } // And they must both be valid for zero-sized accesses ("in-bounds or one past the end"). - self.memory.check_ptr_access_align( + self.check_ptr_access_align( a, Size::ZERO, Align::ONE, CheckInAllocMsg::OffsetFromTest, )?; - self.memory.check_ptr_access_align( + self.check_ptr_access_align( b, Size::ZERO, Align::ONE, @@ -545,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr }; let size = offset_bytes.unsigned_abs(); // This call handles checking for integer/null pointers. - self.memory.check_ptr_access_align( + self.check_ptr_access_align( min_ptr, Size::from_bytes(size), Align::ONE, @@ -577,7 +577,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let src = self.read_pointer(&src)?; let dst = self.read_pointer(&dst)?; - self.memory.copy(src, align, dst, align, size, nonoverlapping) + self.mem_copy(src, align, dst, align, size, nonoverlapping) } pub(crate) fn write_bytes_intrinsic( @@ -600,7 +600,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?; let bytes = std::iter::repeat(byte).take(len.bytes_usize()); - self.memory.write_bytes(dst, bytes) + self.write_bytes_ptr(dst, bytes) } pub(crate) fn raw_eq_intrinsic( @@ -613,8 +613,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let lhs = self.read_pointer(lhs)?; let rhs = self.read_pointer(rhs)?; - let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?; - let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?; + let lhs_bytes = self.read_bytes_ptr(lhs, layout.size)?; + let rhs_bytes = self.read_bytes_ptr(rhs, layout.size)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 7d75c84d10835..39aec33819ce8 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -14,7 +14,7 @@ use rustc_target::spec::abi::Abi; use super::{ AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, + LocalValue, MemPlace, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; @@ -96,11 +96,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Extra data stored in every call frame. type FrameExtra; - /// Extra data stored in memory. A reference to this is available when `AllocExtra` - /// gets initialized, so you can e.g., have an `Rc` here if there is global state you - /// need access to in the `AllocExtra` hooks. - type MemoryExtra; - /// Extra data stored in every allocation. type AllocExtra: Debug + Clone + 'static; @@ -123,11 +118,11 @@ pub trait Machine<'mir, 'tcx>: Sized { const PANIC_ON_ALLOC_FAIL: bool; /// Whether memory accesses should be alignment-checked. - fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; + fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether, when checking alignment, we should `force_int` and thus support /// custom alignment logic based on whatever the integer address happens to be. - fn force_int_for_alignment_check(memory_extra: &Self::MemoryExtra) -> bool; + fn force_int_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; @@ -251,7 +246,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// `def_id` is `Some` if this is the "lazy" allocation of a static. #[inline] fn before_access_global( - _memory_extra: &Self::MemoryExtra, + _machine: &Self, _alloc_id: AllocId, _allocation: ConstAllocation<'tcx>, _static_def_id: Option, @@ -270,7 +265,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Return the root pointer for the given `extern static`. fn extern_static_base_pointer( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, def_id: DefId, ) -> InterpResult<'tcx, Pointer>; @@ -279,19 +274,19 @@ pub trait Machine<'mir, 'tcx>: Sized { /// /// Not called on `extern` or thread-local statics (those use the methods above). fn tag_alloc_base_pointer( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> Pointer; /// "Int-to-pointer cast" fn ptr_from_addr( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, addr: u64, ) -> Pointer>; /// Convert a pointer with provenance into an allocation-offset pair. fn ptr_get_alloc( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> (AllocId, Size); @@ -309,7 +304,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) fn init_allocation_extra<'b>( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, id: AllocId, alloc: Cow<'b, Allocation>, kind: Option>, @@ -322,7 +317,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// need to mutate. #[inline(always)] fn memory_read( - _memory_extra: &Self::MemoryExtra, + _machine: &Self, _alloc_extra: &Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -333,7 +328,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Hook for performing extra checks on a memory write access. #[inline(always)] fn memory_written( - _memory_extra: &mut Self::MemoryExtra, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -344,7 +339,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Hook for performing extra operations on a memory deallocation. #[inline(always)] fn memory_deallocated( - _memory_extra: &mut Self::MemoryExtra, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -408,14 +403,14 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type FrameExtra = (); #[inline(always)] - fn enforce_alignment(_memory_extra: &Self::MemoryExtra) -> bool { + fn enforce_alignment(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { // We do not check for alignment to avoid having to carry an `Align` // in `ConstValue::ByRef`. false } #[inline(always)] - fn force_int_for_alignment_check(_memory_extra: &Self::MemoryExtra) -> bool { + fn force_int_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { // We do not support `force_int`. false } @@ -444,7 +439,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { #[inline(always)] fn init_allocation_extra<'b>( - _mem: &Memory<$mir, $tcx, Self>, + _ecx: &InterpCx<$mir, $tcx, Self>, _id: AllocId, alloc: Cow<'b, Allocation>, _kind: Option>, @@ -454,28 +449,28 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } fn extern_static_base_pointer( - mem: &Memory<$mir, $tcx, Self>, + ecx: &InterpCx<$mir, $tcx, Self>, def_id: DefId, ) -> InterpResult<$tcx, Pointer> { // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail. - Ok(Pointer::new(mem.tcx.create_static_alloc(def_id), Size::ZERO)) + Ok(Pointer::new(ecx.tcx.create_static_alloc(def_id), Size::ZERO)) } #[inline(always)] fn tag_alloc_base_pointer( - _mem: &Memory<$mir, $tcx, Self>, + _ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer, ) -> Pointer { ptr } #[inline(always)] - fn ptr_from_addr(_mem: &Memory<$mir, $tcx, Self>, addr: u64) -> Pointer> { + fn ptr_from_addr(_ecx: &InterpCx<$mir, $tcx, Self>, addr: u64) -> Pointer> { Pointer::new(None, Size::from_bytes(addr)) } #[inline(always)] - fn ptr_get_alloc(_mem: &Memory<$mir, $tcx, Self>, ptr: Pointer) -> (AllocId, Size) { + fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer) -> (AllocId, Size) { // We know `offset` is relative to the allocation, so we can use `into_parts`. let (alloc_id, offset) = ptr.into_parts(); (alloc_id, offset) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4a235809119f6..815bd42fdcc51 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -17,10 +17,10 @@ use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{Instance, ParamEnv, TyCtxt}; -use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; +use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, + alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, }; @@ -108,19 +108,6 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// that do not exist any more. // FIXME: this should not be public, but interning currently needs access to it pub(super) dead_alloc_map: FxHashMap, - - /// Extra data added by the machine. - pub extra: M::MemoryExtra, - - /// Lets us implement `HasDataLayout`, which is awfully convenient. - pub tcx: TyCtxt<'tcx>, -} - -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> { - #[inline] - fn data_layout(&self) -> &TargetDataLayout { - &self.tcx.data_layout - } } /// A reference to some allocation that was already bounds-checked for the given region @@ -142,16 +129,21 @@ pub struct AllocRefMut<'a, 'tcx, Tag, Extra> { } impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { - pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self { + pub fn new() -> Self { Memory { alloc_map: M::MemoryMap::default(), extra_fn_ptr_map: FxHashMap::default(), dead_alloc_map: FxHashMap::default(), - extra, - tcx, } } + /// This is used by [priroda](https://github.com/oli-obk/priroda) + pub fn alloc_map(&self) -> &M::MemoryMap { + &self.alloc_map + } +} + +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Call this to turn untagged "global" pointers (obtained via `tcx`) into /// the machine pointer to the allocation. Must never be used /// for any other pointers, nor for TLS statics. @@ -182,7 +174,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset))) } - pub fn create_fn_alloc( + pub fn create_fn_alloc_ptr( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, ) -> Pointer { @@ -191,7 +183,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { FnVal::Other(extra) => { // FIXME(RalfJung): Should we have a cache here? let id = self.tcx.reserve_alloc_id(); - let old = self.extra_fn_ptr_map.insert(id, extra); + let old = self.memory.extra_fn_ptr_map.insert(id, extra); assert!(old.is_none()); id } @@ -201,17 +193,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.global_base_pointer(Pointer::from(id)).unwrap() } - pub fn allocate( + pub fn allocate_ptr( &mut self, size: Size, align: Align, kind: MemoryKind, ) -> InterpResult<'static, Pointer> { let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; - Ok(self.allocate_with(alloc, kind)) + Ok(self.allocate_with_ptr(alloc, kind)) } - pub fn allocate_bytes( + pub fn allocate_bytes_ptr( &mut self, bytes: &[u8], align: Align, @@ -219,10 +211,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { mutability: Mutability, ) -> Pointer { let alloc = Allocation::from_bytes(bytes, align, mutability); - self.allocate_with(alloc, kind) + self.allocate_with_ptr(alloc, kind) } - pub fn allocate_with( + pub fn allocate_with_ptr( &mut self, alloc: Allocation, kind: MemoryKind, @@ -234,11 +226,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { "dynamically allocating global memory" ); let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind)); - self.alloc_map.insert(id, (kind, alloc.into_owned())); + self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); M::tag_alloc_base_pointer(self, Pointer::from(id)) } - pub fn reallocate( + pub fn reallocate_ptr( &mut self, ptr: Pointer>, old_size_and_align: Option<(Size, Align)>, @@ -256,13 +248,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind)?; + let new_ptr = self.allocate_ptr(new_size, new_align, kind)?; let old_size = match old_size_and_align { Some((size, _align)) => size, - None => self.get_raw(alloc_id)?.size(), + None => self.get_alloc_raw(alloc_id)?.size(), }; // This will also call the access hooks. - self.copy( + self.mem_copy( ptr.into(), Align::ONE, new_ptr.into(), @@ -270,13 +262,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { old_size.min(new_size), /*nonoverlapping*/ true, )?; - self.deallocate(ptr.into(), old_size_and_align, kind)?; + self.deallocate_ptr(ptr.into(), old_size_and_align, kind)?; Ok(new_ptr) } #[instrument(skip(self), level = "debug")] - pub fn deallocate( + pub fn deallocate_ptr( &mut self, ptr: Pointer>, old_size_and_align: Option<(Size, Align)>, @@ -292,7 +284,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ); } - let Some((alloc_kind, mut alloc)) = self.alloc_map.remove(&alloc_id) else { + let Some((alloc_kind, mut alloc)) = self.memory.alloc_map.remove(&alloc_id) else { // Deallocating global memory -- always an error return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { @@ -335,14 +327,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Let the machine take some extra action let size = alloc.size(); M::memory_deallocated( - &mut self.extra, + &mut self.machine, &mut alloc.extra, ptr.provenance, alloc_range(Size::ZERO, size), )?; // Don't forget to remember size and align of this now-dead allocation - let old = self.dead_alloc_map.insert(alloc_id, (size, alloc.align)); + let old = self.memory.dead_alloc_map.insert(alloc_id, (size, alloc.align)); if old.is_some() { bug!("Nothing can be deallocated twice"); } @@ -358,7 +350,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { size: Size, align: Align, ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer)>> { - let align = M::enforce_alignment(&self.extra).then_some(align); + let align = M::enforce_alignment(&self).then_some(align); self.check_and_deref_ptr( ptr, size, @@ -366,7 +358,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, ptr| { let (size, align) = - self.get_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; + self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; Ok((size, align, (alloc_id, offset, ptr))) }, ) @@ -392,7 +384,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { | CheckInAllocMsg::OffsetFromTest | CheckInAllocMsg::InboundsTest => AllocCheck::Live, }; - let (size, align) = self.get_size_and_align(alloc_id, check)?; + let (size, align) = self.get_alloc_size_and_align(alloc_id, check)?; Ok((size, align, ())) })?; Ok(()) @@ -456,7 +448,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { - if M::force_int_for_alignment_check(&self.extra) { + if M::force_int_for_alignment_check(self) { let addr = Scalar::from_pointer(ptr, &self.tcx) .to_machine_usize(&self.tcx) .expect("ptr-to-int cast for align check should never fail"); @@ -479,7 +471,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } /// Allocation accessors -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Helper function to obtain a global (tcx) allocation. /// This attempts to return a reference to an existing allocation if /// one can be found in `tcx`. That, however, is only possible if `tcx` and @@ -517,7 +509,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { (self.tcx.eval_static_initializer(def_id)?, Some(def_id)) } }; - M::before_access_global(&self.extra, id, alloc, def_id, is_write)?; + M::before_access_global(&self.machine, id, alloc, def_id, is_write)?; // We got tcx memory. Let the machine initialize its "extra" stuff. let alloc = M::init_allocation_extra( self, @@ -530,7 +522,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! - fn get_raw( + fn get_alloc_raw( &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation> { @@ -538,7 +530,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // ways of "erroring": An actual error, or because we got a reference from // `get_global_alloc` that we can actually use directly without inserting anything anywhere. // So the error type is `InterpResult<'tcx, &Allocation>`. - let a = self.alloc_map.get_or(id, || { + let a = self.memory.alloc_map.get_or(id, || { let alloc = self.get_global_alloc(id, /*is_write*/ false).map_err(Err)?; match alloc { Cow::Borrowed(alloc) => { @@ -564,27 +556,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } /// "Safe" (bounds and align-checked) allocation access. - pub fn get<'a>( + pub fn get_ptr_alloc<'a>( &'a self, ptr: Pointer>, size: Size, align: Align, ) -> InterpResult<'tcx, Option>> { - let align = M::enforce_alignment(&self.extra).then_some(align); + let align = M::enforce_alignment(self).then_some(align); let ptr_and_alloc = self.check_and_deref_ptr( ptr, size, align, CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, ptr| { - let alloc = self.get_raw(alloc_id)?; + let alloc = self.get_alloc_raw(alloc_id)?; Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc))) }, )?; if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - M::memory_read(&self.extra, &alloc.extra, ptr.provenance, range)?; - Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id })) + M::memory_read(&self.machine, &alloc.extra, ptr.provenance, range)?; + Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in // order to ensure that `static FOO: Type = FOO;` causes a cycle error instead of @@ -596,7 +588,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Return the `extra` field of the given allocation. pub fn get_alloc_extra<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, &'a M::AllocExtra> { - Ok(&self.get_raw(id)?.extra) + Ok(&self.get_alloc_raw(id)?.extra) } /// Gives raw mutable access to the `Allocation`, without bounds or alignment checks. @@ -604,16 +596,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// /// Also returns a ptr to `self.extra` so that the caller can use it in parallel with the /// allocation. - fn get_raw_mut( + fn get_alloc_raw_mut( &mut self, id: AllocId, - ) -> InterpResult<'tcx, (&mut Allocation, &mut M::MemoryExtra)> - { + ) -> InterpResult<'tcx, (&mut Allocation, &mut M)> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.) - if self.alloc_map.get_mut(id).is_none() { + if self.memory.alloc_map.get_mut(id).is_none() { // Slow path. // Allocation not found locally, go look global. let alloc = self.get_global_alloc(id, /*is_write*/ true)?; @@ -621,18 +612,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { "I got a global allocation that I have to copy but the machine does \ not expect that to happen", ); - self.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned())); + self.memory.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned())); } - let (_kind, alloc) = self.alloc_map.get_mut(id).unwrap(); + let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap(); if alloc.mutability == Mutability::Not { throw_ub!(WriteToReadOnly(id)) } - Ok((alloc, &mut self.extra)) + Ok((alloc, &mut self.machine)) } /// "Safe" (bounds and align-checked) allocation access. - pub fn get_mut<'a>( + pub fn get_ptr_alloc_mut<'a>( &'a mut self, ptr: Pointer>, size: Size, @@ -640,12 +631,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> InterpResult<'tcx, Option>> { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, ptr)) = parts { - let tcx = self.tcx; + let tcx = *self.tcx; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. - let (alloc, extra) = self.get_raw_mut(alloc_id)?; + let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::memory_written(extra, &mut alloc.extra, ptr.provenance, range)?; + M::memory_written(machine, &mut alloc.extra, ptr.provenance, range)?; Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) } else { Ok(None) @@ -656,16 +647,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn get_alloc_extra_mut<'a>( &'a mut self, id: AllocId, - ) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M::MemoryExtra)> { - let (alloc, memory_extra) = self.get_raw_mut(id)?; - Ok((&mut alloc.extra, memory_extra)) + ) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M)> { + let (alloc, machine) = self.get_alloc_raw_mut(id)?; + Ok((&mut alloc.extra, machine)) } /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. /// /// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`. - pub fn get_size_and_align( + pub fn get_alloc_size_and_align( &self, id: AllocId, liveness: AllocCheck, @@ -674,7 +665,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri - if let Some((_, alloc)) = self.alloc_map.get(id) { + if let Some((_, alloc)) = self.memory.alloc_map.get(id) { return Ok((alloc.size(), alloc.align)); } @@ -713,6 +704,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Deallocated pointers are allowed, we should be able to find // them in the map. Ok(*self + .memory .dead_alloc_map .get(&id) .expect("deallocated pointers should all be recorded in `dead_alloc_map`")) @@ -724,7 +716,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } fn get_fn_alloc(&self, id: AllocId) -> Option> { - if let Some(extra) = self.extra_fn_ptr_map.get(&id) { + if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) { Some(FnVal::Other(*extra)) } else { match self.tcx.get_global_alloc(id) { @@ -734,7 +726,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } - pub fn get_fn( + pub fn get_ptr_fn( &self, ptr: Pointer>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { @@ -747,8 +739,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into()) } - pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { - self.get_raw_mut(id)?.0.mutability = Mutability::Not; + pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { + self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not; Ok(()) } @@ -765,7 +757,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn dump_allocs<'a>(&'a self, mut allocs: Vec) -> DumpAllocs<'a, 'mir, 'tcx, M> { allocs.sort(); allocs.dedup(); - DumpAllocs { mem: self, allocs } + DumpAllocs { ecx: self, allocs } } /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation @@ -775,14 +767,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let reachable = { let mut reachable = FxHashSet::default(); let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine); - let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| { - if Some(kind) == global_kind { Some(id) } else { None } - }); + let mut todo: Vec<_> = + self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| { + if Some(kind) == global_kind { Some(id) } else { None } + }); todo.extend(static_roots); while let Some(id) = todo.pop() { if reachable.insert(id) { // This is a new allocation, add its relocations to `todo`. - if let Some((_, alloc)) = self.alloc_map.get(id) { + if let Some((_, alloc)) = self.memory.alloc_map.get(id) { todo.extend(alloc.relocations().values().map(|tag| tag.get_alloc_id())); } } @@ -791,7 +784,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { }; // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking. - let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| { + let leaks: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| { if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) } }); let n = leaks.len(); @@ -800,17 +793,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } n } - - /// This is used by [priroda](https://github.com/oli-obk/priroda) - pub fn alloc_map(&self) -> &M::MemoryMap { - &self.alloc_map - } } #[doc(hidden)] /// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods. pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { - mem: &'a Memory<'mir, 'tcx, M>, + ecx: &'a InterpCx<'mir, 'tcx, M>, allocs: Vec, } @@ -840,25 +828,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, } write!(fmt, "{}", id)?; - match self.mem.alloc_map.get(id) { + match self.ecx.memory.alloc_map.get(id) { Some(&(kind, ref alloc)) => { // normal alloc write!(fmt, " ({}, ", kind)?; write_allocation_track_relocs( &mut *fmt, - self.mem.tcx, + *self.ecx.tcx, &mut allocs_to_print, alloc, )?; } None => { // global alloc - match self.mem.tcx.get_global_alloc(id) { + match self.ecx.tcx.get_global_alloc(id) { Some(GlobalAlloc::Memory(alloc)) => { write!(fmt, " (unchanged global, ")?; write_allocation_track_relocs( &mut *fmt, - self.mem.tcx, + *self.ecx.tcx, &mut allocs_to_print, alloc.inner(), )?; @@ -867,7 +855,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, write!(fmt, " (fn: {})", func)?; } Some(GlobalAlloc::Static(did)) => { - write!(fmt, " (static: {})", self.mem.tcx.def_path_str(did))?; + write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?; } None => { write!(fmt, " (deallocated)")?; @@ -923,16 +911,16 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { } } -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Reads the given number of bytes from memory. Returns them as a slice. /// /// Performs appropriate bounds checks. - pub fn read_bytes( + pub fn read_bytes_ptr( &self, ptr: Pointer>, size: Size, ) -> InterpResult<'tcx, &[u8]> { - let Some(alloc_ref) = self.get(ptr, size, Align::ONE)? else { + let Some(alloc_ref) = self.get_ptr_alloc(ptr, size, Align::ONE)? else { // zero-sized access return Ok(&[]); }; @@ -947,7 +935,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Writes the given stream of bytes into memory. /// /// Performs appropriate bounds checks. - pub fn write_bytes( + pub fn write_bytes_ptr( &mut self, ptr: Pointer>, src: impl IntoIterator, @@ -958,7 +946,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert_eq!(lower, len, "can only write iterators with a precise length"); let size = Size::from_bytes(len); - let Some(alloc_ref) = self.get_mut(ptr, size, Align::ONE)? else { + let Some(alloc_ref) = self.get_ptr_alloc_mut(ptr, size, Align::ONE)? else { // zero-sized access assert_matches!( src.next(), @@ -984,7 +972,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(()) } - pub fn copy( + pub fn mem_copy( &mut self, src: Pointer>, src_align: Align, @@ -993,10 +981,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { size: Size, nonoverlapping: bool, ) -> InterpResult<'tcx> { - self.copy_repeatedly(src, src_align, dest, dest_align, size, 1, nonoverlapping) + self.mem_copy_repeatedly(src, src_align, dest, dest_align, size, 1, nonoverlapping) } - pub fn copy_repeatedly( + pub fn mem_copy_repeatedly( &mut self, src: Pointer>, src_align: Align, @@ -1019,9 +1007,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. return Ok(()); }; - let src_alloc = self.get_raw(src_alloc_id)?; + let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - M::memory_read(&self.extra, &src_alloc.extra, src.provenance, src_range)?; + M::memory_read(&self.machine, &src_alloc.extra, src.provenance, src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else { @@ -1044,7 +1032,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let compressed = src_alloc.compress_uninit_range(src_range); // Destination alloc preparations and access hooks. - let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?; + let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); M::memory_written(extra, &mut dest_alloc.extra, dest.provenance, dest_range)?; let dest_bytes = dest_alloc @@ -1112,7 +1100,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } /// Machine pointer introspection. -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to // call to force getting out a pointer. @@ -1129,6 +1117,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } + /// Test if this value might be null. + /// If the machine does not support ptr-to-int casts, this is conservative. + pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { + match scalar.try_to_int() { + Ok(int) => int.is_null(), + Err(_) => { + // Can only happen during CTFE. + let ptr = self.scalar_to_ptr(scalar); + match self.ptr_try_get_alloc(ptr) { + Ok((alloc_id, offset, _)) => { + let (size, _align) = self + .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead) + .expect("alloc info with MaybeDead cannot fail"); + // If the pointer is out-of-bounds, it may be null. + // Note that one-past-the-end (offset == size) is still inbounds, and never null. + offset > size + } + Err(_offset) => bug!("a non-int scalar is always a pointer"), + } + } + } + } + /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. pub fn ptr_try_get_alloc( diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 9000567558b84..3012f763b80c0 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -257,7 +257,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(None); } - let Some(alloc) = self.get_alloc(mplace)? else { + let Some(alloc) = self.get_place_alloc(mplace)? else { return Ok(Some(ImmTy { // zero-sized type imm: Scalar::ZST.into(), @@ -340,7 +340,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; - let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len))?; + let bytes = self.read_bytes_ptr(mplace.ptr, Size::from_bytes(len))?; let str = std::str::from_utf8(bytes).map_err(|err| err_ub!(InvalidStr(err)))?; Ok(str) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5b8d74b43078e..c37973bd1663c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -306,25 +306,25 @@ where } #[inline] - pub(super) fn get_alloc( + pub(super) fn get_place_alloc( &self, place: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Option>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; - self.memory.get(place.ptr, size, place.align) + self.get_ptr_alloc(place.ptr, size, place.align) } #[inline] - pub(super) fn get_alloc_mut( + pub(super) fn get_place_alloc_mut( &mut self, place: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Option>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; - self.memory.get_mut(place.ptr, size, place.align) + self.get_ptr_alloc_mut(place.ptr, size, place.align) } /// Check if this mplace is dereferenceable and sufficiently aligned. @@ -337,8 +337,8 @@ where .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); - let align = M::enforce_alignment(&self.memory.extra).then_some(align); - self.memory.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; + let align = M::enforce_alignment(self).then_some(align); + self.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; Ok(()) } @@ -748,7 +748,7 @@ where // Invalid places are a thing: the return place of a diverging function let tcx = *self.tcx; - let Some(mut alloc) = self.get_alloc_mut(dest)? else { + let Some(mut alloc) = self.get_place_alloc_mut(dest)? else { // zero-sized access return Ok(()); }; @@ -857,8 +857,7 @@ where }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - self.memory - .copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) + self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) } /// Copies the data from an operand to a place. The layouts may disagree, but they must @@ -942,7 +941,7 @@ where let (size, align) = self .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); - let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?; + let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. @@ -979,7 +978,7 @@ where layout: TyAndLayout<'tcx>, kind: MemoryKind, ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; + let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?; Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) } @@ -990,7 +989,7 @@ where kind: MemoryKind, mutbl: Mutability, ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate_bytes(str.as_bytes(), Align::ONE, kind, mutbl); + let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl); let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) }; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 4272bfd5d6c6f..84563daa0880d 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -225,7 +225,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if length == 0 { // Nothing to copy... but let's still make sure that `dest` as a place is valid. - self.get_alloc_mut(&dest)?; + self.get_place_alloc_mut(&dest)?; } else { // Write the src to the first element. let first = self.mplace_field(&dest, 0)?; @@ -241,7 +241,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // that place might be more aligned than its type mandates (a `u8` array could // be 4-aligned if it sits at the right spot in a struct). Instead we use // `first.layout.align`, i.e., the alignment given by the type. - self.memory.copy_repeatedly( + self.mem_copy_repeatedly( first_ptr, first.align, rest_ptr, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d33358499e237..a7587652114bf 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -72,7 +72,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() { ty::FnPtr(_sig) => { let fn_ptr = self.read_pointer(&func)?; - let fn_val = self.memory.get_fn(fn_ptr)?; + let fn_val = self.get_ptr_fn(fn_ptr)?; (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) } ty::FnDef(def_id, substs) => { diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index fc60a40e2ada6..5cf3807faaa6d 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -32,7 +32,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let vtable_allocation = self.tcx.vtable_allocation((ty, poly_trait_ref)); - let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?; + let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_allocation))?; Ok(vtable_ptr.into()) } @@ -48,11 +48,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr_size = self.pointer_size(); let vtable_slot = vtable.offset(ptr_size * idx, self)?; let vtable_slot = self - .memory - .get(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? + .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); - self.memory.get_fn(fn_ptr) + self.get_ptr_fn(fn_ptr) } /// Returns the drop fn instance as well as the actual dynamic type. @@ -63,8 +62,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let pointer_size = self.pointer_size(); // We don't care about the pointee type; we just want a pointer. let vtable = self - .memory - .get( + .get_ptr_alloc( vtable, pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), self.tcx.data_layout.pointer_align.abi, @@ -77,7 +75,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.memory.get_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; + let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); @@ -99,8 +97,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here), // the size, and the align (which we read below). let vtable = self - .memory - .get( + .get_ptr_alloc( vtable, pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), self.tcx.data_layout.pointer_align.abi, @@ -132,8 +129,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let vtable_slot = vtable.offset(pointer_size * idx, self)?; let new_vtable = self - .memory - .get(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? + .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); let new_vtable = self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 9da7f5e30cb9e..08bb2fe723c34 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -315,7 +315,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( - self.ecx.memory.check_ptr_access_align( + self.ecx.check_ptr_access_align( vtable, 3 * self.ecx.tcx.data_layout.pointer_size, // drop, size, align self.ecx.tcx.data_layout.pointer_align.abi, @@ -403,7 +403,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( - self.ecx.memory.check_ptr_access_align( + self.ecx.check_ptr_access_align( place.ptr, size, align, @@ -432,7 +432,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(ref mut ref_tracking) = self.ref_tracking { // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _ptr)) = self.ecx.memory.ptr_try_get_alloc(place.ptr) { + if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc(place.ptr) { // Special handling for pointers to statics (irrespective of their type). let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { @@ -579,7 +579,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(_) = self.ref_tracking { let ptr = self.ecx.scalar_to_ptr(value); let _fn = try_validation!( - self.ecx.memory.get_fn(ptr), + self.ecx.get_ptr_fn(ptr), self.path, err_ub!(DanglingIntPointer(0, _)) => { "a null function pointer" }, @@ -825,7 +825,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let mplace = op.assert_mem_place(); // strings are never immediate let len = mplace.len(self.ecx)?; try_validation!( - self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)), + self.ecx.read_bytes_ptr(mplace.ptr, Size::from_bytes(len)), self.path, err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, err_unsup!(ReadPointerAsBytes) => { "a pointer in `str`" }, @@ -861,7 +861,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. // We also accept uninit, for consistency with the slow path. - let Some(alloc) = self.ecx.memory.get(mplace.ptr, size, mplace.align)? else { + let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, mplace.align)? else { // Size 0, nothing more to check. return Ok(()); }; diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index e1dbf90b5b9e7..49ebdd302545a 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -184,8 +184,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> type MemoryKind = !; - type MemoryExtra = (); - fn load_mir( _ecx: &InterpCx<'mir, 'tcx, Self>, _instance: ty::InstanceDef<'tcx>, @@ -267,7 +265,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } fn before_access_global( - _memory_extra: &(), + _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx, Self::PointerTag, Self::AllocExtra>, _static_def_id: Option, @@ -377,7 +375,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { span, param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), - (), ); let ret = ecx diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 5be745bc1de38..602aa14b9e6c6 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -180,8 +180,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> type MemoryKind = !; - type MemoryExtra = (); - fn load_mir( _ecx: &InterpCx<'mir, 'tcx, Self>, _instance: ty::InstanceDef<'tcx>, @@ -263,7 +261,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } fn before_access_global( - _memory_extra: &(), + _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx, Self::PointerTag, Self::AllocExtra>, _static_def_id: Option, @@ -374,7 +372,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { span, param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), - (), ); let ret = ecx From 84a343d1b5f4064863a1a4a83782454cf6c2ab37 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Apr 2022 15:29:19 -0400 Subject: [PATCH 03/16] tweak some function names --- .../src/const_eval/machine.rs | 2 +- .../src/interpret/intrinsics.rs | 2 +- .../rustc_const_eval/src/interpret/memory.rs | 22 +++++++++---------- .../src/interpret/validity.rs | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index eea43c62ef0ca..5aae4a9096004 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -364,7 +364,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // If an allocation is created in an another const, // we don't deallocate it. - let (alloc_id, _, _) = ecx.ptr_get_alloc(ptr)?; + let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr)?; let is_allocated_in_another_const = matches!( ecx.tcx.get_global_alloc(alloc_id), Some(interpret::GlobalAlloc::Memory(_)) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 3d70ad87cb44e..a956a478cef9e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -318,7 +318,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // exception from the exception.) // This is the dual to the special exception for offset-by-0 // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below). - match (self.ptr_try_get_alloc(a), self.ptr_try_get_alloc(b)) { + match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) { (Err(a), Err(b)) if a == b && a != 0 => { // Both are the same non-null integer. self.write_scalar(Scalar::from_machine_isize(0, self), dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 815bd42fdcc51..fcfcd5d8989f5 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -200,7 +200,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind: MemoryKind, ) -> InterpResult<'static, Pointer> { let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; - Ok(self.allocate_with_ptr(alloc, kind)) + Ok(self.allocate_raw_ptr(alloc, kind)) } pub fn allocate_bytes_ptr( @@ -211,10 +211,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mutability: Mutability, ) -> Pointer { let alloc = Allocation::from_bytes(bytes, align, mutability); - self.allocate_with_ptr(alloc, kind) + self.allocate_raw_ptr(alloc, kind) } - pub fn allocate_with_ptr( + pub fn allocate_raw_ptr( &mut self, alloc: Allocation, kind: MemoryKind, @@ -238,7 +238,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { new_align: Align, kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub_format!( "reallocating {:?} which does not point to the beginning of an object", @@ -274,7 +274,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { old_size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> InterpResult<'tcx> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; trace!("deallocating: {}", alloc_id); if offset.bytes() != 0 { @@ -419,7 +419,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - Ok(match self.ptr_try_get_alloc(ptr) { + Ok(match self.ptr_try_get_alloc_id(ptr) { Err(addr) => { // We couldn't get a proper allocation. This is only okay if the access size is 0, // and the address is not null. @@ -731,7 +731,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { trace!("get_fn({:?})", ptr); - let (alloc_id, offset, _ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, _ptr) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } @@ -1125,7 +1125,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Err(_) => { // Can only happen during CTFE. let ptr = self.scalar_to_ptr(scalar); - match self.ptr_try_get_alloc(ptr) { + match self.ptr_try_get_alloc_id(ptr) { Ok((alloc_id, offset, _)) => { let (size, _align) = self .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead) @@ -1142,7 +1142,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. - pub fn ptr_try_get_alloc( + pub fn ptr_try_get_alloc_id( &self, ptr: Pointer>, ) -> Result<(AllocId, Size, Pointer), u64> { @@ -1157,11 +1157,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). #[inline(always)] - pub fn ptr_get_alloc( + pub fn ptr_get_alloc_id( &self, ptr: Pointer>, ) -> InterpResult<'tcx, (AllocId, Size, Pointer)> { - self.ptr_try_get_alloc(ptr).map_err(|offset| { + self.ptr_try_get_alloc_id(ptr).map_err(|offset| { err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into() }) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 08bb2fe723c34..42ff7b1945918 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -432,7 +432,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(ref mut ref_tracking) = self.ref_tracking { // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc(place.ptr) { + if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { // Special handling for pointers to statics (irrespective of their type). let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { From e0919de0fdfede34fb85f452ddf2754b5768e4f0 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Mon, 4 Apr 2022 11:10:40 +0900 Subject: [PATCH 04/16] remove unnecessary nested blocks --- compiler/rustc_resolve/src/late.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 400adf20cba7c..11844021c1d1b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2296,22 +2296,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take(); if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) = - (block.could_be_bare_literal, &block.stmts[..]) + (block.could_be_bare_literal, &block.stmts[..]) && let ExprKind::Type(..) = expr.kind { - if let ExprKind::Type(..) = expr.kind { - self.diagnostic_metadata.current_block_could_be_bare_struct_literal = - Some(block.span); - } + self.diagnostic_metadata.current_block_could_be_bare_struct_literal = + Some(block.span); } // Descend into the block. for stmt in &block.stmts { - if let StmtKind::Item(ref item) = stmt.kind { - if let ItemKind::MacroDef(..) = item.kind { - num_macro_definition_ribs += 1; - let res = self.r.local_def_id(item.id).to_def_id(); - self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); - self.label_ribs.push(Rib::new(MacroDefinition(res))); - } + if let StmtKind::Item(ref item) = stmt.kind && let ItemKind::MacroDef(..) = item.kind { + num_macro_definition_ribs += 1; + let res = self.r.local_def_id(item.id).to_def_id(); + self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); + self.label_ribs.push(Rib::new(MacroDefinition(res))); } self.visit_stmt(stmt); From a56f21466e09a247e33660d4745963faba56654e Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Mon, 4 Apr 2022 12:49:02 +0900 Subject: [PATCH 05/16] format cond --- compiler/rustc_resolve/src/late.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 11844021c1d1b..6fedabc816cff 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2296,14 +2296,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take(); if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) = - (block.could_be_bare_literal, &block.stmts[..]) && let ExprKind::Type(..) = expr.kind + (block.could_be_bare_literal, &block.stmts[..]) + && let ExprKind::Type(..) = expr.kind { self.diagnostic_metadata.current_block_could_be_bare_struct_literal = Some(block.span); } // Descend into the block. for stmt in &block.stmts { - if let StmtKind::Item(ref item) = stmt.kind && let ItemKind::MacroDef(..) = item.kind { + if let StmtKind::Item(ref item) = stmt.kind + && let ItemKind::MacroDef(..) = item.kind { num_macro_definition_ribs += 1; let res = self.r.local_def_id(item.id).to_def_id(); self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); From 637592d8c3d07aeb2a204402fe250c6a763aa452 Mon Sep 17 00:00:00 2001 From: Declan Kelly Date: Sun, 3 Apr 2022 17:39:02 -0700 Subject: [PATCH 06/16] Add doc links referencing raw pointer methods --- library/core/src/ptr/non_null.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 7516d4bba4cdf..6f402924e75df 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -256,8 +256,10 @@ impl NonNull { /// Gets the "address" portion of the pointer. /// + /// For more details see the equivalent method on a raw pointer, [`pointer::addr`]. + /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -272,8 +274,10 @@ impl NonNull { /// Creates a new pointer with the given address. /// + /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`]. + /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -287,10 +291,10 @@ impl NonNull { /// Creates a new pointer by mapping `self`'s address to a new one. /// - /// This is a convenience for [`with_addr`][Self::with_addr], see that method for details. + /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`]. /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] From 58dfe26045487ad490a8d095823ec69f12edf0f2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 4 Apr 2022 11:48:47 +0200 Subject: [PATCH 07/16] CandidateSource::XCandidate -> CandidateSource::X --- compiler/rustc_typeck/src/check/method/mod.rs | 9 +++-- .../rustc_typeck/src/check/method/probe.rs | 22 ++++++------ .../rustc_typeck/src/check/method/suggest.rs | 35 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index adc284785c294..8137d70292182 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -8,7 +8,6 @@ pub mod probe; mod suggest; pub use self::suggest::SelfSource; -pub use self::CandidateSource::*; pub use self::MethodError::*; use crate::check::FnCtxt; @@ -82,8 +81,8 @@ pub struct NoMatchData<'tcx> { // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum CandidateSource { - ImplSource(DefId), - TraitSource(DefId /* trait id */), + Impl(DefId), + Trait(DefId /* trait id */), } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -237,8 +236,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *source { // Note: this cannot come from an inherent impl, // because the first probing succeeded. - ImplSource(def) => self.tcx.trait_id_of_impl(def), - TraitSource(_) => None, + CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def), + CandidateSource::Trait(_) => None, } }) .collect(), diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 6edcc12bcf5a6..bc5398ec0d433 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1,7 +1,7 @@ use super::suggest; +use super::CandidateSource; use super::MethodError; use super::NoMatchData; -use super::{CandidateSource, ImplSource, TraitSource}; use crate::check::FnCtxt; use crate::errors::MethodCallOnUnknownType; @@ -692,7 +692,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { for item in self.impl_or_trait_item(impl_def_id) { if !self.has_applicable_self(&item) { // No receiver declared. Not a candidate. - self.record_static_candidate(ImplSource(impl_def_id)); + self.record_static_candidate(CandidateSource::Impl(impl_def_id)); continue; } @@ -846,7 +846,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("elaborate_bounds(bound_trait_ref={:?})", bound_trait_ref); for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { if !self.has_applicable_self(&item) { - self.record_static_candidate(TraitSource(bound_trait_ref.def_id())); + self.record_static_candidate(CandidateSource::Trait(bound_trait_ref.def_id())); } else { mk_cand(self, bound_trait_ref, item); } @@ -944,7 +944,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Check whether `trait_def_id` defines a method with suitable name. if !self.has_applicable_self(&item) { debug!("method has inapplicable self"); - self.record_static_candidate(TraitSource(trait_def_id)); + self.record_static_candidate(CandidateSource::Trait(trait_def_id)); continue; } @@ -1016,8 +1016,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Some(Err(MethodError::Ambiguity(v))) => v .into_iter() .map(|source| match source { - TraitSource(id) => id, - ImplSource(impl_id) => match tcx.trait_id_of_impl(impl_id) { + CandidateSource::Trait(id) => id, + CandidateSource::Impl(impl_id) => match tcx.trait_id_of_impl(impl_id) { Some(id) => id, None => span_bug!(span, "found inherent method when looking at traits"), }, @@ -1415,8 +1415,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(..) => ImplSource(candidate.item.container.id()), - ObjectCandidate | WhereClauseCandidate(_) => TraitSource(candidate.item.container.id()), + InherentImplCandidate(..) => CandidateSource::Impl(candidate.item.container.id()), + ObjectCandidate | WhereClauseCandidate(_) => { + CandidateSource::Trait(candidate.item.container.id()) + } TraitCandidate(trait_ref) => self.probe(|_| { let _ = self .at(&ObligationCause::dummy(), self.param_env) @@ -1426,9 +1428,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point // to that impl. - ImplSource(impl_data.impl_def_id) + CandidateSource::Impl(impl_data.impl_def_id) } - _ => TraitSource(candidate.item.container.id()), + _ => CandidateSource::Trait(candidate.item.container.id()), } }), } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b05f0e4d3c389..c2cb233f5b84c 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (idx, source) in sources.iter().take(limit).enumerate() { match *source { - CandidateSource::ImplSource(impl_did) => { + CandidateSource::Impl(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { @@ -193,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - CandidateSource::TraitSource(trait_did) => { + CandidateSource::Trait(trait_did) => { let Some(item) = self.associated_value(trait_did, item_name) else { continue }; let item_span = self .tcx @@ -515,23 +515,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_span_label = true; } if static_sources.len() == 1 { - let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) = - static_sources.get(0) - { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = tcx.at(span).type_of(*impl_did); - match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { - (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { - // Use `actual` as it will have more `substs` filled in. - self.ty_to_value_string(actual.peel_refs()) + let ty_str = + if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let ty = tcx.at(span).type_of(*impl_did); + match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { + (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { + // Use `actual` as it will have more `substs` filled in. + self.ty_to_value_string(actual.peel_refs()) + } + _ => self.ty_to_value_string(ty.peel_refs()), } - _ => self.ty_to_value_string(ty.peel_refs()), - } - } else { - self.ty_to_value_string(actual.peel_refs()) - }; + } else { + self.ty_to_value_string(actual.peel_refs()) + }; if let SelfSource::MethodCall(expr) = source { err.span_suggestion( expr.span.to(span), From 3aac307ca62f6d6c5b3612d3dfe80b6eeae8ba15 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 13 Dec 2021 20:56:40 +0000 Subject: [PATCH 08/16] Mention implementers of unsatisfied trait When encountering an unsatisfied trait bound, if there are no other suggestions, mention all the types that *do* implement that trait: ``` error[E0277]: the trait bound `f32: Foo` is not satisfied --> $DIR/impl_wf.rs:22:6 | LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` | = help: the following other types implement trait `Foo`: Option i32 str note: required by a bound in `Baz` --> $DIR/impl_wf.rs:18:31 | LL | trait Baz where U: Foo { } | ^^^ required by this bound in `Baz` ``` Mention implementers of traits in `ImplObligation`s. Do not mention other `impl`s for closures, ranges and `?`. --- compiler/rustc_errors/src/diagnostic.rs | 6 + compiler/rustc_middle/src/ty/mod.rs | 9 +- .../src/check_packed_ref.rs | 25 +--- compiler/rustc_span/src/symbol.rs | 4 + .../src/traits/error_reporting/mod.rs | 126 +++++++++++++++--- .../src/traits/error_reporting/suggestions.rs | 44 +++--- library/core/src/ops/function.rs | 3 + library/core/src/slice/index.rs | 1 + src/test/ui/allocator/not-an-allocator.rs | 8 +- src/test/ui/allocator/not-an-allocator.stderr | 4 + .../associated-types-path-2.stderr | 12 +- .../hr-associated-type-bound-1.stderr | 3 +- .../hr-associated-type-bound-param-1.stderr | 3 +- .../hr-associated-type-bound-param-2.stderr | 9 +- .../hr-associated-type-bound-param-3.stderr | 3 +- .../hr-associated-type-bound-param-4.stderr | 3 +- .../hr-associated-type-bound-param-5.stderr | 6 +- .../ui/associated-types/issue-65774-1.stderr | 2 + .../ui/associated-types/issue-65774-2.stderr | 2 + ...ypeck-default-trait-impl-precedence.stderr | 3 +- src/test/ui/binop/binop-mul-i32-f32.stderr | 6 + src/test/ui/binop/issue-77910-1.stderr | 6 + .../ui/binop/shift-various-bad-types.stderr | 18 +++ src/test/ui/block-result/issue-22645.stderr | 3 +- src/test/ui/chalkify/generic_impls.stderr | 6 +- src/test/ui/chalkify/impl_wf.stderr | 3 +- src/test/ui/chalkify/impl_wf_2.stderr | 3 +- src/test/ui/chalkify/type_wf.stderr | 3 +- ...ce-issue-49593-box-never.nofallback.stderr | 20 +++ .../associated-type-bound-fail.stderr | 3 +- .../defaults/rp_impl_trait_fail.stderr | 6 +- .../defaults/trait_objects_fail.stderr | 6 +- .../ui/const-generics/defaults/wfness.stderr | 6 +- .../ui/const-generics/exhaustive-value.stderr | 2 +- .../occurs-check/unused-substs-1.stderr | 3 +- .../const-blocks/fn-call-in-non-const.stderr | 3 +- .../consts/const-blocks/migrate-fail.stderr | 6 +- .../ui/consts/const-blocks/nll-fail.stderr | 6 +- .../ui/consts/const-blocks/trait-error.stderr | 3 +- .../const-eval/const-eval-overflow-3b.stderr | 6 + .../const-eval/const-eval-overflow-4b.stderr | 6 + .../ui/consts/too_generic_eval_ice.stderr | 6 + ...e-21659-show-relevant-trait-impls-2.stderr | 1 - .../issue-39802-show-5-trait-impls.stderr | 3 - ...de-confusable-in-float-literal-expt.stderr | 6 + .../feature-gate-trivial_bounds.stderr | 6 + src/test/ui/fmt/ifmt-unimpl.stderr | 10 ++ .../bugs/issue-88460.stderr | 1 + src/test/ui/impl-trait/equality.stderr | 6 + .../ui/impl-trait/issues/issue-62742.stderr | 6 +- .../nested-return-type2-tait.stderr | 2 + .../nested-return-type2-tait2.stderr | 1 + .../nested-return-type2-tait3.stderr | 1 + ...impl-trait-declaration-too-subtle-2.stderr | 1 + src/test/ui/index-help.stderr | 1 + src/test/ui/indexing-requires-a-uint.stderr | 1 + src/test/ui/integral-indexing.stderr | 8 ++ src/test/ui/issues/issue-11771.stderr | 12 ++ src/test/ui/issues/issue-24352.stderr | 6 + src/test/ui/issues/issue-34334.stderr | 1 + src/test/ui/issues/issue-45801.stderr | 3 +- src/test/ui/issues/issue-50582.stderr | 6 + src/test/ui/issues/issue-59488.stderr | 6 + ...e-66923-show-error-for-correct-call.stderr | 2 + src/test/ui/kindck/kindck-copy.stderr | 4 +- .../ui/lexer/lex-bad-char-literals-6.stderr | 12 ++ src/test/ui/mismatched_types/binops.stderr | 36 +++++ .../defaulted-never-note.fallback.stderr | 2 +- .../ui/never_type/defaulted-never-note.rs | 2 +- ...diverging-fallback-no-leak.fallback.stderr | 4 +- .../ui/never_type/impl_trait_fallback2.stderr | 2 + src/test/ui/never_type/issue-13352.stderr | 6 + ...lue-fallback-issue-66757.nofallback.stderr | 3 +- .../not-suggest-float-literal.stderr | 72 ++++++++++ .../suggest-float-literal.stderr | 48 +++++++ .../ui/on-unimplemented/impl-substs.stderr | 1 + .../ui/on-unimplemented/multiple-impls.stderr | 18 +++ src/test/ui/on-unimplemented/on-impl.stderr | 2 + .../ui/on-unimplemented/slice-index.stderr | 4 + src/test/ui/range/range-1.stderr | 10 ++ .../termination-trait-test-wrong-type.stderr | 4 + src/test/ui/span/multiline-span-simple.stderr | 6 + .../default-associated-type-bound-1.stderr | 3 +- src/test/ui/str/str-idx.stderr | 3 + src/test/ui/str/str-mut-idx.stderr | 3 + ...-trait-object-literal-bound-regions.stderr | 3 +- .../imm-ref-trait-object-literal.stderr | 3 +- ...mpl-trait-return-trailing-semicolon.stderr | 2 + src/test/ui/suggestions/into-str.stderr | 1 - .../suggestions/issue-84973-negative.stderr | 3 +- .../check-trait-object-bounds-1.stderr | 3 +- .../check-trait-object-bounds-4.stderr | 3 +- src/test/ui/traits/bound/same-crate-name.rs | 2 +- .../ui/traits/bound/same-crate-name.stderr | 6 +- .../ui/traits/coercion-generic-bad.stderr | 3 +- .../repeated-supertrait-ambig.stderr | 4 + src/test/ui/traits/issue-91594.stderr | 3 +- src/test/ui/traits/map-types.stderr | 1 + .../ui/traits/reservation-impl/no-use.stderr | 3 +- .../suggest-deferences/issue-62530.stderr | 2 - .../suggest-deferences/multiple-1.stderr | 1 + .../ui/try-block/try-block-bad-type.stderr | 3 +- .../ui/try-trait/bad-interconversion.stderr | 9 +- src/test/ui/try-trait/option-to-result.stderr | 2 + src/test/ui/try-trait/try-on-option.stderr | 1 + .../type-alias-impl-trait/issue-60371.stderr | 3 +- .../nested-tait-inference.stderr | 6 +- .../self-referential-2.stderr | 6 + .../self-referential-4.stderr | 18 +++ .../self-referential.stderr | 18 +++ src/test/ui/type/type-check-defaults.stderr | 6 + src/test/ui/typeck/issue-81293.stderr | 6 + .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 6 + .../unevaluated_fixed_size_array_len.stderr | 3 +- .../ui/wf/hir-wf-check-erase-regions.stderr | 2 + 115 files changed, 690 insertions(+), 183 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 00ecbbbb93b98..32c52a6a8a6d9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -378,6 +378,12 @@ impl Diagnostic { self } + /// Add a help message attached to this diagnostic with a customizable highlighted message. + pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + self.sub_with_highlights(Level::Help, msg, MultiSpan::new(), None); + self + } + /// Prints the span with some help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. pub fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 37425c91157b3..45a215354d081 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -41,7 +41,7 @@ use rustc_hir::Node; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::CrateStoreDyn; -use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi::Align; @@ -2206,7 +2206,7 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_ref(def_id).map(|tr| tr.def_id) } - /// If the given defid describes a method belonging to an impl, returns the + /// If the given `DefId` describes a method belonging to an impl, returns the /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { @@ -2215,6 +2215,11 @@ impl<'tcx> TyCtxt<'tcx> { }) } + /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`. + pub fn is_builtin_derive(self, def_id: DefId) -> bool { + self.has_attr(def_id, sym::automatically_derived) + } + /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result { diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index f0367958ef8c5..4bf66cd4c9f2e 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -1,10 +1,9 @@ -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; -use rustc_span::symbol::sym; use crate::util; use crate::MirLint; @@ -50,22 +49,6 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { }); } -fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - debug!("builtin_derive_def_id({:?})", def_id); - if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, sym::automatically_derived) { - debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); - Some(impl_def_id) - } else { - debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); - None - } - } else { - debug!("builtin_derive_def_id({:?}) - not a method", def_id); - None - } -} - impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. @@ -83,7 +66,11 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { let def_id = self.body.source.instance.def_id(); - if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) { + if let Some(impl_def_id) = self + .tcx + .impl_of_method(def_id) + .filter(|&def_id| self.tcx.is_builtin_derive(def_id)) + { // If a method is defined in the local crate, // the impl containing that method should also be. self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2737c26708bc4..f5803aaa0786e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -180,6 +180,9 @@ symbols! { Error, File, FileType, + Fn, + FnMut, + FnOnce, FormatSpec, Formatter, From, @@ -248,6 +251,7 @@ symbols! { RustcEncodable, Send, SeqCst, + SliceIndex, Some, String, StructuralEq, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 216aa89dd1f28..2da4c86a58e9c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -14,6 +14,7 @@ use crate::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + Style, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -354,7 +355,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = - { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; + Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); let (message, note, append_const_msg) = if is_try_conversion { ( Some(format!( @@ -363,7 +364,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )), Some( "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" + conversion on the error value using the `From` trait" .to_owned(), ), Some(None), @@ -519,10 +520,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); - self.suggest_dereferences(&obligation, &mut err, trait_predicate); - self.suggest_fn_call(&obligation, &mut err, trait_predicate); - self.suggest_remove_reference(&obligation, &mut err, trait_predicate); - self.suggest_semicolon_removal( + let mut suggested = + self.suggest_dereferences(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); + suggested |= + self.suggest_remove_reference(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_semicolon_removal( &obligation, &mut err, span, @@ -648,10 +651,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_predicate, obligation.cause.body_id, ); - } else if !have_alt_message { + } else if !suggested { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); + self.report_similar_impl_candidates( + impl_candidates, + trait_ref, + &mut err, + ); } // Changing mutability doesn't make a difference to whether we have @@ -676,7 +683,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }); let unit_obligation = obligation.with(predicate.to_predicate(tcx)); if self.predicate_may_hold(&unit_obligation) { - err.note("this trait is implemented for `()`"); err.note( "this error might have been caused by changes to \ Rust's type-inference algorithm (see issue #48950 \ @@ -1301,8 +1307,9 @@ trait InferCtxtPrivExt<'hir, 'tcx> { fn report_similar_impl_candidates( &self, impl_candidates: Vec>, + trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, - ); + ) -> bool; /// Gets the parent trait chain start fn get_parent_trait_ref( @@ -1313,7 +1320,11 @@ trait InferCtxtPrivExt<'hir, 'tcx> { /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>); + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool; /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the /// `trait_ref`. @@ -1675,10 +1686,63 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { fn report_similar_impl_candidates( &self, impl_candidates: Vec>, + trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, - ) { + ) -> bool { + let def_id = trait_ref.def_id(); if impl_candidates.is_empty() { - return; + if self.tcx.trait_is_auto(def_id) + || self.tcx.lang_items().items().contains(&Some(def_id)) + || self.tcx.get_diagnostic_name(def_id).is_some() + { + // Mentioning implementers of `Copy`, `Debug` and friends is not useful. + return false; + } + let mut normalized_impl_candidates: Vec<_> = self + .tcx + .all_impls(def_id) + // Ignore automatically derived impls and `!Trait` impls. + .filter(|&def_id| { + self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative + || self.tcx.is_builtin_derive(def_id) + }) + .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) + // Avoid mentioning type parameters. + .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_))) + .map(|trait_ref| format!("\n {}", trait_ref.self_ty())) + .collect(); + normalized_impl_candidates.sort(); + normalized_impl_candidates.dedup(); + let len = normalized_impl_candidates.len(); + if len == 0 { + return false; + } + if len == 1 { + err.highlighted_help(vec![ + ( + format!( + "the trait `{}` is implemented for `", + trait_ref.print_only_trait_path() + ), + Style::NoStyle, + ), + (normalized_impl_candidates[0].trim().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + return true; + } + let end = if normalized_impl_candidates.len() <= 9 { + normalized_impl_candidates.len() + } else { + 8 + }; + err.help(&format!( + "the following other types implement trait `{}`:{}{}", + trait_ref.print_only_trait_path(), + normalized_impl_candidates[..end].join(""), + if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + )); + return true; } let len = impl_candidates.len(); @@ -1703,6 +1767,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // // Prefer more similar candidates first, then sort lexicographically // by their normalized string representation. + let first_candidate = impl_candidates.get(0).map(|candidate| candidate.trait_ref); let mut normalized_impl_candidates_and_similarities = impl_candidates .into_iter() .map(|ImplCandidate { trait_ref, similarity }| { @@ -1711,17 +1776,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { }) .collect::>(); normalized_impl_candidates_and_similarities.sort(); + normalized_impl_candidates_and_similarities.dedup(); let normalized_impl_candidates = normalized_impl_candidates_and_similarities .into_iter() .map(|(_, normalized)| normalized) .collect::>(); - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } - )); + if normalized_impl_candidates.len() == 1 { + err.highlighted_help(vec![ + ( + format!( + "the trait `{}` is implemented for `", + first_candidate.unwrap().print_only_trait_path() + ), + Style::NoStyle, + ), + (first_candidate.unwrap().self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + } else { + err.help(&format!( + "the following implementations were found:{}{}", + normalized_impl_candidates[..end].join(""), + if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + )); + } + true } /// Gets the parent trait chain start @@ -1752,7 +1833,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>) { + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool { let get_trait_impl = |trait_def_id| { self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) }; @@ -1763,6 +1848,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) .collect(); + let mut suggested = false; for trait_with_same_path in traits_with_same_path { if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) { let impl_span = self.tcx.def_span(impl_def_id); @@ -1773,8 +1859,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { trait_crate ); err.note(&crate_msg); + suggested = true; } } + suggested } fn mk_trait_obligation_with_new_self_ty( 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 b49a5f6578f75..5bf9be87b57ae 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -58,7 +58,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option; @@ -67,7 +67,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn suggest_add_reference_to_arg( &self, @@ -82,7 +82,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic); @@ -99,7 +99,7 @@ pub trait InferCtxtExt<'tcx> { err: &mut Diagnostic, span: Span, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; @@ -494,14 +494,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { // It only make sense when suggesting dereferences for arguments let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = obligation.cause.code() { parent_code.clone() } else { - return; + return false; }; let param_env = obligation.param_env; let body_id = obligation.cause.body_id; @@ -513,7 +513,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => trait_pred, }; let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { - return; + return false; }; if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { @@ -537,11 +537,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("&{}{}", derefs, &src[1..]), Applicability::MachineApplicable, ); + return true; } } } } } + false } /// Given a closure's `DefId`, return the given name of the closure. @@ -584,22 +586,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let Some(self_ty) = trait_pred.self_ty().no_bound_vars() else { - return; + return false; }; let (def_id, output_ty, callable) = match *self_ty.kind() { ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"), ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"), - _ => return, + _ => return false, }; let msg = format!("use parentheses to call the {}", callable); // `mk_trait_obligation_with_new_self_ty` only works for types with no escaping bound // variables, so bail out if we have any. let Some(output_ty) = output_ty.no_bound_vars() else { - return; + return false; }; let new_obligation = @@ -611,7 +613,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | EvaluationResult::EvaluatedToOkModuloRegions | EvaluationResult::EvaluatedToAmbig, ) => {} - _ => return, + _ => return false, } let hir = self.tcx.hir(); // Get the name of the callable and the arguments to be used in the suggestion. @@ -622,7 +624,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { })) => { err.span_label(*span, "consider calling this closure"); let Some(name) = self.get_closure_name(def_id, err, &msg) else { - return; + return false; }; let args = decl.inputs.iter().map(|_| "_").collect::>().join(", "); let sugg = format!("({})", args); @@ -650,7 +652,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let sugg = format!("({})", args); (format!("{}{}", ident, sugg), sugg) } - _ => return, + _ => return false, }; if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) { @@ -667,6 +669,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else { err.help(&format!("{}: `{}`", msg, snippet)); } + true } fn suggest_add_reference_to_arg( @@ -808,19 +811,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let span = obligation.cause.span; + let mut suggested = false; if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. - return; + return false; } let Some(mut suggested_ty) = trait_pred.self_ty().no_bound_vars() else { - return; + return false; }; for refs_remaining in 0..refs_number { @@ -856,10 +860,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, ); + suggested = true; break; } } } + suggested } fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) { @@ -996,7 +1002,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut Diagnostic, span: Span, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); let node = hir.find(parent_node); @@ -1015,7 +1021,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { let sp = self.tcx.sess.source_map().end_point(stmt.span); err.span_label(sp, "consider removing this semicolon"); + return true; } + false } fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option { diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index e5c4798afcbff..8383f92643550 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -53,6 +53,7 @@ /// ``` #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Fn"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( @@ -133,6 +134,7 @@ pub trait Fn: FnMut { /// ``` #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnMut"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( @@ -205,6 +207,7 @@ pub trait FnMut: FnOnce { /// ``` #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnOnce"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 880d0f80cc8a0..68de4e4e1f32a 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -140,6 +140,7 @@ mod private_slice_index { /// Implementations of this trait have to promise that if the argument /// to `get_(mut_)unchecked` is a safe reference, then so is the result. #[stable(feature = "slice_get_slice", since = "1.28.0")] +#[rustc_diagnostic_item = "SliceIndex"] #[rustc_on_unimplemented( on(T = "str", label = "string indices are ranges of `usize`",), on( diff --git a/src/test/ui/allocator/not-an-allocator.rs b/src/test/ui/allocator/not-an-allocator.rs index 417c371bdbf61..4a538d4d0a0d8 100644 --- a/src/test/ui/allocator/not-an-allocator.rs +++ b/src/test/ui/allocator/not-an-allocator.rs @@ -1,8 +1,8 @@ #[global_allocator] static A: usize = 0; -//~^ the trait bound `usize: -//~| the trait bound `usize: -//~| the trait bound `usize: -//~| the trait bound `usize: +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 fn main() {} diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr index c0f6118a9f163..62bb0679f813a 100644 --- a/src/test/ui/allocator/not-an-allocator.stderr +++ b/src/test/ui/allocator/not-an-allocator.stderr @@ -6,6 +6,7 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -16,6 +17,7 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -26,6 +28,7 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -36,6 +39,7 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index f56631b12aa67..2d8d513409d3a 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -15,8 +15,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied LL | f1(2u32, 4u32); | ^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 | @@ -29,8 +28,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied LL | f1(2u32, 4u32); | ^^^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:8 @@ -40,8 +38,7 @@ LL | f1(2u32, 4i32); | | | required by a bound introduced by this call | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 | @@ -54,8 +51,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied LL | f1(2u32, 4i32); | ^^^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` error[E0308]: mismatched types --> $DIR/associated-types-path-2.rs:41:18 diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr index ec28ca240be2b..73b5e1053fb9d 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-1.rs:3:33 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr index e48ef8d17d1de..af2e616896a87 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type V = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y` --> $DIR/hr-associated-type-bound-param-1.rs:4:36 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr index 2fb3af38c0d9b..5809c407a5f7f 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -21,8 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -38,8 +36,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type W = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr index 775f45ca82965..84d5e0494cb69 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-3.rs:4:33 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr index 4e9b64ba832ad..ee1d5d324954a 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-4.rs:4:36 | diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr index d00abf30d3b05..ece3151ba978c 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 | @@ -21,8 +20,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 | diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index 82c520b99b170..e468a1b3ba484 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied LL | type MpuConfig: MyDisplay = T; | ^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required by a bound in `MPU::MpuConfig` --> $DIR/issue-65774-1.rs:10:21 | @@ -16,6 +17,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required because of the requirements on the impl of `MyDisplay` for `&mut T` --> $DIR/issue-65774-1.rs:5:24 | diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index 349cef9df72dd..4cef4db4698a7 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied LL | type MpuConfig: MyDisplay = T; | ^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required by a bound in `MPU::MpuConfig` --> $DIR/issue-65774-2.rs:10:21 | @@ -16,6 +17,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied LL | writer.my_write(valref) | ^^^^^^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index 5755778fef266..985cdce1224da 100644 --- a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | - = help: the following implementations were found: - + = help: the trait `Signed` is implemented for `i32` note: required because of the requirements on the impl of `Defaulted` for `&'static u32` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 | diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 4a67fe2379b8d..9fcf5d72625c5 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr @@ -5,6 +5,12 @@ LL | x * y | ^ no implementation for `i32 * f32` | = help: the trait `Mul` is not implemented for `i32` + = help: the following implementations were found: + <&'a i32 as Mul> + <&i32 as Mul<&i32>> + > + + and 49 others error: aborting due to previous error diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index db854ae80d738..9553fcc5bb204 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -16,6 +16,12 @@ LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` + = help: the following implementations were found: + Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> + and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/binop/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr index 932a435143b0c..e134095e63879 100644 --- a/src/test/ui/binop/shift-various-bad-types.stderr +++ b/src/test/ui/binop/shift-various-bad-types.stderr @@ -5,6 +5,12 @@ LL | 22 >> p.char; | ^^ no implementation for `{integer} >> char` | = help: the trait `Shr` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others error[E0277]: no implementation for `{integer} >> &str` --> $DIR/shift-various-bad-types.rs:12:8 @@ -13,6 +19,12 @@ LL | 22 >> p.str; | ^^ no implementation for `{integer} >> &str` | = help: the trait `Shr<&str>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others error[E0277]: no implementation for `{integer} >> &Panolpy` --> $DIR/shift-various-bad-types.rs:15:8 @@ -21,6 +33,12 @@ LL | 22 >> p; | ^^ no implementation for `{integer} >> &Panolpy` | = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others error[E0308]: mismatched types --> $DIR/shift-various-bad-types.rs:25:18 diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 397bdac60513e..31663e8e84d72 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied LL | b + 3 | ^ the trait `Scalar` is not implemented for `{integer}` | - = help: the following implementations were found: - + = help: the trait `Scalar` is implemented for `f64` note: required because of the requirements on the impl of `Add<{integer}>` for `Bob` --> $DIR/issue-22645.rs:8:19 | diff --git a/src/test/ui/chalkify/generic_impls.stderr b/src/test/ui/chalkify/generic_impls.stderr index 0c7fcd04dfd2d..d4a8354d3fc80 100644 --- a/src/test/ui/chalkify/generic_impls.stderr +++ b/src/test/ui/chalkify/generic_impls.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `(Option, f32): Foo` is not satisfied LL | gimme::<(Option, f32)>(); | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(Option, f32)` | - = help: the following implementations were found: - <(T, u32) as Foo> + = help: the trait `Foo` is implemented for `(T, u32)` note: required by a bound in `gimme` --> $DIR/generic_impls.rs:7:13 | @@ -18,8 +17,7 @@ error[E0277]: the trait bound `(i32, f32): Foo` is not satisfied LL | gimme::<(i32, f32)>(); | ^^^^^^^^^^ the trait `Foo` is not implemented for `(i32, f32)` | - = help: the following implementations were found: - <(T, u32) as Foo> + = help: the trait `Foo` is implemented for `(T, u32)` note: required by a bound in `gimme` --> $DIR/generic_impls.rs:7:13 | diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index 2bc9f077f0285..a142459bcb4a5 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -17,8 +17,7 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `Baz` --> $DIR/impl_wf.rs:18:31 | diff --git a/src/test/ui/chalkify/impl_wf_2.stderr b/src/test/ui/chalkify/impl_wf_2.stderr index 30cec80b036c6..1c1df644b0610 100644 --- a/src/test/ui/chalkify/impl_wf_2.stderr +++ b/src/test/ui/chalkify/impl_wf_2.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied LL | type Item = f32; | ^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `Bar::Item` --> $DIR/impl_wf_2.rs:8:16 | diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr index 6abd8b28760d8..7f8566082cd26 100644 --- a/src/test/ui/chalkify/type_wf.stderr +++ b/src/test/ui/chalkify/type_wf.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `{float}: Foo` is not satisfied LL | let s = S { | ^ the trait `Foo` is not implemented for `{float}` | - = help: the following implementations were found: - + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `S` --> $DIR/type_wf.rs:6:13 | diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index fbaa874792a01..a4b10a4c339f9 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | + = help: the following other types implement trait `std::error::Error`: + ! + &'a T + AccessError + AddrParseError + Arc + BorrowError + BorrowMutError + Box + and 42 others = note: required for the cast to the object type `dyn std::error::Error` error[E0277]: the trait bound `(): std::error::Error` is not satisfied @@ -12,6 +22,16 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | + = help: the following other types implement trait `std::error::Error`: + ! + &'a T + AccessError + AddrParseError + Arc + BorrowError + BorrowMutError + Box + and 42 others = note: required for the cast to the object type `(dyn std::error::Error + 'static)` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/associated-type-bound-fail.stderr b/src/test/ui/const-generics/associated-type-bound-fail.stderr index 9dc677ef6ed48..da2558229a758 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.stderr +++ b/src/test/ui/const-generics/associated-type-bound-fail.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `u16: Bar` is not satisfied LL | type Assoc = u16; | ^^^ the trait `Bar` is not implemented for `u16` | - = help: the following implementations were found: - > + = help: the trait `Bar<3_usize>` is implemented for `u16` note: required by a bound in `Foo::Assoc` --> $DIR/associated-type-bound-fail.rs:4:17 | diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 81cfcb3560661..9cadc4110e1e6 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied LL | fn rawr() -> impl Trait { | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | - = help: the following implementations were found: - as Trait> + = help: the trait `Trait` is implemented for `Uwu` error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied --> $DIR/rp_impl_trait_fail.rs:6:25 @@ -18,8 +17,7 @@ LL | | Uwu::<10, 12> LL | | } | |_^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | - = help: the following implementations were found: - as Trait> + = help: the trait `Trait` is implemented for `Uwu` error[E0277]: the trait bound `u32: Traitor` is not satisfied --> $DIR/rp_impl_trait_fail.rs:18:26 diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr index 13d03c2d42d31..7f8a1f742d840 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr @@ -6,8 +6,7 @@ LL | foo(&10_u32); | | | required by a bound introduced by this call | - = help: the following implementations were found: - > + = help: the trait `Trait<2_u8>` is implemented for `u32` = note: required for the cast to the object type `dyn Trait` error[E0277]: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied @@ -18,8 +17,7 @@ LL | bar(&true); | | | required by a bound introduced by this call | - = help: the following implementations were found: - > + = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` = note: required for the cast to the object type `dyn Traitor<{_: u8}, {_: u8}>` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/wfness.stderr b/src/test/ui/const-generics/defaults/wfness.stderr index facf0ae19f734..8b405d6753e56 100644 --- a/src/test/ui/const-generics/defaults/wfness.stderr +++ b/src/test/ui/const-generics/defaults/wfness.stderr @@ -10,8 +10,7 @@ error[E0277]: the trait bound `(): Trait<2_u8>` is not satisfied LL | struct WhereClause where (): Trait; | ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` | - = help: the following implementations were found: - <() as Trait<3_u8>> + = help: the trait `Trait<3_u8>` is implemented for `()` error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied --> $DIR/wfness.rs:14:13 @@ -19,8 +18,7 @@ error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied LL | fn foo() -> DependentDefaultWfness { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` | - = help: the following implementations were found: - <() as Trait<3_u8>> + = help: the trait `Trait<3_u8>` is implemented for `()` note: required by a bound in `WhereClause` --> $DIR/wfness.rs:6:47 | diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index 1a8f4abf52aa3..cb85b6cb93d91 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -9,7 +9,7 @@ LL | <() as Foo>::test() <() as Foo<100_u8>> <() as Foo<101_u8>> <() as Foo<102_u8>> - and 252 others + and 248 others error: aborting due to previous error diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr index 486a298a9ffe5..aedf44658db63 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied LL | let _ = A; | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` | - = help: the following implementations were found: - as Bar> + = help: the trait `Bar` is implemented for `A<{ 6 + 1 }>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 | diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr index 329c6cb2b1285..52a1669e33002 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Option: Copy` is not satisfied LL | let _: [Option; 2] = [no_copy(); 2]; | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Option` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Option` = note: the `Copy` trait is required because the repeated element will be copied = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information diff --git a/src/test/ui/consts/const-blocks/migrate-fail.stderr b/src/test/ui/consts/const-blocks/migrate-fail.stderr index 0fdbbc36288e9..318fec60290ee 100644 --- a/src/test/ui/consts/const-blocks/migrate-fail.stderr +++ b/src/test/ui/consts/const-blocks/migrate-fail.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Option: Copy` is not satisfied LL | let arr: [Option; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Option` = note: the `Copy` trait is required because the repeated element will be copied error[E0277]: the trait bound `Option: Copy` is not satisfied @@ -14,8 +13,7 @@ error[E0277]: the trait bound `Option: Copy` is not satisfied LL | let arr: [Option; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Option` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-blocks/nll-fail.stderr b/src/test/ui/consts/const-blocks/nll-fail.stderr index 8122085635977..5a34361aa83b6 100644 --- a/src/test/ui/consts/const-blocks/nll-fail.stderr +++ b/src/test/ui/consts/const-blocks/nll-fail.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Option: Copy` is not satisfied LL | let arr: [Option; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Option` = note: the `Copy` trait is required because the repeated element will be copied error[E0277]: the trait bound `Option: Copy` is not satisfied @@ -14,8 +13,7 @@ error[E0277]: the trait bound `Option: Copy` is not satisfied LL | let arr: [Option; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Option` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-blocks/trait-error.stderr b/src/test/ui/consts/const-blocks/trait-error.stderr index 26e2848e7f7a1..6979ff36176cd 100644 --- a/src/test/ui/consts/const-blocks/trait-error.stderr +++ b/src/test/ui/consts/const-blocks/trait-error.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Foo` | - = help: the following implementations were found: - as Copy> + = help: the trait `Copy` is implemented for `Foo` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 2b96b66819286..aee7192b6eda1 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -11,6 +11,12 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` + = help: the following implementations were found: + <&'a i8 as Add> + <&i8 as Add<&i8>> + > + + and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index f59ff329d18ac..059447f7cacb3 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -11,6 +11,12 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` + = help: the following implementations were found: + <&'a i8 as Add> + <&i8 as Add<&i8>> + > + + and 48 others error[E0604]: only `u8` can be cast as `char`, not `i8` --> $DIR/const-eval-overflow-4b.rs:22:13 diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index ac104ed4a5a58..677fa7d21aef0 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -21,6 +21,12 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | ^^ no implementation for `[{integer}; _] == [{integer}; 0]` | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; _]` + = help: the following implementations were found: + <&[B] as PartialEq<[A; N]>> + <&[T] as PartialEq>> + <&mut [B] as PartialEq<[A; N]>> + <&mut [T] as PartialEq>> + and 3 others error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index d6d5ce4d1a7d2..ea461241bf414 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -9,7 +9,6 @@ LL | f1.foo(1usize); > > > - and 2 others error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index dff980301911c..58faaf4ea9014 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -11,7 +11,6 @@ LL | Foo::::bar(&1i8); > > > - and 5 others error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -26,7 +25,6 @@ LL | Foo::::bar(&1u8); > > > - and 5 others error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 @@ -41,7 +39,6 @@ LL | Foo::::bar(&true); > > > - and 2 others error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 83fc37e7e537f..c12b02a76c58a 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -22,6 +22,12 @@ LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹ | ^ no implementation for `{float} - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `{float}` + = help: the following implementations were found: + <&'a f32 as Sub> + <&'a f64 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + and 48 others error: aborting due to 3 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index 28c49c33bf6b5..1b87ebd9f20ce 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | enum E where i32: Foo { V } | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -13,6 +14,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | struct S where i32: Foo; | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -22,6 +24,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | trait T where i32: Foo {} | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -31,6 +34,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | union U where i32: Foo { f: i32 } | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -40,6 +44,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | impl Foo for () where i32: Foo { | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -49,6 +54,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied LL | fn f() where i32: Foo | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/src/test/ui/fmt/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr index 6e8dd79219106..5204afa4e6bc5 100644 --- a/src/test/ui/fmt/ifmt-unimpl.stderr +++ b/src/test/ui/fmt/ifmt-unimpl.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied LL | format!("{:X}", "3"); | ^^^ the trait `UpperHex` is not implemented for `str` | + = help: the following other types implement trait `UpperHex`: + &T + &mut T + NonZeroI128 + NonZeroI16 + NonZeroI32 + NonZeroI64 + NonZeroI8 + NonZeroIsize + and 21 others = note: required because of the requirements on the impl of `UpperHex` for `&str` note: required by a bound in `ArgumentV1::<'a>::new_upper_hex` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr index 0b83e9da1ab7a..ec8de15dc3957 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not s LL | test(Foo); | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` | + = help: the trait `for<'a> Marker` is implemented for `()` note: required by a bound in `test` --> $DIR/issue-88460.rs:17:27 | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 804ccbcc6c0ab..6592e234d9873 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -24,6 +24,12 @@ LL | n + sum_to(n - 1) | ^ no implementation for `u32 + impl Foo` | = help: the trait `Add` is not implemented for `u32` + = help: the following implementations were found: + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + + and 48 others error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr index 28068b7548ce5..70d693b8bee95 100644 --- a/src/test/ui/impl-trait/issues/issue-62742.stderr +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied LL | WrongImpl::foo(0i32); | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` | - = help: the following implementations were found: - as Raw<[T]>> + = help: the trait `Raw<[T]>` is implemented for `RawImpl` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 | @@ -40,8 +39,7 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` | - = help: the following implementations were found: - as Raw<[T]>> + = help: the trait `Raw<[T]>` is implemented for `RawImpl` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 | diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr index 776c06b20dfc2..81a75e39c9177 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `Sendable: Duh` is not satisfied LL | fn foo() -> impl Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` --> $DIR/nested-return-type2-tait.rs:14:31 | @@ -21,6 +22,7 @@ LL | | || 42 LL | | } | |_^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` --> $DIR/nested-return-type2-tait.rs:14:31 | diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr index 4993202e2532e..42e65e692488d 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `Sendable: Duh` is not satisfied LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:10]` --> $DIR/nested-return-type2-tait2.rs:14:31 | diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr index efeaf059a3bb2..4d3691d0e07fa 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `impl Send: Duh` is not satisfied LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `impl Send` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:10]` --> $DIR/nested-return-type2-tait3.rs:14:31 | diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr index 5476bf9d27745..6cd63db44fa07 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr @@ -5,6 +5,7 @@ LL | Bar | ^^^ no implementation for `Bar == (Bar, i32)` | = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` + = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` error: aborting due to previous error diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index 78a8f439a71cc..7f51a48111b78 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -5,6 +5,7 @@ LL | x[0i32]; | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec<{integer}>` error: aborting due to previous error diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr index 24f42f22f37df..dae11a702fb73 100644 --- a/src/test/ui/indexing-requires-a-uint.stderr +++ b/src/test/ui/indexing-requires-a-uint.stderr @@ -5,6 +5,7 @@ LL | [0][0u8]; | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[{integer}]` error[E0308]: mismatched types diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr index fcd79d19aac6e..be3398552dc0a 100644 --- a/src/test/ui/integral-indexing.stderr +++ b/src/test/ui/integral-indexing.stderr @@ -5,6 +5,7 @@ LL | v[3u8]; | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `i8` @@ -14,6 +15,7 @@ LL | v[3i8]; | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `u32` @@ -23,6 +25,7 @@ LL | v[3u32]; | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `i32` @@ -32,6 +35,7 @@ LL | v[3i32]; | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[u8]` cannot be indexed by `u8` @@ -41,6 +45,7 @@ LL | s.as_bytes()[3u8]; | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i8` @@ -50,6 +55,7 @@ LL | s.as_bytes()[3i8]; | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `u32` @@ -59,6 +65,7 @@ LL | s.as_bytes()[3u32]; | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i32` @@ -68,6 +75,7 @@ LL | s.as_bytes()[3i32]; | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error: aborting due to 8 previous errors diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr index 9f250925e5080..2b93d4aab27db 100644 --- a/src/test/ui/issues/issue-11771.stderr +++ b/src/test/ui/issues/issue-11771.stderr @@ -5,6 +5,12 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + and 48 others error[E0277]: cannot add `()` to `{integer}` --> $DIR/issue-11771.rs:8:7 @@ -13,6 +19,12 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index 69731bfe7ee7d..f61ff0bda0bbd 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr @@ -5,6 +5,12 @@ LL | 1.0f64 - 1 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | 1.0f64 - 1.0 diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index cd697445faff3..48ae2df691c3d 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -19,6 +19,7 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` + = help: the trait `FromIterator` is implemented for `Vec` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-45801.stderr b/src/test/ui/issues/issue-45801.stderr index 099cf4e383426..8967f49df02a5 100644 --- a/src/test/ui/issues/issue-45801.stderr +++ b/src/test/ui/issues/issue-45801.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Params: Plugin` is not satisfied LL | req.get_ref::(); | ^^^^^^^ the trait `Plugin` is not implemented for `Params` | - = help: the following implementations were found: - > + = help: the trait `Plugin` is implemented for `Params` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 465fb9baac3f0..64bcfcd6016ab 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -14,6 +14,12 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 47fd9fdb65472..55616d2d322ee 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -94,6 +94,12 @@ LL | assert_eq!(Foo::Bar, i); | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` + = help: the following implementations were found: + Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> + and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 6a96709cbacdb..d6e39251632ba 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -5,6 +5,7 @@ LL | let x2: Vec = x1.into_iter().collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -18,6 +19,7 @@ LL | let x3 = x1.into_iter().collect::>(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index e147366a22410..6272c4b702266 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -9,7 +9,7 @@ LL | assert_copy::<&'static mut isize>(); - and 10 others + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 | @@ -27,7 +27,7 @@ LL | assert_copy::<&'a mut isize>(); - and 10 others + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 | diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index 4332bdefcb258..0e1851d292cf9 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -38,6 +38,12 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` + = help: the following implementations were found: + <&'a str as PartialEq> + <&'a str as PartialEq> + <&'b str as PartialEq>> + >> + and 4 others error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -54,6 +60,12 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` + = help: the following implementations were found: + <&'a str as PartialEq> + <&'a str as PartialEq> + <&'b str as PartialEq>> + >> + and 4 others error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 19e921dd04d73..6e67a7b454529 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -5,6 +5,12 @@ LL | 1 + Some(1); | ^ no implementation for `{integer} + Option<{integer}>` | = help: the trait `Add>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + and 48 others error[E0277]: cannot subtract `Option<{integer}>` from `usize` --> $DIR/binops.rs:3:16 @@ -13,6 +19,12 @@ LL | 2 as usize - Some(1); | ^ no implementation for `usize - Option<{integer}>` | = help: the trait `Sub>` is not implemented for `usize` + = help: the following implementations were found: + <&'a usize as Sub> + <&usize as Sub<&usize>> + > + + and 48 others error[E0277]: cannot multiply `{integer}` by `()` --> $DIR/binops.rs:4:7 @@ -21,6 +33,12 @@ LL | 3 * (); | ^ no implementation for `{integer} * ()` | = help: the trait `Mul<()>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Mul> + <&'a f64 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + and 49 others error[E0277]: cannot divide `{integer}` by `&str` --> $DIR/binops.rs:5:7 @@ -29,6 +47,12 @@ LL | 4 / ""; | ^ no implementation for `{integer} / &str` | = help: the trait `Div<&str>` is not implemented for `{integer}` + = help: the following implementations were found: + <&'a f32 as Div> + <&'a f64 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + and 54 others error[E0277]: can't compare `{integer}` with `String` --> $DIR/binops.rs:6:7 @@ -37,6 +61,12 @@ LL | 5 < String::new(); | ^ no implementation for `{integer} < String` and `{integer} > String` | = help: the trait `PartialOrd` is not implemented for `{integer}` + = help: the following implementations were found: + + + + + and 6 others error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` --> $DIR/binops.rs:7:7 @@ -45,6 +75,12 @@ LL | 6 == Ok(1); | ^^ no implementation for `{integer} == Result<{integer}, _>` | = help: the trait `PartialEq>` is not implemented for `{integer}` + = help: the following implementations were found: + + + + + and 6 others error: aborting due to 6 previous errors diff --git a/src/test/ui/never_type/defaulted-never-note.fallback.stderr b/src/test/ui/never_type/defaulted-never-note.fallback.stderr index b105f03f81cdd..4c8b492247352 100644 --- a/src/test/ui/never_type/defaulted-never-note.fallback.stderr +++ b/src/test/ui/never_type/defaulted-never-note.fallback.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfie LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | - = note: this trait is implemented for `()` + = help: the trait `ImplementedForUnitButNotNever` is implemented for `()` = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `foo` diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs index 54f551759cb39..aefc739a0a0b0 100644 --- a/src/test/ui/never_type/defaulted-never-note.rs +++ b/src/test/ui/never_type/defaulted-never-note.rs @@ -30,7 +30,7 @@ fn smeg() { foo(_x); //[fallback]~^ ERROR the trait bound //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented - //[fallback]~| NOTE this trait is implemented for `()` + //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()` //[fallback]~| NOTE this error might have been caused //[fallback]~| HELP did you intend } diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr index 72cd69380573e..dee2b1d704b86 100644 --- a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -4,7 +4,9 @@ error[E0277]: the trait bound `!: Test` is not satisfied LL | unconstrained_arg(return); | ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!` | - = note: this trait is implemented for `()` + = help: the following other types implement trait `Test`: + () + i32 = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `unconstrained_arg` diff --git a/src/test/ui/never_type/impl_trait_fallback2.stderr b/src/test/ui/never_type/impl_trait_fallback2.stderr index 2f50b9d245900..4a78e73e5f6d5 100644 --- a/src/test/ui/never_type/impl_trait_fallback2.stderr +++ b/src/test/ui/never_type/impl_trait_fallback2.stderr @@ -3,6 +3,8 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index b98f6c93923b9..12a6d7962f46b 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr @@ -5,6 +5,12 @@ LL | 2_usize + (loop {}); | ^ no implementation for `usize + ()` | = help: the trait `Add<()>` is not implemented for `usize` + = help: the following implementations were found: + <&'a usize as Add> + <&usize as Add<&usize>> + > + + and 48 others error: aborting due to previous error diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index a14253e384a3a..e2045591390e1 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied LL | >::from(never); | ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E` | - = help: the following implementations were found: - > + = help: the trait `From` is implemented for `E` error: aborting due to previous error diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index ce9a08a15897a..d8bba1509d868 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -5,6 +5,12 @@ LL | x + 100.0 | ^ no implementation for `u8 + {float}` | = help: the trait `Add<{float}>` is not implemented for `u8` + = help: the following implementations were found: + <&'a u8 as Add> + <&u8 as Add<&u8>> + > + + and 48 others error[E0277]: cannot add `&str` to `f64` --> $DIR/not-suggest-float-literal.rs:6:7 @@ -13,6 +19,12 @@ LL | x + "foo" | ^ no implementation for `f64 + &str` | = help: the trait `Add<&str>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + + and 48 others error[E0277]: cannot add `{integer}` to `f64` --> $DIR/not-suggest-float-literal.rs:11:7 @@ -21,6 +33,12 @@ LL | x + y | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + + and 48 others error[E0277]: cannot subtract `{float}` from `u8` --> $DIR/not-suggest-float-literal.rs:15:7 @@ -29,6 +47,12 @@ LL | x - 100.0 | ^ no implementation for `u8 - {float}` | = help: the trait `Sub<{float}>` is not implemented for `u8` + = help: the following implementations were found: + <&'a u8 as Sub> + <&u8 as Sub<&u8>> + > + + and 48 others error[E0277]: cannot subtract `&str` from `f64` --> $DIR/not-suggest-float-literal.rs:19:7 @@ -37,6 +61,12 @@ LL | x - "foo" | ^ no implementation for `f64 - &str` | = help: the trait `Sub<&str>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + and 48 others error[E0277]: cannot subtract `{integer}` from `f64` --> $DIR/not-suggest-float-literal.rs:24:7 @@ -45,6 +75,12 @@ LL | x - y | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + and 48 others error[E0277]: cannot multiply `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:28:7 @@ -53,6 +89,12 @@ LL | x * 100.0 | ^ no implementation for `u8 * {float}` | = help: the trait `Mul<{float}>` is not implemented for `u8` + = help: the following implementations were found: + <&'a u8 as Mul> + <&u8 as Mul<&u8>> + > + + and 49 others error[E0277]: cannot multiply `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:32:7 @@ -61,6 +103,12 @@ LL | x * "foo" | ^ no implementation for `f64 * &str` | = help: the trait `Mul<&str>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + + and 49 others error[E0277]: cannot multiply `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:37:7 @@ -69,6 +117,12 @@ LL | x * y | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + + and 49 others error[E0277]: cannot divide `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:41:7 @@ -77,6 +131,12 @@ LL | x / 100.0 | ^ no implementation for `u8 / {float}` | = help: the trait `Div<{float}>` is not implemented for `u8` + = help: the following implementations were found: + <&'a u8 as Div> + <&u8 as Div<&u8>> + > + > + and 54 others error[E0277]: cannot divide `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:45:7 @@ -85,6 +145,12 @@ LL | x / "foo" | ^ no implementation for `f64 / &str` | = help: the trait `Div<&str>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + + and 54 others error[E0277]: cannot divide `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:50:7 @@ -93,6 +159,12 @@ LL | x / y | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + + and 54 others error: aborting due to 12 previous errors diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index eb0be785061e6..b7591dfca99b3 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -5,6 +5,12 @@ LL | x + 100 | ^ no implementation for `f32 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f32` + = help: the following implementations were found: + <&'a f32 as Add> + <&f32 as Add<&f32>> + > + + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -17,6 +23,12 @@ LL | x + 100 | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -29,6 +41,12 @@ LL | x - 100 | ^ no implementation for `f32 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f32` + = help: the following implementations were found: + <&'a f32 as Sub> + <&f32 as Sub<&f32>> + > + + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -41,6 +59,12 @@ LL | x - 100 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -53,6 +77,12 @@ LL | x * 100 | ^ no implementation for `f32 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f32` + = help: the following implementations were found: + <&'a f32 as Mul> + <&f32 as Mul<&f32>> + > + + and 49 others help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -65,6 +95,12 @@ LL | x * 100 | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + + and 49 others help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -77,6 +113,12 @@ LL | x / 100 | ^ no implementation for `f32 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f32` + = help: the following implementations were found: + <&'a f32 as Div> + <&f32 as Div<&f32>> + > + + and 54 others help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 @@ -89,6 +131,12 @@ LL | x / 100 | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following implementations were found: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + + and 54 others help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 diff --git a/src/test/ui/on-unimplemented/impl-substs.stderr b/src/test/ui/on-unimplemented/impl-substs.stderr index db66ab0bfaec1..a0fad0acd0b5c 100644 --- a/src/test/ui/on-unimplemented/impl-substs.stderr +++ b/src/test/ui/on-unimplemented/impl-substs.stderr @@ -7,6 +7,7 @@ LL | Foo::::foo((1i32, 1i32, 1i32)); | required by a bound introduced by this call | = help: the trait `Foo` is not implemented for `(i32, i32, i32)` + = help: the trait `Foo` is implemented for `(A, B, C)` error: aborting due to previous error diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 76aa128e242f9..be29d31d97b8e 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -7,6 +7,9 @@ LL | Index::index(&[] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:18 @@ -17,6 +20,9 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:18 @@ -27,6 +33,9 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 @@ -35,6 +44,9 @@ LL | Index::index(&[] as &[i32], 2u32); | ^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:5 @@ -43,6 +55,9 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:5 @@ -51,6 +66,9 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` + = help: the following implementations were found: + <[i32] as Index>> + <[i32] as Index>> error: aborting due to 6 previous errors diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 940763fae51b8..769a3d77a5726 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -7,6 +7,7 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 @@ -15,6 +16,7 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` error: aborting due to 2 previous errors diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index 44b8b0d8d8444..6dc27b5d4cc56 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -5,6 +5,7 @@ LL | x[1i32]; | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[i32]` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` @@ -14,6 +15,9 @@ LL | x[..1i32]; | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` + = help: the following implementations were found: + as SliceIndex<[T]>> + as SliceIndex> = note: required because of the requirements on the impl of `Index>` for `[i32]` error: aborting due to 2 previous errors diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index 2ce4e1553d28e..0bbed8704243f 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -10,6 +10,16 @@ error[E0277]: the trait bound `bool: Step` is not satisfied LL | for i in false..true {} | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` | + = help: the following other types implement trait `Step`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range` = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range` diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index f8eaf61d7d7ec..d87eceb1c9a7b 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -9,6 +9,10 @@ LL | | } | |_^ `main` can only return types that implement `Termination` | = help: the trait `Termination` is not implemented for `Result` + = help: the following implementations were found: + as Termination> + as Termination> + as Termination> note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL | diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 13ef0d1820881..1542832f0129c 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -5,6 +5,12 @@ LL | foo(1 as u32 + | ^ no implementation for `u32 + ()` | = help: the trait `Add<()>` is not implemented for `u32` + = help: the following implementations were found: + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + + and 48 others error: aborting due to previous error diff --git a/src/test/ui/specialization/default-associated-type-bound-1.stderr b/src/test/ui/specialization/default-associated-type-bound-1.stderr index f88acfb2e793e..af9f2f7c2e9a6 100644 --- a/src/test/ui/specialization/default-associated-type-bound-1.stderr +++ b/src/test/ui/specialization/default-associated-type-bound-1.stderr @@ -14,8 +14,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | default type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::U` --> $DIR/default-associated-type-bound-1.rs:8:13 | diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 9ab409bbdcdf8..45450788b9cbd 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -7,6 +7,7 @@ LL | let _: u8 = s[4]; = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<{integer}>` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -20,6 +21,7 @@ LL | let _ = s.get(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | @@ -37,6 +39,7 @@ LL | let _ = s.get_unchecked(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 5956e363b0c09..9ae085630279e 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -31,6 +31,7 @@ LL | s[1usize] = bot(); | ^^^^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -44,6 +45,7 @@ LL | s.get_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | @@ -61,6 +63,7 @@ LL | s.get_unchecked_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr index 64a62524653b7..0783f04dc9bd3 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied LL | foo::(s); | ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S` | - = help: the following implementations were found: - <&'a mut S as Trait> + = help: the trait `Trait` is implemented for `&'a mut S` note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20 | diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr index 001af27b2484e..5f3f62a7b7570 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -6,8 +6,7 @@ LL | foo(&s); | | | required by a bound introduced by this call | - = help: the following implementations were found: - <&'a mut S as Trait> + = help: the trait `Trait` is implemented for `&'a mut S` note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal.rs:7:11 | diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index ba6967e78e163..0de765588e5b7 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -15,6 +15,8 @@ LL | | 5; LL | | LL | | } | |_^ the trait `Bar` is not implemented for `()` + | + = help: the trait `Bar` is implemented for `u8` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 470c0bfcf73e5..4bdea05b06b8d 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -12,7 +12,6 @@ LL | foo(String::new()); > > >> - and 2 others = note: required because of the requirements on the impl of `Into<&str>` for `String` note: required by a bound in `foo` --> $DIR/into-str.rs:1:31 diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr index bacab64e2642c..15559d4ae2c2f 100644 --- a/src/test/ui/suggestions/issue-84973-negative.stderr +++ b/src/test/ui/suggestions/issue-84973-negative.stderr @@ -6,8 +6,7 @@ LL | bar(a); | | | required by a bound introduced by this call | - = help: the following implementations were found: - <&f32 as Tr> + = help: the trait `Tr` is implemented for `&f32` note: required by a bound in `bar` --> $DIR/issue-84973-negative.rs:5:11 | diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr index 907a1bd75a064..bfbbe7fd25702 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | f::>(); | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-1.rs:7:9 | diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr index b27f8d791a50f..3ca36d5d2ff19 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied LL | f::>(); | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-4.rs:10:9 | diff --git a/src/test/ui/traits/bound/same-crate-name.rs b/src/test/ui/traits/bound/same-crate-name.rs index 1012edb109336..8d646a414599c 100644 --- a/src/test/ui/traits/bound/same-crate-name.rs +++ b/src/test/ui/traits/bound/same-crate-name.rs @@ -50,6 +50,6 @@ fn main() { // impls for the correct trait where the path is not misleading. a::try_foo(other_variant_implements_correct_trait); //~^ ERROR E0277 - //~| the following implementations were found: + //~| the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` } } diff --git a/src/test/ui/traits/bound/same-crate-name.stderr b/src/test/ui/traits/bound/same-crate-name.stderr index 81e5589d6eb35..ef39a70066db6 100644 --- a/src/test/ui/traits/bound/same-crate-name.stderr +++ b/src/test/ui/traits/bound/same-crate-name.stderr @@ -12,6 +12,7 @@ help: trait impl with same name found LL | impl Bar for Foo {} | ^^^^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -26,6 +27,7 @@ LL | a::try_foo(implements_no_traits); | | | required by a bound introduced by this call | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -46,6 +48,7 @@ help: trait impl with same name found LL | impl Bar for ImplementsWrongTraitConditionally {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -60,8 +63,7 @@ LL | a::try_foo(other_variant_implements_correct_trait); | | | required by a bound introduced by this call | - = help: the following implementations were found: - as main::a::Bar> + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | diff --git a/src/test/ui/traits/coercion-generic-bad.stderr b/src/test/ui/traits/coercion-generic-bad.stderr index f367d396da0c2..b213ee635df59 100644 --- a/src/test/ui/traits/coercion-generic-bad.stderr +++ b/src/test/ui/traits/coercion-generic-bad.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Struct: Trait` is not satisfied LL | let s: Box> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` | - = help: the following implementations were found: - > + = help: the trait `Trait<&'static str>` is implemented for `Struct` = note: required for the cast to the object type `dyn Trait` error: aborting due to previous error diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 2bff84363e9e5..3645ad03cb9bb 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -3,6 +3,8 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi | LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` + | + = help: the trait `CompareTo` is implemented for `i64` error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:30:7 @@ -20,6 +22,8 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi | LL | ::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` + | + = help: the trait `CompareTo` is implemented for `i64` error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:38:5 diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr index 10298a0c7037a..f2b3de13beb9e 100644 --- a/src/test/ui/traits/issue-91594.stderr +++ b/src/test/ui/traits/issue-91594.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied LL | impl HasComponent<>::Interface> for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | - = help: the following implementations were found: - >::Interface>> + = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required because of the requirements on the impl of `Component` for `Foo` --> $DIR/issue-91594.rs:13:27 | diff --git a/src/test/ui/traits/map-types.stderr b/src/test/ui/traits/map-types.stderr index 71006e1f4e2d8..37bc5c6badc41 100644 --- a/src/test/ui/traits/map-types.stderr +++ b/src/test/ui/traits/map-types.stderr @@ -4,6 +4,7 @@ error[E0277]: the trait bound `Box>: Map` is LL | let y: Box> = Box::new(x); | ^^^^^^^^^^^ the trait `Map` is not implemented for `Box>` | + = help: the trait `Map` is implemented for `HashMap` = note: required for the cast to the object type `dyn Map` error: aborting due to previous error diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr index 3d5bf3448bd5d..cefb2a8792f17 100644 --- a/src/test/ui/traits/reservation-impl/no-use.stderr +++ b/src/test/ui/traits/reservation-impl/no-use.stderr @@ -6,8 +6,7 @@ LL | <() as MyTrait>::foo(&()); | | | required by a bound introduced by this call | - = help: the following implementations were found: - <() as MyTrait> + = help: the trait `MyTrait` is implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr index 299219431ef11..b77af7ddf4746 100644 --- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr @@ -8,8 +8,6 @@ LL | takes_type_parameter(&string); // Error | | help: consider adding dereference here: `&*string` | required by a bound introduced by this call | - = help: the following implementations were found: - <&str as SomeTrait> note: required by a bound in `takes_type_parameter` --> $DIR/issue-62530.rs:4:44 | diff --git a/src/test/ui/traits/suggest-deferences/multiple-1.stderr b/src/test/ui/traits/suggest-deferences/multiple-1.stderr index 040fbb3e3e699..6e12321c2333b 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-1.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-1.stderr @@ -6,6 +6,7 @@ LL | foo(&mut baz); | | | required by a bound introduced by this call | + = help: the trait `Happy` is implemented for `&mut LDM` note: required by a bound in `foo` --> $DIR/multiple-1.rs:45:26 | diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index cf3a07808de68..f9906713f8427 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -5,8 +5,7 @@ LL | Err("")?; | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following implementations were found: - > + = help: the trait `From` is implemented for `TryFromSliceError` = note: required because of the requirements on the impl of `FromResidual>` for `Result` error[E0271]: type mismatch resolving ` as Try>::Output == &str` diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 171051156b7f2..fc2692a9a9313 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -12,7 +12,7 @@ LL | Ok(Err(123_i32)?) > > > - and 71 others + and 67 others = note: required because of the requirements on the impl of `FromResidual>` for `Result` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` @@ -27,6 +27,7 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` + = help: the trait `FromResidual>` is implemented for `Result` error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` --> $DIR/bad-interconversion.rs:17:31 @@ -39,6 +40,7 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` + = help: the trait `FromResidual>` is implemented for `Result` error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/bad-interconversion.rs:22:22 @@ -51,6 +53,7 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` + = help: the trait `FromResidual` is implemented for `Option` error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` --> $DIR/bad-interconversion.rs:27:33 @@ -63,6 +66,7 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` + = help: the trait `FromResidual` is implemented for `Option` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:32:39 @@ -75,6 +79,7 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:37:12 @@ -88,6 +93,7 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` error[E0277]: the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s (with the same Break type) --> $DIR/bad-interconversion.rs:43:29 @@ -102,6 +108,7 @@ LL | | } | = help: the trait `FromResidual>` is not implemented for `ControlFlow` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` error: aborting due to 8 previous errors diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr index aadfbf61f28f8..b0e4de8cb4bf5 100644 --- a/src/test/ui/try-trait/option-to-result.stderr +++ b/src/test/ui/try-trait/option-to-result.stderr @@ -10,6 +10,7 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` + = help: the trait `FromResidual>` is implemented for `Result` error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/option-to-result.rs:11:6 @@ -23,6 +24,7 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` + = help: the trait `FromResidual` is implemented for `Option` error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index 24db9f5243703..7b2a9a16f900b 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -10,6 +10,7 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` + = help: the trait `FromResidual>` is implemented for `Result` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option.rs:11:6 diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 5fec078956bfc..d0c04371bd793 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -13,8 +13,7 @@ error[E0277]: the trait bound `(): Bug` is not satisfied LL | const FUN: fn() -> Self::Item = || (); | ^^ the trait `Bug` is not implemented for `()` | - = help: the following implementations were found: - <&() as Bug> + = help: the trait `Bug` is implemented for `&()` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr index eb72e88769100..0df2b57d373b6 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | - = help: the following implementations were found: - <() as Foo<()>> + = help: the trait `Foo<()>` is implemented for `()` error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/nested-tait-inference.rs:12:28 @@ -19,8 +18,7 @@ LL | | () LL | | } | |_^ the trait `Foo` is not implemented for `()` | - = help: the following implementations were found: - <() as Foo<()>> + = help: the trait `Foo<()>` is implemented for `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr index 6997676260dd6..b93ded6a7d3e1 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -5,6 +5,12 @@ LL | 42_i32 | ^^^^^^ no implementation for `i32 == Foo` | = help: the trait `PartialEq` is not implemented for `i32` + = help: the following implementations were found: + + + + + and 6 others error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr index 4a6ee2f9279d1..23ca689019634 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -5,6 +5,12 @@ LL | i | ^ no implementation for `&i32 == Bar<'b, 'static>` | = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` --> $DIR/self-referential-4.rs:12:5 @@ -13,6 +19,12 @@ LL | i | ^ no implementation for `&i32 == Foo<'static, 'b>` | = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` --> $DIR/self-referential-4.rs:18:5 @@ -21,6 +33,12 @@ LL | i | ^ no implementation for `&i32 == Moo<'static, 'a>` | = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 0626e6be0d5a5..4384bc9b98a7c 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -5,6 +5,12 @@ LL | i | ^ no implementation for `&i32 == Bar<'b, 'a>` | = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error[E0277]: can't compare `&i32` with `(i32, &i32)` --> $DIR/self-referential.rs:12:10 @@ -13,6 +19,12 @@ LL | (42, i) | ^ no implementation for `&i32 == (i32, &i32)` | = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` --> $DIR/self-referential.rs:18:10 @@ -21,6 +33,12 @@ LL | (42, i) | ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` | = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + = help: the following implementations were found: + + + + + and 6 others error: aborting due to 3 previous errors diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 2a61547997b63..80ff068ff309a 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -65,6 +65,12 @@ LL | trait ProjectionPred> where T::Item : Add {} | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add` is not implemented for `i32` + = help: the following implementations were found: + <&'a i32 as Add> + <&i32 as Add<&i32>> + > + + and 48 others error: aborting due to 7 previous errors diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index c545a563b0d0a..0a5ec56e91512 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -20,6 +20,12 @@ LL | a = c + b * 5; | ^ no implementation for `usize + u16` | = help: the trait `Add` is not implemented for `usize` + = help: the following implementations were found: + <&'a usize as Add> + <&usize as Add<&usize>> + > + + and 48 others error: aborting due to 3 previous errors diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index d0bc432a1cd18..c769a0df7c891 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,6 +5,12 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` + = help: the following implementations were found: + <&'a i32 as Add> + <&i32 as Add<&i32>> + > + + and 48 others error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index 03932d5ed0347..5e67b2c44f2be 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -4,8 +4,7 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied LL | <[(); 0] as Foo>::foo() | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | - = help: the following implementations were found: - <[(); 1] as Foo> + = help: the trait `Foo` is implemented for `[(); 1]` error: aborting due to previous error diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr index 0d9b9627562f9..037f8b9f33770 100644 --- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr +++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr @@ -5,6 +5,7 @@ LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL @@ -19,6 +20,7 @@ LL | fn into_iter(self) -> Self::IntoIter { | ^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL From ac8cbbd200cfa77f03a8560f0305810e4f8f1375 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sat, 26 Mar 2022 21:26:02 +0000 Subject: [PATCH 09/16] Fix #90970, doesn't address #87437 --- .../src/traits/error_reporting/mod.rs | 79 +++++++++++++++++-- .../generic_const_exprs/issue-85848.stderr | 1 + .../cross-return-site-inference.stderr | 1 + .../ui/impl-trait/nested_impl_trait.stderr | 2 + src/test/ui/issues/issue-32709.stderr | 1 + .../ui/kindck/kindck-impl-type-params.stderr | 2 + .../bound/assoc-fn-bound-root-obligation.rs | 12 +++ .../assoc-fn-bound-root-obligation.stderr | 23 ++++++ 8 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs create mode 100644 src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 2da4c86a58e9c..65e2554a6f223 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2,10 +2,11 @@ pub mod on_unimplemented; pub mod suggestions; use super::{ - EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError, + FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation, + ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, + OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, + TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -654,11 +655,77 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else if !suggested { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates( + if !self.report_similar_impl_candidates( impl_candidates, trait_ref, &mut err, - ); + ) { + // This is *almost* equivalent to + // `obligation.cause.code().peel_derives()`, but it gives us the + // trait predicate for that corresponding root obligation. This + // lets us get a derived obligation from a type parameter, like + // when calling `string.strip_suffix(p)` where `p` is *not* an + // implementer of `Pattern<'_>`. + let mut code = obligation.cause.code(); + let mut trait_pred = trait_predicate; + let mut peeled = false; + loop { + match &*code { + ObligationCauseCode::FunctionArgumentObligation { + parent_code, + .. + } => { + code = &parent_code; + } + ObligationCauseCode::ImplDerivedObligation( + box ImplDerivedObligationCause { + derived: + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + .. + }, + ) + | ObligationCauseCode::BuiltinDerivedObligation( + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + ) + | ObligationCauseCode::DerivedObligation( + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + ) => { + peeled = true; + code = &parent_code; + trait_pred = *parent_trait_pred; + } + _ => break, + }; + } + let def_id = trait_pred.def_id(); + // Mention *all* the `impl`s for the *top most* obligation, the + // user might have meant to use one of them, if any found. We skip + // auto-traits or fundamental traits that might not be exactly what + // the user might expect to be presented with. Instead this is + // useful for less general traits. + if peeled + && !self.tcx.trait_is_auto(def_id) + && !self.tcx.lang_items().items().contains(&Some(def_id)) + { + let trait_ref = trait_pred.to_poly_trait_ref(); + let impl_candidates = + self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates( + impl_candidates, + trait_ref, + &mut err, + ); + } + } } // Changing mutability doesn't make a difference to whether we have diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr index 4202cbae7eb29..27f5dce9fb266 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -6,6 +6,7 @@ LL | writes_to_specific_path(&cap); | | | required by a bound introduced by this call | + = help: the trait `Delegates` is implemented for `T` note: required because of the requirements on the impl of `Contains<(), true>` for `&C` --> $DIR/issue-85848.rs:21:12 | diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr index 06afb938c5fad..d458c7be783d5 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.stderr +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr @@ -7,6 +7,7 @@ LL | Err("whoops")?; | ^ the trait `From<&str>` is not implemented for `impl Debug` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `FromResidual>` is implemented for `Result` = note: required because of the requirements on the impl of `FromResidual>` for `Result<(), impl Debug>` error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 26b48c7cdf718..bb4ae5e828254 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -52,6 +52,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` | + = help: the trait `Into` is implemented for `T` = note: required because of the requirements on the impl of `Into` for `impl Into` error[E0277]: the trait bound `impl Debug: From>` is not satisfied @@ -60,6 +61,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie LL | fn bad(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` | + = help: the trait `Into` is implemented for `T` = note: required because of the requirements on the impl of `Into` for `impl Into` error: aborting due to 8 previous errors diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index b4c3f148e32b5..ed5addcbec517 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,6 +7,7 @@ LL | Err(5)?; | ^ the trait `From<{integer}>` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `FromResidual>` is implemented for `Result` = note: required because of the requirements on the impl of `FromResidual>` for `Result` error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index 3558f0c9e6294..64bbc841b330f 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -80,6 +80,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | let a = t as Box>; | ^ the trait `Copy` is not implemented for `String` | + = help: the trait `Gettable` is implemented for `S` note: required because of the requirements on the impl of `Gettable` for `S` --> $DIR/kindck-impl-type-params.rs:14:32 | @@ -93,6 +94,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | let a: Box> = t; | ^ the trait `Copy` is not implemented for `Foo` | + = help: the trait `Gettable` is implemented for `S` note: required because of the requirements on the impl of `Gettable` for `S` --> $DIR/kindck-impl-type-params.rs:14:32 | diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs new file mode 100644 index 0000000000000..2720f94a3c191 --- /dev/null +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs @@ -0,0 +1,12 @@ +fn strip_lf(s: &str) -> &str { + s.strip_suffix(b'\n').unwrap_or(s) + //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8` + //~| NOTE expected an `FnMut<(char,)>` closure, found `u8` + //~| NOTE required by a bound introduced by this call + //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` + //~| HELP the following other types implement trait `Pattern<'_>`: + //~| NOTE required because of the requirements on the impl of `Pattern<'_>` for `u8` + +} + +fn main() {} diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr new file mode 100644 index 0000000000000..37cba4189d725 --- /dev/null +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -0,0 +1,23 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `u8` + --> $DIR/assoc-fn-bound-root-obligation.rs:2:20 + | +LL | s.strip_suffix(b'\n').unwrap_or(s) + | ------------ ^^^^^ expected an `FnMut<(char,)>` closure, found `u8` + | | + | required by a bound introduced by this call + | + = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the following other types implement trait `Pattern<'_>`: + &'b String + &'b [char; N] + &'b [char] + &'b str + &'c &'b str + [char; N] + char + pattern::MultiCharEqPattern + = note: required because of the requirements on the impl of `Pattern<'_>` for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 883b93c7b7eb02ec85f4b8f9fb129efc403d4fb2 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sat, 26 Mar 2022 23:01:29 +0000 Subject: [PATCH 10/16] Suggest dereferncing when possible in E0277, fix #87437 --- .../src/traits/error_reporting/suggestions.rs | 104 +++++++++++------- .../suggest-deferences/issue-39029.stderr | 2 +- .../suggest-deferences/issue-62530.stderr | 2 +- .../suggest-deferences/multiple-0.stderr | 2 +- .../suggest-deferences/root-obligation.fixed | 14 +++ .../suggest-deferences/root-obligation.rs | 14 +++ .../suggest-deferences/root-obligation.stderr | 24 ++++ 7 files changed, 121 insertions(+), 41 deletions(-) create mode 100644 src/test/ui/traits/suggest-deferences/root-obligation.fixed create mode 100644 src/test/ui/traits/suggest-deferences/root-obligation.rs create mode 100644 src/test/ui/traits/suggest-deferences/root-obligation.stderr 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 5bf9be87b57ae..b369c73387198 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1,6 +1,6 @@ use super::{ - EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, - SelectionContext, + DerivedObligationCause, EvaluationResult, ImplDerivedObligationCause, Obligation, + ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, }; use crate::autoderef::Autoderef; @@ -496,50 +496,78 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { // It only make sense when suggesting dereferences for arguments - let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - obligation.cause.code() - { - parent_code.clone() - } else { + let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else { return false; }; let param_env = obligation.param_env; let body_id = obligation.cause.body_id; let span = obligation.cause.span; - let real_trait_pred = match &*code { - ObligationCauseCode::ImplDerivedObligation(cause) => cause.derived.parent_trait_pred, - ObligationCauseCode::DerivedObligation(cause) - | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred, - _ => trait_pred, - }; - let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { - return false; - }; + let mut real_trait_pred = trait_pred; + let mut code = obligation.cause.code(); + loop { + match &code { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { + code = &parent_code; + } + ObligationCauseCode::ImplDerivedObligation(box ImplDerivedObligationCause { + derived: DerivedObligationCause { parent_code, parent_trait_pred }, + .. + }) + | ObligationCauseCode::BuiltinDerivedObligation(DerivedObligationCause { + parent_code, + parent_trait_pred, + }) + | ObligationCauseCode::DerivedObligation(DerivedObligationCause { + parent_code, + parent_trait_pred, + }) => { + code = &parent_code; + real_trait_pred = *parent_trait_pred; + } + _ => break, + }; + let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { + continue; + }; - if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { - let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); - if let Some(steps) = autoderef.find_map(|(ty, steps)| { - // Re-add the `&` - let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); - let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); - Some(steps).filter(|_| self.predicate_may_hold(&obligation)) - }) { - if steps > 0 { - if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { - // Don't care about `&mut` because `DerefMut` is used less - // often and user will not expect autoderef happens. - if src.starts_with('&') && !src.starts_with("&mut ") { - let derefs = "*".repeat(steps); - err.span_suggestion( - span, - "consider adding dereference here", - format!("&{}{}", derefs, &src[1..]), - Applicability::MachineApplicable, - ); - return true; + if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { + let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); + if let Some(steps) = autoderef.find_map(|(ty, steps)| { + // Re-add the `&` + let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); + Some(steps).filter(|_| self.predicate_may_hold(&obligation)) + }) { + if steps > 0 { + if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { + // Don't care about `&mut` because `DerefMut` is used less + // often and user will not expect autoderef happens. + if src.starts_with('&') && !src.starts_with("&mut ") { + let derefs = "*".repeat(steps); + err.span_suggestion( + span, + "consider dereferencing here", + format!("&{}{}", derefs, &src[1..]), + Applicability::MachineApplicable, + ); + return true; + } } } + } else if real_trait_pred != trait_pred { + // This branch addresses #87437. + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, base_ty); + if self.predicate_may_hold(&obligation) { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "consider dereferencing here", + "*".to_string(), + Applicability::MachineApplicable, + ); + return true; + } } } } diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr index 2c225f4311d01..5c324cd38a3ab 100644 --- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr @@ -5,7 +5,7 @@ LL | let _errors = TcpListener::bind(&bad); | ----------------- ^^^^ | | | | | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` - | | help: consider adding dereference here: `&*bad` + | | help: consider dereferencing here: `&*bad` | required by a bound introduced by this call | = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs` diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr index b77af7ddf4746..d129328dae8ef 100644 --- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr @@ -5,7 +5,7 @@ LL | takes_type_parameter(&string); // Error | -------------------- ^^^^^^^ | | | | | the trait `SomeTrait` is not implemented for `&String` - | | help: consider adding dereference here: `&*string` + | | help: consider dereferencing here: `&*string` | required by a bound introduced by this call | note: required by a bound in `takes_type_parameter` diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr index bf9f85f1b4595..efb3c7d123f70 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr @@ -5,7 +5,7 @@ LL | foo(&baz); | --- ^^^^ | | | | | the trait `Happy` is not implemented for `&Baz` - | | help: consider adding dereference here: `&***baz` + | | help: consider dereferencing here: `&***baz` | required by a bound introduced by this call | note: required by a bound in `foo` diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.fixed b/src/test/ui/traits/suggest-deferences/root-obligation.fixed new file mode 100644 index 0000000000000..9fd1924067827 --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(*c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} + diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.rs b/src/test/ui/traits/suggest-deferences/root-obligation.rs new file mode 100644 index 0000000000000..4dd0291b62970 --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.rs @@ -0,0 +1,14 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} + diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.stderr b/src/test/ui/traits/suggest-deferences/root-obligation.stderr new file mode 100644 index 0000000000000..16e03e79c7571 --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.stderr @@ -0,0 +1,24 @@ +error[E0277]: expected a `Fn<(char,)>` closure, found `char` + --> $DIR/root-obligation.rs:6:38 + | +LL | .filter(|c| "aeiou".contains(c)) + | -------- ^ expected an `Fn<(char,)>` closure, found `char` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(char,)>` is not implemented for `char` + = note: required because of the requirements on the impl of `FnOnce<(char,)>` for `&char` + = note: required because of the requirements on the impl of `Pattern<'_>` for `&char` +note: required by a bound in `core::str::::contains` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + | ^^^^^^^^^^^ required by this bound in `core::str::::contains` +help: consider dereferencing here + | +LL | .filter(|c| "aeiou".contains(*c)) + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From e2bba0708a1e4b0c21f94de56c2bd5d66d3b825f Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sat, 26 Mar 2022 23:14:47 +0000 Subject: [PATCH 11/16] Fix list length --- .../src/traits/error_reporting/mod.rs | 2 +- src/test/ui/binop/binop-mul-i32-f32.stderr | 4 ++ src/test/ui/binop/issue-77910-1.stderr | 4 ++ .../ui/binop/shift-various-bad-types.stderr | 12 +++++ .../ui/const-generics/exhaustive-value.stderr | 4 ++ .../const-eval/const-eval-overflow-3b.stderr | 4 ++ .../const-eval/const-eval-overflow-4b.stderr | 4 ++ .../ui/consts/too_generic_eval_ice.stderr | 4 ++ ...e-21659-show-relevant-trait-impls-2.stderr | 2 + .../issue-39802-show-5-trait-impls.stderr | 12 +++++ ...de-confusable-in-float-literal-expt.stderr | 4 ++ src/test/ui/impl-trait/equality.stderr | 4 ++ src/test/ui/issues/issue-11771.stderr | 8 ++++ src/test/ui/issues/issue-24352.stderr | 4 ++ src/test/ui/issues/issue-50582.stderr | 4 ++ src/test/ui/issues/issue-59488.stderr | 4 ++ src/test/ui/kindck/kindck-copy.stderr | 8 ++++ .../ui/lexer/lex-bad-char-literals-6.stderr | 8 ++++ src/test/ui/mismatched_types/binops.stderr | 24 ++++++++++ src/test/ui/never_type/issue-13352.stderr | 4 ++ .../not-suggest-float-literal.stderr | 48 +++++++++++++++++++ .../suggest-float-literal.stderr | 32 +++++++++++++ src/test/ui/span/multiline-span-simple.stderr | 4 ++ src/test/ui/suggestions/into-str.stderr | 2 + .../ui/try-trait/bad-interconversion.stderr | 4 ++ src/test/ui/type/type-check-defaults.stderr | 4 ++ src/test/ui/typeck/issue-81293.stderr | 4 ++ .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 4 ++ 28 files changed, 225 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 65e2554a6f223..fdafb2d3d417e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1813,7 +1813,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; + let end = if impl_candidates.len() <= 9 { impl_candidates.len() } else { 8 }; let normalize = |candidate| { self.tcx.infer_ctxt().enter(|ref infcx| { diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 9fcf5d72625c5..715e52b41e75c 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr @@ -10,6 +10,10 @@ LL | x * y <&i32 as Mul<&i32>> > + <&'a f32 as Mul> + <&'a f64 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> and 49 others error: aborting due to previous error diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index 9553fcc5bb204..16b06a0198b27 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -21,6 +21,10 @@ LL | assert_eq!(foo, y); Ret as Debug> Ret as Debug> Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/binop/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr index e134095e63879..8fdb377751c24 100644 --- a/src/test/ui/binop/shift-various-bad-types.stderr +++ b/src/test/ui/binop/shift-various-bad-types.stderr @@ -10,6 +10,10 @@ LL | 22 >> p.char; <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> and 568 others error[E0277]: no implementation for `{integer} >> &str` @@ -24,6 +28,10 @@ LL | 22 >> p.str; <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> and 568 others error[E0277]: no implementation for `{integer} >> &Panolpy` @@ -38,6 +46,10 @@ LL | 22 >> p; <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> and 568 others error[E0308]: mismatched types diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index cb85b6cb93d91..fcbb41bb4fcc4 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -9,6 +9,10 @@ LL | <() as Foo>::test() <() as Foo<100_u8>> <() as Foo<101_u8>> <() as Foo<102_u8>> + <() as Foo<103_u8>> + <() as Foo<104_u8>> + <() as Foo<105_u8>> + <() as Foo<106_u8>> and 248 others error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index aee7192b6eda1..d2d68506d4e1c 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -16,6 +16,10 @@ LL | = [0; (i8::MAX + 1u8) as usize]; <&i8 as Add<&i8>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index 059447f7cacb3..818e3bc15b19d 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -16,6 +16,10 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] <&i8 as Add<&i8>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error[E0604]: only `u8` can be cast as `char`, not `i8` diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 677fa7d21aef0..45459b931caac 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -26,6 +26,10 @@ LL | [5; Self::HOST_SIZE] == [6; 0] <&[T] as PartialEq>> <&mut [B] as PartialEq<[A; N]>> <&mut [T] as PartialEq>> + <[A; N] as PartialEq<&[B]>> + <[A; N] as PartialEq<&mut [B]>> + <[A; N] as PartialEq<[B; N]>> + <[A; N] as PartialEq<[B]>> and 3 others error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index ea461241bf414..f25c7ce00e548 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -9,6 +9,8 @@ LL | f1.foo(1usize); > > > + > + > error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 58faaf4ea9014..3aa863e900f4a 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -11,6 +11,11 @@ LL | Foo::::bar(&1i8); > > > + > + > + > + > + > error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -25,6 +30,11 @@ LL | Foo::::bar(&1u8); > > > + > + > + > + > + > error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 @@ -39,6 +49,8 @@ LL | Foo::::bar(&true); > > > + > + > error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index c12b02a76c58a..bd9d9e086e044 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -27,6 +27,10 @@ LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹ <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> + <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 6592e234d9873..9137183375aca 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -29,6 +29,10 @@ LL | n + sum_to(n - 1) <&u32 as Add<&u32>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr index 2b93d4aab27db..019677775987e 100644 --- a/src/test/ui/issues/issue-11771.stderr +++ b/src/test/ui/issues/issue-11771.stderr @@ -10,6 +10,10 @@ LL | 1 + <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0277]: cannot add `()` to `{integer}` @@ -24,6 +28,10 @@ LL | 1 + <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index f61ff0bda0bbd..364fbbc981e64 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr @@ -10,6 +10,10 @@ LL | 1.0f64 - 1 <&f64 as Sub<&f64>> > + <&'a f32 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 64bcfcd6016ab..a1e614807de4a 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -19,6 +19,10 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 55616d2d322ee..c61d44bf89526 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -99,6 +99,10 @@ LL | assert_eq!(Foo::Bar, i); Ret as Debug> Ret as Debug> Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> + Ret as Debug> and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index 6272c4b702266..29c9b872b5816 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -9,6 +9,10 @@ LL | assert_copy::<&'static mut isize>(); + + + + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 @@ -27,6 +31,10 @@ LL | assert_copy::<&'a mut isize>(); + + + + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index 0e1851d292cf9..9df6c92d1e578 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -43,6 +43,10 @@ LL | if x == y {} <&'a str as PartialEq> <&'b str as PartialEq>> >> + > + > + > + and 4 others error[E0308]: mismatched types @@ -65,6 +69,10 @@ LL | if x == z {} <&'a str as PartialEq> <&'b str as PartialEq>> >> + > + > + > + and 4 others error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 6e67a7b454529..843ae5044c37a 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -10,6 +10,10 @@ LL | 1 + Some(1); <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0277]: cannot subtract `Option<{integer}>` from `usize` @@ -24,6 +28,10 @@ LL | 2 as usize - Some(1); <&usize as Sub<&usize>> > + <&'a f32 as Sub> + <&'a f64 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> and 48 others error[E0277]: cannot multiply `{integer}` by `()` @@ -38,6 +46,10 @@ LL | 3 * (); <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> + <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others error[E0277]: cannot divide `{integer}` by `&str` @@ -52,6 +64,10 @@ LL | 4 / ""; <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> + <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others error[E0277]: can't compare `{integer}` with `String` @@ -66,6 +82,10 @@ LL | 5 < String::new(); + + + + and 6 others error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` @@ -80,6 +100,10 @@ LL | 6 == Ok(1); + + + + and 6 others error: aborting due to 6 previous errors diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index 12a6d7962f46b..cfb5d28e7674b 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr @@ -10,6 +10,10 @@ LL | 2_usize + (loop {}); <&usize as Add<&usize>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to previous error diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index d8bba1509d868..431cbf81b01bd 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -10,6 +10,10 @@ LL | x + 100.0 <&u8 as Add<&u8>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error[E0277]: cannot add `&str` to `f64` @@ -24,6 +28,10 @@ LL | x + "foo" <&f64 as Add<&f64>> > + <&'a f32 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> and 48 others error[E0277]: cannot add `{integer}` to `f64` @@ -38,6 +46,10 @@ LL | x + y <&f64 as Add<&f64>> > + <&'a f32 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> and 48 others error[E0277]: cannot subtract `{float}` from `u8` @@ -52,6 +64,10 @@ LL | x - 100.0 <&u8 as Sub<&u8>> > + <&'a f32 as Sub> + <&'a f64 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> and 48 others error[E0277]: cannot subtract `&str` from `f64` @@ -66,6 +82,10 @@ LL | x - "foo" <&f64 as Sub<&f64>> > + <&'a f32 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> and 48 others error[E0277]: cannot subtract `{integer}` from `f64` @@ -80,6 +100,10 @@ LL | x - y <&f64 as Sub<&f64>> > + <&'a f32 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> and 48 others error[E0277]: cannot multiply `u8` by `{float}` @@ -94,6 +118,10 @@ LL | x * 100.0 <&u8 as Mul<&u8>> > + <&'a f32 as Mul> + <&'a f64 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> and 49 others error[E0277]: cannot multiply `f64` by `&str` @@ -108,6 +136,10 @@ LL | x * "foo" <&f64 as Mul<&f64>> > + <&'a f32 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + <&'a i32 as Mul> and 49 others error[E0277]: cannot multiply `f64` by `{integer}` @@ -122,6 +154,10 @@ LL | x * y <&f64 as Mul<&f64>> > + <&'a f32 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + <&'a i32 as Mul> and 49 others error[E0277]: cannot divide `u8` by `{float}` @@ -136,6 +172,10 @@ LL | x / 100.0 <&u8 as Div<&u8>> > > + + <&'a f32 as Div> + <&'a f64 as Div> + <&'a i128 as Div> and 54 others error[E0277]: cannot divide `f64` by `&str` @@ -150,6 +190,10 @@ LL | x / "foo" <&f64 as Div<&f64>> > + <&'a f32 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> and 54 others error[E0277]: cannot divide `f64` by `{integer}` @@ -164,6 +208,10 @@ LL | x / y <&f64 as Div<&f64>> > + <&'a f32 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> and 54 others error: aborting due to 12 previous errors diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index b7591dfca99b3..543e3137fdd09 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -10,6 +10,10 @@ LL | x + 100 <&f32 as Add<&f32>> > + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -28,6 +32,10 @@ LL | x + 100 <&f64 as Add<&f64>> > + <&'a f32 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -46,6 +54,10 @@ LL | x - 100 <&f32 as Sub<&f32>> > + <&'a f64 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -64,6 +76,10 @@ LL | x - 100 <&f64 as Sub<&f64>> > + <&'a f32 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -82,6 +98,10 @@ LL | x * 100 <&f32 as Mul<&f32>> > + <&'a f64 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + <&'a i32 as Mul> and 49 others help: consider using a floating-point literal by writing it with `.0` | @@ -100,6 +120,10 @@ LL | x * 100 <&f64 as Mul<&f64>> > + <&'a f32 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + <&'a i32 as Mul> and 49 others help: consider using a floating-point literal by writing it with `.0` | @@ -118,6 +142,10 @@ LL | x / 100 <&f32 as Div<&f32>> > + <&'a f64 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> and 54 others help: consider using a floating-point literal by writing it with `.0` | @@ -136,6 +164,10 @@ LL | x / 100 <&f64 as Div<&f64>> > + <&'a f32 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> and 54 others help: consider using a floating-point literal by writing it with `.0` | diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 1542832f0129c..dee457ebd7f3f 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -10,6 +10,10 @@ LL | foo(1 as u32 + <&u32 as Add<&u32>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to previous error diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 4bdea05b06b8d..88a0f8f065027 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -12,6 +12,8 @@ LL | foo(String::new()); > > >> + >> + > = note: required because of the requirements on the impl of `Into<&str>` for `String` note: required by a bound in `foo` --> $DIR/into-str.rs:1:31 diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index fc2692a9a9313..6567eca38c81d 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -12,6 +12,10 @@ LL | Ok(Err(123_i32)?) > > > + > + > + > + > and 67 others = note: required because of the requirements on the impl of `FromResidual>` for `Result` diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 80ff068ff309a..15bbfeb87c6f3 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -70,6 +70,10 @@ LL | trait ProjectionPred> where T::Item : Add {} <&i32 as Add<&i32>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to 7 previous errors diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 0a5ec56e91512..9e2d8a6159c48 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -25,6 +25,10 @@ LL | a = c + b * 5; <&usize as Add<&usize>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error: aborting due to 3 previous errors diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index c769a0df7c891..64da15c505536 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -10,6 +10,10 @@ LL | >::add(1, 2); <&i32 as Add<&i32>> > + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> and 48 others error[E0308]: mismatched types From ef91519b45d2bbf0ce8c0180118160562eaaa0ca Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 27 Mar 2022 01:49:01 +0000 Subject: [PATCH 12/16] Dedup logic and improve output for other types that impl trait --- .../src/traits/error_reporting/mod.rs | 121 +++++++++-------- .../src/traits/error_reporting/suggestions.rs | 7 +- src/test/ui/binop/binop-mul-i32-f32.stderr | 10 +- src/test/ui/binop/issue-77910-1.stderr | 18 +-- .../ui/binop/shift-various-bad-types.stderr | 6 +- .../ui/chalkify/chalk_initial_program.stderr | 6 +- src/test/ui/chalkify/type_inference.stderr | 6 +- .../defaults/rp_impl_trait_fail.stderr | 6 +- .../ui/const-generics/exhaustive-value.stderr | 2 +- .../issues/issue-67185-2.stderr | 36 +++--- .../occurs-check/unused-substs-1.stderr | 2 +- .../const-eval/const-eval-overflow-3b.stderr | 10 +- .../const-eval/const-eval-overflow-4b.stderr | 10 +- .../ui/consts/too_generic_eval_ice.stderr | 2 +- ...e-21659-show-relevant-trait-impls-1.stderr | 2 +- ...e-21659-show-relevant-trait-impls-2.stderr | 2 +- .../issue-39802-show-5-trait-impls.stderr | 14 +- ...de-confusable-in-float-literal-expt.stderr | 2 +- .../bugs/issue-88460.stderr | 2 +- src/test/ui/impl-trait/equality.stderr | 10 +- src/test/ui/issues/issue-11771.stderr | 4 +- src/test/ui/issues/issue-24352.stderr | 10 +- src/test/ui/issues/issue-50582.stderr | 2 +- src/test/ui/issues/issue-59488.stderr | 18 +-- src/test/ui/kindck/kindck-copy.stderr | 36 +++--- .../ui/lexer/lex-bad-char-literals-6.stderr | 20 +-- src/test/ui/mismatched_types/binops.stderr | 52 ++++---- src/test/ui/never_type/issue-13352.stderr | 10 +- .../not-suggest-float-literal.stderr | 122 +++++++++--------- .../suggest-float-literal.stderr | 72 +++++------ .../ui/on-unimplemented/multiple-impls.stderr | 12 +- .../ui/on-unimplemented/slice-index.stderr | 2 +- .../termination-trait-test-wrong-type.stderr | 8 +- src/test/ui/span/multiline-span-simple.stderr | 10 +- src/test/ui/suggestions/into-str.stderr | 2 +- .../issue-71394-no-from-impl.stderr | 2 +- .../bound/assoc-fn-bound-root-obligation.rs | 2 +- .../assoc-fn-bound-root-obligation.stderr | 2 +- .../repeated-supertrait-ambig.stderr | 10 +- src/test/ui/traits/issue-79458.stderr | 8 +- src/test/ui/traits/map-types.stderr | 2 +- .../ui/try-trait/bad-interconversion.stderr | 6 +- .../nested-tait-inference2.stderr | 2 +- src/test/ui/type/type-check-defaults.stderr | 10 +- src/test/ui/typeck/issue-81293.stderr | 10 +- src/test/ui/typeck/issue-90101.stderr | 2 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 10 +- 47 files changed, 363 insertions(+), 357 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index fdafb2d3d417e..09b445058c0d3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -30,7 +30,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, + self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, }; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; @@ -1756,6 +1756,60 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, ) -> bool { + let report = |mut candidates: Vec>, err: &mut Diagnostic| { + candidates.sort(); + candidates.dedup(); + let len = candidates.len(); + if candidates.len() == 0 { + return false; + } + let trait_ref = candidates[0]; + if candidates.len() == 1 { + err.highlighted_help(vec![ + ( + format!( + "the trait `{}` is implemented for `", + trait_ref.print_only_trait_path() + ), + Style::NoStyle, + ), + (candidates[0].self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + return true; + } + // Check if the trait is the same in all cases. If so, we'll only show the type. + // FIXME: there *has* to be a better way! + let mut traits: Vec<_> = candidates + .iter() + .map(|c| format!("{}", c).split(" as ").last().unwrap().to_string()) + .collect(); + traits.sort(); + traits.dedup(); + + let mut candidates: Vec = candidates + .into_iter() + .map(|c| { + if traits.len() == 1 { + format!("\n {}", c.self_ty()) + } else { + format!("\n {}", c) + } + }) + .collect(); + + candidates.sort(); + candidates.dedup(); + let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; + err.help(&format!( + "the following other types implement trait `{}`:{}{}", + trait_ref.print_only_trait_path(), + candidates[..end].join(""), + if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + )); + true + }; + let def_id = trait_ref.def_id(); if impl_candidates.is_empty() { if self.tcx.trait_is_auto(def_id) @@ -1765,7 +1819,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // Mentioning implementers of `Copy`, `Debug` and friends is not useful. return false; } - let mut normalized_impl_candidates: Vec<_> = self + let normalized_impl_candidates: Vec<_> = self .tcx .all_impls(def_id) // Ignore automatically derived impls and `!Trait` impls. @@ -1776,45 +1830,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) // Avoid mentioning type parameters. .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_))) - .map(|trait_ref| format!("\n {}", trait_ref.self_ty())) .collect(); - normalized_impl_candidates.sort(); - normalized_impl_candidates.dedup(); - let len = normalized_impl_candidates.len(); - if len == 0 { - return false; - } - if len == 1 { - err.highlighted_help(vec![ - ( - format!( - "the trait `{}` is implemented for `", - trait_ref.print_only_trait_path() - ), - Style::NoStyle, - ), - (normalized_impl_candidates[0].trim().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); - return true; - } - let end = if normalized_impl_candidates.len() <= 9 { - normalized_impl_candidates.len() - } else { - 8 - }; - err.help(&format!( - "the following other types implement trait `{}`:{}{}", - trait_ref.print_only_trait_path(), - normalized_impl_candidates[..end].join(""), - if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } - )); - return true; + return report(normalized_impl_candidates, err); } - let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 9 { impl_candidates.len() } else { 8 }; - let normalize = |candidate| { self.tcx.infer_ctxt().enter(|ref infcx| { let normalized = infcx @@ -1822,8 +1841,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .normalize(candidate) .ok(); match normalized { - Some(normalized) => format!("\n {}", normalized.value), - None => format!("\n {}", candidate), + Some(normalized) => normalized.value, + None => candidate, } }) }; @@ -1834,7 +1853,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // // Prefer more similar candidates first, then sort lexicographically // by their normalized string representation. - let first_candidate = impl_candidates.get(0).map(|candidate| candidate.trait_ref); let mut normalized_impl_candidates_and_similarities = impl_candidates .into_iter() .map(|ImplCandidate { trait_ref, similarity }| { @@ -1850,26 +1868,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .map(|(_, normalized)| normalized) .collect::>(); - if normalized_impl_candidates.len() == 1 { - err.highlighted_help(vec![ - ( - format!( - "the trait `{}` is implemented for `", - first_candidate.unwrap().print_only_trait_path() - ), - Style::NoStyle, - ), - (first_candidate.unwrap().self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); - } else { - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } - )); - } - true + report(normalized_impl_candidates, err) } /// Gets the parent trait chain start 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 b369c73387198..16ecca254c7b0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -557,8 +557,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } else if real_trait_pred != trait_pred { // This branch addresses #87437. - let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, base_ty); + let obligation = self.mk_trait_obligation_with_new_self_ty( + param_env, + real_trait_pred, + base_ty, + ); if self.predicate_may_hold(&obligation) { err.span_suggestion_verbose( span.shrink_to_lo(), diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 715e52b41e75c..453333fb56a87 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr @@ -5,15 +5,15 @@ LL | x * y | ^ no implementation for `i32 * f32` | = help: the trait `Mul` is not implemented for `i32` - = help: the following implementations were found: - <&'a i32 as Mul> - <&i32 as Mul<&i32>> - > - + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> + <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others error: aborting due to previous error diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index 16b06a0198b27..95ee51a88261a 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -16,15 +16,15 @@ LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` - = help: the following implementations were found: - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A) -> Ret + extern "C" fn(A, ...) -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/binop/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr index 8fdb377751c24..bb0bb63b22df5 100644 --- a/src/test/ui/binop/shift-various-bad-types.stderr +++ b/src/test/ui/binop/shift-various-bad-types.stderr @@ -5,7 +5,7 @@ LL | 22 >> p.char; | ^^ no implementation for `{integer} >> char` | = help: the trait `Shr` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> @@ -23,7 +23,7 @@ LL | 22 >> p.str; | ^^ no implementation for `{integer} >> &str` | = help: the trait `Shr<&str>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> @@ -41,7 +41,7 @@ LL | 22 >> p; | ^^ no implementation for `{integer} >> &Panolpy` | = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> diff --git a/src/test/ui/chalkify/chalk_initial_program.stderr b/src/test/ui/chalkify/chalk_initial_program.stderr index 7b0b3f85b3915..343c0a31862b9 100644 --- a/src/test/ui/chalkify/chalk_initial_program.stderr +++ b/src/test/ui/chalkify/chalk_initial_program.stderr @@ -4,9 +4,9 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied LL | gimme::(); | ^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - - + = help: the following other types implement trait `Foo`: + i32 + u32 note: required by a bound in `gimme` --> $DIR/chalk_initial_program.rs:9:13 | diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 14d43c1474c57..508a6dd1388cb 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -6,9 +6,9 @@ LL | only_bar(x); | | | required by a bound introduced by this call | - = help: the following implementations were found: - - + = help: the following other types implement trait `Bar`: + i32 + u32 note: required by a bound in `only_bar` --> $DIR/type_inference.rs:12:16 | diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 9cadc4110e1e6..4c9ab6901b1f5 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -25,7 +25,7 @@ error[E0277]: the trait bound `u32: Traitor` is not satisfied LL | fn uwu() -> impl Traitor { | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` | - = help: the following implementations were found: + = help: the following other types implement trait `Traitor`: > > @@ -50,9 +50,9 @@ error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied LL | fn owo() -> impl Traitor { | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | - = help: the following implementations were found: - > + = help: the following other types implement trait `Traitor`: > + > error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied --> $DIR/rp_impl_trait_fail.rs:24:26 diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index fcbb41bb4fcc4..5613ed27cb234 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | <() as Foo>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<0_u8>`: <() as Foo<0_u8>> <() as Foo<100_u8>> <() as Foo<101_u8>> diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 89aa3d395e25b..c7be8e14a10d5 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -4,9 +4,9 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied LL | ::Quaks: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -16,9 +16,9 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied LL | [::Quaks; 2]: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -28,9 +28,9 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 | @@ -46,9 +46,9 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -64,9 +64,9 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -82,9 +82,9 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 | diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr index aedf44658db63..8431d989278ba 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied LL | let _ = A; | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` | - = help: the trait `Bar` is implemented for `A<{ 6 + 1 }>` + = help: the trait `Bar` is implemented for `A<7_usize>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 | diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index d2d68506d4e1c..5fde557a32ad7 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -11,15 +11,15 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` - = help: the following implementations were found: - <&'a i8 as Add> - <&i8 as Add<&i8>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index 818e3bc15b19d..3c192eef14f11 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -11,15 +11,15 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` - = help: the following implementations were found: - <&'a i8 as Add> - <&i8 as Add<&i8>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0604]: only `u8` can be cast as `char`, not `i8` diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 45459b931caac..5544350c34cba 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -21,7 +21,7 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | ^^ no implementation for `[{integer}; _] == [{integer}; 0]` | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; _]` - = help: the following implementations were found: + = help: the following other types implement trait `PartialEq<[B; N]>`: <&[B] as PartialEq<[A; N]>> <&[T] as PartialEq>> <&mut [B] as PartialEq<[A; N]>> diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 8aedb4229e6d3..1c83f75ffb937 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied LL | f1.foo(1usize); | ^^^ the trait `Foo` is not implemented for `Bar` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: > > diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index f25c7ce00e548..85f3eba927d06 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied LL | f1.foo(1usize); | ^^^ the trait `Foo` is not implemented for `Bar` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: > > > diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 3aa863e900f4a..e1d80313bc46b 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -6,7 +6,7 @@ LL | Foo::::bar(&1i8); | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: > > > @@ -25,16 +25,16 @@ LL | Foo::::bar(&1u8); | | | required by a bound introduced by this call | - = help: the following implementations were found: - > - > - > - > + = help: the following other types implement trait `Foo`: > > > > > + > + > + > + > error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 @@ -44,7 +44,7 @@ LL | Foo::::bar(&true); | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: > > > diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index bd9d9e086e044..15af2c26e8fca 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -22,7 +22,7 @@ LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹ | ^ no implementation for `{float} - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `{float}` - = help: the following implementations were found: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr index ec8de15dc3957..98c304cc90b53 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not s LL | test(Foo); | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` | - = help: the trait `for<'a> Marker` is implemented for `()` + = help: the trait `Marker` is implemented for `()` note: required by a bound in `test` --> $DIR/issue-88460.rs:17:27 | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 9137183375aca..48cfcb4ad3e0a 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -24,15 +24,15 @@ LL | n + sum_to(n - 1) | ^ no implementation for `u32 + impl Foo` | = help: the trait `Add` is not implemented for `u32` - = help: the following implementations were found: - <&'a u32 as Add> - <&u32 as Add<&u32>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr index 019677775987e..ef15aa5840482 100644 --- a/src/test/ui/issues/issue-11771.stderr +++ b/src/test/ui/issues/issue-11771.stderr @@ -5,7 +5,7 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -23,7 +23,7 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index 364fbbc981e64..1fa2d356c68ef 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr @@ -5,15 +5,15 @@ LL | 1.0f64 - 1 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Sub> - <&f64 as Sub<&f64>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> + <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index a1e614807de4a..d4e29030c1648 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -14,7 +14,7 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index c61d44bf89526..76a47c49bbafb 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -94,15 +94,15 @@ LL | assert_eq!(Foo::Bar, i); | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` - = help: the following implementations were found: - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> - Ret as Debug> + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A) -> Ret + extern "C" fn(A, ...) -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index 29c9b872b5816..1c61c85368be9 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -4,15 +4,15 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied LL | assert_copy::<&'static mut isize>(); | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize` | - = help: the following implementations were found: - - - - - - - - + = help: the following other types implement trait `Copy`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 @@ -26,15 +26,15 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied LL | assert_copy::<&'a mut isize>(); | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize` | - = help: the following implementations were found: - - - - - - - - + = help: the following other types implement trait `Copy`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index 9df6c92d1e578..199958bc7e416 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -38,15 +38,15 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` - = help: the following implementations were found: + = help: the following other types implement trait `PartialEq>`: <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> + > + >> + > + >> - > - > - > - and 4 others error[E0308]: mismatched types @@ -64,15 +64,15 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` - = help: the following implementations were found: + = help: the following other types implement trait `PartialEq>`: <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> + > + >> + > + >> - > - > - > - and 4 others error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 843ae5044c37a..16d1222899340 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -5,7 +5,7 @@ LL | 1 + Some(1); | ^ no implementation for `{integer} + Option<{integer}>` | = help: the trait `Add>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -23,15 +23,15 @@ LL | 2 as usize - Some(1); | ^ no implementation for `usize - Option<{integer}>` | = help: the trait `Sub>` is not implemented for `usize` - = help: the following implementations were found: - <&'a usize as Sub> - <&usize as Sub<&usize>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> + <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others error[E0277]: cannot multiply `{integer}` by `()` @@ -41,7 +41,7 @@ LL | 3 * (); | ^ no implementation for `{integer} * ()` | = help: the trait `Mul<()>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -59,7 +59,7 @@ LL | 4 / ""; | ^ no implementation for `{integer} / &str` | = help: the trait `Div<&str>` is not implemented for `{integer}` - = help: the following implementations were found: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> @@ -77,15 +77,15 @@ LL | 5 < String::new(); | ^ no implementation for `{integer} < String` and `{integer} > String` | = help: the trait `PartialOrd` is not implemented for `{integer}` - = help: the following implementations were found: - - - - - - - - + = help: the following other types implement trait `PartialOrd`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` @@ -95,15 +95,15 @@ LL | 6 == Ok(1); | ^^ no implementation for `{integer} == Result<{integer}, _>` | = help: the trait `PartialEq>` is not implemented for `{integer}` - = help: the following implementations were found: - - - - - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error: aborting due to 6 previous errors diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index cfb5d28e7674b..449b0756012de 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr @@ -5,15 +5,15 @@ LL | 2_usize + (loop {}); | ^ no implementation for `usize + ()` | = help: the trait `Add<()>` is not implemented for `usize` - = help: the following implementations were found: - <&'a usize as Add> - <&usize as Add<&usize>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to previous error diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index 431cbf81b01bd..72cc4f6ec6469 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -5,15 +5,15 @@ LL | x + 100.0 | ^ no implementation for `u8 + {float}` | = help: the trait `Add<{float}>` is not implemented for `u8` - = help: the following implementations were found: - <&'a u8 as Add> - <&u8 as Add<&u8>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0277]: cannot add `&str` to `f64` @@ -23,15 +23,15 @@ LL | x + "foo" | ^ no implementation for `f64 + &str` | = help: the trait `Add<&str>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Add> - <&f64 as Add<&f64>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> + <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0277]: cannot add `{integer}` to `f64` @@ -41,15 +41,15 @@ LL | x + y | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Add> - <&f64 as Add<&f64>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> + <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0277]: cannot subtract `{float}` from `u8` @@ -59,15 +59,15 @@ LL | x - 100.0 | ^ no implementation for `u8 - {float}` | = help: the trait `Sub<{float}>` is not implemented for `u8` - = help: the following implementations were found: - <&'a u8 as Sub> - <&u8 as Sub<&u8>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> + <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others error[E0277]: cannot subtract `&str` from `f64` @@ -77,15 +77,15 @@ LL | x - "foo" | ^ no implementation for `f64 - &str` | = help: the trait `Sub<&str>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Sub> - <&f64 as Sub<&f64>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> + <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others error[E0277]: cannot subtract `{integer}` from `f64` @@ -95,15 +95,15 @@ LL | x - y | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Sub> - <&f64 as Sub<&f64>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> + <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others error[E0277]: cannot multiply `u8` by `{float}` @@ -113,15 +113,15 @@ LL | x * 100.0 | ^ no implementation for `u8 * {float}` | = help: the trait `Mul<{float}>` is not implemented for `u8` - = help: the following implementations were found: - <&'a u8 as Mul> - <&u8 as Mul<&u8>> - > - + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> + <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others error[E0277]: cannot multiply `f64` by `&str` @@ -131,15 +131,15 @@ LL | x * "foo" | ^ no implementation for `f64 * &str` | = help: the trait `Mul<&str>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Mul> - <&f64 as Mul<&f64>> - > - + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> + <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others error[E0277]: cannot multiply `f64` by `{integer}` @@ -149,15 +149,15 @@ LL | x * y | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Mul> - <&f64 as Mul<&f64>> - > - + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> + <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others error[E0277]: cannot divide `u8` by `{float}` @@ -167,15 +167,15 @@ LL | x / 100.0 | ^ no implementation for `u8 / {float}` | = help: the trait `Div<{float}>` is not implemented for `u8` - = help: the following implementations were found: - <&'a u8 as Div> - <&u8 as Div<&u8>> - > - > - + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others error[E0277]: cannot divide `f64` by `&str` @@ -185,15 +185,15 @@ LL | x / "foo" | ^ no implementation for `f64 / &str` | = help: the trait `Div<&str>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Div> - <&f64 as Div<&f64>> - > - + = help: the following other types implement trait `Div`: <&'a f32 as Div> + <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others error[E0277]: cannot divide `f64` by `{integer}` @@ -203,15 +203,15 @@ LL | x / y | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Div> - <&f64 as Div<&f64>> - > - + = help: the following other types implement trait `Div`: <&'a f32 as Div> + <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others error: aborting due to 12 previous errors diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index 543e3137fdd09..fd3996416b67a 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -5,15 +5,15 @@ LL | x + 100 | ^ no implementation for `f32 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f32` - = help: the following implementations were found: + = help: the following other types implement trait `Add`: <&'a f32 as Add> - <&f32 as Add<&f32>> - > - <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -27,15 +27,15 @@ LL | x + 100 | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Add> - <&f64 as Add<&f64>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> + <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -49,15 +49,15 @@ LL | x - 100 | ^ no implementation for `f32 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f32` - = help: the following implementations were found: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> - <&f32 as Sub<&f32>> - > - <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -71,15 +71,15 @@ LL | x - 100 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Sub> - <&f64 as Sub<&f64>> - > - + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> + <&'a f64 as Sub> <&'a i128 as Sub> <&'a i16 as Sub> <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> and 48 others help: consider using a floating-point literal by writing it with `.0` | @@ -93,15 +93,15 @@ LL | x * 100 | ^ no implementation for `f32 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f32` - = help: the following implementations were found: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> - <&f32 as Mul<&f32>> - > - <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others help: consider using a floating-point literal by writing it with `.0` | @@ -115,15 +115,15 @@ LL | x * 100 | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Mul> - <&f64 as Mul<&f64>> - > - + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> + <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> and 49 others help: consider using a floating-point literal by writing it with `.0` | @@ -137,15 +137,15 @@ LL | x / 100 | ^ no implementation for `f32 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f32` - = help: the following implementations were found: + = help: the following other types implement trait `Div`: <&'a f32 as Div> - <&f32 as Div<&f32>> - > - <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others help: consider using a floating-point literal by writing it with `.0` | @@ -159,15 +159,15 @@ LL | x / 100 | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` - = help: the following implementations were found: - <&'a f64 as Div> - <&f64 as Div<&f64>> - > - + = help: the following other types implement trait `Div`: <&'a f32 as Div> + <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> and 54 others help: consider using a floating-point literal by writing it with `.0` | diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index be29d31d97b8e..ebe7f1f7a34a3 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -7,7 +7,7 @@ LL | Index::index(&[] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> @@ -20,7 +20,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> @@ -33,7 +33,7 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> @@ -44,7 +44,7 @@ LL | Index::index(&[] as &[i32], 2u32); | ^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> @@ -55,7 +55,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> @@ -66,7 +66,7 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following implementations were found: + = help: the following other types implement trait `Index>`: <[i32] as Index>> <[i32] as Index>> diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index 6dc27b5d4cc56..e90d08187ed90 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -15,7 +15,7 @@ LL | x[..1i32]; | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` - = help: the following implementations were found: + = help: the following other types implement trait `SliceIndex`: as SliceIndex<[T]>> as SliceIndex> = note: required because of the requirements on the impl of `Index>` for `[i32]` diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index d87eceb1c9a7b..96a899ecca581 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -9,10 +9,10 @@ LL | | } | |_^ `main` can only return types that implement `Termination` | = help: the trait `Termination` is not implemented for `Result` - = help: the following implementations were found: - as Termination> - as Termination> - as Termination> + = help: the following other types implement trait `Termination`: + Result + Result<(), E> + Result note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL | diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index dee457ebd7f3f..81dd7d03f919c 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -5,15 +5,15 @@ LL | foo(1 as u32 + | ^ no implementation for `u32 + ()` | = help: the trait `Add<()>` is not implemented for `u32` - = help: the following implementations were found: - <&'a u32 as Add> - <&u32 as Add<&u32>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to previous error diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 88a0f8f065027..b7b92e0353485 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -7,7 +7,7 @@ LL | foo(String::new()); | required by a bound introduced by this call | = note: to coerce a `String` into a `&str`, use `&*` as a prefix - = help: the following implementations were found: + = help: the following other types implement trait `From`: > > > diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr index 7972437771399..0f3d0e59e19bc 100644 --- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | - = help: the following implementations were found: + = help: the following other types implement trait `From>`: <[T; LANES] as From>> <[bool; LANES] as From>> = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]` diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs index 2720f94a3c191..1d234518056fd 100644 --- a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs @@ -4,7 +4,7 @@ fn strip_lf(s: &str) -> &str { //~| NOTE expected an `FnMut<(char,)>` closure, found `u8` //~| NOTE required by a bound introduced by this call //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` - //~| HELP the following other types implement trait `Pattern<'_>`: + //~| HELP the following other types implement trait `Pattern<'a>`: //~| NOTE required because of the requirements on the impl of `Pattern<'_>` for `u8` } diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index 37cba4189d725..115539a6dc28d 100644 --- a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -7,7 +7,7 @@ LL | s.strip_suffix(b'\n').unwrap_or(s) | required by a bound introduced by this call | = help: the trait `FnMut<(char,)>` is not implemented for `u8` - = help: the following other types implement trait `Pattern<'_>`: + = help: the following other types implement trait `Pattern<'a>`: &'b String &'b [char; N] &'b [char] diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 3645ad03cb9bb..0220cf4127ebf 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -4,7 +4,9 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` | - = help: the trait `CompareTo` is implemented for `i64` + = help: the following other types implement trait `CompareTo`: + > + > error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:30:7 @@ -23,7 +25,9 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi LL | ::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` | - = help: the trait `CompareTo` is implemented for `i64` + = help: the following other types implement trait `CompareTo`: + > + > error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:38:5 @@ -42,7 +46,7 @@ error[E0277]: the trait bound `i64: CompareTo` is not satisfied LL | assert_eq!(22_i64.same_as(22), true); | ^^^^^^^ the trait `CompareTo` is not implemented for `i64` | - = help: the following implementations were found: + = help: the following other types implement trait `CompareTo`: > > diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr index b970012837313..cf2e4edf9f0a9 100644 --- a/src/test/ui/traits/issue-79458.stderr +++ b/src/test/ui/traits/issue-79458.stderr @@ -7,10 +7,10 @@ LL | struct Foo<'a, T> { LL | bar: &'a mut T | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` | - = help: the following implementations were found: - <&T as Clone> - <*const T as Clone> - <*mut T as Clone> + = help: the following other types implement trait `Clone`: + &T + *const T + *mut T = note: `Clone` is implemented for `&T`, but not for `&mut T` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/traits/map-types.stderr b/src/test/ui/traits/map-types.stderr index 37bc5c6badc41..a4686edb71757 100644 --- a/src/test/ui/traits/map-types.stderr +++ b/src/test/ui/traits/map-types.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Box>: Map` is LL | let y: Box> = Box::new(x); | ^^^^^^^^^^^ the trait `Map` is not implemented for `Box>` | - = help: the trait `Map` is implemented for `HashMap` + = help: the trait `Map` is implemented for `HashMap` = note: required for the cast to the object type `dyn Map` error: aborting due to previous error diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 6567eca38c81d..1b46252ae89ec 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -7,15 +7,15 @@ LL | Ok(Err(123_i32)?) | ^ the trait `From` is not implemented for `u8` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following implementations were found: - > - > + = help: the following other types implement trait `From`: > > > > > > + > + > and 67 others = note: required because of the requirements on the impl of `FromResidual>` for `Result` diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 1372a018667c2..2fe115927c036 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: <() as Foo<()>> <() as Foo> diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 15bbfeb87c6f3..15deade2cd8f1 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -65,15 +65,15 @@ LL | trait ProjectionPred> where T::Item : Add {} | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add` is not implemented for `i32` - = help: the following implementations were found: - <&'a i32 as Add> - <&i32 as Add<&i32>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 7 previous errors diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 9e2d8a6159c48..00f490c465345 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -20,15 +20,15 @@ LL | a = c + b * 5; | ^ no implementation for `usize + u16` | = help: the trait `Add` is not implemented for `usize` - = help: the following implementations were found: - <&'a usize as Add> - <&usize as Add<&usize>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error: aborting due to 3 previous errors diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr index 998b636887f23..b6d02285bd237 100644 --- a/src/test/ui/typeck/issue-90101.stderr +++ b/src/test/ui/typeck/issue-90101.stderr @@ -6,7 +6,7 @@ LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `From>`: > >> >> diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 64da15c505536..09208527210f9 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,15 +5,15 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` - = help: the following implementations were found: - <&'a i32 as Add> - <&i32 as Add<&i32>> - > - + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> and 48 others error[E0308]: mismatched types From 3109c931b495f72fb9758bef15d38aeedc354ca1 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 27 Mar 2022 02:02:07 +0000 Subject: [PATCH 13/16] Refer to the TraitRef::identity in the message to be clearer --- .../src/traits/error_reporting/mod.rs | 4 ++-- src/test/ui/binop/binop-mul-i32-f32.stderr | 2 +- .../ui/binop/shift-various-bad-types.stderr | 6 ++--- .../defaults/rp_impl_trait_fail.stderr | 4 ++-- .../ui/const-generics/exhaustive-value.stderr | 2 +- .../const-eval/const-eval-overflow-3b.stderr | 2 +- .../const-eval/const-eval-overflow-4b.stderr | 2 +- .../ui/consts/too_generic_eval_ice.stderr | 2 +- ...e-21659-show-relevant-trait-impls-1.stderr | 2 +- ...e-21659-show-relevant-trait-impls-2.stderr | 2 +- .../issue-39802-show-5-trait-impls.stderr | 6 ++--- ...de-confusable-in-float-literal-expt.stderr | 2 +- src/test/ui/impl-trait/equality.stderr | 2 +- src/test/ui/issues/issue-11771.stderr | 4 ++-- src/test/ui/issues/issue-24352.stderr | 2 +- src/test/ui/issues/issue-50582.stderr | 2 +- .../ui/lexer/lex-bad-char-literals-6.stderr | 4 ++-- src/test/ui/mismatched_types/binops.stderr | 12 +++++----- src/test/ui/never_type/issue-13352.stderr | 2 +- .../not-suggest-float-literal.stderr | 24 +++++++++---------- .../suggest-float-literal.stderr | 16 ++++++------- .../ui/on-unimplemented/multiple-impls.stderr | 12 +++++----- .../ui/on-unimplemented/slice-index.stderr | 2 +- src/test/ui/span/multiline-span-simple.stderr | 2 +- src/test/ui/suggestions/into-str.stderr | 2 +- .../issue-71394-no-from-impl.stderr | 2 +- .../repeated-supertrait-ambig.stderr | 6 ++--- .../ui/try-trait/bad-interconversion.stderr | 2 +- .../nested-tait-inference2.stderr | 2 +- src/test/ui/type/type-check-defaults.stderr | 2 +- src/test/ui/typeck/issue-81293.stderr | 2 +- src/test/ui/typeck/issue-90101.stderr | 2 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 2 +- 33 files changed, 71 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 09b445058c0d3..88a4b6ee06d3a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1763,13 +1763,12 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if candidates.len() == 0 { return false; } - let trait_ref = candidates[0]; if candidates.len() == 1 { err.highlighted_help(vec![ ( format!( "the trait `{}` is implemented for `", - trait_ref.print_only_trait_path() + candidates[0].print_only_trait_path() ), Style::NoStyle, ), @@ -1778,6 +1777,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { ]); return true; } + let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id); // Check if the trait is the same in all cases. If so, we'll only show the type. // FIXME: there *has* to be a better way! let mut traits: Vec<_> = candidates diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 453333fb56a87..21c490965b147 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr @@ -5,7 +5,7 @@ LL | x * y | ^ no implementation for `i32 * f32` | = help: the trait `Mul` is not implemented for `i32` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> diff --git a/src/test/ui/binop/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr index bb0bb63b22df5..38db66f86b461 100644 --- a/src/test/ui/binop/shift-various-bad-types.stderr +++ b/src/test/ui/binop/shift-various-bad-types.stderr @@ -5,7 +5,7 @@ LL | 22 >> p.char; | ^^ no implementation for `{integer} >> char` | = help: the trait `Shr` is not implemented for `{integer}` - = help: the following other types implement trait `Shr`: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> @@ -23,7 +23,7 @@ LL | 22 >> p.str; | ^^ no implementation for `{integer} >> &str` | = help: the trait `Shr<&str>` is not implemented for `{integer}` - = help: the following other types implement trait `Shr`: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> @@ -41,7 +41,7 @@ LL | 22 >> p; | ^^ no implementation for `{integer} >> &Panolpy` | = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` - = help: the following other types implement trait `Shr`: + = help: the following other types implement trait `Shr`: <&'a i128 as Shr> <&'a i128 as Shr> <&'a i128 as Shr> diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 4c9ab6901b1f5..1fb6b38e4a68f 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -25,7 +25,7 @@ error[E0277]: the trait bound `u32: Traitor` is not satisfied LL | fn uwu() -> impl Traitor { | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` | - = help: the following other types implement trait `Traitor`: + = help: the following other types implement trait `Traitor`: > > @@ -50,7 +50,7 @@ error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied LL | fn owo() -> impl Traitor { | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | - = help: the following other types implement trait `Traitor`: + = help: the following other types implement trait `Traitor`: > > diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index 5613ed27cb234..9c1b086f4da9a 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | <() as Foo>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | - = help: the following other types implement trait `Foo<0_u8>`: + = help: the following other types implement trait `Foo`: <() as Foo<0_u8>> <() as Foo<100_u8>> <() as Foo<101_u8>> diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 5fde557a32ad7..0e6be6d01ed69 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -11,7 +11,7 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index 3c192eef14f11..4fa017e04e97b 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -11,7 +11,7 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | ^ no implementation for `i8 + u8` | = help: the trait `Add` is not implemented for `i8` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 5544350c34cba..8de61fcfb7330 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -21,7 +21,7 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | ^^ no implementation for `[{integer}; _] == [{integer}; 0]` | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; _]` - = help: the following other types implement trait `PartialEq<[B; N]>`: + = help: the following other types implement trait `PartialEq`: <&[B] as PartialEq<[A; N]>> <&[T] as PartialEq>> <&mut [B] as PartialEq<[A; N]>> diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 1c83f75ffb937..26764bc0ee5cc 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied LL | f1.foo(1usize); | ^^^ the trait `Foo` is not implemented for `Bar` | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: > > diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index 85f3eba927d06..bb175367e1f9e 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Foo` is not satisfied LL | f1.foo(1usize); | ^^^ the trait `Foo` is not implemented for `Bar` | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: > > > diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index e1d80313bc46b..d27b05fe7f7df 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -6,7 +6,7 @@ LL | Foo::::bar(&1i8); | | | required by a bound introduced by this call | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: > > > @@ -25,7 +25,7 @@ LL | Foo::::bar(&1u8); | | | required by a bound introduced by this call | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: > > > @@ -44,7 +44,7 @@ LL | Foo::::bar(&true); | | | required by a bound introduced by this call | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: > > > diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 15af2c26e8fca..26986684f0c0a 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -22,7 +22,7 @@ LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹ | ^ no implementation for `{float} - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `{float}` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 48cfcb4ad3e0a..f14b447b07730 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -24,7 +24,7 @@ LL | n + sum_to(n - 1) | ^ no implementation for `u32 + impl Foo` | = help: the trait `Add` is not implemented for `u32` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr index ef15aa5840482..161fce4b0315c 100644 --- a/src/test/ui/issues/issue-11771.stderr +++ b/src/test/ui/issues/issue-11771.stderr @@ -5,7 +5,7 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -23,7 +23,7 @@ LL | 1 + | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index 1fa2d356c68ef..118f37f6971ef 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr @@ -5,7 +5,7 @@ LL | 1.0f64 - 1 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index d4e29030c1648..3d527eb6b4e4a 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -14,7 +14,7 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index 199958bc7e416..afef0cb603485 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -38,7 +38,7 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` - = help: the following other types implement trait `PartialEq>`: + = help: the following other types implement trait `PartialEq`: <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> @@ -64,7 +64,7 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `PartialEq` is not implemented for `&str` - = help: the following other types implement trait `PartialEq>`: + = help: the following other types implement trait `PartialEq`: <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 16d1222899340..3de652d87ec54 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -5,7 +5,7 @@ LL | 1 + Some(1); | ^ no implementation for `{integer} + Option<{integer}>` | = help: the trait `Add>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -23,7 +23,7 @@ LL | 2 as usize - Some(1); | ^ no implementation for `usize - Option<{integer}>` | = help: the trait `Sub>` is not implemented for `usize` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -41,7 +41,7 @@ LL | 3 * (); | ^ no implementation for `{integer} * ()` | = help: the trait `Mul<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -59,7 +59,7 @@ LL | 4 / ""; | ^ no implementation for `{integer} / &str` | = help: the trait `Div<&str>` is not implemented for `{integer}` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> @@ -77,7 +77,7 @@ LL | 5 < String::new(); | ^ no implementation for `{integer} < String` and `{integer} > String` | = help: the trait `PartialOrd` is not implemented for `{integer}` - = help: the following other types implement trait `PartialOrd`: + = help: the following other types implement trait `PartialOrd`: f32 f64 i128 @@ -95,7 +95,7 @@ LL | 6 == Ok(1); | ^^ no implementation for `{integer} == Result<{integer}, _>` | = help: the trait `PartialEq>` is not implemented for `{integer}` - = help: the following other types implement trait `PartialEq`: + = help: the following other types implement trait `PartialEq`: f32 f64 i128 diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index 449b0756012de..fed780e68957f 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr @@ -5,7 +5,7 @@ LL | 2_usize + (loop {}); | ^ no implementation for `usize + ()` | = help: the trait `Add<()>` is not implemented for `usize` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index 72cc4f6ec6469..6aa1ad8dd899f 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -5,7 +5,7 @@ LL | x + 100.0 | ^ no implementation for `u8 + {float}` | = help: the trait `Add<{float}>` is not implemented for `u8` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -23,7 +23,7 @@ LL | x + "foo" | ^ no implementation for `f64 + &str` | = help: the trait `Add<&str>` is not implemented for `f64` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -41,7 +41,7 @@ LL | x + y | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -59,7 +59,7 @@ LL | x - 100.0 | ^ no implementation for `u8 - {float}` | = help: the trait `Sub<{float}>` is not implemented for `u8` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -77,7 +77,7 @@ LL | x - "foo" | ^ no implementation for `f64 - &str` | = help: the trait `Sub<&str>` is not implemented for `f64` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -95,7 +95,7 @@ LL | x - y | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -113,7 +113,7 @@ LL | x * 100.0 | ^ no implementation for `u8 * {float}` | = help: the trait `Mul<{float}>` is not implemented for `u8` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -131,7 +131,7 @@ LL | x * "foo" | ^ no implementation for `f64 * &str` | = help: the trait `Mul<&str>` is not implemented for `f64` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -149,7 +149,7 @@ LL | x * y | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -167,7 +167,7 @@ LL | x / 100.0 | ^ no implementation for `u8 / {float}` | = help: the trait `Div<{float}>` is not implemented for `u8` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> @@ -185,7 +185,7 @@ LL | x / "foo" | ^ no implementation for `f64 / &str` | = help: the trait `Div<&str>` is not implemented for `f64` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> @@ -203,7 +203,7 @@ LL | x / y | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index fd3996416b67a..988379e582a34 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -5,7 +5,7 @@ LL | x + 100 | ^ no implementation for `f32 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f32` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -27,7 +27,7 @@ LL | x + 100 | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> @@ -49,7 +49,7 @@ LL | x - 100 | ^ no implementation for `f32 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f32` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -71,7 +71,7 @@ LL | x - 100 | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Sub`: + = help: the following other types implement trait `Sub`: <&'a f32 as Sub> <&'a f64 as Sub> <&'a i128 as Sub> @@ -93,7 +93,7 @@ LL | x * 100 | ^ no implementation for `f32 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f32` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -115,7 +115,7 @@ LL | x * 100 | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Mul`: + = help: the following other types implement trait `Mul`: <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> @@ -137,7 +137,7 @@ LL | x / 100 | ^ no implementation for `f32 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f32` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> @@ -159,7 +159,7 @@ LL | x / 100 | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` - = help: the following other types implement trait `Div`: + = help: the following other types implement trait `Div`: <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index ebe7f1f7a34a3..06e1a222af881 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -7,7 +7,7 @@ LL | Index::index(&[] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> @@ -20,7 +20,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> @@ -33,7 +33,7 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> @@ -44,7 +44,7 @@ LL | Index::index(&[] as &[i32], 2u32); | ^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> @@ -55,7 +55,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> @@ -66,7 +66,7 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index>`: + = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index e90d08187ed90..ae7d2e1d82393 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -15,7 +15,7 @@ LL | x[..1i32]; | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` - = help: the following other types implement trait `SliceIndex`: + = help: the following other types implement trait `SliceIndex`: as SliceIndex<[T]>> as SliceIndex> = note: required because of the requirements on the impl of `Index>` for `[i32]` diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 81dd7d03f919c..c0d9a8634e487 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -5,7 +5,7 @@ LL | foo(1 as u32 + | ^ no implementation for `u32 + ()` | = help: the trait `Add<()>` is not implemented for `u32` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index b7b92e0353485..8ae5c84794734 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -7,7 +7,7 @@ LL | foo(String::new()); | required by a bound introduced by this call | = note: to coerce a `String` into a `&str`, use `&*` as a prefix - = help: the following other types implement trait `From`: + = help: the following other types implement trait `From`: > > > diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr index 0f3d0e59e19bc..383f40d47fa44 100644 --- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | - = help: the following other types implement trait `From>`: + = help: the following other types implement trait `From`: <[T; LANES] as From>> <[bool; LANES] as From>> = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]` diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 0220cf4127ebf..cab0ccdf710da 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` | - = help: the following other types implement trait `CompareTo`: + = help: the following other types implement trait `CompareTo`: > > @@ -25,7 +25,7 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfi LL | ::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` | - = help: the following other types implement trait `CompareTo`: + = help: the following other types implement trait `CompareTo`: > > @@ -46,7 +46,7 @@ error[E0277]: the trait bound `i64: CompareTo` is not satisfied LL | assert_eq!(22_i64.same_as(22), true); | ^^^^^^^ the trait `CompareTo` is not implemented for `i64` | - = help: the following other types implement trait `CompareTo`: + = help: the following other types implement trait `CompareTo`: > > diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 1b46252ae89ec..1a4105231dc75 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -7,7 +7,7 @@ LL | Ok(Err(123_i32)?) | ^ the trait `From` is not implemented for `u8` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following other types implement trait `From`: + = help: the following other types implement trait `From`: > > > diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 2fe115927c036..9a3fd2f4005f3 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | - = help: the following other types implement trait `Foo`: + = help: the following other types implement trait `Foo`: <() as Foo<()>> <() as Foo> diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 15deade2cd8f1..f292877f30ea2 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -65,7 +65,7 @@ LL | trait ProjectionPred> where T::Item : Add {} | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add` is not implemented for `i32` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 00f490c465345..9658288ac8b28 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -20,7 +20,7 @@ LL | a = c + b * 5; | ^ no implementation for `usize + u16` | = help: the trait `Add` is not implemented for `usize` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr index b6d02285bd237..ab9a72edfe98d 100644 --- a/src/test/ui/typeck/issue-90101.stderr +++ b/src/test/ui/typeck/issue-90101.stderr @@ -6,7 +6,7 @@ LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") | | | required by a bound introduced by this call | - = help: the following other types implement trait `From>`: + = help: the following other types implement trait `From`: > >> >> diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 09208527210f9..74766d9fdd1b1 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,7 +5,7 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` - = help: the following other types implement trait `Add`: + = help: the following other types implement trait `Add`: <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> From a6301cab5e3512bf28c69e60e28e8253911702c9 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 27 Mar 2022 02:08:58 +0000 Subject: [PATCH 14/16] Highlight `is` in the message for emphasis --- .../src/traits/error_reporting/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 88a4b6ee06d3a..de35f545f06c5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1766,12 +1766,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if candidates.len() == 1 { err.highlighted_help(vec![ ( - format!( - "the trait `{}` is implemented for `", - candidates[0].print_only_trait_path() - ), + format!("the trait `{}` ", candidates[0].print_only_trait_path()), Style::NoStyle, ), + ("is".to_string(), Style::Highlight), + (" implemented for `".to_string(), Style::NoStyle), (candidates[0].self_ty().to_string(), Style::Highlight), ("`".to_string(), Style::NoStyle), ]); From e1ef833bca8fe21cb2cbc42795cda4b589ec6f25 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 27 Mar 2022 02:14:54 +0000 Subject: [PATCH 15/16] Remove hack, fix fmt and tests --- .../src/traits/error_reporting/mod.rs | 9 ++-- .../defaults/rp_impl_trait_fail.stderr | 6 +-- .../kindck/kindck-impl-type-params.nll.stderr | 2 + .../suggest-deferences/root-obligation.fixed | 1 - .../suggest-deferences/root-obligation.rs | 1 - .../nested-tait-inference2.stderr | 2 +- .../self-referential-2.stderr | 14 ++++--- .../self-referential-4.stderr | 42 ++++++++++++------- .../self-referential.stderr | 42 ++++++++++++------- 9 files changed, 72 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index de35f545f06c5..408c2ab9675e2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1756,7 +1756,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, ) -> bool { - let report = |mut candidates: Vec>, err: &mut Diagnostic| { + let report = |mut candidates: Vec>, err: &mut Diagnostic| { candidates.sort(); candidates.dedup(); let len = candidates.len(); @@ -1778,11 +1778,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id); // Check if the trait is the same in all cases. If so, we'll only show the type. - // FIXME: there *has* to be a better way! - let mut traits: Vec<_> = candidates - .iter() - .map(|c| format!("{}", c).split(" as ").last().unwrap().to_string()) - .collect(); + let mut traits: Vec<_> = + candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect(); traits.sort(); traits.dedup(); diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 1fb6b38e4a68f..48c61c22e7a32 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -40,7 +40,7 @@ LL | | 1_u32 LL | | } | |_^ the trait `Traitor` is not implemented for `u32` | - = help: the following implementations were found: + = help: the following other types implement trait `Traitor`: > > @@ -65,9 +65,9 @@ LL | | 1_u64 LL | | } | |_^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | - = help: the following implementations were found: - > + = help: the following other types implement trait `Traitor`: > + > error: aborting due to 6 previous errors diff --git a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr index 7129bad8a978a..94f802620a302 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr @@ -72,6 +72,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | let a = t as Box>; | ^ the trait `Copy` is not implemented for `String` | + = help: the trait `Gettable` is implemented for `S` note: required because of the requirements on the impl of `Gettable` for `S` --> $DIR/kindck-impl-type-params.rs:14:32 | @@ -85,6 +86,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | let a: Box> = t; | ^ the trait `Copy` is not implemented for `Foo` | + = help: the trait `Gettable` is implemented for `S` note: required because of the requirements on the impl of `Gettable` for `S` --> $DIR/kindck-impl-type-params.rs:14:32 | diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.fixed b/src/test/ui/traits/suggest-deferences/root-obligation.fixed index 9fd1924067827..7a8433f90572e 100644 --- a/src/test/ui/traits/suggest-deferences/root-obligation.fixed +++ b/src/test/ui/traits/suggest-deferences/root-obligation.fixed @@ -11,4 +11,3 @@ fn get_vowel_count(string: &str) -> usize { fn main() { let _ = get_vowel_count("asdf"); } - diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.rs b/src/test/ui/traits/suggest-deferences/root-obligation.rs index 4dd0291b62970..51bac2107e3b4 100644 --- a/src/test/ui/traits/suggest-deferences/root-obligation.rs +++ b/src/test/ui/traits/suggest-deferences/root-obligation.rs @@ -11,4 +11,3 @@ fn get_vowel_count(string: &str) -> usize { fn main() { let _ = get_vowel_count("asdf"); } - diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 9a3fd2f4005f3..264e8024fac3a 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -19,7 +19,7 @@ LL | | () LL | | } | |_^ the trait `Foo` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo`: <() as Foo<()>> <() as Foo> diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr index b93ded6a7d3e1..348696f25e3b5 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -5,11 +5,15 @@ LL | 42_i32 | ^^^^^^ no implementation for `i32 == Foo` | = help: the trait `PartialEq` is not implemented for `i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr index 23ca689019634..838264794194c 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -5,11 +5,15 @@ LL | i | ^ no implementation for `&i32 == Bar<'b, 'static>` | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` @@ -19,11 +23,15 @@ LL | i | ^ no implementation for `&i32 == Foo<'static, 'b>` | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` @@ -33,11 +41,15 @@ LL | i | ^ no implementation for `&i32 == Moo<'static, 'a>` | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 4384bc9b98a7c..2ebb15b880308 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -5,11 +5,15 @@ LL | i | ^ no implementation for `&i32 == Bar<'b, 'a>` | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error[E0277]: can't compare `&i32` with `(i32, &i32)` @@ -19,11 +23,15 @@ LL | (42, i) | ^ no implementation for `&i32 == (i32, &i32)` | = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` @@ -33,11 +41,15 @@ LL | (42, i) | ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` | = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` - = help: the following implementations were found: - - - - + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize and 6 others error: aborting due to 3 previous errors From 0252fc9619805e59a32e8cf9a13591df69a56a5b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Apr 2022 13:37:03 -0400 Subject: [PATCH 16/16] explicitly distinguish pointer::addr and pointer::expose_addr --- library/core/src/ptr/const_ptr.rs | 54 +++++++++++-- library/core/src/ptr/mod.rs | 128 +++++++++++++++++++++++++++--- library/core/src/ptr/mut_ptr.rs | 54 +++++++++++-- 3 files changed, 217 insertions(+), 19 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 209ea5cb0439b..f862912432e56 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -152,9 +152,17 @@ impl *const T { /// Gets the "address" portion of the pointer. /// - /// This is equivalent to `self as usize`, which semantically discards - /// *provenance* and *address-space* information. To properly restore that information, - /// use [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// This is similar to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. However, unlike `self as usize`, casting the returned address + /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To + /// properly restore the lost information and obtain a dereferencable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, use [`expose_addr`][pointer::expose_addr] and + /// [`from_exposed_addr`][from_exposed_addr] instead. However, note that this makes + /// your code less portable and less amenable to tools that check for compliance with the Rust + /// memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -162,8 +170,9 @@ impl *const T { /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such + /// might change in the future (including possibly weakening this so it becomes wholly + /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -175,6 +184,41 @@ impl *const T { self as usize } + /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future + /// use in [`from_exposed_addr`][]. + /// + /// This is equivalent to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit + /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can + /// later call [`from_exposed_addr`][] to reconstitute the original pointer including its + /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// + /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// [`from_exposed_addr`][] complicates specification and reasoning and may not be supported by + /// tools that help you to stay conformant with the Rust memory model, so it is recommended to + /// use [`addr`][pointer::addr] wherever possible. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`from_exposed_addr`][] to work is typically not + /// available. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, see the + /// [module documentation][crate::ptr] for details. + /// + /// [`from_exposed_addr`]: from_exposed_addr + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn expose_addr(self) -> usize + where + T: Sized, + { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + self as usize + } + /// Creates a new pointer with the given address. /// /// This performs the same operation as an `addr as ptr` cast, but copies diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 42e55ce10462c..a3730448f7354 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -70,7 +70,7 @@ //! interpretation of provenance. It's ok if your code doesn't strictly conform to it.** //! //! [Strict Provenance][] is an experimental set of APIs that help tools that try -//! to validate the memory-safety of your program's execution. Notably this includes [miri][] +//! to validate the memory-safety of your program's execution. Notably this includes [Miri][] //! and [CHERI][], which can detect when you access out of bounds memory or otherwise violate //! Rust's memory model. //! @@ -136,7 +136,7 @@ //! //! The strict provenance experiment is mostly only interested in exploring stricter *spatial* //! provenance. In this sense it can be thought of as a subset of the more ambitious and -//! formal [Stacked Borrows][] research project, which is what tools like [miri][] are based on. +//! formal [Stacked Borrows][] research project, which is what tools like [Miri][] are based on. //! In particular, Stacked Borrows is necessary to properly describe what borrows are allowed //! to do and when they become invalidated. This necessarily involves much more complex //! *temporal* reasoning than simply identifying allocations. Adjusting APIs and code @@ -170,7 +170,8 @@ //! Under Strict Provenance, a usize *cannot* accurately represent a pointer, and converting from //! a pointer to a usize is generally an operation which *only* extracts the address. It is //! therefore *impossible* to construct a valid pointer from a usize because there is no way -//! to restore the address-space and provenance. +//! to restore the address-space and provenance. In other words, pointer-integer-pointer +//! roundtrips are not possible (in the sense that the resulting pointer is not dereferencable). //! //! The key insight to making this model *at all* viable is the [`with_addr`][] method: //! @@ -194,10 +195,10 @@ //! and then immediately converting back to a pointer. To make this use case more ergonomic, //! we provide the [`map_addr`][] method. //! -//! To help make it clear that code is "following" Strict Provenance semantics, we also -//! provide an [`addr`][] method which is currently equivalent to `ptr as usize`. In the -//! future we may provide a lint for pointer<->integer casts to help you audit if your -//! code conforms to strict provenance. +//! To help make it clear that code is "following" Strict Provenance semantics, we also provide an +//! [`addr`][] method which promises that the returned address is not part of a +//! pointer-usize-pointer roundtrip. In the future we may provide a lint for pointer<->integer +//! casts to help you audit if your code conforms to strict provenance. //! //! //! ## Using Strict Provenance @@ -310,6 +311,41 @@ //! For instance, ARM explicitly supports high-bit tagging, and so CHERI on ARM inherits //! that and should support it. //! +//! ## Pointer-usize-pointer roundtrips and 'exposed' provenance +//! +//! **This section is *non-normative* and is part of the [Strict Provenance] experiment.** +//! +//! As discussed above, pointer-usize-pointer roundtrips are not possible under [Strict Provenance]. +//! However, there exists legacy Rust code that is full of such roundtrips, and legacy platform APIs +//! regularly assume that `usize` can capture all the information that makes up a pointer. There +//! also might be code that cannot be ported to Strict Provenance (which is something we would [like +//! to hear about][Strict Provenance]). +//! +//! For situations like this, there is a fallback plan, a way to 'opt out' of Strict Provenance. +//! However, note that this makes your code a lot harder to specify, and the code will not work +//! (well) with tools like [Miri] and [CHERI]. +//! +//! This fallback plan is provided by the [`expose_addr`] and [`from_exposed_addr`] methods (which +//! are equivalent to `as` casts between pointers and integers). [`expose_addr`] is a lot like +//! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed' +//! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but +//! is not materialized in actual executions, except in tools like [Miri].) [`from_exposed_addr`] +//! can be used to construct a pointer with one of these previously 'exposed' provenances. +//! [`from_exposed_addr`] takes only `addr: usize` as arguments, so unlike in [`with_addr`] there is +//! no indication of what the correct provenance for the returned pointer is -- and that is exactly +//! what makes pointer-usize-pointer roundtrips so tricky to rigorously specify! There is no +//! algorithm that decides which provenance will be used. You can think of this as "guessing" the +//! right provenance, and the guess will be "maximally in your favor", in the sense that if there is +//! any way to avoid undefined behavior, then that is the guess that will be taken. However, if +//! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will +//! be used, the program has undefined behavior. +//! +//! Using [`expose_addr`] or [`from_exposed_addr`] (or the equivalent `as` casts) means that code is +//! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to +//! determine whether it is possible to use Rust without [`expose_addr`] and [`from_exposed_addr`]. +//! If this is successful, it would be a major win for avoiding specification complexity and to +//! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the +//! confidence in (unsafe) Rust code. //! //! [aliasing]: ../../nomicon/aliasing.html //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer @@ -322,7 +358,9 @@ //! [`map_addr`]: pointer::map_addr //! [`addr`]: pointer::addr //! [`ptr::invalid`]: core::ptr::invalid -//! [miri]: https://github.com/rust-lang/miri +//! [`expose_addr`]: pointer::expose_addr +//! [`from_exposed_addr`]: from_exposed_addr +//! [Miri]: https://github.com/rust-lang/miri //! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ //! [Strict Provenance]: https://github.com/rust-lang/rust/issues/95228 //! [Stacked Borrows]: https://plv.mpi-sws.org/rustbelt/stacked-borrows/ @@ -547,6 +585,78 @@ pub const fn invalid_mut(addr: usize) -> *mut T { addr as *mut T } +/// Convert an address back to a pointer, picking up a previously 'exposed' provenance. +/// +/// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any* +/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` +/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be +/// used, the program has undefined behavior. Note that there is no algorithm that decides which +/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess +/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined +/// behavior, then that is the guess that will be taken. +/// +/// On platforms with multiple address spaces, it is your responsibility to ensure that the +/// address makes sense in the address space that this pointer will be used with. +/// +/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// suitable provenance complicates specification and reasoning and may not be supported by +/// tools that help you to stay conformant with the Rust memory model, so it is recommended to +/// use [`with_addr`][pointer::with_addr] wherever possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This API and its claimed semantics are part of the Strict Provenance experiment, see the +/// [module documentation][crate::ptr] for details. +#[must_use] +#[inline] +#[unstable(feature = "strict_provenance", issue = "95228")] +pub fn from_exposed_addr(addr: usize) -> *const T +where + T: Sized, +{ + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + addr as *const T +} + +/// Convert an address back to a mutable pointer, picking up a previously 'exposed' provenance. +/// +/// This is equivalent to `addr as *mut T`. The provenance of the returned pointer is that of *any* +/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` +/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be +/// used, the program has undefined behavior. Note that there is no algorithm that decides which +/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess +/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined +/// behavior, then that is the guess that will be taken. +/// +/// On platforms with multiple address spaces, it is your responsibility to ensure that the +/// address makes sense in the address space that this pointer will be used with. +/// +/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// suitable provenance complicates specification and reasoning and may not be supported by +/// tools that help you to stay conformant with the Rust memory model, so it is recommended to +/// use [`with_addr`][pointer::with_addr] wherever possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This API and its claimed semantics are part of the Strict Provenance experiment, see the +/// [module documentation][crate::ptr] for details. +#[must_use] +#[inline] +#[unstable(feature = "strict_provenance", issue = "95228")] +pub fn from_exposed_addr_mut(addr: usize) -> *mut T +where + T: Sized, +{ + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + addr as *mut T +} + /// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. @@ -762,7 +872,7 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { ); } - // NOTE(scottmcm) MIRI is disabled here as reading in smaller units is a + // NOTE(scottmcm) Miri is disabled here as reading in smaller units is a // pessimization for it. Also, if the type contains any unaligned pointers, // copying those over multiple reads is difficult to support. #[cfg(not(miri))] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index bfc89625935d9..5db9c3e941eb4 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -156,9 +156,17 @@ impl *mut T { /// Gets the "address" portion of the pointer. /// - /// This is equivalent to `self as usize`, which semantically discards - /// *provenance* and *address-space* information. To properly restore that information, - /// use [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// This is similar to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. However, unlike `self as usize`, casting the returned address + /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To + /// properly restore the lost information and obtain a dereferencable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, use [`expose_addr`][pointer::expose_addr] and + /// [`from_exposed_addr_mut`][from_exposed_addr_mut] instead. However, note that this makes + /// your code less portable and less amenable to tools that check for compliance with the Rust + /// memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -166,8 +174,9 @@ impl *mut T { /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such + /// might change in the future (including possibly weakening this so it becomes wholly + /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -179,6 +188,41 @@ impl *mut T { self as usize } + /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future + /// use in [`from_exposed_addr`][]. + /// + /// This is equivalent to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit + /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can + /// later call [`from_exposed_addr_mut`][] to reconstitute the original pointer including its + /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// + /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// [`from_exposed_addr_mut`][] complicates specification and reasoning and may not be supported + /// by tools that help you to stay conformant with the Rust memory model, so it is recommended + /// to use [`addr`][pointer::addr] wherever possible. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`from_exposed_addr_mut`][] to work is typically not + /// available. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, see the + /// [module documentation][crate::ptr] for details. + /// + /// [`from_exposed_addr_mut`]: from_exposed_addr_mut + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn expose_addr(self) -> usize + where + T: Sized, + { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + self as usize + } + /// Creates a new pointer with the given address. /// /// This performs the same operation as an `addr as ptr` cast, but copies