Auto merge of #53745 - nikomatsakis:nll-issue-53570, r=pnkfelix
do not propagate closure requirements if we can prove them locally Fixes #53570 cc @mikhail-m1 -- you're the one who last touched this code r? @pnkfelix
This commit is contained in:
commit
295ad30ef4
19 changed files with 178 additions and 80 deletions
|
|
@ -276,7 +276,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
|
|||
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
mir_def_id: DefId,
|
||||
regioncx: &RegionInferenceContext,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements>,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
|
|
@ -299,7 +299,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
|
|||
.diagnostic()
|
||||
.span_note_diag(mir.span, "External requirements");
|
||||
|
||||
regioncx.annotate(&mut err);
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err.note(&format!(
|
||||
"number of external vids: {}",
|
||||
|
|
@ -319,7 +319,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
|
|||
.sess
|
||||
.diagnostic()
|
||||
.span_note_diag(mir.span, "No external requirements");
|
||||
regioncx.annotate(&mut err);
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err.buffer(errors_buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! As part of the NLL unit tests, you can annotate a function with
|
||||
//! `#[rustc_regions]`, and we will emit information about the region
|
||||
//! inference context and -- in particular -- the external constraints
|
||||
//! that this region imposes on others. The methods in this file
|
||||
//! handle the part about dumping the inference context internal
|
||||
//! state.
|
||||
|
||||
use borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use borrow_check::nll::universal_regions::DefiningTy;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Write out our state into the `.mir` files.
|
||||
pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||
match self.universal_regions.defining_ty {
|
||||
DefiningTy::Closure(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with closure substs {:#?}",
|
||||
def_id,
|
||||
&substs.substs[..]
|
||||
));
|
||||
}
|
||||
DefiningTy::Generator(def_id, substs, _) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with generator substs {:#?}",
|
||||
def_id,
|
||||
&substs.substs[..]
|
||||
));
|
||||
}
|
||||
DefiningTy::FnDef(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with substs {:#?}",
|
||||
def_id,
|
||||
&substs[..]
|
||||
));
|
||||
}
|
||||
DefiningTy::Const(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining constant type: {:?} with substs {:#?}",
|
||||
def_id,
|
||||
&substs[..]
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,11 +29,10 @@ use rustc::util::common;
|
|||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_errors::{DiagnosticBuilder, Diagnostic};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
mod annotation;
|
||||
mod dump_mir;
|
||||
mod error_reporting;
|
||||
mod graphviz;
|
||||
|
|
@ -359,6 +358,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
self.universal_regions.to_region_vid(r)
|
||||
}
|
||||
|
||||
/// Add annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
|
||||
crate fn annotate(&self, tcx: TyCtxt<'_, '_, 'tcx>, err: &mut DiagnosticBuilder<'_>) {
|
||||
self.universal_regions.annotate(tcx, err)
|
||||
}
|
||||
|
||||
/// Returns true if the region `r` contains the point `p`.
|
||||
///
|
||||
/// Panics if called before `solve()` executes,
|
||||
|
|
@ -686,7 +690,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
test: _,
|
||||
} = type_test;
|
||||
|
||||
|
||||
let generic_ty = generic_kind.to_ty(tcx);
|
||||
let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
|
||||
Some(s) => s,
|
||||
|
|
@ -698,20 +701,38 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// `ClosureOutlivesRequirement`.
|
||||
let r_scc = self.constraint_sccs.scc(*lower_bound);
|
||||
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
|
||||
// Check whether we can already prove that the "subject" outlives `ur`.
|
||||
// If so, we don't have to propagate this requirement to our caller.
|
||||
//
|
||||
// To continue the example from the function, if we are trying to promote
|
||||
// a requirement that `T: 'X`, and we know that `'X = '1 + '2` (i.e., the union
|
||||
// `'1` and `'2`), then in this loop `ur` will be `'1` (and `'2`). So here
|
||||
// we check whether `T: '1` is something we *can* prove. If so, no need
|
||||
// to propagate that requirement.
|
||||
//
|
||||
// This is needed because -- particularly in the case
|
||||
// where `ur` is a local bound -- we are sometimes in a
|
||||
// position to prove things that our caller cannot. See
|
||||
// #53570 for an example.
|
||||
if self.eval_region_test(mir, ur, &type_test.test) {
|
||||
continue;
|
||||
}
|
||||
|
||||
debug!("try_promote_type_test: ur={:?}", ur);
|
||||
|
||||
let non_local_ub = self.universal_region_relations.non_local_upper_bound(ur);
|
||||
debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub);
|
||||
|
||||
assert!(self.universal_regions.is_universal_region(non_local_ub));
|
||||
assert!(
|
||||
!self
|
||||
.universal_regions
|
||||
.is_local_free_region(non_local_ub)
|
||||
);
|
||||
assert!(!self.universal_regions.is_local_free_region(non_local_ub));
|
||||
|
||||
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
||||
let requirement = ClosureOutlivesRequirement {
|
||||
subject,
|
||||
outlived_free_region: non_local_ub,
|
||||
blame_span: locations.span(mir),
|
||||
});
|
||||
};
|
||||
debug!("try_promote_type_test: pushing {:#?}", requirement);
|
||||
propagated_outlives_requirements.push(requirement);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
@ -917,8 +938,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// now). Therefore, the sup-region outlives the sub-region if,
|
||||
// for each universal region R1 in the sub-region, there
|
||||
// exists some region R2 in the sup-region that outlives R1.
|
||||
let universal_outlives = self
|
||||
.scc_values
|
||||
let universal_outlives = self.scc_values
|
||||
.universal_regions_outlived_by(sub_region_scc)
|
||||
.all(|r1| {
|
||||
self.scc_values
|
||||
|
|
@ -1029,8 +1049,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// (because `fr` includes `end(o)`).
|
||||
for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) {
|
||||
// If it is known that `fr: o`, carry on.
|
||||
if self
|
||||
.universal_region_relations
|
||||
if self.universal_region_relations
|
||||
.outlives(longer_fr, shorter_fr)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -1046,8 +1065,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
|
||||
// Shrink `fr` until we find a non-local region (if we do).
|
||||
// We'll call that `fr-` -- it's ever so slightly smaller than `fr`.
|
||||
if let Some(fr_minus) = self
|
||||
.universal_region_relations
|
||||
if let Some(fr_minus) = self.universal_region_relations
|
||||
.non_local_lower_bound(longer_fr)
|
||||
{
|
||||
debug!("check_universal_region: fr_minus={:?}", fr_minus);
|
||||
|
|
@ -1056,8 +1074,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// region. (We always will.) We'll call that
|
||||
// `shorter_fr+` -- it's ever so slightly larger than
|
||||
// `fr`.
|
||||
let shorter_fr_plus = self
|
||||
.universal_region_relations
|
||||
let shorter_fr_plus = self.universal_region_relations
|
||||
.non_local_upper_bound(shorter_fr);
|
||||
debug!(
|
||||
"check_universal_region: shorter_fr_plus={:?}",
|
||||
|
|
@ -1117,8 +1134,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let error_region = match error_element {
|
||||
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
|
||||
RegionElement::RootUniversalRegion(r) => r,
|
||||
RegionElement::SubUniversalRegion(error_ui) => self
|
||||
.definitions
|
||||
RegionElement::SubUniversalRegion(error_ui) => self.definitions
|
||||
.iter_enumerated()
|
||||
.filter_map(|(r, definition)| match definition.origin {
|
||||
NLLRegionVariableOrigin::BoundRegion(ui) if error_ui == ui => Some(r),
|
||||
|
|
@ -1215,7 +1231,11 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
|
|||
// into a vector. These are the regions that we will be
|
||||
// relating to one another.
|
||||
let closure_mapping = &UniversalRegions::closure_mapping(
|
||||
tcx, user_closure_ty, self.num_external_vids, tcx.closure_base_def_id(closure_def_id));
|
||||
tcx,
|
||||
user_closure_ty,
|
||||
self.num_external_vids,
|
||||
tcx.closure_base_def_id(closure_def_id),
|
||||
);
|
||||
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
|
||||
|
||||
// Create the predicates.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use rustc::ty::subst::Substs;
|
|||
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use std::iter;
|
||||
use syntax::ast;
|
||||
|
||||
|
|
@ -310,6 +311,69 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
self.indices.to_region_vid(r)
|
||||
}
|
||||
|
||||
/// As part of the NLL unit tests, you can annotate a function with
|
||||
/// `#[rustc_regions]`, and we will emit information about the region
|
||||
/// inference context and -- in particular -- the external constraints
|
||||
/// that this region imposes on others. The methods in this file
|
||||
/// handle the part about dumping the inference context internal
|
||||
/// state.
|
||||
crate fn annotate(&self, tcx: TyCtxt<'_, '_, 'tcx>, err: &mut DiagnosticBuilder<'_>) {
|
||||
match self.defining_ty {
|
||||
DefiningTy::Closure(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with closure substs {:#?}",
|
||||
def_id,
|
||||
&substs.substs[..]
|
||||
));
|
||||
|
||||
// FIXME: It'd be nice to print the late-bound regions
|
||||
// here, but unfortunately these wind up stored into
|
||||
// tests, and the resulting print-outs include def-ids
|
||||
// and other things that are not stable across tests!
|
||||
// So we just include the region-vid. Annoying.
|
||||
let closure_base_def_id = tcx.closure_base_def_id(def_id);
|
||||
for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
|
||||
err.note(&format!(
|
||||
"late-bound region is {:?}",
|
||||
self.to_region_vid(r),
|
||||
));
|
||||
});
|
||||
}
|
||||
DefiningTy::Generator(def_id, substs, _) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with generator substs {:#?}",
|
||||
def_id,
|
||||
&substs.substs[..]
|
||||
));
|
||||
|
||||
// FIXME: As above, we'd like to print out the region
|
||||
// `r` but doing so is not stable across architectures
|
||||
// and so forth.
|
||||
let closure_base_def_id = tcx.closure_base_def_id(def_id);
|
||||
for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
|
||||
err.note(&format!(
|
||||
"late-bound region is {:?}",
|
||||
self.to_region_vid(r),
|
||||
));
|
||||
});
|
||||
}
|
||||
DefiningTy::FnDef(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with substs {:#?}",
|
||||
def_id,
|
||||
&substs[..]
|
||||
));
|
||||
}
|
||||
DefiningTy::Const(def_id, substs) => {
|
||||
err.note(&format!(
|
||||
"defining constant type: {:?} with substs {:#?}",
|
||||
def_id,
|
||||
&substs[..]
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct UniversalRegionsBuilder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ LL | | },
|
|||
i16,
|
||||
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#4r
|
||||
= note: late-bound region is '_#5r
|
||||
= note: late-bound region is '_#6r
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/propagate-approximated-fail-no-postdom.rs:56:13
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: late-bound region is '_#4r
|
||||
= note: number of external vids: 5
|
||||
= note: where '_#1r: '_#2r
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#2r
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where '_#1r: '_#0r
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: late-bound region is '_#4r
|
||||
= note: number of external vids: 5
|
||||
= note: where '_#1r: '_#0r
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: late-bound region is '_#4r
|
||||
= note: number of external vids: 5
|
||||
= note: where '_#1r: '_#2r
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ LL | | },
|
|||
i16,
|
||||
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where '_#1r: '_#2r
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#2r
|
||||
= note: late-bound region is '_#3r
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ LL | | });
|
|||
i16,
|
||||
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: late-bound region is '_#4r
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
|
||||
|
|
|
|||
46
src/test/ui/nll/issue-53570.rs
Normal file
46
src/test/ui/nll/issue-53570.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Regression test for #53570. Here, we need to propagate that `T: 'a`
|
||||
// but in some versions of NLL we were propagating a stronger
|
||||
// requirement that `T: 'static`. This arose because we actually had
|
||||
// to propagate both that `T: 'a` but also `T: 'b` where `'b` is the
|
||||
// higher-ranked lifetime that appears in the type of the closure
|
||||
// parameter `x` -- since `'b` cannot be expressed in the caller's
|
||||
// space, that got promoted th `'static`.
|
||||
//
|
||||
// compile-pass
|
||||
|
||||
#![feature(nll)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::cell::{RefCell, Ref};
|
||||
|
||||
trait AnyVec<'a> {
|
||||
}
|
||||
|
||||
trait GenericVec<T> {
|
||||
fn unwrap<'a, 'b>(vec: &'b AnyVec<'a>) -> &'b [T] where T: 'a;
|
||||
}
|
||||
|
||||
struct Scratchpad<'a> {
|
||||
buffers: RefCell<Box<AnyVec<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> Scratchpad<'a> {
|
||||
fn get<T: GenericVec<T>>(&self) -> Ref<[T]>
|
||||
where T: 'a
|
||||
{
|
||||
Ref::map(self.buffers.borrow(), |x| T::unwrap(x.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -10,6 +10,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where T: '_#2r
|
||||
= note: where '_#1r: '_#2r
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where '_#1r: '_#2r
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
|
||||
note: No external requirements
|
||||
--> $DIR/projection-one-region-trait-bound-static-closure.rs:42:1
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#4r
|
||||
= note: number of external vids: 5
|
||||
= note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
|
||||
|
||||
|
|
@ -212,6 +213,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ LL | twice(cell, value, |a, b| invoke(a, b));
|
|||
i16,
|
||||
for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T))
|
||||
]
|
||||
= note: late-bound region is '_#2r
|
||||
= note: number of external vids: 3
|
||||
= note: where T: '_#1r
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ LL | | })
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#2r
|
||||
= note: number of external vids: 3
|
||||
= note: where T: '_#1r
|
||||
|
||||
|
|
@ -106,6 +107,7 @@ LL | | })
|
|||
i32,
|
||||
extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
|
||||
]
|
||||
= note: late-bound region is '_#3r
|
||||
= note: number of external vids: 4
|
||||
= note: where T: '_#2r
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue