@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
33
44#[ cfg( feature = "nightly" ) ]
55use rustc_macros:: StableHash ;
6- use rustc_type_ir:: data_structures:: HashSet ;
6+ use rustc_type_ir:: data_structures:: { HashMap , HashSet } ;
77use rustc_type_ir:: inherent:: * ;
88use rustc_type_ir:: region_constraint:: { RegionConstraint , evaluate_solver_constraint} ;
99use rustc_type_ir:: relate:: Relate ;
@@ -18,8 +18,8 @@ use rustc_type_ir::solve::{
1818} ;
1919use rustc_type_ir:: {
2020 self as ty, CanonicalVarValues , ClauseKind , InferCtxtLike , Interner , MayBeErased ,
21- OpaqueTypeKey , PredicateKind , Region , TypeFoldable , TypeSuperVisitable , TypeVisitable ,
22- TypeVisitableExt , TypeVisitor , TypingMode , eager_resolve_vars,
21+ OpaqueTypeKey , PredicateKind , Region , RegionVid , TypeFoldable , TypeSuperVisitable ,
22+ TypeVisitable , TypeVisitableExt , TypeVisitor , TypingMode , eager_resolve_vars,
2323} ;
2424use thin_vec:: ThinVec ;
2525use tracing:: { Level , debug, instrument, trace, warn} ;
@@ -1608,6 +1608,60 @@ where
16081608 r. retain ( |( outlives, _) | !outlives. is_trivial ( ) && unique. insert ( * outlives) ) ;
16091609 }
16101610
1611+ #[ derive( Default ) ]
1612+ struct TrivialVars {
1613+ counts : HashMap < RegionVid , usize > ,
1614+ }
1615+ impl < I > TypeVisitor < I > for TrivialVars
1616+ where
1617+ I : Interner ,
1618+ {
1619+ type Result = ( ) ;
1620+ fn visit_ty ( & mut self , t : I :: Ty ) {
1621+ // If a nested type doesn't have any `ReVar`s, then visiting it won't affect
1622+ // our `counts` anyway, so skip visiting it entirely for better perf.
1623+ if !t. has_infer_regions ( ) {
1624+ return ;
1625+ }
1626+ t. super_visit_with ( self ) ;
1627+ }
1628+ fn visit_const ( & mut self , c : I :: Const ) {
1629+ // The same goes for consts.
1630+ if !c. has_infer_regions ( ) {
1631+ return ;
1632+ }
1633+ c. super_visit_with ( self ) ;
1634+ }
1635+ fn visit_region ( & mut self , r : Region < I > ) {
1636+ if let ty:: ReVar ( vid) = r. kind ( ) {
1637+ * self . counts . entry ( vid) . or_insert ( 0 ) += 1 ;
1638+ }
1639+ }
1640+ }
1641+
1642+ // If we have a constraint like `'re: '?1`, and `?1` appears nowhere else in the response
1643+ // besides the constraint itself, then this kind of constraint is also trivial, since
1644+ // one can always pick `'?1 := 'empty`, and `'re: 'empty` is always true for any 're.
1645+ if !external_constraints. region_constraints . is_empty ( ) {
1646+ let mut vis = TrivialVars :: default ( ) ;
1647+ var_values. visit_with ( & mut vis) ;
1648+ external_constraints. visit_with ( & mut vis) ;
1649+
1650+ if let ExternalRegionConstraints :: Old ( r) = & mut external_constraints. region_constraints
1651+ {
1652+ r. retain ( |( outlives, _) | {
1653+ if let ty:: RegionConstraint :: Outlives ( ty:: OutlivesClause ( sup, re) ) = * outlives
1654+ && sup. as_region ( ) . is_some ( )
1655+ && let ty:: RegionKind :: ReVar ( vid) = re. kind ( )
1656+ {
1657+ vis. counts . get ( & vid) . is_some_and ( |c| * c > 1 )
1658+ } else {
1659+ true
1660+ }
1661+ } ) ;
1662+ }
1663+ }
1664+
16111665 let canonical = canonicalize_response (
16121666 self . delegate ,
16131667 self . max_input_universe ,
0 commit comments