diff options
Diffstat (limited to 'compiler/rustc_infer/src/infer/canonical')
4 files changed, 62 insertions, 60 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index ca7862c9d..a3ff70363 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::Idx; use smallvec::SmallVec; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { /// Canonicalizes a query value `V`. When we canonicalize a query, /// we not only canonicalize unbound inference variables, but we /// *also* replace all free regions whatsoever. So for example a @@ -180,11 +180,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { match *r { - ty::ReFree(_) - | ty::ReErased - | ty::ReStatic - | ty::ReEmpty(ty::UniverseIndex::ROOT) - | ty::ReEarlyBound(..) => r, + ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r, ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region( CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) }, @@ -199,10 +195,6 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { ) } - ty::ReEmpty(ui) => { - bug!("canonicalizing 'empty in universe {:?}", ui) // FIXME - } - _ => { // Other than `'static` or `'empty`, the query // response should be executing in a fully @@ -324,7 +316,7 @@ impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic { } struct Canonicalizer<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, + infcx: &'cx InferCtxt<'tcx>, tcx: TyCtxt<'tcx>, variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>, query_state: &'cx mut OriginalQueryValues<'tcx>, @@ -372,7 +364,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { debug!( "canonical: region var found with vid {:?}, \ opportunistically resolved to {:?}", - vid, r + vid, resolved_vid ); let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid)); self.canonicalize_mode.canonicalize_free_region(self, r) @@ -381,7 +373,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { ty::ReStatic | ty::ReEarlyBound(..) | ty::ReFree(_) - | ty::ReEmpty(_) | ty::RePlaceholder(..) | ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r), } @@ -530,7 +521,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// `canonicalize_query` and `canonicalize_response`. fn canonicalize<V>( value: V, - infcx: &InferCtxt<'_, 'tcx>, + infcx: &InferCtxt<'tcx>, tcx: TyCtxt<'tcx>, canonicalize_region_mode: &dyn CanonicalizeMode, query_state: &mut OriginalQueryValues<'tcx>, diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index a9294a85e..06ca2534d 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -36,7 +36,7 @@ mod canonicalizer; pub mod query_response; mod substitute; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { /// Creates a substitution S for the canonical value with fresh /// inference variables and applies it to the canonical value. /// Returns both the instantiated result *and* the substitution S. diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8dc20544f..a299a3e57 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -16,12 +16,13 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; -use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{PredicateObligations, TraitEngine}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; use rustc_middle::arena::ArenaAllocatable; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; @@ -31,7 +32,7 @@ use rustc_span::Span; use std::fmt::Debug; use std::iter; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { /// This method is meant to be invoked as the final step of a canonical query /// implementation. It is given: /// @@ -63,8 +64,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; + debug!("query_response = {:#?}", query_response); let canonical_result = self.canonicalize_response(query_response); - debug!("canonical_result = {:#?}", canonical_result); Ok(self.tcx.arena.alloc(canonical_result)) @@ -125,13 +126,17 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { debug!("ambig_errors = {:#?}", ambig_errors); let region_obligations = self.take_registered_region_obligations(); + debug!(?region_obligations); let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( tcx, - region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)), + region_obligations + .iter() + .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), region_constraints, ) }); + debug!(?region_constraints); let certainty = if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous }; @@ -246,6 +251,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // the original values `v_o` that was canonicalized into a // variable... + let constraint_category = cause.to_constraint_category(); + for (index, original_value) in original_values.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| { @@ -261,12 +268,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { (GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => { // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`. if v_o != v_r { - output_query_region_constraints - .outlives - .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r))); - output_query_region_constraints - .outlives - .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o))); + output_query_region_constraints.outlives.push(( + ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)), + constraint_category, + )); + output_query_region_constraints.outlives.push(( + ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)), + constraint_category, + )); } } @@ -312,7 +321,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Screen out `'a: 'a` cases -- we skip the binder here but // only compare the inner values to one another, so they are still at // consistent binding levels. - let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = r_c.0.skip_binder(); if k1 != r2.into() { Some(r_c) } else { None } }), ); @@ -500,7 +509,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { for &(a, b) in &query_response.value.opaque_types { let a = substitute_value(self.tcx, &result_subst, a); let b = substitute_value(self.tcx, &result_subst, b); - obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations); + obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -557,7 +566,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Obligation<'tcx, ty::Predicate<'tcx>> { - let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = predicate.0.skip_binder(); let atom = match k1.unpack() { GenericArgKind::Lifetime(r1) => { @@ -572,7 +581,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { span_bug!(cause.span, "unexpected const outlives {:?}", predicate); } }; - let predicate = predicate.rebind(atom).to_predicate(self.tcx); + let predicate = predicate.0.rebind(atom).to_predicate(self.tcx); Obligation::new(cause, param_env, predicate) } @@ -623,7 +632,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( tcx: TyCtxt<'tcx>, - outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>, + outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>, region_constraints: &RegionConstraintData<'tcx>, ) -> QueryRegionConstraints<'tcx> { let RegionConstraintData { constraints, verifys, givens, member_constraints } = @@ -632,28 +641,35 @@ pub fn make_query_region_constraints<'tcx>( assert!(verifys.is_empty()); assert!(givens.is_empty()); + debug!(?constraints); + let outlives: Vec<_> = constraints .iter() - .map(|(k, _)| match *k { - // Swap regions because we are going from sub (<=) to outlives - // (>=). - Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( - tcx.mk_region(ty::ReVar(v2)).into(), - tcx.mk_region(ty::ReVar(v1)), - ), - Constraint::VarSubReg(v1, r2) => { - ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) - } - Constraint::RegSubVar(r1, v2) => { - ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) - } - Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), + .map(|(k, origin)| { + // no bound vars in the code above + let constraint = ty::Binder::dummy(match *k { + // Swap regions because we are going from sub (<=) to outlives + // (>=). + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + tcx.mk_region(ty::ReVar(v2)).into(), + tcx.mk_region(ty::ReVar(v1)), + ), + Constraint::VarSubReg(v1, r2) => { + ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) + } + Constraint::RegSubVar(r1, v2) => { + ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) + } + Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), + }); + (constraint, origin.to_constraint_category()) }) - .map(ty::Binder::dummy) // no bound vars in the code above .chain( outlives_obligations - .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) - .map(ty::Binder::dummy), // no bound vars in the code above + // no bound vars in the code above + .map(|(ty, r, constraint_category)| { + (ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category) + }), ) .collect(); @@ -661,7 +677,7 @@ pub fn make_query_region_constraints<'tcx>( } struct QueryTypeRelatingDelegate<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'tcx>, obligations: &'a mut Vec<PredicateObligation<'tcx>>, param_env: ty::ParamEnv<'tcx>, cause: &'a ObligationCause<'tcx>, @@ -725,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { true } - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: PredicateObligations<'tcx>, ) -> Result<(), TypeError<'tcx>> { - self.obligations.extend( - self.infcx - .handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)? - .obligations, - ); + self.obligations.extend(obligations); Ok(()) } } diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs index 34b611342..389afe22e 100644 --- a/compiler/rustc_infer/src/infer/canonical/substitute.rs +++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs @@ -72,15 +72,16 @@ where value } else { let delegate = FnMutDelegate { - regions: |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { + regions: &mut |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { GenericArgKind::Lifetime(l) => l, r => bug!("{:?} is a region but value is {:?}", br, r), }, - types: |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { + types: &mut |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { GenericArgKind::Type(ty) => ty, r => bug!("{:?} is a type but value is {:?}", bound_ty, r), }, - consts: |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack() { + consts: &mut |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack() + { GenericArgKind::Const(ct) => ct, c => bug!("{:?} is a const but value is {:?}", bound_ct, c), }, |