@@ -4,7 +4,7 @@ use crate::traits;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def_id:: DefId ;
6
6
use rustc_hir:: lang_items;
7
- use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
7
+ use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , SubstsRef } ;
8
8
use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable , WithConstness } ;
9
9
use rustc_span:: Span ;
10
10
use std:: rc:: Rc ;
@@ -37,14 +37,44 @@ pub fn obligations<'a, 'tcx>(
37
37
} ;
38
38
39
39
let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item : None } ;
40
- wf. compute ( ty) ;
40
+ wf. compute ( ty. into ( ) ) ;
41
41
debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
42
42
43
43
let result = wf. normalize ( ) ;
44
44
debug ! ( "wf::obligations({:?}, body_id={:?}) ~~> {:?}" , ty, body_id, result) ;
45
45
Some ( result)
46
46
}
47
47
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
+
48
78
/// Returns the obligations that make this trait reference
49
79
/// well-formed. For example, if there is a trait `Set` defined like
50
80
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
@@ -78,33 +108,36 @@ pub fn predicate_obligations<'a, 'tcx>(
78
108
}
79
109
ty:: PredicateKind :: RegionOutlives ( ..) => { }
80
110
ty:: PredicateKind :: TypeOutlives ( t) => {
81
- wf. compute ( t. skip_binder ( ) . 0 ) ;
111
+ wf. compute ( t. skip_binder ( ) . 0 . into ( ) ) ;
82
112
}
83
113
ty:: PredicateKind :: Projection ( t) => {
84
114
let t = t. skip_binder ( ) ; // (*)
85
115
wf. compute_projection ( t. projection_ty ) ;
86
- wf. compute ( t. ty ) ;
116
+ wf. compute ( t. ty . into ( ) ) ;
87
117
}
88
118
& ty:: PredicateKind :: WellFormed ( t) => {
89
- wf. compute ( t) ;
119
+ wf. compute ( t. into ( ) ) ;
90
120
}
91
121
ty:: PredicateKind :: ObjectSafe ( _) => { }
92
122
ty:: PredicateKind :: ClosureKind ( ..) => { }
93
123
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 ( ) ) ; // (*)
96
126
}
97
127
& ty:: PredicateKind :: ConstEvaluatable ( def_id, substs) => {
98
128
let obligations = wf. nominal_obligations ( def_id, substs) ;
99
129
wf. out . extend ( obligations) ;
100
130
101
- for ty in substs. types ( ) {
102
- wf. compute ( ty ) ;
131
+ for subst in substs. iter ( ) . copied ( ) {
132
+ wf. compute ( subst ) ;
103
133
}
104
134
}
105
135
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 ( ) ) ;
108
141
}
109
142
}
110
143
@@ -213,7 +246,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
213
246
self . infcx . tcx
214
247
}
215
248
216
- fn cause ( & mut self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
249
+ fn cause ( & self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
217
250
traits:: ObligationCause :: new ( self . span , self . body_id , code)
218
251
}
219
252
@@ -300,22 +333,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
300
333
}
301
334
}
302
335
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
-
319
336
fn require_sized ( & mut self , subty : Ty < ' tcx > , cause : traits:: ObligationCauseCode < ' tcx > ) {
320
337
if !subty. has_escaping_bound_vars ( ) {
321
338
let cause = self . cause ( cause) ;
@@ -332,8 +349,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
332
349
}
333
350
334
351
/// 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 ( ) ;
337
354
let param_env = self . param_env ;
338
355
while let Some ( arg) = walker. next ( ) {
339
356
let ty = match arg. unpack ( ) {
@@ -343,9 +360,43 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
343
360
// obligations are handled by the parent (e.g. `ty::Ref`).
344
361
GenericArgKind :: Lifetime ( _) => continue ,
345
362
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
+ }
349
400
} ;
350
401
351
402
match ty. kind {
@@ -375,10 +426,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
375
426
self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
376
427
}
377
428
378
- ty:: Array ( subty, len ) => {
429
+ ty:: Array ( subty, _ ) => {
379
430
self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
380
- // FIXME(eddyb) handle `GenericArgKind::Const` above instead.
381
- self . compute_array_len ( * len) ;
382
431
}
383
432
384
433
ty:: Tuple ( ref tys) => {
@@ -467,7 +516,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
467
516
walker. skip_current_subtree ( ) ; // subtree handled below
468
517
for upvar_ty in substs. as_closure ( ) . upvar_tys ( ) {
469
518
// FIXME(eddyb) add the type to `walker` instead of recursing.
470
- self . compute ( upvar_ty) ;
519
+ self . compute ( upvar_ty. into ( ) ) ;
471
520
}
472
521
}
473
522
@@ -540,7 +589,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
540
589
} else {
541
590
// Yes, resolved, proceed with the result.
542
591
// FIXME(eddyb) add the type to `walker` instead of recursing.
543
- self . compute ( ty) ;
592
+ self . compute ( ty. into ( ) ) ;
544
593
}
545
594
}
546
595
}
0 commit comments