@@ -4,7 +4,7 @@ use crate::traits;
44use rustc_hir as hir;
55use rustc_hir:: def_id:: DefId ;
66use rustc_hir:: lang_items;
7- use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
7+ use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , SubstsRef } ;
88use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable , WithConstness } ;
99use rustc_span:: Span ;
1010use std:: rc:: Rc ;
@@ -37,14 +37,44 @@ pub fn obligations<'a, 'tcx>(
3737 } ;
3838
3939 let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item : None } ;
40- wf. compute ( ty) ;
40+ wf. compute ( ty. into ( ) ) ;
4141 debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
4242
4343 let result = wf. normalize ( ) ;
4444 debug ! ( "wf::obligations({:?}, body_id={:?}) ~~> {:?}" , ty, body_id, result) ;
4545 Some ( result)
4646}
4747
48+ /// Returns the set of obligations needed to make the `constant` well-formed.
49+ pub fn const_obligations < ' a , ' tcx > (
50+ infcx : & InferCtxt < ' a , ' tcx > ,
51+ param_env : ty:: ParamEnv < ' tcx > ,
52+ body_id : hir:: HirId ,
53+ constant : & ' tcx ty:: Const < ' tcx > ,
54+ span : Span ,
55+ ) -> Option < Vec < traits:: PredicateObligation < ' tcx > > > {
56+ let constant = match constant. val {
57+ ty:: ConstKind :: Infer ( infer) => {
58+ let resolved = infcx. shallow_resolve ( infer) ;
59+ if resolved == infer {
60+ // No progress.
61+ return None ;
62+ }
63+
64+ infcx. tcx . mk_const ( ty:: Const { val : ty:: ConstKind :: Infer ( resolved) , ..* constant } )
65+ }
66+ _ => constant,
67+ } ;
68+
69+ let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item : None } ;
70+ wf. compute ( constant. into ( ) ) ;
71+ debug ! ( "wf::const obligations({:?}, body_id={:?}) = {:?}" , constant, body_id, wf. out) ;
72+
73+ let result = wf. normalize ( ) ;
74+ debug ! ( "wf::const obligations({:?}, body_id={:?}) ~~> {:?}" , constant, body_id, result) ;
75+ Some ( result)
76+ }
77+
4878/// Returns the obligations that make this trait reference
4979/// well-formed. For example, if there is a trait `Set` defined like
5080/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
@@ -78,33 +108,36 @@ pub fn predicate_obligations<'a, 'tcx>(
78108 }
79109 ty:: PredicateKind :: RegionOutlives ( ..) => { }
80110 ty:: PredicateKind :: TypeOutlives ( t) => {
81- wf. compute ( t. skip_binder ( ) . 0 ) ;
111+ wf. compute ( t. skip_binder ( ) . 0 . into ( ) ) ;
82112 }
83113 ty:: PredicateKind :: Projection ( t) => {
84114 let t = t. skip_binder ( ) ; // (*)
85115 wf. compute_projection ( t. projection_ty ) ;
86- wf. compute ( t. ty ) ;
116+ wf. compute ( t. ty . into ( ) ) ;
87117 }
88118 & ty:: PredicateKind :: WellFormed ( t) => {
89- wf. compute ( t) ;
119+ wf. compute ( t. into ( ) ) ;
90120 }
91121 ty:: PredicateKind :: ObjectSafe ( _) => { }
92122 ty:: PredicateKind :: ClosureKind ( ..) => { }
93123 ty:: PredicateKind :: Subtype ( data) => {
94- wf. compute ( data. skip_binder ( ) . a ) ; // (*)
95- wf. compute ( data. skip_binder ( ) . b ) ; // (*)
124+ wf. compute ( data. skip_binder ( ) . a . into ( ) ) ; // (*)
125+ wf. compute ( data. skip_binder ( ) . b . into ( ) ) ; // (*)
96126 }
97127 & ty:: PredicateKind :: ConstEvaluatable ( def_id, substs) => {
98128 let obligations = wf. nominal_obligations ( def_id, substs) ;
99129 wf. out . extend ( obligations) ;
100130
101- for ty in substs. types ( ) {
102- wf. compute ( ty ) ;
131+ for subst in substs. iter ( ) . copied ( ) {
132+ wf. compute ( subst ) ;
103133 }
104134 }
105135 ty:: PredicateKind :: ConstEquate ( c1, c2) => {
106- wf. compute ( c1. ty ) ;
107- wf. compute ( c2. ty ) ;
136+ wf. compute ( c1. ty . into ( ) ) ;
137+ wf. compute ( c2. ty . into ( ) ) ;
138+ }
139+ ty:: Predicate :: WellFormedConst ( constant) => {
140+ wf. compute ( constant. into ( ) ) ;
108141 }
109142 }
110143
@@ -213,7 +246,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
213246 self . infcx . tcx
214247 }
215248
216- fn cause ( & mut self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
249+ fn cause ( & self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
217250 traits:: ObligationCause :: new ( self . span , self . body_id , code)
218251 }
219252
@@ -300,22 +333,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
300333 }
301334 }
302335
303- /// Pushes the obligations required for an array length to be WF
304- /// into `self.out`.
305- fn compute_array_len ( & mut self , constant : ty:: Const < ' tcx > ) {
306- if let ty:: ConstKind :: Unevaluated ( def_id, substs, promoted) = constant. val {
307- assert ! ( promoted. is_none( ) ) ;
308-
309- let obligations = self . nominal_obligations ( def_id, substs) ;
310- self . out . extend ( obligations) ;
311-
312- let predicate =
313- ty:: PredicateKind :: ConstEvaluatable ( def_id, substs) . to_predicate ( self . tcx ( ) ) ;
314- let cause = self . cause ( traits:: MiscObligation ) ;
315- self . out . push ( traits:: Obligation :: new ( cause, self . param_env , predicate) ) ;
316- }
317- }
318-
319336 fn require_sized ( & mut self , subty : Ty < ' tcx > , cause : traits:: ObligationCauseCode < ' tcx > ) {
320337 if !subty. has_escaping_bound_vars ( ) {
321338 let cause = self . cause ( cause) ;
@@ -332,8 +349,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
332349 }
333350
334351 /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
335- fn compute ( & mut self , ty : Ty < ' tcx > ) {
336- let mut walker = ty . walk ( ) ;
352+ fn compute ( & mut self , arg : GenericArg < ' tcx > ) {
353+ let mut walker = arg . walk ( ) ;
337354 let param_env = self . param_env ;
338355 while let Some ( arg) = walker. next ( ) {
339356 let ty = match arg. unpack ( ) {
@@ -343,9 +360,43 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
343360 // obligations are handled by the parent (e.g. `ty::Ref`).
344361 GenericArgKind :: Lifetime ( _) => continue ,
345362
346- // FIXME(eddyb) this is wrong and needs to be replaced
347- // (see https://github.com/rust-lang/rust/pull/70107).
348- GenericArgKind :: Const ( _) => continue ,
363+ GenericArgKind :: Const ( constant) => {
364+ match constant. val {
365+ ty:: ConstKind :: Unevaluated ( def_id, substs, promoted) => {
366+ assert ! ( promoted. is_none( ) ) ;
367+
368+ let obligations = self . nominal_obligations ( def_id, substs) ;
369+ self . out . extend ( obligations) ;
370+
371+ let predicate = ty:: PredicateKind :: ConstEvaluatable ( def_id, substs) . to_predicate ( self . tcx ( ) ) ;
372+ let cause = self . cause ( traits:: MiscObligation ) ;
373+ self . out . push ( traits:: Obligation :: new (
374+ cause,
375+ self . param_env ,
376+ predicate,
377+ ) ) ;
378+ }
379+ ty:: ConstKind :: Infer ( infer) => {
380+ let resolved = self . infcx . shallow_resolve ( infer) ;
381+ // the `InferConst` changed, meaning that we made progress.
382+ if resolved != infer {
383+ let cause = self . cause ( traits:: MiscObligation ) ;
384+
385+ let resolved_constant = self . infcx . tcx . mk_const ( ty:: Const {
386+ val : ty:: ConstKind :: Infer ( resolved) ,
387+ ..* constant
388+ } ) ;
389+ self . out . push ( traits:: Obligation :: new (
390+ cause,
391+ self . param_env ,
392+ ty:: PredicateKind :: WellFormedConst ( resolved_constant) . to_predicate ( self . tcx ( ) ) ,
393+ ) ) ;
394+ }
395+ }
396+ _ => ( ) ,
397+ }
398+ continue ;
399+ }
349400 } ;
350401
351402 match ty. kind {
@@ -375,10 +426,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
375426 self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
376427 }
377428
378- ty:: Array ( subty, len ) => {
429+ ty:: Array ( subty, _ ) => {
379430 self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
380- // FIXME(eddyb) handle `GenericArgKind::Const` above instead.
381- self . compute_array_len ( * len) ;
382431 }
383432
384433 ty:: Tuple ( ref tys) => {
@@ -467,7 +516,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
467516 walker. skip_current_subtree ( ) ; // subtree handled below
468517 for upvar_ty in substs. as_closure ( ) . upvar_tys ( ) {
469518 // FIXME(eddyb) add the type to `walker` instead of recursing.
470- self . compute ( upvar_ty) ;
519+ self . compute ( upvar_ty. into ( ) ) ;
471520 }
472521 }
473522
@@ -540,7 +589,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
540589 } else {
541590 // Yes, resolved, proceed with the result.
542591 // FIXME(eddyb) add the type to `walker` instead of recursing.
543- self . compute ( ty) ;
592+ self . compute ( ty. into ( ) ) ;
544593 }
545594 }
546595 }
0 commit comments