@@ -12,7 +12,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind};
1212use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
1313use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1414use rustc_infer:: infer:: { self , InferCtxt , TyCtxtInferExt } ;
15- use rustc_infer:: traits:: util;
15+ use rustc_infer:: traits:: { util, Obligation } ;
1616use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
1717use rustc_middle:: ty:: util:: ExplicitSelf ;
1818use rustc_middle:: ty:: {
@@ -190,15 +190,13 @@ fn compare_method_predicate_entailment<'tcx>(
190190 . map ( |( predicate, _) | predicate) ,
191191 ) ;
192192
193+ let caller_bounds = filter_trivial_predicates ( tcx, hybrid_preds. predicates ) ;
194+
193195 // Construct trait parameter environment and then shift it into the placeholder viewpoint.
194196 // The key step here is to update the caller_bounds's predicates to be
195197 // the new hybrid bounds we computed.
196198 let normalize_cause = traits:: ObligationCause :: misc ( impl_m_span, impl_m_def_id) ;
197- let param_env = ty:: ParamEnv :: new (
198- tcx. mk_predicates ( & hybrid_preds. predicates ) ,
199- Reveal :: UserFacing ,
200- hir:: Constness :: NotConst ,
201- ) ;
199+ let param_env = ty:: ParamEnv :: new ( caller_bounds, Reveal :: UserFacing , hir:: Constness :: NotConst ) ;
202200 let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
203201
204202 let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
@@ -2080,3 +2078,83 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
20802078 ty:: AssocKind :: Type => "type" ,
20812079 }
20822080}
2081+
2082+ // FIXME(-Ztrait-solver=next): This hack should be unnecessary with the new trait
2083+ // solver as it is better at dealing with ambiguity.
2084+ //
2085+ // Even if this code isn't completely trivial, it only removes predicates so it
2086+ // should always remain sound.
2087+ #[ instrument( level = "debug" , skip( tcx, predicates) ) ]
2088+ fn filter_trivial_predicates < ' tcx > (
2089+ tcx : TyCtxt < ' tcx > ,
2090+ mut predicates : Vec < ty:: Predicate < ' tcx > > ,
2091+ ) -> & ' tcx ty:: List < ty:: Predicate < ' tcx > > {
2092+ // We start with a bad approximation of whether a predicate is trivial and put all
2093+ // non-trivial predicates into the environment used when checking whether the
2094+ // remaining ones are trivial.
2095+ let mut non_trivial_predicates = Vec :: new ( ) ;
2096+ for & predicate in predicates. iter ( ) {
2097+ if !may_be_trivial_predicate ( predicate) {
2098+ non_trivial_predicates. push ( predicate) ;
2099+ }
2100+ }
2101+
2102+ let non_trivial_predicates = tcx. mk_predicates ( & non_trivial_predicates) ;
2103+ if non_trivial_predicates. len ( ) == predicates. len ( ) {
2104+ non_trivial_predicates
2105+ } else {
2106+ let param_env =
2107+ ty:: ParamEnv :: new ( non_trivial_predicates, Reveal :: UserFacing , hir:: Constness :: NotConst ) ;
2108+ predicates. retain ( |& p| !is_trivial_predicate ( tcx, param_env, p) ) ;
2109+ tcx. mk_predicates ( & predicates)
2110+ }
2111+ }
2112+
2113+ // A bad approximation of whether a predicate is trivial. Used to put all non-trivial
2114+ // predicates into the environment while checking whether the remaining ones are trivial.
2115+ fn may_be_trivial_predicate < ' tcx > ( predicate : ty:: Predicate < ' tcx > ) -> bool {
2116+ // We only consider trait and projection predicates which don't have a parameter
2117+ // as a self type as potentially non-trivial.
2118+ match predicate. kind ( ) . skip_binder ( ) {
2119+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( predicate) ) => {
2120+ !matches ! ( predicate. self_ty( ) . kind( ) , ty:: Param ( _) )
2121+ }
2122+ ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( predicate) ) => {
2123+ !matches ! ( predicate. self_ty( ) . kind( ) , ty:: Param ( _) )
2124+ }
2125+ _ => false ,
2126+ }
2127+ }
2128+
2129+ /// Returns whether `predicate` is trivially provable in the empty environment.
2130+ ///
2131+ /// While it's definitely trivial if we return `Yes`, this function is incomplete,
2132+ /// so it may incorrectly return `No` even though the `predicate` is actually trivial.
2133+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
2134+ fn is_trivial_predicate < ' tcx > (
2135+ tcx : TyCtxt < ' tcx > ,
2136+ param_env : ty:: ParamEnv < ' tcx > ,
2137+ predicate : ty:: Predicate < ' tcx > ,
2138+ ) -> bool {
2139+ if !may_be_trivial_predicate ( predicate) {
2140+ return false ;
2141+ }
2142+
2143+ let infcx = tcx. infer_ctxt ( ) . build ( ) ;
2144+ // HACK: This can overflow and we must not abort here as that would break existing
2145+ // crates, most notably `typenum`.
2146+ //
2147+ // To deal with this we change overflow to only abort trait solving without
2148+ // aborting compilation. This means that this code isn't complete and may
2149+ // incorrectly error which is acceptable as this is just a best effort.
2150+ let ocx = ObligationCtxt :: with_query_mode_canonical ( & infcx) ;
2151+ let obligation = Obligation :: new ( tcx, ObligationCause :: dummy ( ) , param_env, predicate) ;
2152+ ocx. register_obligation ( obligation) ;
2153+ if ocx. select_all_or_error ( ) . is_empty ( ) {
2154+ let outlives_env = OutlivesEnvironment :: new ( param_env) ;
2155+ infcx. process_registered_region_obligations ( outlives_env. region_bound_pairs ( ) , param_env) ;
2156+ infcx. resolve_regions ( & outlives_env) . is_empty ( )
2157+ } else {
2158+ false
2159+ }
2160+ }
0 commit comments