Skip to content

Commit 6827909

Browse files
authored
Rollup merge of rust-lang#133517 - compiler-errors:deep-norm, r=lcnr
Deeply normalize when computing implied outlives bounds r? lcnr Unfortunately resolving regions is still slightly scuffed (though in an unrelated way). Specifically, we should be normalizing our param-env outlives when constructing the `OutlivesEnv`; otherwise, these assumptions (https://github.com/rust-lang/rust/blob/dd2837ec5de4301a692e05a7c4475e980af57a57/compiler/rustc_infer/src/infer/outlives/env.rs#L78) are not constructed correctly. Let me know if you want us to track that somewhere.
2 parents 9709334 + 398fd90 commit 6827909

File tree

13 files changed

+88
-29
lines changed

13 files changed

+88
-29
lines changed

Diff for: compiler/rustc_data_structures/src/obligation_forest/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ impl<O: ForestObligation> ObligationForest<O> {
415415
.collect()
416416
}
417417

418+
pub fn has_pending_obligations(&self) -> bool {
419+
self.nodes.iter().any(|node| node.state.get() == NodeState::Pending)
420+
}
421+
418422
fn insert_into_error_cache(&mut self, index: usize) {
419423
let node = &self.nodes[index];
420424
self.error_cache

Diff for: compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,12 @@ where
117117
}
118118
f(&mut wfcx)?;
119119

120-
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
121-
122120
let errors = wfcx.select_all_or_error();
123121
if !errors.is_empty() {
124122
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
125123
}
126124

125+
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
127126
debug!(?assumed_wf_types);
128127

129128
let infcx_compat = infcx.fork();

Diff for: compiler/rustc_infer/src/traits/engine.rs

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
8484
self.collect_remaining_errors(infcx)
8585
}
8686

87+
fn has_pending_obligations(&self) -> bool;
88+
8789
fn pending_obligations(&self) -> PredicateObligations<'tcx>;
8890

8991
/// Among all pending obligations, collect those are stalled on a inference variable which has

Diff for: compiler/rustc_trait_selection/src/solve/fulfill.rs

+4
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ where
199199
errors
200200
}
201201

202+
fn has_pending_obligations(&self) -> bool {
203+
!self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty()
204+
}
205+
202206
fn pending_obligations(&self) -> PredicateObligations<'tcx> {
203207
self.obligations.clone_pending()
204208
}

Diff for: compiler/rustc_trait_selection/src/traits/fulfill.rs

+4
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ where
213213
}
214214
}
215215

216+
fn has_pending_obligations(&self) -> bool {
217+
self.predicates.has_pending_obligations()
218+
}
219+
216220
fn pending_obligations(&self) -> PredicateObligations<'tcx> {
217221
self.predicates.map_pending_obligations(|o| o.obligation.clone())
218222
}

Diff for: compiler/rustc_trait_selection/src/traits/normalize.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_infer::traits::{
77
FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine,
88
};
99
use rustc_macros::extension;
10+
use rustc_middle::span_bug;
1011
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
1112
use rustc_middle::ty::{
1213
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
@@ -63,10 +64,18 @@ impl<'tcx> At<'_, 'tcx> {
6364
if self.infcx.next_trait_solver() {
6465
crate::solve::deeply_normalize(self, value)
6566
} else {
67+
if fulfill_cx.has_pending_obligations() {
68+
let pending_obligations = fulfill_cx.pending_obligations();
69+
span_bug!(
70+
pending_obligations[0].cause.span,
71+
"deeply_normalize should not be called with pending obligations: \
72+
{pending_obligations:#?}"
73+
);
74+
}
6675
let value = self
6776
.normalize(value)
6877
.into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
69-
let errors = fulfill_cx.select_where_possible(self.infcx);
78+
let errors = fulfill_cx.select_all_or_error(self.infcx);
7079
let value = self.infcx.resolve_vars_if_possible(value);
7180
if errors.is_empty() { Ok(value) } else { Err(errors) }
7281
}

Diff for: compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,16 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
5959
param_env: ty::ParamEnv<'tcx>,
6060
ty: Ty<'tcx>,
6161
) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
62-
let normalize_op = |ty| {
63-
let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty);
62+
let normalize_op = |ty| -> Result<_, NoSolution> {
63+
// We must normalize the type so we can compute the right outlives components.
64+
// for example, if we have some constrained param type like `T: Trait<Out = U>`,
65+
// and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
66+
let ty = ocx
67+
.deeply_normalize(&ObligationCause::dummy(), param_env, ty)
68+
.map_err(|_| NoSolution)?;
6469
if !ocx.select_all_or_error().is_empty() {
6570
return Err(NoSolution);
6671
}
67-
let ty = ocx.infcx.resolve_vars_if_possible(ty);
6872
let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty);
6973
Ok(ty)
7074
};

