Trait bounds defined inside a where clause are a superset of the trait bounds declared inline. The inline style existed before the where clause; the where clause was introduced in RFC 135:
Add where clauses, which provide a more expressive means of
specifying trait parameter bounds. [...] The existing bounds notation
would remain as syntactic sugar for where clauses.
Here is a list of limitations with the current bounds syntax that are
overcome with the where syntax:
It cannot express bounds on anything other than type parameters. Therefore, if you have a function generic in T, you can write
T:MyTrait to declare that T must implement MyTrait, but you can't
write Option<T> : MyTrait or (int, T) : MyTrait. These forms are less
commonly required but still important.
It does not work well with associated types. This is because there is no space to specify the value of an associated type. Other
languages use where clauses (or something analogous) for this purpose.
It's just plain hard to read. Experience has shown that as the number of bounds grows, the current syntax becomes hard to read and
format.
Since then you can also use higher-ranked trait bounds (for <'a> ...) in a where clause:
fn foo<T, U>()
where
// higher-ranked trait bounds
for<'a> T: SomethingElse<'a>,
// Bound not directly on the generic type
i32: From<U>,
T: Iterator,
// Bound on an associated type
T::Item: Clone,
// Just really long
U: ReallyLong + AnotherReallyLong + WowReallyLong,
{}
If your needs can be met by the inline trait bounds, then there is no impact on your code. If you need the extra powers that only where enables, then you need to use where.
See also:
My personal style is to always use the where form. Having a single shape that is also easier to git diff when adding new bounds is worth the extra line of code for me.