| 
 | 1 | +use rustc_data_structures::fx::FxHashMap;  | 
 | 2 | +use syntax_pos::Span;  | 
 | 3 | + | 
1 | 4 | use crate::hir::def_id::DefId;  | 
2 | 5 | use crate::hir;  | 
3 | 6 | use crate::hir::Node;  | 
4 | 7 | use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin};  | 
5 | 8 | use crate::infer::outlives::free_region_map::FreeRegionRelations;  | 
6 |  | -use rustc_data_structures::fx::FxHashMap;  | 
7 | 9 | use crate::traits::{self, PredicateObligation};  | 
8 | 10 | use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind};  | 
9 |  | -use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};  | 
10 |  | -use crate::ty::outlives::Component;  | 
 | 11 | +use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};  | 
11 | 12 | use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};  | 
12 | 13 | use crate::util::nodemap::DefIdMap;  | 
13 | 14 | 
 
  | 
@@ -373,58 +374,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {  | 
373 | 374 |         let least_region = least_region.unwrap_or(self.tcx.lifetimes.re_static);  | 
374 | 375 |         debug!("constrain_opaque_types: least_region={:?}", least_region);  | 
375 | 376 | 
 
  | 
376 |  | -        // Require that the type `concrete_ty` outlives  | 
377 |  | -        // `least_region`, modulo any type parameters that appear  | 
378 |  | -        // in the type, which we ignore. This is because impl  | 
379 |  | -        // trait values are assumed to capture all the in-scope  | 
380 |  | -        // type parameters. This little loop here just invokes  | 
381 |  | -        // `outlives` repeatedly, draining all the nested  | 
382 |  | -        // obligations that result.  | 
383 |  | -        let mut types = vec![concrete_ty];  | 
384 |  | -        let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r);  | 
385 |  | -        while let Some(ty) = types.pop() {  | 
386 |  | -            let mut components = smallvec![];  | 
387 |  | -            self.tcx.push_outlives_components(ty, &mut components);  | 
388 |  | -            while let Some(component) = components.pop() {  | 
389 |  | -                match component {  | 
390 |  | -                    Component::Region(r) => {  | 
391 |  | -                        bound_region(r);  | 
392 |  | -                    }  | 
393 |  | - | 
394 |  | -                    Component::Param(_) => {  | 
395 |  | -                        // ignore type parameters like `T`, they are captured  | 
396 |  | -                        // implicitly by the `impl Trait`  | 
397 |  | -                    }  | 
398 |  | - | 
399 |  | -                    Component::UnresolvedInferenceVariable(_) => {  | 
400 |  | -                        // we should get an error that more type  | 
401 |  | -                        // annotations are needed in this case  | 
402 |  | -                        self.tcx  | 
403 |  | -                            .sess  | 
404 |  | -                            .delay_span_bug(span, "unresolved inf var in opaque");  | 
405 |  | -                    }  | 
406 |  | - | 
407 |  | -                    Component::Projection(ty::ProjectionTy {  | 
408 |  | -                        substs,  | 
409 |  | -                        item_def_id: _,  | 
410 |  | -                    }) => {  | 
411 |  | -                        for k in substs {  | 
412 |  | -                            match k.unpack() {  | 
413 |  | -                                UnpackedKind::Lifetime(lt) => bound_region(lt),  | 
414 |  | -                                UnpackedKind::Type(ty) => types.push(ty),  | 
415 |  | -                                UnpackedKind::Const(_) => {  | 
416 |  | -                                    // Const parameters don't impose constraints.  | 
417 |  | -                                }  | 
418 |  | -                            }  | 
419 |  | -                        }  | 
420 |  | -                    }  | 
421 |  | - | 
422 |  | -                    Component::EscapingProjection(more_components) => {  | 
423 |  | -                        components.extend(more_components);  | 
424 |  | -                    }  | 
425 |  | -                }  | 
426 |  | -            }  | 
427 |  | -        }  | 
 | 377 | +        concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor {  | 
 | 378 | +            infcx: self,  | 
 | 379 | +            least_region,  | 
 | 380 | +            span,  | 
 | 381 | +        });  | 
428 | 382 |     }  | 
429 | 383 | 
 
  | 