Diff for: tests/ui/higher-ranked/structually-relate-aliases.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ impl<T> Overlap<T> for T {}
1212

1313
impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
1414
//~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
15-
//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
1615

1716
fn main() {}

Diff for: tests/ui/higher-ranked/structually-relate-aliases.stderr

+1-12
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,6 @@ help: consider restricting type parameter `T`
1010
LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
1111
| ++++++++++++++++++++
1212

13-
error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
14-
--> $DIR/structually-relate-aliases.rs:13:17
15-
|
16-
LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
18-
|
19-
help: consider restricting type parameter `T`
20-
|
21-
LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
22-
| ++++++++++++++++++++
23-
24-
error: aborting due to 2 previous errors
13+
error: aborting due to 1 previous error
2514

2615
For more information about this error, try `rustc --explain E0277`.

Diff for: tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | #![feature(lazy_type_alias)]
88
= note: `#[warn(incomplete_features)]` on by default
99

1010
error[E0277]: the trait bound `usize: Foo` is not satisfied
11-
--> $DIR/alias-bounds-when-not-wf.rs:16:13
11+
--> $DIR/alias-bounds-when-not-wf.rs:16:15
1212
|
1313
LL | fn hello(_: W<A<usize>>) {}
14-
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
14+
| ^^^^^^^^ the trait `Foo` is not implemented for `usize`
1515
|
1616
help: this trait has no implementations, consider adding one
1717
--> $DIR/alias-bounds-when-not-wf.rs:6:1

Diff for: tests/ui/traits/next-solver/issue-118950-root-region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ impl<T> Overlap<T> for T {}
1818

1919
impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
2020
//~^ ERROR cannot find type `Missing` in this scope
21-
//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
21+
//~| ERROR the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
2222

2323
fn main() {}

Diff for: tests/ui/traits/next-solver/issue-118950-root-region.stderr

+6-7
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,16 @@ LL | trait ToUnit<'a> {
2626
| ^^^^^^^^^^^^^^^^
2727

2828
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
29-
error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
30-
--> $DIR/issue-118950-root-region.rs:19:17
29+
error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
30+
--> $DIR/issue-118950-root-region.rs:19:47
3131
|
3232
LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
33-
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T`
33+
| ^ the trait `Overlap<for<'a> fn(Assoc<'a, T>)>` is not implemented for `T`
3434
|
35-
help: this trait has no implementations, consider adding one
36-
--> $DIR/issue-118950-root-region.rs:8:1
35+
help: consider further restricting type parameter `T`
3736
|
38-
LL | trait ToUnit<'a> {
39-
| ^^^^^^^^^^^^^^^^
37+
LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {}
38+
| ++++++++++++++++++++++++++++++++++++++
4039

4140
error: aborting due to 3 previous errors; 1 warning emitted
4241

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//@ check-pass
2+
//@ compile-flags: -Znext-solver
3+
4+
// Minimized example from `rustc_type_ir` that demonstrates a missing deep normalization
5+
// in the new solver when computing the implies outlives bounds of an impl.
6+
7+
use std::marker::PhantomData;
8+
use std::ops::Deref;
9+
10+
pub struct SearchGraph<D: Delegate, X = <D as Delegate>::Cx> {
11+
d: PhantomData<D>,
12+
x: PhantomData<X>,
13+
}
14+
15+
pub trait Delegate {
16+
type Cx;
17+
}
18+
19+
struct SearchGraphDelegate<D: SolverDelegate> {
20+
_marker: PhantomData<D>,
21+
}
22+
23+
impl<D> Delegate for SearchGraphDelegate<D>
24+
where
25+
D: SolverDelegate,
26+
{
27+
type Cx = D::Interner;
28+
}
29+
30+
pub trait SolverDelegate {
31+
type Interner;
32+
}
33+
34+
struct EvalCtxt<'a, D, I>
35+
where
36+
D: SolverDelegate<Interner = I>,
37+
{
38+
search_graph: &'a SearchGraph<SearchGraphDelegate<D>>,
39+
}
40+
41+
impl<'a, D, I> EvalCtxt<'a, D, <D as SolverDelegate>::Interner>
42+
where
43+
D: SolverDelegate<Interner = I>
44+
{}
45+
46+
fn main() {}

0 commit comments

Comments
 (0)