Rollup merge of #119385 - fmease:assoc-const-eq-fixes-2, r=oli-obk,cjgillot
Fix type resolution of associated const equality bounds (take 2) Instead of trying to re-resolve the type of assoc const bindings inside the `type_of` query impl in an incomplete manner, transfer the already (correctly) resolved type from `add_predicates_for_ast_type_binding` to `type_of`/`anon_type_of` through query feeding. --- Together with #118668 (merged) and #121258, this supersedes #118360. Fixes #118040. r? ``@ghost``
This commit is contained in:
commit
a4503390ba
@ -408,7 +408,7 @@ pub(super) fn add_predicates_for_ast_type_binding(
|
|||||||
// Create the generic arguments for the associated type or constant by joining the
|
// Create the generic arguments for the associated type or constant by joining the
|
||||||
// parent arguments (the arguments of the trait) and the own arguments (the ones of
|
// parent arguments (the arguments of the trait) and the own arguments (the ones of
|
||||||
// the associated item itself) and construct an alias type using them.
|
// the associated item itself) and construct an alias type using them.
|
||||||
candidate.map_bound(|trait_ref| {
|
let alias_ty = candidate.map_bound(|trait_ref| {
|
||||||
let ident = Ident::new(assoc_item.name, binding.ident.span);
|
let ident = Ident::new(assoc_item.name, binding.ident.span);
|
||||||
let item_segment = hir::PathSegment {
|
let item_segment = hir::PathSegment {
|
||||||
ident,
|
ident,
|
||||||
@ -430,7 +430,25 @@ pub(super) fn add_predicates_for_ast_type_binding(
|
|||||||
// *constants* to represent *const projections*. Alias *term* would be a more
|
// *constants* to represent *const projections*. Alias *term* would be a more
|
||||||
// appropriate name but alas.
|
// appropriate name but alas.
|
||||||
ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
|
ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
|
||||||
})
|
});
|
||||||
|
|
||||||
|
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
|
||||||
|
if !speculative
|
||||||
|
&& let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } =
|
||||||
|
binding.kind
|
||||||
|
{
|
||||||
|
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
|
||||||
|
// Since the arguments passed to the alias type above may contain early-bound
|
||||||
|
// generic parameters, the instantiated type may contain some as well.
|
||||||
|
// Therefore wrap it in `EarlyBinder`.
|
||||||
|
// FIXME(fmease): Reject escaping late-bound vars.
|
||||||
|
tcx.feed_anon_const_type(
|
||||||
|
anon_const.def_id,
|
||||||
|
ty::EarlyBinder::bind(ty.skip_binder()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
alias_ty
|
||||||
};
|
};
|
||||||
|
|
||||||
match binding.kind {
|
match binding.kind {
|
||||||
|
@ -79,37 +79,6 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||||||
.expect("const parameter types cannot be generic");
|
.expect("const parameter types cannot be generic");
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
|
|
||||||
if let Node::TraitRef(trait_ref) = tcx.parent_hir_node(binding_id) =>
|
|
||||||
{
|
|
||||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
tcx.def_span(def_id),
|
|
||||||
"Could not find trait",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let assoc_items = tcx.associated_items(trait_def_id);
|
|
||||||
let assoc_item = assoc_items.find_by_name_and_kind(
|
|
||||||
tcx,
|
|
||||||
binding.ident,
|
|
||||||
ty::AssocKind::Const,
|
|
||||||
def_id.to_def_id(),
|
|
||||||
);
|
|
||||||
return if let Some(assoc_item) = assoc_item {
|
|
||||||
tcx.type_of(assoc_item.def_id)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("const parameter types cannot be generic")
|
|
||||||
} else {
|
|
||||||
// FIXME(associated_const_equality): add a useful error message here.
|
|
||||||
Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
tcx.def_span(def_id),
|
|
||||||
"Could not find associated const on trait",
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// This match arm is for when the def_id appears in a GAT whose
|
// This match arm is for when the def_id appears in a GAT whose
|
||||||
// path can't be resolved without typechecking e.g.
|
// path can't be resolved without typechecking e.g.
|
||||||
//
|
//
|
||||||
|
16
tests/ui/associated-consts/assoc-const-eq-supertraits.rs
Normal file
16
tests/ui/associated-consts/assoc-const-eq-supertraits.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Regression test for issue #118040.
|
||||||
|
// Ensure that we support assoc const eq bounds where the assoc const comes from a supertrait.
|
||||||
|
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(associated_const_equality)]
|
||||||
|
|
||||||
|
trait Trait: SuperTrait {}
|
||||||
|
trait SuperTrait: SuperSuperTrait<i32> {}
|
||||||
|
trait SuperSuperTrait<T> {
|
||||||
|
const K: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take(_: impl Trait<K = 0>) {}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,21 +1,25 @@
|
|||||||
// Regression test for issue #112560.
|
// Regression test for issue #112560.
|
||||||
// Respect the fact that (associated) types and constants live in different namespaces and
|
// Respect the fact that (associated) types and constants live in different namespaces and
|
||||||
// therefore equality bounds involving identically named associated items don't conflict if
|
// therefore equality bounds involving identically named associated items don't conflict if
|
||||||
// their kind (type vs. const) differs.
|
// their kind (type vs. const) differs. This obviously extends to supertraits.
|
||||||
|
|
||||||
// FIXME(fmease): Extend this test to cover supertraits again
|
|
||||||
// once #118040 is fixed. See initial version of PR #118360.
|
|
||||||
|
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
|
|
||||||
#![feature(associated_const_equality)]
|
#![feature(associated_const_equality)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait: SuperTrait {
|
||||||
type N;
|
type N;
|
||||||
|
type Q;
|
||||||
|
|
||||||
const N: usize;
|
const N: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take(_: impl Trait<N = 0, N = ()>) {}
|
trait SuperTrait {
|
||||||
|
const Q: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take0(_: impl Trait<N = 0, N = ()>) {}
|
||||||
|
|
||||||
|
fn take1(_: impl Trait<Q = "...", Q = [()]>) {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,22 +1,31 @@
|
|||||||
//@ check-pass
|
//@ check-pass
|
||||||
|
|
||||||
#![feature(generic_const_items, associated_const_equality)]
|
#![feature(generic_const_items, associated_const_equality, adt_const_params)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
trait Owner {
|
trait Owner {
|
||||||
const C<const N: u32>: u32;
|
const C<const N: u32>: u32;
|
||||||
const K<const N: u32>: u32;
|
const K<const N: u32>: u32;
|
||||||
|
const Q<T>: Maybe<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Owner for () {
|
impl Owner for () {
|
||||||
const C<const N: u32>: u32 = N;
|
const C<const N: u32>: u32 = N;
|
||||||
const K<const N: u32>: u32 = N + 1;
|
const K<const N: u32>: u32 = N + 1;
|
||||||
|
const Q<T>: Maybe<T> = Maybe::Nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
|
fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
|
||||||
fn take1(_: impl Owner<K<99> = 100>) {}
|
fn take1(_: impl Owner<K<99> = 100>) {}
|
||||||
|
fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
take0::<128>(());
|
take0::<128>(());
|
||||||
take1(());
|
take1(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, std::marker::ConstParamTy)]
|
||||||
|
enum Maybe<T> {
|
||||||
|
Nothing,
|
||||||
|
Just(T),
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user