@@ -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, max_universe ,
2323} ;
2424use thin_vec:: ThinVec ;
2525use tracing:: { Level , debug, instrument, trace, warn} ;
@@ -1608,6 +1608,65 @@ 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`, where '?1 can name 're and '?1 appears
1643+ // nowhere else in the response besides the constraint itself, then this kind of
1644+ // constraint is also trivial, since we're able to pick '?1 := 'empty, and 're: 'empty
1645+ // is always true for any 're.
1646+ if !external_constraints. region_constraints . is_empty ( ) {
1647+ let mut vis = TrivialVars :: default ( ) ;
1648+ var_values. visit_with ( & mut vis) ;
1649+ external_constraints. visit_with ( & mut vis) ;
1650+
1651+ if let ExternalRegionConstraints :: Old ( r) = & mut external_constraints. region_constraints
1652+ {
1653+ r. retain ( |( outlives, _) | {
1654+ if let ty:: RegionConstraint :: Outlives ( ty:: OutlivesClause ( sup, re) ) = * outlives
1655+ && let Some ( sup_re) = sup. as_region ( )
1656+ && let ty:: RegionKind :: ReVar ( vid) = re. kind ( )
1657+ // This is only safe if we call `eager_resolve_vars` beforehand,
1658+ // which we do.
1659+ && self . delegate . universe_of_lt ( vid) . unwrap ( )
1660+ . can_name ( max_universe ( & * * self . delegate , sup_re) )
1661+ {
1662+ vis. counts . get ( & vid) . is_some_and ( |c| * c > 1 )
1663+ } else {
1664+ true
1665+ }
1666+ } ) ;
1667+ }
1668+ }
1669+
16111670 let canonical = canonicalize_response (
16121671 self . delegate ,
16131672 self . max_input_universe ,
0 commit comments