Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9ff30a7

Browse files
committedDec 21, 2019
Auto merge of #67464 - Centril:rollup-j3mkl1m, r=Centril
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
2 parents ccd2383 + f465f95 commit 9ff30a7

File tree

18 files changed

+2090
-1828
lines changed

18 files changed

+2090
-1828
lines changed
 

‎src/libcore/ptr/const_ptr.rs

Lines changed: 755 additions & 0 deletions
Large diffs are not rendered by default.

‎src/libcore/ptr/mod.rs

Lines changed: 5 additions & 1691 deletions
Large diffs are not rendered by default.

‎src/libcore/ptr/mut_ptr.rs

Lines changed: 925 additions & 0 deletions
Large diffs are not rendered by default.

‎src/librustc/hir/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,16 @@ impl fmt::Display for YieldSource {
18571857
}
18581858
}
18591859

1860+
impl From<GeneratorKind> for YieldSource {
1861+
fn from(kind: GeneratorKind) -> Self {
1862+
match kind {
1863+
// Guess based on the kind of the current generator.
1864+
GeneratorKind::Gen => Self::Yield,
1865+
GeneratorKind::Async(_) => Self::Await,
1866+
}
1867+
}
1868+
}
1869+
18601870
// N.B., if you change this, you'll probably want to change the corresponding
18611871
// type structure in middle/ty.rs as well.
18621872
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]

‎src/librustc/middle/region.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ fn resolve_local<'tcx>(
11731173
/// | VariantName(..., P&, ...)
11741174
/// | [ ..., P&, ... ]
11751175
/// | ( ..., P&, ... )
1176+
/// | ... "|" P& "|" ...
11761177
/// | box P&
11771178
fn is_binding_pat(pat: &hir::Pat) -> bool {
11781179
// Note that the code below looks for *explicit* refs only, that is, it won't
@@ -1212,6 +1213,7 @@ fn resolve_local<'tcx>(
12121213
pats3.iter().any(|p| is_binding_pat(&p))
12131214
}
12141215

1216+
PatKind::Or(ref subpats) |
12151217
PatKind::TupleStruct(_, ref subpats, _) |
12161218
PatKind::Tuple(ref subpats, _) => {
12171219
subpats.iter().any(|p| is_binding_pat(&p))
@@ -1221,7 +1223,13 @@ fn resolve_local<'tcx>(
12211223
is_binding_pat(&subpat)
12221224
}
12231225

1224-
_ => false,
1226+
PatKind::Ref(_, _) |
1227+
PatKind::Binding(hir::BindingAnnotation::Unannotated, ..) |
1228+
PatKind::Binding(hir::BindingAnnotation::Mutable, ..) |
1229+
PatKind::Wild |
1230+
PatKind::Path(_) |
1231+
PatKind::Lit(_) |
1232+
PatKind::Range(_, _, _) => false,
12251233
}
12261234
}
12271235

‎src/librustc_mir/borrow_check/diagnostics/region_errors.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
//! Error reporting machinery for lifetime errors.
22
33
use rustc::hir::def_id::DefId;
4-
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
5-
use rustc::infer::InferCtxt;
6-
use rustc::infer::NLLRegionVariableOrigin;
7-
use rustc::mir::{ConstraintCategory, Local, Location, Body};
4+
use rustc::infer::{
5+
error_reporting::nice_region_error::NiceRegionError,
6+
InferCtxt, NLLRegionVariableOrigin,
7+
};
8+
use rustc::mir::{
9+
ConstraintCategory, Local, Location, Body,
10+
};
811
use rustc::ty::{self, RegionVid};
912
use rustc_index::vec::IndexVec;
1013
use rustc_errors::DiagnosticBuilder;
@@ -93,6 +96,32 @@ pub struct ErrorConstraintInfo {
9396
}
9497

