1
+ use crate :: check:: regionck:: OutlivesEnvironmentExt ;
1
2
use crate :: check:: { FnCtxt , Inherited } ;
2
3
use crate :: constrained_generic_params:: { identify_constrained_generic_params, Parameter } ;
3
4
4
- use crate :: traits:: query:: type_op:: { self , TypeOp , TypeOpOutput } ;
5
5
use rustc_ast as ast;
6
6
use rustc_data_structures:: fx:: FxHashSet ;
7
7
use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
@@ -12,7 +12,10 @@ use rustc_hir::intravisit::Visitor;
12
12
use rustc_hir:: itemlikevisit:: ParItemLikeVisitor ;
13
13
use rustc_hir:: lang_items:: LangItem ;
14
14
use rustc_hir:: ItemKind ;
15
+ use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
16
+ use rustc_infer:: infer:: outlives:: obligations:: TypeOutlives ;
15
17
use rustc_infer:: infer:: TyCtxtInferExt ;
18
+ use rustc_infer:: infer:: { self , RegionckMode , SubregionOrigin } ;
16
19
use rustc_middle:: hir:: map as hir_map;
17
20
use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts , Subst } ;
18
21
use rustc_middle:: ty:: trait_def:: TraitSpecializationKind ;
@@ -22,7 +25,7 @@ use rustc_middle::ty::{
22
25
} ;
23
26
use rustc_session:: parse:: feature_err;
24
27
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
25
- use rustc_span:: Span ;
28
+ use rustc_span:: { Span , DUMMY_SP } ;
26
29
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
27
30
use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCauseCode , WellFormedLoc } ;
28
31
@@ -279,84 +282,104 @@ fn check_gat_where_clauses(
279
282
return ;
280
283
}
281
284
let associated_items: & ty:: AssocItems < ' _ > = tcx. associated_items ( encl_trait_def_id) ;
285
+ let mut clauses = FxHashSet :: default ( ) ;
282
286
// For every function in this trait...
283
287
for item in
284
288
associated_items. in_definition_order ( ) . filter ( |item| matches ! ( item. kind, ty:: AssocKind :: Fn ) )
285
289
{
286
- tcx. infer_ctxt ( ) . enter ( |infcx| {
287
- let sig: ty:: Binder < ' _ , ty:: FnSig < ' _ > > = tcx. fn_sig ( item. def_id ) ;
288
- let sig = infcx. replace_bound_vars_with_placeholders ( sig) ;
289
- // Find out what regions are passed as GAT substs
290
- let mut visitor = GATSubstCollector {
291
- tcx,
292
- gat : trait_item. def_id . to_def_id ( ) ,
293
- regions : FxHashSet :: default ( ) ,
294
- _types : FxHashSet :: default ( ) ,
295
- } ;
296
- sig. output ( ) . visit_with ( & mut visitor) ;
297
- // If there are none, then it nothing to do
298
- if visitor. regions . is_empty ( ) {
299
- return ;
300
- }
301
- let mut clauses = FxHashSet :: default ( ) ;
302
- // Otherwise, find the clauses required from implied bounds
303
- for input in sig. inputs ( ) {
304
- // For a given input type, find the implied bounds
305
- let TypeOpOutput { output : bounds, .. } = match ty:: ParamEnv :: empty ( )
306
- . and ( type_op:: implied_outlives_bounds:: ImpliedOutlivesBounds { ty : input } )
307
- . fully_perform ( & infcx)
308
- {
309
- Ok ( o) => o,
310
- Err ( _) => continue ,
311
- } ;
312
- debug ! ( ?bounds) ;
313
- for bound in bounds {
314
- match bound {
315
- traits:: query:: OutlivesBound :: RegionSubParam ( r, p) => {
316
- // If the implied bound is a `RegionSubParam` and
317
- // the region is used a GAT subst...
318
- for idx in visitor
319
- . regions
320
- . iter ( )
321
- . filter ( |( proj_r, _) | proj_r == & r)
322
- . map ( |r| r. 1 )
323
- {
324
- // Then create a clause that is required on the GAT
325
- let param_r = tcx. mk_region ( ty:: RegionKind :: ReEarlyBound (
326
- ty:: EarlyBoundRegion {
327
- def_id : generics. params [ idx] . def_id ,
328
- index : idx as u32 ,
329
- name : generics. params [ idx] . name ,
330
- } ,
331
- ) ) ;
332
- let clause = ty:: PredicateKind :: TypeOutlives (
333
- ty:: OutlivesPredicate ( tcx. mk_ty ( ty:: Param ( p) ) , param_r) ,
334
- ) ;
335
- let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
336
- clauses. insert ( clause) ;
337
- }
338
- }
339
- _ => { }
340
- }
341
- }
342
- }
343
- // If there are any missing clauses, emit an error
344
- debug ! ( ?clauses) ;
345
- if !clauses. is_empty ( ) {
346
- let written_predicates: ty:: GenericPredicates < ' _ > =
347
- tcx. predicates_of ( trait_item. def_id ) ;
348
- for clause in clauses {
349
- let found =
350
- written_predicates. predicates . iter ( ) . find ( |p| p. 0 == clause) . is_some ( ) ;
351
- debug ! ( ?clause, ?found) ;
352
- let mut error = tcx. sess . struct_span_err (
353
- trait_item. generics . span ,
354
- & format ! ( "Missing bound: {}" , clause) ,
290
+ let id = hir:: HirId :: make_owner ( item. def_id . expect_local ( ) ) ;
291
+ let span = DUMMY_SP ;
292
+ let param_env = tcx. param_env ( item. def_id . expect_local ( ) ) ;
293
+
294
+ let sig = tcx. fn_sig ( item. def_id ) ;
295
+ let sig = tcx. liberate_late_bound_regions ( item. def_id , sig) ;
296
+ let mut visitor = GATSubstCollector {
297
+ tcx,
298
+ gat : trait_item. def_id . to_def_id ( ) ,
299
+ regions : FxHashSet :: default ( ) ,
300
+ types : FxHashSet :: default ( ) ,
301
+ } ;
302
+ sig. output ( ) . visit_with ( & mut visitor) ;
303
+ let mut wf_tys = FxHashSet :: default ( ) ;
304
+ wf_tys. extend ( sig. inputs ( ) ) ;
305
+ // FIXME: normalize and add normalized inputs?
306
+
307
+ for ( region, region_idx) in & visitor. regions {
308
+ for ( ty, ty_idx) in & visitor. types {
309
+ tcx. infer_ctxt ( ) . enter ( |infcx| {
310
+ let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
311
+ outlives_environment. add_implied_bounds ( & infcx, wf_tys. clone ( ) , id, span) ;
312
+ outlives_environment. save_implied_bounds ( id) ;
313
+ let region_bound_pairs =
314
+ outlives_environment. region_bound_pairs_map ( ) . get ( & id) . unwrap ( ) ;
315
+
316
+ let cause =
317
+ ObligationCause :: new ( DUMMY_SP , id, ObligationCauseCode :: MiscObligation ) ;
318
+
319
+ let sup_type = * ty;
320
+ let sub_region = region;
321
+
322
+ let origin = SubregionOrigin :: from_obligation_cause ( & cause, || {
323
+ infer:: RelateParamBound ( cause. span , sup_type, None )
324
+ } ) ;
325
+
326
+ let outlives = & mut TypeOutlives :: new (
327
+ & infcx,
328
+ tcx,
329
+ & region_bound_pairs,
330
+ Some ( tcx. lifetimes . re_root_empty ) ,
331
+ param_env,
355
332
) ;
356
- error. emit ( ) ;
357
- }
333
+ outlives. type_must_outlive ( origin, sup_type, sub_region) ;
334
+
335
+ let errors = infcx. resolve_regions (
336
+ trait_item. def_id . to_def_id ( ) ,
337
+ & outlives_environment,
338
+ RegionckMode :: default ( ) ,
339
+ ) ;
340
+
341
+ debug ! ( ?errors, "errors" ) ;
342
+
343
+ if errors. is_empty ( ) {
344
+ debug ! ( ?ty_idx, ?region_idx) ;
345
+ debug ! ( "required clause: {} must outlive {}" , ty, region) ;
346
+ let ty_param = generics. param_at ( * ty_idx, tcx) ;
347
+ let ty_param = tcx. mk_ty ( ty:: Param ( ty:: ParamTy {
348
+ index : ty_param. index ,
349
+ name : ty_param. name ,
350
+ } ) ) ;
351
+ let region_param = generics. param_at ( * region_idx, tcx) ;
352
+ // Then create a clause that is required on the GAT
353
+ let region_param =
354
+ tcx. mk_region ( ty:: RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion {
355
+ def_id : region_param. def_id ,
356
+ index : region_param. index ,
357
+ name : region_param. name ,
358
+ } ) ) ;
359
+ let clause = ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate (
360
+ ty_param,
361
+ region_param,
362
+ ) ) ;
363
+ let clause = tcx. mk_predicate ( ty:: Binder :: dummy ( clause) ) ;
364
+ clauses. insert ( clause) ;
365
+ }
366
+ } ) ;
358
367
}
359
- } )
368
+ }
369
+ }
370
+
371
+ // If there are any missing clauses, emit an error
372
+ debug ! ( ?clauses) ;
373
+ if !clauses. is_empty ( ) {
374
+ let written_predicates: ty:: GenericPredicates < ' _ > = tcx. predicates_of ( trait_item. def_id ) ;
375
+ for clause in clauses {
376
+ let found = written_predicates. predicates . iter ( ) . find ( |p| p. 0 == clause) . is_some ( ) ;
377
+ debug ! ( ?clause, ?found) ;
378
+ let mut error = tcx
379
+ . sess
380
+ . struct_span_err ( trait_item. generics . span , & format ! ( "Missing bound: {}" , clause) ) ;
381
+ error. emit ( ) ;
382
+ }
360
383
}
361
384
}
362
385
@@ -366,7 +389,7 @@ struct GATSubstCollector<'tcx> {
366
389
// Which region appears and which parameter index its subsituted for
367
390
regions : FxHashSet < ( ty:: Region < ' tcx > , usize ) > ,
368
391
// Which params appears and which parameter index its subsituted for
369
- _types : FxHashSet < ( Ty < ' tcx > , usize ) > ,
392
+ types : FxHashSet < ( Ty < ' tcx > , usize ) > ,
370
393
}
371
394
372
395
impl < ' tcx > TypeVisitor < ' tcx > for GATSubstCollector < ' tcx > {
@@ -375,13 +398,20 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
375
398
fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
376
399
match t. kind ( ) {
377
400
ty:: Projection ( p) if p. item_def_id == self . gat => {
378
- let ( _, substs) = p. trait_ref_and_own_substs ( self . tcx ) ;
379
- self . regions . extend ( substs. iter ( ) . enumerate ( ) . filter_map ( |( idx, subst) | {
401
+ for ( idx, subst) in p. substs . iter ( ) . enumerate ( ) {
380
402
match subst. unpack ( ) {
381
- GenericArgKind :: Lifetime ( lt) => Some ( ( lt, idx) ) ,
382
- _ => None ,
403
+ GenericArgKind :: Lifetime ( lt) => {
404
+ self . regions . insert ( ( lt, idx) ) ;
405
+ }
406
+ GenericArgKind :: Type ( t) => match t. kind ( ) {
407
+ ty:: Param ( _) => {
408
+ self . types . insert ( ( t, idx) ) ;
409
+ }
410
+ _ => { }
411
+ } ,
412
+ _ => { }
383
413
}
384
- } ) ) ;
414
+ }
385
415
}
386
416
_ => { }
387
417
}
0 commit comments