mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Auto merge of #69012 - Dylan-DPC:rollup-13qn0fq, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #68694 (Reduce the number of `RefCell`s in `InferCtxt`.) - #68966 (Improve performance of coherence checks) - #68976 (Make `num::NonZeroX::new` an unstable `const fn`) - #68992 (Correctly parse `mut a @ b`) - #69005 (Small graphviz improvements for the new dataflow framework) - #69006 (parser: Keep current and previous tokens precisely) Failed merges: r? @ghost
This commit is contained in:
@@ -69,8 +69,9 @@ impl $Ty {
|
||||
|
||||
/// Creates a non-zero if the given value is not zero.
|
||||
#[$stability]
|
||||
#[rustc_const_unstable(feature = "const_nonzero_int_methods", issue = "53718")]
|
||||
#[inline]
|
||||
pub fn new(n: $Int) -> Option<Self> {
|
||||
pub const fn new(n: $Int) -> Option<Self> {
|
||||
if n != 0 {
|
||||
// SAFETY: we just checked that there's no `0`
|
||||
Some(unsafe { Self(n) })
|
||||
|
||||
@@ -597,6 +597,8 @@ pub enum RenderOption {
|
||||
NoNodeLabels,
|
||||
NoEdgeStyles,
|
||||
NoNodeStyles,
|
||||
|
||||
Monospace,
|
||||
}
|
||||
|
||||
/// Returns vec holding all the default render options.
|
||||
@@ -626,6 +628,14 @@ pub fn render_opts<'a, N, E, G, W>(g: &'a G, w: &mut W, options: &[RenderOption]
|
||||
W: Write,
|
||||
{
|
||||
writeln!(w, "digraph {} {{", g.graph_id().as_slice())?;
|
||||
|
||||
// Global graph properties
|
||||
if options.contains(&RenderOption::Monospace) {
|
||||
writeln!(w, r#" graph[fontname="monospace"];"#)?;
|
||||
writeln!(w, r#" node[fontname="monospace"];"#)?;
|
||||
writeln!(w, r#" edge[fontname="monospace"];"#)?;
|
||||
}
|
||||
|
||||
for n in g.nodes().iter() {
|
||||
write!(w, " ")?;
|
||||
let id = g.node_id(n);
|
||||
|
||||
@@ -317,7 +317,9 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
let r = self
|
||||
.infcx
|
||||
.unwrap()
|
||||
.borrow_region_constraints()
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.tcx, vid);
|
||||
debug!(
|
||||
"canonical: region var found with vid {:?}, \
|
||||
@@ -621,7 +623,7 @@ fn canonical_var_for_region_in_root_universe(
|
||||
|
||||
/// Returns the universe in which `vid` is defined.
|
||||
fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
|
||||
self.infcx.unwrap().borrow_region_constraints().var_universe(vid)
|
||||
self.infcx.unwrap().inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
|
||||
}
|
||||
|
||||
/// Creates a canonical variable (with the given `info`)
|
||||
|
||||
@@ -74,8 +74,9 @@ pub fn super_combine_tys<R>(
|
||||
match (&a.kind, &b.kind) {
|
||||
// Relate integral variables to other types
|
||||
(&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
|
||||
self.int_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table
|
||||
.unify_var_var(a_id, b_id)
|
||||
.map_err(|e| int_unification_error(a_is_expected, e))?;
|
||||
Ok(a)
|
||||
@@ -95,8 +96,9 @@ pub fn super_combine_tys<R>(
|
||||
|
||||
// Relate floating-point variables to other types
|
||||
(&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
|
||||
self.float_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table
|
||||
.unify_var_var(a_id, b_id)
|
||||
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
|
||||
Ok(a)
|
||||
@@ -131,8 +133,8 @@ pub fn super_combine_consts<R>(
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
let a = replace_if_possible(self.const_unification_table.borrow_mut(), a);
|
||||
let b = replace_if_possible(self.const_unification_table.borrow_mut(), b);
|
||||
let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, a);
|
||||
let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, b);
|
||||
|
||||
let a_is_expected = relation.a_is_expected();
|
||||
|
||||
@@ -141,8 +143,9 @@ pub fn super_combine_consts<R>(
|
||||
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
||||
ty::ConstKind::Infer(InferConst::Var(b_vid)),
|
||||
) => {
|
||||
self.const_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table
|
||||
.unify_var_var(a_vid, b_vid)
|
||||
.map_err(|e| const_unification_error(a_is_expected, e))?;
|
||||
return Ok(a);
|
||||
@@ -174,8 +177,9 @@ pub fn unify_const_variable(
|
||||
vid: ty::ConstVid<'tcx>,
|
||||
value: &'tcx ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||
self.const_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table
|
||||
.unify_var_value(
|
||||
vid,
|
||||
ConstVarValue {
|
||||
@@ -196,8 +200,9 @@ fn unify_integral_variable(
|
||||
vid: ty::IntVid,
|
||||
val: ty::IntVarValue,
|
||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
self.int_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table
|
||||
.unify_var_value(vid, Some(val))
|
||||
.map_err(|e| int_unification_error(vid_is_expected, e))?;
|
||||
match val {
|
||||
@@ -212,8 +217,9 @@ fn unify_float_variable(
|
||||
vid: ty::FloatVid,
|
||||
val: ast::FloatTy,
|
||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
self.float_unification_table
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table
|
||||
.unify_var_value(vid, Some(ty::FloatVarValue(val)))
|
||||
.map_err(|e| float_unification_error(vid_is_expected, e))?;
|
||||
Ok(self.tcx.mk_mach_float(val))
|
||||
@@ -260,7 +266,7 @@ pub fn instantiate(
|
||||
use self::RelationDir::*;
|
||||
|
||||
// Get the actual variable that b_vid has been inferred to
|
||||
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_unknown());
|
||||
debug_assert!(self.infcx.inner.borrow_mut().type_variables.probe(b_vid).is_unknown());
|
||||
|
||||
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
|
||||
|
||||
@@ -280,7 +286,7 @@ pub fn instantiate(
|
||||
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
|
||||
a_ty, dir, b_vid, b_ty
|
||||
);
|
||||
self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty);
|
||||
self.infcx.inner.borrow_mut().type_variables.instantiate(b_vid, b_ty);
|
||||
|
||||
if needs_wf {
|
||||
self.obligations.push(Obligation::new(
|
||||
@@ -338,7 +344,7 @@ fn generalize(
|
||||
|
||||
debug!("generalize: ambient_variance = {:?}", ambient_variance);
|
||||
|
||||
let for_universe = match self.infcx.type_variables.borrow_mut().probe(for_vid) {
|
||||
let for_universe = match self.infcx.inner.borrow_mut().type_variables.probe(for_vid) {
|
||||
v @ TypeVariableValue::Known { .. } => {
|
||||
panic!("instantiating {:?} which has a known value {:?}", for_vid, v,)
|
||||
}
|
||||
@@ -350,7 +356,7 @@ fn generalize(
|
||||
let mut generalize = Generalizer {
|
||||
infcx: self.infcx,
|
||||
span: self.trace.cause.span,
|
||||
for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid),
|
||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables.sub_root_var(for_vid),
|
||||
for_universe,
|
||||
ambient_variance,
|
||||
needs_wf: false,
|
||||
@@ -502,17 +508,16 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
// us from creating infinitely sized types.
|
||||
match t.kind {
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let mut variables = self.infcx.type_variables.borrow_mut();
|
||||
let vid = variables.root_var(vid);
|
||||
let sub_vid = variables.sub_root_var(vid);
|
||||
let vid = self.infcx.inner.borrow_mut().type_variables.root_var(vid);
|
||||
let sub_vid = self.infcx.inner.borrow_mut().type_variables.sub_root_var(vid);
|
||||
if sub_vid == self.for_vid_sub_root {
|
||||
// If sub-roots are equal, then `for_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
Err(TypeError::CyclicTy(self.root_ty))
|
||||
} else {
|
||||
match variables.probe(vid) {
|
||||
let probe = self.infcx.inner.borrow_mut().type_variables.probe(vid);
|
||||
match probe {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
drop(variables);
|
||||
debug!("generalize: known value {:?}", u);
|
||||
self.relate(&u, &u)
|
||||
}
|
||||
@@ -536,8 +541,13 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
ty::Covariant | ty::Contravariant => (),
|
||||
}
|
||||
|
||||
let origin = *variables.var_origin(vid);
|
||||
let new_var_id = variables.new_var(self.for_universe, false, origin);
|
||||
let origin =
|
||||
*self.infcx.inner.borrow_mut().type_variables.var_origin(vid);
|
||||
let new_var_id = self.infcx.inner.borrow_mut().type_variables.new_var(
|
||||
self.for_universe,
|
||||
false,
|
||||
origin,
|
||||
);
|
||||
let u = self.tcx().mk_ty_var(new_var_id);
|
||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
@@ -612,7 +622,7 @@ fn consts(
|
||||
|
||||
match c.val {
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
|
||||
let variable_table = &mut self.infcx.inner.borrow_mut().const_unification_table;
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val {
|
||||
ConstVariableValue::Known { value: u } => self.relate(&u, &u),
|
||||
|
||||
@@ -72,14 +72,14 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
|
||||
let infcx = self.fields.infcx;
|
||||
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
|
||||
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
|
||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
||||
|
||||
debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
|
||||
|
||||
match (&a.kind, &b.kind) {
|
||||
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
|
||||
infcx.type_variables.borrow_mut().equate(a_id, b_id);
|
||||
infcx.inner.borrow_mut().type_variables.equate(a_id, b_id);
|
||||
}
|
||||
|
||||
(&ty::Infer(TyVar(a_id)), _) => {
|
||||
@@ -105,7 +105,12 @@ fn regions(
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
|
||||
let origin = Subtype(box self.fields.trace.clone());
|
||||
self.fields.infcx.borrow_region_constraints().make_eqregion(origin, a, b);
|
||||
self.fields
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.make_eqregion(origin, a, b);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,12 @@ fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
|
||||
if ty.walk().any(|inner_ty| {
|
||||
inner_ty == self.target_ty
|
||||
|| match (&inner_ty.kind, &self.target_ty.kind) {
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
|
||||
self.infcx.type_variables.borrow_mut().sub_unified(a_vid, b_vid)
|
||||
}
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.type_variables
|
||||
.sub_unified(a_vid, b_vid),
|
||||
_ => false,
|
||||
}
|
||||
}) {
|
||||
@@ -166,7 +169,7 @@ pub fn extract_type_name(
|
||||
highlight: Option<ty::print::RegionHighlightMode>,
|
||||
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
|
||||
if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
|
||||
let ty_vars = self.type_variables.borrow();
|
||||
let ty_vars = &self.inner.borrow().type_variables;
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
|
||||
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
|
||||
@@ -224,7 +227,7 @@ pub fn need_type_info_err(
|
||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||
let mut s = String::new();
|
||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
||||
let ty_vars = self.type_variables.borrow();
|
||||
let ty_vars = &self.inner.borrow().type_variables;
|
||||
let getter = move |ty_vid| {
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
|
||||
|
||||
@@ -154,14 +154,15 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
||||
match t.kind {
|
||||
ty::Infer(ty::TyVar(v)) => {
|
||||
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
|
||||
let opt_ty = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
|
||||
self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => self.freshen_ty(
|
||||
self.infcx
|
||||
.int_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(tcx)),
|
||||
ty::IntVar(v),
|
||||
@@ -170,8 +171,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
|
||||
self.infcx
|
||||
.float_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(tcx)),
|
||||
ty::FloatVar(v),
|
||||
@@ -225,8 +227,14 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
match ct.val {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
|
||||
let opt_ct =
|
||||
self.infcx.const_unification_table.borrow_mut().probe_value(v).val.known();
|
||||
let opt_ct = self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table
|
||||
.probe_value(v)
|
||||
.val
|
||||
.known();
|
||||
return self.freshen_const(
|
||||
opt_ct,
|
||||
ty::InferConst::Var(v),
|
||||
|
||||
+14
-18
@@ -8,11 +8,10 @@
|
||||
use rustc_data_structures::unify as ut;
|
||||
use ut::UnifyKey;
|
||||
|
||||
use std::cell::RefMut;
|
||||
use std::ops::Range;
|
||||
|
||||
fn const_vars_since_snapshot<'tcx>(
|
||||
mut table: RefMut<'_, ut::UnificationTable<ut::InPlace<ConstVid<'tcx>>>>,
|
||||
table: &mut ut::UnificationTable<ut::InPlace<ConstVid<'tcx>>>,
|
||||
snapshot: &ut::Snapshot<ut::InPlace<ConstVid<'tcx>>>,
|
||||
) -> (Range<ConstVid<'tcx>>, Vec<ConstVariableOrigin>) {
|
||||
let range = table.vars_since_snapshot(snapshot);
|
||||
@@ -82,23 +81,18 @@ pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
|
||||
// going to be popped, so we will have to
|
||||
// eliminate any references to them.
|
||||
|
||||
let type_vars = self
|
||||
.type_variables
|
||||
.borrow_mut()
|
||||
.vars_since_snapshot(&snapshot.type_snapshot);
|
||||
let int_vars = self
|
||||
.int_unification_table
|
||||
.borrow_mut()
|
||||
.vars_since_snapshot(&snapshot.int_snapshot);
|
||||
let float_vars = self
|
||||
.float_unification_table
|
||||
.borrow_mut()
|
||||
.vars_since_snapshot(&snapshot.float_snapshot);
|
||||
let region_vars = self
|
||||
.borrow_region_constraints()
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let type_vars =
|
||||
inner.type_variables.vars_since_snapshot(&snapshot.type_snapshot);
|
||||
let int_vars =
|
||||
inner.int_unification_table.vars_since_snapshot(&snapshot.int_snapshot);
|
||||
let float_vars =
|
||||
inner.float_unification_table.vars_since_snapshot(&snapshot.float_snapshot);
|
||||
let region_vars = inner
|
||||
.unwrap_region_constraints()
|
||||
.vars_since_snapshot(&snapshot.region_constraints_snapshot);
|
||||
let const_vars = const_vars_since_snapshot(
|
||||
self.const_unification_table.borrow_mut(),
|
||||
&mut inner.const_unification_table,
|
||||
&snapshot.const_snapshot,
|
||||
);
|
||||
|
||||
@@ -166,7 +160,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
// variables to their binding anyhow, we know
|
||||
// that it is unbound, so we can just return
|
||||
// it.
|
||||
debug_assert!(self.infcx.type_variables.borrow_mut().probe(vid).is_unknown());
|
||||
debug_assert!(
|
||||
self.infcx.inner.borrow_mut().type_variables.probe(vid).is_unknown()
|
||||
);
|
||||
ty
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,12 @@ fn regions(
|
||||
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
|
||||
|
||||
let origin = Subtype(box self.fields.trace.clone());
|
||||
Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
|
||||
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
|
||||
self.tcx(),
|
||||
origin,
|
||||
a,
|
||||
b,
|
||||
))
|
||||
}
|
||||
|
||||
fn consts(
|
||||
|
||||
@@ -138,7 +138,7 @@ pub fn leak_check(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.borrow_region_constraints().leak_check(
|
||||
self.inner.borrow_mut().unwrap_region_constraints().leak_check(
|
||||
self.tcx,
|
||||
overly_polymorphic,
|
||||
placeholder_map,
|
||||
|
||||
@@ -56,8 +56,8 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
|
||||
}
|
||||
|
||||
let infcx = this.infcx();
|
||||
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
|
||||
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
|
||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
||||
match (&a.kind, &b.kind) {
|
||||
// If one side is known to be a variable and one is not,
|
||||
// create a variable (`v`) to represent the LUB. Make sure to
|
||||
|
||||
@@ -66,7 +66,12 @@ fn regions(
|
||||
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
|
||||
|
||||
let origin = Subtype(box self.fields.trace.clone());
|
||||
Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
|
||||
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
|
||||
self.tcx(),
|
||||
origin,
|
||||
a,
|
||||
b,
|
||||
))
|
||||
}
|
||||
|
||||
fn consts(
|
||||
|
||||
+181
-155
@@ -29,7 +29,7 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
use std::cell::{Cell, Ref, RefCell, RefMut};
|
||||
use std::cell::{Cell, Ref, RefCell};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
@@ -105,6 +105,89 @@ pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
/// This type contains all the things within `InferCtxt` that sit within a
|
||||
/// `RefCell` and are involved with taking/rolling back snapshots. Snapshot
|
||||
/// operations are hot enough that we want only one call to `borrow_mut` per
|
||||
/// call to `start_snapshot` and `rollback_to`.
|
||||
pub struct InferCtxtInner<'tcx> {
|
||||
/// Cache for projections. This cache is snapshotted along with the infcx.
|
||||
///
|
||||
/// Public so that `traits::project` can use it.
|
||||
pub projection_cache: traits::ProjectionCache<'tcx>,
|
||||
|
||||
/// We instantiate `UnificationTable` with `bounds<Ty>` because the types
|
||||
/// that might instantiate a general type variable have an order,
|
||||
/// represented by its upper and lower bounds.
|
||||
type_variables: type_variable::TypeVariableTable<'tcx>,
|
||||
|
||||
/// Map from const parameter variable to the kind of const it represents.
|
||||
const_unification_table: ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>,
|
||||
|
||||
/// Map from integral variable to the kind of integer it represents.
|
||||
int_unification_table: ut::UnificationTable<ut::InPlace<ty::IntVid>>,
|
||||
|
||||
/// Map from floating variable to the kind of float it represents.
|
||||
float_unification_table: ut::UnificationTable<ut::InPlace<ty::FloatVid>>,
|
||||
|
||||
/// Tracks the set of region variables and the constraints between them.
|
||||
/// This is initially `Some(_)` but when
|
||||
/// `resolve_regions_and_report_errors` is invoked, this gets set to `None`
|
||||
/// -- further attempts to perform unification, etc., may fail if new
|
||||
/// region constraints would've been added.
|
||||
region_constraints: Option<RegionConstraintCollector<'tcx>>,
|
||||
|
||||
/// A set of constraints that regionck must validate. Each
|
||||
/// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
/// outlive the lifetime 'a". These constraints derive from
|
||||
/// instantiated type parameters. So if you had a struct defined
|
||||
/// like
|
||||
///
|
||||
/// struct Foo<T:'static> { ... }
|
||||
///
|
||||
/// then in some expression `let x = Foo { ... }` it will
|
||||
/// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
/// the same time, it will record a region obligation of
|
||||
/// `$0:'static`. This will get checked later by regionck. (We
|
||||
/// can't generally check these things right away because we have
|
||||
/// to wait until types are resolved.)
|
||||
///
|
||||
/// These are stored in a map keyed to the id of the innermost
|
||||
/// enclosing fn body / static initializer expression. This is
|
||||
/// because the location where the obligation was incurred can be
|
||||
/// relevant with respect to which sublifetime assumptions are in
|
||||
/// place. The reason that we store under the fn-id, and not
|
||||
/// something more fine-grained, is so that it is easier for
|
||||
/// regionck to be sure that it has found *all* the region
|
||||
/// obligations (otherwise, it's easy to fail to walk to a
|
||||
/// particular node-id).
|
||||
///
|
||||
/// Before running `resolve_regions_and_report_errors`, the creator
|
||||
/// of the inference context is expected to invoke
|
||||
/// `process_region_obligations` (defined in `self::region_obligations`)
|
||||
/// for each body-id in this map, which will process the
|
||||
/// obligations within. This is expected to be done 'late enough'
|
||||
/// that all type inference variables have been bound and so forth.
|
||||
pub region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtInner<'tcx> {
|
||||
fn new() -> InferCtxtInner<'tcx> {
|
||||
InferCtxtInner {
|
||||
projection_cache: Default::default(),
|
||||
type_variables: type_variable::TypeVariableTable::new(),
|
||||
const_unification_table: ut::UnificationTable::new(),
|
||||
int_unification_table: ut::UnificationTable::new(),
|
||||
float_unification_table: ut::UnificationTable::new(),
|
||||
region_constraints: Some(RegionConstraintCollector::new()),
|
||||
region_obligations: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_region_constraints(&mut self) -> &mut RegionConstraintCollector<'tcx> {
|
||||
self.region_constraints.as_mut().expect("region constraints already solved")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InferCtxt<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
@@ -114,16 +197,7 @@ pub struct InferCtxt<'a, 'tcx> {
|
||||
/// and for error reporting logic to read arbitrary node types.
|
||||
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
|
||||
|
||||
/// Cache for projections. This cache is snapshotted along with the
|
||||
/// infcx.
|
||||
///
|
||||
/// Public so that `traits::project` can use it.
|
||||
pub projection_cache: RefCell<traits::ProjectionCache<'tcx>>,
|
||||
|
||||
/// We instantiate `UnificationTable` with `bounds<Ty>` because the
|
||||
/// types that might instantiate a general type variable have an
|
||||
/// order, represented by its upper and lower bounds.
|
||||
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
|
||||
pub inner: RefCell<InferCtxtInner<'tcx>>,
|
||||
|
||||
/// If set, this flag causes us to skip the 'leak check' during
|
||||
/// higher-ranked subtyping operations. This flag is a temporary one used
|
||||
@@ -132,22 +206,6 @@ pub struct InferCtxt<'a, 'tcx> {
|
||||
/// when entering a snapshot.
|
||||
skip_leak_check: Cell<bool>,
|
||||
|
||||
/// Map from const parameter variable to the kind of const it represents.
|
||||
const_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>>,
|
||||
|
||||
/// Map from integral variable to the kind of integer it represents.
|
||||
int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::IntVid>>>,
|
||||
|
||||
/// Map from floating variable to the kind of float it represents
|
||||
float_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::FloatVid>>>,
|
||||
|
||||
/// Tracks the set of region variables and the constraints between
|
||||
/// them. This is initially `Some(_)` but when
|
||||
/// `resolve_regions_and_report_errors` is invoked, this gets set
|
||||
/// to `None` -- further attempts to perform unification etc may
|
||||
/// fail if new region constraints would've been added.
|
||||
region_constraints: RefCell<Option<RegionConstraintCollector<'tcx>>>,
|
||||
|
||||
/// Once region inference is done, the values for each variable.
|
||||
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
|
||||
|
||||
@@ -189,39 +247,6 @@ pub struct InferCtxt<'a, 'tcx> {
|
||||
/// This flag is true while there is an active snapshot.
|
||||
in_snapshot: Cell<bool>,
|
||||
|
||||
/// A set of constraints that regionck must validate. Each
|
||||
/// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
/// outlive the lifetime 'a". These constraints derive from
|
||||
/// instantiated type parameters. So if you had a struct defined
|
||||
/// like
|
||||
///
|
||||
/// struct Foo<T:'static> { ... }
|
||||
///
|
||||
/// then in some expression `let x = Foo { ... }` it will
|
||||
/// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
/// the same time, it will record a region obligation of
|
||||
/// `$0:'static`. This will get checked later by regionck. (We
|
||||
/// can't generally check these things right away because we have
|
||||
/// to wait until types are resolved.)
|
||||
///
|
||||
/// These are stored in a map keyed to the id of the innermost
|
||||
/// enclosing fn body / static initializer expression. This is
|
||||
/// because the location where the obligation was incurred can be
|
||||
/// relevant with respect to which sublifetime assumptions are in
|
||||
/// place. The reason that we store under the fn-id, and not
|
||||
/// something more fine-grained, is so that it is easier for
|
||||
/// regionck to be sure that it has found *all* the region
|
||||
/// obligations (otherwise, it's easy to fail to walk to a
|
||||
/// particular node-id).
|
||||
///
|
||||
/// Before running `resolve_regions_and_report_errors`, the creator
|
||||
/// of the inference context is expected to invoke
|
||||
/// `process_region_obligations` (defined in `self::region_obligations`)
|
||||
/// for each body-id in this map, which will process the
|
||||
/// obligations within. This is expected to be done 'late enough'
|
||||
/// that all type inference variables have been bound and so forth.
|
||||
pub region_obligations: RefCell<Vec<(hir::HirId, RegionObligation<'tcx>)>>,
|
||||
|
||||
/// What is the innermost universe we have created? Starts out as
|
||||
/// `UniverseIndex::root()` but grows from there as we enter
|
||||
/// universal quantifiers.
|
||||
@@ -543,12 +568,7 @@ pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) ->
|
||||
f(InferCtxt {
|
||||
tcx,
|
||||
in_progress_tables,
|
||||
projection_cache: Default::default(),
|
||||
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
||||
const_unification_table: RefCell::new(ut::UnificationTable::new()),
|
||||
int_unification_table: RefCell::new(ut::UnificationTable::new()),
|
||||
float_unification_table: RefCell::new(ut::UnificationTable::new()),
|
||||
region_constraints: RefCell::new(Some(RegionConstraintCollector::new())),
|
||||
inner: RefCell::new(InferCtxtInner::new()),
|
||||
lexical_region_resolutions: RefCell::new(None),
|
||||
selection_cache: Default::default(),
|
||||
evaluation_cache: Default::default(),
|
||||
@@ -558,7 +578,6 @@ pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) ->
|
||||
err_count_on_creation: tcx.sess.err_count(),
|
||||
in_snapshot: Cell::new(false),
|
||||
skip_leak_check: Cell::new(false),
|
||||
region_obligations: RefCell::new(vec![]),
|
||||
universe: Cell::new(ty::UniverseIndex::ROOT),
|
||||
})
|
||||
})
|
||||
@@ -616,7 +635,7 @@ pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
|
||||
|
||||
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
|
||||
match ty.kind {
|
||||
ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
|
||||
ty::Infer(ty::TyVar(vid)) => self.inner.borrow().type_variables.var_diverges(vid),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -630,14 +649,14 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumer
|
||||
use crate::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt};
|
||||
match ty.kind {
|
||||
ty::Infer(ty::IntVar(vid)) => {
|
||||
if self.int_unification_table.borrow_mut().probe_value(vid).is_some() {
|
||||
if self.inner.borrow_mut().int_unification_table.probe_value(vid).is_some() {
|
||||
Neither
|
||||
} else {
|
||||
UnconstrainedInt
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::FloatVar(vid)) => {
|
||||
if self.float_unification_table.borrow_mut().probe_value(vid).is_some() {
|
||||
if self.inner.borrow_mut().float_unification_table.probe_value(vid).is_some() {
|
||||
Neither
|
||||
} else {
|
||||
UnconstrainedFloat
|
||||
@@ -648,28 +667,28 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumer
|
||||
}
|
||||
|
||||
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
|
||||
let mut type_variables = self.type_variables.borrow_mut();
|
||||
let mut int_unification_table = self.int_unification_table.borrow_mut();
|
||||
let mut float_unification_table = self.float_unification_table.borrow_mut();
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
// FIXME(const_generics): should there be an equivalent function for const variables?
|
||||
|
||||
type_variables
|
||||
let mut vars: Vec<Ty<'_>> = inner
|
||||
.type_variables
|
||||
.unsolved_variables()
|
||||
.into_iter()
|
||||
.map(|t| self.tcx.mk_ty_var(t))
|
||||
.chain(
|
||||
(0..int_unification_table.len())
|
||||
.map(|i| ty::IntVid { index: i as u32 })
|
||||
.filter(|&vid| int_unification_table.probe_value(vid).is_none())
|
||||
.map(|v| self.tcx.mk_int_var(v)),
|
||||
)
|
||||
.chain(
|
||||
(0..float_unification_table.len())
|
||||
.map(|i| ty::FloatVid { index: i as u32 })
|
||||
.filter(|&vid| float_unification_table.probe_value(vid).is_none())
|
||||
.map(|v| self.tcx.mk_float_var(v)),
|
||||
)
|
||||
.collect()
|
||||
.collect();
|
||||
vars.extend(
|
||||
(0..inner.int_unification_table.len())
|
||||
.map(|i| ty::IntVid { index: i as u32 })
|
||||
.filter(|&vid| inner.int_unification_table.probe_value(vid).is_none())
|
||||
.map(|v| self.tcx.mk_int_var(v)),
|
||||
);
|
||||
vars.extend(
|
||||
(0..inner.float_unification_table.len())
|
||||
.map(|i| ty::FloatVid { index: i as u32 })
|
||||
.filter(|&vid| inner.float_unification_table.probe_value(vid).is_none())
|
||||
.map(|v| self.tcx.mk_float_var(v)),
|
||||
);
|
||||
vars
|
||||
}
|
||||
|
||||
fn combine_fields(
|
||||
@@ -719,14 +738,15 @@ fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
|
||||
let in_snapshot = self.in_snapshot.get();
|
||||
self.in_snapshot.set(true);
|
||||
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
CombinedSnapshot {
|
||||
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
|
||||
type_snapshot: self.type_variables.borrow_mut().snapshot(),
|
||||
const_snapshot: self.const_unification_table.borrow_mut().snapshot(),
|
||||
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
|
||||
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
|
||||
region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(),
|
||||
region_obligations_snapshot: self.region_obligations.borrow().len(),
|
||||
projection_cache_snapshot: inner.projection_cache.snapshot(),
|
||||
type_snapshot: inner.type_variables.snapshot(),
|
||||
const_snapshot: inner.const_unification_table.snapshot(),
|
||||
int_snapshot: inner.int_unification_table.snapshot(),
|
||||
float_snapshot: inner.float_unification_table.snapshot(),
|
||||
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
|
||||
region_obligations_snapshot: inner.region_obligations.len(),
|
||||
universe: self.universe(),
|
||||
was_in_snapshot: in_snapshot,
|
||||
was_skip_leak_check: self.skip_leak_check.get(),
|
||||
@@ -756,13 +776,14 @@ fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
|
||||
self.universe.set(universe);
|
||||
self.skip_leak_check.set(was_skip_leak_check);
|
||||
|
||||
self.projection_cache.borrow_mut().rollback_to(projection_cache_snapshot);
|
||||
self.type_variables.borrow_mut().rollback_to(type_snapshot);
|
||||
self.const_unification_table.borrow_mut().rollback_to(const_snapshot);
|
||||
self.int_unification_table.borrow_mut().rollback_to(int_snapshot);
|
||||
self.float_unification_table.borrow_mut().rollback_to(float_snapshot);
|
||||
self.region_obligations.borrow_mut().truncate(region_obligations_snapshot);
|
||||
self.borrow_region_constraints().rollback_to(region_constraints_snapshot);
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.projection_cache.rollback_to(projection_cache_snapshot);
|
||||
inner.type_variables.rollback_to(type_snapshot);
|
||||
inner.const_unification_table.rollback_to(const_snapshot);
|
||||
inner.int_unification_table.rollback_to(int_snapshot);
|
||||
inner.float_unification_table.rollback_to(float_snapshot);
|
||||
inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
|
||||
inner.region_obligations.truncate(region_obligations_snapshot);
|
||||
}
|
||||
|
||||
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
|
||||
@@ -784,12 +805,13 @@ fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
|
||||
self.in_snapshot.set(was_in_snapshot);
|
||||
self.skip_leak_check.set(was_skip_leak_check);
|
||||
|
||||
self.projection_cache.borrow_mut().commit(projection_cache_snapshot);
|
||||
self.type_variables.borrow_mut().commit(type_snapshot);
|
||||
self.const_unification_table.borrow_mut().commit(const_snapshot);
|
||||
self.int_unification_table.borrow_mut().commit(int_snapshot);
|
||||
self.float_unification_table.borrow_mut().commit(float_snapshot);
|
||||
self.borrow_region_constraints().commit(region_constraints_snapshot);
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.projection_cache.commit(projection_cache_snapshot);
|
||||
inner.type_variables.commit(type_snapshot);
|
||||
inner.const_unification_table.commit(const_snapshot);
|
||||
inner.int_unification_table.commit(int_snapshot);
|
||||
inner.float_unification_table.commit(float_snapshot);
|
||||
inner.unwrap_region_constraints().commit(region_constraints_snapshot);
|
||||
}
|
||||
|
||||
/// Executes `f` and commit the bindings.
|
||||
@@ -859,12 +881,14 @@ pub fn region_constraints_added_in_snapshot(
|
||||
&self,
|
||||
snapshot: &CombinedSnapshot<'a, 'tcx>,
|
||||
) -> Option<bool> {
|
||||
self.borrow_region_constraints()
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.region_constraints_added_in_snapshot(&snapshot.region_constraints_snapshot)
|
||||
}
|
||||
|
||||
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
|
||||
self.borrow_region_constraints().add_given(sub, sup);
|
||||
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
|
||||
}
|
||||
|
||||
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
|
||||
@@ -900,7 +924,7 @@ pub fn sub_regions(
|
||||
b: ty::Region<'tcx>,
|
||||
) {
|
||||
debug!("sub_regions({:?} <: {:?})", a, b);
|
||||
self.borrow_region_constraints().make_subregion(origin, a, b);
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
|
||||
}
|
||||
|
||||
/// Require that the region `r` be equal to one of the regions in
|
||||
@@ -914,7 +938,7 @@ pub fn member_constraint(
|
||||
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
|
||||
) {
|
||||
debug!("member_constraint({:?} <: {:?})", region, in_regions);
|
||||
self.borrow_region_constraints().member_constraint(
|
||||
self.inner.borrow_mut().unwrap_region_constraints().member_constraint(
|
||||
opaque_type_def_id,
|
||||
definition_span,
|
||||
hidden_ty,
|
||||
@@ -978,7 +1002,7 @@ pub fn region_outlives_predicate(
|
||||
}
|
||||
|
||||
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
||||
self.type_variables.borrow_mut().new_var(self.universe(), diverging, origin)
|
||||
self.inner.borrow_mut().type_variables.new_var(self.universe(), diverging, origin)
|
||||
}
|
||||
|
||||
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||
@@ -990,7 +1014,7 @@ pub fn next_ty_var_in_universe(
|
||||
origin: TypeVariableOrigin,
|
||||
universe: ty::UniverseIndex,
|
||||
) -> Ty<'tcx> {
|
||||
let vid = self.type_variables.borrow_mut().new_var(universe, false, origin);
|
||||
let vid = self.inner.borrow_mut().type_variables.new_var(universe, false, origin);
|
||||
self.tcx.mk_ty_var(vid)
|
||||
}
|
||||
|
||||
@@ -1013,21 +1037,22 @@ pub fn next_const_var_in_universe(
|
||||
universe: ty::UniverseIndex,
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
let vid = self
|
||||
.const_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table
|
||||
.new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } });
|
||||
self.tcx.mk_const_var(vid, ty)
|
||||
}
|
||||
|
||||
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
|
||||
self.const_unification_table.borrow_mut().new_key(ConstVarValue {
|
||||
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
|
||||
origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.universe() },
|
||||
})
|
||||
}
|
||||
|
||||
fn next_int_var_id(&self) -> IntVid {
|
||||
self.int_unification_table.borrow_mut().new_key(None)
|
||||
self.inner.borrow_mut().int_unification_table.new_key(None)
|
||||
}
|
||||
|
||||
pub fn next_int_var(&self) -> Ty<'tcx> {
|
||||
@@ -1035,7 +1060,7 @@ pub fn next_int_var(&self) -> Ty<'tcx> {
|
||||
}
|
||||
|
||||
fn next_float_var_id(&self) -> FloatVid {
|
||||
self.float_unification_table.borrow_mut().new_key(None)
|
||||
self.inner.borrow_mut().float_unification_table.new_key(None)
|
||||
}
|
||||
|
||||
pub fn next_float_var(&self) -> Ty<'tcx> {
|
||||
@@ -1057,7 +1082,8 @@ pub fn next_region_var_in_universe(
|
||||
origin: RegionVariableOrigin,
|
||||
universe: ty::UniverseIndex,
|
||||
) -> ty::Region<'tcx> {
|
||||
let region_var = self.borrow_region_constraints().new_region_var(universe, origin);
|
||||
let region_var =
|
||||
self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
|
||||
self.tcx.mk_region(ty::ReVar(region_var))
|
||||
}
|
||||
|
||||
@@ -1067,12 +1093,12 @@ pub fn next_region_var_in_universe(
|
||||
/// placeholders, however, it will return the universe which which
|
||||
/// they are associated.
|
||||
fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex {
|
||||
self.borrow_region_constraints().universe(r)
|
||||
self.inner.borrow_mut().unwrap_region_constraints().universe(r)
|
||||
}
|
||||
|
||||
/// Number of region variables created so far.
|
||||
pub fn num_region_vars(&self) -> usize {
|
||||
self.borrow_region_constraints().num_region_vars()
|
||||
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
|
||||
}
|
||||
|
||||
/// Just a convenient wrapper of `next_region_var` for using during NLL.
|
||||
@@ -1105,7 +1131,7 @@ pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg
|
||||
// used in a path such as `Foo::<T, U>::new()` will
|
||||
// use an inference variable for `C` with `[T, U]`
|
||||
// as the substitutions for the default, `(T, U)`.
|
||||
let ty_var_id = self.type_variables.borrow_mut().new_var(
|
||||
let ty_var_id = self.inner.borrow_mut().type_variables.new_var(
|
||||
self.universe(),
|
||||
false,
|
||||
TypeVariableOrigin {
|
||||
@@ -1125,7 +1151,7 @@ pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg
|
||||
span,
|
||||
};
|
||||
let const_var_id =
|
||||
self.const_unification_table.borrow_mut().new_key(ConstVarValue {
|
||||
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
|
||||
origin,
|
||||
val: ConstVariableValue::Unknown { universe: self.universe() },
|
||||
});
|
||||
@@ -1179,9 +1205,9 @@ pub fn resolve_regions_and_report_errors(
|
||||
suppress: SuppressRegionErrors,
|
||||
) {
|
||||
assert!(
|
||||
self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
|
||||
self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
self.region_obligations.borrow()
|
||||
self.inner.borrow().region_obligations
|
||||
);
|
||||
|
||||
let region_rels = &RegionRelations::new(
|
||||
@@ -1191,8 +1217,9 @@ pub fn resolve_regions_and_report_errors(
|
||||
outlives_env.free_region_map(),
|
||||
);
|
||||
let (var_infos, data) = self
|
||||
.region_constraints
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.region_constraints
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.into_infos_and_data();
|
||||
@@ -1224,12 +1251,12 @@ pub fn resolve_regions_and_report_errors(
|
||||
/// understands. See the NLL module for mode details.
|
||||
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
|
||||
assert!(
|
||||
self.region_obligations.borrow().is_empty(),
|
||||
self.inner.borrow().region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
self.region_obligations.borrow()
|
||||
self.inner.borrow().region_obligations
|
||||
);
|
||||
|
||||
self.borrow_region_constraints().take_and_reset_data()
|
||||
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
|
||||
}
|
||||
|
||||
/// Gives temporary access to the region constraint data.
|
||||
@@ -1238,8 +1265,8 @@ pub fn with_region_constraints<R>(
|
||||
&self,
|
||||
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
|
||||
) -> R {
|
||||
let region_constraints = self.borrow_region_constraints();
|
||||
op(region_constraints.data())
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
op(inner.unwrap_region_constraints().data())
|
||||
}
|
||||
|
||||
/// Takes ownership of the list of variable regions. This implies
|
||||
@@ -1249,8 +1276,9 @@ pub fn with_region_constraints<R>(
|
||||
/// of the set of region variables into the NLL region context.
|
||||
pub fn take_region_var_origins(&self) -> VarInfos {
|
||||
let (var_infos, data) = self
|
||||
.region_constraints
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.region_constraints
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.into_infos_and_data();
|
||||
@@ -1276,7 +1304,7 @@ pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
|
||||
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
|
||||
use self::type_variable::TypeVariableValue;
|
||||
|
||||
match self.type_variables.borrow_mut().probe(vid) {
|
||||
match self.inner.borrow_mut().type_variables.probe(vid) {
|
||||
TypeVariableValue::Known { value } => Ok(value),
|
||||
TypeVariableValue::Unknown { universe } => Err(universe),
|
||||
}
|
||||
@@ -1299,7 +1327,7 @@ pub fn shallow_resolve<T>(&self, value: T) -> T
|
||||
}
|
||||
|
||||
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.type_variables.borrow_mut().root_var(var)
|
||||
self.inner.borrow_mut().type_variables.root_var(var)
|
||||
}
|
||||
|
||||
/// Where possible, replaces type/const variables in
|
||||
@@ -1337,7 +1365,7 @@ pub fn probe_const_var(
|
||||
&self,
|
||||
vid: ty::ConstVid<'tcx>,
|
||||
) -> Result<&'tcx ty::Const<'tcx>, ty::UniverseIndex> {
|
||||
match self.const_unification_table.borrow_mut().probe_value(vid).val {
|
||||
match self.inner.borrow_mut().const_unification_table.probe_value(vid).val {
|
||||
ConstVariableValue::Known { value } => Ok(value),
|
||||
ConstVariableValue::Unknown { universe } => Err(universe),
|
||||
}
|
||||
@@ -1434,7 +1462,10 @@ pub fn verify_generic_bound(
|
||||
) {
|
||||
debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound);
|
||||
|
||||
self.borrow_region_constraints().verify_generic_bound(origin, kind, a, bound);
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.verify_generic_bound(origin, kind, a, bound);
|
||||
}
|
||||
|
||||
pub fn type_is_copy_modulo_regions(
|
||||
@@ -1509,19 +1540,13 @@ pub fn partially_normalize_associated_types_in<T>(
|
||||
InferOk { value, obligations }
|
||||
}
|
||||
|
||||
pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
|
||||
RefMut::map(self.region_constraints.borrow_mut(), |c| {
|
||||
c.as_mut().expect("region constraints already solved")
|
||||
})
|
||||
}
|
||||
|
||||
/// Clears the selection, evaluation, and projection caches. This is useful when
|
||||
/// repeatedly attempting to select an `Obligation` while changing only
|
||||
/// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
|
||||
pub fn clear_caches(&self) {
|
||||
self.selection_cache.clear();
|
||||
self.evaluation_cache.clear();
|
||||
self.projection_cache.borrow_mut().clear();
|
||||
self.inner.borrow_mut().projection_cache.clear();
|
||||
}
|
||||
|
||||
fn universe(&self) -> ty::UniverseIndex {
|
||||
@@ -1562,27 +1587,27 @@ pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
||||
// structurally), and we prevent cycles in any case,
|
||||
// so this recursion should always be of very limited
|
||||
// depth.
|
||||
self.infcx
|
||||
.type_variables
|
||||
.borrow_mut()
|
||||
.probe(v)
|
||||
.known()
|
||||
.map(|t| self.fold_ty(t))
|
||||
.unwrap_or(typ)
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.infcx.inner`.
|
||||
let known = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
|
||||
known.map(|t| self.fold_ty(t)).unwrap_or(typ)
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => self
|
||||
.infcx
|
||||
.int_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.unwrap_or(typ),
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => self
|
||||
.infcx
|
||||
.float_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.unwrap_or(typ),
|
||||
@@ -1603,7 +1628,7 @@ pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
|
||||
|
||||
// If `inlined_probe` returns a `Known` value its `kind` never
|
||||
// matches `infer`.
|
||||
match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
|
||||
match self.infcx.inner.borrow_mut().type_variables.inlined_probe(v) {
|
||||
TypeVariableValue::Unknown { .. } => false,
|
||||
TypeVariableValue::Known { .. } => true,
|
||||
}
|
||||
@@ -1613,7 +1638,7 @@ pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
|
||||
// If inlined_probe_value returns a value it's always a
|
||||
// `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
|
||||
// `ty::Infer(_)`.
|
||||
self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v).is_some()
|
||||
self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
|
||||
}
|
||||
|
||||
ty::FloatVar(v) => {
|
||||
@@ -1621,7 +1646,7 @@ pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
|
||||
// `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
|
||||
//
|
||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||
self.infcx.float_unification_table.borrow_mut().probe_value(v).is_some()
|
||||
self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
@@ -1641,8 +1666,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
|
||||
self.infcx
|
||||
.const_unification_table
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table
|
||||
.probe_value(*vid)
|
||||
.val
|
||||
.known()
|
||||
|
||||
@@ -322,7 +322,7 @@ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
|
||||
match value_ty.kind {
|
||||
ty::Infer(ty::TyVar(value_vid)) => {
|
||||
// Two type variables: just equate them.
|
||||
self.infcx.type_variables.borrow_mut().equate(vid, value_vid);
|
||||
self.infcx.inner.borrow_mut().type_variables.equate(vid, value_vid);
|
||||
return Ok(value_ty);
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
|
||||
assert!(!generalized_ty.has_infer_types());
|
||||
}
|
||||
|
||||
self.infcx.type_variables.borrow_mut().instantiate(vid, generalized_ty);
|
||||
self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty);
|
||||
|
||||
// The generalized values we extract from `canonical_var_values` have
|
||||
// been fully instantiated and hence the set of scopes we have
|
||||
@@ -373,7 +373,7 @@ fn generalize_value<T: Relate<'tcx>>(
|
||||
delegate: &mut self.delegate,
|
||||
first_free_index: ty::INNERMOST,
|
||||
ambient_variance: self.ambient_variance,
|
||||
for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid),
|
||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables.sub_root_var(for_vid),
|
||||
universe,
|
||||
};
|
||||
|
||||
@@ -870,7 +870,7 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let mut variables = self.infcx.type_variables.borrow_mut();
|
||||
let variables = &mut self.infcx.inner.borrow_mut().type_variables;
|
||||
let vid = variables.root_var(vid);
|
||||
let sub_vid = variables.sub_root_var(vid);
|
||||
if sub_vid == self.for_vid_sub_root {
|
||||
@@ -972,7 +972,7 @@ fn consts(
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
|
||||
}
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
|
||||
let variable_table = &mut self.infcx.inner.borrow_mut().const_unification_table;
|
||||
let var_value = variable_table.probe_value(vid);
|
||||
match var_value.val.known() {
|
||||
Some(u) => self.relate(&u, &u),
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn register_region_obligation(
|
||||
) {
|
||||
debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation);
|
||||
|
||||
self.region_obligations.borrow_mut().push((body_id, obligation));
|
||||
self.inner.borrow_mut().region_obligations.push((body_id, obligation));
|
||||
}
|
||||
|
||||
pub fn register_region_obligation_with_cause(
|
||||
@@ -103,7 +103,7 @@ pub fn register_region_obligation_with_cause(
|
||||
|
||||
/// Trait queries just want to pass back type obligations "as is"
|
||||
pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
|
||||
::std::mem::take(&mut *self.region_obligations.borrow_mut())
|
||||
::std::mem::take(&mut self.inner.borrow_mut().region_obligations)
|
||||
}
|
||||
|
||||
/// Process the region obligations that must be proven (during
|
||||
|
||||
@@ -75,9 +75,12 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReVar(rid) => {
|
||||
self.infcx.borrow_region_constraints().opportunistic_resolve_var(self.tcx(), rid)
|
||||
}
|
||||
ty::ReVar(rid) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.tcx(), rid),
|
||||
_ => r,
|
||||
}
|
||||
}
|
||||
@@ -120,7 +123,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
// Since we called `shallow_resolve` above, this must
|
||||
// be an (as yet...) unresolved inference variable.
|
||||
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
|
||||
let ty_vars = self.infcx.type_variables.borrow();
|
||||
let ty_vars = &self.infcx.inner.borrow().type_variables;
|
||||
if let TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
||||
span,
|
||||
|
||||
@@ -80,8 +80,8 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
|
||||
let infcx = self.fields.infcx;
|
||||
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
|
||||
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
|
||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
||||
match (&a.kind, &b.kind) {
|
||||
(&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => {
|
||||
// Shouldn't have any LBR here, so we can safely put
|
||||
@@ -95,7 +95,7 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
// have to record in the `type_variables` tracker that
|
||||
// the two variables are equal modulo subtyping, which
|
||||
// is important to the occurs check later on.
|
||||
infcx.type_variables.borrow_mut().sub(a_vid, b_vid);
|
||||
infcx.inner.borrow_mut().type_variables.sub(a_vid, b_vid);
|
||||
self.fields.obligations.push(Obligation::new(
|
||||
self.fields.trace.cause.clone(),
|
||||
self.fields.param_env,
|
||||
@@ -140,7 +140,12 @@ fn regions(
|
||||
// from the "cause" field, we could perhaps give more tailored
|
||||
// error messages.
|
||||
let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
|
||||
self.fields.infcx.borrow_region_constraints().make_subregion(origin, a, b);
|
||||
self.fields
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.make_subregion(origin, a, b);
|
||||
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::cell::RefMut;
|
||||
use std::cmp;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -214,7 +213,7 @@ fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
|
||||
impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
|
||||
|
||||
pub fn replace_if_possible(
|
||||
mut table: RefMut<'_, UnificationTable<InPlace<ty::ConstVid<'tcx>>>>,
|
||||
table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>>>,
|
||||
c: &'tcx ty::Const<'tcx>,
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {
|
||||
|
||||
@@ -647,7 +647,8 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls {
|
||||
desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {
|
||||
query specialization_graph_of(key: DefId) -> &'tcx specialization_graph::Graph {
|
||||
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
query is_object_safe(key: DefId) -> bool {
|
||||
|
||||
@@ -199,12 +199,22 @@ pub fn find_auto_trait_generics<A>(
|
||||
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
|
||||
});
|
||||
|
||||
let body_id_map: FxHashMap<_, _> =
|
||||
infcx.region_obligations.borrow().iter().map(|&(id, _)| (id, vec![])).collect();
|
||||
let body_id_map: FxHashMap<_, _> = infcx
|
||||
.inner
|
||||
.borrow()
|
||||
.region_obligations
|
||||
.iter()
|
||||
.map(|&(id, _)| (id, vec![]))
|
||||
.collect();
|
||||
|
||||
infcx.process_registered_region_obligations(&body_id_map, None, full_env);
|
||||
|
||||
let region_data = infcx.borrow_region_constraints().region_constraint_data().clone();
|
||||
let region_data = infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.region_constraint_data()
|
||||
.clone();
|
||||
|
||||
let vid_to_region = self.map_vid_to_region(®ion_data);
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
use crate::infer::{CombinedSnapshot, InferOk};
|
||||
use crate::traits::select::IntercrateAmbiguityCause;
|
||||
use crate::traits::IntercrateMode;
|
||||
use crate::traits::SkipLeakCheck;
|
||||
use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext};
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
@@ -27,7 +26,7 @@ enum InCrate {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Conflict {
|
||||
Upstream,
|
||||
Downstream { used_to_be_broken: bool },
|
||||
Downstream,
|
||||
}
|
||||
|
||||
pub struct OverlapResult<'tcx> {
|
||||
@@ -53,7 +52,6 @@ pub fn overlapping_impls<F1, F2, R>(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl1_def_id: DefId,
|
||||
impl2_def_id: DefId,
|
||||
intercrate_mode: IntercrateMode,
|
||||
skip_leak_check: SkipLeakCheck,
|
||||
on_overlap: F1,
|
||||
no_overlap: F2,
|
||||
@@ -65,13 +63,12 @@ pub fn overlapping_impls<F1, F2, R>(
|
||||
debug!(
|
||||
"overlapping_impls(\
|
||||
impl1_def_id={:?}, \
|
||||
impl2_def_id={:?},
|
||||
intercrate_mode={:?})",
|
||||
impl1_def_id, impl2_def_id, intercrate_mode
|
||||
impl2_def_id={:?})",
|
||||
impl1_def_id, impl2_def_id,
|
||||
);
|
||||
|
||||
let overlaps = tcx.infer_ctxt().enter(|infcx| {
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
|
||||
});
|
||||
|
||||
@@ -83,7 +80,7 @@ pub fn overlapping_impls<F1, F2, R>(
|
||||
// this time tracking intercrate ambuiguity causes for better
|
||||
// diagnostics. (These take time and can lead to false errors.)
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||
on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap())
|
||||
})
|
||||
@@ -202,15 +199,7 @@ pub fn trait_ref_is_knowable<'tcx>(
|
||||
if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
|
||||
// A downstream or cousin crate is allowed to implement some
|
||||
// substitution of this trait-ref.
|
||||
|
||||
// A trait can be implementable for a trait ref by both the current
|
||||
// crate and crates downstream of it. Older versions of rustc
|
||||
// were not aware of this, causing incoherence (issue #43355).
|
||||
let used_to_be_broken = orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok();
|
||||
if used_to_be_broken {
|
||||
debug!("trait_ref_is_knowable({:?}) - USED TO BE BROKEN", trait_ref);
|
||||
}
|
||||
return Some(Conflict::Downstream { used_to_be_broken });
|
||||
return Some(Conflict::Downstream);
|
||||
}
|
||||
|
||||
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
|
||||
|
||||
@@ -78,13 +78,6 @@
|
||||
|
||||
pub use self::types::*;
|
||||
|
||||
/// Whether to enable bug compatibility with issue #43355.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum IntercrateMode {
|
||||
Issue43355,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
/// Whether to skip the leak check, as part of a future compatibility warning step.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum SkipLeakCheck {
|
||||
|
||||
@@ -486,7 +486,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
// bounds. It might be the case that we want two distinct caches,
|
||||
// or else another kind of cache entry.
|
||||
|
||||
let cache_result = infcx.projection_cache.borrow_mut().try_start(cache_key);
|
||||
let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
|
||||
match cache_result {
|
||||
Ok(()) => {}
|
||||
Err(ProjectionCacheEntry::Ambiguous) => {
|
||||
@@ -560,7 +560,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
// Once we have inferred everything we need to know, we
|
||||
// can ignore the `obligations` from that point on.
|
||||
if infcx.unresolved_type_vars(&ty.value).is_none() {
|
||||
infcx.projection_cache.borrow_mut().complete_normalized(cache_key, &ty);
|
||||
infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
|
||||
// No need to extend `obligations`.
|
||||
} else {
|
||||
obligations.extend(ty.obligations);
|
||||
@@ -627,7 +627,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
};
|
||||
|
||||
let cache_value = prune_cache_value_obligations(infcx, &result);
|
||||
infcx.projection_cache.borrow_mut().insert_ty(cache_key, cache_value);
|
||||
infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
|
||||
obligations.extend(result.obligations);
|
||||
Some(result.value)
|
||||
}
|
||||
@@ -638,7 +638,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
projected_ty
|
||||
);
|
||||
let result = Normalized { value: projected_ty, obligations: vec![] };
|
||||
infcx.projection_cache.borrow_mut().insert_ty(cache_key, result.clone());
|
||||
infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
|
||||
// No need to extend `obligations`.
|
||||
Some(result.value)
|
||||
}
|
||||
@@ -647,7 +647,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
"opt_normalize_projection_type: \
|
||||
too many candidates"
|
||||
);
|
||||
infcx.projection_cache.borrow_mut().ambiguous(cache_key);
|
||||
infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
|
||||
None
|
||||
}
|
||||
Err(ProjectionTyError::TraitSelectionError(_)) => {
|
||||
@@ -657,7 +657,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
// Trait`, which when processed will cause the error to be
|
||||
// reported later
|
||||
|
||||
infcx.projection_cache.borrow_mut().error(cache_key);
|
||||
infcx.inner.borrow_mut().projection_cache.error(cache_key);
|
||||
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
|
||||
obligations.extend(result.obligations);
|
||||
Some(result.value)
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
use super::Selection;
|
||||
use super::SelectionResult;
|
||||
use super::TraitNotObjectSafe;
|
||||
use super::TraitQueryMode;
|
||||
use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
|
||||
use super::{IntercrateMode, TraitQueryMode};
|
||||
use super::{ObjectCastObligation, Obligation};
|
||||
use super::{ObligationCause, PredicateObligation, TraitObligation};
|
||||
use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
|
||||
@@ -80,7 +80,7 @@ pub struct SelectionContext<'cx, 'tcx> {
|
||||
/// other words, we consider `$0: Bar` to be unimplemented if
|
||||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
intercrate: Option<IntercrateMode>,
|
||||
intercrate: bool,
|
||||
|
||||
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
|
||||
|
||||
@@ -218,22 +218,18 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intercrate(
|
||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||
mode: IntercrateMode,
|
||||
) -> SelectionContext<'cx, 'tcx> {
|
||||
debug!("intercrate({:?})", mode);
|
||||
pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: Some(mode),
|
||||
intercrate: true,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
@@ -248,7 +244,7 @@ pub fn with_negative(
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
@@ -263,7 +259,7 @@ pub fn with_query_mode(
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
query_mode,
|
||||
@@ -276,7 +272,7 @@ pub fn with_query_mode(
|
||||
/// false overflow results (#47139) and because it costs
|
||||
/// computation time.
|
||||
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||
assert!(self.intercrate.is_some());
|
||||
assert!(self.intercrate);
|
||||
assert!(self.intercrate_ambiguity_causes.is_none());
|
||||
self.intercrate_ambiguity_causes = Some(vec![]);
|
||||
debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
|
||||
@@ -286,7 +282,7 @@ pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||
/// was enabled and disables tracking at the same time. If
|
||||
/// tracking is not enabled, just returns an empty vector.
|
||||
pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
|
||||
assert!(self.intercrate.is_some());
|
||||
assert!(self.intercrate);
|
||||
self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
|
||||
}
|
||||
|
||||
@@ -513,7 +509,7 @@ fn evaluate_predicate_recursively<'o>(
|
||||
if let Some(key) =
|
||||
ProjectionCacheKey::from_poly_projection_predicate(self, data)
|
||||
{
|
||||
self.infcx.projection_cache.borrow_mut().complete(key);
|
||||
self.infcx.inner.borrow_mut().projection_cache.complete(key);
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -562,7 +558,7 @@ fn evaluate_trait_predicate_recursively<'o>(
|
||||
) -> Result<EvaluationResult, OverflowError> {
|
||||
debug!("evaluate_trait_predicate_recursively({:?})", obligation);
|
||||
|
||||
if self.intercrate.is_none()
|
||||
if !self.intercrate
|
||||
&& obligation.is_global()
|
||||
&& obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst())
|
||||
{
|
||||
@@ -727,7 +723,7 @@ fn evaluate_stack<'o>(
|
||||
stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh());
|
||||
// This check was an imperfect workaround for a bug in the old
|
||||
// intercrate mode; it should be removed when that goes away.
|
||||
if unbound_input_types && self.intercrate == Some(IntercrateMode::Issue43355) {
|
||||
if unbound_input_types && self.intercrate {
|
||||
debug!(
|
||||
"evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous",
|
||||
stack.fresh_trait_ref
|
||||
@@ -1206,7 +1202,7 @@ fn candidate_from_obligation_no_cache<'o>(
|
||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
|
||||
debug!("is_knowable(intercrate={:?})", self.intercrate);
|
||||
|
||||
if !self.intercrate.is_some() {
|
||||
if !self.intercrate {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1218,17 +1214,7 @@ fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<
|
||||
// bound regions.
|
||||
let trait_ref = predicate.skip_binder().trait_ref;
|
||||
|
||||
let result = coherence::trait_ref_is_knowable(self.tcx(), trait_ref);
|
||||
if let (
|
||||
Some(Conflict::Downstream { used_to_be_broken: true }),
|
||||
Some(IntercrateMode::Issue43355),
|
||||
) = (result, self.intercrate)
|
||||
{
|
||||
debug!("is_knowable: IGNORING conflict to be bug-compatible with #43355");
|
||||
None
|
||||
} else {
|
||||
result
|
||||
}
|
||||
coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
|
||||
}
|
||||
|
||||
/// Returns `true` if the global caches can be used.
|
||||
@@ -1249,7 +1235,7 @@ fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// the master cache. Since coherence executes pretty quickly,
|
||||
// it's not worth going to more trouble to increase the
|
||||
// hit-rate, I don't think.
|
||||
if self.intercrate.is_some() {
|
||||
if self.intercrate {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3305,7 +3291,7 @@ fn match_impl(
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if self.intercrate.is_none()
|
||||
if !self.intercrate
|
||||
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
|
||||
{
|
||||
debug!("match_impl: reservation impls only apply in intercrate mode");
|
||||
|
||||
@@ -332,14 +332,9 @@ pub(super) fn specialization_graph_provider(
|
||||
let impl_span =
|
||||
tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||
let mut err = match used_to_be_allowed {
|
||||
Some(FutureCompatOverlapErrorKind::Issue43355) | None => {
|
||||
struct_span_err!(tcx.sess, impl_span, E0119, "{}", msg)
|
||||
}
|
||||
None => struct_span_err!(tcx.sess, impl_span, E0119, "{}", msg),
|
||||
Some(kind) => {
|
||||
let lint = match kind {
|
||||
FutureCompatOverlapErrorKind::Issue43355 => {
|
||||
unreachable!("converted to hard error above")
|
||||
}
|
||||
FutureCompatOverlapErrorKind::Issue33140 => {
|
||||
ORDER_DEPENDENT_TRAIT_OBJECTS
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum FutureCompatOverlapErrorKind {
|
||||
Issue43355,
|
||||
Issue33140,
|
||||
LeakCheck,
|
||||
}
|
||||
@@ -107,16 +106,16 @@ fn insert(
|
||||
}
|
||||
};
|
||||
|
||||
let allowed_to_overlap =
|
||||
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling);
|
||||
|
||||
let (le, ge) = traits::overlapping_impls(
|
||||
tcx,
|
||||
possible_sibling,
|
||||
impl_def_id,
|
||||
traits::IntercrateMode::Issue43355,
|
||||
traits::SkipLeakCheck::default(),
|
||||
|overlap| {
|
||||
if let Some(overlap_kind) =
|
||||
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
|
||||
{
|
||||
if let Some(overlap_kind) = &allowed_to_overlap {
|
||||
match overlap_kind {
|
||||
ty::ImplOverlapKind::Permitted { marker: _ } => {}
|
||||
ty::ImplOverlapKind::Issue33140 => {
|
||||
@@ -154,31 +153,14 @@ fn insert(
|
||||
|
||||
replace_children.push(possible_sibling);
|
||||
} else {
|
||||
if let None = tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
|
||||
// do future-compat checks for overlap. Have issue #33140
|
||||
// errors overwrite issue #43355 errors when both are present.
|
||||
|
||||
traits::overlapping_impls(
|
||||
tcx,
|
||||
possible_sibling,
|
||||
impl_def_id,
|
||||
traits::IntercrateMode::Fixed,
|
||||
traits::SkipLeakCheck::default(),
|
||||
|overlap| {
|
||||
last_lint = Some(FutureCompatOverlapError {
|
||||
error: overlap_error(overlap),
|
||||
kind: FutureCompatOverlapErrorKind::Issue43355,
|
||||
});
|
||||
},
|
||||
|| (),
|
||||
);
|
||||
if let None = allowed_to_overlap {
|
||||
// Do future-compat checks for overlap.
|
||||
|
||||
if last_lint.is_none() {
|
||||
traits::overlapping_impls(
|
||||
tcx,
|
||||
possible_sibling,
|
||||
impl_def_id,
|
||||
traits::IntercrateMode::Fixed,
|
||||
traits::SkipLeakCheck::Yes,
|
||||
|overlap| {
|
||||
last_lint = Some(FutureCompatOverlapError {
|
||||
|
||||
@@ -331,7 +331,7 @@ fn write_graphviz_results<A>(
|
||||
let mut buf = Vec::new();
|
||||
|
||||
let graphviz = graphviz::Formatter::new(body, def_id, results, &mut *formatter);
|
||||
dot::render(&graphviz, &mut buf)?;
|
||||
dot::render_opts(&graphviz, &mut buf, &[dot::RenderOption::Monospace])?;
|
||||
fs::write(&path, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -171,10 +171,19 @@ fn write_node_label(
|
||||
// | | (on successful return) | +_4 |
|
||||
// +-+----------------------------------+------------+
|
||||
|
||||
write!(
|
||||
w,
|
||||
r#"<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb">"#,
|
||||
)?;
|
||||
// N.B., Some attributes (`align`, `balign`) are repeated on parent elements and their
|
||||
// children. This is because `xdot` seemed to have a hard time correctly propagating
|
||||
// attributes. Make sure to test the output before trying to remove the redundancy.
|
||||
// Notably, `align` was found to have no effect when applied only to <table>.
|
||||
|
||||
let table_fmt = concat!(
|
||||
" border=\"1\"",
|
||||
" cellborder=\"1\"",
|
||||
" cellspacing=\"0\"",
|
||||
" cellpadding=\"3\"",
|
||||
" sides=\"rb\"",
|
||||
);
|
||||
write!(w, r#"<table{fmt}>"#, fmt = table_fmt)?;
|
||||
|
||||
// A + B: Block header
|
||||
if self.state_formatter.column_names().is_empty() {
|
||||
@@ -186,7 +195,7 @@ fn write_node_label(
|
||||
// C: Entry state
|
||||
self.bg = Background::Light;
|
||||
self.results.seek_to_block_start(block);
|
||||
self.write_row_with_full_state(w, "", "(on_entry)")?;
|
||||
self.write_row_with_full_state(w, "", "(on entry)")?;
|
||||
|
||||
// D: Statement transfer functions
|
||||
for (i, statement) in body[block].statements.iter().enumerate() {
|
||||
@@ -212,7 +221,7 @@ fn write_node_label(
|
||||
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
|
||||
write!(
|
||||
w,
|
||||
r#"<td colspan="{colspan}" {fmt} align="left">"#,
|
||||
r#"<td balign="left" colspan="{colspan}" {fmt} align="left">"#,
|
||||
colspan = num_state_columns,
|
||||
fmt = fmt,
|
||||
)?;
|
||||
@@ -311,7 +320,9 @@ fn write_row<W: io::Write>(
|
||||
f: impl FnOnce(&mut Self, &mut W, &str) -> io::Result<()>,
|
||||
) -> io::Result<()> {
|
||||
let bg = self.toggle_background();
|
||||
let fmt = format!("sides=\"tl\" {}", bg.attr());
|
||||
let valign = if mir.starts_with("(on ") && mir != "(on entry)" { "bottom" } else { "top" };
|
||||
|
||||
let fmt = format!("valign=\"{}\" sides=\"tl\" {}", valign, bg.attr());
|
||||
|
||||
write!(
|
||||
w,
|
||||
@@ -345,7 +356,7 @@ fn write_row_with_full_state(
|
||||
colspan = this.num_state_columns(),
|
||||
fmt = fmt,
|
||||
)?;
|
||||
pretty_print_state_elems(w, analysis, state.iter(), ",", LIMIT_40_ALIGN_1)?;
|
||||
pretty_print_state_elems(w, analysis, state.iter(), ", ", LIMIT_30_ALIGN_1)?;
|
||||
write!(w, "}}</td>")
|
||||
})
|
||||
}
|
||||
@@ -387,7 +398,6 @@ pub struct SimpleDiff<T: Idx> {
|
||||
}
|
||||
|
||||
impl<T: Idx> SimpleDiff<T> {
|
||||
#![allow(unused)]
|
||||
pub fn new(bits_per_block: usize) -> Self {
|
||||
SimpleDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START }
|
||||
}
|
||||
@@ -417,8 +427,8 @@ fn write_state_for_location(
|
||||
}
|
||||
|
||||
self.prev_loc = location;
|
||||
write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
|
||||
results.seek_before(location);
|
||||
write!(w, r#"<td {fmt} balign="left" align="left">"#, fmt = fmt)?;
|
||||
results.seek_after(location);
|
||||
let curr_state = results.get();
|
||||
write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?;
|
||||
self.prev_state.overwrite(curr_state);
|
||||
@@ -434,7 +444,6 @@ pub struct TwoPhaseDiff<T: Idx> {
|
||||
}
|
||||
|
||||
impl<T: Idx> TwoPhaseDiff<T> {
|
||||
#![allow(unused)]
|
||||
pub fn new(bits_per_block: usize) -> Self {
|
||||
TwoPhaseDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START }
|
||||
}
|
||||
@@ -445,7 +454,7 @@ impl<A> StateFormatter<'tcx, A> for TwoPhaseDiff<A::Idx>
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
fn column_names(&self) -> &[&str] {
|
||||
&["ENTRY", " EXIT"]
|
||||
&["BEFORE", " AFTER"]
|
||||
}
|
||||
|
||||
fn write_state_for_location(
|
||||
@@ -465,7 +474,7 @@ fn write_state_for_location(
|
||||
|
||||
self.prev_loc = location;
|
||||
|
||||
// Entry
|
||||
// Before
|
||||
|
||||
write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
|
||||
results.seek_before(location);
|
||||
@@ -474,7 +483,7 @@ fn write_state_for_location(
|
||||
self.prev_state.overwrite(curr_state);
|
||||
write!(w, "</td>")?;
|
||||
|
||||
// Exit
|
||||
// After
|
||||
|
||||
write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
|
||||
results.seek_after(location);
|
||||
@@ -492,7 +501,6 @@ pub struct BlockTransferFunc<'a, 'tcx, T: Idx> {
|
||||
}
|
||||
|
||||
impl<T: Idx> BlockTransferFunc<'mir, 'tcx, T> {
|
||||
#![allow(unused)]
|
||||
pub fn new(
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
trans_for_block: IndexVec<BasicBlock, GenKillSet<T>>,
|
||||
@@ -527,12 +535,12 @@ fn write_state_for_location(
|
||||
for set in &[&block_trans.gen, &block_trans.kill] {
|
||||
write!(
|
||||
w,
|
||||
r#"<td {fmt} rowspan="{rowspan}" align="center">"#,
|
||||
r#"<td {fmt} rowspan="{rowspan}" balign="left" align="left">"#,
|
||||
fmt = fmt,
|
||||
rowspan = rowspan
|
||||
)?;
|
||||
|
||||
pretty_print_state_elems(&mut w, results.analysis(), set.iter(), "\n", None)?;
|
||||
pretty_print_state_elems(&mut w, results.analysis(), set.iter(), BR_LEFT, None)?;
|
||||
write!(w, "</td>")?;
|
||||
}
|
||||
|
||||
@@ -564,25 +572,28 @@ fn write_diff<A: Analysis<'tcx>>(
|
||||
|
||||
if !set.is_empty() {
|
||||
write!(w, r#"<font color="darkgreen">+"#)?;
|
||||
pretty_print_state_elems(w, analysis, set.iter(), ",", LIMIT_40_ALIGN_1)?;
|
||||
pretty_print_state_elems(w, analysis, set.iter(), ", ", LIMIT_30_ALIGN_1)?;
|
||||
write!(w, r#"</font>"#)?;
|
||||
}
|
||||
|
||||
if !set.is_empty() && !clear.is_empty() {
|
||||
write!(w, "<br/>")?;
|
||||
write!(w, "{}", BR_LEFT)?;
|
||||
}
|
||||
|
||||
if !clear.is_empty() {
|
||||
write!(w, r#"<font color="red">-"#)?;
|
||||
pretty_print_state_elems(w, analysis, clear.iter(), ",", LIMIT_40_ALIGN_1)?;
|
||||
pretty_print_state_elems(w, analysis, clear.iter(), ", ", LIMIT_30_ALIGN_1)?;
|
||||
write!(w, r#"</font>"#)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const BR_LEFT: &'static str = r#"<br align="left"/>"#;
|
||||
const BR_LEFT_SPACE: &'static str = r#"<br align="left"/> "#;
|
||||
|
||||
/// Line break policy that breaks at 40 characters and starts the next line with a single space.
|
||||
const LIMIT_40_ALIGN_1: Option<LineBreak> = Some(LineBreak { sequence: "<br/> ", limit: 40 });
|
||||
const LIMIT_30_ALIGN_1: Option<LineBreak> = Some(LineBreak { sequence: BR_LEFT_SPACE, limit: 30 });
|
||||
|
||||
struct LineBreak {
|
||||
sequence: &'static str,
|
||||
@@ -613,13 +624,6 @@ fn pretty_print_state_elems<A>(
|
||||
let mut line_break_inserted = false;
|
||||
|
||||
for idx in elems {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
write!(w, "{}", sep)?;
|
||||
curr_line_width += sep_width;
|
||||
}
|
||||
|
||||
buf.clear();
|
||||
analysis.pretty_print_idx(&mut buf, idx)?;
|
||||
let idx_str =
|
||||
@@ -627,11 +631,18 @@ fn pretty_print_state_elems<A>(
|
||||
let escaped = dot::escape_html(idx_str);
|
||||
let escaped_width = escaped.chars().count();
|
||||
|
||||
if let Some(line_break) = &line_break {
|
||||
if curr_line_width + sep_width + escaped_width > line_break.limit {
|
||||
write!(w, "{}", line_break.sequence)?;
|
||||
line_break_inserted = true;
|
||||
curr_line_width = 0;
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
write!(w, "{}", sep)?;
|
||||
curr_line_width += sep_width;
|
||||
|
||||
if let Some(line_break) = &line_break {
|
||||
if curr_line_width + sep_width + escaped_width > line_break.limit {
|
||||
write!(w, "{}", line_break.sequence)?;
|
||||
line_break_inserted = true;
|
||||
curr_line_width = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,8 +95,6 @@ enum PrevTokenKind {
|
||||
Other,
|
||||
}
|
||||
|
||||
// NOTE: `Ident`s are handled by `common.rs`.
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Parser<'a> {
|
||||
pub sess: &'a ParseSess,
|
||||
@@ -104,14 +102,25 @@ pub struct Parser<'a> {
|
||||
/// "Normalized" means that some interpolated tokens
|
||||
/// (`$i: ident` and `$l: lifetime` meta-variables) are replaced
|
||||
/// with non-interpolated identifier and lifetime tokens they refer to.
|
||||
/// Perhaps the normalized / non-normalized setup can be simplified somehow.
|
||||
/// Use span from this token if you need an isolated span.
|
||||
pub token: Token,
|
||||
/// The span of the current non-normalized token.
|
||||
meta_var_span: Option<Span>,
|
||||
/// The span of the previous non-normalized token.
|
||||
pub prev_span: Span,
|
||||
/// The kind of the previous normalized token (in simplified form).
|
||||
/// The current non-normalized token if it's different from `token`.
|
||||
/// Preferable use is through the `unnormalized_token()` getter.
|
||||
/// Use span from this token if you need to concatenate it with some neighbouring spans.
|
||||
unnormalized_token: Option<Token>,
|
||||
/// The previous normalized token.
|
||||
/// Use span from this token if you need an isolated span.
|
||||
prev_token: Token,
|
||||
/// The previous non-normalized token if it's different from `prev_token`.
|
||||
/// Preferable use is through the `unnormalized_prev_token()` getter.
|
||||
/// Use span from this token if you need to concatenate it with some neighbouring spans.
|
||||
unnormalized_prev_token: Option<Token>,
|
||||
/// Equivalent to `prev_token.kind` in simplified form.
|
||||
/// FIXME: Remove in favor of `(unnormalized_)prev_token().kind`.
|
||||
prev_token_kind: PrevTokenKind,
|
||||
/// Equivalent to `unnormalized_prev_token().span`.
|
||||
/// FIXME: Remove in favor of `(unnormalized_)prev_token().span`.
|
||||
pub prev_span: Span,
|
||||
restrictions: Restrictions,
|
||||
/// Used to determine the path to externally loaded source files.
|
||||
pub(super) directory: Directory<'a>,
|
||||
@@ -384,9 +393,11 @@ pub fn new(
|
||||
let mut parser = Parser {
|
||||
sess,
|
||||
token: Token::dummy(),
|
||||
prev_span: DUMMY_SP,
|
||||
meta_var_span: None,
|
||||
unnormalized_token: None,
|
||||
prev_token: Token::dummy(),
|
||||
unnormalized_prev_token: None,
|
||||
prev_token_kind: PrevTokenKind::Other,
|
||||
prev_span: DUMMY_SP,
|
||||
restrictions: Restrictions::empty(),
|
||||
recurse_into_file_modules,
|
||||
directory: Directory {
|
||||
@@ -427,6 +438,14 @@ pub fn new(
|
||||
parser
|
||||
}
|
||||
|
||||
fn unnormalized_token(&self) -> &Token {
|
||||
self.unnormalized_token.as_ref().unwrap_or(&self.token)
|
||||
}
|
||||
|
||||
fn unnormalized_prev_token(&self) -> &Token {
|
||||
self.unnormalized_prev_token.as_ref().unwrap_or(&self.prev_token)
|
||||
}
|
||||
|
||||
fn next_tok(&mut self) -> Token {
|
||||
let mut next = if self.desugar_doc_comments {
|
||||
self.token_cursor.next_desugared()
|
||||
@@ -435,7 +454,7 @@ fn next_tok(&mut self) -> Token {
|
||||
};
|
||||
if next.span.is_dummy() {
|
||||
// Tweak the location for better diagnostics, but keep syntactic context intact.
|
||||
next.span = self.prev_span.with_ctxt(next.span.ctxt());
|
||||
next.span = self.unnormalized_token().span.with_ctxt(next.span.ctxt());
|
||||
}
|
||||
next
|
||||
}
|
||||
@@ -895,10 +914,13 @@ pub fn bump(&mut self) {
|
||||
self.span_bug(self.token.span, msg);
|
||||
}
|
||||
|
||||
self.prev_span = self.meta_var_span.take().unwrap_or(self.token.span);
|
||||
// Update the current and previous tokens.
|
||||
let next_token = self.next_tok();
|
||||
self.prev_token = mem::replace(&mut self.token, next_token);
|
||||
self.unnormalized_prev_token = self.unnormalized_token.take();
|
||||
|
||||
// Record last token kind for possible error recovery.
|
||||
self.prev_token_kind = match self.token.kind {
|
||||
// Update fields derived from the previous token.
|
||||
self.prev_token_kind = match self.prev_token.kind {
|
||||
token::DocComment(..) => PrevTokenKind::DocComment,
|
||||
token::Comma => PrevTokenKind::Comma,
|
||||
token::BinOp(token::Plus) => PrevTokenKind::Plus,
|
||||
@@ -908,8 +930,8 @@ pub fn bump(&mut self) {
|
||||
token::Ident(..) => PrevTokenKind::Ident,
|
||||
_ => PrevTokenKind::Other,
|
||||
};
|
||||
self.prev_span = self.unnormalized_prev_token().span;
|
||||
|
||||
self.token = self.next_tok();
|
||||
self.expected_tokens.clear();
|
||||
// Check after each token.
|
||||
self.process_potential_macro_variable();
|
||||
@@ -917,13 +939,19 @@ pub fn bump(&mut self) {
|
||||
|
||||
/// Advances the parser using provided token as a next one. Use this when
|
||||
/// consuming a part of a token. For example a single `<` from `<<`.
|
||||
/// FIXME: this function sets the previous token data to some semi-nonsensical values
|
||||
/// which kind of work because they are currently used in very limited ways in practice.
|
||||
/// Correct token kinds and spans need to be calculated instead.
|
||||
fn bump_with(&mut self, next: TokenKind, span: Span) {
|
||||
self.prev_span = self.token.span.with_hi(span.lo());
|
||||
// It would be incorrect to record the kind of the current token, but
|
||||
// fortunately for tokens currently using `bump_with`, the
|
||||
// `prev_token_kind` will be of no use anyway.
|
||||
// Update the current and previous tokens.
|
||||
let next_token = Token::new(next, span);
|
||||
self.prev_token = mem::replace(&mut self.token, next_token);
|
||||
self.unnormalized_prev_token = self.unnormalized_token.take();
|
||||
|
||||
// Update fields derived from the previous token.
|
||||
self.prev_token_kind = PrevTokenKind::Other;
|
||||
self.token = Token::new(next, span);
|
||||
self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo());
|
||||
|
||||
self.expected_tokens.clear();
|
||||
}
|
||||
|
||||
@@ -1054,7 +1082,7 @@ fn parse_or_use_outer_attributes(
|
||||
}
|
||||
|
||||
pub fn process_potential_macro_variable(&mut self) {
|
||||
self.token = match self.token.kind {
|
||||
let normalized_token = match self.token.kind {
|
||||
token::Dollar
|
||||
if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) =>
|
||||
{
|
||||
@@ -1071,7 +1099,6 @@ pub fn process_potential_macro_variable(&mut self) {
|
||||
return;
|
||||
}
|
||||
token::Interpolated(ref nt) => {
|
||||
self.meta_var_span = Some(self.token.span);
|
||||
// Interpolated identifier and lifetime tokens are replaced with usual identifier
|
||||
// and lifetime tokens, so the former are never encountered during normal parsing.
|
||||
match **nt {
|
||||
@@ -1084,6 +1111,7 @@ pub fn process_potential_macro_variable(&mut self) {
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token));
|
||||
}
|
||||
|
||||
/// Parses a single token tree from the input.
|
||||
@@ -1100,7 +1128,7 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
|
||||
}
|
||||
token::CloseDelim(_) | token::Eof => unreachable!(),
|
||||
_ => {
|
||||
let token = self.token.take();
|
||||
let token = self.token.clone();
|
||||
self.bump();
|
||||
TokenTree::Token(token)
|
||||
}
|
||||
|
||||
@@ -542,11 +542,14 @@ fn visit_mac(&mut self, mac: &mut Mac) {
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &mut P<Pat>) {
|
||||
if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Not), ..) =
|
||||
pat.kind
|
||||
{
|
||||
*m = Mutability::Mut;
|
||||
if let PatKind::Ident(ref mut bm, ..) = pat.kind {
|
||||
if let BindingMode::ByValue(ref mut m @ Mutability::Not) = bm {
|
||||
*m = Mutability::Mut;
|
||||
}
|
||||
self.0 = true;
|
||||
// Don't recurse into the subpattern, mut on the outer
|
||||
// binding doesn't affect the inner bindings.
|
||||
return;
|
||||
}
|
||||
noop_visit_pat(pat, self);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
|
||||
path
|
||||
});
|
||||
|
||||
let lo = self.meta_var_span.unwrap_or(self.token.span);
|
||||
let lo = self.unnormalized_token().span;
|
||||
let mut segments = Vec::new();
|
||||
let mod_sep_ctxt = self.token.span.ctxt();
|
||||
if self.eat(&token::ModSep) {
|
||||
|
||||
@@ -226,7 +226,9 @@ fn regions(
|
||||
let b = match b {
|
||||
&ty::ReVar(vid) => self
|
||||
.infcx
|
||||
.borrow_region_constraints()
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.infcx.tcx, vid),
|
||||
|
||||
other => other,
|
||||
|
||||
@@ -18,14 +18,12 @@
|
||||
use rustc_hir::ItemKind;
|
||||
|
||||
pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
|
||||
let lang_items = tcx.lang_items();
|
||||
Checker { tcx, trait_def_id }
|
||||
.check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
|
||||
.check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
|
||||
.check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
|
||||
.check(
|
||||
tcx.lang_items().dispatch_from_dyn_trait(),
|
||||
visit_implementation_of_dispatch_from_dyn,
|
||||
);
|
||||
.check(lang_items.drop_trait(), visit_implementation_of_drop)
|
||||
.check(lang_items.copy_trait(), visit_implementation_of_copy)
|
||||
.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
|
||||
}
|
||||
|
||||
struct Checker<'tcx> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::namespace::Namespace;
|
||||
use rustc::traits::{self, IntercrateMode, SkipLeakCheck};
|
||||
use rustc::traits::{self, SkipLeakCheck};
|
||||
use rustc::ty::{AssocItem, TyCtxt};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
@@ -93,7 +93,6 @@ fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id
|
||||
self.tcx,
|
||||
impl1_def_id,
|
||||
impl2_def_id,
|
||||
IntercrateMode::Issue43355,
|
||||
// We go ahead and just skip the leak check for
|
||||
// inherent impls without warning.
|
||||
SkipLeakCheck::Yes,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
use rustc::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_span::Span;
|
||||
|
||||
mod builtin;
|
||||
mod inherent_impls;
|
||||
@@ -18,37 +18,35 @@
|
||||
mod orphan;
|
||||
mod unsafety;
|
||||
|
||||
fn check_impl(tcx: TyCtxt<'_>, hir_id: HirId) {
|
||||
let impl_def_id = tcx.hir().local_def_id(hir_id);
|
||||
/// Obtains the span of just the impl header of `impl_def_id`.
|
||||
fn impl_header_span(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Span {
|
||||
tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap())
|
||||
}
|
||||
|
||||
// If there are no traits, then this implementation must have a
|
||||
// base type.
|
||||
fn check_impl(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_ref: ty::TraitRef<'_>) {
|
||||
debug!(
|
||||
"(checking implementation) adding impl for trait '{:?}', item '{}'",
|
||||
trait_ref,
|
||||
tcx.def_path_str(impl_def_id)
|
||||
);
|
||||
|
||||
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
|
||||
debug!(
|
||||
"(checking implementation) adding impl for trait '{:?}', item '{}'",
|
||||
trait_ref,
|
||||
tcx.def_path_str(impl_def_id)
|
||||
);
|
||||
|
||||
// Skip impls where one of the self type is an error type.
|
||||
// This occurs with e.g., resolve failures (#30589).
|
||||
if trait_ref.references_error() {
|
||||
return;
|
||||
}
|
||||
|
||||
enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
|
||||
enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
|
||||
// Skip impls where one of the self type is an error type.
|
||||
// This occurs with e.g., resolve failures (#30589).
|
||||
if trait_ref.references_error() {
|
||||
return;
|
||||
}
|
||||
|
||||
enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
|
||||
enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
|
||||
}
|
||||
|
||||
fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_def_id: DefId) {
|
||||
let did = Some(trait_def_id);
|
||||
let li = tcx.lang_items();
|
||||
let span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||
|
||||
// Disallow *all* explicit impls of `Sized` and `Unsize` for now.
|
||||
if did == li.sized_trait() {
|
||||
let span = impl_header_span(tcx, impl_def_id);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
@@ -61,6 +59,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra
|
||||
}
|
||||
|
||||
if did == li.unsize_trait() {
|
||||
let span = impl_header_span(tcx, impl_def_id);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
@@ -86,6 +85,8 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra
|
||||
} else {
|
||||
return; // everything OK
|
||||
};
|
||||
|
||||
let span = impl_header_span(tcx, impl_def_id);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
@@ -109,7 +110,7 @@ fn enforce_empty_impls_for_marker_traits(tcx: TyCtxt<'_>, impl_def_id: DefId, tr
|
||||
return;
|
||||
}
|
||||
|
||||
let span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||
let span = impl_header_span(tcx, impl_def_id);
|
||||
struct_span_err!(tcx.sess, span, E0715, "impls for marker traits cannot contain items").emit();
|
||||
}
|
||||
|
||||
@@ -129,12 +130,17 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||
}
|
||||
|
||||
fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
// Trigger building the specialization graph for the trait. This will detect and report any
|
||||
// overlap errors.
|
||||
tcx.specialization_graph_of(def_id);
|
||||
|
||||
let impls = tcx.hir().trait_impls(def_id);
|
||||
for &impl_id in impls {
|
||||
check_impl(tcx, impl_id);
|
||||
}
|
||||
for &impl_id in impls {
|
||||
check_impl_overlap(tcx, impl_id);
|
||||
for &hir_id in impls {
|
||||
let impl_def_id = tcx.hir().local_def_id(hir_id);
|
||||
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||
|
||||
check_impl(tcx, impl_def_id, trait_ref);
|
||||
check_object_overlap(tcx, impl_def_id, trait_ref);
|
||||
}
|
||||
builtin::check_trait(tcx, def_id);
|
||||
}
|
||||
@@ -152,12 +158,12 @@ pub fn check_coherence(tcx: TyCtxt<'_>) {
|
||||
tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE);
|
||||
}
|
||||
|
||||
/// Overlap: no two impls for the same trait are implemented for the
|
||||
/// same type. Likewise, no two inherent impls for a given type
|
||||
/// constructor provide a method with the same name.
|
||||
fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
|
||||
let impl_def_id = tcx.hir().local_def_id(hir_id);
|
||||
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||
/// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
|
||||
fn check_object_overlap<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_def_id: DefId,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
) {
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
|
||||
if trait_ref.references_error() {
|
||||
@@ -165,11 +171,7 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger building the specialization graph for the trait of this impl.
|
||||
// This will detect any overlap errors.
|
||||
tcx.specialization_graph_of(trait_def_id);
|
||||
|
||||
// check for overlap with the automatic `impl Trait for Trait`
|
||||
// check for overlap with the automatic `impl Trait for dyn Trait`
|
||||
if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().kind {
|
||||
// This is something like impl Trait1 for Trait2. Illegal
|
||||
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
|
||||
@@ -194,17 +196,17 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
|
||||
} else {
|
||||
let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
|
||||
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
||||
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
|
||||
let span = impl_header_span(tcx, impl_def_id);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
sp,
|
||||
span,
|
||||
E0371,
|
||||
"the object type `{}` automatically implements the trait `{}`",
|
||||
trait_ref.self_ty(),
|
||||
tcx.def_path_str(trait_def_id)
|
||||
)
|
||||
.span_label(
|
||||
sp,
|
||||
span,
|
||||
format!(
|
||||
"`{}` automatically implements trait `{}`",
|
||||
trait_ref.self_ty(),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
error[E0391]: cycle detected when processing `Trait`
|
||||
error[E0391]: cycle detected when building specialization graph of trait `Trait`
|
||||
--> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
|
||||
|
|
||||
LL | trait Trait<T> { type Assoc; }
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires processing `Trait`, completing the cycle
|
||||
= note: ...which again requires building specialization graph of trait `Trait`, completing the cycle
|
||||
note: cycle used when coherence checking all impls of trait `Trait`
|
||||
--> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
|
||||
|
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
// run-pass
|
||||
|
||||
#![feature(const_nonzero_int_methods)]
|
||||
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
const X: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) };
|
||||
const Y: u8 = X.get();
|
||||
|
||||
const ZERO: Option<NonZeroU8> = NonZeroU8::new(0);
|
||||
const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
|
||||
|
||||
fn main() {
|
||||
assert_eq!(Y, 5);
|
||||
|
||||
assert!(ZERO.is_none());
|
||||
assert_eq!(ONE.unwrap().get(), 1);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ LL | macro_rules! abc(ؼ;
|
||||
| ^
|
||||
|
||||
error: unexpected end of macro invocation
|
||||
--> $DIR/mbe_missing_right_paren.rs:3:1
|
||||
--> $DIR/mbe_missing_right_paren.rs:3:19
|
||||
|
|
||||
LL | macro_rules! abc(ؼ
|
||||
| ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
||||
| ^ missing tokens in macro arguments
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![deny(unused_mut)]
|
||||
|
||||
fn main() {
|
||||
let mut is_mut @ not_mut = 42;
|
||||
&mut is_mut;
|
||||
¬_mut;
|
||||
let not_mut @ mut is_mut = 42;
|
||||
&mut is_mut;
|
||||
¬_mut;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
fn main() {
|
||||
let mut is_mut @ not_mut = 42;
|
||||
&mut is_mut;
|
||||
&mut not_mut;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
let not_mut @ mut is_mut = 42;
|
||||
&mut is_mut;
|
||||
&mut not_mut;
|
||||
//~^ ERROR cannot borrow
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable
|
||||
--> $DIR/nested-binding-modes-mut.rs:6:5
|
||||
|
|
||||
LL | let mut is_mut @ not_mut = 42;
|
||||
| ------- help: consider changing this to be mutable: `mut not_mut`
|
||||
LL | &mut is_mut;
|
||||
LL | &mut not_mut;
|
||||
| ^^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable
|
||||
--> $DIR/nested-binding-modes-mut.rs:11:5
|
||||
|
|
||||
LL | let not_mut @ mut is_mut = 42;
|
||||
| -------------------- help: consider changing this to be mutable: `mut not_mut`
|
||||
LL | &mut is_mut;
|
||||
LL | &mut not_mut;
|
||||
| ^^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0596`.
|
||||
@@ -0,0 +1,13 @@
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
fn main() {
|
||||
let ref is_ref @ is_val = 42;
|
||||
*is_ref;
|
||||
*is_val;
|
||||
//~^ ERROR cannot be dereferenced
|
||||
|
||||
let is_val @ ref is_ref = 42;
|
||||
*is_ref;
|
||||
*is_val;
|
||||
//~^ ERROR cannot be dereferenced
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
error[E0614]: type `{integer}` cannot be dereferenced
|
||||
--> $DIR/nested-binding-modes-ref.rs:6:5
|
||||
|
|
||||
LL | *is_val;
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0614]: type `{integer}` cannot be dereferenced
|
||||
--> $DIR/nested-binding-modes-ref.rs:11:5
|
||||
|
|
||||
LL | *is_val;
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0614`.
|
||||
Reference in New Issue
Block a user