Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,21 @@ fn compare_method_predicate_entailment<'tcx>(
let hybrid_preds = hybrid_preds.into_iter().map(Unnormalized::skip_norm_wip);
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds));
// FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds`
// NOTE(-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.
// We eagerly normalize the where-clauses 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
// This 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)
};
let param_env = 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());
Expand Down
89 changes: 11 additions & 78 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use rustc_errors::ErrorGuaranteed;
pub use rustc_infer::traits::*;
use rustc_macros::TypeVisitable;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{
self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder,
Expand Down Expand Up @@ -257,12 +256,6 @@ fn do_normalize_predicates<'tcx>(
elaborated_env: ty::ParamEnv<'tcx>,
predicates: Vec<ty::Clause<'tcx>>,
) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
// Even if we move back to eager normalization elsewhere,
// param env normalization remains lazy in the next solver.
if tcx.next_trait_solver_globally() {
return Ok(predicates);
}

// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
// behavior (i.e., doesn't cause any new bugs), and it would
Expand Down Expand Up @@ -291,17 +284,20 @@ fn do_normalize_predicates<'tcx>(

// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
//
// FIXME: It's very weird that we ignore region obligations but apparently
// still need to use `resolve_regions` as we need the resolved regions in
// the normalized predicates.
let errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
if !errors.is_empty() {
tcx.dcx().span_delayed_bug(
span,
format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"),
);
}

