Auto merge of #43700 - gaurikholkar:struct_lifetimes, r=nikomatsakis

Adding E0623 for structs

This is a fix to #43275

The error message is
```
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
+   |
+14 | fn foo(mut x: Vec<Ref>, y: Ref) {
+   |                   ---      --- these structs are declared with different lifetimes...
+15 |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
```

r? @nikomatsakis
This commit is contained in:
bors 2017-08-25 12:59:04 +00:00
commit a4d11495f9
29 changed files with 624 additions and 204 deletions

View File

@ -27,65 +27,84 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// { x.push(y); }.
// The example gives
// fn foo(x: &mut Vec<&u8>, y: &u8) {
// --- --- these references must have the same lifetime
// --- --- these references are declared with different lifetimes...
// x.push(y);
// ^ data from `y` flows into `x` here
// It will later be extended to trait objects and structs.
// ^ ...but data from `y` flows into `x` here
// It has been extended for the case of structs too.
// Consider the example
// struct Ref<'a> { x: &'a u32 }
// fn foo(mut x: Vec<Ref>, y: Ref) {
// --- --- these structs are declared with different lifetimes...
// x.push(y);
// ^ ...but data from `y` flows into `x` here
// }
// It will later be extended to trait objects.
pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
let (span, sub, sup) = match *error {
ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
_ => return false, // inapplicable
};
// Determine whether the sub and sup consist of both anonymous (elided) regions.
let (ty1, ty2) = if self.is_suitable_anonymous_region(sup).is_some() &&
self.is_suitable_anonymous_region(sub).is_some() {
if let (Some(anon_reg1), Some(anon_reg2)) =
(self.is_suitable_anonymous_region(sup), self.is_suitable_anonymous_region(sub)) {
let ((_, br1), (_, br2)) = (anon_reg1, anon_reg2);
if self.find_anon_type(sup, &br1).is_some() &&
self.find_anon_type(sub, &br2).is_some() {
(self.find_anon_type(sup, &br1).unwrap(),
self.find_anon_type(sub, &br2).unwrap())
} else {
return false;
}
} else {
return false;
}
} else {
return false; // inapplicable
};
let anon_reg_sup = or_false!(self.is_suitable_anonymous_region(sup));
if let (Some(sup_arg), Some(sub_arg)) =
let anon_reg_sub = or_false!(self.is_suitable_anonymous_region(sub));
let scope_def_id_sup = anon_reg_sup.def_id;
let bregion_sup = anon_reg_sup.boundregion;
let scope_def_id_sub = anon_reg_sub.def_id;
let bregion_sub = anon_reg_sub.boundregion;
let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup));
let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub));
let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
(self.find_arg_with_anonymous_region(sup, sup),
self.find_arg_with_anonymous_region(sub, sub)) {
let ((anon_arg1, _, _, _), (anon_arg2, _, _, _)) = (sup_arg, sub_arg);
let span_label_var1 = if let Some(simple_name) = anon_arg1.pat.simple_name() {
let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) =
(sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first);
if self.is_self_anon(is_first_sup, scope_def_id_sup) ||
self.is_self_anon(is_first_sub, scope_def_id_sub) {
return false;
}
if self.is_return_type_anon(scope_def_id_sup, bregion_sup) ||
self.is_return_type_anon(scope_def_id_sub, bregion_sub) {
return false;
}
if anon_arg_sup == anon_arg_sub {
(format!("this type was declared with multiple lifetimes..."),
format!(" with one lifetime"),
format!(" into the other"))
} else {
let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
format!(" from `{}`", simple_name)
} else {
format!("")
};
let span_label_var2 = if let Some(simple_name) = anon_arg2.pat.simple_name() {
let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
format!(" into `{}`", simple_name)
} else {
format!("")
};
struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
.span_label(ty1.span,
format!("these references are not declared with the same lifetime..."))
.span_label(ty2.span, format!(""))
.span_label(span,
format!("...but data{}flows{}here", span_label_var1, span_label_var2))
.emit();
let span_label =
format!("these two types are declared with different lifetimes...",);
(span_label, span_label_var1, span_label_var2)
}
} else {
return false;
}
};
struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
.span_label(ty_sup.span, main_label)
.span_label(ty_sub.span, format!(""))
.span_label(span, format!("...but data{} flows{} here", label1, label2))
.emit();
return true;
}
@ -94,7 +113,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// contains the anonymous type.
///
/// # Arguments
///
/// region - the anonymous region corresponding to the anon_anon conflict
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
///
@ -105,38 +123,55 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// ```
/// The function returns the nested type corresponding to the anonymous region
/// for e.g. `&u8` and Vec<`&u8`.
fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
if let Some(anon_reg) = self.is_suitable_anonymous_region(region) {
let (def_id, _) = anon_reg;
let def_id = anon_reg.def_id;
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
let ret_ty = self.tcx.type_of(def_id);
if let ty::TyFnDef(_, _) = ret_ty.sty {
if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
return fndecl
.inputs
let inputs: &[_] =
match self.tcx.hir.get(node_id) {
hir_map::NodeItem(&hir::Item {
node: hir::ItemFn(ref fndecl, ..), ..
}) => &fndecl.inputs,
hir_map::NodeTraitItem(&hir::TraitItem {
node: hir::TraitItemKind::Method(ref fndecl, ..),
..
}) => &fndecl.decl.inputs,
hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(ref fndecl, ..),
..
}) => &fndecl.decl.inputs,
_ => &[],
};
return inputs
.iter()
.filter_map(|arg| {
self.find_component_for_bound_region(&**arg, br)
})
.next();
}
}
}
None
}
// This method creates a FindNestedTypeVisitor which returns the type corresponding
// to the anonymous region.
fn find_component_for_bound_region(&self,
arg: &'gcx hir::Ty,
br: &ty::BoundRegion)
-> Option<(&'gcx hir::Ty)> {
let mut nested_visitor = FindNestedTypeVisitor {
infcx: &self,
hir_map: &self.tcx.hir,
bound_region: *br,
found_type: None,
};
nested_visitor.visit_ty(&**arg);
if nested_visitor.found_type.is_some() {
nested_visitor.visit_ty(arg);
nested_visitor.found_type
} else {
None
}
})
.next();
}
}
}
}
}
None
}
}
@ -176,8 +211,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
hir::TyRptr(ref lifetime, _) => {
match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
// the lifetime of the TyRptr
Some(&rl::Region::LateBoundAnon(debuijn_index, anon_index)) => {
if debuijn_index.depth == 1 && anon_index == br_index {
Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
if debruijn_index.depth == 1 && anon_index == br_index {
self.found_type = Some(arg);
return; // we can stop visiting now
}
@ -191,6 +226,20 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
}
}
}
// Checks if it is of type `hir::TyPath` which corresponds to a struct.
hir::TyPath(_) => {
let subvisitor = &mut TyPathVisitor {
infcx: self.infcx,
found_it: false,
bound_region: self.bound_region,
hir_map: self.hir_map,
};
intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
// this will visit only outermost type
if subvisitor.found_it {
self.found_type = Some(arg);
}
}
_ => {}
}
// walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
@ -198,3 +247,56 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
intravisit::walk_ty(self, arg);
}
}
// The visitor captures the corresponding `hir::Ty` of the anonymous region
// in the case of structs ie. `hir::TyPath`.
// This visitor would be invoked for each lifetime corresponding to a struct,
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
hir_map: &'a hir::map::Map<'gcx>,
found_it: bool,
bound_region: ty::BoundRegion,
}
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
NestedVisitorMap::OnlyBodies(&self.hir_map)
}
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
let br_index = match self.bound_region {
ty::BrAnon(index) => index,
_ => return,
};
match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
// the lifetime of the TyPath!
Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
if debruijn_index.depth == 1 && anon_index == br_index {
self.found_it = true;
}
}
Some(&rl::Region::Static) |
Some(&rl::Region::EarlyBound(_, _)) |
Some(&rl::Region::LateBound(_, _)) |
Some(&rl::Region::Free(_, _)) |
None => {
debug!("no arg found");
}
}
}
fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
// ignore nested types
//
// If you have a type like `Foo<'a, &Ty>` we
// are only interested in the immediate lifetimes ('a).
//
// Making `visit_ty` empty will ignore the `&Ty` embedded
// inside, it will get reached by the outer visitor.
debug!("`Ty` corresponding to a struct is {:?}", arg);
}
}

