1
+ //! Core logic responsible for determining what it means for various type system
2
+ //! primitives to be "well formed". Actually checking whether these primitives are
3
+ //! well formed is performed elsewhere (e.g. during type checking or item well formedness
4
+ //! checking).
5
+
1
6
use std:: iter;
2
7
3
8
use rustc_hir as hir;
@@ -15,12 +20,13 @@ use tracing::{debug, instrument, trace};
15
20
16
21
use crate :: infer:: InferCtxt ;
17
22
use crate :: traits;
23
+
18
24
/// Returns the set of obligations needed to make `arg` well-formed.
19
25
/// If `arg` contains unresolved inference variables, this may include
20
26
/// further WF obligations. However, if `arg` IS an unresolved
21
27
/// 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".
28
+ /// make any progress at all. This is to prevent cycles where we
29
+ /// say "? 0 is WF if ? 0 is WF".
24
30
pub fn obligations < ' tcx > (
25
31
infcx : & InferCtxt < ' tcx > ,
26
32
param_env : ty:: ParamEnv < ' tcx > ,
@@ -29,14 +35,14 @@ pub fn obligations<'tcx>(
29
35
arg : GenericArg < ' tcx > ,
30
36
span : Span ,
31
37
) -> Option < PredicateObligations < ' tcx > > {
32
- // Handle the "livelock " case (see comment above) by bailing out if necessary.
38
+ // Handle the "cycle " case (see comment above) by bailing out if necessary.
33
39
let arg = match arg. unpack ( ) {
34
40
GenericArgKind :: Type ( ty) => {
35
41
match ty. kind ( ) {
36
42
ty:: Infer ( ty:: TyVar ( _) ) => {
37
43
let resolved_ty = infcx. shallow_resolve ( ty) ;
38
44
if resolved_ty == ty {
39
- // No progress, bail out to prevent "livelock" .
45
+ // No progress, bail out to prevent cycles .
40
46
return None ;
41
47
} else {
42
48
resolved_ty
@@ -51,7 +57,7 @@ pub fn obligations<'tcx>(
51
57
ty:: ConstKind :: Infer ( _) => {
52
58
let resolved = infcx. shallow_resolve_const ( ct) ;
53
59
if resolved == ct {
54
- // No progress.
60
+ // No progress, bail out to prevent cycles .
55
61
return None ;
56
62
} else {
57
63
resolved
@@ -74,7 +80,7 @@ pub fn obligations<'tcx>(
74
80
recursion_depth,
75
81
item : None ,
76
82
} ;
77
- wf. compute ( arg) ;
83
+ wf. add_wf_preds_for_generic_arg ( arg) ;
78
84
debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , arg, body_id, wf. out) ;
79
85
80
86
let result = wf. normalize ( infcx) ;
@@ -97,7 +103,7 @@ pub fn unnormalized_obligations<'tcx>(
97
103
98
104
// However, if `arg` IS an unresolved inference variable, returns `None`,
99
105
// 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".
106
+ // cycles where we say "? 0 is WF if ? 0 is WF".
101
107
if arg. is_non_region_infer ( ) {
102
108
return None ;
103
109
}
@@ -115,7 +121,7 @@ pub fn unnormalized_obligations<'tcx>(
115
121
recursion_depth : 0 ,
116
122
item : None ,
117
123
} ;
118
- wf. compute ( arg) ;
124
+ wf. add_wf_preds_for_generic_arg ( arg) ;
119
125
Some ( wf. out )
120
126
}
121
127
@@ -140,7 +146,7 @@ pub fn trait_obligations<'tcx>(
140
146
recursion_depth : 0 ,
141
147
item : Some ( item) ,
142
148
} ;
143
- wf. compute_trait_pred ( trait_pred, Elaborate :: All ) ;
149
+ wf. add_wf_preds_for_trait_pred ( trait_pred, Elaborate :: All ) ;
144
150
debug ! ( obligations = ?wf. out) ;
145
151
wf. normalize ( infcx)
146
152
}
@@ -171,30 +177,30 @@ pub fn clause_obligations<'tcx>(
171
177
// It's ok to skip the binder here because wf code is prepared for it
172
178
match clause. kind ( ) . skip_binder ( ) {
173
179
ty:: ClauseKind :: Trait ( t) => {
174
- wf. compute_trait_pred ( t, Elaborate :: None ) ;
180
+ wf. add_wf_preds_for_trait_pred ( t, Elaborate :: None ) ;
175
181
}
176
182
ty:: ClauseKind :: HostEffect ( ..) => {
177
183
// Technically the well-formedness of this predicate is implied by
178
184
// the corresponding trait predicate it should've been generated beside.
179
185
}
180
186
ty:: ClauseKind :: RegionOutlives ( ..) => { }
181
187
ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate ( ty, _reg) ) => {
182
- wf. compute ( ty. into ( ) ) ;
188
+ wf. add_wf_preds_for_generic_arg ( ty. into ( ) ) ;
183
189
}
184
190
ty:: ClauseKind :: Projection ( t) => {
185
- wf. compute_alias_term ( t. projection_term ) ;
186
- wf. compute ( t. term . into_arg ( ) ) ;
191
+ wf. add_wf_preds_for_alias_term ( t. projection_term ) ;
192
+ wf. add_wf_preds_for_generic_arg ( t. term . into_arg ( ) ) ;
187
193
}
188
194
ty:: ClauseKind :: ConstArgHasType ( ct, ty) => {
189
- wf. compute ( ct. into ( ) ) ;
190
- wf. compute ( ty. into ( ) ) ;
195
+ wf. add_wf_preds_for_generic_arg ( ct. into ( ) ) ;
196
+ wf. add_wf_preds_for_generic_arg ( ty. into ( ) ) ;
191
197
}
192
198
ty:: ClauseKind :: WellFormed ( arg) => {
193
- wf. compute ( arg) ;
199
+ wf. add_wf_preds_for_generic_arg ( arg) ;
194
200
}
195
201
196
202
ty:: ClauseKind :: ConstEvaluatable ( ct) => {
197
- wf. compute ( ct. into ( ) ) ;
203
+ wf. add_wf_preds_for_generic_arg ( ct. into ( ) ) ;
198
204
}
199
205
}
200
206
@@ -372,14 +378,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
372
378
}
373
379
374
380
/// 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 ) {
381
+ fn add_wf_preds_for_trait_pred (
382
+ & mut self ,
383
+ trait_pred : ty:: TraitPredicate < ' tcx > ,
384
+ elaborate : Elaborate ,
385
+ ) {
376
386
let tcx = self . tcx ( ) ;
377
387
let trait_ref = trait_pred. trait_ref ;
378
388
379
389
// Negative trait predicates don't require supertraits to hold, just
380
390
// that their args are WF.
381
391
if trait_pred. polarity == ty:: PredicatePolarity :: Negative {
382
- self . compute_negative_trait_pred ( trait_ref) ;
392
+ self . add_wf_preds_for_negative_trait_pred ( trait_ref) ;
383
393
return ;
384
394
}
385
395
@@ -445,15 +455,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
445
455
446
456
// Compute the obligations that are required for `trait_ref` to be WF,
447
457
// given that it is a *negative* trait predicate.
448
- fn compute_negative_trait_pred ( & mut self , trait_ref : ty:: TraitRef < ' tcx > ) {
458
+ fn add_wf_preds_for_negative_trait_pred ( & mut self , trait_ref : ty:: TraitRef < ' tcx > ) {
449
459
for arg in trait_ref. args {
450
- self . compute ( arg) ;
460
+ self . add_wf_preds_for_generic_arg ( arg) ;
451
461
}
452
462
}
453
463
454
464
/// Pushes the obligations required for an alias (except inherent) to be WF
455
465
/// into `self.out`.
456
- fn compute_alias_term ( & mut self , data : ty:: AliasTerm < ' tcx > ) {
466
+ fn add_wf_preds_for_alias_term ( & mut self , data : ty:: AliasTerm < ' tcx > ) {
457
467
// A projection is well-formed if
458
468
//
459
469
// (a) its predicates hold (*)
@@ -478,13 +488,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
478
488
let obligations = self . nominal_obligations ( data. def_id , data. args ) ;
479
489
self . out . extend ( obligations) ;
480
490
481
- self . compute_projection_args ( data. args ) ;
491
+ self . add_wf_preds_for_projection_args ( data. args ) ;
482
492
}
483
493
484
494
/// Pushes the obligations required for an inherent alias to be WF
485
495
/// into `self.out`.
486
496
// FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
487
- fn compute_inherent_projection ( & mut self , data : ty:: AliasTy < ' tcx > ) {
497
+ fn add_wf_preds_for_inherent_projection ( & mut self , data : ty:: AliasTy < ' tcx > ) {
488
498
// An inherent projection is well-formed if
489
499
//
490
500
// (a) its predicates hold (*)
@@ -511,7 +521,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
511
521
data. args . visit_with ( self ) ;
512
522
}
513
523
514
- fn compute_projection_args ( & mut self , args : GenericArgsRef < ' tcx > ) {
524
+ fn add_wf_preds_for_projection_args ( & mut self , args : GenericArgsRef < ' tcx > ) {
515
525
let tcx = self . tcx ( ) ;
516
526
let cause = self . cause ( ObligationCauseCode :: WellFormed ( None ) ) ;
517
527
let param_env = self . param_env ;
@@ -557,7 +567,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
557
567
558
568
/// Pushes all the predicates needed to validate that `ty` is WF into `out`.
559
569
#[ instrument( level = "debug" , skip( self ) ) ]
560
- fn compute ( & mut self , arg : GenericArg < ' tcx > ) {
570
+ fn add_wf_preds_for_generic_arg ( & mut self , arg : GenericArg < ' tcx > ) {
561
571
arg. visit_with ( self ) ;
562
572
debug ! ( ?self . out) ;
563
573
}
@@ -596,7 +606,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
596
606
. collect ( )
597
607
}
598
608
599
- fn from_object_ty (
609
+ fn add_wf_preds_for_dyn_ty (
600
610
& mut self ,
601
611
ty : Ty < ' tcx > ,
602
612
data : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
@@ -651,6 +661,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
651
661
outlives,
652
662
) ) ;
653
663
}
664
+
665
+ // We don't add any wf predicates corresponding to the trait ref's generic arguments
666
+ // which allows code like this to compile:
667
+ // ```rust
668
+ // trait Trait<T: Sized> {}
669
+ // fn foo(_: &dyn Trait<[u32]>) {}
670
+ // ```
654
671
}
655
672
}
656
673
}
@@ -761,7 +778,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
761
778
self . out . extend ( obligations) ;
762
779
}
763
780
ty:: Alias ( ty:: Inherent , data) => {
764
- self . compute_inherent_projection ( data) ;
781
+ self . add_wf_preds_for_inherent_projection ( data) ;
765
782
return ; // Subtree handled by compute_inherent_projection.
766
783
}
767
784
@@ -895,7 +912,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
895
912
//
896
913
// Here, we defer WF checking due to higher-ranked
897
914
// regions. This is perhaps not ideal.
898
- self . from_object_ty ( t, data, r) ;
915
+ self . add_wf_preds_for_dyn_ty ( t, data, r) ;
899
916
900
917
// FIXME(#27579) RFC also considers adding trait
901
918
// obligations that don't refer to Self and
@@ -917,11 +934,11 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
917
934
// 1. Check if they have been resolved, and if so proceed with
918
935
// THAT type.
919
936
// 2. If not, we've at least simplified things (e.g., we went
920
- // from `Vec<$ 0>: WF` to `$ 0: WF`), so we can
937
+ // from `Vec? 0>: WF` to `? 0: WF`), so we can
921
938
// register a pending obligation and keep
922
939
// moving. (Goal is that an "inductive hypothesis"
923
940
// is satisfied to ensure termination.)
924
- // See also the comment on `fn obligations`, describing "livelock"
941
+ // See also the comment on `fn obligations`, describing cycle
925
942
// prevention, which happens before this can be reached.
926
943
ty:: Infer ( _) => {
927
944
let cause = self . cause ( ObligationCauseCode :: WellFormed ( None ) ) ;
0 commit comments