Use regular type equating instead of a custom query
This commit is contained in:
parent
9dc76207ff
commit
d5eb7a71b3
9 changed files with 50 additions and 66 deletions
|
@ -22,11 +22,11 @@ use super::glb::Glb;
|
|||
use super::lub::Lub;
|
||||
use super::type_relating::TypeRelating;
|
||||
use super::StructurallyRelateAliases;
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::canonical::OriginalQueryValues;
|
||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
|
||||
|
@ -159,34 +159,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let a = self.shallow_resolve_const(a);
|
||||
let b = self.shallow_resolve_const(b);
|
||||
|
||||
// We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
|
||||
// correct type for the generic param they are an argument for. However there have been a number of cases
|
||||
// historically where asserting that the types are equal has found bugs in the compiler so this is valuable
|
||||
// to check even if it is a bit nasty impl wise :(
|
||||
//
|
||||
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
|
||||
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
|
||||
self.probe(|_| {
|
||||
if a.ty() == b.ty() {
|
||||
return Ok(());
|
||||
}
|
||||
// It is always an error if the types of two constants that are related are not equal.
|
||||
let InferOk { value: (), obligations } = self
|
||||
.at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
|
||||
.eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
|
||||
relation.register_obligations(obligations);
|
||||
|
||||
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
|
||||
// two const param's types are able to be equal has to go through a canonical query with the actual logic
|
||||
// in `rustc_trait_selection`.
|
||||
let canonical = self.canonicalize_query(
|
||||
relation.param_env().and((a.ty(), b.ty())),
|
||||
&mut OriginalQueryValues::default(),
|
||||
);
|
||||
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
|
||||
// The error will only be reported later. If we emit an ErrorGuaranteed
|
||||
// here, then we will never get to the code that actually emits the error.
|
||||
self.tcx.dcx().delayed_bug(format!(
|
||||
"cannot relate consts of different types (a={a:?}, b={b:?})",
|
||||
));
|
||||
TypeError::Mismatch
|
||||
})
|
||||
})?;
|
||||
match (a.kind(), b.kind()) {
|
||||
(
|
||||
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
||||
|
|
|
@ -2218,15 +2218,6 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
|
||||
/// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
|
||||
/// the types might be equal.
|
||||
query check_tys_might_be_eq(
|
||||
arg: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>
|
||||
) -> Result<(), NoSolution> {
|
||||
desc { "check whether two const param are definitely not equal to eachother"}
|
||||
}
|
||||
|
||||
/// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
|
||||
/// Should not be called for the local crate before the resolver outputs are created, as it
|
||||
/// is only fed there.
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
||||
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
use crate::traits::{self, ObligationCause, ObligationCtxt};
|
||||
use crate::traits::{self, ObligationCause};
|
||||
|
||||
use hir::LangItem;
|
||||
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, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use super::outlives_bounds::InferCtxtExt;
|
||||
|
||||
|
@ -207,19 +204,3 @@ pub fn all_fields_implement_trait<'tcx>(
|
|||
|
||||
if infringing.is_empty() { Ok(()) } else { Err(infringing) }
|
||||
}
|
||||
|
||||
pub fn check_tys_might_be_eq<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
canonical: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>,
|
||||
) -> Result<(), NoSolution> {
|
||||
let (infcx, key, _) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
|
||||
let (param_env, (ty_a, ty_b)) = key.into_parts();
|
||||
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(()) }
|
||||
}
|
||||
|
|
|
@ -551,7 +551,6 @@ pub fn provide(providers: &mut Providers) {
|
|||
specialization_graph_of: specialize::specialization_graph_provider,
|
||||
specializes: specialize::specializes,
|
||||
instantiate_and_check_impossible_predicates,
|
||||
check_tys_might_be_eq: misc::check_tys_might_be_eq,
|
||||
is_impossible_associated_item,
|
||||
..*providers
|
||||
};
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
//@ known-bug: #119381
|
||||
|
||||
#![feature(with_negative_coherence)]
|
||||
trait Trait {}
|
||||
impl<const N: u8> Trait for [(); N] {}
|
||||
impl<const N: i8> Trait for [(); N] {}
|
|
@ -0,0 +1,12 @@
|
|||
//! This test used to ICE (#119381), because relating the `u8` and `i8` generic
|
||||
//! const with the array length of the `Self` type was succeeding under the
|
||||
//! assumption that an error had already been reported.
|
||||
|
||||
#![feature(with_negative_coherence)]
|
||||
trait Trait {}
|
||||
impl<const N: u8> Trait for [(); N] {}
|
||||
//~^ ERROR: mismatched types
|
||||
impl<const N: i8> Trait for [(); N] {}
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,15 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/generic_const_type_mismatch.rs:7:34
|
||||
|
|
||||
LL | impl<const N: u8> Trait for [(); N] {}
|
||||
| ^ expected `usize`, found `u8`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/generic_const_type_mismatch.rs:9:34
|
||||
|
|
||||
LL | impl<const N: i8> Trait for [(); N] {}
|
||||
| ^ expected `usize`, found `i8`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,4 +1,10 @@
|
|||
//@ check-pass
|
||||
//@ failure-status: 101
|
||||
//@ known-bug: unknown
|
||||
//@ normalize-stderr-test "note: .*\n\n" -> ""
|
||||
//@ normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
|
||||
//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
|
||||
//@ normalize-stderr-test "delayed at .*" -> ""
|
||||
//@ rustc-env:RUST_BACKTRACE=0
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params, generic_const_exprs)]
|
||||
|
|
8
tests/ui/const-generics/issues/issue-105821.stderr
Normal file
8
tests/ui/const-generics/issues/issue-105821.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
error: internal compiler error: compiler/rustc_borrowck/src/universal_regions.rs:LL:CC: cannot convert `'{erased}` to a region vid
|
||||
|
||||
query stack during panic:
|
||||
#0 [mir_borrowck] borrow-checking `<impl at $DIR/issue-105821.rs:21:1: 23:24>::R`
|
||||
#1 [analysis] running analysis passes on this crate
|
||||
end of query stack
|
||||
error: aborting due to 1 previous error
|
||||
|
Loading…
Add table
Reference in a new issue