9598
impl<'tcx> RegionInferenceContext<'tcx> {
99+
/// Converts a region inference variable into a `ty::Region` that
100+
/// we can use for error reporting. If `r` is universally bound,
101+
/// then we use the name that we have on record for it. If `r` is
102+
/// existentially bound, then we check its inferred value and try
103+
/// to find a good name from that. Returns `None` if we can't find
104+
/// one (e.g., this is just some random part of the CFG).
105+
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
106+
self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
107+
}
108+
109+
/// Returns the [RegionVid] corresponding to the region returned by
110+
/// `to_error_region`.
111+
pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
112+
if self.universal_regions.is_universal_region(r) {
113+
Some(r)
114+
} else {
115+
let r_scc = self.constraint_sccs.scc(r);
116+
let upper_bound = self.universal_upper_bound(r);
117+
if self.scc_values.contains(r_scc, upper_bound) {
118+
self.to_error_region_vid(upper_bound)
119+
} else {
120+
None
121+
}
122+
}
123+
}
124+
96125
/// Tries to find the best constraint to blame for the fact that
97126
/// `R: from_region`, where `R` is some region that meets
98127
/// `target_test`. This works by following the constraint graph,

‎src/librustc_mir/borrow_check/region_infer/mod.rs

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -928,32 +928,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
928928
}
929929
}
930930

931-
/// Converts a region inference variable into a `ty::Region` that
932-
/// we can use for error reporting. If `r` is universally bound,
933-
/// then we use the name that we have on record for it. If `r` is
934-
/// existentially bound, then we check its inferred value and try
935-
/// to find a good name from that. Returns `None` if we can't find
936-
/// one (e.g., this is just some random part of the CFG).
937-
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
938-
self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
939-
}
940-
941-
/// Returns the [RegionVid] corresponding to the region returned by
942-
/// `to_error_region`.
943-
pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
944-
if self.universal_regions.is_universal_region(r) {
945-
Some(r)
946-
} else {
947-
let r_scc = self.constraint_sccs.scc(r);
948-
let upper_bound = self.universal_upper_bound(r);
949-
if self.scc_values.contains(r_scc, upper_bound) {
950-
self.to_error_region_vid(upper_bound)
951-
} else {
952-
None
953-
}
954-
}
955-
}
956-
957931
/// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot
958932
/// prove to be satisfied. If this is a closure, we will attempt to
959933
/// "promote" this type-test into our `ClosureRegionRequirements` and
@@ -1164,7 +1138,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11641138
/// include the CFG anyhow.
11651139
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
11661140
/// a result `'y`.
1167-
fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
1141+
pub (in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
11681142
debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
11691143

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

1461-
self.report_or_propagate_universal_region_error(
1435+
let propagated = self.try_propagate_universal_region_error(
14621436
*longer_fr,
14631437
*shorter_fr,
1464-
infcx,
14651438
body,
1466-
local_names,
1467-
upvars,
1468-
mir_def_id,
14691439
&mut propagated_outlives_requirements,
1470-
&mut outlives_suggestion,
1471-
errors_buffer,
1472-
region_naming,
14731440
);
1441+
if !propagated {
1442+
// If we are not in a context where we can't propagate errors, or we
1443+
// could not shrink `fr` to something smaller, then just report an
1444+
// error.
1445+
//
1446+
// Note: in this case, we use the unapproximated regions to report the
1447+
// error. This gives better error messages in some cases.
1448+
let db = self.report_error(
1449+
body,
1450+
local_names,
1451+
upvars,
1452+
infcx,
1453+
mir_def_id,
1454+
*longer_fr,
1455+
NLLRegionVariableOrigin::FreeRegion,
1456+
*shorter_fr,
1457+
&mut outlives_suggestion,
1458+
region_naming,
1459+
);
1460+
1461+
db.buffer(errors_buffer);
1462+
}
14741463
}
14751464

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

1597-
self.report_or_propagate_universal_region_error(
1586+
let propagated = self.try_propagate_universal_region_error(
15981587
longer_fr,
15991588
shorter_fr,
1600-
infcx,
16011589
body,
1602-
local_names,
1603-
upvars,
1604-
mir_def_id,
16051590
propagated_outlives_requirements,
1606-
outlives_suggestion,
1607-
errors_buffer,
1608-
region_naming,
1609-
)
1591+
);
1592+
1593+
if propagated {
1594+
None
1595+
} else {
1596+
// If we are not in a context where we can't propagate errors, or we
1597+
// could not shrink `fr` to something smaller, then just report an
1598+
// error.
1599+
//
1600+
// Note: in this case, we use the unapproximated regions to report the
1601+
// error. This gives better error messages in some cases.
1602+
let db = self.report_error(
1603+
body,
1604+
local_names,
1605+
upvars,
1606+
infcx,
1607+
mir_def_id,
1608+
longer_fr,
1609+
NLLRegionVariableOrigin::FreeRegion,
1610+
shorter_fr,
1611+
outlives_suggestion,
1612+
region_naming,
1613+
);
1614+
1615+
db.buffer(errors_buffer);
1616+
1617+
Some(ErrorReported)
1618+
}
16101619
}
16111620

