Skip to content

Commit

Permalink
Rollup merge of rust-lang#90266 - b-naber:uneval_substs, r=lcnr
Browse files Browse the repository at this point in the history
Prevent duplicate caller bounds candidates by exposing default substs in Unevaluated

Fixes rust-lang#89334

The changes introduced in rust-lang#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`
  • Loading branch information
matthiaskrgr committed Oct 25, 2021
2 parents d35ecb9 + 0199a81 commit 26e9a71
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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))
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/const-generics/expose-default-substs-param-env.rs
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/ui/const-generics/issues/issue-89334.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 26e9a71

Please sign in to comment.