Skip to content

Commit

Permalink
Auto merge of #67464 - Centril:rollup-j3mkl1m, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - #67130 (Const prop should finish propagation into user defined variables)
 - #67163 (Split up ptr/mod.rs in libcore...)
 - #67314 (Don't suppress move errors for union fields)
 - #67392 (Fix unresolved type span inside async object)
 - #67404 (Separate region inference logic from error handling better)
 - #67428 (`is_binding_pat`: use explicit match & include or-pats in grammar)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Dec 21, 2019
2 parents ccd2383 + f465f95 commit 9ff30a7
Show file tree
Hide file tree
Showing 18 changed files with 2,090 additions and 1,828 deletions.
755 changes: 755 additions & 0 deletions src/libcore/ptr/const_ptr.rs

Large diffs are not rendered by default.

1,696 changes: 5 additions & 1,691 deletions src/libcore/ptr/mod.rs

Large diffs are not rendered by default.

925 changes: 925 additions & 0 deletions src/libcore/ptr/mut_ptr.rs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,16 @@ impl fmt::Display for YieldSource {
}
}

impl From<GeneratorKind> for YieldSource {
fn from(kind: GeneratorKind) -> Self {
match kind {
// Guess based on the kind of the current generator.
GeneratorKind::Gen => Self::Yield,
GeneratorKind::Async(_) => Self::Await,
}
}
}

// N.B., if you change this, you'll probably want to change the corresponding
// type structure in middle/ty.rs as well.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
Expand Down
10 changes: 9 additions & 1 deletion src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ fn resolve_local<'tcx>(
/// | VariantName(..., P&, ...)
/// | [ ..., P&, ... ]
/// | ( ..., P&, ... )
/// | ... "|" P& "|" ...
/// | box P&
fn is_binding_pat(pat: &hir::Pat) -> bool {
// Note that the code below looks for *explicit* refs only, that is, it won't
Expand Down Expand Up @@ -1212,6 +1213,7 @@ fn resolve_local<'tcx>(
pats3.iter().any(|p| is_binding_pat(&p))
}

PatKind::Or(ref subpats) |
PatKind::TupleStruct(_, ref subpats, _) |
PatKind::Tuple(ref subpats, _) => {
subpats.iter().any(|p| is_binding_pat(&p))
Expand All @@ -1221,7 +1223,13 @@ fn resolve_local<'tcx>(
is_binding_pat(&subpat)
}

_ => false,
PatKind::Ref(_, _) |
PatKind::Binding(hir::BindingAnnotation::Unannotated, ..) |
PatKind::Binding(hir::BindingAnnotation::Mutable, ..) |
PatKind::Wild |
PatKind::Path(_) |
PatKind::Lit(_) |
PatKind::Range(_, _, _) => false,
}
}

Expand Down
37 changes: 33 additions & 4 deletions src/librustc_mir/borrow_check/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Error reporting machinery for lifetime errors.

use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::infer::NLLRegionVariableOrigin;
use rustc::mir::{ConstraintCategory, Local, Location, Body};
use rustc::infer::{
error_reporting::nice_region_error::NiceRegionError,
InferCtxt, NLLRegionVariableOrigin,
};
use rustc::mir::{
ConstraintCategory, Local, Location, Body,
};
use rustc::ty::{self, RegionVid};
use rustc_index::vec::IndexVec;
use rustc_errors::DiagnosticBuilder;
Expand Down Expand Up @@ -93,6 +96,32 @@ pub struct ErrorConstraintInfo {
}

impl<'tcx> RegionInferenceContext<'tcx> {
/// Converts a region inference variable into a `ty::Region` that
/// we can use for error reporting. If `r` is universally bound,
/// then we use the name that we have on record for it. If `r` is
/// existentially bound, then we check its inferred value and try
/// to find a good name from that. Returns `None` if we can't find
/// one (e.g., this is just some random part of the CFG).
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
}

/// Returns the [RegionVid] corresponding to the region returned by
/// `to_error_region`.
pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
if self.universal_regions.is_universal_region(r) {
Some(r)
} else {
let r_scc = self.constraint_sccs.scc(r);
let upper_bound = self.universal_upper_bound(r);
if self.scc_values.contains(r_scc, upper_bound) {
self.to_error_region_vid(upper_bound)
} else {
None
}
}
}

/// Tries to find the best constraint to blame for the fact that
/// `R: from_region`, where `R` is some region that meets
/// `target_test`. This works by following the constraint graph,
Expand Down
147 changes: 63 additions & 84 deletions src/librustc_mir/borrow_check/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,32 +928,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}

/// Converts a region inference variable into a `ty::Region` that
/// we can use for error reporting. If `r` is universally bound,
/// then we use the name that we have on record for it. If `r` is
/// existentially bound, then we check its inferred value and try
/// to find a good name from that. Returns `None` if we can't find
/// one (e.g., this is just some random part of the CFG).
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
}

/// Returns the [RegionVid] corresponding to the region returned by
/// `to_error_region`.
pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
if self.universal_regions.is_universal_region(r) {
Some(r)
} else {
let r_scc = self.constraint_sccs.scc(r);
let upper_bound = self.universal_upper_bound(r);
if self.scc_values.contains(r_scc, upper_bound) {
self.to_error_region_vid(upper_bound)
} else {
None
}
}
}

/// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot
/// prove to be satisfied. If this is a closure, we will attempt to
/// "promote" this type-test into our `ClosureRegionRequirements` and
Expand Down Expand Up @@ -1164,7 +1138,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// include the CFG anyhow.
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
/// a result `'y`.
fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
pub (in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));

