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

NLL feature complete (adds feature(nll))! #46862

Merged
merged 39 commits into from
Dec 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f3335c6
simplify `AnonTypeDecl` in the impl trait code
nikomatsakis Dec 6, 2017
f6741d0
region_infer/values.rs: rustfmt
nikomatsakis Dec 6, 2017
e447b54
Add tracking of causes for nll
Nashenas88 Nov 21, 2017
39b0e49
rustfmt: borrow_check/mod.rs
nikomatsakis Dec 14, 2017
594c386
dump out causal information for "free region" errors
nikomatsakis Dec 7, 2017
741ef41
use Rc to store nonlexical_regioncx in Borrows
nikomatsakis Dec 7, 2017
0e64a75
integrate -Znll-dump-cause into borrowck
nikomatsakis Dec 7, 2017
fe89f4b
get the `DefiningTy` from the `body_owner_kind` not type
nikomatsakis Dec 8, 2017
4a967c9
propagate `region_bound_pairs` into MIR type-check
nikomatsakis Dec 8, 2017
e96f4be
extract `instantiate_anon_types` to the `InferCtxt`
nikomatsakis Dec 9, 2017
8e64ba8
extract `constrain_anon_types` to the `InferCtxt`
nikomatsakis Dec 9, 2017
7f50e7c
extract the writeback code for anon types into InferCtxt
nikomatsakis Dec 9, 2017
a66c651
pass `UniversalRegions` to MIR type-checker instead of fields
nikomatsakis Dec 10, 2017
da63aaa
extract `input_output` code into its own module
nikomatsakis Dec 10, 2017
93afb1a
connect NLL type checker to the impl trait code
nikomatsakis Dec 10, 2017
58b0506
Move MirVisitable to visit.rs
spastorino Dec 12, 2017
6d2987c
Move categorize logic out of visit_local function
nikomatsakis Dec 20, 2017
3a185a5
Add three point error handling to borrowck
spastorino Dec 12, 2017
e28d03f
only dump causes if we have nothing better
nikomatsakis Dec 14, 2017
4089d14
move nice-region-error reporting into its own module
nikomatsakis Dec 12, 2017
93498e0
make `util` fns private to nice_region_error
nikomatsakis Dec 12, 2017
3720242
extract `find_anon_type` into its own module
nikomatsakis Dec 12, 2017
a28ab84
nice_region_error: rustfmt
nikomatsakis Dec 12, 2017
cba4732
introduce a `NiceRegionError` type and define methods on that
nikomatsakis Dec 12, 2017
de56308
use `Option<ErrorReported>` instead of `bool`
nikomatsakis Dec 12, 2017
94e7072
give precedence to `try_report_named_anon_conflict` method
nikomatsakis Dec 12, 2017
6b39781
connect NLL machinery to the `NiceRegionError` code
nikomatsakis Dec 12, 2017
3788f42
refactor `report_generic_bound_failure` to be usable by NLL code
nikomatsakis Dec 19, 2017
508a831
use `report_generic_bound_failure` when we can in the compiler
nikomatsakis Dec 19, 2017
95b6148
Add nll_dump_cause helper to Session
spastorino Dec 19, 2017
0b2db1e
Add nll feature and make nll imply nll_dump_cause
spastorino Dec 19, 2017
2019d69
feature nll implies two-phase-borrows
spastorino Dec 19, 2017
e980fb8
feature nll implies borrowck=mir
spastorino Dec 19, 2017
cfa4ffa
document and tweak the nll, use_mir, etc helpers
nikomatsakis Dec 20, 2017
80c510e
when using feature(nll), don't warn about AST-based region errors
nikomatsakis Dec 20, 2017
cba8256
add some run-pass tests for NLL showing that things work as expected
nikomatsakis Dec 7, 2017
3f490ca
convert region-liveness-drop{-,-no-}may-dangle.rs into ui tests
nikomatsakis Dec 20, 2017
4f549fe
improve comment about instantiating anon types
nikomatsakis Dec 20, 2017
d925f4d
fix truncated comment
nikomatsakis Dec 20, 2017
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
626 changes: 626 additions & 0 deletions src/librustc/infer/anon_types/mod.rs

Large diffs are not rendered by default.

415 changes: 0 additions & 415 deletions src/librustc/infer/error_reporting/different_lifetimes.rs

This file was deleted.

57 changes: 35 additions & 22 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ mod note;

mod need_type_info;

mod named_anon_conflict;
#[macro_use]
mod util;
mod different_lifetimes;
pub mod nice_region_error;

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn note_and_explain_region(self,
Expand Down Expand Up @@ -261,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: &region::ScopeTree,
errors: &Vec<RegionResolutionError<'tcx>>) {
errors: &Vec<RegionResolutionError<'tcx>>,
will_later_be_reported_by_nll: bool) {
debug!("report_region_errors(): {} errors to start", errors.len());

if self.tcx.sess.opts.debugging_opts.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, ..) |
Expand Down Expand Up @@ -294,9 +300,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
for error in errors {
debug!("report_region_errors: error = {:?}", error);

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

RegionResolutionError::GenericBoundFailure(kind, param_ty, sub) => {
self.report_generic_bound_failure(region_scope_tree, kind, param_ty, sub);
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
self.report_generic_bound_failure(
region_scope_tree,
origin.span(),
Some(origin),
param_ty,
sub,
);
}

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

fn report_generic_bound_failure(&self,
region_scope_tree: &region::ScopeTree,
origin: SubregionOrigin<'tcx>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>)
pub fn report_generic_bound_failure(&self,
region_scope_tree: &region::ScopeTree,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>)
{
// Attempt to obtain the span of the parameter so we can
// suggest adding an explicit lifetime bound to it.
Expand Down Expand Up @@ -958,9 +969,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format!("the associated type `{}`", p),
};

if let SubregionOrigin::CompareImplMethodObligation {
if let Some(SubregionOrigin::CompareImplMethodObligation {
span, item_name, impl_item_def_id, trait_item_def_id,
} = origin {
}) = origin {
self.report_extra_impl_obligation(span,
item_name,
impl_item_def_id,
Expand Down Expand Up @@ -995,7 +1006,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
origin.span(),
span,
E0309,
"{} may not live long enough",
labeled_user_string);
Expand All @@ -1006,7 +1017,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::ReStatic => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
origin.span(),
span,
E0310,
"{} may not live long enough",
labeled_user_string);
Expand All @@ -1017,7 +1028,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
_ => {
// If not, be less specific.
let mut err = struct_span_err!(self.tcx.sess,
origin.span(),
span,
E0311,
"{} may not live long enough",
labeled_user_string);
Expand All @@ -1033,7 +1044,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
};

self.note_region_origin(&mut err, &origin);
if let Some(origin) = origin {
self.note_region_origin(&mut err, &origin);
}
err.emit();
}

Expand Down
101 changes: 0 additions & 101 deletions src/librustc/infer/error_reporting/named_anon_conflict.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright 2012-2013 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.

//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.

use infer::error_reporting::nice_region_error::NiceRegionError;
use infer::error_reporting::nice_region_error::util::AnonymousArgInfo;
use util::common::ErrorReported;

impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// Print the error message for lifetime errors when both the concerned regions are anonymous.
///
/// Consider a case where we have
///
/// ```no_run
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
/// x.push(y);
/// }
/// ```
///
/// The example gives
///
/// ```text
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
/// --- --- these references are declared with different lifetimes...
/// x.push(y);
/// ^ ...but data from `y` flows into `x` here
/// ```
///
/// It has been extended for the case of structs too.
///
/// Consider the example
///
/// ```no_run
/// struct Ref<'a> { x: &'a u32 }
/// ```
///
/// ```text
/// fn foo(mut x: Vec<Ref>, y: Ref) {
/// --- --- these structs are declared with different lifetimes...
/// x.push(y);
/// ^ ...but data from `y` flows into `x` here
/// }
/// ````
///
/// It will later be extended to trait objects.
pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
let NiceRegionError { span, sub, sup, .. } = *self;

// Determine whether the sub and sup consist of both anonymous (elided) regions.
let anon_reg_sup = self.is_suitable_region(sup)?;

let anon_reg_sub = self.is_suitable_region(sub)?;
let scope_def_id_sup = anon_reg_sup.def_id;
let bregion_sup = anon_reg_sup.boundregion;
let scope_def_id_sub = anon_reg_sub.def_id;
let bregion_sub = anon_reg_sub.boundregion;

let ty_sup = self.find_anon_type(sup, &bregion_sup)?;

let ty_sub = self.find_anon_type(sub, &bregion_sub)?;

debug!(
"try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}",
ty_sub,
sup,
bregion_sup
);
debug!(
"try_report_anon_anon_conflict: found_arg2={:?} sub={:?} br2={:?}",
ty_sup,
sub,
bregion_sub
);

let (ty_sup, ty_fndecl_sup) = ty_sup;
let (ty_sub, ty_fndecl_sub) = ty_sub;

let AnonymousArgInfo {
arg: anon_arg_sup, ..
} = self.find_arg_with_region(sup, sup)?;
let AnonymousArgInfo {
arg: anon_arg_sub, ..
} = self.find_arg_with_region(sub, sub)?;

let sup_is_ret_type =
self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
let sub_is_ret_type =
self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);

let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
format!(" from `{}`", simple_name)
} else {
format!("")
};

let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
format!(" into `{}`", simple_name)
} else {
format!("")
};


let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
(None, None) => {
let (main_label_1, span_label_1) = if ty_sup == ty_sub {
(
format!("this type is declared with multiple lifetimes..."),
format!(
"...but data{} flows{} here",
format!(" with one lifetime"),
format!(" into the other")
),
)
} else {
(
format!("these two types are declared with different lifetimes..."),
format!(
"...but data{} flows{} here",
span_label_var1,
span_label_var2
),
)
};
(ty_sup.span, ty_sub.span, main_label_1, span_label_1)
}

(Some(ret_span), _) => (
ty_sub.span,
ret_span,
format!(
"this parameter and the return type are declared \
with different lifetimes...",
),
format!("...but data{} is returned here", span_label_var1),
),
(_, Some(ret_span)) => (
ty_sup.span,
ret_span,
format!(
"this parameter and the return type are declared \
with different lifetimes...",
),
format!("...but data{} is returned here", span_label_var1),
),
};


struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
.span_label(span_1, main_label)
.span_label(span_2, format!(""))
.span_label(span, span_label)
.emit();
return Some(ErrorReported);
}
}
Loading