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::lub::Lub;
|
||||||
use super::type_relating::TypeRelating;
|
use super::type_relating::TypeRelating;
|
||||||
use super::StructurallyRelateAliases;
|
use super::StructurallyRelateAliases;
|
||||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
|
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
|
||||||
use crate::traits::{Obligation, PredicateObligations};
|
use crate::traits::{Obligation, PredicateObligations};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::infer::canonical::OriginalQueryValues;
|
|
||||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||||
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
|
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 a = self.shallow_resolve_const(a);
|
||||||
let b = self.shallow_resolve_const(b);
|
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
|
// It is always an error if the types of two constants that are related are not equal.
|
||||||
// correct type for the generic param they are an argument for. However there have been a number of cases
|
let InferOk { value: (), obligations } = self
|
||||||
// historically where asserting that the types are equal has found bugs in the compiler so this is valuable
|
.at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
|
||||||
// to check even if it is a bit nasty impl wise :(
|
.eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
|
||||||
//
|
relation.register_obligations(obligations);
|
||||||
// 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(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()) {
|
match (a.kind(), b.kind()) {
|
||||||
(
|
(
|
||||||
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
||||||
|
|
|
@ -2218,15 +2218,6 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
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.
|
/// 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
|
/// Should not be called for the local crate before the resolver outputs are created, as it
|
||||||
/// is only fed there.
|
/// is only fed there.
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
||||||
|
|
||||||
use crate::regions::InferCtxtRegionExt;
|
use crate::regions::InferCtxtRegionExt;
|
||||||
use crate::traits::{self, ObligationCause, ObligationCtxt};
|
use crate::traits::{self, ObligationCause};
|
||||||
|
|
||||||
use hir::LangItem;
|
use hir::LangItem;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::infer::canonical::Canonical;
|
|
||||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
|
||||||
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
|
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
|
||||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
|
|
||||||
use super::outlives_bounds::InferCtxtExt;
|
use super::outlives_bounds::InferCtxtExt;
|
||||||
|
|
||||||
|
@ -207,19 +204,3 @@ pub fn all_fields_implement_trait<'tcx>(
|
||||||
|
|
||||||
if infringing.is_empty() { Ok(()) } else { Err(infringing) }
|
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,
|
specialization_graph_of: specialize::specialization_graph_provider,
|
||||||
specializes: specialize::specializes,
|
specializes: specialize::specializes,
|
||||||
instantiate_and_check_impossible_predicates,
|
instantiate_and_check_impossible_predicates,
|
||||||
check_tys_might_be_eq: misc::check_tys_might_be_eq,
|
|
||||||
is_impossible_associated_item,
|
is_impossible_associated_item,
|
||||||
..*providers
|
..*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)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(adt_const_params, generic_const_exprs)]
|
#![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
Add a link
Reference in a new issue