summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/type_check
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/type_check')
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs11
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs20
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs181
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs100
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs63
8 files changed, 234 insertions, 163 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 11729e2c8..b27d5d205 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -2,7 +2,7 @@ use std::fmt;
use rustc_infer::infer::{canonical::Canonical, InferOk};
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
@@ -66,7 +66,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
canonical: &Canonical<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let old_universe = self.infcx.universe();
@@ -117,7 +117,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn prove_predicates(
&mut self,
- predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
+ predicates: impl IntoIterator<Item: ToPredicate<'tcx> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
@@ -181,9 +181,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_ty: ty::UserType<'tcx>,
span: Span,
) {
- // FIXME: Ideally MIR types are normalized, but this is not always true.
- let mir_ty = self.normalize(mir_ty, Locations::All(span));
-
self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
@@ -217,7 +214,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return;
}
+ // FIXME: Ideally MIR types are normalized, but this is not always true.
let mir_ty = self.normalize(mir_ty, Locations::All(span));
+
let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env;
let op = |infcx: &'_ _| {
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index e15d1b99a..a93561350 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -6,8 +6,8 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
use rustc_span::{Span, DUMMY_SP};
use crate::{
@@ -83,16 +83,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
self.constraints.member_constraints = tmp;
- for (predicate, constraint_category) in outlives {
- // At the moment, we never generate any "higher-ranked"
- // region constraints like `for<'a> 'a: 'b`. At some point
- // when we move to universes, we will, and this assertion
- // will start to fail.
- let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
- bug!("query_constraint {:?} contained bound vars", predicate,);
- });
-
- self.convert(predicate, *constraint_category);
+ for &(predicate, constraint_category) in outlives {
+ self.convert(predicate, constraint_category);
}
}
@@ -124,7 +116,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
let subject = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
- ClosureOutlivesSubject::Ty(ty) => ty.into(),
+ ClosureOutlivesSubject::Ty(subject_ty) => {
+ subject_ty.instantiate(self.tcx, |vid| closure_mapping[vid]).into()
+ }
};
self.category = outlives_requirement.category;
@@ -179,7 +173,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
///
/// FIXME: This should get removed once higher ranked region obligations
/// are dealt with during trait solving.
- fn replace_placeholders_with_nll<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
+ fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
if value.has_placeholders() {
self.tcx.fold_regions(value, |r, _| match *r {
ty::RePlaceholder(placeholder) => {
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 82ff86247..4004966c4 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,6 +8,7 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
+use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
@@ -92,31 +93,6 @@ impl UniversalRegionRelations<'_> {
res
}
- /// Returns the "postdominating" bound of the set of
- /// `non_local_upper_bounds` for the given region.
- pub(crate) fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
- let upper_bounds = self.non_local_upper_bounds(fr);
-
- // In case we find more than one, reduce to one for
- // convenience. This is to prevent us from generating more
- // complex constraints, but it will cause spurious errors.
- let post_dom = self.inverse_outlives.mutual_immediate_postdominator(upper_bounds);
-
- debug!("non_local_bound: post_dom={:?}", post_dom);
-
- post_dom
- .and_then(|post_dom| {
- // If the mutual immediate postdom is not local, then
- // there is no non-local result we can return.
- if !self.universal_regions.is_local_free_region(post_dom) {
- Some(post_dom)
- } else {
- None
- }
- })
- .unwrap_or(self.universal_regions.fr_static)
- }
-
/// Finds a "lower bound" for `fr` that is not local. In other
/// words, returns the largest (*) known region `fr1` that (a) is
/// outlived by `fr` and (b) is not local.
@@ -217,8 +193,27 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.inverse_outlives.add(fr_b, fr_a);
}
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
+
+ // Insert the facts we know from the predicates. Why? Why not.
+ let param_env = self.param_env;
+ self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
+
+ // - outlives is reflexive, so `'r: 'r` for every region `'r`
+ // - `'static: 'r` for every region `'r`
+ // - `'r: 'fn_body` for every (other) universally quantified
+ // region `'r`, all of which are provided by our caller
+ let fr_static = self.universal_regions.fr_static;
+ let fr_fn_body = self.universal_regions.fr_fn_body;
+ for fr in self.universal_regions.universal_regions() {
+ debug!("build: relating free region {:?} to itself and to 'static", fr);
+ self.relate_universal_regions(fr, fr);
+ self.relate_universal_regions(fr_static, fr);
+ self.relate_universal_regions(fr, fr_fn_body);
+ }
+
let unnormalized_input_output_tys = self
.universal_regions
.unnormalized_input_tys
@@ -236,78 +231,59 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
// the `relations` is built.
let mut normalized_inputs_and_output =
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
- let constraint_sets: Vec<_> = unnormalized_input_output_tys
- .flat_map(|ty| {
- debug!("build: input_or_output={:?}", ty);
- // We add implied bounds from both the unnormalized and normalized ty.
- // See issue #87748
- let constraints_implied1 = self.add_implied_bounds(ty);
- let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
- .param_env
- .and(type_op::normalize::Normalize::new(ty))
- .fully_perform(self.infcx)
- .unwrap_or_else(|_| {
- let reported = self
- .infcx
- .tcx
- .sess
- .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
- TypeOpOutput {
- output: self.infcx.tcx.ty_error_with_guaranteed(reported),
- constraints: None,
- error_info: None,
- }
- });
- // Note: we need this in examples like
- // ```
- // trait Foo {
- // type Bar;
- // fn foo(&self) -> &Self::Bar;
- // }
- // impl Foo for () {
- // type Bar = ();
- // fn foo(&self) -> &() {}
- // }
- // ```
- // Both &Self::Bar and &() are WF
- let constraints_implied2 =
- if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
- normalized_inputs_and_output.push(norm_ty);
- constraints1.into_iter().chain(constraints_implied1).chain(constraints_implied2)
- })
- .collect();
+ let mut constraints = vec![];
+ for ty in unnormalized_input_output_tys {
+ debug!("build: input_or_output={:?}", ty);
+ // We add implied bounds from both the unnormalized and normalized ty.
+ // See issue #87748
+ let constraints_unnorm = self.add_implied_bounds(ty);
+ if let Some(c) = constraints_unnorm {
+ constraints.push(c)
+ }
+ let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
+ .param_env
+ .and(type_op::normalize::Normalize::new(ty))
+ .fully_perform(self.infcx)
+ .unwrap_or_else(|_| {
+ let guar = self
+ .infcx
+ .tcx
+ .sess
+ .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
+ TypeOpOutput {
+ output: self.infcx.tcx.ty_error(guar),
+ constraints: None,
+ error_info: None,
+ }
+ });
+ if let Some(c) = constraints_normalize {
+ constraints.push(c)
+ }
- // Insert the facts we know from the predicates. Why? Why not.
- let param_env = self.param_env;
- self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
+ // Note: we need this in examples like
+ // ```
+ // trait Foo {
+ // type Bar;
+ // fn foo(&self) -> &Self::Bar;
+ // }
+ // impl Foo for () {
+ // type Bar = ();
+ // fn foo(&self) ->&() {}
+ // }
+ // ```
+ // Both &Self::Bar and &() are WF
+ if ty != norm_ty {
+ let constraints_norm = self.add_implied_bounds(norm_ty);
+ if let Some(c) = constraints_norm {
+ constraints.push(c)
+ }
+ }
- // Finally:
- // - outlives is reflexive, so `'r: 'r` for every region `'r`
- // - `'static: 'r` for every region `'r`
- // - `'r: 'fn_body` for every (other) universally quantified
- // region `'r`, all of which are provided by our caller
- let fr_static = self.universal_regions.fr_static;
- let fr_fn_body = self.universal_regions.fr_fn_body;
- for fr in self.universal_regions.universal_regions() {
- debug!("build: relating free region {:?} to itself and to 'static", fr);
- self.relate_universal_regions(fr, fr);
- self.relate_universal_regions(fr_static, fr);
- self.relate_universal_regions(fr, fr_fn_body);
+ normalized_inputs_and_output.push(norm_ty);
}
- for data in &constraint_sets {
- constraint_conversion::ConstraintConversion::new(
- self.infcx,
- &self.universal_regions,
- &self.region_bound_pairs,
- self.implicit_region_bound,
- self.param_env,
- Locations::All(span),
- span,
- ConstraintCategory::Internal,
- &mut self.constraints,
- )
- .convert_all(data);
+ for c in constraints {
+ self.push_region_constraints(c, span);
}
CreateResult {
@@ -321,6 +297,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
}
}
+ #[instrument(skip(self, data), level = "debug")]
+ fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) {
+ debug!("constraints generated: {:#?}", data);
+
+ constraint_conversion::ConstraintConversion::new(
+ self.infcx,
+ &self.universal_regions,
+ &self.region_bound_pairs,
+ self.implicit_region_bound,
+ self.param_env,
+ Locations::All(span),
+ span,
+ ConstraintCategory::Internal,
+ &mut self.constraints,
+ )
+ .convert_all(data);
+ }
+
/// Update the type of a single local, which should represent
/// either the return type of the MIR or one of its arguments. At
/// the same time, compute and add any implied bounds that come
@@ -332,6 +326,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self.infcx)
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
+ debug!(?bounds, ?constraints);
self.add_outlives_bounds(bounds);
constraints
}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index fa9ea769a..717020ea5 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -26,11 +26,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
return;
}
- let Some(user_provided_poly_sig) =
- self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
- else {
- return;
- };
+ let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
// Instantiate the canonicalized variables from user-provided signature
// (e.g., the `_` in the code above) with fresh variables.
@@ -38,7 +34,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// so that they represent the view from "inside" the closure.
let user_provided_sig = self
.instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig);
- let user_provided_sig = self.infcx.replace_bound_vars_with_fresh_vars(
+ let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
body.span,
LateBoundRegionConversionTime::FnCall,
user_provided_sig,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index d5c401ae1..a411aec51 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -50,13 +50,11 @@ pub(super) fn generate<'mir, 'tcx>(
compute_relevant_live_locals(typeck.tcx(), &free_regions, &body);
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
- let polonius_drop_used = if facts_enabled {
+ let polonius_drop_used = facts_enabled.then(|| {
let mut drop_used = Vec::new();
polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used);
- Some(drop_used)
- } else {
- None
- };
+ drop_used
+ });
trace::trace(
typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 3ff5d188a..473c05963 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,7 +3,7 @@ use rustc_index::bit_set::HybridBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
-use rustc_middle::ty::{Ty, TypeVisitable};
+use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -477,7 +477,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// points `live_at`.
fn add_use_live_facts_for(
&mut self,
- value: impl TypeVisitable<'tcx>,
+ value: impl TypeVisitable<TyCtxt<'tcx>>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("add_use_live_facts_for(value={:?})", value);
@@ -542,7 +542,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
fn make_all_regions_live(
elements: &RegionValueElements,
typeck: &mut TypeChecker<'_, 'tcx>,
- value: impl TypeVisitable<'tcx>,
+ value: impl TypeVisitable<TyCtxt<'tcx>>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("make_all_regions_live(value={:?})", value);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 81bd4c2a7..a49da3da6 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -30,7 +30,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
@@ -64,7 +64,7 @@ use crate::{
region_infer::TypeTest,
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
universal_regions::{DefiningTy, UniversalRegions},
- Upvar,
+ BorrowckInferCtxt, Upvar,
};
macro_rules! span_mirbug {
@@ -123,7 +123,7 @@ mod relate_tys;
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
/// - `elements` -- MIR region map
pub(crate) fn type_check<'mir, 'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -137,7 +137,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
upvars: &[Upvar<'tcx>],
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
- let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+ let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -239,7 +239,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
- hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
+ hidden_type.ty = infcx.tcx.ty_error(reported);
}
(opaque_type_key, (hidden_type, decl.origin))
@@ -402,7 +402,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
);
}
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
- let unnormalized_ty = tcx.type_of(static_def_id);
+ let unnormalized_ty = tcx.type_of(static_def_id).subst_identity();
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
@@ -529,12 +529,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
- if place_ty.ty.references_error() {
+ if let Err(guar) = place_ty.ty.error_reported() {
assert!(self.errors_reported);
- return PlaceTy::from_ty(self.tcx().ty_error());
+ return PlaceTy::from_ty(self.tcx().ty_error(guar));
}
}
- place_ty = self.sanitize_projection(place_ty, elem, place, location);
+ place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
}
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
@@ -630,12 +630,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
}
+ #[instrument(skip(self), level = "debug")]
fn sanitize_projection(
&mut self,
base: PlaceTy<'tcx>,
pi: PlaceElem<'tcx>,
place: &Place<'tcx>,
location: Location,
+ context: PlaceContext,
) -> PlaceTy<'tcx> {
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
let tcx = self.tcx();
@@ -713,8 +715,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
match self.field_ty(place, base, field, location) {
Ok(ty) => {
let ty = self.cx.normalize(ty, location);
- if let Err(terr) = self.cx.eq_types(
+ debug!(?fty, ?ty);
+
+ if let Err(terr) = self.cx.relate_types(
ty,
+ self.get_ambient_variance(context),
fty,
location.to_locations(),
ConstraintCategory::Boring,
@@ -743,9 +748,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
let ty = self.sanitize_type(place, ty);
let ty = self.cx.normalize(ty, location);
self.cx
- .eq_types(
- base.ty,
+ .relate_types(
ty,
+ self.get_ambient_variance(context),
+ base.ty,
location.to_locations(),
ConstraintCategory::TypeAnnotation,
)
@@ -757,7 +763,22 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
fn error(&mut self) -> Ty<'tcx> {
self.errors_reported = true;
- self.tcx().ty_error()
+ self.tcx().ty_error_misc()
+ }
+
+ fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
+ use rustc_middle::mir::visit::NonMutatingUseContext::*;
+ use rustc_middle::mir::visit::NonUseContext::*;
+
+ match context {
+ PlaceContext::MutatingUse(_) => ty::Invariant,
+ PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+ PlaceContext::NonMutatingUse(
+ Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
+ | Projection,
+ ) => ty::Covariant,
+ PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
+ }
}
fn field_ty(
@@ -845,7 +866,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
/// way, it accrues region constraints -- these can later be used by
/// NLL region checking.
struct TypeChecker<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
body: &'a Body<'tcx>,
@@ -910,6 +931,8 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
}
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
+ /// Creates a `Region` for a given `PlaceholderRegion`, or returns the
+ /// region that corresponds to a previously created one.
fn placeholder_region(
&mut self,
infcx: &InferCtxt<'tcx>,
@@ -996,7 +1019,7 @@ impl Locations {
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1258,6 +1281,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| StatementKind::StorageDead(..)
| StatementKind::Retag { .. }
| StatementKind::Coverage(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
@@ -1332,11 +1356,34 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
};
let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
- self.infcx.next_region_var(LateBoundRegion(
- term.source_info.span,
- br.kind,
- LateBoundRegionConversionTime::FnCall,
- ))
+ use crate::renumber::{BoundRegionInfo, RegionCtxt};
+ use rustc_span::Symbol;
+
+ let region_ctxt_fn = || {
+ let reg_info = match br.kind {
+ ty::BoundRegionKind::BrAnon(_, Some(span)) => {
+ BoundRegionInfo::Span(span)
+ }
+ ty::BoundRegionKind::BrAnon(..) => {
+ BoundRegionInfo::Name(Symbol::intern("anon"))
+ }
+ ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
+ ty::BoundRegionKind::BrEnv => {
+ BoundRegionInfo::Name(Symbol::intern("env"))
+ }
+ };
+
+ RegionCtxt::LateBound(reg_info)
+ };
+
+ self.infcx.next_region_var(
+ LateBoundRegion(
+ term.source_info.span,
+ br.kind,
+ LateBoundRegionConversionTime::FnCall,
+ ),
+ region_ctxt_fn,
+ )
});
debug!(?sig);
// IMPORTANT: We have to prove well formed for the function signature before
@@ -1483,7 +1530,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
None => {
- if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
+ // The signature in this call can reference region variables,
+ // so erase them before calling a query.
+ let output_ty = self.tcx().erase_regions(sig.output());
+ if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
}
@@ -1776,7 +1826,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// than 1.
// If the length is larger than 1, the repeat expression will need to copy the
// element, so we require the `Copy` trait.
- if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+ if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
match operand {
Operand::Copy(..) | Operand::Constant(..) => {
// These are always okay: direct use of a const, or a value that can evidently be copied.
@@ -2027,7 +2077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
};
- if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
+ if ty_to_mut.is_mut() && ty_mut.is_not() {
span_mirbug!(
self,
rvalue,
@@ -2532,7 +2582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// clauses on the struct.
AggregateKind::Closure(def_id, substs)
| AggregateKind::Generator(def_id, substs, _) => {
- (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location))
+ (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
}
AggregateKind::Array(_) | AggregateKind::Tuple => {
@@ -2583,7 +2633,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
other => bug!("unexpected item {:?}", other),
};
- let parent_substs = tcx.mk_substs(parent_substs.iter());
+ let parent_substs = tcx.mk_substs(parent_substs);
assert_eq!(typeck_root_substs.len(), parent_substs.len());
if let Err(_) = self.eq_substs(
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index b2702eafd..d96372fb9 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,14 +1,15 @@
-use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
+use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{self, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use rustc_trait_selection::traits::query::Fallible;
use crate::constraints::OutlivesConstraint;
use crate::diagnostics::UniverseInfo;
+use crate::renumber::{BoundRegionInfo, RegionCtxt};
use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
@@ -100,23 +101,65 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
universe
}
- fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
+ #[instrument(skip(self), level = "debug")]
+ fn next_existential_region_var(
+ &mut self,
+ from_forall: bool,
+ _name: Option<Symbol>,
+ ) -> ty::Region<'tcx> {
let origin = NllRegionVariableOrigin::Existential { from_forall };
- self.type_checker.infcx.next_nll_region_var(origin)
+
+ let reg_var =
+ self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name));
+
+ reg_var
}
+ #[instrument(skip(self), level = "debug")]
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
- self.type_checker
+ let reg = self
+ .type_checker
.borrowck_context
.constraints
- .placeholder_region(self.type_checker.infcx, placeholder)
+ .placeholder_region(self.type_checker.infcx, placeholder);
+
+ let reg_info = match placeholder.name {
+ ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span),
+ ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
+ ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
+ ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")),
+ };
+
+ let reg_var =
+ reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
+ let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info));
+ assert!(matches!(prev, None));
+
+ reg
}
+ #[instrument(skip(self), level = "debug")]
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
- self.type_checker.infcx.next_nll_region_var_in_universe(
+ let reg = self.type_checker.infcx.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
universe,
- )
+ );
+
+ let reg_var =
+ reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
+
+ if cfg!(debug_assertions) {
+ let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(reg_var, RegionCtxt::Existential(None));
+
+ // It only makes sense to track region vars in non-canonicalization contexts. If this
+ // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
+ // or modify how we track nll region vars for that map.
+ assert!(matches!(prev, None));
+ }
+
+ reg
}
fn push_outlives(
@@ -140,10 +183,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
);
}
- fn normalization() -> NormalizationStrategy {
- NormalizationStrategy::Eager
- }
-
fn forbid_inference_vars() -> bool {
true
}