Rollup merge of #149345 - adwinwhite:next-166, r=lcnr
Deeply normalize param env in `compare_impl_item` if using the next solver Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/166. Duplicated the `normalize_param_env_or_error` function to force deep normalization for `compare_impl_item`. r? `@lcnr`
This commit is contained in:
commit
a8cf0c7080
6 changed files with 134 additions and 2 deletions
|
|
@ -236,7 +236,26 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
|
||||
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
// FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds`
|
||||
// should be well-formed. However, using them may result in
|
||||
// region errors as we currently don't track placeholder
|
||||
// assumptions.
|
||||
//
|
||||
// To avoid being backwards incompatible with the old solver,
|
||||
// we also eagerly normalize the where-bounds in the new solver
|
||||
// here while ignoring region constraints. This means we can then
|
||||
// use where-bounds whose normalization results in placeholder
|
||||
// errors further down without getting any errors.
|
||||
//
|
||||
// It should be sound to do so as the only region errors here
|
||||
// should be due to missing implied bounds.
|
||||
//
|
||||
// cc trait-system-refactor-initiative/issues/166.
|
||||
let param_env = if tcx.next_trait_solver_globally() {
|
||||
traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause)
|
||||
} else {
|
||||
traits::normalize_param_env_or_error(tcx, param_env, normalize_cause)
|
||||
};
|
||||
debug!(caller_bounds=?param_env.caller_bounds());
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
|
|
|
|||
|
|
@ -477,6 +477,69 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
ty::ParamEnv::new(tcx.mk_clauses(&predicates))
|
||||
}
|
||||
|
||||
/// Deeply normalize the param env using the next solver ignoring
|
||||
/// region errors.
|
||||
///
|
||||
/// FIXME(-Zhigher-ranked-assumptions): this is a hack to work around
|
||||
/// the fact that we don't support placeholder assumptions right now
|
||||
/// and is necessary for `compare_method_predicate_entailment`, see the
|
||||
/// use of this function for more info. We should remove this once we
|
||||
/// have proper support for implied bounds on binders.
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub fn deeply_normalize_param_env_ignoring_regions<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
unnormalized_env: ty::ParamEnv<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
) -> ty::ParamEnv<'tcx> {
|
||||
let predicates: Vec<_> =
|
||||
util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
|
||||
|
||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
|
||||
|
||||
let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates));
|
||||
if !elaborated_env.has_aliases() {
|
||||
return elaborated_env;
|
||||
}
|
||||
|
||||
let span = cause.span;
|
||||
let infcx = tcx
|
||||
.infer_ctxt()
|
||||
.with_next_trait_solver(true)
|
||||
.ignoring_regions()
|
||||
.build(TypingMode::non_body_analysis());
|
||||
let predicates = match crate::solve::deeply_normalize::<_, FulfillmentError<'tcx>>(
|
||||
infcx.at(&cause, elaborated_env),
|
||||
predicates,
|
||||
) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(errors) => {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
// An unnormalized env is better than nothing.
|
||||
debug!("normalize_param_env_or_error: errored resolving predicates");
|
||||
return elaborated_env;
|
||||
}
|
||||
};
|
||||
|
||||
debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
|
||||
// FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now.
|
||||
// There're placeholder constraints `leaking` out.
|
||||
// See the fixme in the enclosing function's docs for more.
|
||||
let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
|
||||
|
||||
let predicates = match infcx.fully_resolve(predicates) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(fixup_err) => {
|
||||
span_bug!(
|
||||
span,
|
||||
"inference variables in normalized parameter environment: {}",
|
||||
fixup_err
|
||||
)
|
||||
}
|
||||
};
|
||||
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
|
||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EvaluateConstErr {
|
||||
/// The constant being evaluated was either a generic parameter or inference variable, *or*,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
//@ check-pass
|
||||
//@ revisions: old next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
struct Foo<'a> {
|
||||
foo: &'a mut usize,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
//@ check-pass
|
||||
//@ revisions: old next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
pub trait BufferTrait<'buffer> {
|
||||
type Subset<'channel>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// See trait-system-refactor-initiative/issues/166.
|
||||
// The old solver doesn't check normalization constraints in `compare_impl_item`.
|
||||
// The new solver performs lazy normalization so those region constraints may get postponed to
|
||||
// an infcx that considers regions.
|
||||
trait Trait {
|
||||
type Assoc<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
}
|
||||
impl<'b> Trait for &'b u32 {
|
||||
type Assoc<'a> = &'a u32
|
||||
where
|
||||
Self: 'a;
|
||||
}
|
||||
|
||||
trait Bound<T> {}
|
||||
trait Entailment<T: Trait> {
|
||||
fn method()
|
||||
where
|
||||
Self: for<'a> Bound<<T as Trait>::Assoc<'a>>;
|
||||
}
|
||||
|
||||
impl<'b, T> Entailment<&'b u32> for T {
|
||||
// Instantiates trait where-clauses with `&'b u32` and then normalizes
|
||||
// `T: for<'a> Bound<<&'b u32 as Trait>::Assoc<'a>>` in a separate infcx
|
||||
// without checking region constraints.
|
||||
//
|
||||
// It normalizes to `T: Bound<&'a u32>`, dropping the `&'b u32: 'a` constraint.
|
||||
fn method()
|
||||
where
|
||||
Self: for<'a> Bound<&'a u32>
|
||||
{}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,3 +1,11 @@
|
|||
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
|
||||
--> $DIR/normalize-param-env-2.rs:22:5
|
||||
|
|
||||
LL | / fn f()
|
||||
LL | | where
|
||||
LL | | Self::Assoc: A<T>,
|
||||
| |__________________________^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
|
||||
--> $DIR/normalize-param-env-2.rs:24:22
|
||||
|
|
||||
|
|
@ -46,6 +54,6 @@ LL | where
|
|||
LL | Self::Assoc: A<T>,
|
||||
| ^^^^ required by this bound in `A::f`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue