Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a minimum complete implementation to be specified for mutually recursive default methods #7771

Closed
huonw opened this issue Jul 13, 2013 · 10 comments
Labels
A-attributes Area: #[attributes(..)] A-diagnostics Area: Messages for errors, warnings, and lints A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-traits Area: Trait system

Comments

@huonw
Copy link
Member

huonw commented Jul 13, 2013

It should be possible to tell the compiler that at least one of a given set of default methods is required to be implemented, e.g.

#[requires(one_of(foo, bar), one_of(baz, qux))]
trait A {
   fn foo(&self) { self.bar() }
   fn bar(&self) { self.foo() }

   fn baz(&self) { self.qux() }
   fn qux(&self) { self.baz() }
}

impl A for int { // ok
   fn foo(&self) {}
   fn bar(&self) {}

   fn baz(&self) {} 
}

impl A for uint { // "requires at least one of foo or bar"
   fn baz(&self) {}
}

impl A for float { // "requires at least one of baz or qux"
   fn foo(&self) {}
}

This allows e.g. Eq to write eq and ne in terms of each other, without allowing the infinitely recursive impl Eq for Foo {}.

It could even allow saying "either foo or both bar and baz", e.g. #[requires(one_of(foo, all_of(bar, baz)))], and would hopefully warn if a non-default method was listed.

@huonw
Copy link
Member Author

huonw commented Sep 19, 2013

This feature recently landed in GHC: http://ghc.haskell.org/trac/ghc/ticket/7633. Example of the syntax:

    {-# MINIMAL (.&.), (.|.), xor, complement,
                (shift | (shiftL, shiftR)),
                (rotate | (rotateL, rotateR)),
                bitSize, bitSizeMaybe, isSigned, testBit, bit, popCount #-}

Of particular note is that it supports nested conjunction/disjunction (, == and, | == or).

(taken from http://ghc.haskell.org/trac/ghc/changeset/7ab62490dbc1ea7430fe60d5dad9c3b0fa0bedad/base)

@huonw
Copy link
Member Author

huonw commented Feb 3, 2014

Triage, no change.

@pnkfelix
Copy link
Member

cc me

@huonw
Copy link
Member Author

huonw commented Jul 22, 2014

I think this can be entirely implemented as a lint plugin out of the the compiler, although some traits in the standard library (std::rand::Rng is one example I definitely know) would like it.

@SimonSapin
Copy link
Contributor

@huonw would that mean that incorrect impl in a different crate will build without error unless they load the lint themselves?

@huonw
Copy link
Member Author

huonw commented Jul 22, 2014

Yes it would, which is a good point, since it reduces the usefulness of the lint. But, it is just some assistance for avoiding accidental infinite recursion, i.e. not required for safety, or to get a correct impl. (I am personally in favour of it being in the compiler itself.)

It can certainly be prototyped out of tree to avoid the horrendous bootstrap times.

@SimonSapin
Copy link
Contributor

Yeah, that’s fine for prototyping, but I’d say that this limitation makes this feature useless as far as I’m concerned. Just because infinite recursion is not a memory-safety problem doesn’t mean it’s not a problem that the type system should help solve :)

@huonw
Copy link
Member Author

huonw commented Jul 22, 2014

This isn't a type system feature... but yes, your point stands.

@ghost ghost added the B-RFC label Oct 18, 2014
@lambda-fairy
Copy link
Contributor

We can copy the syntax for #[cfg] (RFC 194), using all() and any() for conjunctions and disjunctions respectively. Then @huonw's example will look something like this:

#[requires(any(foo, bar), any(baz, qux))]
trait A {
   // ...
}

I'm not sure whether we should allow not() though. Is there a use case for asserting that a method is not implemented?

@steveklabnik
Copy link
Member

I'm pulling a massive triage effort to get us ready for 1.0. As part of this, I'm moving stuff that's wishlist-like to the RFCs repo, as that's where major new things should get discussed/prioritized.

This issue has been moved to the RFCs repo: rust-lang/rfcs#628

nivkner added a commit to nivkner/rust that referenced this issue Sep 30, 2017
remove FIXME(rust-lang#13101) since `assert_receiver_is_total_eq` stays.
remove FIXME(rust-lang#19649) now that stability markers render.
remove FIXME(rust-lang#13642) now the benchmarks were moved.
remove FIXME(rust-lang#6220) now that floating points can be formatted.
remove FIXME(rust-lang#18248) and write tests for `Rc<str>` and `Rc<[u8]>`
remove reference to irelevent issues in FIXME(rust-lang#1697, rust-lang#2178...)
update FIXME(rust-lang#5516) to point to getopts issue 7
update FIXME(rust-lang#7771) to point to RFC 628
update FIXME(rust-lang#19839) to point to issue 26925
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: #[attributes(..)] A-diagnostics Area: Messages for errors, warnings, and lints A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-traits Area: Trait system
Projects
None yet
Development

No branches or pull requests

5 participants