//
// FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now.
// There're placeholder constraints `leaking` out. 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`. We should remove this once we
// have proper support for implied bounds on binders.
//
// This is required by trait-system-refactor-initiative#166. The new solver encounters
// this more frequently as we entirely ignore outlives predicates with the old solver.
let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
match infcx.fully_resolve(predicates) {
Ok(predicates) => Ok(predicates),
Err(fixup_err) => {
Expand Down Expand Up @@ -478,69 +474,6 @@ 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),
Unnormalized::new_wip(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*,
Expand Down
25 changes: 0 additions & 25 deletions tests/crashes/136661.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ where
}

impl<'a, T> Foo for &T
//~^ ERROR: conflicting implementations of trait `Foo` for type `&_`
//~^ ERROR: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
where
Self::Item: Baz,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
error[E0119]: conflicting implementations of trait `Foo` for type `&_`
error[E0391]: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
--> $DIR/next-solver-region-resolution.rs:18:1
|
LL | / impl<'a, T> Foo for &'a T
LL | | where
LL | | Self::Item: 'a,
| |___________________- first implementation here
...
LL | / impl<'a, T> Foo for &T
LL | |
LL | | where
LL | | Self::Item: Baz,
| |____________________^ conflicting implementation for `&_`
| |____________________^
|
= note: ...which immediately requires computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>` again
note: cycle used when computing whether impls specialize one another
--> $DIR/next-solver-region-resolution.rs:12:1
|
LL | / impl<'a, T> Foo for &'a T
LL | | where
LL | | Self::Item: 'a,
| |___________________^
= note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
For more information about this error, try `rustc --explain E0391`.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
= note: ...which requires building an abstract representation for `accept0::{constant#0}`...
= note: ...which requires building THIR for `accept0::{constant#0}`...
= note: ...which requires type-checking `accept0::{constant#0}`...
= note: ...which requires computing normalized predicates of `accept0::{constant#0}`...
= note: ...which again requires evaluating type-level constant, completing the cycle
= note: cycle used when checking that `accept0` is well-formed
= note: cycle used when computing normalized predicates of `accept0`
= note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>

error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const
Expand All @@ -32,6 +33,7 @@ LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
= note: ...which requires building an abstract representation for `accept1::{constant#0}`...
= note: ...which requires building THIR for `accept1::{constant#0}`...
= note: ...which requires type-checking `accept1::{constant#0}`...
= note: ...which requires computing normalized predicates of `accept1::{constant#0}`...
= note: ...which requires evaluating type-level constant...
= note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
= note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/traits/next-solver/alias-bound-unsound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ trait Foo {
impl Foo for () {
type Item = String where String: Copy;
//~^ ERROR overflow evaluating the requirement `String: Copy`
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
}

fn main() {
Expand Down
40 changes: 35 additions & 5 deletions tests/ui/traits/next-solver/alias-bound-unsound.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:22:5
|
LL | type Item = String where String: Copy;
| ^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:22:5
|
LL | type Item = String where String: Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:22:5
|
LL | type Item = String where String: Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:22:5
|
LL | type Item = String where String: Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0275]: overflow evaluating the requirement `String: Copy`
--> $DIR/alias-bound-unsound.rs:22:38
|
Expand All @@ -13,31 +43,31 @@ LL | type Item: Copy
| ^^^^ this trait's associated type doesn't have the requirement `String: Copy`

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String`
--> $DIR/alias-bound-unsound.rs:28:22
--> $DIR/alias-bound-unsound.rs:32:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:28:22
--> $DIR/alias-bound-unsound.rs:32:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:28:43
--> $DIR/alias-bound-unsound.rs:32:43
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^

error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:28:22
--> $DIR/alias-bound-unsound.rs:32:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 5 previous errors
error: aborting due to 9 previous errors

For more information about this error, try `rustc --explain E0275`.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fn impls_bound<T: Bound>() {
// - normalize `<Foo as Trait<T>>::Assoc`
// - via blanket impl, requires where-clause `Foo: Bound` -> cycle
fn generic<T>()
//~^ ERROR the trait bound `Foo: Bound` is not satisfied
where
<Foo as Trait<T>>::Assoc: Bound,
//~^ ERROR the trait bound `Foo: Bound` is not satisfied
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
error[E0277]: the trait bound `Foo: Bound` is not satisfied
--> $DIR/normalizes-to-is-not-productive.rs:42:31
--> $DIR/normalizes-to-is-not-productive.rs:40:1
|
LL | / fn generic<T>()
LL | |
LL | | where
LL | | <Foo as Trait<T>>::Assoc: Bound,
| |____________________________________^ unsatisfied trait bound
|
help: the trait `Bound` is not implemented for `Foo`
--> $DIR/normalizes-to-is-not-productive.rs:18:1
|
LL | struct Foo;
| ^^^^^^^^^^
help: the trait `Bound` is implemented for `u32`
--> $DIR/normalizes-to-is-not-productive.rs:11:1
|
LL | impl Bound for u32 {
| ^^^^^^^^^^^^^^^^^^
note: required for `Foo` to implement `Trait<T>`
--> $DIR/normalizes-to-is-not-productive.rs:23:19
|
LL | impl<T: Bound, U> Trait<U> for T {
| ----- ^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here

error[E0277]: the trait bound `Foo: Bound` is not satisfied
--> $DIR/normalizes-to-is-not-productive.rs:43:31
|
LL | <Foo as Trait<T>>::Assoc: Bound,
| ^^^^^ unsatisfied trait bound
Expand Down Expand Up @@ -30,7 +57,7 @@ LL | | }
| |_^ required by this bound in `Bound`

error[E0277]: the trait bound `Foo: Bound` is not satisfied
--> $DIR/normalizes-to-is-not-productive.rs:47:19
--> $DIR/normalizes-to-is-not-productive.rs:48:19
|
LL | impls_bound::<Foo>();
| ^^^ unsatisfied trait bound
Expand All @@ -51,6 +78,6 @@ note: required by a bound in `impls_bound`
LL | fn impls_bound<T: Bound>() {
| ^^^^^ required by this bound in `impls_bound`

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn foo<T>()
where
T: for<'a> Proj<'a, Assoc = for<'b> fn(<T as Proj<'b>>::Assoc)>,
(): Trait<<T as Proj<'static>>::Assoc>
//~^ ERROR: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
//~^ ERROR: the trait bound `(): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not satisfied
{
}

Expand Down
Loading
Loading