Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 71 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use rustc_type_ir::solve::{
};
use rustc_type_ir::{
self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased,
OpaqueTypeKey, PredicateKind, Region, TypeFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, TypingMode, eager_resolve_vars,
OpaqueTypeKey, PredicateKind, Region, RegionVid, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, eager_resolve_vars, max_universe,
};
use thin_vec::ThinVec;
use tracing::{Level, debug, instrument, trace, warn};
Expand Down Expand Up @@ -1608,6 +1608,75 @@ where
r.retain(|(outlives, _)| !outlives.is_trivial() && unique.insert(*outlives));
}

#[derive(Default)]
struct NonTrivialVars {
vars: HashSet<RegionVid>,
}
impl<I> TypeVisitor<I> for NonTrivialVars
where
I: Interner,
{
type Result = ();
fn visit_ty(&mut self, t: I::Ty) {
// If a nested type doesn't have any `ReVar`s, then we won't insert
// anything into `vars` anyway, so skip for better perf.
if !t.has_infer_regions() {
Comment thread
ShoyuVanilla marked this conversation as resolved.
return;
}
t.super_visit_with(self);
}
fn visit_const(&mut self, c: I::Const) {
// The same goes for consts.
if !c.has_infer_regions() {
return;
}
c.super_visit_with(self);
}
fn visit_region(&mut self, r: Region<I>) {
if let ty::ReVar(vid) = r.kind() {
self.vars.insert(vid);
}
}
}

// If we have a constraint like `'re: '?1`, where '?1 can name 're and '?1 appears
// only on the RHS of region constraints, then this kind of constraint is also trivial,
// since we're able to pick '?1 := 'empty, and 're: 'empty is always true for any 're.
if let ExternalRegionConstraints::Old(r) = &mut external_constraints.region_constraints
&& !r.is_empty()
{
let mut vis = NonTrivialVars::default();
var_values.visit_with(&mut vis);
// We have to visit each component of `external_constraints` individually here
// because we skip the RHS of outlives constraints, and `TypeVisitor` doesn't
// have a method we can easily override in order to do this.
external_constraints.opaque_types.visit_with(&mut vis);
external_constraints.normalization_nested_goals.visit_with(&mut vis);
for (constraint, _) in r.iter() {
match constraint {
ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, _)) => {
sup.visit_with(&mut vis)
}
ty::RegionConstraint::Eq(eq) => eq.visit_with(&mut vis),
}
}

r.retain(|(outlives, _)| {
if let ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, re)) = *outlives
&& let Some(sup_re) = sup.as_region()
&& let ty::RegionKind::ReVar(vid) = re.kind()
// This is only safe if we call `eager_resolve_vars` beforehand,
// which we do.
&& self.delegate.universe_of_lt(vid).unwrap()
.can_name(max_universe(&**self.delegate, sup_re))
{
vis.vars.contains(&vid)
} else {
true
}
});
}

let canonical = canonicalize_response(
self.delegate,
self.max_input_universe,
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/traits/next-solver/no-dedup-universes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ compile-flags: -Znext-solver -Zno-leak-check

//! Make sure we don't drop trivial-looking region constraints that would otherwise fail
//! leak check.

trait Trait {}
trait Other<'a, 'b> {}

struct Foo;
// We need this indirection because something direct like `for<'a> &'a (): 'b` gives us a
// TypeOutlives constraint, whereas we want to be testing how we handle RegionOutlives, and
// only `impl Other for Bar`'s where-clause can give us that.
impl<'b> Trait for Foo where for<'a> Bar: Other<'a, 'b> {}

struct Bar;
impl<'a, 'b> Other<'a, 'b> for Bar where 'a: 'b {}

fn f<T: Trait>(_: T) {}

fn main() { f(Foo); }
//~^ ERROR higher-ranked lifetime error
10 changes: 10 additions & 0 deletions tests/ui/traits/next-solver/no-dedup-universes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: higher-ranked lifetime error
--> $DIR/no-dedup-universes.rs:20:13
|
LL | fn main() { f(Foo); }
| ^^^^^^
|
= note: could not prove `Foo: Trait`

error: aborting due to 1 previous error

Loading