Skip to content

Commit

Permalink
Use ReEmpty(U0) as the implicit region bound in typeck
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Jul 20, 2020
1 parent 0701419 commit 45c01ed
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 10 deletions.
9 changes: 0 additions & 9 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,6 @@ pub struct Inherited<'a, 'tcx> {
/// opaque type.
opaque_types_vars: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,

/// Each type parameter has an implicit region bound that
/// indicates it must outlive at least the function body (the user
/// may specify stronger requirements). This field indicates the
/// region of the callee. If it is `None`, then the parameter
/// environment is for an item or something where the "callee" is
/// not clear.
implicit_region_bound: Option<ty::Region<'tcx>>,

body_id: Option<hir::BodyId>,
}

Expand Down Expand Up @@ -684,7 +676,6 @@ impl Inherited<'a, 'tcx> {
deferred_generator_interiors: RefCell::new(Vec::new()),
opaque_types: RefCell::new(Default::default()),
opaque_types_vars: RefCell::new(Default::default()),
implicit_region_bound: None,
body_id,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
self.infcx.process_registered_region_obligations(
self.outlives_environment.region_bound_pairs_map(),
self.implicit_region_bound,
Some(self.tcx.lifetimes.re_root_empty),
self.param_env,
);

Expand Down
66 changes: 66 additions & 0 deletions src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Regression test for #74429, where we didn't think that a type parameter
// outlived `ReEmpty`.

// check-pass

use std::marker::PhantomData;
use std::ptr::NonNull;

pub unsafe trait RawData {
type Elem;
}

unsafe impl<A> RawData for OwnedRepr<A> {
type Elem = A;
}

unsafe impl<'a, A> RawData for ViewRepr<&'a A> {
type Elem = A;
}

pub struct OwnedRepr<A> {
ptr: PhantomData<A>,
}

// these Copy impls are not necessary for the repro, but allow the code to compile without error
// on 1.44.1
#[derive(Copy, Clone)]
pub struct ViewRepr<A> {
life: PhantomData<A>,
}

#[derive(Copy, Clone)]
pub struct ArrayBase<S>
where
S: RawData,
{
ptr: NonNull<S::Elem>,
}

pub type Array<A> = ArrayBase<OwnedRepr<A>>;

pub type ArrayView<'a, A> = ArrayBase<ViewRepr<&'a A>>;

impl<A, S> ArrayBase<S>
where
S: RawData<Elem = A>,
{
pub fn index_axis(&self) -> ArrayView<'_, A> {
unimplemented!()
}

pub fn axis_iter<'a>(&'a self) -> std::iter::Empty<&'a A> {
unimplemented!()
}
}

pub fn x<T: Copy>(a: Array<T>) {
// drop just avoids a must_use warning
drop((0..1).filter(|_| true));
let y = a.index_axis();
a.axis_iter().for_each(|_| {
drop(y);
});
}

fn main() {}
35 changes: 35 additions & 0 deletions src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Regression test for #74429, where we didn't think that a type parameter
// outlived `ReEmpty`.

// check-pass

use std::marker::PhantomData;

fn apply<T, F: FnOnce(T)>(_: T, _: F) {}

#[derive(Clone, Copy)]
struct Invariant<T> {
t: T,
p: PhantomData<fn(T) -> T>,
}

fn verify_reempty<T>(x: T) {
// r is inferred to have type `Invariant<&ReEmpty(U0) T>`
let r = Invariant { t: &x, p: PhantomData };
// Creates a new universe, all variables from now on are in `U1`, say.
let _: fn(&()) = |_| {};
// Closure parameter is of type `&ReEmpty(U1) T`, so the closure has an implied
// bound of `T: ReEmpty(U1)`
apply(&x, |_| {
// Requires `typeof(r)` is well-formed, i.e. `T: ReEmpty(U0)`. If we
// only have the implied bound from the closure parameter to use this
// requires `ReEmpty(U1): ReEmpty(U0)`, which isn't true so we reported
// an error.
//
// This doesn't happen any more because we ensure that `T: ReEmpty(U0)`
// is an implicit bound for all type parameters.
drop(r);
});
}

fn main() {}

0 comments on commit 45c01ed

Please sign in to comment.