rust-lang / trait-system-refactor-initiative

The Rustc Trait System Refactor Initiative
21 stars 0 forks source link

stronger leak-check #37

Open aliemjay opened 1 year ago

aliemjay commented 1 year ago

investigate why this compiles under the new solver while fails under the old one.

trait Leak<'a> {}
impl<'a> Leak<'a> for Box<u32> {}
impl<'a> Leak<'a> for Box<u16> where 'a: 'static, {}

// This indirection is necessary to bypass #34
trait Indirect {}
impl Indirect for Box<u32> where Self: for<'a> Leak<'a>, {}
impl Indirect for Box<u16> where Self: for<'a> Leak<'a>, {}

fn impl_trait<T: Indirect>() {}

fn main() {
    impl_trait::<Box<_>>();
    //[current]~^ ERROR type annotations needed
}
compiler-errors commented 1 year ago

This makes sense to me. I'm actually surprised that this doesn't work in the old solver, since we do a leak check in the evaluation probe in the old solver :thinking:

compiler-errors commented 1 year ago

Oh, it doesn't trigger in the old solver because we literally just ignore region predicates in evaluate_predicates_recursively.

https://github.com/rust-lang/rust/blob/22e9fe644ea710eec50cb0aabcae7fa8dd9fd675/compiler/rustc_trait_selection/src/traits/select/mod.rs#L777

If we were to, e.g. call self.infcx.region_outlives_predicate(&obligation.cause, bound_predicate.rebind(outlives));, then the above code passes:

diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 160a1f30df9..6a7acecc96f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -779,8 +779,8 @@ fn evaluate_predicate_recursively<'o>(
                     }
                 }

-                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
-                    // We do not consider region relationships when evaluating trait matches.
+                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
+                    self.infcx.region_outlives_predicate(&obligation.cause, bound_predicate.rebind(outlives));
                     Ok(EvaluatedToOkModuloRegions)
                 }

I don't think it's necessary to apply this to the old solver, since it just turns ambiguity -> pass, but I'd be happy to open a PR and FCP it, I guess.