430 | 384 |     /// Given the fully resolved, instantiated type for an opaque  | 
@@ -502,6 +456,80 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {  | 
502 | 456 |     }  | 
503 | 457 | }  | 
504 | 458 | 
 
  | 
 | 459 | +// Visitor that requires that (almost) all regions in the type visited outlive  | 
 | 460 | +// `least_region`. We cannot use `push_outlives_components` because regions in  | 
 | 461 | +// closure signatures are not included in their outlives components. We need to  | 
 | 462 | +// ensure all regions outlive the given bound so that we don't end up with,  | 
 | 463 | +// say, `ReScope` appearing in a return type and causing ICEs when other  | 
 | 464 | +// functions end up with region constraints involving regions from other  | 
 | 465 | +// functions.  | 
 | 466 | +//  | 
 | 467 | +// We also cannot use `for_each_free_region` because for closures it includes  | 
 | 468 | +// the regions parameters from the enclosing item.  | 
 | 469 | +//  | 
 | 470 | +// We ignore any type parameters because impl trait values are assumed to  | 
 | 471 | +// capture all the in-scope type parameters.  | 
 | 472 | +struct OpaqueTypeOutlivesVisitor<'a, 'gcx, 'tcx> {  | 
 | 473 | +    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,  | 
 | 474 | +    least_region: ty::Region<'tcx>,  | 
 | 475 | +    span: Span,  | 
 | 476 | +}  | 
 | 477 | + | 
 | 478 | +impl<'tcx> TypeVisitor<'tcx> for OpaqueTypeOutlivesVisitor<'_, '_, 'tcx>  | 
 | 479 | +{  | 
 | 480 | +    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {  | 
 | 481 | +        t.skip_binder().visit_with(self);  | 
 | 482 | +        false // keep visiting  | 
 | 483 | +    }  | 
 | 484 | + | 
 | 485 | +    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {  | 
 | 486 | +        match *r {  | 
 | 487 | +            // ignore bound regions, keep visiting  | 
 | 488 | +            ty::ReLateBound(_, _) => false,  | 
 | 489 | +            _ => {  | 
 | 490 | +                self.infcx.sub_regions(infer::CallReturn(self.span), self.least_region, r);  | 
 | 491 | +                false  | 
 | 492 | +            }  | 
 | 493 | +        }  | 
 | 494 | +    }  | 
 | 495 | + | 
 | 496 | +    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {  | 
 | 497 | +        // We're only interested in types involving regions  | 
 | 498 | +        if !ty.flags.intersects(ty::TypeFlags::HAS_FREE_REGIONS) {  | 
 | 499 | +            return false; // keep visiting  | 
 | 500 | +        }  | 
 | 501 | + | 
 | 502 | +        match ty.sty {  | 
 | 503 | +            ty::Closure(def_id, ref substs) => {  | 
 | 504 | +                // Skip lifetime parameters of the enclosing item(s)  | 
 | 505 | + | 
 | 506 | +                for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {  | 
 | 507 | +                    upvar_ty.visit_with(self);  | 
 | 508 | +                }  | 
 | 509 | + | 
 | 510 | +                substs.closure_sig_ty(def_id, self.infcx.tcx).visit_with(self);  | 
 | 511 | +            }  | 
 | 512 | + | 
 | 513 | +            ty::Generator(def_id, ref substs, _) => {  | 
 | 514 | +                // Skip lifetime parameters of the enclosing item(s)  | 
 | 515 | +                // Also skip the witness type, because that has no free regions.  | 
 | 516 | + | 
 | 517 | +                for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {  | 
 | 518 | +                    upvar_ty.visit_with(self);  | 
 | 519 | +                }  | 
 | 520 | + | 
 | 521 | +                substs.return_ty(def_id, self.infcx.tcx).visit_with(self);  | 
 | 522 | +                substs.yield_ty(def_id, self.infcx.tcx).visit_with(self);  | 
 | 523 | +            }  | 
 | 524 | +            _ => {  | 
 | 525 | +                ty.super_visit_with(self);  | 
 | 526 | +            }  | 
 | 527 | +        }  | 
 | 528 | + | 
 | 529 | +        false  | 
 | 530 | +    }  | 
 | 531 | +}  | 
 | 532 | + | 
505 | 533 | struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {  | 
506 | 534 |     tcx: TyCtxt<'cx, 'gcx, 'tcx>,  | 
507 | 535 | 
 
  | 
@@ -563,8 +591,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>  | 
563 | 591 |             // ignore `'static`, as that can appear anywhere  | 
564 | 592 |             ty::ReStatic |  | 
565 | 593 | 
 
  | 
566 |  | -            // ignore `ReScope`, as that can appear anywhere  | 
567 |  | -            // See `src/test/run-pass/issue-49556.rs` for example.  | 
 | 594 | +            // ignore `ReScope`, which may appear in impl Trait in bindings.  | 
568 | 595 |             ty::ReScope(..) => return r,  | 
569 | 596 | 
 
  | 
570 | 597 |             _ => { }  | 
 | 
0 commit comments