Skip to content

Commit d164448

Browse files
committed
fix: Unexpected trait bound not satisfied in HRTB
1 parent 21f6839 commit d164448

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

compiler/rustc_trait_selection/src/traits/select/mod.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use super::{
2727

2828
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
2929
use crate::traits::error_reporting::TypeErrCtxtExt;
30+
use crate::traits::project::try_normalize_with_depth_to;
3031
use crate::traits::project::ProjectAndUnifyResult;
3132
use crate::traits::project::ProjectionCacheKeyExt;
3233
use crate::traits::ProjectionCacheKey;
@@ -1017,7 +1018,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10171018
return Ok(cycle_result);
10181019
}
10191020

1020-
let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
1021+
let (result, dep_node) = self.in_task(|this| {
1022+
let mut result = this.evaluate_stack(&stack)?;
1023+
1024+
// fix issue #103563, we don't normalize
1025+
// nested obligations which produced by `TraitDef` candidate
1026+
// (i.e. using bounds on assoc items as assumptions).
1027+
// because we don't have enough information to
1028+
// normalize these obligations before evaluating.
1029+
// so we will try to normalize the obligation and evaluate again.
1030+
// we will replace it with new solver in the future.
1031+
if EvaluationResult::EvaluatedToErr == result
1032+
&& fresh_trait_pred.has_projections()
1033+
&& fresh_trait_pred.is_global()
1034+
{
1035+
let mut nested_obligations = Vec::new();
1036+
let predicate = try_normalize_with_depth_to(
1037+
this,
1038+
param_env,
1039+
obligation.cause.clone(),
1040+
obligation.recursion_depth + 1,
1041+
obligation.predicate,
1042+
&mut nested_obligations,
1043+
);
1044+
if predicate != obligation.predicate {
1045+
let mut nested_result = EvaluationResult::EvaluatedToOk;
1046+
for obligation in nested_obligations {
1047+
nested_result = cmp::max(
1048+
this.evaluate_predicate_recursively(stack.list(), obligation)?,
1049+
nested_result,
1050+
);
1051+
}
1052+
1053+
if nested_result.must_apply_modulo_regions() {
1054+
let obligation = obligation.with(this.tcx(), predicate);
1055+
result = cmp::max(
1056+
nested_result,
1057+
this.evaluate_trait_predicate_recursively(stack.list(), obligation)?,
1058+
);
1059+
}
1060+
}
1061+
}
1062+
1063+
Ok::<_, OverflowError>(result)
1064+
});
1065+
10211066
let result = result?;
10221067

10231068
if !result.must_apply_modulo_regions() {

tests/ui/traits/issue-103563.rs

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// build-pass
2+
3+
fn main() {
4+
let mut log_service = LogService { inner: Inner };
5+
log_service.call(());
6+
}
7+
8+
pub trait Service<Request> {
9+
type Response;
10+
11+
fn call(&mut self, req: Request) -> Self::Response;
12+
}
13+
14+
pub struct LogService<S> {
15+
inner: S,
16+
}
17+
18+
impl<T, U, S> Service<T> for LogService<S>
19+
where
20+
S: Service<T, Response = U>,
21+
U: Extension + 'static,
22+
for<'a> U::Item<'a>: std::fmt::Debug,
23+
{
24+
type Response = S::Response;
25+
26+
fn call(&mut self, req: T) -> Self::Response {
27+
self.inner.call(req)
28+
}
29+
}
30+
31+
pub struct Inner;
32+
33+
impl Service<()> for Inner {
34+
type Response = Resp;
35+
36+
fn call(&mut self, req: ()) -> Self::Response {
37+
Resp::A(req)
38+
}
39+
}
40+
41+
pub trait Extension {
42+
type Item<'a>;
43+
44+
fn touch<F>(self, f: F) -> Self
45+
where
46+
for<'a> F: Fn(Self::Item<'a>);
47+
}
48+
49+
pub enum Resp {
50+
A(()),
51+
}
52+
53+
impl Extension for Resp {
54+
type Item<'a> = RespItem<'a>;
55+
fn touch<F>(self, _f: F) -> Self
56+
where
57+
for<'a> F: Fn(Self::Item<'a>),
58+
{
59+
match self {
60+
Self::A(a) => Self::A(a),
61+
}
62+
}
63+
}
64+
65+
pub enum RespItem<'a> {
66+
A(&'a ()),
67+
}
68+
69+
impl<'a> std::fmt::Debug for RespItem<'a> {
70+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71+
match self {
72+
Self::A(arg0) => f.debug_tuple("A").field(arg0).finish(),
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)