diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 38bbddfd825a..cae7bf5c25c8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -258,10 +258,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_region_errors(&self, region_scope_tree: ®ion::ScopeTree, - errors: &Vec>) { + errors: &Vec>, + will_later_be_reported_by_nll: bool) { debug!("report_region_errors(): {} errors to start", errors.len()); - if self.tcx.sess.nll() { + if will_later_be_reported_by_nll && self.tcx.sess.nll() { + // With `#![feature(nll)]`, we want to present a nice user + // experience, so don't even mention the errors from the + // AST checker. + if self.tcx.sess.features.borrow().nll { + return; + } + + // But with -Znll, it's nice to have some note for later. for error in errors { match *error { RegionResolutionError::ConcreteFailure(ref origin, ..) | diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 32da08bf476c..07c5b319970f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1159,10 +1159,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_type_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions_and_report_errors(&self, - region_context: DefId, - region_map: ®ion::ScopeTree, - outlives_env: &OutlivesEnvironment<'tcx>) { + pub fn resolve_regions_and_report_errors( + &self, + region_context: DefId, + region_map: ®ion::ScopeTree, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.resolve_regions_and_report_errors_inner( + region_context, + region_map, + outlives_env, + false, + ) + } + + /// Like `resolve_regions_and_report_errors`, but skips error + /// reporting if NLL is enabled. This is used for fn bodies where + /// the same error may later be reported by the NLL-based + /// inference. + pub fn resolve_regions_and_report_errors_unless_nll( + &self, + region_context: DefId, + region_map: ®ion::ScopeTree, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.resolve_regions_and_report_errors_inner( + region_context, + region_map, + outlives_env, + true, + ) + } + + fn resolve_regions_and_report_errors_inner( + &self, + region_context: DefId, + region_map: ®ion::ScopeTree, + outlives_env: &OutlivesEnvironment<'tcx>, + will_later_be_reported_by_nll: bool, + ) { assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(), "region_obligations not empty: {:#?}", self.region_obligations.borrow()); @@ -1187,7 +1222,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(region_map, &errors); // see error_reporting module + self.report_region_errors(region_map, &errors, will_later_be_reported_by_nll); } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 97352783db85..64063ec5beda 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rcx.visit_body(body); rcx.visit_region_obligations(id); } - rcx.resolve_regions_and_report_errors(); + rcx.resolve_regions_and_report_errors_unless_nll(); assert!(self.tables.borrow().free_region_map.is_empty()); 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> { rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id)); } - rcx.resolve_regions_and_report_errors(); + rcx.resolve_regions_and_report_errors_unless_nll(); // In this mode, we also copy the free-region-map into the // tables of the enclosing fcx. In the other regionck modes @@ -371,6 +371,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { &self.outlives_environment); } + fn resolve_regions_and_report_errors_unless_nll(&self) { + self.fcx.resolve_regions_and_report_errors_unless_nll(self.subject_def_id, + &self.region_scope_tree, + &self.outlives_environment); + } + fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) { debug!("regionck::visit_pat(pat={:?})", pat); pat.each_binding(|_, id, span, _| { diff --git a/src/test/compile-fail/regions-struct-not-wf.rs b/src/test/compile-fail/regions-struct-not-wf.rs index a7f182897032..9106f1f0ba69 100644 --- a/src/test/compile-fail/regions-struct-not-wf.rs +++ b/src/test/compile-fail/regions-struct-not-wf.rs @@ -10,11 +10,15 @@ // Various examples of structs whose fields are not well-formed. +// revisions:lexical nll + #![allow(dead_code)] +#![cfg_attr(nll, feature(nll))] struct Ref<'a, T> { field: &'a T - //~^ ERROR the parameter type `T` may not live long enough + //[lexical]~^ ERROR the parameter type `T` may not live long enough + //[nll]~^^ ERROR the parameter type `T` may not live long enough } struct RefOk<'a, T:'a> { @@ -23,12 +27,14 @@ struct RefOk<'a, T:'a> { struct RefIndirect<'a, T> { field: RefOk<'a, T> - //~^ ERROR the parameter type `T` may not live long enough + //[lexical]~^ ERROR the parameter type `T` may not live long enough + //[nll]~^^ ERROR the parameter type `T` may not live long enough } struct DoubleRef<'a, 'b, T> { field: &'a &'b T - //~^ ERROR reference has a longer lifetime than the data it references + //[lexical]~^ ERROR reference has a longer lifetime than the data it references + //[nll]~^^ ERROR reference has a longer lifetime than the data it references } fn main() { } diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs index 2d208c885527..74b086ab18a5 100644 --- a/src/test/ui/nll/capture-ref-in-struct.rs +++ b/src/test/ui/nll/capture-ref-in-struct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Zborrowck=mir -Znll-dump-cause +// compile-flags:-Znll-dump-cause // Test that a structure which tries to store a pointer to `y` into // `p` (indirectly) fails to compile. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs new file mode 100644 index 000000000000..babe608354fb --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs @@ -0,0 +1,41 @@ +// Copyright 2016 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. + +// Test that we assume that universal types like `T` outlive the +// function body. Same as ty-param-fn-body, but uses `feature(nll)`, +// which affects error reporting. + +#![feature(nll)] + +#![allow(warnings)] +#![feature(dyn_trait)] + +use std::cell::Cell; + +// No errors here, because `'a` is local to the body. +fn region_within_body(t: T) { + let some_int = 22; + let cell = Cell::new(&some_int); + outlives(cell, t) +} + +// Error here, because T: 'a is not satisfied. +fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { + outlives(cell, t) + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives<'a, T>(x: Cell<&'a usize>, y: T) +where + T: 'a, +{ +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr new file mode 100644 index 000000000000..fa9105df0702 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr @@ -0,0 +1,10 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn-body-nll-feature.rs:31:5 + | +31 | outlives(cell, t) + | ^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'a`... + +error: aborting due to previous error +