Description
This is the summary issue for the incoherent_fundamental_impls
future-compatibility warning and other related errors. The goal of
this page is describe why this change was made and how you can fix
code that is affected by it. It also provides a place to ask questions
or register a complaint if you feel the change should not be made. For
more information on the policy around future-compatibility warnings,
see our breaking change policy guidelines.
What is the warning for?
What is coherence
Rust relies coherence to ensure that for every use of a trait item, there is a single impl that is used to provide it. This is important for general understandability, and also for ensuring soundness in the presence of associated types.
While coherence is a relation between 2 impls of a single trait, in more complicated cases, coherence can rely on the non-existence of impls for a different trait.
For example, in one long-present case in libstd
, std::str::pattern::Pattern
is implemented for both char
and all types implementing FnMut(char) -> bool
, allowing searching strings using str::contains
with both characters (my_str.contains('a')
) and predicates on characters (my_str.contains(|c| c.is_uppercase())
).
However, in order to be coherent, that relies on char
not implementing FnMut(char) -> bool
! If char
behaved like a function, it would be not obvious which impl would be used in the case of my_string.contains('a')
.
Therefore, when making sure the impls for Pattern
are coherent, the compiler has to check for impls in FnMut
.
Dependent Crate Coherence
Coherence checking is sometimes more subtle. For example, in this wrong case, found in the crate rusqlite
:
// This code is WRONG
pub enum ValueRef<'a> {
// ...
}
pub enum Value {
// ...
}
pub trait ToSqlOutput<'a> {
// ...
}
impl<'a> From<&'a str> for ValueRef<'a> {
// ...
}
impl<'a> From<String> for Value {
// ...
}
impl<'a, T: ?Sized> From<&'a T> for dyn ToSqlOutput<'a>
where
&'a T: Into<ValueRef<'a>>
{
// ...
}
impl<'a, T: Into<Value>> From<T> for dyn ToSqlOutput<'a> {
//~^ ERROR conflicting implementations
// ...
}
This code would violate coherence if there exists a type &'a T
where both impls can be used. That would happen if both &'a T: Into<Value>
and &'a T: Into<ValueRef<'a>>
.
We can see in the code that the only types that are Into<Value>
are Value
(using the identity impl for From
) and String
(using the explicit impl for From
), so no reference can be Into<Value>
, and it would seem that coherence holds.
In that case, why is that code wrong? As compiling that crate will tell you, "downstream crates may implement trait std::convert::From<&_>
for type Value
". Even through there is no impl for Value
in this crate, a dependent crate could implement both From<&MyReference> for Value
and From<&'a MyReference> for ValueRef<'a>
without breaking the orphan rules, causing a coherence conflict for From<&'a MyReference> for ToSqlOutput<'a>
.
While all versions of rustc try to catch this sort of trick, older versions had a subtle bug that would miss it in more complicated cases (such as the above) which means that the code that appeared to work in the wild (as long as nobody actually did the tricky impls) is now not compiling.
How to fix this?
Are you seeing the warning in another crate or in your dependencies? We've made a big effort to ensure that there are newer versions available for crates that avoid this error. Upgrading will likely fix your problem:
- gtk-rs: upgrade to at least 0.4
- rusqlite: upgrade to at least 0.14
- nalgebra: upgrade to at least 0.15
- spade: upgrade or refresh the Cargo.lock file to use version 1.7
- imageproc: upgrade to at least 0.16
If however you are getting the warning for your own code, then read on: As this warning indicates a deep problem in the way the impls in the crate appear, there is no fix that works in all cases. However, it is often possible to change the impls a bit to get rid of the problem.
For example, rusqlite
changed the second generic impl (the one where T: Into<Value>
) to instead match all concrete cases:
impl<'a> From<String> for ToSqlOutput<'a> {
fn from(t: String) -> Self { /* ... */ }
}
// <other cases>
Now, we already know that String
isn't Into<ValueRef<'a>>
, and no dependent crate can add such an impl, as the orphan rule would stop them in their tracks, which means coherence is restored!
When will this warning become a hard error?
At the beginning of each 6-week release cycle, the Rust compiler team
will review the set of outstanding future compatibility warnings and
nominate some of them for Final Comment Period. Toward the end of
the cycle, we will review any comments and make a final determination
whether to convert the warning into a hard error or remove it
entirely.
Activity