@@ -12,7 +12,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind};
12
12
use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
13
13
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
14
14
use rustc_infer:: infer:: { self , InferCtxt , TyCtxtInferExt } ;
15
- use rustc_infer:: traits:: util;
15
+ use rustc_infer:: traits:: { util, Obligation } ;
16
16
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
17
17
use rustc_middle:: ty:: util:: ExplicitSelf ;
18
18
use rustc_middle:: ty:: {
@@ -190,15 +190,13 @@ fn compare_method_predicate_entailment<'tcx>(
190
190
. map ( |( predicate, _) | predicate) ,
191
191
) ;
192
192
193
+ let caller_bounds = filter_trivial_predicates ( tcx, hybrid_preds. predicates ) ;
194
+
193
195
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
194
196
// The key step here is to update the caller_bounds's predicates to be
195
197
// the new hybrid bounds we computed.
196
198
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 ) ;
202
200
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
203
201
204
202
let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
@@ -2080,3 +2078,83 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
2080
2078
ty:: AssocKind :: Type => "type" ,
2081
2079
}
2082
2080
}
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