1+ use crate :: check:: regionck:: OutlivesEnvironmentExt ;
12use crate :: check:: { FnCtxt , Inherited } ;
23use crate :: constrained_generic_params:: { identify_constrained_generic_params, Parameter } ;
34
4- use crate :: traits:: query:: type_op:: { self , TypeOp , TypeOpOutput } ;
55use rustc_ast as ast;
66use rustc_data_structures:: fx:: FxHashSet ;
77use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
@@ -12,7 +12,10 @@ use rustc_hir::intravisit::Visitor;
1212use rustc_hir:: itemlikevisit:: ParItemLikeVisitor ;
1313use rustc_hir:: lang_items:: LangItem ;
1414use rustc_hir:: ItemKind ;
15+ use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
16+ use rustc_infer:: infer:: outlives:: obligations:: TypeOutlives ;
1517use rustc_infer:: infer:: TyCtxtInferExt ;
18+ use rustc_infer:: infer:: { self , RegionckMode , SubregionOrigin } ;
1619use rustc_middle:: hir:: map as hir_map;
1720use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts , Subst } ;
1821use rustc_middle:: ty:: trait_def:: TraitSpecializationKind ;
@@ -22,7 +25,7 @@ use rustc_middle::ty::{
2225} ;
2326use rustc_session:: parse:: feature_err;
2427use rustc_span:: symbol:: { sym, Ident , Symbol } ;
25- use rustc_span:: Span ;
28+ use rustc_span:: { Span , DUMMY_SP } ;
2629use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
2730use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCauseCode , WellFormedLoc } ;
2831
@@ -279,84 +282,104 @@ fn check_gat_where_clauses(
279282 return ;
280283 }
281284 let associated_items: & ty:: AssocItems < ' _ > = tcx. associated_items ( encl_trait_def_id) ;
285+ let mut clauses = FxHashSet :: default ( ) ;
282286 // For every function in this trait...
283287 for item in
284288 associated_items. in_definition_order ( ) . filter ( |item| matches ! ( item. kind, ty:: AssocKind :: Fn ) )
285289 {
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,
355332 ) ;
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+ } ) ;
358367 }
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+ }
360383 }
361384}
362385
@@ -366,7 +389,7 @@ struct GATSubstCollector<'tcx> {
366389 // Which region appears and which parameter index its subsituted for
367390 regions : FxHashSet < ( ty:: Region < ' tcx > , usize ) > ,
368391 // Which params appears and which parameter index its subsituted for
369- _types : FxHashSet < ( Ty < ' tcx > , usize ) > ,
392+ types : FxHashSet < ( Ty < ' tcx > , usize ) > ,
370393}
371394
372395impl < ' tcx > TypeVisitor < ' tcx > for GATSubstCollector < ' tcx > {
@@ -375,13 +398,20 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
375398 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
376399 match t. kind ( ) {
377400 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 ( ) {
380402 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+ _ => { }
383413 }
384- } ) ) ;
414+ }
385415 }
386416 _ => { }
387417 }
0 commit comments