diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7c7ee9b330ecc..5b5a0f08941d3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -753,7 +753,8 @@ impl Binder { pub fn dummy<'tcx>(value: T) -> Binder where T: TypeFoldable<'tcx> { - debug_assert!(!value.has_escaping_regions()); + debug_assert!(!value.has_escaping_regions(), + "Value has unexpected escaping regions: {:?}", value); Binder(value) } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index fc55d8f34a23f..2199604339689 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -487,7 +487,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // Note: in fact we only permit builtin traits, not `Bar<'d>`, I // am looking forward to the future here. - if !data.has_escaping_regions() { + if !data.has_escaping_regions() && !region.has_escaping_regions() { let implicit_bounds = object_region_bounds(self.infcx.tcx, data); @@ -495,6 +495,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { for implicit_bound in implicit_bounds { let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); + debug!("Testing implicit bound {:?} with explicit bound {:?}, cause {:?}", + implicit_bound, explicit_bound, cause); let outlives = ty::Binder::dummy( ty::OutlivesPredicate(explicit_bound, implicit_bound)); self.out.push(traits::Obligation::new(cause, diff --git a/src/test/run-pass/issue-53548.rs b/src/test/run-pass/issue-53548.rs new file mode 100644 index 0000000000000..7fb853f2b8228 --- /dev/null +++ b/src/test/run-pass/issue-53548.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #53548: having a 'static bound on a trait +// made it impossible to keep a trait object to it across an +// await point inside a closure + +#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] + +use std::future::Future; +use std::mem::PinMut; +use std::task::{Poll, Context}; + +// A trait with 'static bound +trait Trait: 'static {} + +// Anything we can give to await!() +struct DummyFut(); +impl Future for DummyFut { + type Output = (); + fn poll(self: PinMut, _ctx: &mut Context) -> Poll<()> { + Poll::Pending + } +} + +// The actual reproducer, requires that Trait is 'static and a trait +// object to it is captured in a closure for successful reproduction. +async fn foo(b: Box) -> () { + let _bar = move || { b; () }; + await!(DummyFut()) +} + +pub fn main() {}