Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Use regular type equating instead of a custom query
  • Loading branch information
oli-obk committed May 24, 2024
commit d5eb7a71b3c869eb9e15f10da6eb92303b96dfb5
36 changes: 7 additions & 29 deletions compiler/rustc_infer/src/infer/relate/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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)),
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 1 addition & 20 deletions compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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(()) }
}
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
6 changes: 0 additions & 6 deletions tests/crashes/119381.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
8 changes: 7 additions & 1 deletion tests/ui/const-generics/issues/issue-105821.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/const-generics/issues/issue-105821.stderr
Original file line number Diff line number Diff line change
@@ -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