Skip to content

Commit

Permalink
Auto merge of #44167 - cengizIO:master, r=nikomatsakis
Browse files Browse the repository at this point in the history
Improve SubSupConflict with a named and an anonymous lifetime parameter #42701

Hello!

This fixes #42701.

## UPDATE 01
Tests are producing different results between different env builds.
This inconsistency might take a long time to investigate and fix. So, be patient

## UPDATE 02
Changed an `FxHashMap` with a `BTreeMap`. Inconsistency seems to be resolved for now.
  • Loading branch information
bors committed Nov 12, 2017
2 parents fb5ba4e + f53fc57 commit 79cfce3
Show file tree
Hide file tree
Showing 32 changed files with 99 additions and 131 deletions.
1 change: 1 addition & 0 deletions src/librustc/infer/error_reporting/different_lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
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),
SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
_ => return false, // inapplicable
};

Expand Down
1 change: 1 addition & 0 deletions src/librustc/infer/error_reporting/named_anon_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
let (span, sub, sup) = match *error {
ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
_ => return false, // inapplicable
};

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/infer/region_inference/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use util::nodemap::{FxHashMap, FxHashSet};

use std::borrow::Cow;
use std::collections::hash_map::Entry::Vacant;
use std::collections::btree_map::BTreeMap;
use std::env;
use std::fs::File;
use std::io;
Expand Down Expand Up @@ -124,7 +125,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
graph_name: String,
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
map: &'a BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
node_ids: FxHashMap<Node, usize>,
}

Expand Down Expand Up @@ -264,7 +265,7 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
}
}

pub type ConstraintMap<'tcx> = FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
pub type ConstraintMap<'tcx> = BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;

fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
map: &ConstraintMap<'tcx>,
Expand Down
13 changes: 10 additions & 3 deletions src/librustc/infer/region_inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use ty::{Region, RegionVid};
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};

use std::collections::BTreeMap;
use std::cell::{Cell, RefCell};
use std::fmt;
use std::mem;
Expand All @@ -36,7 +37,7 @@ use std::u32;
mod graphviz;

/// A constraint that influences the inference process.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub enum Constraint<'tcx> {
/// One region variable is subregion of another
ConstrainVarSubVar(RegionVid, RegionVid),
Expand Down Expand Up @@ -186,7 +187,13 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
/// Constraints of the form `A <= B` introduced by the region
/// checker. Here at least one of `A` and `B` must be a region
/// variable.
constraints: RefCell<FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
///
/// Using `BTreeMap` because the order in which we iterate over
/// these constraints can affect the way we build the region graph,
/// which in turn affects the way that region errors are reported,
/// leading to small variations in error output across runs and
/// platforms.
constraints: RefCell<BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,

/// A "verify" is something that we need to verify after inference is
/// done, but which does not directly affect inference in any way.
Expand Down Expand Up @@ -357,7 +364,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
tcx,
var_origins: RefCell::new(Vec::new()),
values: RefCell::new(None),
constraints: RefCell::new(FxHashMap()),
constraints: RefCell::new(BTreeMap::new()),
verifys: RefCell::new(Vec::new()),
givens: RefCell::new(FxHashSet()),
lubs: RefCell::new(FxHashMap()),
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
/// is the outer fn.
///
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy, PartialOrd, Ord)]
pub struct DebruijnIndex {
/// We maintain the invariant that this is never 0. So 1 indicates
/// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
Expand Down Expand Up @@ -825,7 +825,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
///
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub enum RegionKind {
// Region bound in a type or fn declaration which will be
// substituted 'early' -- that is, at the same time when type
Expand Down Expand Up @@ -871,7 +871,7 @@ pub enum RegionKind {

impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}

#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)]
pub struct EarlyBoundRegion {
pub def_id: DefId,
pub index: u32,
Expand All @@ -893,12 +893,12 @@ pub struct FloatVid {
pub index: u32,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, PartialOrd, Ord)]
pub struct RegionVid {
pub index: u32,
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub struct SkolemizedRegionVid {
pub index: u32,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
{
// x and y here have two distinct lifetimes:
let z: I::A = if cond { x } else { y };
//~^ ERROR cannot infer
//~^ ERROR lifetime mismatch
}

pub fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ fn baz<'a,'b>(x: &'a u32) -> &'static u32 {

#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
let a = bar(foo, y); //[krisskross]~ ERROR E0495
let b = bar(foo, x); //[krisskross]~ ERROR E0495
(a, b)
let a = bar(foo, y);
let b = bar(foo, x);
(a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623]
//[krisskross]~^ ERROR 55:8: 55:9: lifetime mismatch [E0623]
}

#[rustc_error]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
#[cfg(oneuse)] // one instantiation: BAD
fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
let f = foo; // <-- No consistent type can be inferred for `f` here.
let a = bar(f, x); //[oneuse]~^ ERROR E0495
let b = bar(f, y);
let a = bar(f, x);
let b = bar(f, y); //[oneuse]~ ERROR 49:19: 49:20: lifetime mismatch [E0623]
(a, b)
}

Expand All @@ -60,9 +60,9 @@ fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {

#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
let a = bar(foo, y); //[krisskross]~ ERROR E0495
let b = bar(foo, x); //[krisskross]~ ERROR E0495
(a, b)
let a = bar(foo, y); //[krisskross]~ ERROR E0623
let b = bar(foo, x);
(a, b) //[krisskross]~ ERROR E0623
}

#[rustc_error]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct S<'a> {

fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
S { pointer: &mut *p.pointer }
//~^ ERROR cannot infer
//~^ ERROR lifetime mismatch
}

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-13058.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'r> Itble<'r, usize, Range<usize>> for (usize, usize) {
fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
{
let cont_iter = cont.iter();
//~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
//~^ ERROR 24:26: 24:30: explicit lifetime required in the type of `cont` [E0621]
let result = cont_iter.fold(Some(0), |state, val| {
state.map_or(None, |mask| {
let bit = 1 << val;
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-14285.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Foo for A {}
struct B<'a>(&'a (Foo+'a));

fn foo<'a>(a: &Foo) -> B<'a> {
B(a) //~ ERROR cannot infer an appropriate lifetime
B(a) //~ ERROR 22:5: 22:9: explicit lifetime required in the type of `a` [E0621]
}

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-15034.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct Parser<'a> {
impl<'a> Parser<'a> {
pub fn new(lexer: &'a mut Lexer) -> Parser<'a> {
Parser { lexer: lexer }
//~^ ERROR cannot infer an appropriate lifetime
//~^ ERROR 27:25: 27:30: explicit lifetime required in the type of `lexer` [E0621]
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-17728.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ trait TraversesWorld {
fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
let direction = str_to_direction(directionStr);
let maybe_room = room.direction_to_room.get(&direction);
//~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
match maybe_room {
Some(entry) => Ok(entry),
//~^ ERROR 25:28: 25:37: lifetime mismatch [E0623]
_ => Err("Direction does not exist in room.")
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-3154.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct thing<'a, Q:'a> {
}

fn thing<'a,Q>(x: &Q) -> thing<'a,Q> {
thing{ x: x } //~ ERROR cannot infer
thing{ x: x } //~ ERROR 16:5: 16:18: explicit lifetime required in the type of `x` [E0621]
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-40288-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ fn prove_static<T: 'static + ?Sized>(_: &'static T) {}

fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
let mut out = [x];
//~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
{
let slice: &mut [_] = &mut out;
slice[0] = y;
}
out[0]
//~^ ERROR 19:5: 19:11: explicit lifetime required in the type of `y` [E0621]
}

struct Struct<T, U: ?Sized> {
Expand All @@ -27,12 +27,12 @@ struct Struct<T, U: ?Sized> {

fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
let mut out = Struct { head: x, _tail: [()] };
//~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
{
let dst: &mut Struct<_, [()]> = &mut out;
dst.head = y;
}
out.head
//~^ ERROR 34:5: 34:13: explicit lifetime required in the type of `y` [E0621]
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.

ss.r = b; //~ ERROR cannot infer an appropriate lifetime
ss.r = b; //~ ERROR 41:12: 41:13: explicit lifetime required in the type of `ss` [E0621]
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
// Here we try to call `foo` but do not know that `'a` and `'b` are
// related as required.
a(x, y); //~ ERROR cannot infer
a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
}

fn d() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
// Here we try to call `foo` but do not know that `'a` and `'b` are
// related as required.
a(x, y, z); //~ ERROR cannot infer
a(x, y, z); //~ ERROR 26:7: 26:8: lifetime mismatch [E0623]
}

fn d() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {

fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
// Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
a.bigger_region(b) //~ ERROR cannot infer
a.bigger_region(b) //~ ERROR 30:7: 30:20: lifetime mismatch [E0623]
}

fn main() { }
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {

fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
// Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
f.method(b); //~ ERROR cannot infer
f.method(b); //~ ERROR 30:7: 30:13: lifetime mismatch [E0623]
}

fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/regions-creating-enums3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ enum ast<'a> {
}

fn mk_add_bad1<'a,'b>(x: &'a ast<'a>, y: &'b ast<'b>) -> ast<'a> {
ast::add(x, y) //~ ERROR cannot infer
ast::add(x, y) //~ ERROR 17:5: 17:19: lifetime mismatch [E0623]
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/regions-free-region-ordering-callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ fn ordering1<'a, 'b>(x: &'a &'b usize) -> &'a usize {

fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
// However, it is not safe to assume that 'b <= 'a
&*y //~ ERROR cannot infer
&*y //~ ERROR 23:5: 23:8: lifetime mismatch [E0623]
}

fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
// Do not infer an ordering from the return value.
let z: &'b usize = &*x;
//~^ ERROR cannot infer
//~^ ERROR 28:24: 28:27: lifetime mismatch [E0623]
panic!();
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/regions-glb-free-free.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod argparse {

impl<'a> Flag<'a> {
pub fn set_desc(self, s: &str) -> Flag<'a> {
Flag { //~ ERROR cannot infer
Flag { //~ ERROR 25:13: 30:14: explicit lifetime required in the type of `s` [E0621]
name: self.name,
desc: s,
max_count: self.max_count,
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/regions-lifetime-bounds-on-fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
// Here we try to call `foo` but do not know that `'a` and `'b` are
// related as required.
a(x, y); //~ ERROR E0495
a(x, y); //~ ERROR 24:7: 24:8: lifetime mismatch [E0623]
}

fn d() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// Issue #8624. Test for reborrowing with 3 levels, not just two.

fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize {
&mut ***p //~ ERROR cannot infer
&mut ***p //~ ERROR 14:5: 14:14: lifetime mismatch [E0623]
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// for `'a` (which must be a sublifetime of `'b`).

fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
&mut **p //~ ERROR cannot infer
&mut **p //~ ERROR 16:5: 16:13: lifetime mismatch [E0623]
}

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/variance-trait-matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn get<'a, G>(get: &G) -> i32
// This fails to type-check because, without variance, we can't
// use `G : Get<&'a i32>` as evidence that `G : Get<&'b i32>`,
// even if `'a : 'b`.
pick(get, &22) //~ ERROR cannot infer
pick(get, &22) //~ ERROR 34:5: 34:9: explicit lifetime required in the type of `get` [E0621]
}

fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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,
}

fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
if true {
let p: &i32 = &a.field;
&*p
} else {
&*x
}
}

fn main() { }
Loading

0 comments on commit 79cfce3

Please sign in to comment.