View File

@ -75,8 +75,10 @@ use errors::{DiagnosticBuilder, DiagnosticStyledString};
mod note;
mod need_type_info;
mod util;
mod named_anon_conflict;
#[macro_use]
mod util;
mod anon_anon_conflict;
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

View File

@ -11,7 +11,6 @@
//! Error Reporting for Anonymous Region Lifetime Errors
//! where one region is named and the other is anonymous.
use infer::InferCtxt;
use ty;
use infer::region_inference::RegionResolutionError::*;
use infer::region_inference::RegionResolutionError;
@ -30,8 +29,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// where the anonymous region appears (there must always be one; we
// only introduced anonymous regions in parameters) as well as a
// version new_ty of its type where the anonymous region is replaced
// with the named one.
let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) =
// with the named one.//scope_def_id
let (named, anon_arg_info, region_info) =
if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() {
(sub,
self.find_arg_with_anonymous_region(sup, sub).unwrap(),
@ -44,33 +43,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
return false; // inapplicable
};
// Here, we check for the case where the anonymous region
// is in the return type.
// FIXME(#42703) - Need to handle certain cases here.
let ret_ty = self.tcx.type_of(scope_def_id);
match ret_ty.sty {
ty::TyFnDef(_, _) => {
let sig = ret_ty.fn_sig(self.tcx);
let late_bound_regions = self.tcx
.collect_referenced_late_bound_regions(&sig.output());
if late_bound_regions.iter().any(|r| *r == br) {
let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
anon_arg_info.arg_ty,
anon_arg_info.bound_region,
anon_arg_info.is_first,
region_info.def_id,
region_info.is_impl_item);
if is_impl_item {
return false;
}
}
_ => {}
}
// Here we check for the case where anonymous region
// corresponds to self and if yes, we display E0312.
// FIXME(#42700) - Need to format self properly to
// enable E0621 for it.
if is_first &&
self.tcx
.opt_associated_item(scope_def_id)
.map(|i| i.method_has_self_argument)
.unwrap_or(false) {
if self.is_return_type_anon(scope_def_id, br) || self.is_self_anon(is_first, scope_def_id) {
return false;
}
} else {
let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
(format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
@ -88,6 +73,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.span_label(span, format!("lifetime `{}` required", named))
.emit();
}
return true;
}
}