1612-
fn report_or_propagate_universal_region_error(
1621+
/// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
1622+
/// creator. If we cannot, then the caller should report an error to the user.
1623+
///
1624+
/// Returns `true` if the error was propagated, and `false` otherwise.
1625+
fn try_propagate_universal_region_error(
16131626
&self,
16141627
longer_fr: RegionVid,
16151628
shorter_fr: RegionVid,
1616-
infcx: &InferCtxt<'_, 'tcx>,
16171629
body: &Body<'tcx>,
1618-
local_names: &IndexVec<Local, Option<Symbol>>,
1619-
upvars: &[Upvar],
1620-
mir_def_id: DefId,
16211630
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1622-
outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
1623-
errors_buffer: &mut Vec<Diagnostic>,
1624-
region_naming: &mut RegionErrorNamingCtx,
1625-
) -> Option<ErrorReported> {
1626-
debug!(
1627-
"report_or_propagate_universal_region_error: fr={:?} does not outlive shorter_fr={:?}",
1628-
longer_fr, shorter_fr,
1629-
);
1630-
1631+
) -> bool {
16311632
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
16321633
// Shrink `longer_fr` until we find a non-local region (if we do).
16331634
// We'll call it `fr-` -- it's ever so slightly smaller than
16341635
// `longer_fr`.
1635-
16361636
if let Some(fr_minus) =
16371637
self.universal_region_relations.non_local_lower_bound(longer_fr) {
1638-
debug!("report_or_propagate_universal_region_error: fr_minus={:?}", fr_minus);
1638+
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
16391639

16401640
let blame_span_category =
16411641
self.find_outlives_blame_span(body, longer_fr,
@@ -1648,7 +1648,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
16481648
.universal_region_relations
16491649
.non_local_upper_bounds(&shorter_fr);
16501650
debug!(
1651-
"report_or_propagate_universal_region_error: shorter_fr_plus={:?}",
1651+
"try_propagate_universal_region_error: shorter_fr_plus={:?}",
16521652
shorter_fr_plus
16531653
);
16541654
for &&fr in &shorter_fr_plus {
@@ -1660,32 +1660,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
16601660
category: blame_span_category.0,
16611661
});
16621662
}
1663-
return None;
1663+
return true;
16641664
}
16651665
}
16661666

1667-
// If we are not in a context where we can't propagate errors, or we
1668-
// could not shrink `fr` to something smaller, then just report an
1669-
// error.
1670-
//
1671-
// Note: in this case, we use the unapproximated regions to report the
1672-
// error. This gives better error messages in some cases.
1673-
let db = self.report_error(
1674-
body,
1675-
local_names,
1676-
upvars,
1677-
infcx,
1678-
mir_def_id,
1679-
longer_fr,
1680-
NLLRegionVariableOrigin::FreeRegion,
1681-
shorter_fr,
1682-
outlives_suggestion,
1683-
region_naming,
1684-
);
1685-
1686-
db.buffer(errors_buffer);
1687-
1688-
Some(ErrorReported)
1667+
false
16891668
}
16901669

16911670
fn check_bound_universal_region(

‎src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
103103
}
104104
};
105105

