mirror of
https://github.com/rust-lang/rust
synced 2024-10-14 12:33:57 +00:00
Auto merge of #55229 - nikomatsakis:issue-54692-closure-signatures, r=MatthewJasper
enforce user annotations in closure signatures Not *quite* ready yet but I'm opening anyway. Still have to finish running tests locally. Fixes #54692 Fixes #54124 r? @matthewjasper
This commit is contained in:
commit
f99911a4a0
|
@ -50,7 +50,8 @@
|
|||
use ty::steal::Steal;
|
||||
use ty::BindingMode;
|
||||
use ty::CanonicalTy;
|
||||
use util::nodemap::{DefIdSet, ItemLocalMap};
|
||||
use ty::CanonicalPolyFnSig;
|
||||
use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use smallvec::SmallVec;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
|
||||
|
@ -344,10 +345,6 @@ pub struct TypeckTables<'tcx> {
|
|||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated until after typeck. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
|
@ -359,6 +356,14 @@ pub struct TypeckTables<'tcx> {
|
|||
/// other items.
|
||||
node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
/// Stores the substitutions that the user explicitly gave (if any)
|
||||
/// attached to `id`. These will not include any inferred
|
||||
/// values. The canonical form is used to capture things like `_`
|
||||
|
@ -442,6 +447,7 @@ pub fn empty(local_id_root: Option<DefId>) -> TypeckTables<'tcx> {
|
|||
type_dependent_defs: ItemLocalMap(),
|
||||
field_indices: ItemLocalMap(),
|
||||
user_provided_tys: ItemLocalMap(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: ItemLocalMap(),
|
||||
node_substs: ItemLocalMap(),
|
||||
user_substs: ItemLocalMap(),
|
||||
|
@ -748,6 +754,7 @@ fn hash_stable<W: StableHasherResult>(&self,
|
|||
ref type_dependent_defs,
|
||||
ref field_indices,
|
||||
ref user_provided_tys,
|
||||
ref user_provided_sigs,
|
||||
ref node_types,
|
||||
ref node_substs,
|
||||
ref user_substs,
|
||||
|
@ -771,6 +778,7 @@ fn hash_stable<W: StableHasherResult>(&self,
|
|||
type_dependent_defs.hash_stable(hcx, hasher);
|
||||
field_indices.hash_stable(hcx, hasher);
|
||||
user_provided_tys.hash_stable(hcx, hasher);
|
||||
user_provided_sigs.hash_stable(hcx, hasher);
|
||||
node_types.hash_stable(hcx, hasher);
|
||||
node_substs.hash_stable(hcx, hasher);
|
||||
user_substs.hash_stable(hcx, hasher);
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
use hir;
|
||||
|
||||
pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
|
||||
pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig};
|
||||
pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
|
||||
pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
|
||||
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
|
||||
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! This module contains TyKind and its major components
|
||||
|
||||
use hir::def_id::DefId;
|
||||
|
||||
use infer::canonical::Canonical;
|
||||
use mir::interpret::ConstValue;
|
||||
use middle::region;
|
||||
use polonius_engine::Atom;
|
||||
|
@ -980,6 +980,9 @@ pub fn abi(&self) -> abi::Abi {
|
|||
}
|
||||
}
|
||||
|
||||
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
|
||||
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct ParamTy {
|
||||
pub idx: u32,
|
||||
|
|
|
@ -1208,6 +1208,7 @@ fn check_universal_region<'gcx>(
|
|||
// to report the error. This gives better error messages
|
||||
// in some cases.
|
||||
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
||||
return; // continuing to iterate just reports more errors than necessary
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
//! contain revealed `impl Trait` values).
|
||||
|
||||
use borrow_check::nll::universal_regions::UniversalRegions;
|
||||
use rustc::infer::LateBoundRegionConversionTime;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::Ty;
|
||||
|
||||
|
@ -36,9 +37,47 @@ pub(super) fn equate_inputs_and_outputs(
|
|||
let (&normalized_output_ty, normalized_input_tys) =
|
||||
normalized_inputs_and_output.split_last().unwrap();
|
||||
|
||||
// If the user explicitly annotated the input types, extract
|
||||
// those.
|
||||
//
|
||||
// e.g. `|x: FxHashMap<_, &'static u32>| ...`
|
||||
let user_provided_sig;
|
||||
if !self.tcx().is_closure(self.mir_def_id) {
|
||||
user_provided_sig = None;
|
||||
} else {
|
||||
let typeck_tables = self.tcx().typeck_tables_of(self.mir_def_id);
|
||||
user_provided_sig = match typeck_tables.user_provided_sigs.get(&self.mir_def_id) {
|
||||
None => None,
|
||||
Some(user_provided_poly_sig) => {
|
||||
// Instantiate the canonicalized variables from
|
||||
// user-provided signature (e.g. the `_` in the code
|
||||
// above) with fresh variables.
|
||||
let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
|
||||
mir.span,
|
||||
&user_provided_poly_sig,
|
||||
);
|
||||
|
||||
// Replace the bound items in the fn sig with fresh
|
||||
// variables, so that they represent the view from
|
||||
// "inside" the closure.
|
||||
Some(
|
||||
self.infcx
|
||||
.replace_late_bound_regions_with_fresh_var(
|
||||
mir.span,
|
||||
LateBoundRegionConversionTime::FnCall,
|
||||
&poly_sig,
|
||||
)
|
||||
.0,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Equate expected input tys with those in the MIR.
|
||||
let argument_locals = (1..).map(Local::new);
|
||||
for (&normalized_input_ty, local) in normalized_input_tys.iter().zip(argument_locals) {
|
||||
for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
|
||||
// In MIR, argument N is stored in local N+1.
|
||||
let local = Local::new(argument_index + 1);
|
||||
|
||||
debug!(
|
||||
"equate_inputs_and_outputs: normalized_input_ty = {:?}",
|
||||
normalized_input_ty
|
||||
|
@ -53,6 +92,27 @@ pub(super) fn equate_inputs_and_outputs(
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(user_provided_sig) = user_provided_sig {
|
||||
for (&user_provided_input_ty, argument_index) in
|
||||
user_provided_sig.inputs().iter().zip(0..)
|
||||
{
|
||||
// In MIR, closures begin an implicit `self`, so
|
||||
// argument N is stored in local N+2.
|
||||
let local = Local::new(argument_index + 2);
|
||||
let mir_input_ty = mir.local_decls[local].ty;
|
||||
let mir_input_span = mir.local_decls[local].source_info.span;
|
||||
|
||||
// If the user explicitly annotated the input types, enforce those.
|
||||
let user_provided_input_ty =
|
||||
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
|
||||
self.equate_normalized_input_or_output(
|
||||
user_provided_input_ty,
|
||||
mir_input_ty,
|
||||
mir_input_span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
mir.yield_ty.is_some() && universal_regions.yield_ty.is_some()
|
||||
|| mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
|
||||
|
@ -83,6 +143,18 @@ pub(super) fn equate_inputs_and_outputs(
|
|||
terr
|
||||
);
|
||||
};
|
||||
|
||||
// If the user explicitly annotated the output types, enforce those.
|
||||
if let Some(user_provided_sig) = user_provided_sig {
|
||||
let user_provided_output_ty = user_provided_sig.output();
|
||||
let user_provided_output_ty =
|
||||
self.normalize(user_provided_output_ty, Locations::All(output_span));
|
||||
self.equate_normalized_input_or_output(
|
||||
user_provided_output_ty,
|
||||
mir_output_ty,
|
||||
output_span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
|
||||
|
|
|
@ -1033,6 +1033,12 @@ fn relate_type_and_user_type(
|
|||
assert!(!impl_self_ty.has_infer_types());
|
||||
|
||||
self.eq_types(self_ty, impl_self_ty, locations, category)?;
|
||||
|
||||
self.prove_predicate(
|
||||
ty::Predicate::WellFormed(impl_self_ty),
|
||||
locations,
|
||||
category,
|
||||
);
|
||||
}
|
||||
|
||||
// Prove the predicates coming along with `def_id`.
|
||||
|
@ -1070,11 +1076,9 @@ fn relate_type_and_user_type(
|
|||
/// particularly necessary -- we'll do it lazilly as we process
|
||||
/// the value anyway -- but in some specific cases it is useful to
|
||||
/// normalize so we can suppress duplicate error messages.
|
||||
fn fold_to_region_vid<T>(
|
||||
&self,
|
||||
value: T
|
||||
) -> T
|
||||
where T: TypeFoldable<'tcx>
|
||||
fn fold_to_region_vid<T>(&self, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
if let Some(borrowck_context) = &self.borrowck_context {
|
||||
self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
|
||||
|
@ -1210,12 +1214,14 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
|
|||
// though.
|
||||
let category = match *place {
|
||||
Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
|
||||
universal_regions: UniversalRegions {
|
||||
defining_ty: DefiningTy::Const(def_id, _),
|
||||
..
|
||||
},
|
||||
universal_regions:
|
||||
UniversalRegions {
|
||||
defining_ty: DefiningTy::Const(def_id, _),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) = self.borrowck_context {
|
||||
}) = self.borrowck_context
|
||||
{
|
||||
if tcx.is_static(*def_id).is_some() {
|
||||
ConstraintCategory::UseAsStatic
|
||||
} else {
|
||||
|
@ -1223,7 +1229,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
|
|||
}
|
||||
} else {
|
||||
ConstraintCategory::Return
|
||||
}
|
||||
},
|
||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||
ConstraintCategory::Boring
|
||||
}
|
||||
|
@ -1510,12 +1516,14 @@ fn check_call_dest(
|
|||
let category = match *dest {
|
||||
Place::Local(RETURN_PLACE) => {
|
||||
if let Some(BorrowCheckContext {
|
||||
universal_regions: UniversalRegions {
|
||||
defining_ty: DefiningTy::Const(def_id, _),
|
||||
..
|
||||
},
|
||||
universal_regions:
|
||||
UniversalRegions {
|
||||
defining_ty: DefiningTy::Const(def_id, _),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) = self.borrowck_context {
|
||||
}) = self.borrowck_context
|
||||
{
|
||||
if tcx.is_static(*def_id).is_some() {
|
||||
ConstraintCategory::UseAsStatic
|
||||
} else {
|
||||
|
@ -1524,7 +1532,7 @@ fn check_call_dest(
|
|||
} else {
|
||||
ConstraintCategory::Return
|
||||
}
|
||||
},
|
||||
}
|
||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||
ConstraintCategory::Boring
|
||||
}
|
||||
|
@ -1582,12 +1590,9 @@ fn check_call_inputs(
|
|||
} else {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
if let Err(terr) = self.sub_types(
|
||||
op_arg_ty,
|
||||
fn_arg,
|
||||
term_location.to_locations(),
|
||||
category,
|
||||
) {
|
||||
if let Err(terr) =
|
||||
self.sub_types(op_arg_ty, fn_arg, term_location.to_locations(), category)
|
||||
{
|
||||
span_mirbug!(
|
||||
self,
|
||||
term,
|
||||
|
|
|
@ -377,7 +377,7 @@ fn sig_of_closure_no_expectation(
|
|||
) -> ClosureSignatures<'tcx> {
|
||||
debug!("sig_of_closure_no_expectation()");
|
||||
|
||||
let bound_sig = self.supplied_sig_of_closure(decl);
|
||||
let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl);
|
||||
|
||||
self.closure_sigs(expr_def_id, body, bound_sig)
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ fn sig_of_closure_with_expectation(
|
|||
// Along the way, it also writes out entries for types that the user
|
||||
// wrote into our tables, which are then later used by the privacy
|
||||
// check.
|
||||
match self.check_supplied_sig_against_expectation(decl, &closure_sigs) {
|
||||
match self.check_supplied_sig_against_expectation(expr_def_id, decl, &closure_sigs) {
|
||||
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
|
||||
Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body),
|
||||
}
|
||||
|
@ -521,6 +521,7 @@ fn sig_of_closure_with_mismatched_number_of_arguments(
|
|||
/// strategy.
|
||||
fn check_supplied_sig_against_expectation(
|
||||
&self,
|
||||
expr_def_id: DefId,
|
||||
decl: &hir::FnDecl,
|
||||
expected_sigs: &ClosureSignatures<'tcx>,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
|
@ -528,7 +529,7 @@ fn check_supplied_sig_against_expectation(
|
|||
//
|
||||
// (See comment on `sig_of_closure_with_expectation` for the
|
||||
// meaning of these letters.)
|
||||
let supplied_sig = self.supplied_sig_of_closure(decl);
|
||||
let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl);
|
||||
|
||||
debug!(
|
||||
"check_supplied_sig_against_expectation: supplied_sig={:?}",
|
||||
|
@ -598,7 +599,13 @@ fn check_supplied_sig_against_expectation(
|
|||
|
||||
/// If there is no expected signature, then we will convert the
|
||||
/// types that the user gave into a signature.
|
||||
fn supplied_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> {
|
||||
///
|
||||
/// Also, record this closure signature for later.
|
||||
fn supplied_sig_of_closure(
|
||||
&self,
|
||||
expr_def_id: DefId,
|
||||
decl: &hir::FnDecl,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let astconv: &dyn AstConv = self;
|
||||
|
||||
// First, convert the types that the user supplied (if any).
|
||||
|
@ -618,6 +625,12 @@ fn supplied_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> {
|
|||
|
||||
debug!("supplied_sig_of_closure: result={:?}", result);
|
||||
|
||||
let c_result = self.inh.infcx.canonicalize_response(&result);
|
||||
self.tables.borrow_mut().user_provided_sigs.insert(
|
||||
expr_def_id,
|
||||
c_result,
|
||||
);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
|
|||
wbcx.visit_cast_types();
|
||||
wbcx.visit_free_region_map();
|
||||
wbcx.visit_user_provided_tys();
|
||||
wbcx.visit_user_provided_sigs();
|
||||
|
||||
let used_trait_imports = mem::replace(
|
||||
&mut self.tables.borrow_mut().used_trait_imports,
|
||||
|
@ -388,6 +389,27 @@ fn visit_user_provided_tys(&mut self) {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_user_provided_sigs(&mut self) {
|
||||
let fcx_tables = self.fcx.tables.borrow();
|
||||
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
|
||||
|
||||
for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() {
|
||||
let c_sig = if let Some(c_sig) = self.tcx().lift_to_global(c_sig) {
|
||||
c_sig
|
||||
} else {
|
||||
span_bug!(
|
||||
self.fcx.tcx.hir.span_if_local(def_id).unwrap(),
|
||||
"writeback: `{:?}` missing from the global type context",
|
||||
c_sig
|
||||
);
|
||||
};
|
||||
|
||||
self.tables
|
||||
.user_provided_sigs
|
||||
.insert(def_id, c_sig.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_opaque_types(&mut self, span: Span) {
|
||||
for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
|
||||
let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
|
||||
|
|
|
@ -95,7 +95,7 @@ pub fn add_type_ascription_to_parameter() {
|
|||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(cfg="cfail2", except="HirBody")]
|
||||
#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
pub fn add_type_ascription_to_parameter() {
|
||||
let closure = |x: u32| x + 1u32;
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-compare-mode-nll
|
||||
|
||||
struct Foo<'a, 'b: 'a>(&'a &'b ());
|
||||
|
||||
impl<'a, 'b> Foo<'a, 'b> {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
error[E0478]: lifetime bound not satisfied
|
||||
--> $DIR/issue-28848.rs:22:5
|
||||
--> $DIR/issue-28848.rs:20:5
|
||||
|
|
||||
LL | Foo::<'a, 'b>::xmute(u) //~ ERROR lifetime bound not satisfied
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 21:16
|
||||
--> $DIR/issue-28848.rs:21:16
|
||||
note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 19:16
|
||||
--> $DIR/issue-28848.rs:19:16
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
| ^^
|
||||
note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 21:12
|
||||
--> $DIR/issue-28848.rs:21:12
|
||||
note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 19:12
|
||||
--> $DIR/issue-28848.rs:19:12
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
| ^^
|
||||
|
|
|
@ -47,7 +47,6 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
|||
|
||||
// Only works if 'x: 'y:
|
||||
demand_y(x, y, x.get())
|
||||
//~^ ERROR unsatisfied lifetime constraints
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ LL | | //~^ ERROR borrowed data escapes outside of function
|
|||
LL | |
|
||||
LL | | // Only works if 'x: 'y:
|
||||
LL | | demand_y(x, y, x.get())
|
||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
|
||||
|
@ -44,21 +43,9 @@ LL | | //~^ ERROR borrowed data escapes outside of function
|
|||
LL | |
|
||||
LL | | // Only works if 'x: 'y:
|
||||
LL | | demand_y(x, y, x.get())
|
||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
||||
LL | | });
|
||||
| |______^ `cell_a` escapes the function body here
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9
|
||||
|
|
||||
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | demand_y(x, y, x.get())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0521`.
|
||||
|
|
|
@ -47,9 +47,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
|
|||
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
||||
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||
//~^ ERROR borrowed data escapes outside of function
|
||||
|
||||
// Only works if 'x: 'y:
|
||||
demand_y(x, y, x.get())
|
||||
//~^ ERROR unsatisfied lifetime constraints
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ note: External requirements
|
|||
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||
| _______________________________________________^
|
||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||
LL | |
|
||||
LL | | // Only works if 'x: 'y:
|
||||
LL | | demand_y(x, y, x.get())
|
||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
|
||||
|
@ -25,7 +25,7 @@ note: No external requirements
|
|||
LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
||||
LL | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||
LL | | // Only works if 'x: 'y:
|
||||
LL | |
|
||||
... |
|
||||
LL | | });
|
||||
LL | | }
|
||||
|
@ -40,23 +40,12 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
|||
| ------ `cell_a` is a reference that is only valid in the function body
|
||||
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||
LL | |
|
||||
LL | | // Only works if 'x: 'y:
|
||||
LL | | demand_y(x, y, x.get())
|
||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
||||
LL | | });
|
||||
| |______^ `cell_a` escapes the function body here
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9
|
||||
|
|
||||
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | demand_y(x, y, x.get())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0521`.
|
||||
|
|
43
src/test/ui/nll/user-annotations/closure-substs.rs
Normal file
43
src/test/ui/nll/user-annotations/closure-substs.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
// 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.
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
// Test that we enforce user-provided type annotations on closures.
|
||||
|
||||
fn foo<'a>() {
|
||||
// Here `x` is free in the closure sig:
|
||||
|x: &'a i32| -> &'static i32 {
|
||||
return x; //~ ERROR unsatisfied lifetime constraints
|
||||
};
|
||||
}
|
||||
|
||||
fn foo1() {
|
||||
// Here `x` is bound in the closure sig:
|
||||
|x: &i32| -> &'static i32 {
|
||||
return x; //~ ERROR unsatisfied lifetime constraints
|
||||
};
|
||||
}
|
||||
|
||||
fn bar<'a>() {
|
||||
// Here `x` is free in the closure sig:
|
||||
|x: &'a i32, b: fn(&'static i32)| {
|
||||
b(x); //~ ERROR unsatisfied lifetime constraints
|
||||
};
|
||||
}
|
||||
|
||||
fn bar1() {
|
||||
// Here `x` is bound in the closure sig:
|
||||
|x: &i32, b: fn(&'static i32)| {
|
||||
b(x); //~ ERROR borrowed data escapes outside of closure
|
||||
};
|
||||
}
|
||||
|
||||
fn main() { }
|
37
src/test/ui/nll/user-annotations/closure-substs.stderr
Normal file
37
src/test/ui/nll/user-annotations/closure-substs.stderr
Normal file
|
@ -0,0 +1,37 @@
|
|||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/closure-substs.rs:18:16
|
||||
|
|
||||
LL | fn foo<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | return x; //~ ERROR unsatisfied lifetime constraints
|
||||
| ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/closure-substs.rs:25:16
|
||||
|
|
||||
LL | |x: &i32| -> &'static i32 {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | return x; //~ ERROR unsatisfied lifetime constraints
|
||||
| ^ returning this value requires that `'1` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/closure-substs.rs:32:9
|
||||
|
|
||||
LL | fn bar<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | b(x); //~ ERROR unsatisfied lifetime constraints
|
||||
| ^^^^ argument requires that `'a` must outlive `'static`
|
||||
|
||||
error[E0521]: borrowed data escapes outside of closure
|
||||
--> $DIR/closure-substs.rs:39:9
|
||||
|
|
||||
LL | |x: &i32, b: fn(&'static i32)| {
|
||||
| - `x` is a reference that is only valid in the closure body
|
||||
LL | b(x); //~ ERROR borrowed data escapes outside of closure
|
||||
| ^^^^ `x` escapes the closure body here
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0521`.
|
9
src/test/ui/nll/user-annotations/issue-54124.rs
Normal file
9
src/test/ui/nll/user-annotations/issue-54124.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
#![feature(nll)]
|
||||
|
||||
fn test<'a>() {
|
||||
let _:fn(&()) = |_:&'a ()| {};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test();
|
||||
}
|
20
src/test/ui/nll/user-annotations/issue-54124.stderr
Normal file
20
src/test/ui/nll/user-annotations/issue-54124.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/issue-54124.rs:4:22
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let _:fn(&()) = |_:&'a ()| {};
|
||||
| ^ - let's call the lifetime of this reference `'1`
|
||||
| |
|
||||
| requires that `'1` must outlive `'a`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/issue-54124.rs:4:22
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let _:fn(&()) = |_:&'a ()| {};
|
||||
| ^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
25
src/test/ui/nll/user-annotations/wf-self-type.rs
Normal file
25
src/test/ui/nll/user-annotations/wf-self-type.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
// 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.
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
struct Foo<'a, 'b: 'a>(&'a &'b ());
|
||||
|
||||
impl<'a, 'b> Foo<'a, 'b> {
|
||||
fn xmute(a: &'b ()) -> &'a () {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/nll/user-annotations/wf-self-type.stderr
Normal file
12
src/test/ui/nll/user-annotations/wf-self-type.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/wf-self-type.rs:22:5
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
|
||||
| ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -20,7 +20,7 @@ LL | static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of
|
|||
| ^^^^^^^^^ lifetime `'static` required
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `v`
|
||||
--> $DIR/regions-static-bound.rs:27:5
|
||||
--> $DIR/regions-static-bound.rs:26:5
|
||||
|
|
||||
LL | fn error(u: &(), v: &()) {
|
||||
| --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
|
||||
|
|
|
@ -15,7 +15,7 @@ LL | static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of
|
|||
| ^^^^^^^^^^^^^ lifetime `'static` required
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `v`
|
||||
--> $DIR/regions-static-bound.rs:27:5
|
||||
--> $DIR/regions-static-bound.rs:26:5
|
||||
|
|
||||
LL | fn error(u: &(), v: &()) {
|
||||
| --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
|
||||
|
@ -23,27 +23,6 @@ LL | fn error(u: &(), v: &()) {
|
|||
LL | static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/regions-static-bound.rs:24:5
|
||||
|
|
||||
LL | fn error(u: &(), v: &()) {
|
||||
| - - let's call the lifetime of this reference `'2`
|
||||
| |
|
||||
| let's call the lifetime of this reference `'1`
|
||||
LL | static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
|
||||
| ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/regions-static-bound.rs:27:5
|
||||
|
|
||||
LL | fn error(u: &(), v: &()) {
|
||||
| - - let's call the lifetime of this reference `'1`
|
||||
| |
|
||||
| let's call the lifetime of this reference `'2`
|
||||
...
|
||||
LL | static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0621`.
|
||||
|
|
|
@ -23,10 +23,8 @@ fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
|
|||
fn error(u: &(), v: &()) {
|
||||
static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
|
||||
//[nll]~^ ERROR explicit lifetime required in the type of `u` [E0621]
|
||||
//[nll]~| ERROR unsatisfied lifetime constraints
|
||||
static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
|
||||
//[nll]~^ ERROR explicit lifetime required in the type of `v` [E0621]
|
||||
//[nll]~| ERROR unsatisfied lifetime constraints
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
Loading…
Reference in a new issue