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

E0122 says bounds aren't enforced, but they actually are? #40640

Open
clarfonthey opened this issue Mar 18, 2017 · 12 comments
Open

E0122 says bounds aren't enforced, but they actually are? #40640

clarfonthey opened this issue Mar 18, 2017 · 12 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@clarfonthey
Copy link
Contributor

clarfonthey commented Mar 18, 2017

For multistr I've included trait bounds in type aliases so that it's clear in the documentation what should be passed to the generics for these aliases, e.g. SliceArray5.

But because I've generated several of these aliases E0122 floods my error output and I don't see any way of turning it off:

warning[E0122]: trait bounds are not (yet) enforced in type definitions
   --> src/array.rs:166:13
    |
166 |             pub type $slice_name<T: 'static + Copy> = $name<[T]>;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

(× 17)

It'd be really nice if I could silence this error somehow, because while it's good to have the error by default, it's making debugging my code very hard when I have to scroll past a wall of these errors.

@nagisa
Copy link
Member

nagisa commented Mar 19, 2017

Future compatibility warnings are made explicitly un"turn-off"able exactly because people "turn-off" them and then when stable version making it a hard error releases, complain on rust-lang/rust that their code was broken without any prior warning.

@durka
Copy link
Contributor

durka commented Mar 19, 2017

How hard is it to enforce trait bounds in type aliases?

@Kixunil
Copy link
Contributor

Kixunil commented May 1, 2017

I've run into similar issue recently. What's weird is that compiler actually does enforce trait bounds in type aliases, at least in this case. If you try to compile the example, you'll see that compiler contradicts itself. I can't imagine a universe in which it isn't a bug.

@jsgf
Copy link
Contributor

jsgf commented May 12, 2017

In my case I want to use a trait's associated types, so the type bound is unavoidable:

type CacheHash<F: Filler> = BoundedHash<F::Key, Slot<<F::Value as IntoFuture>::Future>>;

For this use the message is pure noise.

And as @Kixunil mentioned: it looks like the bound is enforced:

trait Foo {
    type Bar;
    type Biff;
}

type Thing<F: Foo> = (F::Bar, F::Biff);

fn main() {
    let v: Thing<u32> = unimplemented!();
}

fails to compile with:

rustc 1.17.0 (56124baa9 2017-04-24)
warning[E0122]: trait bounds are not (yet) enforced in type definitions
 --> <anon>:6:1
  |
6 | type Thing<F: Foo> = (F::Bar, F::Biff);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `u32: Foo` is not satisfied
 --> <anon>:9:12
  |
9 |     let v: Thing<u32> = unimplemented!();
  |            ^^^^^^^^^^ the trait `Foo` is not implemented for `u32`

error: aborting due to previous error

Playground: https://play.rust-lang.org/?gist=85d34e30da9c6ba78893fd885ab05547

@durka
Copy link
Contributor

durka commented May 12, 2017

Shockingly, you're allowed to make a type alias using associated types without declaring the bounds:

type Foo<I> = Box<<I as Iterator>::Item>;

@jsgf
Copy link
Contributor

jsgf commented May 12, 2017

Oh, interesting! I hadn't considered that variation.

@clarfonthey clarfonthey changed the title Option to silence E0122 Actually enforce trait bounds on type definitions (E0122) May 12, 2017
@clarfonthey clarfonthey changed the title Actually enforce trait bounds on type definitions (E0122) E0122 says bounds aren't enforced, but they actually are? May 12, 2017
@jsgf
Copy link
Contributor

jsgf commented May 12, 2017

I think the message is referring to the fact that you can do something like this without raising an error:

trait Thing {}

type Alias<T: Thing> = (T);

type Bad = Alias<i32>; // i32 doesn't implement Thing, but no error

You do get an error if Bad is actually used though.

@Kixunil
Copy link
Contributor

Kixunil commented May 13, 2017

@durka Interesting. Seems like the best way to turn off that message is to remove the bound and put it into doc comment.

@johncf
Copy link
Contributor

johncf commented May 28, 2017

Any plans for actually enforcing these bounds soon?

Future compatibility warnings are made explicitly un"turn-off"able exactly because people "turn-off" them and then when stable version making it a hard error releases, complain on rust-lang/rust that their code was broken without any prior warning.

In most cases, objects which don't satisfy those bounds cannot be created (due to other bounds). I don't think this is significant enough to put Rust's stability guarantees at risk. So please make these warnings suppress-able, if this is at low priority for being implemented.

@steveklabnik
Copy link
Member

Triage: as far as I know, these warnings are not silence-able today.

@clarfonthey
Copy link
Contributor Author

Checking the linked playground, and just off memory, I believe this error message has been removed? Is there anything left to do here?

@durka
Copy link
Contributor

durka commented May 22, 2023

Looks like it is still there if you don't attempt to use the alias: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=c12b07f4ca88e40071ccfdbe2167e347

warning: bounds on generic parameters are not enforced in type aliases
  --> src/main.rs:10:16
   |
10 | type FooBar<F: Foo> = Bar<F, F::SomeType>;
   |                ^^^
   |
help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
  --> src/main.rs:10:30
   |
10 | type FooBar<F: Foo> = Bar<F, F::SomeType>;
   |                              ^^^^^^^^^^^
   = note: `#[warn(type_alias_bounds)]` on by default
help: the bound will not be checked when the type alias is used, and should be removed
   |
10 - type FooBar<F: Foo> = Bar<F, F::SomeType>;
10 + type FooBar<F> = Bar<F, F::SomeType>;
   |

It seems to me the compiler is not enforcing the bounds in the alias.

Rather, it's enforcing implicit bounds that come from using a fully qualified associated type in the right side of the alias, as I noted above.

That is, if you remove the SomeType piece of the example, then the warning is true and the compiler will let you instantiate a FooBar<u32>. But even if you remove the F: Foo bound, and you use <F as Foo>::SomeType on the RHS, then you get a bounds error when trying to instantiate FooBar<u32>. This is weird to me; it seems like more of a C++ templates paradigm where you can hum merrily along until you try to instantiate your types and everything explodes -- and I like Rust better where the mistakes generally get caught at the beginning.

Circling back around to @steveklabnik's comment, the warnings are now silenceable with #[allow(type_alias_bounds)]. But I don't know that that closes this issue.

With compiler-colored glasses, the only issue is that we don't enforce bounds declared in type aliases (why though?), but it's definitely a confusing diagnostic situation in all of these cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants