]> git.lizzy.rs Git - rust.git/commitdiff
Use more appropriate spans on object unsafe traits and provide structured suggestions...
authorEsteban Küber <esteban@kuber.com.ar>
Sat, 1 Feb 2020 02:48:35 +0000 (18:48 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Sun, 2 Feb 2020 19:53:10 +0000 (11:53 -0800)
22 files changed:
src/librustc/traits/error_reporting/mod.rs
src/librustc/traits/object_safety.rs
src/librustc_hir/hir.rs
src/librustc_parse/parser/generics.rs
src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
src/test/ui/error-codes/E0033-teach.stderr
src/test/ui/error-codes/E0033.stderr
src/test/ui/error-codes/E0038.stderr
src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
src/test/ui/issues/issue-19380.stderr
src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
src/test/ui/object-safety/object-safety-no-static.curr.stderr
src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr
src/test/ui/traits/trait-object-safety.stderr
src/test/ui/traits/trait-test-2.stderr
src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
src/test/ui/wf/wf-object-safe.stderr

index f2cc8a303a95216f2d35650bb947bf712aada14c..0ea0f271fd60e4ad6eddae6d97fc712c946278cd 100644 (file)
@@ -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(&note);
+                }
+                (Some(_), Some((note, Some((sugg, span))))) => {
+                    err.span_suggestion(span, &note, sugg, Applicability::MachineApplicable);
+                }
                 // Only provide the help if its a local trait, otherwise it's not actionable.
-                err.help(&note);
+                _ => {}
             }
         }
     }
index ac9e4950b72cf22640bcd68cd2b9211239ec0628..efb46a1b8d3eebfdbabb5d9e80f3e51b043c0237 100644 (file)
@@ -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<String> {
+    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<String> {
 #[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(&note);
+                    }
+                    (Some(_), Some((note, Some((sugg, span))))) => {
+                        err.span_suggestion(span, &note, sugg, Applicability::MachineApplicable);
+                    }
                     // Only provide the help if its a local trait, otherwise it's not actionable.
-                    err.help(&note);
+                    _ => {}
                 }
                 err.emit();
                 false
@@ -398,7 +422,7 @@ fn object_safety_violation_for_method(
     tcx: TyCtxt<'_>,
     trait_def_id: DefId,
     method: &ty::AssocItem,
-) -> Option<MethodViolationCode> {
+) -> 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<MethodViolationCode> {
     // 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<A>(...)`.
index 0db75454aee3864c094946a89e8caf2de1458d74..3ed0ad16eebf2ee336e8bf5c309f8636270b377d 100644 (file)
@@ -2631,4 +2631,25 @@ pub fn ident(&self) -> Option<Ident> {
             _ => 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,
+        }
+    }
 }
index 075583711f5d3e8f9b129364cd1a0f9143327557..0984263bb283ebf56bd7f6c779ffd54d38900373 100644 (file)
@@ -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);
index c999cabcc14132815618fa4a196d87945b6a1b2f..85ed360a1f74a2d3de1a3f471e2d38900e42200c 100644 (file)
@@ -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 { }
index 050ea63aa4fa8a8ab9b7bcfd2c66e9054b387775..f323a9904557a7eb614d759db784acd4a49961f9 100644 (file)
@@ -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
index c736fbcf92a8eb96805ea3ed80d021f2a3ef0774..84481ff16c07e2dc71e5e796d25796aa38e5fbe3 100644 (file)
@@ -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
index 62b6f4cf246922dafd9d44986578be4d43b1b21e..638e924b0eb4391602fe343c358f2cb462c90fc5 100644 (file)
@@ -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<dyn Trait>) {
    |                ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
index 290598806689822fe6e442ab4156f1ed1cffa929..c66bbb0c5045f4ef99c4d31cd12e784a6353d5ca 100644 (file)
@@ -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<dyn NonObjectSafe4> {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object
index 1443be0b30ebe06178d3d632c1ae200a543df43b..9df5188bbdd0883cf8a1969f889b0ed71fbd8954 100644 (file)
@@ -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<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: aborting due to 2 previous errors
 
index 22e744f88417137dff805c7be97fe807374951d4..0a080171a795158e949f8f6e90dc8d18fe6380a5 100644 (file)
@@ -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
 
index e90f9b6d0a0cc228b48b297e15160960d6e6e667..4dbb27b425b3266bba4f70b5704b9da0253869d0 100644 (file)
@@ -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: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:Baz>(t: &T) -> &dyn Baz {
    |                              ^^^^^^^^ the trait `Baz` cannot be made into an object
index 4a23fb56e91a9cc6c98a1b2ea4ab6121cd463a0b..89b273fb8adde246796d0e062df44e772a3ddeef 100644 (file)
@@ -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
index 2f79d53d1c12469752186829c35ffd5a32c53957..f878cf8b462415b8d0b21340bd11416e157ba830 100644 (file)
@@ -9,7 +9,10 @@ LL |     fn foo() {}
 LL | fn diverges() -> Box<dyn Foo> {
    |                  ^^^^^^^^^^^^ 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
 
index bed6757fc68037ac92491a56cb4fc1e18d99d91f..de56843962bea381bd9f5fa6319726f31f65b06e 100644 (file)
@@ -9,9 +9,12 @@ LL |     fn foo() {}
 LL |     let b: Box<dyn Foo> = 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<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<Bar>`
    = note: required by cast to type `std::boxed::Box<dyn Foo>`
+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
 
index c06538fae3b4ed0c3b7a85bd0449b9beb3463f82..7948f7e9d6bc69e258898e446090a18331828d3f 100644 (file)
@@ -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<Self>) -> 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<dyn Foo>;
    |                                ^^^^^^^^^^^ 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<Self>) -> 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<dyn Foo>;
    |             ^^^^^^^^^^^^^^^ 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<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
    = note: required by cast to type `std::rc::Rc<dyn Foo>`
 
index bebd5cbcf780c8a048dffbb3e4c26b0bada9ad8c..74e76b8265f7055d49d9be4b0e2bd641ab53366f 100644 (file)
@@ -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<Self>) -> 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<dyn Foo>;
    |             ^^^^^^^^^^^^^^^ 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<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
    = note: required by cast to type `std::rc::Rc<dyn Foo>`
 
index 55185a2c8cdd179e0e98bd75e9dbe4c912d100e7..58be59602b9c54a94b3e21760bdabaeec6713270 100644 (file)
@@ -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
 
index 5eb8cd0d80636542b7c6954e91d31e428f49c618..162e9249b880efe953bd468103af16a2affbedbe 100644 (file)
@@ -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
 
index 5b2b7b51f3dae299ce33ef931948f447e48c34c3..9d1eef547568eb547b2e896b4a1e8874f4f55583 100644 (file)
@@ -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<X>(&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<dyn bar>).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<X>(&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<dyn bar>).dup();
index fa6c5a92fb437bc8cc5c588ec535d0e20aeb1358..539189982a8d7e8ec6b3dbb2f4d5196c4d6e01bd 100644 (file)
@@ -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<Rhs=Self> { 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...
 ...
index 2ff6383bc80eb6330f34c8b63b1400ecad31b65b..8935d766354fe8d8d46dfa4e820c2532df7659e7 100644 (file)
@@ -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