Skip to content

Commit fdfb007

Browse files
committed
Auto merge of #46862 - nikomatsakis:nll-master, r=arielb1
NLL feature complete (adds `feature(nll)`)! This is the final PR for the nll-master branch; it brings over all remaining content. The contents of the branch include: - track causal information and use it to report extended errors - handle `impl Trait` in NLL code - improve printing of outlives errors - add `#![feature(nll)]` and some more sample tests The commits should for the most part build independently. r? @pnkfelix (and/or @arielb1)
2 parents 7eb64b8 + d925f4d commit fdfb007

File tree

139 files changed

+4132
-1844
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+4132
-1844
lines changed

Diff for: src/librustc/infer/anon_types/mod.rs

+626
Large diffs are not rendered by default.

Diff for: src/librustc/infer/error_reporting/different_lifetimes.rs

-415
This file was deleted.

Diff for: src/librustc/infer/error_reporting/mod.rs

+35-22
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,7 @@ mod note;
7878

7979
mod need_type_info;
8080

81-
mod named_anon_conflict;
82-
#[macro_use]
83-
mod util;
84-
mod different_lifetimes;
81+
pub mod nice_region_error;
8582

8683
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
8784
pub fn note_and_explain_region(self,
@@ -261,10 +258,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
261258
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
262259
pub fn report_region_errors(&self,
263260
region_scope_tree: &region::ScopeTree,
264-
errors: &Vec<RegionResolutionError<'tcx>>) {
261+
errors: &Vec<RegionResolutionError<'tcx>>,
262+
will_later_be_reported_by_nll: bool) {
265263
debug!("report_region_errors(): {} errors to start", errors.len());
266264

267-
if self.tcx.sess.opts.debugging_opts.nll {
265+
if will_later_be_reported_by_nll && self.tcx.sess.nll() {
266+
// With `#![feature(nll)]`, we want to present a nice user
267+
// experience, so don't even mention the errors from the
268+
// AST checker.
269+
if self.tcx.sess.features.borrow().nll {
270+
return;
271+
}
272+
273+
// But with -Znll, it's nice to have some note for later.
268274
for error in errors {
269275
match *error {
270276
RegionResolutionError::ConcreteFailure(ref origin, ..) |
@@ -294,9 +300,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
294300
for error in errors {
295301
debug!("report_region_errors: error = {:?}", error);
296302

297-
if !self.try_report_named_anon_conflict(&error) &&
298-
!self.try_report_anon_anon_conflict(&error)
299-
{
303+
if !self.try_report_nice_region_error(&error) {
300304
match error.clone() {
301305
// These errors could indicate all manner of different
302306
// problems with many different solutions. Rather
@@ -309,8 +313,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
309313
self.report_concrete_failure(region_scope_tree, origin, sub, sup).emit();
310314
}
311315

312-
RegionResolutionError::GenericBoundFailure(kind, param_ty, sub) => {
313-
self.report_generic_bound_failure(region_scope_tree, kind, param_ty, sub);
316+
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
317+
self.report_generic_bound_failure(
318+
region_scope_tree,
319+
origin.span(),
320+
Some(origin),
321+
param_ty,
322+
sub,
323+
);
314324
}
315325

316326
RegionResolutionError::SubSupConflict(var_origin,
@@ -906,11 +916,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
906916
DiagnosticStyledString::highlighted(format!("{}", exp_found.found))))
907917
}
908918

909-
fn report_generic_bound_failure(&self,
910-
region_scope_tree: &region::ScopeTree,
911-
origin: SubregionOrigin<'tcx>,
912-
bound_kind: GenericKind<'tcx>,
913-
sub: Region<'tcx>)
919+
pub fn report_generic_bound_failure(&self,
920+
region_scope_tree: &region::ScopeTree,
921+
span: Span,
922+
origin: Option<SubregionOrigin<'tcx>>,
923+
bound_kind: GenericKind<'tcx>,
924+
sub: Region<'tcx>)
914925
{
915926
// Attempt to obtain the span of the parameter so we can
916927
// suggest adding an explicit lifetime bound to it.
@@ -958,9 +969,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
958969
format!("the associated type `{}`", p),
959970
};
960971

961-
if let SubregionOrigin::CompareImplMethodObligation {
972+
if let Some(SubregionOrigin::CompareImplMethodObligation {
962973
span, item_name, impl_item_def_id, trait_item_def_id,
963-
} = origin {
974+
}) = origin {
964975
self.report_extra_impl_obligation(span,
965976
item_name,
966977
impl_item_def_id,
@@ -995,7 +1006,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
9951006
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
9961007
// Does the required lifetime have a nice name we can print?
9971008
let mut err = struct_span_err!(self.tcx.sess,
998-
origin.span(),
1009+
span,
9991010
E0309,
10001011
"{} may not live long enough",
10011012
labeled_user_string);
@@ -1006,7 +1017,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10061017
ty::ReStatic => {
10071018
// Does the required lifetime have a nice name we can print?
10081019
let mut err = struct_span_err!(self.tcx.sess,
1009-
origin.span(),
1020+
span,
10101021
E0310,
10111022
"{} may not live long enough",
10121023
labeled_user_string);
@@ -1017,7 +1028,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10171028
_ => {
10181029
// If not, be less specific.
10191030
let mut err = struct_span_err!(self.tcx.sess,
1020-
origin.span(),
1031+
span,
10211032
E0311,
10221033
"{} may not live long enough",
10231034
labeled_user_string);
@@ -1033,7 +1044,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10331044
}
10341045
};
10351046

1036-
self.note_region_origin(&mut err, &origin);
1047+
if let Some(origin) = origin {
1048+
self.note_region_origin(&mut err, &origin);
1049+
}
10371050
err.emit();
10381051
}
10391052

Diff for: src/librustc/infer/error_reporting/named_anon_conflict.rs

-101
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Error Reporting for Anonymous Region Lifetime Errors
12+
//! where both the regions are anonymous.
13+
14+
use infer::error_reporting::nice_region_error::NiceRegionError;
15+
use infer::error_reporting::nice_region_error::util::AnonymousArgInfo;
16+
use util::common::ErrorReported;
17+
18+
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
19+
/// Print the error message for lifetime errors when both the concerned regions are anonymous.
20+
///
21+
/// Consider a case where we have
22+
///
23+
/// ```no_run
24+
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
25+
/// x.push(y);
26+
/// }
27+
/// ```
28+
///
29+
/// The example gives
30+
///
31+
/// ```text
32+
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
33+
/// --- --- these references are declared with different lifetimes...
34+
/// x.push(y);
35+
/// ^ ...but data from `y` flows into `x` here
36+
/// ```
37+
///
38+
/// It has been extended for the case of structs too.
39+
///
40+
/// Consider the example
41+
///
42+
/// ```no_run
43+
/// struct Ref<'a> { x: &'a u32 }
44+
/// ```
45+
///
46+
/// ```text
47+
/// fn foo(mut x: Vec<Ref>, y: Ref) {
48+
/// --- --- these structs are declared with different lifetimes...
49+
/// x.push(y);
50+
/// ^ ...but data from `y` flows into `x` here
51+
/// }
52+
/// ````
53+
///
54+
/// It will later be extended to trait objects.
55+
pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
56+
let NiceRegionError { span, sub, sup, .. } = *self;
57+
58+
// Determine whether the sub and sup consist of both anonymous (elided) regions.
59+
let anon_reg_sup = self.is_suitable_region(sup)?;
60+
61+
let anon_reg_sub = self.is_suitable_region(sub)?;
62+
let scope_def_id_sup = anon_reg_sup.def_id;
63+
let bregion_sup = anon_reg_sup.boundregion;
64+
let scope_def_id_sub = anon_reg_sub.def_id;
65+
let bregion_sub = anon_reg_sub.boundregion;
66+
67+
let ty_sup = self.find_anon_type(sup, &bregion_sup)?;
68+
69+
let ty_sub = self.find_anon_type(sub, &bregion_sub)?;
70+
71+
debug!(
72+
"try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}",
73+
ty_sub,
74+
sup,
75+
bregion_sup
76+
);
77+
debug!(
78+
"try_report_anon_anon_conflict: found_arg2={:?} sub={:?} br2={:?}",
79+
ty_sup,
80+
sub,
81+
bregion_sub
82+
);
83+
84+
let (ty_sup, ty_fndecl_sup) = ty_sup;
85+
let (ty_sub, ty_fndecl_sub) = ty_sub;
86+
87+
let AnonymousArgInfo {
88+
arg: anon_arg_sup, ..
89+
} = self.find_arg_with_region(sup, sup)?;
90+
let AnonymousArgInfo {
91+
arg: anon_arg_sub, ..
92+
} = self.find_arg_with_region(sub, sub)?;
93+
94+
let sup_is_ret_type =
95+
self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
96+
let sub_is_ret_type =
97+
self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
98+
99+
let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
100+
format!(" from `{}`", simple_name)
101+
} else {
102+
format!("")
103+
};
104+
105+
let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
106+
format!(" into `{}`", simple_name)
107+
} else {
108+
format!("")
109+
};
110+
111+
112+
let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
113+
(None, None) => {
114+
let (main_label_1, span_label_1) = if ty_sup == ty_sub {
115+
(
116+
format!("this type is declared with multiple lifetimes..."),
117+
format!(
118+
"...but data{} flows{} here",
119+
format!(" with one lifetime"),
120+
format!(" into the other")
121+
),
122+
)
123+
} else {
124+
(
125+
format!("these two types are declared with different lifetimes..."),
126+
format!(
127+
"...but data{} flows{} here",
128+
span_label_var1,
129+
span_label_var2
130+
),
131+
)
132+
};
133+
(ty_sup.span, ty_sub.span, main_label_1, span_label_1)
134+
}
135+
136+
(Some(ret_span), _) => (
137+
ty_sub.span,
138+
ret_span,
139+
format!(
140+
"this parameter and the return type are declared \
141+
with different lifetimes...",
142+
),
143+
format!("...but data{} is returned here", span_label_var1),
144+
),
145+
(_, Some(ret_span)) => (
146+
ty_sup.span,
147+
ret_span,
148+
format!(
149+
"this parameter and the return type are declared \
150+
with different lifetimes...",
151+
),
152+
format!("...but data{} is returned here", span_label_var1),
153+
),
154+
};
155+
156+
157+
struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
158+
.span_label(span_1, main_label)
159+
.span_label(span_2, format!(""))
160+
.span_label(span, span_label)
161+
.emit();
162+
return Some(ErrorReported);
163+
}
164+
}

0 commit comments

Comments
 (0)