How is there a conflicting implementation of `From` when using a generic type?











up vote
5
down vote

favorite
1












I'm trying to implement an error enum which can contain an error associated with one of our traits like this:



trait Storage {
type Error;
}

enum MyError<S: Storage> {
StorageProblem(S::Error),
}


I have also tried to implement the From trait to allow construction of MyError from an instance of a Storage::Error:



impl<S: Storage> From<S::Error> for MyError<S> {
fn from(error: S::Error) -> MyError<S> {
MyError::StorageProblem(error)
}
}


(playground)



However this fails to compile:



error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
--> src/main.rs:9:1
|
9 | / impl<S: Storage> From<S::Error> for MyError<S> {
10 | | fn from(error: S::Error) -> MyError<S> {
11 | | MyError::StorageProblem(error)
12 | | }
13 | | }
| |_^
|
= note: conflicting implementation in crate `core`


I don't understand why the compiler reckons this has already been implemented. The error message is telling me that there's already an implementation of From<MyError<_>> (which there is), but I'm not trying to implement that here - I'm trying to implement From<S::Error> and MyError is not the same type as S::Error from what I can see.



Am I missing something fundamental to generics here?










share|improve this question




























    up vote
    5
    down vote

    favorite
    1












    I'm trying to implement an error enum which can contain an error associated with one of our traits like this:



    trait Storage {
    type Error;
    }

    enum MyError<S: Storage> {
    StorageProblem(S::Error),
    }


    I have also tried to implement the From trait to allow construction of MyError from an instance of a Storage::Error:



    impl<S: Storage> From<S::Error> for MyError<S> {
    fn from(error: S::Error) -> MyError<S> {
    MyError::StorageProblem(error)
    }
    }


    (playground)



    However this fails to compile:



    error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
    --> src/main.rs:9:1
    |
    9 | / impl<S: Storage> From<S::Error> for MyError<S> {
    10 | | fn from(error: S::Error) -> MyError<S> {
    11 | | MyError::StorageProblem(error)
    12 | | }
    13 | | }
    | |_^
    |
    = note: conflicting implementation in crate `core`


    I don't understand why the compiler reckons this has already been implemented. The error message is telling me that there's already an implementation of From<MyError<_>> (which there is), but I'm not trying to implement that here - I'm trying to implement From<S::Error> and MyError is not the same type as S::Error from what I can see.



    Am I missing something fundamental to generics here?










    share|improve this question


























      up vote
      5
      down vote

      favorite
      1









      up vote
      5
      down vote

      favorite
      1






      1





      I'm trying to implement an error enum which can contain an error associated with one of our traits like this:



      trait Storage {
      type Error;
      }

      enum MyError<S: Storage> {
      StorageProblem(S::Error),
      }


      I have also tried to implement the From trait to allow construction of MyError from an instance of a Storage::Error:



      impl<S: Storage> From<S::Error> for MyError<S> {
      fn from(error: S::Error) -> MyError<S> {
      MyError::StorageProblem(error)
      }
      }


      (playground)



      However this fails to compile:



      error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
      --> src/main.rs:9:1
      |
      9 | / impl<S: Storage> From<S::Error> for MyError<S> {
      10 | | fn from(error: S::Error) -> MyError<S> {
      11 | | MyError::StorageProblem(error)
      12 | | }
      13 | | }
      | |_^
      |
      = note: conflicting implementation in crate `core`


      I don't understand why the compiler reckons this has already been implemented. The error message is telling me that there's already an implementation of From<MyError<_>> (which there is), but I'm not trying to implement that here - I'm trying to implement From<S::Error> and MyError is not the same type as S::Error from what I can see.



      Am I missing something fundamental to generics here?










      share|improve this question















      I'm trying to implement an error enum which can contain an error associated with one of our traits like this:



      trait Storage {
      type Error;
      }

      enum MyError<S: Storage> {
      StorageProblem(S::Error),
      }


      I have also tried to implement the From trait to allow construction of MyError from an instance of a Storage::Error:



      impl<S: Storage> From<S::Error> for MyError<S> {
      fn from(error: S::Error) -> MyError<S> {
      MyError::StorageProblem(error)
      }
      }


      (playground)



      However this fails to compile:



      error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
      --> src/main.rs:9:1
      |
      9 | / impl<S: Storage> From<S::Error> for MyError<S> {
      10 | | fn from(error: S::Error) -> MyError<S> {
      11 | | MyError::StorageProblem(error)
      12 | | }
      13 | | }
      | |_^
      |
      = note: conflicting implementation in crate `core`


      I don't understand why the compiler reckons this has already been implemented. The error message is telling me that there's already an implementation of From<MyError<_>> (which there is), but I'm not trying to implement that here - I'm trying to implement From<S::Error> and MyError is not the same type as S::Error from what I can see.



      Am I missing something fundamental to generics here?







      rust






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 24 '17 at 0:53









      Shepmaster

      144k11268401




      144k11268401










      asked May 20 '16 at 12:54









      Fraser

      50.5k7160175




      50.5k7160175
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          8
          down vote



          accepted










          The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).



          Specifically,



          struct Tricky;

          impl Storage for Tricky {
          type Error = MyError<Tricky>;
          }


          (The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)



          If we substitute Tricky in place of S in your impl, we get:



          impl From<MyError<Tricky>> for MyError<Tricky> {
          ...
          }


          This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.



          This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.






          share|improve this answer























          • Has the extension been implemented in nightly now?
            – WiSaGaN
            May 20 '16 at 13:08










          • No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
            – huon
            May 20 '16 at 13:10










          • A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
            – Fraser
            May 20 '16 at 13:11










          • @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
            – huon
            May 20 '16 at 13:14










          • Brilliant - thanks again.
            – Fraser
            May 20 '16 at 13:15


















          up vote
          1
          down vote













          A workaround for the coherence issue is to use Result::map_err to perform the conversion yourself. You can then use the end Result with try! or ?:



          fn example<S: Storage>(s: S) -> Result<i32, MyError<S>> {
          s.do_a_thing().map_err(MyError::StorageProblem)?;
          Ok(42)
          }


          This solution is also valuable when there are error variants that have the same underlying Error, such as if you want to separate "file opening" and "file reading" errors, both of which are io::Error.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37347311%2fhow-is-there-a-conflicting-implementation-of-from-when-using-a-generic-type%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            8
            down vote



            accepted










            The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).



            Specifically,



            struct Tricky;

            impl Storage for Tricky {
            type Error = MyError<Tricky>;
            }


            (The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)



            If we substitute Tricky in place of S in your impl, we get:



            impl From<MyError<Tricky>> for MyError<Tricky> {
            ...
            }


            This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.



            This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.






            share|improve this answer























            • Has the extension been implemented in nightly now?
              – WiSaGaN
              May 20 '16 at 13:08










            • No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
              – huon
              May 20 '16 at 13:10










            • A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
              – Fraser
              May 20 '16 at 13:11










            • @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
              – huon
              May 20 '16 at 13:14










            • Brilliant - thanks again.
              – Fraser
              May 20 '16 at 13:15















            up vote
            8
            down vote



            accepted










            The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).



            Specifically,



            struct Tricky;

            impl Storage for Tricky {
            type Error = MyError<Tricky>;
            }


            (The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)



            If we substitute Tricky in place of S in your impl, we get:



            impl From<MyError<Tricky>> for MyError<Tricky> {
            ...
            }


            This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.



            This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.






            share|improve this answer























            • Has the extension been implemented in nightly now?
              – WiSaGaN
              May 20 '16 at 13:08










            • No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
              – huon
              May 20 '16 at 13:10










            • A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
              – Fraser
              May 20 '16 at 13:11










            • @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
              – huon
              May 20 '16 at 13:14










            • Brilliant - thanks again.
              – Fraser
              May 20 '16 at 13:15













            up vote
            8
            down vote



            accepted







            up vote
            8
            down vote



            accepted






            The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).



            Specifically,



            struct Tricky;

            impl Storage for Tricky {
            type Error = MyError<Tricky>;
            }


            (The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)



            If we substitute Tricky in place of S in your impl, we get:



            impl From<MyError<Tricky>> for MyError<Tricky> {
            ...
            }


            This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.



            This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.






            share|improve this answer














            The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).



            Specifically,



            struct Tricky;

            impl Storage for Tricky {
            type Error = MyError<Tricky>;
            }


            (The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)



            If we substitute Tricky in place of S in your impl, we get:



            impl From<MyError<Tricky>> for MyError<Tricky> {
            ...
            }


            This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.



            This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 20 '16 at 13:24

























            answered May 20 '16 at 13:04









            huon

            53.5k6142171




            53.5k6142171












            • Has the extension been implemented in nightly now?
              – WiSaGaN
              May 20 '16 at 13:08










            • No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
              – huon
              May 20 '16 at 13:10










            • A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
              – Fraser
              May 20 '16 at 13:11










            • @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
              – huon
              May 20 '16 at 13:14










            • Brilliant - thanks again.
              – Fraser
              May 20 '16 at 13:15


















            • Has the extension been implemented in nightly now?
              – WiSaGaN
              May 20 '16 at 13:08










            • No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
              – huon
              May 20 '16 at 13:10










            • A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
              – Fraser
              May 20 '16 at 13:11










            • @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
              – huon
              May 20 '16 at 13:14










            • Brilliant - thanks again.
              – Fraser
              May 20 '16 at 13:15
















            Has the extension been implemented in nightly now?
            – WiSaGaN
            May 20 '16 at 13:08




            Has the extension been implemented in nightly now?
            – WiSaGaN
            May 20 '16 at 13:08












            No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
            – huon
            May 20 '16 at 13:10




            No, and in fact the restricted form is still available only in nightly. I believe the intention is to let that bake for a bit/iron out the bugs before diving into the more flexible/powerful versions.
            – huon
            May 20 '16 at 13:10












            A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
            – Fraser
            May 20 '16 at 13:11




            A clear answer: thanks. I guess the error message could be a bit clearer if it said something like there could be conflicting implementations rather than implying there already are.
            – Fraser
            May 20 '16 at 13:11












            @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
            – huon
            May 20 '16 at 13:14




            @Fraser, yeah, definitely, I guess it may be covered by github.com/rust-lang/rust/issues/23980 (I'll write a comment summarising this particular piece of confusion there).
            – huon
            May 20 '16 at 13:14












            Brilliant - thanks again.
            – Fraser
            May 20 '16 at 13:15




            Brilliant - thanks again.
            – Fraser
            May 20 '16 at 13:15












            up vote
            1
            down vote













            A workaround for the coherence issue is to use Result::map_err to perform the conversion yourself. You can then use the end Result with try! or ?:



            fn example<S: Storage>(s: S) -> Result<i32, MyError<S>> {
            s.do_a_thing().map_err(MyError::StorageProblem)?;
            Ok(42)
            }


            This solution is also valuable when there are error variants that have the same underlying Error, such as if you want to separate "file opening" and "file reading" errors, both of which are io::Error.






            share|improve this answer



























              up vote
              1
              down vote













              A workaround for the coherence issue is to use Result::map_err to perform the conversion yourself. You can then use the end Result with try! or ?:



              fn example<S: Storage>(s: S) -> Result<i32, MyError<S>> {
              s.do_a_thing().map_err(MyError::StorageProblem)?;
              Ok(42)
              }


              This solution is also valuable when there are error variants that have the same underlying Error, such as if you want to separate "file opening" and "file reading" errors, both of which are io::Error.






              share|improve this answer

























                up vote
                1
                down vote










                up vote
                1
                down vote









                A workaround for the coherence issue is to use Result::map_err to perform the conversion yourself. You can then use the end Result with try! or ?:



                fn example<S: Storage>(s: S) -> Result<i32, MyError<S>> {
                s.do_a_thing().map_err(MyError::StorageProblem)?;
                Ok(42)
                }


                This solution is also valuable when there are error variants that have the same underlying Error, such as if you want to separate "file opening" and "file reading" errors, both of which are io::Error.






                share|improve this answer














                A workaround for the coherence issue is to use Result::map_err to perform the conversion yourself. You can then use the end Result with try! or ?:



                fn example<S: Storage>(s: S) -> Result<i32, MyError<S>> {
                s.do_a_thing().map_err(MyError::StorageProblem)?;
                Ok(42)
                }


                This solution is also valuable when there are error variants that have the same underlying Error, such as if you want to separate "file opening" and "file reading" errors, both of which are io::Error.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 4 '17 at 15:06

























                answered Oct 9 '17 at 15:27









                Shepmaster

                144k11268401




                144k11268401






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37347311%2fhow-is-there-a-conflicting-implementation-of-from-when-using-a-generic-type%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Florida Star v. B. J. F.

                    Danny Elfman

                    Lugert, Oklahoma