@@ -15,12 +15,13 @@ use tracing::{debug, instrument, trace};
15
15
16
16
use crate :: infer:: InferCtxt ;
17
17
use crate :: traits;
18
+
18
19
/// Returns the set of obligations needed to make `arg` well-formed.
19
20
/// If `arg` contains unresolved inference variables, this may include
20
21
/// further WF obligations. However, if `arg` IS an unresolved
21
22
/// inference variable, returns `None`, because we are not able to
22
- /// make any progress at all. This is to prevent "livelock" where we
23
- /// say "$ 0 is WF if $ 0 is WF".
23
+ /// make any progress at all. This is to prevent cycles where we
24
+ /// say "? 0 is WF if ? 0 is WF".
24
25
pub fn obligations < ' tcx > (
25
26
infcx : & InferCtxt < ' tcx > ,
26
27
param_env : ty:: ParamEnv < ' tcx > ,
@@ -29,14 +30,14 @@ pub fn obligations<'tcx>(
29
30
arg : GenericArg < ' tcx > ,
30
31
span : Span ,
31
32
) -> Option < PredicateObligations < ' tcx > > {
32
- // Handle the "livelock " case (see comment above) by bailing out if necessary.
33
+ // Handle the "cycle " case (see comment above) by bailing out if necessary.
33
34
let arg = match arg. unpack ( ) {
34
35
GenericArgKind :: Type ( ty) => {
35
36
match ty. kind ( ) {
36
37
ty:: Infer ( ty:: TyVar ( _) ) => {
37
38
let resolved_ty = infcx. shallow_resolve ( ty) ;
38
39
if resolved_ty == ty {
39
- // No progress, bail out to prevent "livelock" .
40
+ // No progress, bail out to prevent cycles .
40
41
return None ;
41
42
} else {
42
43
resolved_ty
@@ -51,7 +52,7 @@ pub fn obligations<'tcx>(
51
52
ty:: ConstKind :: Infer ( _) => {
52
53
let resolved = infcx. shallow_resolve_const ( ct) ;
53
54
if resolved == ct {
54
- // No progress.
55
+ // No progress, bail out to prevent cycles .
55
56
return None ;
56
57
} else {
57
58
resolved
@@ -74,7 +75,7 @@ pub fn obligations<'tcx>(
74
75
recursion_depth,
75
76
item : None ,
76
77
} ;
77
- wf. compute ( arg) ;
78
+ wf. add_generic_arg_wf_reqs ( arg) ;
78
79
debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , arg, body_id, wf. out) ;
79
80
80
81
let result = wf. normalize ( infcx) ;
@@ -97,7 +98,7 @@ pub fn unnormalized_obligations<'tcx>(
97
98
98
99
// However, if `arg` IS an unresolved inference variable, returns `None`,
99
100
// because we are not able to make any progress at all. This is to prevent
100
- // "livelock" where we say "$ 0 is WF if $ 0 is WF".
101
+ // cycles where we say "? 0 is WF if ? 0 is WF".
101
102
if arg. is_non_region_infer ( ) {
102
103
return None ;
103
104
}
@@ -115,7 +116,7 @@ pub fn unnormalized_obligations<'tcx>(
115
116
recursion_depth : 0 ,
116
117
item : None ,
117
118
} ;
118
- wf. compute ( arg) ;
119
+ wf. add_generic_arg_wf_reqs ( arg) ;
119
120
Some ( wf. out )
120
121
}
121
122
@@ -140,7 +141,7 @@ pub fn trait_obligations<'tcx>(
140
141
recursion_depth : 0 ,
141
142
item : Some ( item) ,
142
143
} ;
143
- wf. compute_trait_pred ( trait_pred, Elaborate :: All ) ;
144
+ wf. add_trait_pred_wf_reqs ( trait_pred, Elaborate :: All ) ;
144
145
debug ! ( obligations = ?wf. out) ;
145
146
wf. normalize ( infcx)
146
147
}
@@ -171,30 +172,30 @@ pub fn clause_obligations<'tcx>(
171
172
// It's ok to skip the binder here because wf code is prepared for it
172
173
match clause. kind ( ) . skip_binder ( ) {
173
174
ty:: ClauseKind :: Trait ( t) => {
174
- wf. compute_trait_pred ( t, Elaborate :: None ) ;
175
+ wf. add_trait_pred_wf_reqs ( t, Elaborate :: None ) ;
175
176
}
176
177
ty:: ClauseKind :: HostEffect ( ..) => {
177
178
// Technically the well-formedness of this predicate is implied by
178
179
// the corresponding trait predicate it should've been generated beside.
179
180
}
180
181
ty:: ClauseKind :: RegionOutlives ( ..) => { }
181
182
ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate ( ty, _reg) ) => {
182
- wf. compute ( ty. into ( ) ) ;
183
+ wf. add_generic_arg_wf_reqs ( ty. into ( ) ) ;
183
184
}
184
185
ty:: ClauseKind :: Projection ( t) => {
185
- wf. compute_alias_term ( t. projection_term ) ;
186
- wf. compute ( t. term . into_arg ( ) ) ;
186
+ wf. add_alias_term_wf_reqs ( t. projection_term ) ;
187
+ wf. add_generic_arg_wf_reqs ( t. term . into_arg ( ) ) ;
187
188
}
188
189
ty:: ClauseKind :: ConstArgHasType ( ct, ty) => {
189
- wf. compute ( ct. into ( ) ) ;
190
- wf. compute ( ty. into ( ) ) ;
190
+ wf. add_generic_arg_wf_reqs ( ct. into ( ) ) ;
191
+ wf. add_generic_arg_wf_reqs ( ty. into ( ) ) ;
191
192
}
192
193
ty:: ClauseKind :: WellFormed ( arg) => {
193
- wf. compute ( arg) ;
194
+ wf. add_generic_arg_wf_reqs ( arg) ;
194
195
}
195
196
196
197
ty:: ClauseKind :: ConstEvaluatable ( ct) => {
197
- wf. compute ( ct. into ( ) ) ;
198
+ wf. add_generic_arg_wf_reqs ( ct. into ( ) ) ;
198
199
}
199
200
}
200
201
@@ -372,14 +373,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
372
373
}
373
374
374
375
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
375
- fn compute_trait_pred ( & mut self , trait_pred : ty:: TraitPredicate < ' tcx > , elaborate : Elaborate ) {
376
+ fn add_trait_pred_wf_reqs (
377
+ & mut self ,
378
+ trait_pred : ty:: TraitPredicate < ' tcx > ,
379
+ elaborate : Elaborate ,
380
+ ) {
376
381
let tcx = self . tcx ( ) ;
377
382
let trait_ref = trait_pred. trait_ref ;
378
383
379
384
// Negative trait predicates don't require supertraits to hold, just
380
385
// that their args are WF.
381
386
if trait_pred. polarity == ty:: PredicatePolarity :: Negative {
382
- self . compute_negative_trait_pred ( trait_ref) ;
387
+ self . add_negative_trait_pred_wf_reqs ( trait_ref) ;
383
388
return ;
384
389
}
385
390
@@ -445,15 +450,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
445
450
446
451
// Compute the obligations that are required for `trait_ref` to be WF,
447
452
// given that it is a *negative* trait predicate.
448
- fn compute_negative_trait_pred ( & mut self , trait_ref : ty:: TraitRef < ' tcx > ) {
453
+ fn add_negative_trait_pred_wf_reqs ( & mut self , trait_ref : ty:: TraitRef < ' tcx > ) {
449
454
for arg in trait_ref. args {
450
- self . compute ( arg) ;
455
+ self . add_generic_arg_wf_reqs ( arg) ;
451
456
}
452
457
}
453
458
454
459
/// Pushes the obligations required for an alias (except inherent) to be WF
455
460
/// into `self.out`.
456
- fn compute_alias_term ( & mut self , data : ty:: AliasTerm < ' tcx > ) {
461
+ fn add_alias_term_wf_reqs ( & mut self , data : ty:: AliasTerm < ' tcx > ) {
457
462
// A projection is well-formed if
458
463
//
459
464
// (a) its predicates hold (*)
@@ -478,13 +483,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
478
483
let obligations = self . nominal_obligations ( data. def_id , data. args ) ;
479
484
self . out . extend ( obligations) ;
480
485
481
- self . compute_projection_args ( data. args ) ;
486
+ self . add_projection_args_wf_reqs ( data. args ) ;
482
487
}
483
488
484
489
/// Pushes the obligations required for an inherent alias to be WF
485
490
/// into `self.out`.
486
491
// FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
487
- fn compute_inherent_projection ( & mut self , data : ty:: AliasTy < ' tcx > ) {
492
+ fn add_inherent_projection_wf_reqs ( & mut self , data : ty:: AliasTy < ' tcx > ) {
488
493
// An inherent projection is well-formed if
489
494
//
490
495
// (a) its predicates hold (*)
@@ -511,7 +516,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
511
516
data. args . visit_with ( self ) ;
512
517
}
513
518
514
- fn compute_projection_args ( & mut self , args : GenericArgsRef < ' tcx > ) {
519
+ fn add_projection_args_wf_reqs ( & mut self , args : GenericArgsRef < ' tcx > ) {
515
520
let tcx = self . tcx ( ) ;
516
521
let cause = self . cause ( ObligationCauseCode :: WellFormed ( None ) ) ;
517
522
let param_env = self . param_env ;
@@ -557,7 +562,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
557
562
558
563
/// Pushes all the predicates needed to validate that `ty` is WF into `out`.
559
564
#[ instrument( level = "debug" , skip( self ) ) ]
560
- fn compute ( & mut self , arg : GenericArg < ' tcx > ) {
565
+ fn add_generic_arg_wf_reqs ( & mut self , arg : GenericArg < ' tcx > ) {
561
566
arg. visit_with ( self ) ;
562
567
debug ! ( ?self . out) ;
563
568
}
@@ -596,7 +601,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
596
601
. collect ( )
597
602
}
598
603
599
- fn from_object_ty (
604
+ fn add_dyn_ty_wf_reqs (
600
605
& mut self ,
601
606
ty : Ty < ' tcx > ,
602
607
data : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
@@ -651,6 +656,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
651
656
outlives,
652
657
) ) ;
653
658
}
659
+
660
+ // We don't add any wf predicates corresponding to the trait ref's generic arguments
661
+ // which allows code like this to compile:
662
+ // ```rust
663
+ // trait Trait<T: Sized> {}
664
+ // fn foo(_: &dyn Trait<[u32]>) {}
665
+ // ```
654
666
}
655
667
}
656
668
}
@@ -761,7 +773,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
761
773
self . out . extend ( obligations) ;
762
774
}
763
775
ty:: Alias ( ty:: Inherent , data) => {
764
- self . compute_inherent_projection ( data) ;
776
+ self . add_inherent_projection_wf_reqs ( data) ;
765
777
return ; // Subtree handled by compute_inherent_projection.
766
778
}
767
779
@@ -895,7 +907,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
895
907
//
896
908
// Here, we defer WF checking due to higher-ranked
897
909
// regions. This is perhaps not ideal.
898
- self . from_object_ty ( t, data, r) ;
910
+ self . add_dyn_ty_wf_reqs ( t, data, r) ;
899
911
900
912
// FIXME(#27579) RFC also considers adding trait
901
913
// obligations that don't refer to Self and
@@ -917,11 +929,11 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
917
929
// 1. Check if they have been resolved, and if so proceed with
918
930
// THAT type.
919
931
// 2. If not, we've at least simplified things (e.g., we went
920
- // from `Vec<$ 0>: WF` to `$ 0: WF`), so we can
932
+ // from `Vec? 0>: WF` to `? 0: WF`), so we can
921
933
// register a pending obligation and keep
922
934
// moving. (Goal is that an "inductive hypothesis"
923
935
// is satisfied to ensure termination.)
924
- // See also the comment on `fn obligations`, describing "livelock"
936
+ // See also the comment on `fn obligations`, describing cycle
925
937
// prevention, which happens before this can be reached.
926
938
ty:: Infer ( _) => {
927
939
let cause = self . cause ( ObligationCauseCode :: WellFormed ( None ) ) ;
0 commit comments