mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
Auto merge of #71717 - Dylan-DPC:rollup-av5vjor, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #70950 (extend NLL checker to understand `'empty` combined with universes) - #71433 (Add help message for missing right operand in condition) - #71449 (Move `{Free,}RegionRelations` and `FreeRegionMap` to `rustc_infer`) - #71559 (Detect git version before attempting to use --progress) - #71597 (Rename Unique::empty() -> Unique::dangling()) Failed merges: r? @ghost
This commit is contained in:
commit
7ced01a730
@ -3852,6 +3852,7 @@ dependencies = [
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"serialize",
|
||||
"smallvec 1.0.0",
|
||||
]
|
||||
|
||||
|
@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function
|
||||
import argparse
|
||||
import contextlib
|
||||
import datetime
|
||||
import distutils.version
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
@ -331,6 +332,7 @@ class RustBuild(object):
|
||||
self.use_locked_deps = ''
|
||||
self.use_vendored_sources = ''
|
||||
self.verbose = False
|
||||
self.git_version = None
|
||||
|
||||
def download_stage0(self):
|
||||
"""Fetch the build system for Rust, written in Rust
|
||||
@ -743,15 +745,13 @@ class RustBuild(object):
|
||||
|
||||
run(["git", "submodule", "-q", "sync", module],
|
||||
cwd=self.rust_root, verbose=self.verbose)
|
||||
try:
|
||||
run(["git", "submodule", "update",
|
||||
"--init", "--recursive", "--progress", module],
|
||||
cwd=self.rust_root, verbose=self.verbose, exception=True)
|
||||
except RuntimeError:
|
||||
# Some versions of git don't support --progress.
|
||||
run(["git", "submodule", "update",
|
||||
"--init", "--recursive", module],
|
||||
cwd=self.rust_root, verbose=self.verbose)
|
||||
|
||||
update_args = ["git", "submodule", "update", "--init", "--recursive"]
|
||||
if self.git_version >= distutils.version.LooseVersion("2.11.0"):
|
||||
update_args.append("--progress")
|
||||
update_args.append(module)
|
||||
run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
|
||||
|
||||
run(["git", "reset", "-q", "--hard"],
|
||||
cwd=module_path, verbose=self.verbose)
|
||||
run(["git", "clean", "-qdfx"],
|
||||
@ -763,9 +763,13 @@ class RustBuild(object):
|
||||
self.get_toml('submodules') == "false":
|
||||
return
|
||||
|
||||
# check the existence of 'git' command
|
||||
default_encoding = sys.getdefaultencoding()
|
||||
|
||||
# check the existence and version of 'git' command
|
||||
try:
|
||||
subprocess.check_output(['git', '--version'])
|
||||
git_version_output = subprocess.check_output(['git', '--version'])
|
||||
git_version_str = git_version_output.strip().split()[2].decode(default_encoding)
|
||||
self.git_version = distutils.version.LooseVersion(git_version_str)
|
||||
except (subprocess.CalledProcessError, OSError):
|
||||
print("error: `git` is not found, please make sure it's installed and in the path.")
|
||||
sys.exit(1)
|
||||
|
@ -25,9 +25,9 @@ mod tests;
|
||||
/// involved. This type is excellent for building your own data structures like Vec and VecDeque.
|
||||
/// In particular:
|
||||
///
|
||||
/// * Produces `Unique::empty()` on zero-sized types.
|
||||
/// * Produces `Unique::empty()` on zero-length allocations.
|
||||
/// * Avoids freeing `Unique::empty()`.
|
||||
/// * Produces `Unique::dangling()` on zero-sized types.
|
||||
/// * Produces `Unique::dangling()` on zero-length allocations.
|
||||
/// * Avoids freeing `Unique::dangling()`.
|
||||
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics).
|
||||
/// * Guards against 32-bit systems allocating more than isize::MAX bytes.
|
||||
/// * Guards against overflowing your length.
|
||||
@ -125,7 +125,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
|
||||
/// the returned `RawVec`.
|
||||
pub const fn new_in(alloc: A) -> Self {
|
||||
// `cap: 0` means "unallocated". zero-sized types are ignored.
|
||||
Self { ptr: Unique::empty(), cap: 0, alloc }
|
||||
Self { ptr: Unique::dangling(), cap: 0, alloc }
|
||||
}
|
||||
|
||||
/// Like `with_capacity`, but parameterized over the choice of
|
||||
@ -172,7 +172,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
|
||||
}
|
||||
|
||||
/// Gets a raw pointer to the start of the allocation. Note that this is
|
||||
/// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
|
||||
/// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
|
||||
/// be careful.
|
||||
pub fn ptr(&self) -> *mut T {
|
||||
self.ptr.as_ptr()
|
||||
|
@ -70,9 +70,8 @@ impl<T: Sized> Unique<T> {
|
||||
/// a `T`, which means this must not be used as a "not yet initialized"
|
||||
/// sentinel value. Types that lazily allocate must track initialization by
|
||||
/// some other means.
|
||||
// FIXME: rename to dangling() to match NonNull?
|
||||
#[inline]
|
||||
pub const fn empty() -> Self {
|
||||
pub const fn dangling() -> Self {
|
||||
// SAFETY: mem::align_of() returns a valid, non-null pointer. The
|
||||
// conditions to call new_unchecked() are thus respected.
|
||||
unsafe { Unique::new_unchecked(mem::align_of::<T>() as *mut T) }
|
||||
|
@ -47,6 +47,11 @@ impl<N: Idx, S: Idx> Sccs<N, S> {
|
||||
}
|
||||
|
||||
/// Returns an iterator over the SCCs in the graph.
|
||||
///
|
||||
/// The SCCs will be iterated in **dependency order** (or **post order**),
|
||||
/// meaning that if `S1 -> S2`, we will visit `S2` first and `S1` after.
|
||||
/// This is convenient when the edges represent dependencies: when you visit
|
||||
/// `S1`, the value for `S2` will already have been computed.
|
||||
pub fn all_sccs(&self) -> impl Iterator<Item = S> {
|
||||
(0..self.scc_data.len()).map(S::new)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ rustc_hir = { path = "../librustc_hir" }
|
||||
rustc_index = { path = "../librustc_index" }
|
||||
rustc_macros = { path = "../librustc_macros" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
||||
|
@ -1,5 +1,47 @@
|
||||
use crate::ty::{self, Lift, Region, TyCtxt};
|
||||
//! This module handles the relationships between "free regions", i.e., lifetime parameters.
|
||||
//! Ordinarily, free regions are unrelated to one another, but they can be related via implied
|
||||
//! or explicit bounds. In that case, we track the bounds using the `TransitiveRelation` type,
|
||||
//! and use that to decide when one free region outlives another, and so forth.
|
||||
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::ty::{self, Lift, Region, TyCtxt};
|
||||
|
||||
/// Combines a `region::ScopeTree` (which governs relationships between
|
||||
/// scopes) and a `FreeRegionMap` (which governs relationships between
|
||||
/// free regions) to yield a complete relation between concrete
|
||||
/// regions.
|
||||
///
|
||||
/// This stuff is a bit convoluted and should be refactored, but as we
|
||||
/// transition to NLL, it'll all go away anyhow.
|
||||
pub struct RegionRelations<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
/// The context used to fetch the region maps.
|
||||
pub context: DefId,
|
||||
|
||||
/// The region maps for the given context.
|
||||
pub region_scope_tree: &'a region::ScopeTree,
|
||||
|
||||
/// Free-region relationships.
|
||||
pub free_regions: &'a FreeRegionMap<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
context: DefId,
|
||||
region_scope_tree: &'a region::ScopeTree,
|
||||
free_regions: &'a FreeRegionMap<'tcx>,
|
||||
) -> Self {
|
||||
Self { tcx, context, region_scope_tree, free_regions }
|
||||
}
|
||||
|
||||
pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
|
||||
self.free_regions.lub_free_regions(self.tcx, r_a, r_b)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default, HashStable)]
|
||||
pub struct FreeRegionMap<'tcx> {
|
@ -10,10 +10,10 @@ use graphviz as dot;
|
||||
|
||||
use super::Constraint;
|
||||
use crate::infer::region_constraints::RegionConstraintData;
|
||||
use crate::infer::RegionRelations;
|
||||
use crate::infer::SubregionOrigin;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::def_id::DefIndex;
|
||||
use rustc_middle::middle::free_region::RegionRelations;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::ty;
|
||||
|
||||
|
@ -6,6 +6,7 @@ use crate::infer::region_constraints::MemberConstraint;
|
||||
use crate::infer::region_constraints::RegionConstraintData;
|
||||
use crate::infer::region_constraints::VarInfos;
|
||||
use crate::infer::region_constraints::VerifyBound;
|
||||
use crate::infer::RegionRelations;
|
||||
use crate::infer::RegionVariableOrigin;
|
||||
use crate::infer::RegionckMode;
|
||||
use crate::infer::SubregionOrigin;
|
||||
@ -14,7 +15,6 @@ use rustc_data_structures::graph::implementation::{
|
||||
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_middle::middle::free_region::RegionRelations;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
|
||||
|
@ -18,7 +18,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
||||
use rustc_middle::middle::free_region::RegionRelations;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::ConstEvalResult;
|
||||
@ -39,6 +38,7 @@ use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
use self::combine::CombineFields;
|
||||
use self::free_regions::RegionRelations;
|
||||
use self::lexical_region_resolve::LexicalRegionResolutions;
|
||||
use self::outlives::env::OutlivesEnvironment;
|
||||
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
|
||||
@ -50,6 +50,7 @@ pub mod canonical;
|
||||
mod combine;
|
||||
mod equate;
|
||||
pub mod error_reporting;
|
||||
pub mod free_regions;
|
||||
mod freshen;
|
||||
mod fudge;
|
||||
mod glb;
|
||||
@ -472,6 +473,9 @@ pub enum NLLRegionVariableOrigin {
|
||||
/// from a `for<'a> T` binder). Meant to represent "any region".
|
||||
Placeholder(ty::PlaceholderRegion),
|
||||
|
||||
/// The variable we create to represent `'empty(U0)`.
|
||||
RootEmptyRegion,
|
||||
|
||||
Existential {
|
||||
/// If this is true, then this variable was created to represent a lifetime
|
||||
/// bound in a `for` binder. For example, it might have been created to
|
||||
@ -493,6 +497,7 @@ impl NLLRegionVariableOrigin {
|
||||
NLLRegionVariableOrigin::FreeRegion => true,
|
||||
NLLRegionVariableOrigin::Placeholder(..) => true,
|
||||
NLLRegionVariableOrigin::Existential { .. } => false,
|
||||
NLLRegionVariableOrigin::RootEmptyRegion => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::infer::free_regions::FreeRegionMap;
|
||||
use crate::infer::{GenericKind, InferCtxt};
|
||||
use crate::traits::query::OutlivesBound;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::free_region_map::FreeRegionMap;
|
||||
|
||||
use super::explicit_outlives_bounds;
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
//! This module handles the relationships between "free regions", i.e., lifetime parameters.
|
||||
//! Ordinarily, free regions are unrelated to one another, but they can be related via implied
|
||||
//! or explicit bounds. In that case, we track the bounds using the `TransitiveRelation` type,
|
||||
//! and use that to decide when one free region outlives another, and so forth.
|
||||
|
||||
use crate::middle::region;
|
||||
use crate::ty::free_region_map::FreeRegionMap;
|
||||
use crate::ty::{Region, TyCtxt};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
/// Combines a `region::ScopeTree` (which governs relationships between
|
||||
/// scopes) and a `FreeRegionMap` (which governs relationships between
|
||||
/// free regions) to yield a complete relation between concrete
|
||||
/// regions.
|
||||
///
|
||||
/// This stuff is a bit convoluted and should be refactored, but as we
|
||||
/// transition to NLL, it'll all go away anyhow.
|
||||
pub struct RegionRelations<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
/// The context used to fetch the region maps.
|
||||
pub context: DefId,
|
||||
|
||||
/// The region maps for the given context.
|
||||
pub region_scope_tree: &'a region::ScopeTree,
|
||||
|
||||
/// Free-region relationships.
|
||||
pub free_regions: &'a FreeRegionMap<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
context: DefId,
|
||||
region_scope_tree: &'a region::ScopeTree,
|
||||
free_regions: &'a FreeRegionMap<'tcx>,
|
||||
) -> Self {
|
||||
Self { tcx, context, region_scope_tree, free_regions }
|
||||
}
|
||||
|
||||
pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
|
||||
self.free_regions.lub_free_regions(self.tcx, r_a, r_b)
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ pub mod codegen_fn_attrs;
|
||||
pub mod cstore;
|
||||
pub mod dependency_format;
|
||||
pub mod exported_symbols;
|
||||
pub mod free_region;
|
||||
pub mod lang_items;
|
||||
pub mod lib_features {
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
@ -96,7 +96,6 @@ pub mod error;
|
||||
pub mod fast_reject;
|
||||
pub mod flags;
|
||||
pub mod fold;
|
||||
pub mod free_region_map;
|
||||
pub mod inhabitedness;
|
||||
pub mod layout;
|
||||
pub mod normalize_erasing_regions;
|
||||
|
@ -6,7 +6,6 @@ use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
|
||||
@ -315,16 +314,81 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// SCC could have as well. This implies that the SCC must have
|
||||
/// the minimum, or narrowest, universe.
|
||||
fn compute_scc_universes(
|
||||
constraints_scc: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
constraint_sccs: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> IndexVec<ConstraintSccIndex, ty::UniverseIndex> {
|
||||
let num_sccs = constraints_scc.num_sccs();
|
||||
let num_sccs = constraint_sccs.num_sccs();
|
||||
let mut scc_universes = IndexVec::from_elem_n(ty::UniverseIndex::MAX, num_sccs);
|
||||
|
||||
debug!("compute_scc_universes()");
|
||||
|
||||
// For each region R in universe U, ensure that the universe for the SCC
|
||||
// that contains R is "no bigger" than U. This effectively sets the universe
|
||||
// for each SCC to be the minimum of the regions within.
|
||||
for (region_vid, region_definition) in definitions.iter_enumerated() {
|
||||
let scc = constraints_scc.scc(region_vid);
|
||||
let scc = constraint_sccs.scc(region_vid);
|
||||
let scc_universe = &mut scc_universes[scc];
|
||||
*scc_universe = ::std::cmp::min(*scc_universe, region_definition.universe);
|
||||
let scc_min = std::cmp::min(region_definition.universe, *scc_universe);
|
||||
if scc_min != *scc_universe {
|
||||
*scc_universe = scc_min;
|
||||
debug!(
|
||||
"compute_scc_universes: lowered universe of {scc:?} to {scc_min:?} \
|
||||
because it contains {region_vid:?} in {region_universe:?}",
|
||||
scc = scc,
|
||||
scc_min = scc_min,
|
||||
region_vid = region_vid,
|
||||
region_universe = region_definition.universe,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Walk each SCC `A` and `B` such that `A: B`
|
||||
// and ensure that universe(A) can see universe(B).
|
||||
//
|
||||
// This serves to enforce the 'empty/placeholder' hierarchy
|
||||
// (described in more detail on `RegionKind`):
|
||||
//
|
||||
// ```
|
||||
// static -----+
|
||||
// | |
|
||||
// empty(U0) placeholder(U1)
|
||||
// | /
|
||||
// empty(U1)
|
||||
// ```
|
||||
//
|
||||
// In particular, imagine we have variables R0 in U0 and R1
|
||||
// created in U1, and constraints like this;
|
||||
//
|
||||
// ```
|
||||
// R1: !1 // R1 outlives the placeholder in U1
|
||||
// R1: R0 // R1 outlives R0
|
||||
// ```
|
||||
//
|
||||
// Here, we wish for R1 to be `'static`, because it
|
||||
// cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
|
||||
//
|
||||
// Thanks to this loop, what happens is that the `R1: R0`
|
||||
// constraint lowers the universe of `R1` to `U0`, which in turn
|
||||
// means that the `R1: !1` constraint will (later) cause
|
||||
// `R1` to become `'static`.
|
||||
for scc_a in constraint_sccs.all_sccs() {
|
||||
for &scc_b in constraint_sccs.successors(scc_a) {
|
||||
let scc_universe_a = scc_universes[scc_a];
|
||||
let scc_universe_b = scc_universes[scc_b];
|
||||
let scc_universe_min = std::cmp::min(scc_universe_a, scc_universe_b);
|
||||
if scc_universe_a != scc_universe_min {
|
||||
scc_universes[scc_a] = scc_universe_min;
|
||||
|
||||
debug!(
|
||||
"compute_scc_universes: lowered universe of {scc_a:?} to {scc_universe_min:?} \
|
||||
because {scc_a:?}: {scc_b:?} and {scc_b:?} is in universe {scc_universe_b:?}",
|
||||
scc_a = scc_a,
|
||||
scc_b = scc_b,
|
||||
scc_universe_min = scc_universe_min,
|
||||
scc_universe_b = scc_universe_b
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("compute_scc_universes: scc_universe = {:#?}", scc_universes);
|
||||
@ -416,7 +480,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
NLLRegionVariableOrigin::Existential { .. } => {
|
||||
NLLRegionVariableOrigin::RootEmptyRegion
|
||||
| NLLRegionVariableOrigin::Existential { .. } => {
|
||||
// For existential, regions, nothing to do.
|
||||
}
|
||||
}
|
||||
@ -550,9 +615,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// SCC. For each SCC, we visit its successors and compute
|
||||
// their values, then we union all those values to get our
|
||||
// own.
|
||||
let visited = &mut BitSet::new_empty(self.constraint_sccs.num_sccs());
|
||||
for scc_index in self.constraint_sccs.all_sccs() {
|
||||
self.propagate_constraint_sccs_if_new(scc_index, visited);
|
||||
let constraint_sccs = self.constraint_sccs.clone();
|
||||
for scc in constraint_sccs.all_sccs() {
|
||||
self.compute_value_for_scc(scc);
|
||||
}
|
||||
|
||||
// Sort the applied member constraints so we can binary search
|
||||
@ -560,37 +625,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.member_constraints_applied.sort_by_key(|applied| applied.member_region_scc);
|
||||
}
|
||||
|
||||
/// Computes the value of the SCC `scc_a` if it has not already
|
||||
/// been computed. The `visited` parameter is a bitset
|
||||
#[inline]
|
||||
fn propagate_constraint_sccs_if_new(
|
||||
&mut self,
|
||||
scc_a: ConstraintSccIndex,
|
||||
visited: &mut BitSet<ConstraintSccIndex>,
|
||||
) {
|
||||
if visited.insert(scc_a) {
|
||||
self.propagate_constraint_sccs_new(scc_a, visited);
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the value of the SCC `scc_a`, which has not yet been
|
||||
/// computed. This works by first computing all successors of the
|
||||
/// SCC (if they haven't been computed already) and then unioning
|
||||
/// together their elements.
|
||||
fn propagate_constraint_sccs_new(
|
||||
&mut self,
|
||||
scc_a: ConstraintSccIndex,
|
||||
visited: &mut BitSet<ConstraintSccIndex>,
|
||||
) {
|
||||
/// computed, by unioning the values of its successors.
|
||||
/// Assumes that all successors have been computed already
|
||||
/// (which is assured by iterating over SCCs in dependency order).
|
||||
fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) {
|
||||
let constraint_sccs = self.constraint_sccs.clone();
|
||||
|
||||
// Walk each SCC `B` such that `A: B`...
|
||||
for &scc_b in constraint_sccs.successors(scc_a) {
|
||||
debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
|
||||
|
||||
// ...compute the value of `B`...
|
||||
self.propagate_constraint_sccs_if_new(scc_b, visited);
|
||||
|
||||
// ...and add elements from `B` into `A`. One complication
|
||||
// arises because of universes: If `B` contains something
|
||||
// that `A` cannot name, then `A` can only contain `B` if
|
||||
@ -1258,7 +1303,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.check_bound_universal_region(fr, placeholder, errors_buffer);
|
||||
}
|
||||
|
||||
NLLRegionVariableOrigin::Existential { .. } => {
|
||||
NLLRegionVariableOrigin::RootEmptyRegion
|
||||
| NLLRegionVariableOrigin::Existential { .. } => {
|
||||
// nothing to check here
|
||||
}
|
||||
}
|
||||
@ -1360,7 +1406,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.check_bound_universal_region(fr, placeholder, errors_buffer);
|
||||
}
|
||||
|
||||
NLLRegionVariableOrigin::Existential { .. } => {
|
||||
NLLRegionVariableOrigin::RootEmptyRegion
|
||||
| NLLRegionVariableOrigin::Existential { .. } => {
|
||||
// nothing to check here
|
||||
}
|
||||
}
|
||||
@ -1633,9 +1680,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
universe1.cannot_name(placeholder.universe)
|
||||
}
|
||||
|
||||
NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => {
|
||||
false
|
||||
}
|
||||
NLLRegionVariableOrigin::RootEmptyRegion
|
||||
| NLLRegionVariableOrigin::FreeRegion
|
||||
| NLLRegionVariableOrigin::Existential { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1773,6 +1820,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Finds some region R such that `fr1: R` and `R` is live at `elem`.
|
||||
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
|
||||
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
|
||||
debug!("find_sub_region_live_at: {:?} is in scc {:?}", fr1, self.constraint_sccs.scc(fr1));
|
||||
debug!(
|
||||
"find_sub_region_live_at: {:?} is in universe {:?}",
|
||||
fr1,
|
||||
self.scc_universes[self.constraint_sccs.scc(fr1)]
|
||||
);
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
// First look for some `r` such that `fr1: r` and `r` is live at `elem`
|
||||
debug!(
|
||||
@ -1794,13 +1847,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.or_else(|| {
|
||||
// If we fail to find THAT, it may be that `fr1` is a
|
||||
// placeholder that cannot "fit" into its SCC. In that
|
||||
// case, there should be some `r` where `fr1: r`, both
|
||||
// `fr1` and `r` are in the same SCC, and `fr1` is a
|
||||
// case, there should be some `r` where `fr1: r` and `fr1` is a
|
||||
// placeholder that `r` cannot name. We can blame that
|
||||
// edge.
|
||||
//
|
||||
// Remember that if `R1: R2`, then the universe of R1
|
||||
// must be able to name the universe of R2, because R2 will
|
||||
// be at least `'empty(Universe(R2))`, and `R1` must be at
|
||||
// larger than that.
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r)
|
||||
&& self.cannot_name_placeholder(r, fr1)
|
||||
self.cannot_name_placeholder(r, fr1)
|
||||
})
|
||||
})
|
||||
.map(|(_path, r)| r)
|
||||
@ -1944,7 +2000,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let blame_source = match from_region_origin {
|
||||
NLLRegionVariableOrigin::FreeRegion
|
||||
| NLLRegionVariableOrigin::Existential { from_forall: false } => true,
|
||||
NLLRegionVariableOrigin::Placeholder(_)
|
||||
NLLRegionVariableOrigin::RootEmptyRegion
|
||||
| NLLRegionVariableOrigin::Placeholder(_)
|
||||
| NLLRegionVariableOrigin::Existential { from_forall: true } => false,
|
||||
};
|
||||
|
||||
|
@ -160,10 +160,6 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
) {
|
||||
// FIXME -- this is not the fix I would prefer
|
||||
if let ty::ReEmpty(ty::UniverseIndex::ROOT) = a {
|
||||
return;
|
||||
}
|
||||
let b = self.to_region_vid(b);
|
||||
let a = self.to_region_vid(a);
|
||||
self.add_outlives(b, a);
|
||||
@ -176,10 +172,6 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
|
||||
a: ty::Region<'tcx>,
|
||||
bound: VerifyBound<'tcx>,
|
||||
) {
|
||||
// FIXME: I'd prefer if NLL had a notion of empty
|
||||
if let ty::ReEmpty(ty::UniverseIndex::ROOT) = a {
|
||||
return;
|
||||
}
|
||||
let type_test = self.verify_to_type_test(kind, a, bound);
|
||||
self.add_type_test(type_test);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::free_regions::FreeRegionRelations;
|
||||
use rustc_infer::infer::outlives;
|
||||
use rustc_infer::infer::region_constraints::GenericKind;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty::free_region_map::FreeRegionRelations;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||
|
@ -54,6 +54,13 @@ pub struct UniversalRegions<'tcx> {
|
||||
/// The total number of universal region variables instantiated.
|
||||
num_universals: usize,
|
||||
|
||||
/// A special region variable created for the `'empty(U0)` region.
|
||||
/// Note that this is **not** a "universal" region, as it doesn't
|
||||
/// represent a universally bound placeholder or any such thing.
|
||||
/// But we do create it here in this type because it's a useful region
|
||||
/// to have around in a few limited cases.
|
||||
pub root_empty: RegionVid,
|
||||
|
||||
/// The "defining" type for this function, with all universal
|
||||
/// regions instantiated. For a closure or generator, this is the
|
||||
/// closure type, but for a top-level function it's the `FnDef`.
|
||||
@ -317,7 +324,11 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
|
||||
/// See `UniversalRegionIndices::to_region_vid`.
|
||||
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
self.indices.to_region_vid(r)
|
||||
if let ty::ReEmpty(ty::UniverseIndex::ROOT) = r {
|
||||
self.root_empty
|
||||
} else {
|
||||
self.indices.to_region_vid(r)
|
||||
}
|
||||
}
|
||||
|
||||
/// As part of the NLL unit tests, you can annotate a function with
|
||||
@ -473,10 +484,16 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let root_empty = self
|
||||
.infcx
|
||||
.next_nll_region_var(NLLRegionVariableOrigin::RootEmptyRegion)
|
||||
.to_region_vid();
|
||||
|
||||
UniversalRegions {
|
||||
indices,
|
||||
fr_static,
|
||||
fr_fn_body,
|
||||
root_empty,
|
||||
first_extern_index,
|
||||
first_local_index,
|
||||
num_universals,
|
||||
|
@ -1549,6 +1549,11 @@ impl<'a> Parser<'a> {
|
||||
let block = self.parse_block().map_err(|mut err| {
|
||||
if not_block {
|
||||
err.span_label(lo, "this `if` expression has a condition, but no block");
|
||||
if let ExprKind::Binary(_, _, ref right) = cond.kind {
|
||||
if let ExprKind::Block(_, _) = right.kind {
|
||||
err.help("maybe you forgot the right operand of the condition?");
|
||||
}
|
||||
}
|
||||
}
|
||||
err
|
||||
})?;
|
||||
|
@ -6,10 +6,10 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::free_regions::FreeRegionRelations;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{self, InferCtxt, InferOk};
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use rustc_middle::ty::free_region_map::FreeRegionRelations;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
|
||||
use rustc_session::config::nightly_options;
|
||||
|
@ -13,10 +13,11 @@
|
||||
| '_#2r | U0 | {bb0[0..=1], '_#2r}
|
||||
| '_#3r | U0 | {bb0[0..=1], '_#3r}
|
||||
| '_#4r | U0 | {bb0[0..=1], '_#4r}
|
||||
| '_#5r | U0 | {bb0[0..=1], '_#1r}
|
||||
| '_#6r | U0 | {bb0[0..=1], '_#2r}
|
||||
| '_#7r | U0 | {bb0[0..=1], '_#1r}
|
||||
| '_#8r | U0 | {bb0[0..=1], '_#3r}
|
||||
| '_#5r | U0 | {}
|
||||
| '_#6r | U0 | {bb0[0..=1], '_#1r}
|
||||
| '_#7r | U0 | {bb0[0..=1], '_#2r}
|
||||
| '_#8r | U0 | {bb0[0..=1], '_#1r}
|
||||
| '_#9r | U0 | {bb0[0..=1], '_#3r}
|
||||
|
|
||||
| Inference Constraints
|
||||
| '_#0r live at {bb0[0..=1]}
|
||||
@ -24,16 +25,16 @@
|
||||
| '_#2r live at {bb0[0..=1]}
|
||||
| '_#3r live at {bb0[0..=1]}
|
||||
| '_#4r live at {bb0[0..=1]}
|
||||
| '_#1r: '_#5r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
|
||||
| '_#1r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
|
||||
| '_#2r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
|
||||
| '_#3r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
|
||||
| '_#5r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
|
||||
| '_#6r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
|
||||
| '_#7r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
|
||||
| '_#8r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
|
||||
| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
|
||||
| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
|
||||
| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
|
||||
| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
|
||||
| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
|
||||
| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
|
||||
| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
|
||||
| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
|
||||
|
|
||||
fn use_x(_1: &'_#5r mut i32, _2: &'_#6r u32, _3: &'_#7r u32, _4: &'_#8r u32) -> bool {
|
||||
fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> bool {
|
||||
debug w => _1; // in scope 0 at $DIR/named-lifetimes-basic.rs:12:26: 12:27
|
||||
debug x => _2; // in scope 0 at $DIR/named-lifetimes-basic.rs:12:42: 12:43
|
||||
debug y => _3; // in scope 0 at $DIR/named-lifetimes-basic.rs:12:54: 12:55
|
||||
|
@ -7,7 +7,9 @@
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
fn use_x(_: usize) -> bool { true }
|
||||
fn use_x(_: usize) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
// EMIT_MIR rustc.main.nll.0.mir
|
||||
|
@ -7,164 +7,165 @@
|
||||
| Inferred Region Values
|
||||
| '_#0r | U0 | {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5], '_#0r, '_#1r}
|
||||
| '_#1r | U0 | {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5], '_#1r}
|
||||
| '_#2r | U0 | {bb2[0..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#3r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#2r | U0 | {}
|
||||
| '_#3r | U0 | {bb2[0..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#4r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#5r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
|
|
||||
| Inference Constraints
|
||||
| '_#0r live at {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5]}
|
||||
| '_#1r live at {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5]}
|
||||
| '_#2r live at {bb2[0]}
|
||||
| '_#3r live at {bb2[1..=3]}
|
||||
| '_#4r live at {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#2r: '_#3r due to Assignment at Single(bb2[0])
|
||||
| '_#3r: '_#4r due to Assignment at Single(bb2[3])
|
||||
| '_#3r live at {bb2[0]}
|
||||
| '_#4r live at {bb2[1..=3]}
|
||||
| '_#5r live at {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#3r: '_#4r due to Assignment at Single(bb2[0])
|
||||
| '_#4r: '_#5r due to Assignment at Single(bb2[3])
|
||||
|
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:14:11: 14:11
|
||||
let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
|
||||
let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
scope 1 {
|
||||
debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
let _2: &'_#3r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
let _2: &'_#4r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
scope 2 {
|
||||
debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
let _6: &'_#4r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
let _6: &'_#5r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
scope 3 {
|
||||
debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
_1 = [const Const(Value(Scalar(0x00000001)): usize), const Const(Value(Scalar(0x00000002)): usize), const Const(Value(Scalar(0x00000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:15:17: 15:26
|
||||
StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
_1 = [const Const(Value(Scalar(0x00000001)): usize), const Const(Value(Scalar(0x00000002)): usize), const Const(Value(Scalar(0x00000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:18: 15:19
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:18: 17:19
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000002))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:21: 15:22
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:21: 17:22
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000003))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:24: 15:25
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:24: 17:25
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
|
||||
FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
_3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
_3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
|
||||
_4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
_5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
_4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
_5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
}
|
||||
|
||||
bb1 (cleanup): {
|
||||
resume; // bb1[0]: scope 0 at $DIR/region-subtyping-basic.rs:14:1: 23:2
|
||||
resume; // bb1[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_2 = &'_#2r _1[_3]; // bb2[0]: scope 1 at $DIR/region-subtyping-basic.rs:16:13: 16:18
|
||||
FakeRead(ForLet, _2); // bb2[1]: scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
StorageLive(_6); // bb2[2]: scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
_6 = _2; // bb2[3]: scope 2 at $DIR/region-subtyping-basic.rs:17:13: 17:14
|
||||
FakeRead(ForLet, _6); // bb2[4]: scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
StorageLive(_7); // bb2[5]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
_7 = const Const(Value(Scalar(0x01)): bool); // bb2[6]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
_2 = &'_#3r _1[_3]; // bb2[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18
|
||||
FakeRead(ForLet, _2); // bb2[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
StorageLive(_6); // bb2[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
_6 = _2; // bb2[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14
|
||||
FakeRead(ForLet, _6); // bb2[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
StorageLive(_7); // bb2[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
_7 = const Const(Value(Scalar(0x01)): bool); // bb2[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
// ty::Const
|
||||
// + ty: bool
|
||||
// + val: Value(Scalar(0x01))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
// + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
FakeRead(ForMatchedPlace, _7); // bb2[7]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb3]; // bb2[8]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
FakeRead(ForMatchedPlace, _7); // bb2[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb3]; // bb2[8]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb3: {
|
||||
falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
_10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
_10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000016))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:23:15: 23:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000016)) }
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_8); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
StorageLive(_9); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
_9 = (*_6); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
_8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x00000016))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x00000016)) }
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_8); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
StorageLive(_9); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
_9 = (*_6); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
_8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:19:9: 19:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_9); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:19:17: 19:18
|
||||
StorageDead(_8); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:19:18: 19:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:18:13: 20:6
|
||||
StorageDead(_9); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
|
||||
StorageDead(_8); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:13: 20:6
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:13: 22:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
goto -> bb8; // bb6[3]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
goto -> bb8; // bb6[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_10); // bb7[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb7[1]: scope 3 at $DIR/region-subtyping-basic.rs:20:12: 22:6
|
||||
StorageDead(_10); // bb7[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb7[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:12: 22:6
|
||||
// + span: $DIR/region-subtyping-basic.rs:22:12: 24:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
goto -> bb8; // bb7[2]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
goto -> bb8; // bb7[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageDead(_6); // bb8[0]: scope 2 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_3); // bb8[1]: scope 1 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_2); // bb8[2]: scope 1 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_1); // bb8[3]: scope 0 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_7); // bb8[4]: scope 0 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
return; // bb8[5]: scope 0 at $DIR/region-subtyping-basic.rs:23:2: 23:2
|
||||
StorageDead(_6); // bb8[0]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_3); // bb8[1]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_2); // bb8[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_1); // bb8[3]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_7); // bb8[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
return; // bb8[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
|
||||
}
|
||||
}
|
||||
|
@ -7,164 +7,165 @@
|
||||
| Inferred Region Values
|
||||
| '_#0r | U0 | {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5], '_#0r, '_#1r}
|
||||
| '_#1r | U0 | {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5], '_#1r}
|
||||
| '_#2r | U0 | {bb2[0..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#3r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#2r | U0 | {}
|
||||
| '_#3r | U0 | {bb2[0..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#4r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#5r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
|
|
||||
| Inference Constraints
|
||||
| '_#0r live at {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5]}
|
||||
| '_#1r live at {bb0[0..=8], bb1[0], bb2[0..=8], bb3[0], bb4[0..=1], bb5[0..=3], bb6[0..=3], bb7[0..=2], bb8[0..=5]}
|
||||
| '_#2r live at {bb2[0]}
|
||||
| '_#3r live at {bb2[1..=3]}
|
||||
| '_#4r live at {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#2r: '_#3r due to Assignment at Single(bb2[0])
|
||||
| '_#3r: '_#4r due to Assignment at Single(bb2[3])
|
||||
| '_#3r live at {bb2[0]}
|
||||
| '_#4r live at {bb2[1..=3]}
|
||||
| '_#5r live at {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||
| '_#3r: '_#4r due to Assignment at Single(bb2[0])
|
||||
| '_#4r: '_#5r due to Assignment at Single(bb2[3])
|
||||
|
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:14:11: 14:11
|
||||
let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
|
||||
let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
let mut _7: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
let _8: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
let mut _9: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
let _10: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
scope 1 {
|
||||
debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
let _2: &'_#3r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
debug v => _1; // in scope 1 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
let _2: &'_#4r usize; // in scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
scope 2 {
|
||||
debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
let _6: &'_#4r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
debug p => _2; // in scope 2 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
let _6: &'_#5r usize; // in scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
scope 3 {
|
||||
debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
debug q => _6; // in scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
_1 = [const Const(Value(Scalar(0x0000000000000001)): usize), const Const(Value(Scalar(0x0000000000000002)): usize), const Const(Value(Scalar(0x0000000000000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:15:17: 15:26
|
||||
StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
_1 = [const Const(Value(Scalar(0x0000000000000001)): usize), const Const(Value(Scalar(0x0000000000000002)): usize), const Const(Value(Scalar(0x0000000000000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000001))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:18: 15:19
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:18: 17:19
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000002))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:21: 15:22
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:21: 17:22
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000003))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:15:24: 15:25
|
||||
// + span: $DIR/region-subtyping-basic.rs:17:24: 17:25
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
|
||||
FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:15:9: 15:14
|
||||
StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
_3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||
StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
_3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:16:16: 16:17
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
|
||||
_4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
_5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18
|
||||
_4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
_5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||
}
|
||||
|
||||
bb1 (cleanup): {
|
||||
resume; // bb1[0]: scope 0 at $DIR/region-subtyping-basic.rs:14:1: 23:2
|
||||
resume; // bb1[0]: scope 0 at $DIR/region-subtyping-basic.rs:16:1: 25:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_2 = &'_#2r _1[_3]; // bb2[0]: scope 1 at $DIR/region-subtyping-basic.rs:16:13: 16:18
|
||||
FakeRead(ForLet, _2); // bb2[1]: scope 1 at $DIR/region-subtyping-basic.rs:16:9: 16:10
|
||||
StorageLive(_6); // bb2[2]: scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
_6 = _2; // bb2[3]: scope 2 at $DIR/region-subtyping-basic.rs:17:13: 17:14
|
||||
FakeRead(ForLet, _6); // bb2[4]: scope 2 at $DIR/region-subtyping-basic.rs:17:9: 17:10
|
||||
StorageLive(_7); // bb2[5]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
_7 = const Const(Value(Scalar(0x01)): bool); // bb2[6]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
_2 = &'_#3r _1[_3]; // bb2[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18
|
||||
FakeRead(ForLet, _2); // bb2[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
|
||||
StorageLive(_6); // bb2[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
_6 = _2; // bb2[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14
|
||||
FakeRead(ForLet, _6); // bb2[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||
StorageLive(_7); // bb2[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
_7 = const Const(Value(Scalar(0x01)): bool); // bb2[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
// ty::Const
|
||||
// + ty: bool
|
||||
// + val: Value(Scalar(0x01))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
// + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
FakeRead(ForMatchedPlace, _7); // bb2[7]: scope 3 at $DIR/region-subtyping-basic.rs:18:8: 18:12
|
||||
switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb3]; // bb2[8]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
FakeRead(ForMatchedPlace, _7); // bb2[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||
switchInt(_7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb3]; // bb2[8]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb3: {
|
||||
falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
_10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
_10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000016))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:23:15: 23:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000016)) }
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_8); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
StorageLive(_9); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
_9 = (*_6); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
_8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
// ty::Const
|
||||
// + ty: usize
|
||||
// + val: Value(Scalar(0x0000000000000016))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:21:15: 21:17
|
||||
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000016)) }
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_8); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
StorageLive(_9); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
_9 = (*_6); // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:19:15: 19:17
|
||||
_8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:19:9: 19:18
|
||||
// ty::Const
|
||||
// + ty: fn(usize) -> bool {use_x}
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:19:9: 19:14
|
||||
// + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_9); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:19:17: 19:18
|
||||
StorageDead(_8); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:19:18: 19:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:18:13: 20:6
|
||||
StorageDead(_9); // bb6[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
|
||||
StorageDead(_8); // bb6[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb6[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:18:13: 20:6
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:13: 22:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
goto -> bb8; // bb6[3]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
goto -> bb8; // bb6[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_10); // bb7[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb7[1]: scope 3 at $DIR/region-subtyping-basic.rs:20:12: 22:6
|
||||
StorageDead(_10); // bb7[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19
|
||||
_0 = const Const(Value(Scalar(<ZST>)): ()); // bb7[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/region-subtyping-basic.rs:20:12: 22:6
|
||||
// + span: $DIR/region-subtyping-basic.rs:22:12: 24:6
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
goto -> bb8; // bb7[2]: scope 3 at $DIR/region-subtyping-basic.rs:18:5: 22:6
|
||||
goto -> bb8; // bb7[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageDead(_6); // bb8[0]: scope 2 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_3); // bb8[1]: scope 1 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_2); // bb8[2]: scope 1 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_1); // bb8[3]: scope 0 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
StorageDead(_7); // bb8[4]: scope 0 at $DIR/region-subtyping-basic.rs:23:1: 23:2
|
||||
return; // bb8[5]: scope 0 at $DIR/region-subtyping-basic.rs:23:2: 23:2
|
||||
StorageDead(_6); // bb8[0]: scope 2 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_3); // bb8[1]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_2); // bb8[2]: scope 1 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_1); // bb8[3]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
StorageDead(_7); // bb8[4]: scope 0 at $DIR/region-subtyping-basic.rs:25:1: 25:2
|
||||
return; // bb8[5]: scope 0 at $DIR/region-subtyping-basic.rs:25:2: 25:2
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,16 @@
|
||||
| Inferred Region Values
|
||||
| '_#0r | U0 | {bb0[0..=22], '_#0r, '_#1r}
|
||||
| '_#1r | U0 | {bb0[0..=22], '_#1r}
|
||||
| '_#2r | U0 | {bb0[10..=11]}
|
||||
| '_#3r | U0 | {bb0[11]}
|
||||
| '_#2r | U0 | {}
|
||||
| '_#3r | U0 | {bb0[10..=11]}
|
||||
| '_#4r | U0 | {bb0[11]}
|
||||
|
|
||||
| Inference Constraints
|
||||
| '_#0r live at {bb0[0..=22]}
|
||||
| '_#1r live at {bb0[0..=22]}
|
||||
| '_#2r live at {bb0[10]}
|
||||
| '_#3r live at {bb0[11]}
|
||||
| '_#2r: '_#3r due to Assignment at Single(bb0[10])
|
||||
| '_#3r live at {bb0[10]}
|
||||
| '_#4r live at {bb0[11]}
|
||||
| '_#3r: '_#4r due to Assignment at Single(bb0[10])
|
||||
|
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/storage_ranges.rs:3:11: 3:11
|
||||
|
@ -34,7 +34,7 @@ LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#4r
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#5r
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
||||
@ -48,7 +48,7 @@ LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#5r
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#6r
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -8,9 +8,9 @@ use test::black_box as b; // prevent promotion of the argument and const-propaga
|
||||
use std::ptr::Unique;
|
||||
|
||||
|
||||
const PTR: *mut u32 = Unique::empty().as_ptr();
|
||||
const PTR: *mut u32 = Unique::dangling().as_ptr();
|
||||
|
||||
pub fn main() {
|
||||
// Be super-extra paranoid and cast the fn items to fn pointers before blackboxing them.
|
||||
assert_eq!(PTR, b::<fn() -> _>(Unique::<u32>::empty)().as_ptr());
|
||||
assert_eq!(PTR, b::<fn() -> _>(Unique::<u32>::dangling)().as_ptr());
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ error: higher-ranked subtype error
|
||||
--> $DIR/due-to-where-clause.rs:2:5
|
||||
|
|
||||
LL | test::<FooS>(&mut 42);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,6 +6,8 @@ LL | if 5 == {
|
||||
...
|
||||
LL | }
|
||||
| ^ expected `{`
|
||||
|
|
||||
= help: maybe you forgot the right operand of the condition?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime '_#8r
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime '_#9r
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime '_#5r
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime '_#6r
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
15
src/test/ui/nll/issue-68550.rs
Normal file
15
src/test/ui/nll/issue-68550.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Regression test for issue #68550.
|
||||
//
|
||||
// The `&'static A:` where clause was triggering
|
||||
// ICEs because it wound up being compiled to reference
|
||||
// the `'empty(U0)` region.
|
||||
|
||||
fn run<'a, A>(x: A)
|
||||
where
|
||||
A: 'static,
|
||||
&'static A: ,
|
||||
{
|
||||
let _: &'a A = &x; //~ ERROR `x` does not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
16
src/test/ui/nll/issue-68550.stderr
Normal file
16
src/test/ui/nll/issue-68550.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/issue-68550.rs:12:20
|
||||
|
|
||||
LL | fn run<'a, A>(x: A)
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | let _: &'a A = &x;
|
||||
| ----- ^^ borrowed value does not live long enough
|
||||
| |
|
||||
| type annotation requires that `x` is borrowed for `'a`
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
@ -0,0 +1,36 @@
|
||||
// Test that the NLL solver cannot find a solution
|
||||
// for `exists<R1> { forall<R1> { R2: R1 } }`.
|
||||
//
|
||||
// In this test, the impl should match `fn(T)` for some `T`,
|
||||
// but we ask it to match `for<'a> fn(&'a ())`. Due to argument
|
||||
// contravariance, this effectively requires a `T = &'b ()` where
|
||||
// `forall<'a> { 'a: 'b }`. Therefore, we get an error.
|
||||
//
|
||||
// Note the use of `-Zno-leak-check` and `feature(nll)` here. These
|
||||
// are presently required in order to skip the leak-check errors.
|
||||
//
|
||||
// c.f. Issue #57642.
|
||||
//
|
||||
// compile-flags:-Zno-leak-check
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
trait Y {
|
||||
type F;
|
||||
fn make_f() -> Self::F;
|
||||
}
|
||||
|
||||
impl<T> Y for fn(T) {
|
||||
type F = fn(T);
|
||||
|
||||
fn make_f() -> Self::F {
|
||||
|_| {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _x = <fn(&())>::make_f();
|
||||
//~^ higher-ranked subtype error
|
||||
//~| higher-ranked subtype error
|
||||
//~| higher-ranked subtype error
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
|
||||
|
|
||||
LL | let _x = <fn(&())>::make_f();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
|
||||
|
|
||||
LL | let _x = <fn(&())>::make_f();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
|
||||
|
|
||||
LL | let _x = <fn(&())>::make_f();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -21,13 +21,13 @@ fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
|
||||
}
|
||||
|
||||
fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
|
||||
// Ideally this should compile with the operands swapped as well, but HIR
|
||||
// type checking prevents it (and stops compilation) for now.
|
||||
f == g; // OK
|
||||
f == g;
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
}
|
||||
|
||||
fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
|
||||
f == g; // OK
|
||||
f == g;
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -76,5 +76,17 @@ LL | f == g;
|
||||
|
||||
help: `'a` and `'b` must be the same: replace one with the other
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/type-check-pointer-comparisons.rs:24:5
|
||||
|
|
||||
LL | f == g;
|
||||
| ^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/type-check-pointer-comparisons.rs:29:5
|
||||
|
|
||||
LL | f == g;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user