-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Trait implementation accepts wrong lifetime in method signature with associated type #22077
Comments
This seems to be a problem with associated types, converting trait Fun<Output> {
fn call<'x>(&'x self) -> Output;
}
struct Holder { x: String }
impl<'a> Fun<&'a str> for Holder {
fn call<'b>(&'b self) -> &'b str {
&self.x[]
}
}
|
cc me. It feels very closely related to #21750, although on the surface they are quite the opposite. Also, @nikomatsakis may have something in the making for #21974. |
P-backcompat-lang, 1.0 beta. |
Possibly related to #21259. |
Have an fix in the same vein of #22338. But, it also reports an error
for libstd/collections/hash/map.rs: impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
where K: Eq + Hash<H>,
Q: Eq + Hash<H> + BorrowFrom<K>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
{
type Output = V;
#[inline]
fn index<'a>(&'a self, index: &Q) -> &'a V {
self.get(index).expect("no entry found for key")
}
}
impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
where K: Eq + Hash<H>,
Q: Eq + Hash<H> + BorrowFrom<K>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
{
#[inline]
fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
self.get_mut(index).expect("no entry found for key")
}
} Notice, the order of the type parameters is different. So is the error legit or does the fix simply have a regression? |
Otherwise, the substitution is carried out from outside perspective, which would be against the very purpose of `ParameterEnvironment`. Closes rust-lang#21750 Closes rust-lang#22077
Ah, I see. The problem is that the But this logic does not hold with associated types. They allow us to create links between a projected type and the return type of a method. In that case, it is harmful if there are lifetimes that are not constrained by the trait reference or the input types, since every instantiation of We should prohibit these unconstrainted lifetime parameters, either completely, or at minimum from appearing in the value of an associated type. |
Example illustrating soundness hole: struct Foo<'a> {
inner: &'a mut [u8]
}
impl<'a, 'b> Iterator for Foo<'a> {
type Item = &'b mut u8;
fn next(&mut self) -> Option<&mut u8> {
Some(&mut self.inner[0])
}
}
fn main() {
let mut fun = [1,2,3,4,5];
let mut foo = Foo {
inner: &mut fun
};
{
let a = foo.next().unwrap();
let b = foo.next().unwrap();
*a = 1;
*b = 2;
println!("{}", a);
}
} |
This is "just a bug", but one we would really like to fix. Nonetheless, not a beta-blocker. But we want to fix for 1.0; so reclassifying as such. |
…turon This makes it illegal to have unconstrained lifetimes that appear in an associated type definition. Arguably, we should prohibit all unconstrained lifetimes -- but it would break various macros. It'd be good to evaluate how large a break change it would be. But this seems like the minimal change we need to do to establish soundness, so we should land it regardless. Another variant would be to prohibit all lifetimes that appear in any impl item, not just associated types. I don't think that's necessary for soundness -- associated types are different because they can be projected -- but it would feel a bit more consistent and "obviously" safe. I'll experiment with that in the meantime. r? @aturon Fixes #22077.
(Sorry for the bad title)
This compiles even though the trait's definition should require
call
's signature in the impl to befn call<'b>(&'b self) -> &'a str
.The text was updated successfully, but these errors were encountered: