Skip to content

Commit a450339

Browse files
Rollup merge of rust-lang#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 rust-lang#118668 (merged) and rust-lang#121258, this supersedes rust-lang#118360. Fixes rust-lang#118040. r? ``@ghost``
2 parents e1ceadc + 858d336 commit a450339

File tree

5 files changed

+56
-40
lines changed

5 files changed

+56
-40
lines changed

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
408408
// Create the generic arguments for the associated type or constant by joining the
409409
// parent arguments (the arguments of the trait) and the own arguments (the ones of
410410
// the associated item itself) and construct an alias type using them.
411-
candidate.map_bound(|trait_ref| {
411+
let alias_ty = candidate.map_bound(|trait_ref| {
412412
let ident = Ident::new(assoc_item.name, binding.ident.span);
413413
let item_segment = hir::PathSegment {
414414
ident,
@@ -430,7 +430,25 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
430430
// *constants* to represent *const projections*. Alias *term* would be a more
431431
// appropriate name but alas.
432432
ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
433-
})
433+
});
434+
435+
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
436+
if !speculative
437+
&& let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } =
438+
binding.kind
439+
{
440+
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
441+
// Since the arguments passed to the alias type above may contain early-bound
442+
// generic parameters, the instantiated type may contain some as well.
443+
// Therefore wrap it in `EarlyBinder`.
444+
// FIXME(fmease): Reject escaping late-bound vars.
445+
tcx.feed_anon_const_type(
446+
anon_const.def_id,
447+
ty::EarlyBinder::bind(ty.skip_binder()),
448+
);
449+
}
450+
451+
alias_ty
434452
};
435453

436454
match binding.kind {

compiler/rustc_hir_analysis/src/collect/type_of.rs

-31
Original file line numberDiff line numberDiff line change
@@ -79,37 +79,6 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
7979
.expect("const parameter types cannot be generic");
8080
}
8181

82-
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
83-
if let Node::TraitRef(trait_ref) = tcx.parent_hir_node(binding_id) =>
84-
{
85-
let Some(trait_def_id) = trait_ref.trait_def_id() else {
86-
return Ty::new_error_with_message(
87-
tcx,
88-
tcx.def_span(def_id),
89-
"Could not find trait",
90-
);
91-
};
92-
let assoc_items = tcx.associated_items(trait_def_id);
93-
let assoc_item = assoc_items.find_by_name_and_kind(
94-
tcx,
95-
binding.ident,
96-
ty::AssocKind::Const,
97-
def_id.to_def_id(),
98-
);
99-
return if let Some(assoc_item) = assoc_item {
100-
tcx.type_of(assoc_item.def_id)
101-
.no_bound_vars()
102-
.expect("const parameter types cannot be generic")
103-
} else {
104-
// FIXME(associated_const_equality): add a useful error message here.
105-
Ty::new_error_with_message(
106-
tcx,
107-
tcx.def_span(def_id),
108-
"Could not find associated const on trait",
109-
)
110-
};
111-
}
112-
11382
// This match arm is for when the def_id appears in a GAT whose
11483
// path can't be resolved without typechecking e.g.
11584
//
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for issue #118040.
2+
// Ensure that we support assoc const eq bounds where the assoc const comes from a supertrait.
3+
4+
//@ check-pass
5+
6+
#![feature(associated_const_equality)]
7+
8+
trait Trait: SuperTrait {}
9+
trait SuperTrait: SuperSuperTrait<i32> {}
10+
trait SuperSuperTrait<T> {
11+
const K: T;
12+
}
13+
14+
fn take(_: impl Trait<K = 0>) {}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
// Regression test for issue #112560.
22
// Respect the fact that (associated) types and constants live in different namespaces and
33
// therefore equality bounds involving identically named associated items don't conflict if
4-
// their kind (type vs. const) differs.
5-
6-
// FIXME(fmease): Extend this test to cover supertraits again
7-
// once #118040 is fixed. See initial version of PR #118360.
4+
// their kind (type vs. const) differs. This obviously extends to supertraits.
85

96
//@ check-pass
107

118
#![feature(associated_const_equality)]
129

13-
trait Trait {
10+
trait Trait: SuperTrait {
1411
type N;
12+
type Q;
1513

1614
const N: usize;
1715
}
1816

19-
fn take(_: impl Trait<N = 0, N = ()>) {}
17+
trait SuperTrait {
18+
const Q: &'static str;
19+
}
20+
21+
fn take0(_: impl Trait<N = 0, N = ()>) {}
22+
23+
fn take1(_: impl Trait<Q = "...", Q = [()]>) {}
2024

2125
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
//@ check-pass
22

3-
#![feature(generic_const_items, associated_const_equality)]
3+
#![feature(generic_const_items, associated_const_equality, adt_const_params)]
44
#![allow(incomplete_features)]
55

66
trait Owner {
77
const C<const N: u32>: u32;
88
const K<const N: u32>: u32;
9+
const Q<T>: Maybe<T>;
910
}
1011

1112
impl Owner for () {
1213
const C<const N: u32>: u32 = N;
1314
const K<const N: u32>: u32 = N + 1;
15+
const Q<T>: Maybe<T> = Maybe::Nothing;
1416
}
1517

1618
fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
1719
fn take1(_: impl Owner<K<99> = 100>) {}
20+
fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
1821

1922
fn main() {
2023
take0::<128>(());
2124
take1(());
2225
}
26+
27+
#[derive(PartialEq, Eq, std::marker::ConstParamTy)]
28+
enum Maybe<T> {
29+
Nothing,
30+
Just(T),
31+
}

0 commit comments

Comments
 (0)