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:
@@ -50,7 +50,8 @@ use ty::query;
|
|||||||
use ty::steal::Steal;
|
use ty::steal::Steal;
|
||||||
use ty::BindingMode;
|
use ty::BindingMode;
|
||||||
use ty::CanonicalTy;
|
use ty::CanonicalTy;
|
||||||
use util::nodemap::{DefIdSet, ItemLocalMap};
|
use ty::CanonicalPolyFnSig;
|
||||||
|
use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
|
||||||
use util::nodemap::{FxHashMap, FxHashSet};
|
use util::nodemap::{FxHashMap, FxHashSet};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
|
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`).
|
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||||
field_indices: ItemLocalMap<usize>,
|
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
|
/// Stores the types for various nodes in the AST. Note that this table
|
||||||
/// is not guaranteed to be populated until after typeck. See
|
/// is not guaranteed to be populated until after typeck. See
|
||||||
/// typeck::check::fn_ctxt for details.
|
/// typeck::check::fn_ctxt for details.
|
||||||
@@ -359,6 +356,14 @@ pub struct TypeckTables<'tcx> {
|
|||||||
/// other items.
|
/// other items.
|
||||||
node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
|
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)
|
/// Stores the substitutions that the user explicitly gave (if any)
|
||||||
/// attached to `id`. These will not include any inferred
|
/// attached to `id`. These will not include any inferred
|
||||||
/// values. The canonical form is used to capture things like `_`
|
/// values. The canonical form is used to capture things like `_`
|
||||||
@@ -442,6 +447,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
type_dependent_defs: ItemLocalMap(),
|
type_dependent_defs: ItemLocalMap(),
|
||||||
field_indices: ItemLocalMap(),
|
field_indices: ItemLocalMap(),
|
||||||
user_provided_tys: ItemLocalMap(),
|
user_provided_tys: ItemLocalMap(),
|
||||||
|
user_provided_sigs: Default::default(),
|
||||||
node_types: ItemLocalMap(),
|
node_types: ItemLocalMap(),
|
||||||
node_substs: ItemLocalMap(),
|
node_substs: ItemLocalMap(),
|
||||||
user_substs: ItemLocalMap(),
|
user_substs: ItemLocalMap(),
|
||||||
@@ -748,6 +754,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
|||||||
ref type_dependent_defs,
|
ref type_dependent_defs,
|
||||||
ref field_indices,
|
ref field_indices,
|
||||||
ref user_provided_tys,
|
ref user_provided_tys,
|
||||||
|
ref user_provided_sigs,
|
||||||
ref node_types,
|
ref node_types,
|
||||||
ref node_substs,
|
ref node_substs,
|
||||||
ref user_substs,
|
ref user_substs,
|
||||||
@@ -771,6 +778,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
|||||||
type_dependent_defs.hash_stable(hcx, hasher);
|
type_dependent_defs.hash_stable(hcx, hasher);
|
||||||
field_indices.hash_stable(hcx, hasher);
|
field_indices.hash_stable(hcx, hasher);
|
||||||
user_provided_tys.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_types.hash_stable(hcx, hasher);
|
||||||
node_substs.hash_stable(hcx, hasher);
|
node_substs.hash_stable(hcx, hasher);
|
||||||
user_substs.hash_stable(hcx, hasher);
|
user_substs.hash_stable(hcx, hasher);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
|
|||||||
use hir;
|
use hir;
|
||||||
|
|
||||||
pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
|
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::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
|
||||||
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
|
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
|
||||||
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
|
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
//! This module contains TyKind and its major components
|
//! This module contains TyKind and its major components
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
|
use infer::canonical::Canonical;
|
||||||
use mir::interpret::ConstValue;
|
use mir::interpret::ConstValue;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use polonius_engine::Atom;
|
use polonius_engine::Atom;
|
||||||
@@ -980,6 +980,9 @@ impl<'tcx> PolyFnSig<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ParamTy {
|
pub struct ParamTy {
|
||||||
pub idx: u32,
|
pub idx: u32,
|
||||||
|
|||||||
@@ -1208,6 +1208,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
// to report the error. This gives better error messages
|
// to report the error. This gives better error messages
|
||||||
// in some cases.
|
// in some cases.
|
||||||
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
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).
|
//! contain revealed `impl Trait` values).
|
||||||
|
|
||||||
use borrow_check::nll::universal_regions::UniversalRegions;
|
use borrow_check::nll::universal_regions::UniversalRegions;
|
||||||
|
use rustc::infer::LateBoundRegionConversionTime;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::ty::Ty;
|
use rustc::ty::Ty;
|
||||||
|
|
||||||
@@ -36,9 +37,47 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
let (&normalized_output_ty, normalized_input_tys) =
|
let (&normalized_output_ty, normalized_input_tys) =
|
||||||
normalized_inputs_and_output.split_last().unwrap();
|
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.
|
// Equate expected input tys with those in the MIR.
|
||||||
let argument_locals = (1..).map(Local::new);
|
for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
|
||||||
for (&normalized_input_ty, local) in normalized_input_tys.iter().zip(argument_locals) {
|
// In MIR, argument N is stored in local N+1.
|
||||||
|
let local = Local::new(argument_index + 1);
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"equate_inputs_and_outputs: normalized_input_ty = {:?}",
|
"equate_inputs_and_outputs: normalized_input_ty = {:?}",
|
||||||
normalized_input_ty
|
normalized_input_ty
|
||||||
@@ -53,6 +92,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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!(
|
assert!(
|
||||||
mir.yield_ty.is_some() && universal_regions.yield_ty.is_some()
|
mir.yield_ty.is_some() && universal_regions.yield_ty.is_some()
|
||||||
|| mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
|
|| mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
|
||||||
@@ -83,6 +143,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
terr
|
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) {
|
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
|
||||||
|
|||||||
@@ -1033,6 +1033,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
assert!(!impl_self_ty.has_infer_types());
|
assert!(!impl_self_ty.has_infer_types());
|
||||||
|
|
||||||
self.eq_types(self_ty, impl_self_ty, locations, category)?;
|
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`.
|
// Prove the predicates coming along with `def_id`.
|
||||||
@@ -1070,11 +1076,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
/// particularly necessary -- we'll do it lazilly as we process
|
/// particularly necessary -- we'll do it lazilly as we process
|
||||||
/// the value anyway -- but in some specific cases it is useful to
|
/// the value anyway -- but in some specific cases it is useful to
|
||||||
/// normalize so we can suppress duplicate error messages.
|
/// normalize so we can suppress duplicate error messages.
|
||||||
fn fold_to_region_vid<T>(
|
fn fold_to_region_vid<T>(&self, value: T) -> T
|
||||||
&self,
|
where
|
||||||
value: T
|
T: TypeFoldable<'tcx>,
|
||||||
) -> T
|
|
||||||
where T: TypeFoldable<'tcx>
|
|
||||||
{
|
{
|
||||||
if let Some(borrowck_context) = &self.borrowck_context {
|
if let Some(borrowck_context) = &self.borrowck_context {
|
||||||
self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
|
self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
|
||||||
@@ -1210,12 +1214,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
// though.
|
// though.
|
||||||
let category = match *place {
|
let category = match *place {
|
||||||
Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
|
Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
|
||||||
universal_regions: UniversalRegions {
|
universal_regions:
|
||||||
|
UniversalRegions {
|
||||||
defining_ty: DefiningTy::Const(def_id, _),
|
defining_ty: DefiningTy::Const(def_id, _),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
}) = self.borrowck_context {
|
}) = self.borrowck_context
|
||||||
|
{
|
||||||
if tcx.is_static(*def_id).is_some() {
|
if tcx.is_static(*def_id).is_some() {
|
||||||
ConstraintCategory::UseAsStatic
|
ConstraintCategory::UseAsStatic
|
||||||
} else {
|
} else {
|
||||||
@@ -1223,7 +1229,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ConstraintCategory::Return
|
ConstraintCategory::Return
|
||||||
}
|
},
|
||||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
}
|
}
|
||||||
@@ -1510,12 +1516,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
let category = match *dest {
|
let category = match *dest {
|
||||||
Place::Local(RETURN_PLACE) => {
|
Place::Local(RETURN_PLACE) => {
|
||||||
if let Some(BorrowCheckContext {
|
if let Some(BorrowCheckContext {
|
||||||
universal_regions: UniversalRegions {
|
universal_regions:
|
||||||
|
UniversalRegions {
|
||||||
defining_ty: DefiningTy::Const(def_id, _),
|
defining_ty: DefiningTy::Const(def_id, _),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
}) = self.borrowck_context {
|
}) = self.borrowck_context
|
||||||
|
{
|
||||||
if tcx.is_static(*def_id).is_some() {
|
if tcx.is_static(*def_id).is_some() {
|
||||||
ConstraintCategory::UseAsStatic
|
ConstraintCategory::UseAsStatic
|
||||||
} else {
|
} else {
|
||||||
@@ -1524,7 +1532,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
ConstraintCategory::Return
|
ConstraintCategory::Return
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
}
|
}
|
||||||
@@ -1582,12 +1590,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
};
|
};
|
||||||
if let Err(terr) = self.sub_types(
|
if let Err(terr) =
|
||||||
op_arg_ty,
|
self.sub_types(op_arg_ty, fn_arg, term_location.to_locations(), category)
|
||||||
fn_arg,
|
{
|
||||||
term_location.to_locations(),
|
|
||||||
category,
|
|
||||||
) {
|
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
self,
|
self,
|
||||||
term,
|
term,
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
) -> ClosureSignatures<'tcx> {
|
) -> ClosureSignatures<'tcx> {
|
||||||
debug!("sig_of_closure_no_expectation()");
|
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)
|
self.closure_sigs(expr_def_id, body, bound_sig)
|
||||||
}
|
}
|
||||||
@@ -479,7 +479,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// Along the way, it also writes out entries for types that the user
|
// 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
|
// wrote into our tables, which are then later used by the privacy
|
||||||
// check.
|
// 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),
|
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
|
||||||
Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body),
|
Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body),
|
||||||
}
|
}
|
||||||
@@ -521,6 +521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
/// strategy.
|
/// strategy.
|
||||||
fn check_supplied_sig_against_expectation(
|
fn check_supplied_sig_against_expectation(
|
||||||
&self,
|
&self,
|
||||||
|
expr_def_id: DefId,
|
||||||
decl: &hir::FnDecl,
|
decl: &hir::FnDecl,
|
||||||
expected_sigs: &ClosureSignatures<'tcx>,
|
expected_sigs: &ClosureSignatures<'tcx>,
|
||||||
) -> InferResult<'tcx, ()> {
|
) -> InferResult<'tcx, ()> {
|
||||||
@@ -528,7 +529,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
//
|
//
|
||||||
// (See comment on `sig_of_closure_with_expectation` for the
|
// (See comment on `sig_of_closure_with_expectation` for the
|
||||||
// meaning of these letters.)
|
// 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!(
|
debug!(
|
||||||
"check_supplied_sig_against_expectation: supplied_sig={:?}",
|
"check_supplied_sig_against_expectation: supplied_sig={:?}",
|
||||||
@@ -598,7 +599,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
/// If there is no expected signature, then we will convert the
|
/// If there is no expected signature, then we will convert the
|
||||||
/// types that the user gave into a signature.
|
/// 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;
|
let astconv: &dyn AstConv = self;
|
||||||
|
|
||||||
// First, convert the types that the user supplied (if any).
|
// First, convert the types that the user supplied (if any).
|
||||||
@@ -618,6 +625,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
debug!("supplied_sig_of_closure: result={:?}", result);
|
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
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
wbcx.visit_cast_types();
|
wbcx.visit_cast_types();
|
||||||
wbcx.visit_free_region_map();
|
wbcx.visit_free_region_map();
|
||||||
wbcx.visit_user_provided_tys();
|
wbcx.visit_user_provided_tys();
|
||||||
|
wbcx.visit_user_provided_sigs();
|
||||||
|
|
||||||
let used_trait_imports = mem::replace(
|
let used_trait_imports = mem::replace(
|
||||||
&mut self.tables.borrow_mut().used_trait_imports,
|
&mut self.tables.borrow_mut().used_trait_imports,
|
||||||
@@ -388,6 +389,27 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
fn visit_opaque_types(&mut self, span: Span) {
|
||||||
for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
|
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();
|
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))]
|
#[cfg(not(cfail1))]
|
||||||
#[rustc_clean(cfg="cfail2", except="HirBody")]
|
#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")]
|
||||||
#[rustc_clean(cfg="cfail3")]
|
#[rustc_clean(cfg="cfail3")]
|
||||||
pub fn add_type_ascription_to_parameter() {
|
pub fn add_type_ascription_to_parameter() {
|
||||||
let closure = |x: u32| x + 1u32;
|
let closure = |x: u32| x + 1u32;
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// ignore-compare-mode-nll
|
|
||||||
|
|
||||||
struct Foo<'a, 'b: 'a>(&'a &'b ());
|
struct Foo<'a, 'b: 'a>(&'a &'b ());
|
||||||
|
|
||||||
impl<'a, 'b> Foo<'a, 'b> {
|
impl<'a, 'b> Foo<'a, 'b> {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
error[E0478]: lifetime bound not satisfied
|
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
|
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
|
note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 19:16
|
||||||
--> $DIR/issue-28848.rs:21:16
|
--> $DIR/issue-28848.rs:19:16
|
||||||
|
|
|
|
||||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
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
|
note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 19:12
|
||||||
--> $DIR/issue-28848.rs:21:12
|
--> $DIR/issue-28848.rs:19:12
|
||||||
|
|
|
|
||||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
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:
|
// Only works if 'x: 'y:
|
||||||
demand_y(x, y, x.get())
|
demand_y(x, y, x.get())
|
||||||
//~^ ERROR unsatisfied lifetime constraints
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ LL | | //~^ ERROR borrowed data escapes outside of function
|
|||||||
LL | |
|
LL | |
|
||||||
LL | | // Only works if 'x: 'y:
|
LL | | // Only works if 'x: 'y:
|
||||||
LL | | demand_y(x, y, x.get())
|
LL | | demand_y(x, y, x.get())
|
||||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
|
||||||
LL | | });
|
LL | | });
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
@@ -44,21 +43,9 @@ LL | | //~^ ERROR borrowed data escapes outside of function
|
|||||||
LL | |
|
LL | |
|
||||||
LL | | // Only works if 'x: 'y:
|
LL | | // Only works if 'x: 'y:
|
||||||
LL | | demand_y(x, y, x.get())
|
LL | | demand_y(x, y, x.get())
|
||||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
|
||||||
LL | | });
|
LL | | });
|
||||||
| |______^ `cell_a` escapes the function body here
|
| |______^ `cell_a` escapes the function body here
|
||||||
|
|
||||||
error: unsatisfied lifetime constraints
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0521`.
|
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>) {
|
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
|
||||||
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||||
//~^ ERROR borrowed data escapes outside of function
|
//~^ ERROR borrowed data escapes outside of function
|
||||||
|
|
||||||
// Only works if 'x: 'y:
|
// Only works if 'x: 'y:
|
||||||
demand_y(x, y, x.get())
|
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 | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||||
| _______________________________________________^
|
| _______________________________________________^
|
||||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||||
|
LL | |
|
||||||
LL | | // Only works if 'x: 'y:
|
LL | | // Only works if 'x: 'y:
|
||||||
LL | | demand_y(x, y, x.get())
|
LL | | demand_y(x, y, x.get())
|
||||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
|
||||||
LL | | });
|
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 | / 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 | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||||
LL | | // Only works if 'x: 'y:
|
LL | |
|
||||||
... |
|
... |
|
||||||
LL | | });
|
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
|
| ------ `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 | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||||
LL | | //~^ ERROR borrowed data escapes outside of function
|
LL | | //~^ ERROR borrowed data escapes outside of function
|
||||||
|
LL | |
|
||||||
LL | | // Only works if 'x: 'y:
|
LL | | // Only works if 'x: 'y:
|
||||||
LL | | demand_y(x, y, x.get())
|
LL | | demand_y(x, y, x.get())
|
||||||
LL | | //~^ ERROR unsatisfied lifetime constraints
|
|
||||||
LL | | });
|
LL | | });
|
||||||
| |______^ `cell_a` escapes the function body here
|
| |______^ `cell_a` escapes the function body here
|
||||||
|
|
||||||
error: unsatisfied lifetime constraints
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0521`.
|
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
|
| ^^^^^^^^^ lifetime `'static` required
|
||||||
|
|
||||||
error[E0621]: explicit lifetime required in the type of `v`
|
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: &()) {
|
LL | fn error(u: &(), v: &()) {
|
||||||
| --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
|
| --- 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
|
| ^^^^^^^^^^^^^ lifetime `'static` required
|
||||||
|
|
||||||
error[E0621]: explicit lifetime required in the type of `v`
|
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: &()) {
|
LL | fn error(u: &(), v: &()) {
|
||||||
| --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()`
|
| --- 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]
|
LL | static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
|
| ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
|
||||||
|
|
||||||
error: unsatisfied lifetime constraints
|
error: aborting due to 3 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0621`.
|
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: &()) {
|
fn error(u: &(), v: &()) {
|
||||||
static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
|
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 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]
|
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 explicit lifetime required in the type of `v` [E0621]
|
||||||
//[nll]~| ERROR unsatisfied lifetime constraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user