View File

@ -16,6 +16,40 @@ use ty::{self, Region};
use hir::def_id::DefId;
use hir::map as hir_map;
macro_rules! or_false {
($v:expr) => {
match $v {
Some(v) => v,
None => return false,
}
}
}
// The struct contains the information about the anonymous region
// we are searching for.
pub struct AnonymousArgInfo<'tcx> {
// the argument corresponding to the anonymous region
pub arg: &'tcx hir::Arg,
// the type corresponding to the anonymopus region argument
pub arg_ty: ty::Ty<'tcx>,
// the ty::BoundRegion corresponding to the anonymous region
pub bound_region: ty::BoundRegion,
// corresponds to id the argument is the first parameter
// in the declaration
pub is_first: bool,
}
// This struct contains information regarding the
// Refree((FreeRegion) corresponding to lifetime conflict
pub struct FreeRegionInfo {
// def id corresponding to FreeRegion
pub def_id: DefId,
// the bound region corresponding to FreeRegion
pub boundregion: ty::BoundRegion,
// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// This method walks the Type of the function body arguments using
// `fold_regions()` function and returns the
@ -28,14 +62,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// i32, which is the type of y but with the anonymous region replaced
// with 'a, the corresponding bound region and is_first which is true if
// the hir::Arg is the first argument in the function declaration.
pub fn find_arg_with_anonymous_region
(&self,
pub fn find_arg_with_anonymous_region(&self,
anon_region: Region<'tcx>,
replace_region: Region<'tcx>)
-> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
-> Option<AnonymousArgInfo> {
if let ty::ReFree(ref free_region) = *anon_region {
let id = free_region.scope;
let hir = &self.tcx.hir;
if let Some(node_id) = hir.as_local_node_id(id) {
@ -57,7 +89,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
});
if found_anon_region {
let is_first = index == 0;
Some((arg, new_arg_ty, free_region.bound_region, is_first))
Some(AnonymousArgInfo {
arg: arg,
arg_ty: new_arg_ty,
bound_region: free_region.bound_region,
is_first: is_first,
})
} else {
None
}
@ -79,9 +116,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// This method returns whether the given Region is Anonymous
// and returns the DefId and the BoundRegion corresponding to the given region.
pub fn is_suitable_anonymous_region(&self,
region: Region<'tcx>)
-> Option<(DefId, ty::BoundRegion)> {
pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
if let ty::ReFree(ref free_region) = *region {
if let ty::BrAnon(..) = free_region.bound_region {
let anonymous_region_binding_scope = free_region.scope;
@ -89,12 +124,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.hir
.as_local_node_id(anonymous_region_binding_scope)
.unwrap();
let mut is_impl_item = false;
match self.tcx.hir.find(node_id) {
Some(hir_map::NodeItem(..)) |
Some(hir_map::NodeTraitItem(..)) => {
// Success -- proceed to return Some below
}
Some(hir_map::NodeImplItem(..)) => {
is_impl_item =
self.is_bound_region_in_impl_item(anonymous_region_binding_scope);
}
_ => return None,
}
return Some(FreeRegionInfo {
def_id: anonymous_region_binding_scope,
boundregion: free_region.bound_region,
is_impl_item: is_impl_item,
});
}
}
None
}
// Here, we check for the case where the anonymous region
// is in the return type.
// FIXME(#42703) - Need to handle certain cases here.
pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool {
let ret_ty = self.tcx.type_of(scope_def_id);
match ret_ty.sty {
ty::TyFnDef(_, _) => {
let sig = ret_ty.fn_sig(self.tcx);
let late_bound_regions = self.tcx
.collect_referenced_late_bound_regions(&sig.output());
if late_bound_regions.iter().any(|r| *r == br) {
return true;
}
}
_ => {}
}
false
}
// Here we check for the case where anonymous region
// corresponds to self and if yes, we display E0312.
// FIXME(#42700) - Need to format self properly to
// enable E0621 for it.
pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
is_first &&
self.tcx
.opt_associated_item(scope_def_id)
.map(|i| i.method_has_self_argument) == Some(true)
}
// Here we check if the bound region is in Impl Item.
pub fn is_bound_region_in_impl_item(&self, anonymous_region_binding_scope: DefId) -> bool {
let container_id = self.tcx
.associated_item(anonymous_region_binding_scope)
.container
@ -106,15 +189,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// since the signature must match the trait.
//
// FIXME(#42706) -- in some cases, we could do better here.
return None;
}
}
_ => return None, // inapplicable
// we target only top-level functions
}
return Some((anonymous_region_binding_scope, free_region.bound_region));
}
}
None
return true;
}
false
}
}

View File

@ -1,25 +1,10 @@
error[E0308]: mismatched types
error[E0623]: lifetime mismatch
--> $DIR/ex2b-push-no-existing-names.rs:16:12
|
15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
| -------- -------- these two types are declared with different lifetimes...
16 | x.push(y);
| ^ lifetime mismatch
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
note: the anonymous lifetime #3 defined on the function body at 15:1...
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
| ^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-2.rs:12:9
|
11 | fn foo((v, w): (&u8, &u8), x: &u8) {
| --- --- these references are not declared with the same lifetime...
| --- --- these two types are declared with different lifetimes...
12 | v = x;
| ^ ...but data from `x` flows here

View File

@ -8,8 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
v = x;
fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
z.push((x,y));
}
fn main() { }

View File

@ -1,10 +1,18 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-3.rs:12:9
--> $DIR/ex3-both-anon-regions-3.rs:12:13
|
11 | fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
| --- --- these references are not declared with the same lifetime...
12 | v = x;
| ^ ...but data flows here
11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- --- these two types are declared with different lifetimes...
12 | z.push((x,y));
| ^ ...but data flows into `z` here
error: aborting due to previous error
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-3.rs:12:15
|
11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- --- these two types are declared with different lifetimes...
12 | z.push((x,y));
| ^ ...but data flows into `z` here
error: aborting due to 2 previous errors

View File

@ -1,20 +0,0 @@
error[E0601]: main function not found
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-4.rs:12:13
|
11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- --- these references are not declared with the same lifetime...
12 | z.push((x,y));
| ^ ...but data flows into `z` here
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-4.rs:12:15
|
11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- --- these references are not declared with the same lifetime...
12 | z.push((x,y));
| ^ ...but data flows into `z` here
error: aborting due to 3 previous errors

View File

@ -0,0 +1,19 @@
// 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.
struct Ref<'a, 'b> {
a: &'a u32,
b: &'b u32,
}
fn foo(mut x: Ref, y: Ref) {
x.b = y.b;
}
fn main() {}

View File

