|
| 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