106+
// The move path index of the first union that we find. Once this is
107+
// some we stop creating child move paths, since moves from unions
108+
// move the whole thing.
109+
// We continue looking for other move errors though so that moving
110+
// from `*(u.f: &_)` isn't allowed.
111+
let mut union_path = None;
112+
106113
for (i, elem) in place.projection.iter().enumerate() {
107114
let proj_base = &place.projection[..i];
108115
let body = self.builder.body;
@@ -127,9 +134,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
127134
InteriorOfTypeWithDestructor { container_ty: place_ty },
128135
));
129136
}
130-
// move out of union - always move the entire union
131137
ty::Adt(adt, _) if adt.is_union() => {
132-
return Err(MoveError::UnionMove { path: base });
138+
union_path.get_or_insert(base);
133139
}
134140
ty::Slice(_) => {
135141
return Err(MoveError::cannot_move_out_of(
@@ -155,15 +161,22 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
155161
_ => {}
156162
};
157163

158-
base = self.add_move_path(base, elem, |tcx| {
159-
Place {
160-
base: place.base.clone(),
161-
projection: tcx.intern_place_elems(&place.projection[..i+1]),
162-
}
163-
});
164+
if union_path.is_none() {
165+
base = self.add_move_path(base, elem, |tcx| {
166+
Place {
167+
base: place.base.clone(),
168+
projection: tcx.intern_place_elems(&place.projection[..i+1]),
169+
}
170+
});
171+
}
164172
}
165173

166-
Ok(base)
174+
if let Some(base) = union_path {
175+
// Move out of union - always move the entire union.
176+
Err(MoveError::UnionMove { path: base })
177+
} else {
178+
Ok(base)
179+
}
167180
}
168181

169182
fn add_move_path(

‎src/librustc_mir/transform/const_prop.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ struct ConstPropagator<'mir, 'tcx> {
262262
ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
263263
tcx: TyCtxt<'tcx>,
264264
source: MirSource<'tcx>,
265-
can_const_prop: IndexVec<Local, bool>,
265+
can_const_prop: IndexVec<Local, ConstPropMode>,
266266
param_env: ParamEnv<'tcx>,
267267
// FIXME(eddyb) avoid cloning these two fields more than once,
268268
// by accessing them through `ecx` instead.
@@ -708,17 +708,28 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
708708
}
709709
}
710710

711+
/// The mode that `ConstProp` is allowed to run in for a given `Local`.
712+
#[derive(Clone, Copy, Debug, PartialEq)]
713+
enum ConstPropMode {
714+
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
715+
FullConstProp,
716+
/// The `Local` can be propagated into but reads cannot be propagated.
717+
OnlyPropagateInto,
718+
/// No propagation is allowed at all.
719+
NoPropagation,
720+
}
721+
711722
struct CanConstProp {
712-
can_const_prop: IndexVec<Local, bool>,
723+
can_const_prop: IndexVec<Local, ConstPropMode>,
713724
// false at the beginning, once set, there are not allowed to be any more assignments
714725
found_assignment: IndexVec<Local, bool>,
715726
}
716727

