Skip to content

Commit a8cf0c7

Browse files
authored
Rollup merge of #149345 - adwinwhite:next-166, r=lcnr
Deeply normalize param env in `compare_impl_item` if using the next solver Fixes rust-lang/trait-system-refactor-initiative#166. Duplicated the `normalize_param_env_or_error` function to force deep normalization for `compare_impl_item`. r? `@lcnr`
2 parents 9320a7d + 133d520 commit a8cf0c7

File tree

6 files changed

+134
-2
lines changed

6 files changed

+134
-2
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,26 @@ fn compare_method_predicate_entailment<'tcx>(
236236

237237
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
238238
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
239-
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
239+
// FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds`
240+
// should be well-formed. However, using them may result in
241+
// region errors as we currently don't track placeholder
242+
// assumptions.
243+
//
244+
// To avoid being backwards incompatible with the old solver,
245+
// we also eagerly normalize the where-bounds in the new solver
246+
// here while ignoring region constraints. This means we can then
247+
// use where-bounds whose normalization results in placeholder
248+
// errors further down without getting any errors.
249+
//
250+
// It should be sound to do so as the only region errors here
251+
// should be due to missing implied bounds.
252+
//
253+
// cc trait-system-refactor-initiative/issues/166.
254+
let param_env = if tcx.next_trait_solver_globally() {
255+
traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause)
256+
} else {
257+
traits::normalize_param_env_or_error(tcx, param_env, normalize_cause)
258+
};
240259
debug!(caller_bounds=?param_env.caller_bounds());
241260

242261
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,69 @@ pub fn normalize_param_env_or_error<'tcx>(
477477
ty::ParamEnv::new(tcx.mk_clauses(&predicates))
478478
}
479479

480+
/// Deeply normalize the param env using the next solver ignoring
481+
/// region errors.
482+
///
483+
/// FIXME(-Zhigher-ranked-assumptions): this is a hack to work around
484+
/// the fact that we don't support placeholder assumptions right now
485+
/// and is necessary for `compare_method_predicate_entailment`, see the
486+
/// use of this function for more info. We should remove this once we
487+
/// have proper support for implied bounds on binders.
488+
#[instrument(level = "debug", skip(tcx))]
489+
pub fn deeply_normalize_param_env_ignoring_regions<'tcx>(
490+
tcx: TyCtxt<'tcx>,
491+
unnormalized_env: ty::ParamEnv<'tcx>,
492+
cause: ObligationCause<'tcx>,
493+
) -> ty::ParamEnv<'tcx> {
494+
let predicates: Vec<_> =
495+
util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
496+
497+
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
498+
499+
let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates));
500+
if !elaborated_env.has_aliases() {
501+
return elaborated_env;
502+
}
503+
504+
let span = cause.span;
505+
let infcx = tcx
506+
.infer_ctxt()
507+
.with_next_trait_solver(true)
508+
.ignoring_regions()
509+
.build(TypingMode::non_body_analysis());
510+
let predicates = match crate::solve::deeply_normalize::<_, FulfillmentError<'tcx>>(
511+
infcx.at(&cause, elaborated_env),
512+
predicates,
513+
) {
514+
Ok(predicates) => predicates,
515+
Err(errors) => {
516+
infcx.err_ctxt().report_fulfillment_errors(errors);
517+
// An unnormalized env is better than nothing.
518+
debug!("normalize_param_env_or_error: errored resolving predicates");
519+
return elaborated_env;
520+
}
521+
};
522+
523+
debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
524+
// FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now.
525+
// There're placeholder constraints `leaking` out.
526+
// See the fixme in the enclosing function's docs for more.
527+
let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
528+
529+
let predicates = match infcx.fully_resolve(predicates) {
530+
Ok(predicates) => predicates,
531+
Err(fixup_err) => {
532+
span_bug!(
533+
span,
534+
"inference variables in normalized parameter environment: {}",
535+
fixup_err
536+
)
537+
}
538+
};
539+
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
540+
ty::ParamEnv::new(tcx.mk_clauses(&predicates))
541+
}
542+
480543
#[derive(Debug)]
481544
pub enum EvaluateConstErr {
482545
/// The constant being evaluated was either a generic parameter or inference variable, *or*,

tests/ui/higher-ranked/trait-bounds/issue-100689.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//@ check-pass
2+
//@ revisions: old next
3+
//@[next] compile-flags: -Znext-solver
24

35
struct Foo<'a> {
46
foo: &'a mut usize,

tests/ui/higher-ranked/trait-bounds/issue-102899.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//@ check-pass
2+
//@ revisions: old next
3+
//@[next] compile-flags: -Znext-solver
24

35
pub trait BufferTrait<'buffer> {
46
type Subset<'channel>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//@ check-pass
2+
//@ compile-flags: -Znext-solver
3+
4+
// See trait-system-refactor-initiative/issues/166.
5+
// The old solver doesn't check normalization constraints in `compare_impl_item`.
6+
// The new solver performs lazy normalization so those region constraints may get postponed to
7+
// an infcx that considers regions.
8+
trait Trait {
9+
type Assoc<'a>
10+
where
11+
Self: 'a;
12+
}
13+
impl<'b> Trait for &'b u32 {
14+
type Assoc<'a> = &'a u32
15+
where
16+
Self: 'a;
17+
}
18+
19+
trait Bound<T> {}
20+
trait Entailment<T: Trait> {
21+
fn method()
22+
where
23+
Self: for<'a> Bound<<T as Trait>::Assoc<'a>>;
24+
}
25+
26+
impl<'b, T> Entailment<&'b u32> for T {
27+
// Instantiates trait where-clauses with `&'b u32` and then normalizes
28+
// `T: for<'a> Bound<<&'b u32 as Trait>::Assoc<'a>>` in a separate infcx
29+
// without checking region constraints.
30+
//
31+
// It normalizes to `T: Bound<&'a u32>`, dropping the `&'b u32: 'a` constraint.
32+
fn method()
33+
where
34+
Self: for<'a> Bound<&'a u32>
35+
{}
36+
}
37+
38+
fn main() {}

tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
2+
--> $DIR/normalize-param-env-2.rs:22:5
3+
|
4+
LL | / fn f()
5+
LL | | where
6+
LL | | Self::Assoc: A<T>,
7+
| |__________________________^
8+
19
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
210
--> $DIR/normalize-param-env-2.rs:24:22
311
|
@@ -46,6 +54,6 @@ LL | where
4654
LL | Self::Assoc: A<T>,
4755
| ^^^^ required by this bound in `A::f`
4856

49-
error: aborting due to 5 previous errors
57+
error: aborting due to 6 previous errors
5058

5159
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)