-
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
Use placeholders to prevent using inferred RPITIT types to imply their own well-formedness #116072
Conversation
108ab9c
to
8568121
Compare
a couple problems with this implementation:
#![feature(return_position_impl_trait_in_trait)]
trait Trait {
fn foo() -> impl Sized;
}
impl<T> Trait for &'static T {
fn foo() -> &'static T { loop {} } //~ERROR
}
trait Trait {
fn foo<T>() -> (&'static impl Sized, impl Sized);
}
impl Trait for () {
fn foo<T>() -> (&'static T, &'static T) { loop {} }
} Both cases seem rather rare and can hopefully be fixed later in a back-compat way, so I'm fine landing this PR as it is. |
@aliemjay: Good point. I can fix both of these in a quick follow-up after this PR (or just r- if you want me to fix them now, they both seem easy to do). |
Well, better to fix them here if you like so. |
In retrospect, this was a stupid idea :) #![feature(return_position_impl_trait_in_trait)]
use core::fmt::Display;
trait Trait {
fn foo(self) -> (Option<&'static (impl Sized + 'static)>, Box<dyn Display>);
}
impl<T: Display> Trait for T {
fn foo(self) -> (Option<&'static T>, Box<dyn Display>) {
(None, Box::new(self))
}
}
fn extend(arg: impl Trait) -> Box<dyn Display> {
arg.foo().1
}
fn main() {
let use_after_free = extend(&String::from("temporary"));
println!("{}", use_after_free);
} |
Actually yeah I'll do that implied-bounds-from-the-impl-header one in a separate pr @bors r=aliemjay |
…s, r=aliemjay Use placeholders to prevent using inferred RPITIT types to imply their own well-formedness The issue here is that we use the same signature to do RPITIT inference as we do to compute implied bounds. To fix this, when gathering the assumed wf types for the method, we replace all of the infer vars (that will be eventually used to infer RPITIT types) with type placeholders, which imply nothing about lifetime bounds. This solution kind of sucks, but I'm not certain there's another feasible way to fix this. If anyone has a better solution, I'd be glad to hear it. My naive first solution was, instead of using placeholders, to replace the signature with the RPITIT projections that it originally started out with. But turns out that we can't just use the unnormalized signature of the trait method in `implied_outlives_bounds` since we normalize during WF computation -- that would cause a query cycle in `collect_return_position_impl_trait_in_trait_tys`. idk who to request review... r? `@lcnr` or `@aliemjay` i guess. Fixes rust-lang#116060
💔 Test failed - checks-actions |
?? not related @bors retry |
The job Click to see the possible cause of the failure (guessed by this bot)
|
☀️ Test successful - checks-actions |
Finished benchmarking commit (a61f6f3): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)This benchmark run did not return any relevant results for this metric. CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 631.966s -> 630.902s (-0.17%) |
@compiler-errors do you think it would be useful to extend the rustc-dev-guide with the changes from this PR? It feels like there's a subtle soundness issue here so it would be good to document this as part of the "RPITIT overview". |
The issue here is that we use the same signature to do RPITIT inference as we do to compute implied bounds. To fix this, when gathering the assumed wf types for the method, we replace all of the infer vars (that will be eventually used to infer RPITIT types) with type placeholders, which imply nothing about lifetime bounds.
This solution kind of sucks, but I'm not certain there's another feasible way to fix this. If anyone has a better solution, I'd be glad to hear it.
My naive first solution was, instead of using placeholders, to replace the signature with the RPITIT projections that it originally started out with. But turns out that we can't just use the unnormalized signature of the trait method in
implied_outlives_bounds
since we normalize during WF computation -- that would cause a query cycle incollect_return_position_impl_trait_in_trait_tys
.idk who to request review...
r? @lcnr or @aliemjay i guess.
Fixes #116060