Auto merge of #107940 - BoxyUwU:const_ty_assertion_use_semantic_equality, r=compiler-errors

use semantic equality for const param type equality assertion

Fixes #107898

See added test for what caused this ICE

---

The current in assertion in `relate.rs` is rather inadequate when keeping in mind future expansions to const generics:
- it will ICE when there are infer vars in a projection in a const param ty
- it will spurriously return false when either ty has infer vars because of using `==` instead of `infcx.at(..).eq`
- i am also unsure if it would be possible with `adt_const_params` to craft a situation where the const param type is not wf causing `normalize_erasing_regions` to `bug!` when we would have emitted a diagnostic.

This impl feels pretty Not Great to me  although i am not sure what a better idea would be.

- We have to have the logic behind a query because neither `relate.rs` or `combine.rs` have access to trait solving machinery (without evaluating nested obligations this assert will become _far_ less useful under lazy norm, which consts are already doing)
- `relate.rs` does not have access to canonicalization machinery which is necessary in order to have types potentially containing infer vars in query arguments.

We could possible add a method to `TypeRelation` to do this assertion rather than a query but to avoid implementing the same logic over and over we'd probably end up with the logic in a free function somewhere in `rustc_trait_selection` _anyway_ so I don't think that would be much better.

We could also just remove this assertion, it should not actually be necessary for it to be present. It has caught some bugs in the past though so if possible I would like to keep it.

r? `@compiler-errors`
This commit is contained in:
bors 2023-02-15 05:17:58 +00:00
commit 068161ea48
7 changed files with 240 additions and 22 deletions

View file

@ -1,12 +1,15 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::traits::{self, ObligationCause};
use crate::traits::{self, ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_span::DUMMY_SP;
use super::outlives_bounds::InferCtxtExt;
@ -131,3 +134,19 @@ pub fn type_allowed_to_implement_copy<'tcx>(
Ok(())
}
pub fn check_tys_might_be_eq<'tcx>(
tcx: TyCtxt<'tcx>,
canonical: Canonical<'tcx, (ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>,
) -> Result<(), NoSolution> {
let (infcx, (param_env, ty_a, ty_b), _) =
tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
let ocx = ObligationCtxt::new(&infcx);
let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b);
// use `select_where_possible` instead of `select_all_or_error` so that
// we don't get errors from obligations being ambiguous.
let errors = ocx.select_where_possible();
if errors.len() > 0 || result.is_err() { Err(NoSolution) } else { Ok(()) }
}

View file

@ -554,6 +554,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
subst_and_check_impossible_predicates,
check_tys_might_be_eq: misc::check_tys_might_be_eq,
is_impossible_method,
..*providers
};