Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve SubSupConflict with a named and an anonymous lifetime parameter #42701 #44167

Merged
merged 7 commits into from
Nov 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will have to remove the is_self_anon check. Maybe you can try an example without self, that should work.

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>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would appreciate a comment here like this:

// 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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, actually, not here, but down below =)

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