717728
impl CanConstProp {
718729
/// returns true if `local` can be propagated
719-
fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec<Local, bool> {
730+
fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec<Local, ConstPropMode> {
720731
let mut cpv = CanConstProp {
721-
can_const_prop: IndexVec::from_elem(true, &body.local_decls),
732+
can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls),
722733
found_assignment: IndexVec::from_elem(false, &body.local_decls),
723734
};
724735
for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
@@ -728,10 +739,10 @@ impl CanConstProp {
728739
// FIXME(oli-obk): lint variables until they are used in a condition
729740
// FIXME(oli-obk): lint if return value is constant
730741
let local_kind = body.local_kind(local);
731-
*val = local_kind == LocalKind::Temp || local_kind == LocalKind::ReturnPointer;
732742

733-
if !*val {
734-
trace!("local {:?} can't be propagated because it's not a temporary", local);
743+
if local_kind == LocalKind::Arg || local_kind == LocalKind::Var {
744+
*val = ConstPropMode::OnlyPropagateInto;
745+
trace!("local {:?} can't be const propagated because it's not a temporary", local);
735746
}
736747
}
737748
cpv.visit_body(body);
@@ -753,7 +764,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
753764
// only occur in independent execution paths
754765
MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] {
755766
trace!("local {:?} can't be propagated because of multiple assignments", local);
756-
self.can_const_prop[local] = false;
767+
self.can_const_prop[local] = ConstPropMode::NoPropagation;
757768
} else {
758769
self.found_assignment[local] = true
759770
},
@@ -766,7 +777,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
766777
NonUse(_) => {},
767778
_ => {
768779
trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
769-
self.can_const_prop[local] = false;
780+
self.can_const_prop[local] = ConstPropMode::NoPropagation;
770781
},
771782
}
772783
}
@@ -800,10 +811,10 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
800811
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
801812
if let Some(local) = place.as_local() {
802813
let source = statement.source_info;
814+
let can_const_prop = self.can_const_prop[local];
803815
if let Some(()) = self.const_prop(rval, place_layout, source, place) {
804-
if self.can_const_prop[local] {
805-
trace!("propagated into {:?}", local);
806-
816+
if can_const_prop == ConstPropMode::FullConstProp ||
817+
can_const_prop == ConstPropMode::OnlyPropagateInto {
807818
if let Some(value) = self.get_const(local) {
808819
if self.should_const_prop(value) {
809820
trace!("replacing {:?} with {:?}", rval, value);
@@ -812,21 +823,26 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
812823
value,
813824
statement.source_info,
814825
);
826+
827+
if can_const_prop == ConstPropMode::FullConstProp {
828+
trace!("propagated into {:?}", local);
829+
}
815830
}
816831
}
817-
} else {
818-
trace!("can't propagate into {:?}", local);
819-
if local != RETURN_PLACE {
820-
self.remove_const(local);
821-
}
832+
}
833+
}
834+
if self.can_const_prop[local] != ConstPropMode::FullConstProp {
835+
trace!("can't propagate into {:?}", local);
836+
if local != RETURN_PLACE {
837+
self.remove_const(local);
822838
}
823839
}
824840
}
825841
}
826842
} else {
827843
match statement.kind {
828844
StatementKind::StorageLive(local) |
829-
StatementKind::StorageDead(local) if self.can_const_prop[local] => {
845+
StatementKind::StorageDead(local) => {
830846
let frame = self.ecx.frame_mut();
831847
frame.locals[local].value =
832848
if let StatementKind::StorageLive(_) = statement.kind {

‎src/librustc_typeck/check/generator_interior.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct InteriorVisitor<'a, 'tcx> {
1919
region_scope_tree: &'tcx region::ScopeTree,
2020
expr_count: usize,
2121
kind: hir::GeneratorKind,
22+
prev_unresolved_span: Option<Span>,
2223
}
2324

2425
impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
@@ -32,7 +33,6 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
3233
debug!("generator_interior: attempting to record type {:?} {:?} {:?} {:?}",
3334
ty, scope, expr, source_span);
3435

35-
3636
let live_across_yield = scope.map(|s| {
3737
self.region_scope_tree.yield_in_scope(s).and_then(|yield_data| {
3838
// If we are recording an expression that is the last yield
@@ -54,15 +54,11 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
5454
}).unwrap_or_else(|| Some(YieldData {
5555
span: DUMMY_SP,
5656
expr_and_pat_count: 0,
57-
source: match self.kind { // Guess based on the kind of the current generator.
58-
hir::GeneratorKind::Gen => hir::YieldSource::Yield,
59-
hir::GeneratorKind::Async(_) => hir::YieldSource::Await,
60-
},
57+
source: self.kind.into(),
6158
}));
6259

6360
if let Some(yield_data) = live_across_yield {
6461
let ty = self.fcx.resolve_vars_if_possible(&ty);
65-
6662
debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
6763
expr, scope, ty, self.expr_count, yield_data.span);
6864

@@ -74,9 +70,12 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
7470
yield_data.source);
7571

7672
// If unresolved type isn't a ty_var then unresolved_type_span is None
73+
let span = self.prev_unresolved_span.unwrap_or_else(
74+
|| unresolved_type_span.unwrap_or(source_span)
75+
);
7776
self.fcx.need_type_info_err_in_generator(
7877
self.kind,
79-
unresolved_type_span.unwrap_or(source_span),
78+
span,
8079
unresolved_type,
8180
)
8281
.span_note(yield_data.span, &*note)
@@ -94,6 +93,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
9493
} else {
9594
debug!("no type in expr = {:?}, count = {:?}, span = {:?}",
9695
expr, self.expr_count, expr.map(|e| e.span));
96+
let ty = self.fcx.resolve_vars_if_possible(&ty);
97+
if let Some((unresolved_type, unresolved_type_span))
98+
= self.fcx.unresolved_type_vars(&ty) {
99+
debug!("remained unresolved_type = {:?}, unresolved_type_span: {:?}",
100+
unresolved_type, unresolved_type_span);
101+
self.prev_unresolved_span = unresolved_type_span;
102+
}
97103
}
98104
}
99105
}
@@ -112,6 +118,7 @@ pub fn resolve_interior<'a, 'tcx>(
112118
region_scope_tree: fcx.tcx.region_scope_tree(def_id),
113119
expr_count: 0,
114120
kind,
121+
prev_unresolved_span: None,
115122
};
116123
intravisit::walk_body(&mut visitor, body);
117124

‎src/test/mir-opt/const_prop/aggregate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn main() {
1919
// ...
2020
// _3 = (const 0i32, const 1i32, const 2i32);
2121
// _2 = const 1i32;
22-
// _1 = Add(move _2, const 0i32);
22+
// _1 = const 1i32;
2323
// ...
2424
// }
2525
// END rustc.main.ConstProp.after.mir

‎src/test/mir-opt/const_prop/array_index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn main() {
2626
// assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
2727
// }
2828
// bb1: {
29-
// _1 = _2[_3];
29+
// _1 = const 2u32;
3030
// ...
3131
// return;
3232
// }
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// compile-flags: -C overflow-checks=on
2+
3+
struct Point {
4+
x: u32,
5+
y: u32,
6+
}
7+
8+
fn main() {
9+
let x = 2 + 2;
10+
let y = [0, 1, 2, 3, 4, 5][3];
11+
let z = (Point { x: 12, y: 42}).y;
12+
}
13+
14+
// END RUST SOURCE
15+
// START rustc.main.ConstProp.before.mir
16+
// let mut _0: ();
17+
// let _1: i32;
18+
// let mut _2: (i32, bool);
19+
// let mut _4: [i32; 6];
20+
// let _5: usize;
21+
// let mut _6: usize;
22+
// let mut _7: bool;
23+
// let mut _9: Point;
24+
// scope 1 {
25+
// debug x => _1;
26+
// let _3: i32;
27+
// scope 2 {
28+
// debug y => _3;
29+
// let _8: u32;
30+
// scope 3 {
31+
// debug z => _8;
32+
// }
33+
// }
34+
// }
35+
// bb0: {
36+
// StorageLive(_1);
37+
// _2 = CheckedAdd(const 2i32, const 2i32);
38+
// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
39+
// }
40+
// bb1: {
41+
// _1 = move (_2.0: i32);
42+
// StorageLive(_3);
43+
// StorageLive(_4);
44+
// _4 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
45+
// StorageLive(_5);
46+
// _5 = const 3usize;
47+
// _6 = const 6usize;
48+
// _7 = Lt(_5, _6);
49+
// assert(move _7, "index out of bounds: the len is move _6 but the index is _5") -> bb2;
50+
// }
51+
// bb2: {
52+
// _3 = _4[_5];
53+
// StorageDead(_5);
54+
// StorageDead(_4);
55+
// StorageLive(_8);
56+
// StorageLive(_9);
57+
// _9 = Point { x: const 12u32, y: const 42u32 };
58+
// _8 = (_9.1: u32);
59+
// StorageDead(_9);
60+
// _0 = ();
61+
// StorageDead(_8);
62+
// StorageDead(_3);
63+
// StorageDead(_1);
64+
// return;
65+
// }
66+
// END rustc.main.ConstProp.before.mir
67+
// START rustc.main.ConstProp.after.mir
68+
// let mut _0: ();
69+
// let _1: i32;
70+
// let mut _2: (i32, bool);
71+
// let mut _4: [i32; 6];
72+
// let _5: usize;
73+
// let mut _6: usize;
74+
// let mut _7: bool;
75+
// let mut _9: Point;
76+
// scope 1 {
77+
// debug x => _1;
78+
// let _3: i32;
79+
// scope 2 {
80+
// debug y => _3;
81+
// let _8: u32;
82+
// scope 3 {
83+
// debug z => _8;
84+
// }
85+
// }
86+
// }
87+
// bb0: {
88+
// StorageLive(_1);
89+
// _2 = (const 4i32, const false);
90+
// assert(!const false, "attempt to add with overflow") -> bb1;
91+
// }
92+
// bb1: {
93+
// _1 = const 4i32;
94+
// StorageLive(_3);
95+
// StorageLive(_4);
96+
// _4 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
97+
// StorageLive(_5);
98+
// _5 = const 3usize;
99+
// _6 = const 6usize;
100+
// _7 = const true;
101+
// assert(const true, "index out of bounds: the len is move _6 but the index is _5") -> bb2;
102+
// }
103+
// bb2: {
104+
// _3 = const 3i32;
105+
// StorageDead(_5);
106+
// StorageDead(_4);
107+
// StorageLive(_8);
108+
// StorageLive(_9);
109+
// _9 = Point { x: const 12u32, y: const 42u32 };
110+
// _8 = const 42u32;
111+
// StorageDead(_9);
112+
// _0 = ();
113+
// StorageDead(_8);
114+
// StorageDead(_3);
115+
// StorageDead(_1);
116+
// return;
117+
// }
118+
// END rustc.main.ConstProp.after.mir
119+
// START rustc.main.SimplifyLocals.after.mir
120+
// let mut _0: ();
121+
// let _1: i32;
122+
// let mut _3: [i32; 6];
123+
// scope 1 {
124+
// debug x => _1;
125+
// let _2: i32;
126+
// scope 2 {
127+
// debug y => _2;
128+
// let _4: u32;
129+
// scope 3 {
130+
// debug z => _4;
131+
// }
132+
// }
133+
// }
134+
// bb0: {
135+
// StorageLive(_1);
136+
// _1 = const 4i32;
137+
// StorageLive(_2);
138+
// StorageLive(_3);
139+
// _3 = [const 0i32, const 1i32, const 2i32, const 3i32, const 4i32, const 5i32];
140+
// _2 = const 3i32;
141+
// StorageDead(_3);
142+
// StorageLive(_4);
143+
// _4 = const 42u32;
144+
// StorageDead(_4);
145+
// StorageDead(_2);
146+
// StorageDead(_1);
147+
// return;
148+
// }
149+
// END rustc.main.SimplifyLocals.after.mir

‎src/test/mir-opt/const_prop/read_immutable_static.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn main() {
2525
// _2 = const 2u8;
2626
// ...
2727
// _4 = const 2u8;
28-
// _1 = Add(move _2, move _4);
28+
// _1 = const 4u8;
2929
// ...
3030
// }
3131
// END rustc.main.ConstProp.after.mir

‎src/test/mir-opt/const_prop/repeat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn main() {
3030
// }
3131
// bb1: {
3232
// _2 = const 42u32;
33-
// _1 = Add(move _2, const 0u32);
33+
// _1 = const 42u32;
3434
// ...
3535
// return;
3636
// }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Moving from a reference/raw pointer should be an error, even when they're
2+
// the field of a union.
3+
4+
#![feature(untagged_unions)]
5+
6+
union Pointers {
7+
a: &'static String,
8+
b: &'static mut String,
9+
c: *const String,
10+
d: *mut String,
11+
}
12+
13+
unsafe fn move_ref(u: Pointers) -> String {
14+
*u.a
15+
//~^ ERROR cannot move out of `*u.a`
16+
}
17+
unsafe fn move_ref_mut(u: Pointers) -> String {
18+
*u.b
19+
//~^ ERROR cannot move out of `*u.b`
20+
}
21+
unsafe fn move_ptr(u: Pointers) -> String {
22+
*u.c
23+
//~^ ERROR cannot move out of `*u.c`
24+
}
25+
unsafe fn move_ptr_mut(u: Pointers) -> String {
26+
*u.d
27+
//~^ ERROR cannot move out of `*u.d`
28+
}
29+
30+
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0507]: cannot move out of `*u.a` which is behind a shared reference
2+
--> $DIR/move-from-union-field-issue-66500.rs:14:5
3+
|
4+
LL | *u.a
5+
| ^^^^ move occurs because `*u.a` has type `std::string::String`, which does not implement the `Copy` trait
6+
7+
error[E0507]: cannot move out of `*u.b` which is behind a mutable reference
8+
--> $DIR/move-from-union-field-issue-66500.rs:18:5
9+
|
10+
LL | *u.b
11+
| ^^^^ move occurs because `*u.b` has type `std::string::String`, which does not implement the `Copy` trait
12+
13+
error[E0507]: cannot move out of `*u.c` which is behind a raw pointer
14+
--> $DIR/move-from-union-field-issue-66500.rs:22:5
15+
|
16+
LL | *u.c
17+
| ^^^^ move occurs because `*u.c` has type `std::string::String`, which does not implement the `Copy` trait
18+
19+
error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
20+
--> $DIR/move-from-union-field-issue-66500.rs:26:5
21+
|
22+
LL | *u.d
23+
| ^^^^ move occurs because `*u.d` has type `std::string::String`, which does not implement the `Copy` trait
24+
25+
error: aborting due to 4 previous errors
26+
27+
For more information about this error, try `rustc --explain E0507`.

‎src/test/ui/consts/offset_from_ub.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error: any use of this value will cause an error
2-
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
2+
--> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
33
|
44
LL | intrinsics::ptr_offset_from(self, origin)
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
| |
77
| ptr_offset_from cannot compute offset of pointers into different allocations.
8-
| inside call to `std::ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:19:27
8+
| inside call to `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:19:27
99
|
1010
::: $DIR/offset_from_ub.rs:13:1
1111
|
@@ -21,13 +21,13 @@ LL | | };
2121
= note: `#[deny(const_err)]` on by default
2222

2323
error: any use of this value will cause an error
24-
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
24+
--> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
2525
|
2626
LL | intrinsics::ptr_offset_from(self, origin)
2727
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2828
| |
2929
| a memory access tried to interpret some bytes as a pointer
30-
| inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:25:14
30+
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:25:14
3131
|
3232
::: $DIR/offset_from_ub.rs:23:1
3333
|
@@ -38,13 +38,13 @@ LL | | };
3838
| |__-
3939

4040
error: any use of this value will cause an error
41-
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
41+
--> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
4242
|
4343
LL | intrinsics::ptr_offset_from(self, origin)
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4545
| |
4646
| exact_div: 1 cannot be divided by 2 without remainder
47-
| inside call to `std::ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:14
47+
| inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:14
4848
|
4949
::: $DIR/offset_from_ub.rs:28:1
5050
|
@@ -58,13 +58,13 @@ LL | | };
5858
| |__-
5959

6060
error: any use of this value will cause an error
61-
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
61+
--> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
6262
|
6363
LL | intrinsics::ptr_offset_from(self, origin)
6464
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6565
| |
6666
| invalid use of NULL pointer
67-
| inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:39:14
67+
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:39:14
6868
|
6969
::: $DIR/offset_from_ub.rs:36:1
7070
|
@@ -76,13 +76,13 @@ LL | | };
7676
| |__-
7777

7878
error: any use of this value will cause an error
79-
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
79+
--> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
8080
|
8181
LL | intrinsics::ptr_offset_from(self, origin)
8282
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8383
| |
8484
| a memory access tried to interpret some bytes as a pointer
85-
| inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:46:14
85+
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:46:14
8686
|
8787
::: $DIR/offset_from_ub.rs:42:1
8888
|

0 commit comments

Comments
 (0)
Please sign in to comment.