// Find the smallest universal region that contains all other
Expand Down Expand Up @@ -1458,19 +1432,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {
debug!("check_polonius_subset_errors: subset_error longer_fr={:?},\
shorter_fr={:?}", longer_fr, shorter_fr);

self.report_or_propagate_universal_region_error(
let propagated = self.try_propagate_universal_region_error(
*longer_fr,
*shorter_fr,
infcx,
body,
local_names,
upvars,
mir_def_id,
&mut propagated_outlives_requirements,
&mut outlives_suggestion,
errors_buffer,
region_naming,
);
if !propagated {
// If we are not in a context where we can't propagate errors, or we
// could not shrink `fr` to something smaller, then just report an
// error.
//
// Note: in this case, we use the unapproximated regions to report the
// error. This gives better error messages in some cases.
let db = self.report_error(
body,
local_names,
upvars,
infcx,
mir_def_id,
*longer_fr,
NLLRegionVariableOrigin::FreeRegion,
*shorter_fr,
&mut outlives_suggestion,
region_naming,
);

db.buffer(errors_buffer);
}
}

// Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has
Expand Down Expand Up @@ -1594,48 +1583,59 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return None;
}

self.report_or_propagate_universal_region_error(
let propagated = self.try_propagate_universal_region_error(
longer_fr,
shorter_fr,
infcx,
body,
local_names,
upvars,
mir_def_id,
propagated_outlives_requirements,
outlives_suggestion,
errors_buffer,
region_naming,
)
);

if propagated {
None
} else {
// If we are not in a context where we can't propagate errors, or we
// could not shrink `fr` to something smaller, then just report an
// error.
//
// Note: in this case, we use the unapproximated regions to report the
// error. This gives better error messages in some cases.
let db = self.report_error(
body,
local_names,
upvars,
infcx,
mir_def_id,
longer_fr,
NLLRegionVariableOrigin::FreeRegion,
shorter_fr,
outlives_suggestion,
region_naming,
);

db.buffer(errors_buffer);

Some(ErrorReported)
}
}

fn report_or_propagate_universal_region_error(
/// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
/// creator. If we cannot, then the caller should report an error to the user.
///
/// Returns `true` if the error was propagated, and `false` otherwise.
fn try_propagate_universal_region_error(
&self,
longer_fr: RegionVid,
shorter_fr: RegionVid,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
errors_buffer: &mut Vec<Diagnostic>,
region_naming: &mut RegionErrorNamingCtx,
) -> Option<ErrorReported> {
debug!(
"report_or_propagate_universal_region_error: fr={:?} does not outlive shorter_fr={:?}",
longer_fr, shorter_fr,
);

) -> bool {
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
// Shrink `longer_fr` until we find a non-local region (if we do).
// We'll call it `fr-` -- it's ever so slightly smaller than
// `longer_fr`.

if let Some(fr_minus) =
self.universal_region_relations.non_local_lower_bound(longer_fr) {
debug!("report_or_propagate_universal_region_error: fr_minus={:?}", fr_minus);
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);

let blame_span_category =
self.find_outlives_blame_span(body, longer_fr,
Expand All @@ -1648,7 +1648,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.universal_region_relations
.non_local_upper_bounds(&shorter_fr);
debug!(
"report_or_propagate_universal_region_error: shorter_fr_plus={:?}",
"try_propagate_universal_region_error: shorter_fr_plus={:?}",
shorter_fr_plus
);
for &&fr in &shorter_fr_plus {
Expand All @@ -1660,32 +1660,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
category: blame_span_category.0,
});
}
return None;
return true;
}
}

// If we are not in a context where we can't propagate errors, or we
// could not shrink `fr` to something smaller, then just report an
// error.
//
// Note: in this case, we use the unapproximated regions to report the
// error. This gives better error messages in some cases.
let db = self.report_error(
body,
local_names,
upvars,
infcx,
mir_def_id,
longer_fr,
NLLRegionVariableOrigin::FreeRegion,
shorter_fr,
outlives_suggestion,
region_naming,
);

db.buffer(errors_buffer);

Some(ErrorReported)
false
}

fn check_bound_universal_region(
Expand Down
31 changes: 22 additions & 9 deletions src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}
};

// The move path index of the first union that we find. Once this is
// some we stop creating child move paths, since moves from unions
// move the whole thing.
// We continue looking for other move errors though so that moving
// from `*(u.f: &_)` isn't allowed.
let mut union_path = None;

for (i, elem) in place.projection.iter().enumerate() {
let proj_base = &place.projection[..i];
let body = self.builder.body;
Expand All @@ -127,9 +134,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
InteriorOfTypeWithDestructor { container_ty: place_ty },
));
}
// move out of union - always move the entire union
ty::Adt(adt, _) if adt.is_union() => {
return Err(MoveError::UnionMove { path: base });
union_path.get_or_insert(base);
}
ty::Slice(_) => {
return Err(MoveError::cannot_move_out_of(
Expand All @@ -155,15 +161,22 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
_ => {}
};

base = self.add_move_path(base, elem, |tcx| {
Place {
base: place.base.clone(),
projection: tcx.intern_place_elems(&place.projection[..i+1]),
}
});
if union_path.is_none() {
base = self.add_move_path(base, elem, |tcx| {
Place {
base: place.base.clone(),
projection: tcx.intern_place_elems(&place.projection[..i+1]),
}
});
}
}

Ok(base)
if let Some(base) = union_path {
// Move out of union - always move the entire union.
Err(MoveError::UnionMove { path: base })
} else {
Ok(base)
}
}

fn add_move_path(
Expand Down
Loading

0 comments on commit 9ff30a7

Please sign in to comment.