diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 21139c8dde2a4..9fa2bc8a2a7a9 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -426,30 +426,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { debug!("note_issue_32330: terr={:?}", terr); match *terr { - TypeError::RegionsInsufficientlyPolymorphic(_, &Region::ReVar(vid)) | - TypeError::RegionsOverlyPolymorphic(_, &Region::ReVar(vid)) => { - match self.region_vars.var_origin(vid) { - RegionVariableOrigin::EarlyBoundRegion(_, _, Some(Issue32330 { - fn_def_id, - region_name - })) => { - diag.note( - &format!("lifetime parameter `{0}` declared on fn `{1}` \ - appears only in the return type, \ - but here is required to be higher-ranked, \ - which means that `{0}` must appear in both \ - argument and return types", - region_name, - self.tcx.item_path_str(fn_def_id))); - diag.note( - &format!("this error is the result of a recent bug fix; \ - for more information, see issue #33685 \ - ")); - } - _ => { } - } + TypeError::RegionsInsufficientlyPolymorphic(_, _, Some(box Issue32330 { + fn_def_id, region_name + })) | + TypeError::RegionsOverlyPolymorphic(_, _, Some(box Issue32330 { + fn_def_id, region_name + })) => { + diag.note( + &format!("lifetime parameter `{0}` declared on fn `{1}` \ + appears only in the return type, \ + but here is required to be higher-ranked, \ + which means that `{0}` must appear in both \ + argument and return types", + region_name, + self.tcx.item_path_str(fn_def_id))); + diag.note( + &format!("this error is the result of a recent bug fix; \ + for more information, see issue #33685 \ + ")); } - _ => { } + _ => {} } } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index e919f025409c5..e3ffc99c0e967 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -15,6 +15,7 @@ use super::{CombinedSnapshot, InferCtxt, LateBoundRegion, HigherRankedType, + RegionVariableOrigin, SubregionOrigin, SkolemizationMap}; use super::combine::CombineFields; @@ -656,14 +657,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { skol_br, tainted_region); + let issue_32330 = if let &ty::ReVar(vid) = tainted_region { + match self.region_vars.var_origin(vid) { + RegionVariableOrigin::EarlyBoundRegion(_, _, issue_32330) => { + issue_32330.map(Box::new) + } + _ => None + } + } else { + None + }; + if overly_polymorphic { debug!("Overly polymorphic!"); return Err(TypeError::RegionsOverlyPolymorphic(skol_br, - tainted_region)); + tainted_region, + issue_32330)); } else { debug!("Not as polymorphic!"); return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br, - tainted_region)); + tainted_region, + issue_32330)); } } } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 5a696446b4bb6..73d9c8b00ae47 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -39,8 +39,8 @@ pub enum TypeError<'tcx> { RegionsDoesNotOutlive(&'tcx Region, &'tcx Region), RegionsNotSame(&'tcx Region, &'tcx Region), RegionsNoOverlap(&'tcx Region, &'tcx Region), - RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region), - RegionsOverlyPolymorphic(BoundRegion, &'tcx Region), + RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region, Option>), + RegionsOverlyPolymorphic(BoundRegion, &'tcx Region, Option>), Sorts(ExpectedFound>), IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), @@ -116,11 +116,11 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsNoOverlap(..) => { write!(f, "lifetimes do not intersect") } - RegionsInsufficientlyPolymorphic(br, _) => { + RegionsInsufficientlyPolymorphic(br, _, _) => { write!(f, "expected bound lifetime parameter {}, \ found concrete lifetime", br) } - RegionsOverlyPolymorphic(br, _) => { + RegionsOverlyPolymorphic(br, _, _) => { write!(f, "expected concrete lifetime, \ found bound lifetime parameter {}", br) } @@ -253,15 +253,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.note_and_explain_region(db, "...does not overlap ", region2, ""); } - RegionsInsufficientlyPolymorphic(_, conc_region) => { + RegionsInsufficientlyPolymorphic(_, conc_region, _) => { self.note_and_explain_region(db, "concrete lifetime that was found is ", conc_region, ""); } - RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => { + RegionsOverlyPolymorphic(_, &ty::ReVar(_), _) => { // don't bother to print out the message below for // inference variables, it's not very illuminating. } - RegionsOverlyPolymorphic(_, conc_region) => { + RegionsOverlyPolymorphic(_, conc_region, _) => { self.note_and_explain_region(db, "expected concrete lifetime is ", conc_region, ""); } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 49824e8a738d7..9126600e3f653 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -293,11 +293,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsNoOverlap(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsNoOverlap(a, b)) } - RegionsInsufficientlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) + RegionsInsufficientlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b, c)) } - RegionsOverlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b)) + RegionsOverlyPolymorphic(a, b, ref c) => { + let c = c.clone(); + return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b, c)) } IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), diff --git a/src/test/compile-fail/issue-40000.rs b/src/test/compile-fail/issue-40000.rs new file mode 100644 index 0000000000000..9be114ebcb6e0 --- /dev/null +++ b/src/test/compile-fail/issue-40000.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(closure_to_fn_coercion)] + +fn main() { + let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types + //~| expected concrete lifetime, found bound lifetime parameter + + fn foo(x: Box) {} + let bar = Box::new(|x: &i32| {}) as Box; + foo(bar); //~ ERROR mismatched types + //~| expected concrete lifetime, found bound lifetime parameter +}