From a52ec87a1720bda5a2aac437a909af01cd35e3f7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Esteban=20K=C3=BCber?= Date: Fri, 31 Jan 2020 18:48:35 -0800 Subject: [PATCH] Use more appropriate spans on object unsafe traits and provide structured suggestions when possible --- src/librustc/traits/error_reporting/mod.rs | 10 +- src/librustc/traits/object_safety.rs | 103 +++++++++++++----- src/librustc_hir/hir.rs | 21 ++++ src/librustc_parse/parser/generics.rs | 2 +- ...ce-impl-trait-for-trait-object-safe.stderr | 2 +- src/test/ui/error-codes/E0033-teach.stderr | 5 +- src/test/ui/error-codes/E0033.stderr | 5 +- src/test/ui/error-codes/E0038.stderr | 2 +- ...ature-gate-object_safe_for_dispatch.stderr | 7 +- ...-trait-in-return-position-dyn-trait.stderr | 10 +- src/test/ui/issues/issue-19380.stderr | 5 +- .../object-safety-mentions-Self.curr.stderr | 4 +- ...tions-Self.object_safe_for_dispatch.stderr | 4 +- .../object-safety-no-static.curr.stderr | 5 +- ...-no-static.object_safe_for_dispatch.stderr | 5 +- ...ary-self-types-not-object-safe.curr.stderr | 13 ++- ...bject-safe.object_safe_for_dispatch.stderr | 6 +- ...object-unsafe-trait-should-use-self.stderr | 5 +- src/test/ui/traits/trait-object-safety.stderr | 10 +- src/test/ui/traits/trait-test-2.stderr | 12 +- ...ter-defaults-referencing-Self-ppaux.stderr | 2 +- src/test/ui/wf/wf-object-safe.stderr | 2 +- 22 files changed, 178 insertions(+), 62 deletions(-) diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs index f2cc8a303a9..0ea0f271fd6 100644 --- a/src/librustc/traits/error_reporting/mod.rs +++ b/src/librustc/traits/error_reporting/mod.rs @@ -1073,9 +1073,15 @@ pub fn report_object_safety_error( err.span_label(span, &msg); } } - if let (Some(_), Some(note)) = (trait_span, violation.solution()) { + match (trait_span, violation.solution()) { + (Some(_), Some((note, None))) => { + err.help(¬e); + } + (Some(_), Some((note, Some((sugg, span))))) => { + err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); + } // Only provide the help if its a local trait, otherwise it's not actionable. - err.help(¬e); + _ => {} } } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index ac9e4950b72..efb46a1b8d3 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -13,6 +13,7 @@ use crate::traits::{self, Obligation, ObligationCause}; use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; @@ -48,14 +49,20 @@ pub fn error_msg(&self) -> Cow<'static, str> { "it cannot use `Self` as a type parameter in the supertraits or `where`-clauses" .into() } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => { + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { format!("associated function `{}` has no `self` parameter", name).into() } - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( - "method `{}` references the `Self` type in its parameters or return type", + ObjectSafetyViolation::Method( name, - ) - .into(), + MethodViolationCode::ReferencesSelfInput(_), + DUMMY_SP, + ) => format!("method `{}` references the `Self` type in its parameters", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => { + format!("method `{}` references the `Self` type in this parameter", name).into() + } + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => { + format!("method `{}` references the `Self` type in its return type", name).into() + } ObjectSafetyViolation::Method( name, MethodViolationCode::WhereClauseReferencesSelf, @@ -78,23 +85,31 @@ pub fn error_msg(&self) -> Cow<'static, str> { } } - pub fn solution(&self) -> Option { + pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> { Some(match *self { ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf => { return None; } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!( - "consider turning `{}` into a method by giving it a `&self` argument or \ - constraining it with `where Self: Sized`", - name + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => ( + format!( + "consider turning `{}` into a method by giving it a `&self` argument or \ + constraining it so it does not apply to trait objects", + name + ), + sugg.map(|(sugg, sp)| (sugg.to_string(), sp)), ), - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { + ObjectSafetyViolation::Method( + name, + MethodViolationCode::UndispatchableReceiver, + span, + ) => ( format!("consider changing method `{}`'s `self` parameter to be `&self`", name) - .into() - } + .into(), + Some(("&Self".to_string(), span)), + ), ObjectSafetyViolation::AssocConst(name, _) | ObjectSafetyViolation::Method(name, ..) => { - format!("consider moving `{}` to another trait", name) + (format!("consider moving `{}` to another trait", name), None) } }) } @@ -119,10 +134,13 @@ pub fn solution(&self) -> Option { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum MethodViolationCode { /// e.g., `fn foo()` - StaticMethod, + StaticMethod(Option<(&'static str, Span)>), + + /// e.g., `fn foo(&self, x: Self)` + ReferencesSelfInput(usize), - /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self` - ReferencesSelf, + /// e.g., `fn foo(&self) -> Self` + ReferencesSelfOutput, /// e.g., `fn foo(&self) where Self: Clone` WhereClauseReferencesSelf, @@ -193,7 +211,7 @@ fn object_safety_violations_for_trait( .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| { object_safety_violation_for_method(tcx, trait_def_id, &item) - .map(|code| ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)) + .map(|(code, span)| ObjectSafetyViolation::Method(item.ident.name, code, span)) }) .filter(|violation| { if let ObjectSafetyViolation::Method( @@ -224,9 +242,15 @@ fn object_safety_violations_for_trait( ) }; err.span_label(*span, &msg); - if let (Some(_), Some(note)) = (node, violation.solution()) { + match (node, violation.solution()) { + (Some(_), Some((note, None))) => { + err.help(¬e); + } + (Some(_), Some((note, Some((sugg, span))))) => { + err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); + } // Only provide the help if its a local trait, otherwise it's not actionable. - err.help(¬e); + _ => {} } err.emit(); false @@ -398,7 +422,7 @@ fn object_safety_violation_for_method( tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem, -) -> Option { +) -> Option<(MethodViolationCode, Span)> { debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method); // Any method that has a `Self : Sized` requisite is otherwise // exempt from the regulations. @@ -406,7 +430,26 @@ fn object_safety_violation_for_method( return None; } - virtual_call_violation_for_method(tcx, trait_def_id, method) + let violation = virtual_call_violation_for_method(tcx, trait_def_id, method); + // Get an accurate span depending on the violation. + violation.map(|v| { + let node = tcx.hir().get_if_local(method.def_id); + let span = match (v, node) { + (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node + .fn_decl() + .and_then(|decl| decl.inputs.get(arg + 1)) + .map_or(method.ident.span, |arg| arg.span), + (MethodViolationCode::UndispatchableReceiver, Some(node)) => node + .fn_decl() + .and_then(|decl| decl.inputs.get(0)) + .map_or(method.ident.span, |arg| arg.span), + (MethodViolationCode::ReferencesSelfOutput, Some(node)) => { + node.fn_decl().map_or(method.ident.span, |decl| decl.output.span()) + } + _ => method.ident.span, + }; + (v, span) + }) } /// Returns `Some(_)` if this method cannot be called on a trait @@ -420,18 +463,26 @@ fn virtual_call_violation_for_method<'tcx>( ) -> Option { // The method's first parameter must be named `self` if !method.method_has_self_argument { - return Some(MethodViolationCode::StaticMethod); + // We'll attempt to provide a structured suggestion for `Self: Sized`. + let sugg = + tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map( + |generics| match generics.where_clause.predicates { + [] => (" where Self: Sized", generics.where_clause.span), + [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()), + }, + ); + return Some(MethodViolationCode::StaticMethod(sugg)); } let sig = tcx.fn_sig(method.def_id); - for input_ty in &sig.skip_binder().inputs()[1..] { + for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() { if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) { - return Some(MethodViolationCode::ReferencesSelf); + return Some(MethodViolationCode::ReferencesSelfInput(i)); } } if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) { - return Some(MethodViolationCode::ReferencesSelf); + return Some(MethodViolationCode::ReferencesSelfOutput); } // We can't monomorphize things like `fn foo(...)`. diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 0db75454aee..3ed0ad16eeb 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2631,4 +2631,25 @@ pub fn ident(&self) -> Option { _ => None, } } + + pub fn fn_decl(&self) -> Option<&FnDecl<'_>> { + match self { + Node::TraitItem(TraitItem { kind: TraitItemKind::Method(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. }) + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), + Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { + Some(fn_decl) + } + _ => None, + } + } + + pub fn generics(&self) -> Option<&Generics<'_>> { + match self { + Node::TraitItem(TraitItem { generics, .. }) + | Node::ImplItem(ImplItem { generics, .. }) + | Node::Item(Item { kind: ItemKind::Fn(_, generics, _), .. }) => Some(generics), + _ => None, + } + } } diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs index 075583711f5..0984263bb28 100644 --- a/src/librustc_parse/parser/generics.rs +++ b/src/librustc_parse/parser/generics.rs @@ -172,7 +172,7 @@ pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { /// ``` pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { let mut where_clause = - WhereClause { predicates: Vec::new(), span: self.prev_span.to(self.prev_span) }; + WhereClause { predicates: Vec::new(), span: self.prev_span.shrink_to_hi() }; if !self.eat_keyword(kw::Where) { return Ok(where_clause); diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr index c999cabcc14..85ed360a1f7 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:6 | LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | ------------- -- ...because method `eq` references the `Self` type in its parameters or return type + | ------------- ---- ...because method `eq` references the `Self` type in this parameter | | | this trait cannot be made into an object... LL | impl NotObjectSafe for dyn NotObjectSafe { } diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 050ea63aa4f..f323a990455 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -15,7 +15,10 @@ LL | fn foo(); LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033-teach.rs:12:9 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index c736fbcf92a..84481ff16c0 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -15,7 +15,10 @@ LL | fn foo(); LL | let trait_obj: &dyn SomeTrait = SomeTrait; | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033.rs:10:9 diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index 62b6f4cf246..638e924b0eb 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Trait` cannot be made into an object LL | trait Trait { | ----- this trait cannot be made into an object... LL | fn foo(&self) -> Self; - | --- ...because method `foo` references the `Self` type in its parameters or return type + | ---- ...because method `foo` references the `Self` type in its return type ... LL | fn call_foo(x: Box) { | ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index 29059880668..c66bbb0c504 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -20,7 +20,10 @@ LL | fn static_fn() {} LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object | - = help: consider turning `static_fn` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `static_fn` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn static_fn() where Self: Sized {} + | ^^^^^^^^^^^^^^^^^ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35 @@ -41,7 +44,7 @@ error[E0038]: the trait `NonObjectSafe4` cannot be made into an object LL | trait NonObjectSafe4 { | -------------- this trait cannot be made into an object... LL | fn foo(&self, &Self); - | --- ...because method `foo` references the `Self` type in its parameters or return type + | ----- ...because method `foo` references the `Self` type in this parameter ... LL | fn return_non_object_safe_rc() -> std::rc::Rc { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr index 1443be0b30e..9df5188bbdd 100644 --- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr +++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr @@ -9,7 +9,10 @@ LL | fn foo() -> Self; LL | fn car() -> dyn NotObjectSafe { | ^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error[E0038]: the trait `NotObjectSafe` cannot be made into an object --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:13 @@ -22,7 +25,10 @@ LL | fn foo() -> Self; LL | fn cat() -> Box { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index 22e744f8841..0a080171a79 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -9,7 +9,10 @@ LL | fn qiz(); LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object | - = help: consider turning `qiz` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `qiz` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn qiz() where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr index e90f9b6d0a0..4dbb27b425b 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, x: &Self); - | --- ...because method `bar` references the `Self` type in its parameters or return type + | ----- ...because method `bar` references the `Self` type in this parameter ... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^ the trait `Bar` cannot be made into an object @@ -17,7 +17,7 @@ error[E0038]: the trait `Baz` cannot be made into an object LL | trait Baz { | --- this trait cannot be made into an object... LL | fn baz(&self) -> Self; - | --- ...because method `baz` references the `Self` type in its parameters or return type + | ---- ...because method `baz` references the `Self` type in its return type ... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^ the trait `Baz` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr index 4a23fb56e91..89b273fb8ad 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, x: &Self); - | --- ...because method `bar` references the `Self` type in its parameters or return type + | ----- ...because method `bar` references the `Self` type in this parameter ... LL | t | ^ the trait `Bar` cannot be made into an object @@ -19,7 +19,7 @@ error[E0038]: the trait `Baz` cannot be made into an object LL | trait Baz { | --- this trait cannot be made into an object... LL | fn baz(&self) -> Self; - | --- ...because method `baz` references the `Self` type in its parameters or return type + | ---- ...because method `baz` references the `Self` type in its return type ... LL | t | ^ the trait `Baz` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-no-static.curr.stderr b/src/test/ui/object-safety/object-safety-no-static.curr.stderr index 2f79d53d1c1..f878cf8b462 100644 --- a/src/test/ui/object-safety/object-safety-no-static.curr.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.curr.stderr @@ -9,7 +9,10 @@ LL | fn foo() {} LL | fn diverges() -> Box { | ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr index bed6757fc68..de56843962b 100644 --- a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr @@ -9,9 +9,12 @@ LL | fn foo() {} LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` = note: required by cast to type `std::boxed::Box` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr index c06538fae3b..7948f7e9d6b 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr @@ -4,12 +4,13 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | trait Foo { | --- this trait cannot be made into an object... LL | fn foo(self: &Rc) -> usize; - | --- ...because method `foo`'s `self` parameter cannot be dispatched on + | --------- + | | + | ...because method `foo`'s `self` parameter cannot be dispatched on + | help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object - | - = help: consider changing method `foo`'s `self` parameter to be `&self` error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 @@ -17,12 +18,14 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | trait Foo { | --- this trait cannot be made into an object... LL | fn foo(self: &Rc) -> usize; - | --- ...because method `foo`'s `self` parameter cannot be dispatched on + | --------- + | | + | ...because method `foo`'s `self` parameter cannot be dispatched on + | help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = help: consider changing method `foo`'s `self` parameter to be `&self` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` = note: required by cast to type `std::rc::Rc` diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr index bebd5cbcf78..74e76b8265f 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr @@ -4,12 +4,14 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | trait Foo { | --- this trait cannot be made into an object... LL | fn foo(self: &Rc) -> usize; - | --- ...because method `foo`'s `self` parameter cannot be dispatched on + | --------- + | | + | ...because method `foo`'s `self` parameter cannot be dispatched on + | help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | - = help: consider changing method `foo`'s `self` parameter to be `&self` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` = note: required by cast to type `std::rc::Rc` diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr index 55185a2c8cd..58be59602b9 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr @@ -44,7 +44,10 @@ LL | fn f(a: B) -> B; | | | ...because associated function `f` has no `self` parameter | - = help: consider turning `f` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `f` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 5eb8cd0d806..162e9249b88 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -9,9 +9,12 @@ LL | fn foo(); LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` = note: required by cast to type `&dyn Tr` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 @@ -24,7 +27,10 @@ LL | fn foo(); LL | let _: &dyn Tr = &St; | ^^^^^^^ the trait `Tr` cannot be made into an object | - = help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` +help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 5b2b7b51f3d..9d1eef54756 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -14,9 +14,9 @@ error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:16 | LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } - | --- --- ---- ...because method `blah` has generic type parameters - | | | - | | ...because method `dup` references the `Self` type in its parameters or return type + | --- ---- ---- ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type | this trait cannot be made into an object... ... LL | (box 10 as Box).dup(); @@ -29,9 +29,9 @@ error[E0038]: the trait `bar` cannot be made into an object --> $DIR/trait-test-2.rs:11:6 | LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } - | --- --- ---- ...because method `blah` has generic type parameters - | | | - | | ...because method `dup` references the `Self` type in its parameters or return type + | --- ---- ---- ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type | this trait cannot be made into an object... ... LL | (box 10 as Box).dup(); diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index fa6c5a92fb4..539189982a8 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -14,7 +14,7 @@ error[E0038]: the trait `MyAdd` cannot be made into an object --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } - | ----- --- ...because method `add` references the `Self` type in its parameters or return type + | ----- ---- ...because method `add` references the `Self` type in its return type | | | this trait cannot be made into an object... ... diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index 2ff6383bc80..8935d766354 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -4,7 +4,7 @@ error[E0038]: the trait `A` cannot be made into an object LL | trait A { | - this trait cannot be made into an object... LL | fn foo(&self, _x: &Self); - | --- ...because method `foo` references the `Self` type in its parameters or return type + | ----- ...because method `foo` references the `Self` type in this parameter ... LL | let _x: &dyn A; | ^^^^^^ the trait `A` cannot be made into an object -- 2.44.0