Skip to content

Commit 80c510e

Browse files
committed
when using feature(nll), don't warn about AST-based region errors
Also, keep reporting AST-based region errors that are not occuring in a fn body.
1 parent cfa4ffa commit 80c510e

File tree

7 files changed

+120
-13
lines changed

7 files changed

+120
-13
lines changed

src/librustc/infer/error_reporting/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
258258
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
259259
pub fn report_region_errors(&self,
260260
region_scope_tree: &region::ScopeTree,
261-
errors: &Vec<RegionResolutionError<'tcx>>) {
261+
errors: &Vec<RegionResolutionError<'tcx>>,
262+
will_later_be_reported_by_nll: bool) {
262263
debug!("report_region_errors(): {} errors to start", errors.len());
263264

264-
if self.tcx.sess.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.
265274
for error in errors {
266275
match *error {
267276
RegionResolutionError::ConcreteFailure(ref origin, ..) |

src/librustc/infer/mod.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -1159,10 +1159,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11591159
/// result. After this, no more unification operations should be
11601160
/// done -- or the compiler will panic -- but it is legal to use
11611161
/// `resolve_type_vars_if_possible` as well as `fully_resolve`.
1162-
pub fn resolve_regions_and_report_errors(&self,
1163-
region_context: DefId,
1164-
region_map: &region::ScopeTree,
1165-
outlives_env: &OutlivesEnvironment<'tcx>) {
1162+
pub fn resolve_regions_and_report_errors(
1163+
&self,
1164+
region_context: DefId,
1165+
region_map: &region::ScopeTree,
1166+
outlives_env: &OutlivesEnvironment<'tcx>,
1167+
) {
1168+
self.resolve_regions_and_report_errors_inner(
1169+
region_context,
1170+
region_map,
1171+
outlives_env,
1172+
false,
1173+
)
1174+
}
1175+
1176+
/// Like `resolve_regions_and_report_errors`, but skips error
1177+
/// reporting if NLL is enabled. This is used for fn bodies where
1178+
/// the same error may later be reported by the NLL-based
1179+
/// inference.
1180+
pub fn resolve_regions_and_report_errors_unless_nll(
1181+
&self,
1182+
region_context: DefId,
1183+
region_map: &region::ScopeTree,
1184+
outlives_env: &OutlivesEnvironment<'tcx>,
1185+
) {
1186+
self.resolve_regions_and_report_errors_inner(
1187+
region_context,
1188+
region_map,
1189+
outlives_env,
1190+
true,
1191+
)
1192+
}
1193+
1194+
fn resolve_regions_and_report_errors_inner(
1195+
&self,
1196+
region_context: DefId,
1197+
region_map: &region::ScopeTree,
1198+
outlives_env: &OutlivesEnvironment<'tcx>,
1199+
will_later_be_reported_by_nll: bool,
1200+
) {
11661201
assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
11671202
"region_obligations not empty: {:#?}",
11681203
self.region_obligations.borrow());
@@ -1187,7 +1222,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11871222
// this infcx was in use. This is totally hokey but
11881223
// otherwise we have a hard time separating legit region
11891224
// errors from silly ones.
1190-
self.report_region_errors(region_map, &errors); // see error_reporting module
1225+
self.report_region_errors(region_map, &errors, will_later_be_reported_by_nll);
11911226
}
11921227
}
11931228

src/librustc_typeck/check/regionck.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
124124
rcx.visit_body(body);
125125
rcx.visit_region_obligations(id);
126126
}
127-
rcx.resolve_regions_and_report_errors();
127+
rcx.resolve_regions_and_report_errors_unless_nll();
128128

129129
assert!(self.tables.borrow().free_region_map.is_empty());
130130
self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
@@ -173,7 +173,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
173173
rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id));
174174
}
175175

176-
rcx.resolve_regions_and_report_errors();
176+
rcx.resolve_regions_and_report_errors_unless_nll();
177177

178178
// In this mode, we also copy the free-region-map into the
179179
// tables of the enclosing fcx. In the other regionck modes
@@ -371,6 +371,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
371371
&self.outlives_environment);
372372
}
373373

374+
fn resolve_regions_and_report_errors_unless_nll(&self) {
375+
self.fcx.resolve_regions_and_report_errors_unless_nll(self.subject_def_id,
376+
&self.region_scope_tree,
377+
&self.outlives_environment);
378+
}
379+
374380
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
375381
debug!("regionck::visit_pat(pat={:?})", pat);
376382
pat.each_binding(|_, id, span, _| {

src/test/compile-fail/regions-struct-not-wf.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@
1010

1111
// Various examples of structs whose fields are not well-formed.
1212

13+
// revisions:lexical nll
14+
1315
#![allow(dead_code)]
16+
#![cfg_attr(nll, feature(nll))]
1417

1518
struct Ref<'a, T> {
1619
field: &'a T
17-
//~^ ERROR the parameter type `T` may not live long enough
20+
//[lexical]~^ ERROR the parameter type `T` may not live long enough
21+
//[nll]~^^ ERROR the parameter type `T` may not live long enough
1822
}
1923

2024
struct RefOk<'a, T:'a> {
@@ -23,12 +27,14 @@ struct RefOk<'a, T:'a> {
2327

2428
struct RefIndirect<'a, T> {
2529
field: RefOk<'a, T>
26-
//~^ ERROR the parameter type `T` may not live long enough
30+
//[lexical]~^ ERROR the parameter type `T` may not live long enough
31+
//[nll]~^^ ERROR the parameter type `T` may not live long enough
2732
}
2833

2934
struct DoubleRef<'a, 'b, T> {
3035
field: &'a &'b T
31-
//~^ ERROR reference has a longer lifetime than the data it references
36+
//[lexical]~^ ERROR reference has a longer lifetime than the data it references
37+
//[nll]~^^ ERROR reference has a longer lifetime than the data it references
3238
}
3339

3440
fn main() { }

src/test/ui/nll/capture-ref-in-struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags:-Zborrowck=mir -Znll-dump-cause
11+
// compile-flags:-Znll-dump-cause
1212

1313
// Test that a structure which tries to store a pointer to `y` into
1414
// `p` (indirectly) fails to compile.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2016 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+
// Test that we assume that universal types like `T` outlive the
12+
// function body. Same as ty-param-fn-body, but uses `feature(nll)`,
13+
// which affects error reporting.
14+
15+
#![feature(nll)]
16+
17+
#![allow(warnings)]
18+
#![feature(dyn_trait)]
19+
20+
use std::cell::Cell;
21+
22+
// No errors here, because `'a` is local to the body.
23+
fn region_within_body<T>(t: T) {
24+
let some_int = 22;
25+
let cell = Cell::new(&some_int);
26+
outlives(cell, t)
27+
}
28+
29+
// Error here, because T: 'a is not satisfied.
30+
fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
31+
outlives(cell, t)
32+
//~^ ERROR the parameter type `T` may not live long enough
33+
}
34+
35+
fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
36+
where
37+
T: 'a,
38+
{
39+
}
40+
41+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0309]: the parameter type `T` may not live long enough
2+
--> $DIR/ty-param-fn-body-nll-feature.rs:31:5
3+
|
4+
31 | outlives(cell, t)
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= help: consider adding an explicit lifetime bound `T: 'a`...
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)