fix: Unexpected trait bound not satisfied in HRTB
This commit is contained in:
parent
21f6839352
commit
d164448038
@ -27,6 +27,7 @@ use super::{
|
|||||||
|
|
||||||
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
||||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||||
|
use crate::traits::project::try_normalize_with_depth_to;
|
||||||
use crate::traits::project::ProjectAndUnifyResult;
|
use crate::traits::project::ProjectAndUnifyResult;
|
||||||
use crate::traits::project::ProjectionCacheKeyExt;
|
use crate::traits::project::ProjectionCacheKeyExt;
|
||||||
use crate::traits::ProjectionCacheKey;
|
use crate::traits::ProjectionCacheKey;
|
||||||
@ -1017,7 +1018,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
return Ok(cycle_result);
|
return Ok(cycle_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
|
let (result, dep_node) = self.in_task(|this| {
|
||||||
|
let mut result = this.evaluate_stack(&stack)?;
|
||||||
|
|
||||||
|
// fix issue #103563, we don't normalize
|
||||||
|
// nested obligations which produced by `TraitDef` candidate
|
||||||
|
// (i.e. using bounds on assoc items as assumptions).
|
||||||
|
// because we don't have enough information to
|
||||||
|
// normalize these obligations before evaluating.
|
||||||
|
// so we will try to normalize the obligation and evaluate again.
|
||||||
|
// we will replace it with new solver in the future.
|
||||||
|
if EvaluationResult::EvaluatedToErr == result
|
||||||
|
&& fresh_trait_pred.has_projections()
|
||||||
|
&& fresh_trait_pred.is_global()
|
||||||
|
{
|
||||||
|
let mut nested_obligations = Vec::new();
|
||||||
|
let predicate = try_normalize_with_depth_to(
|
||||||
|
this,
|
||||||
|
param_env,
|
||||||
|
obligation.cause.clone(),
|
||||||
|
obligation.recursion_depth + 1,
|
||||||
|
obligation.predicate,
|
||||||
|
&mut nested_obligations,
|
||||||
|
);
|
||||||
|
if predicate != obligation.predicate {
|
||||||
|
let mut nested_result = EvaluationResult::EvaluatedToOk;
|
||||||
|
for obligation in nested_obligations {
|
||||||
|
nested_result = cmp::max(
|
||||||
|
this.evaluate_predicate_recursively(stack.list(), obligation)?,
|
||||||
|
nested_result,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if nested_result.must_apply_modulo_regions() {
|
||||||
|
let obligation = obligation.with(this.tcx(), predicate);
|
||||||
|
result = cmp::max(
|
||||||
|
nested_result,
|
||||||
|
this.evaluate_trait_predicate_recursively(stack.list(), obligation)?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok::<_, OverflowError>(result)
|
||||||
|
});
|
||||||
|
|
||||||
let result = result?;
|
let result = result?;
|
||||||
|
|
||||||
if !result.must_apply_modulo_regions() {
|
if !result.must_apply_modulo_regions() {
|
||||||
|
75
tests/ui/traits/issue-103563.rs
Normal file
75
tests/ui/traits/issue-103563.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// build-pass
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_service = LogService { inner: Inner };
|
||||||
|
log_service.call(());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Service<Request> {
|
||||||
|
type Response;
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request) -> Self::Response;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LogService<S> {
|
||||||
|
inner: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U, S> Service<T> for LogService<S>
|
||||||
|
where
|
||||||
|
S: Service<T, Response = U>,
|
||||||
|
U: Extension + 'static,
|
||||||
|
for<'a> U::Item<'a>: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
type Response = S::Response;
|
||||||
|
|
||||||
|
fn call(&mut self, req: T) -> Self::Response {
|
||||||
|
self.inner.call(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Inner;
|
||||||
|
|
||||||
|
impl Service<()> for Inner {
|
||||||
|
type Response = Resp;
|
||||||
|
|
||||||
|
fn call(&mut self, req: ()) -> Self::Response {
|
||||||
|
Resp::A(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Extension {
|
||||||
|
type Item<'a>;
|
||||||
|
|
||||||
|
fn touch<F>(self, f: F) -> Self
|
||||||
|
where
|
||||||
|
for<'a> F: Fn(Self::Item<'a>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Resp {
|
||||||
|
A(()),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Extension for Resp {
|
||||||
|
type Item<'a> = RespItem<'a>;
|
||||||
|
fn touch<F>(self, _f: F) -> Self
|
||||||
|
where
|
||||||
|
for<'a> F: Fn(Self::Item<'a>),
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Self::A(a) => Self::A(a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RespItem<'a> {
|
||||||
|
A(&'a ()),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::fmt::Debug for RespItem<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::A(arg0) => f.debug_tuple("A").field(arg0).finish(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user