1- use crate :: solve:: FulfillmentCtxt ;
21use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
3- use crate :: traits:: { self , DefiningAnchor , ObligationCtxt } ;
2+ use crate :: traits:: { self , DefiningAnchor , ObligationCtxt , SelectionContext } ;
43
4+ use crate :: traits:: TraitEngineExt as _;
55use rustc_hir:: def_id:: DefId ;
66use rustc_hir:: lang_items:: LangItem ;
7- use rustc_infer:: traits:: { TraitEngine , TraitEngineExt } ;
7+ use rustc_infer:: traits:: { Obligation , TraitEngine , TraitEngineExt as _ } ;
88use rustc_middle:: arena:: ArenaAllocatable ;
99use rustc_middle:: infer:: canonical:: { Canonical , CanonicalQueryResponse , QueryResponse } ;
1010use rustc_middle:: traits:: query:: NoSolution ;
11+ use rustc_middle:: traits:: ObligationCause ;
1112use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable , TypeVisitableExt } ;
1213use rustc_middle:: ty:: { GenericArg , ToPredicate } ;
1314use rustc_span:: DUMMY_SP ;
@@ -21,24 +22,36 @@ pub trait InferCtxtExt<'tcx> {
2122
2223 fn type_is_sized_modulo_regions ( & self , param_env : ty:: ParamEnv < ' tcx > , ty : Ty < ' tcx > ) -> bool ;
2324
24- /// Check whether a `ty` implements given trait(trait_def_id).
25+ /// Check whether a `ty` implements given trait(trait_def_id) without side-effects.
26+ ///
2527 /// The inputs are:
2628 ///
2729 /// - the def-id of the trait
2830 /// - the type parameters of the trait, including the self-type
2931 /// - the parameter environment
3032 ///
3133 /// Invokes `evaluate_obligation`, so in the event that evaluating
32- /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent (or EvaluatedToAmbigStackDependent)
33- /// will be returned.
34+ /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent
35+ /// (or EvaluatedToAmbigStackDependent) will be returned.
3436 fn type_implements_trait (
3537 & self ,
3638 trait_def_id : DefId ,
3739 params : impl IntoIterator < Item : Into < GenericArg < ' tcx > > > ,
3840 param_env : ty:: ParamEnv < ' tcx > ,
3941 ) -> traits:: EvaluationResult ;
4042
41- fn could_impl_trait (
43+ /// Returns `Some` if a type implements a trait shallowly, without side-effects,
44+ /// along with any errors that would have been reported upon further obligation
45+ /// processing.
46+ ///
47+ /// - If this returns `Some([])`, then the trait holds modulo regions.
48+ /// - If this returns `Some([errors..])`, then the trait has an impl for
49+ /// the self type, but some nested obligations do not hold.
50+ /// - If this returns `None`, no implementation that applies could be found.
51+ ///
52+ /// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
53+ /// this will probably only ever return `Some([])` or `None`.
54+ fn type_implements_trait_shallow (
4255 & self ,
4356 trait_def_id : DefId ,
4457 ty : Ty < ' tcx > ,
@@ -86,64 +99,26 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
8699 self . evaluate_obligation ( & obligation) . unwrap_or ( traits:: EvaluationResult :: EvaluatedToErr )
87100 }
88101
89- fn could_impl_trait (
102+ fn type_implements_trait_shallow (
90103 & self ,
91104 trait_def_id : DefId ,
92105 ty : Ty < ' tcx > ,
93106 param_env : ty:: ParamEnv < ' tcx > ,
94107 ) -> Option < Vec < traits:: FulfillmentError < ' tcx > > > {
95108 self . probe ( |_snapshot| {
96- if let ty:: Adt ( def, args) = ty. kind ( )
97- && let Some ( ( impl_def_id, _) ) = self
98- . tcx
99- . all_impls ( trait_def_id)
100- . filter_map ( |impl_def_id| {
101- self . tcx . impl_trait_ref ( impl_def_id) . map ( |r| ( impl_def_id, r) )
102- } )
103- . map ( |( impl_def_id, imp) | ( impl_def_id, imp. skip_binder ( ) ) )
104- . find ( |( _, imp) | match imp. self_ty ( ) . peel_refs ( ) . kind ( ) {
105- ty:: Adt ( i_def, _) if i_def. did ( ) == def. did ( ) => true ,
106- _ => false ,
107- } )
108- {
109- let mut fulfill_cx = FulfillmentCtxt :: new ( self ) ;
110- // We get all obligations from the impl to talk about specific
111- // trait bounds.
112- let obligations = self
113- . tcx
114- . predicates_of ( impl_def_id)
115- . instantiate ( self . tcx , args)
116- . into_iter ( )
117- . map ( |( clause, span) | {
118- traits:: Obligation :: new (
119- self . tcx ,
120- traits:: ObligationCause :: dummy_with_span ( span) ,
121- param_env,
122- clause,
123- )
124- } )
125- . collect :: < Vec < _ > > ( ) ;
126- fulfill_cx. register_predicate_obligations ( self , obligations) ;
127- let trait_ref = ty:: TraitRef :: new ( self . tcx , trait_def_id, [ ty] ) ;
128- let obligation = traits:: Obligation :: new (
129- self . tcx ,
130- traits:: ObligationCause :: dummy ( ) ,
131- param_env,
132- trait_ref,
133- ) ;
134- fulfill_cx. register_predicate_obligation ( self , obligation) ;
135- let mut errors = fulfill_cx. select_all_or_error ( self ) ;
136- // We remove the last predicate failure, which corresponds to
137- // the top-level obligation, because most of the type we only
138- // care about the other ones, *except* when it is the only one.
139- // This seems to only be relevant for arbitrary self-types.
140- // Look at `tests/ui/moves/move-fn-self-receiver.rs`.
141- if errors. len ( ) > 1 {
142- errors. truncate ( errors. len ( ) - 1 ) ;
109+ let mut selcx = SelectionContext :: new ( self ) ;
110+ match selcx. select ( & Obligation :: new (
111+ self . tcx ,
112+ ObligationCause :: dummy ( ) ,
113+ param_env,
114+ ty:: TraitRef :: new ( self . tcx , trait_def_id, [ ty] ) ,
115+ ) ) {
116+ Ok ( Some ( selection) ) => {
117+ let mut fulfill_cx = <dyn TraitEngine < ' tcx > >:: new ( self ) ;
118+ fulfill_cx. register_predicate_obligations ( self , selection. nested_obligations ( ) ) ;
119+ Some ( fulfill_cx. select_all_or_error ( self ) )
143120 }
144- Some ( errors)
145- } else {
146- None
121+ Ok ( None ) | Err ( _) => None ,
147122 }
148123 } )
149124 }
0 commit comments