Use ReEmpty(U0) as the implicit region bound in typeck
This commit is contained in:
parent
0701419e96
commit
45c01edaf2
4 changed files with 102 additions and 10 deletions
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue