Rollup merge of #69591 - matthewjasper:query-response-relate, r=nikomatsakis
Use TypeRelating for instantiating query responses `eq` can add constraints to `RegionConstraintData`, which isn't allowed during borrow checking outside of a `CustomTypeOp`. Use `TypeRelating` instead to always push constraints to the obligations list. closes #69490
This commit is contained in:
commit
d7f0b88ade
2 changed files with 111 additions and 7 deletions
|
@ -12,14 +12,15 @@ use crate::infer::canonical::{
|
||||||
Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty, OriginalQueryValues,
|
Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty, OriginalQueryValues,
|
||||||
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
|
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
|
||||||
};
|
};
|
||||||
|
use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
|
||||||
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use crate::infer::InferCtxtBuilder;
|
use crate::infer::{InferCtxt, InferCtxtBuilder, InferOk, InferResult, NLLRegionVariableOrigin};
|
||||||
use crate::infer::{InferCtxt, InferOk, InferResult};
|
|
||||||
use crate::traits::query::{Fallible, NoSolution};
|
use crate::traits::query::{Fallible, NoSolution};
|
||||||
use crate::traits::TraitEngine;
|
use crate::traits::{DomainGoal, TraitEngine};
|
||||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
||||||
use rustc::arena::ArenaAllocatable;
|
use rustc::arena::ArenaAllocatable;
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
|
use rustc::ty::relate::TypeRelation;
|
||||||
use rustc::ty::subst::{GenericArg, GenericArgKind};
|
use rustc::ty::subst::{GenericArg, GenericArgKind};
|
||||||
use rustc::ty::{self, BoundVar, Ty, TyCtxt};
|
use rustc::ty::{self, BoundVar, Ty, TyCtxt};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
|
@ -304,13 +305,31 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
|
(GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
|
||||||
let ok = self.at(cause, param_env).eq(v1, v2)?;
|
TypeRelating::new(
|
||||||
obligations.extend(ok.into_obligations());
|
self,
|
||||||
|
QueryTypeRelatingDelegate {
|
||||||
|
infcx: self,
|
||||||
|
param_env,
|
||||||
|
cause,
|
||||||
|
obligations: &mut obligations,
|
||||||
|
},
|
||||||
|
ty::Variance::Invariant,
|
||||||
|
)
|
||||||
|
.relate(&v1, &v2)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
(GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
|
(GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
|
||||||
let ok = self.at(cause, param_env).eq(v1, v2)?;
|
TypeRelating::new(
|
||||||
obligations.extend(ok.into_obligations());
|
self,
|
||||||
|
QueryTypeRelatingDelegate {
|
||||||
|
infcx: self,
|
||||||
|
param_env,
|
||||||
|
cause,
|
||||||
|
obligations: &mut obligations,
|
||||||
|
},
|
||||||
|
ty::Variance::Invariant,
|
||||||
|
)
|
||||||
|
.relate(&v1, &v2)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -656,3 +675,55 @@ pub fn make_query_region_constraints<'tcx>(
|
||||||
|
|
||||||
QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
|
QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct QueryTypeRelatingDelegate<'a, 'tcx> {
|
||||||
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
|
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
cause: &'a ObligationCause<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
||||||
|
fn create_next_universe(&mut self) -> ty::UniverseIndex {
|
||||||
|
self.infcx.create_next_universe()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
|
||||||
|
let origin = NLLRegionVariableOrigin::Existential { from_forall };
|
||||||
|
self.infcx.next_nll_region_var(origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
|
||||||
|
self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||||
|
self.infcx.next_nll_region_var_in_universe(
|
||||||
|
NLLRegionVariableOrigin::Existential { from_forall: false },
|
||||||
|
universe,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
|
||||||
|
self.obligations.push(Obligation {
|
||||||
|
cause: self.cause.clone(),
|
||||||
|
param_env: self.param_env,
|
||||||
|
predicate: ty::Predicate::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
|
||||||
|
sup, sub,
|
||||||
|
))),
|
||||||
|
recursion_depth: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_domain_goal(&mut self, _: DomainGoal<'tcx>) {
|
||||||
|
bug!("should never be invoked with eager normalization")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalization() -> NormalizationStrategy {
|
||||||
|
NormalizationStrategy::Eager
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forbid_inference_vars() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Regression test for issue #69490
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
pub trait Trait<T> {
|
||||||
|
const S: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Trait<()> for T
|
||||||
|
where
|
||||||
|
T: for<'a> Trait<&'a ()>,
|
||||||
|
{
|
||||||
|
// Use of `T::S` here caused an ICE
|
||||||
|
const S: &'static str = T::S;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some similar cases that didn't ICE:
|
||||||
|
|
||||||
|
impl<'a, T> Trait<()> for (T,)
|
||||||
|
where
|
||||||
|
T: Trait<&'a ()>,
|
||||||
|
{
|
||||||
|
const S: &'static str = T::S;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Trait<()> for [T; 1]
|
||||||
|
where
|
||||||
|
T: Trait<for<'a> fn(&'a ())>,
|
||||||
|
{
|
||||||
|
const S: &'static str = T::S;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue