Rollup merge of #81911 - BoxyUwU:constgenericgaticefix, r=nikomatsakis
GAT/const_generics: Allow with_opt_const_param to return GAT param def_id Fixes #75415 Fixes #79666 cc ```@lcnr``` I've absolutely no idea who to r? for this...
This commit is contained in:
commit
b67be3aa6b
5 changed files with 139 additions and 0 deletions
|
@ -29,6 +29,73 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
||||||
let parent_node = tcx.hir().get(parent_node_id);
|
let parent_node = tcx.hir().get(parent_node_id);
|
||||||
|
|
||||||
match parent_node {
|
match parent_node {
|
||||||
|
// This match arm is for when the def_id appears in a GAT whose
|
||||||
|
// path can't be resolved without typechecking e.g.
|
||||||
|
//
|
||||||
|
// trait Foo {
|
||||||
|
// type Assoc<const N: usize>;
|
||||||
|
// fn foo() -> Self::Assoc<3>;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// In the above code we would call this query with the def_id of 3 and
|
||||||
|
// the parent_node we match on would be the hir node for Self::Assoc<3>
|
||||||
|
//
|
||||||
|
// `Self::Assoc<3>` cant be resolved without typchecking here as we
|
||||||
|
// didnt write <Self as Foo>::Assoc<3>. If we did then another match
|
||||||
|
// arm would handle this.
|
||||||
|
//
|
||||||
|
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
|
||||||
|
Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
|
||||||
|
// Find the Item containing the associated type so we can create an ItemCtxt.
|
||||||
|
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
|
||||||
|
// ty which is a fully resolved projection.
|
||||||
|
// For the code example above, this would mean converting Self::Assoc<3>
|
||||||
|
// into a ty::Projection(<Self as Foo>::Assoc<3>)
|
||||||
|
let item_hir_id = tcx
|
||||||
|
.hir()
|
||||||
|
.parent_iter(hir_id)
|
||||||
|
.filter(|(_, node)| matches!(node, Node::Item(_)))
|
||||||
|
.map(|(id, _)| id)
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
|
||||||
|
let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
|
||||||
|
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
|
||||||
|
|
||||||
|
// Iterate through the generics of the projection to find the one that corresponds to
|
||||||
|
// the def_id that this query was called with. We filter to only const args here as a
|
||||||
|
// precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
|
||||||
|
// but it can't hurt to be safe ^^
|
||||||
|
if let ty::Projection(projection) = ty.kind() {
|
||||||
|
let generics = tcx.generics_of(projection.item_def_id);
|
||||||
|
|
||||||
|
let arg_index = segment
|
||||||
|
.args
|
||||||
|
.and_then(|args| {
|
||||||
|
args.args
|
||||||
|
.iter()
|
||||||
|
.filter(|arg| arg.is_const())
|
||||||
|
.position(|arg| arg.id() == hir_id)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
bug!("no arg matching AnonConst in segment");
|
||||||
|
});
|
||||||
|
|
||||||
|
return generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
|
||||||
|
.nth(arg_index)
|
||||||
|
.map(|param| param.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
|
||||||
|
tcx.sess.delay_span_bug(
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
"unexpected non-GAT usage of an anon const",
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
Node::Expr(&Expr {
|
Node::Expr(&Expr {
|
||||||
kind:
|
kind:
|
||||||
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
|
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
|
||||||
|
|
|
@ -56,6 +56,7 @@ This API is completely unstable and subject to change.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
|
#![feature(bindings_after_at)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// run-pass
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// This test unsures that with_opt_const_param returns the
|
||||||
|
// def_id of the N param in the Foo::Assoc GAT.
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type Assoc<const N: usize>;
|
||||||
|
fn foo(&self) -> Self::Assoc<3>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
type Assoc<const N: usize> = [(); N];
|
||||||
|
fn foo(&self) -> Self::Assoc<3> {
|
||||||
|
[(); 3]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(().foo(), [(); 3]);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// run-pass
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// This test unsures that with_opt_const_param returns the
|
||||||
|
// def_id of the N param in the Foo::Assoc GAT.
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type Assoc<const N: usize>;
|
||||||
|
fn foo<const N: usize>(&self) -> Self::Assoc<N>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
type Assoc<const N: usize> = [(); N];
|
||||||
|
fn foo<const N: usize>(&self) -> Self::Assoc<N> {
|
||||||
|
[(); N]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(().foo::<10>(), [(); 10]);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// run-pass
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// This test unsures that with_opt_const_param returns the
|
||||||
|
// def_id of the N param in the Bar::Assoc GAT.
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
type Assoc<const N: usize>;
|
||||||
|
}
|
||||||
|
trait Foo: Bar {
|
||||||
|
fn foo(&self) -> Self::Assoc<3>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bar for () {
|
||||||
|
type Assoc<const N: usize> = [(); N];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
fn foo(&self) -> Self::Assoc<3> {
|
||||||
|
[(); 3]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(().foo(), [(); 3]);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue