implied bounds from projections in function signatures can be unsound
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
edit: we've fixed the non-higher ranked version for FnDef to FnPtr casts in #129021. However, we're aware that keeping the target of the function pointer cast higher-ranked, it's still possible to exploit this
trait ToArg<T> {
type Arg;
}
impl<T, U> ToArg<T> for U {
type Arg = T;
}
fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x }
fn extend<'a, 'b>(x: &'a str) -> &'b str {
(extend_inner as for<'hr> fn(&'hr str) -> &'b str)(x)
}
fn main() {
let y = extend(&String::from("Hello World"));
println!("{}", y);
}
Fixing this properly is blocked on properly tracking implied bounds on binders
Related to #100051, but the underlying reason is slightly different. The full fix will be the same however and is blocked on the new trait solver.
trait ToArg<T> {
type Arg;
}
impl<T, U> ToArg<T> for U {
type Arg = T;
}
fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x }
fn extend<'a, 'b>(x: &'a str) -> &'b str {
(extend_inner as fn(_) -> _)(x)
}
fn main() {
let y = extend(&String::from("Hello World"));
println!("{}", y);
}
Introduced by #99217. The idea of that PR was that we check that the unnormalized function signature is well-formed when calling a function. We previously only checked the normalized signature, causing another unsoundness #98543 by having an associated type which we're able to normalize in the definition, but not the use. Checking that the unnormalized signature is well-formed, without assuming that it is well-formed, resulted in breaking changes. Because of this, we changed it to both check, and assume, that the unnormalized function signature is well-formed. This would be sound, except that we can first cast the function to a function pointer, discarding its unnormalized signature, and then call it.
We may be able to partially fix this by checking that the unnormalized signature is well-formed when casting function definitions to function pointers. This still leaves us with the general set of unsound higher-ranked implied bounds, cc #100051 #84591 #25860, which can only really be fixed by supporting implications in the type systems. cc @rust-lang/types
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the two Rust reproducers using extend_inner and extend, then read the discussion of #129021, #100051, #84591 and #25860. Investigate how the new trait solver can track implied bounds on binders; done means the demonstrated function-pointer casts no longer permit the reported unsound behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100