Fix const generics in GAT

This commit is contained in:
Ellen 2021-02-09 08:57:42 +00:00
parent 36931ce3d9
commit 1d9ac3c22c
5 changed files with 114 additions and 0 deletions

View File

@ -29,6 +29,48 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
let parent_node = tcx.hir().get(parent_node_id);
match parent_node {
Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
let 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(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);
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);
}
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
return None;
}
Node::Expr(&Expr {
kind:
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),

View File

@ -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/")]
#![feature(bindings_after_at)]
#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]

View File

@ -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]);
}

View File

@ -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]);
}

View File

@ -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]);
}