Skip to content

Commit

Permalink
Auto merge of #103695 - LYF1999:yf/103563, r=lcnr
Browse files Browse the repository at this point in the history
fix: Unexpected trait bound not satisfied in HRTB and Associated Type

fix #103563
  • Loading branch information
bors committed Feb 14, 2023
2 parents e9ab787 + d164448 commit 9bb6e60
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 1 deletion.
47 changes: 46 additions & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use super::{

use crate::infer::{InferCtxt, InferOk, TypeFreshener};
use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::try_normalize_with_depth_to;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
Expand Down Expand Up @@ -1049,7 +1050,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
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?;

if !result.must_apply_modulo_regions() {
Expand Down
75 changes: 75 additions & 0 deletions tests/ui/traits/issue-103563.rs
Original file line number Diff line number Diff line change
@@ -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(),
}
}
}

0 comments on commit 9bb6e60

Please sign in to comment.