track anonymous regions in return types, fix tidy errors
This commit is contained in:
parent
8fb6f74e57
commit
2d99ffd11b
@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
for error in errors {
|
||||
|
||||
debug!("report_region_errors: error = {:?}", error);
|
||||
|
||||
|
||||
if !self.try_report_named_anon_conflict(&error){
|
||||
|
||||
match error.clone() {
|
||||
|
@ -15,6 +15,7 @@ use ty::{self, Region};
|
||||
use infer::region_inference::RegionResolutionError::*;
|
||||
use infer::region_inference::RegionResolutionError;
|
||||
use hir::map as hir_map;
|
||||
use hir::def_id::DefId;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// This method walks the Type of the function body arguments using
|
||||
@ -24,13 +25,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// Currently only the case where the function declaration consists of
|
||||
// one named region and one anonymous region is handled.
|
||||
// Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
|
||||
// Here, we would return the hir::Arg for y, and we return the type &'a
|
||||
// Here, we would return the hir::Arg for y, we return the type &'a
|
||||
// i32, which is the type of y but with the anonymous region replaced
|
||||
// with 'a.
|
||||
// with 'a and also the corresponding bound region.
|
||||
fn find_arg_with_anonymous_region(&self,
|
||||
anon_region: Region<'tcx>,
|
||||
named_region: Region<'tcx>)
|
||||
-> Option<(&hir::Arg, ty::Ty<'tcx>)> {
|
||||
-> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion)> {
|
||||
|
||||
match *anon_region {
|
||||
ty::ReFree(ref free_region) => {
|
||||
@ -55,7 +56,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
r
|
||||
});
|
||||
if found_anon_region {
|
||||
return Some((arg, new_arg_ty));
|
||||
return Some((arg, new_arg_ty, free_region.bound_region));
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -85,15 +86,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// 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)) =
|
||||
if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup) {
|
||||
(sub, self.find_arg_with_anonymous_region(sup, sub).unwrap())
|
||||
} else if self.is_named_region(sup) && self.is_suitable_anonymous_region(sub) {
|
||||
(sup, self.find_arg_with_anonymous_region(sub, sup).unwrap())
|
||||
let (named, (arg, new_ty, br), scope_def_id) =
|
||||
if self.is_named_region(sub) && self.is_suitable_anonymous_region(sup).is_some() {
|
||||
(sub,
|
||||
self.find_arg_with_anonymous_region(sup, sub).unwrap(),
|
||||
self.is_suitable_anonymous_region(sup).unwrap())
|
||||
} else if self.is_named_region(sup) &&
|
||||
self.is_suitable_anonymous_region(sub).is_some() {
|
||||
(sup,
|
||||
self.find_arg_with_anonymous_region(sub, sup).unwrap(),
|
||||
self.is_suitable_anonymous_region(sub).unwrap())
|
||||
} else {
|
||||
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(_, _, sig) => {
|
||||
let late_bound_regions = self.tcx
|
||||
.collect_referenced_late_bound_regions(&sig.output());
|
||||
if late_bound_regions.iter().any(|r| *r == br) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(simple_name) = arg.pat.simple_name() {
|
||||
struct_span_err!(self.tcx.sess,
|
||||
span,
|
||||
@ -122,7 +144,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// This method returns whether the given Region is Anonymous
|
||||
pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> bool {
|
||||
// and returns the DefId corresponding to the region.
|
||||
pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<DefId> {
|
||||
|
||||
match *region {
|
||||
ty::ReFree(ref free_region) => {
|
||||
@ -147,20 +170,20 @@ associated_item(anonymous_region_binding_scope).container.id()).is_some() {
|
||||
// since the signature must match the trait.
|
||||
//
|
||||
// FIXME(#42706) -- in some cases, we could do better here.
|
||||
return false;//None;
|
||||
return None;
|
||||
}
|
||||
else{ }
|
||||
|
||||
}
|
||||
_ => return false, // inapplicable
|
||||
_ => return None, // inapplicable
|
||||
// we target only top-level functions
|
||||
}
|
||||
return true;
|
||||
return Some(anonymous_region_binding_scope);
|
||||
}
|
||||
_ => false,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ struct Foo {
|
||||
|
||||
impl Foo {
|
||||
fn foo<'a>(&'a self, x: &i32) -> &i32 {
|
||||
|
||||
|
||||
if true { &self.field } else { x }
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Copyright 2016 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: &'a i32) -> &i32 {
|
||||
|
||||
x
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,27 @@
|
||||
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
|
||||
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
|
||||
|
|
||||
18 | x
|
||||
| ^
|
||||
|
|
||||
note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
|
||||
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
|
||||
|
|
||||
16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 {
|
||||
17 | |
|
||||
18 | | x
|
||||
19 | |
|
||||
20 | | }
|
||||
| |___^
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3
|
||||
--> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
|
||||
|
|
||||
16 | / fn foo<'a>(&self, x: &'a i32) -> &i32 {
|
||||
17 | |
|
||||
18 | | x
|
||||
19 | |
|
||||
20 | | }
|
||||
| |___^
|
||||
|
||||
error: aborting due to previous error(s)
|
||||
|
Loading…
Reference in New Issue
Block a user