Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

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

compiler/rustc_data_structures/src/obligation_forest/mod.rs

Lines changed: 4 additions & 0 deletions
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

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 2 deletions
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();

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 2 additions & 0 deletions
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

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 4 additions & 0 deletions
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
}

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 4 additions & 0 deletions
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
}

compiler/rustc_trait_selection/src/traits/normalize.rs

Lines changed: 10 additions & 1 deletion
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
}

compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs

Lines changed: 7 additions & 3 deletions
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
};

tests/ui/higher-ranked/structually-relate-aliases.rs

Lines changed: 0 additions & 1 deletion
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() {}

tests/ui/higher-ranked/structually-relate-aliases.stderr

Lines changed: 1 addition & 12 deletions
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`.

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

Lines changed: 2 additions & 2 deletions
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

0 commit comments

Comments
 (0)