@ -0,0 +1,10 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
|
15 | fn foo(mut x: Ref, y: Ref) {
| --- --- these two types are declared with different lifetimes...
16 | x.b = y.b;
| ^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View File

@ -0,0 +1,19 @@
// 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.
struct Ref<'a, 'b> {
a: &'a u32,
b: &'b u32,
}
fn foo(mut x: Ref) {
x.a = x.b;
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
|
15 | fn foo(mut x: Ref) {
| ---
| |
| this type was declared with multiple lifetimes...
16 | x.a = x.b;
| ^^^ ...but data with one lifetime flows into the other here
error: aborting due to previous error

View File

@ -1,4 +1,4 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// 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.
//
@ -7,7 +7,12 @@
// <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.
fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
z.push((x,y));
struct Ref<'a> {
x: &'a u32,
}
fn foo(mut x: Vec<Ref>, y: Ref) {
x.push(y);
}
fn main() {}

View File

@ -0,0 +1,10 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
|
14 | fn foo(mut x: Vec<Ref>, y: Ref) {
| --- --- these two types are declared with different lifetimes...
15 | x.push(y);
| ^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View File

@ -0,0 +1,17 @@
// 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.
struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
fn foo(mut x: Ref, y: &u32) {
y = x.b;
}
fn main() { }

View File

@ -0,0 +1,12 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
|
13 | fn foo(mut x: Ref, y: &u32) {
| --- ----
| |
| these two types are declared with different lifetimes...
14 | y = x.b;
| ^^^ ...but data from `x` flows into `y` here
error: aborting due to previous error

View File

@ -0,0 +1,17 @@
// 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.
struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
fn foo(mut y: Ref, x: &u32) {
y.b = x;
}
fn main() { }

View File

@ -0,0 +1,10 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
|
13 | fn foo(mut y: Ref, x: &u32) {
| --- ---- these two types are declared with different lifetimes...
14 | y.b = x;
| ^ ...but data from `x` flows into `y` here
error: aborting due to previous error

View File

@ -0,0 +1,20 @@
// 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.
struct Ref<'a, 'b> {
a: &'a u32,
b: &'b u32,
}
fn foo(mut x: Ref, y: &u32) {
x.b = y;
}
fn main() {}

View File

@ -0,0 +1,10 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
|
16 | fn foo(mut x: Ref, y: &u32) {
| --- ---- these two types are declared with different lifetimes...
17 | x.b = y;
| ^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View File

@ -0,0 +1,22 @@
// 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.
struct Foo {
field: i32
}
impl Foo {
fn foo<'a>(&self, x: &i32) -> &i32 {
x
}
}
fn main() { }

View File

@ -0,0 +1,23 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
|
17 | x
| ^
|
note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
--> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
|
16 | / fn foo<'a>(&self, x: &i32) -> &i32 {
17 | | x
18 | | }
| |___^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3
--> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
|
16 | / fn foo<'a>(&self, x: &i32) -> &i32 {
17 | | x
18 | | }
| |___^
error: aborting due to previous error

View File

@ -0,0 +1,22 @@
// 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.
struct Foo {
field: i32,
}
impl Foo {
fn foo<'a>(&self, x: &Foo) -> &Foo {
if true { x } else { self }
}
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
|
17 | if true { x } else { self }
| ^
|
note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5...
--> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
|
16 | / fn foo<'a>(&self, x: &Foo) -> &Foo {
17 | | if true { x } else { self }
18 | | }
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5
--> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
|
16 | / fn foo<'a>(&self, x: &Foo) -> &Foo {
17 | | if true { x } else { self }
18 | | }
| |_____^
error: aborting due to previous error

View File

@ -0,0 +1,18 @@
// 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.
trait Foo {
fn foo<'a>(x: &mut Vec<&u8>, y: &u8);
}
impl Foo for () {
fn foo(x: &mut Vec<&u8>, y: &u8) {
x.push(y);
}
}
fn main() {}

View File

@ -0,0 +1,10 @@
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
|
14 | fn foo(x: &mut Vec<&u8>, y: &u8) {
| --- --- these two types are declared with different lifetimes...
15 | x.push(y);
| ^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View File

@ -1,4 +1,4 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// 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.
//

View File

@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions.rs:12:12
|
11 | fn foo(x: &mut Vec<&u8>, y: &u8) {
| --- --- these references are not declared with the same lifetime...
| --- --- these two types are declared with different lifetimes...
12 | x.push(y);
| ^ ...but data from `y` flows into `x` here