Rollup merge of #90266 - b-naber:uneval_substs, r=lcnr

Prevent duplicate caller bounds candidates by exposing default substs in Unevaluated

Fixes https://github.com/rust-lang/rust/issues/89334

The changes introduced in https://github.com/rust-lang/rust/pull/87280 allowed for "duplicate" caller bounds candidates to be assembled that only differed in their default substs having been "exposed" or not and resulted in an ambiguity error during trait selection. To fix this we expose the defaults substs during the creation of the ParamEnv.

r? `@lcnr`
This commit is contained in:
Matthias Krüger 2021-10-25 22:59:49 +02:00 committed by GitHub
commit 26e9a719f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 0 deletions

View File

@ -247,6 +247,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
}
/// See `ParamEnv` struct definition for details.
#[instrument(level = "debug", skip(tcx))]
fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
// The param_env of an impl Trait type is its defining function's param_env
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
@ -274,9 +275,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
predicates.extend(environment);
}
// It's important that we include the default substs in unevaluated
// constants, since `Unevaluated` instances in predicates whose substs are None
// can lead to "duplicate" caller bounds candidates during trait selection,
// duplicate in the sense that both have their default substs, but the
// candidate that resulted from a superpredicate still uses `None` in its
// `substs_` field of `Unevaluated` to indicate that it has its default substs,
// whereas the other candidate has `substs_: Some(default_substs)`, see
// issue #89334
predicates = tcx.expose_default_const_substs(predicates);
let unnormalized_env =
ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds());
let body_id = def_id
.as_local()
.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))

View File

@ -0,0 +1,9 @@
// build-pass
#![feature(generic_const_exprs)]
#![allow(unused_braces, incomplete_features)]
pub trait Foo<const N: usize> {}
pub trait Bar: Foo<{ 1 }> { }
fn main() {}

View File

@ -0,0 +1,16 @@
// build-pass
#![feature(generic_const_exprs)]
#![allow(unused_braces, incomplete_features)]
pub trait AnotherTrait{
const ARRAY_SIZE: usize;
}
pub trait Shard<T: AnotherTrait>:
AsMut<[[u8; T::ARRAY_SIZE]]>
where
[(); T::ARRAY_SIZE]: Sized
{
}
fn main() {}