From 73945fd6200521c5e2d18b2e0ec4cbd5f9d3762b Mon Sep 17 00:00:00 2001 From: Ellen Date: Fri, 14 Jan 2022 00:17:09 +0000 Subject: [PATCH 1/3] fix bug --- compiler/rustc_hir/src/hir.rs | 4 -- compiler/rustc_typeck/src/collect/type_of.rs | 67 ++++++++++--------- .../infer_arg_and_const_arg.rs | 12 ++++ .../issues/issue-62878.full.stderr | 11 +-- .../ui/const-generics/issues/issue-62878.rs | 3 +- 5 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 src/test/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f03d8eea40bb3..7a348a2c94aed 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -293,10 +293,6 @@ impl GenericArg<'_> { } } - pub fn is_const(&self) -> bool { - matches!(self, GenericArg::Const(_)) - } - pub fn is_synthetic(&self) -> bool { matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty()) } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index ae8d262fcf176..06f224802041f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -18,6 +18,7 @@ use super::{bad_placeholder, is_suggestable_infer_ty}; /// Computes the relevant generic parameter for a potential generic const argument. /// /// This should be called using the query `tcx.opt_const_param_of`. +#[instrument(level = "debug", skip(tcx))] pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { // FIXME(generic_arg_infer): allow for returning DefIds of inference of // GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag @@ -29,7 +30,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< let parent_node_id = tcx.hir().get_parent_node(hir_id); let parent_node = tcx.hir().get(parent_node_id); - match parent_node { + let (generics, arg_idx) = 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. // @@ -75,27 +76,22 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .and_then(|args| { args.args .iter() - .filter(|arg| arg.is_const()) + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) .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); + (generics, arg_index) + } else { + // 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; } - - // 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 { kind: @@ -113,19 +109,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .and_then(|args| { args.args .iter() - .filter(|arg| arg.is_const()) + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) .position(|arg| arg.id() == hir_id) }) .unwrap_or_else(|| { bug!("no arg matching AnonConst in segment"); }); - tcx.generics_of(type_dependent_def) - .params - .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) - .nth(idx) - .map(|param| param.def_id) + (tcx.generics_of(type_dependent_def), idx) } Node::Ty(&Ty { kind: TyKind::Path(_), .. }) @@ -178,7 +169,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .filter_map(|seg| seg.args.map(|args| (args.args, seg))) .find_map(|(args, seg)| { args.iter() - .filter(|arg| arg.is_const()) + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) .position(|arg| arg.id() == hir_id) .map(|index| (index, seg)) }); @@ -238,15 +229,29 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< } }; - generics - .params - .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) - .nth(arg_index) - .map(|param| param.def_id) + (generics, arg_index) } - _ => None, - } + _ => return None, + }; + + debug!(?parent_node); + debug!(?generics); + debug!(?arg_idx); + generics + .params + .iter() + .filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. })) + .nth(match generics.has_self && generics.parent.is_none() { + true => arg_idx + 1, + false => arg_idx, + }) + .and_then(|param| match param.kind { + ty::GenericParamDefKind::Const { .. } => { + debug!(?param); + Some(param.def_id) + } + _ => None, + }) } else { None } diff --git a/src/test/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs b/src/test/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs new file mode 100644 index 0000000000000..23c8d75375218 --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_arg_infer)] + +struct Foo; +struct Bar; + +fn main() { + let _: Foo = Foo::<_, 1>; + let _: Foo<_, 1> = Foo::; + let _: Bar<1, _> = Bar::<_, 300>; + let _: Bar<_, 300> = Bar::<1, _>; +} diff --git a/src/test/ui/const-generics/issues/issue-62878.full.stderr b/src/test/ui/const-generics/issues/issue-62878.full.stderr index f074a65313f12..3a2b291d7ba1f 100644 --- a/src/test/ui/const-generics/issues/issue-62878.full.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.full.stderr @@ -4,13 +4,6 @@ error[E0770]: the type of const parameters must not depend on other generic para LL | fn foo() {} | ^ the type must not depend on the parameter `N` -error[E0308]: mismatched types - --> $DIR/issue-62878.rs:10:15 - | -LL | foo::<_, {[1]}>(); - | ^^^ expected `usize`, found array `[{integer}; 1]` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0770. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0770`. diff --git a/src/test/ui/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs index 38f5ff77b56a9..578ce765b2fb8 100644 --- a/src/test/ui/const-generics/issues/issue-62878.rs +++ b/src/test/ui/const-generics/issues/issue-62878.rs @@ -7,6 +7,5 @@ fn foo() {} //[min]~| ERROR `[u8; _]` is forbidden as the type of a const generic parameter fn main() { - foo::<_, {[1]}>(); - //[full]~^ ERROR mismatched types + foo::<_, { [1] }>(); } From b3d71d900186c3fab2a91d84efcccc739df191d5 Mon Sep 17 00:00:00 2001 From: Ellen Date: Fri, 14 Jan 2022 00:18:11 +0000 Subject: [PATCH 2/3] reduce indentaton --- compiler/rustc_typeck/src/collect/type_of.rs | 408 +++++++++---------- 1 file changed, 201 insertions(+), 207 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 06f224802041f..effe31e4ee70c 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -26,85 +26,56 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< use hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - if let Node::AnonConst(_) = tcx.hir().get(hir_id) { - let parent_node_id = tcx.hir().get_parent_node(hir_id); - let parent_node = tcx.hir().get(parent_node_id); + match tcx.hir().get(hir_id) { + Node::AnonConst(_) => (), + _ => return None, + }; - let (generics, arg_idx) = 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; - // 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 ::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(::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| !matches!(arg, GenericArg::Lifetime(_))) - .position(|arg| arg.id() == hir_id) - }) - .unwrap_or_else(|| { - bug!("no arg matching AnonConst in segment"); - }); + let parent_node_id = tcx.hir().get_parent_node(hir_id); + let parent_node = tcx.hir().get(parent_node_id); - (generics, arg_index) - } else { - // 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 { - kind: - ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)), - .. - }) => { - let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id)); - let tables = tcx.typeck(body_owner); - // This may fail in case the method/path does not actually exist. - // As there is no relevant param for `def_id`, we simply return - // `None` here. - let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?; - let idx = segment + let (generics, arg_idx) = 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; + // 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 ::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(::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 @@ -116,145 +87,168 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< bug!("no arg matching AnonConst in segment"); }); - (tcx.generics_of(type_dependent_def), idx) + (generics, arg_index) + } else { + // 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 { + kind: + ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)), + .. + }) => { + let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id)); + let tables = tcx.typeck(body_owner); + // This may fail in case the method/path does not actually exist. + // As there is no relevant param for `def_id`, we simply return + // `None` here. + let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?; + let idx = segment + .args + .and_then(|args| { + args.args + .iter() + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .position(|arg| arg.id() == hir_id) + }) + .unwrap_or_else(|| { + bug!("no arg matching AnonConst in segment"); + }); - Node::Ty(&Ty { kind: TyKind::Path(_), .. }) - | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. }) - | Node::TraitRef(..) - | Node::Pat(_) => { - let path = match parent_node { - Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. }) - | Node::TraitRef(&TraitRef { path, .. }) => &*path, - Node::Expr(&Expr { - kind: - ExprKind::Path(QPath::Resolved(_, path)) - | ExprKind::Struct(&QPath::Resolved(_, path), ..), - .. - }) => { - let body_owner = - tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id)); - let _tables = tcx.typeck(body_owner); - &*path - } - Node::Pat(pat) => { - if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { - path - } else { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - &format!( - "unable to find const parent for {} in pat {:?}", - hir_id, pat - ), - ); - return None; - } - } - _ => { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - &format!("unexpected const parent path {:?}", parent_node), - ); - return None; - } - }; - - // We've encountered an `AnonConst` in some path, so we need to - // figure out which generic parameter it corresponds to and return - // the relevant type. - let filtered = path - .segments - .iter() - .filter_map(|seg| seg.args.map(|args| (args.args, seg))) - .find_map(|(args, seg)| { - args.iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) - .position(|arg| arg.id() == hir_id) - .map(|index| (index, seg)) - }); - let (arg_index, segment) = match filtered { - None => { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - "no arg matching AnonConst in path", - ); - return None; - } - Some(inner) => inner, - }; - - // Try to use the segment resolution if it is valid, otherwise we - // default to the path resolution. - let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); - use def::CtorOf; - let generics = match res { - Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx.generics_of( - tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap(), - ), - Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { - tcx.generics_of(tcx.parent(def_id).unwrap()) - } - // Other `DefKind`s don't have generics and would ICE when calling - // `generics_of`. - Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::OpaqueTy - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Fn - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::Impl, - def_id, - ) => tcx.generics_of(def_id), - Res::Err => { - tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); - return None; - } - _ => { - // If the user tries to specify generics on a type that does not take them, - // e.g. `usize`, we may hit this branch, in which case we treat it as if - // no arguments have been passed. An error should already have been emitted. + (tcx.generics_of(type_dependent_def), idx) + } + + Node::Ty(&Ty { kind: TyKind::Path(_), .. }) + | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. }) + | Node::TraitRef(..) + | Node::Pat(_) => { + let path = match parent_node { + Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. }) + | Node::TraitRef(&TraitRef { path, .. }) => &*path, + Node::Expr(&Expr { + kind: + ExprKind::Path(QPath::Resolved(_, path)) + | ExprKind::Struct(&QPath::Resolved(_, path), ..), + .. + }) => { + let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id)); + let _tables = tcx.typeck(body_owner); + &*path + } + Node::Pat(pat) => { + if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { + path + } else { tcx.sess.delay_span_bug( tcx.def_span(def_id), - &format!("unexpected anon const res {:?} in path: {:?}", res, path), + &format!("unable to find const parent for {} in pat {:?}", hir_id, pat), ); return None; } - }; + } + _ => { + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + &format!("unexpected const parent path {:?}", parent_node), + ); + return None; + } + }; + + // We've encountered an `AnonConst` in some path, so we need to + // figure out which generic parameter it corresponds to and return + // the relevant type. + let filtered = path + .segments + .iter() + .filter_map(|seg| seg.args.map(|args| (args.args, seg))) + .find_map(|(args, seg)| { + args.iter() + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .position(|arg| arg.id() == hir_id) + .map(|index| (index, seg)) + }); + let (arg_index, segment) = match filtered { + None => { + tcx.sess + .delay_span_bug(tcx.def_span(def_id), "no arg matching AnonConst in path"); + return None; + } + Some(inner) => inner, + }; + + // Try to use the segment resolution if it is valid, otherwise we + // default to the path resolution. + let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); + use def::CtorOf; + let generics = match res { + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx + .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()), + Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { + tcx.generics_of(tcx.parent(def_id).unwrap()) + } + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => tcx.generics_of(def_id), + Res::Err => { + tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); + return None; + } + _ => { + // If the user tries to specify generics on a type that does not take them, + // e.g. `usize`, we may hit this branch, in which case we treat it as if + // no arguments have been passed. An error should already have been emitted. + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + &format!("unexpected anon const res {:?} in path: {:?}", res, path), + ); + return None; + } + }; - (generics, arg_index) + (generics, arg_index) + } + _ => return None, + }; + + debug!(?parent_node); + debug!(?generics); + debug!(?arg_idx); + generics + .params + .iter() + .filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. })) + .nth(match generics.has_self && generics.parent.is_none() { + true => arg_idx + 1, + false => arg_idx, + }) + .and_then(|param| match param.kind { + ty::GenericParamDefKind::Const { .. } => { + debug!(?param); + Some(param.def_id) } - _ => return None, - }; - - debug!(?parent_node); - debug!(?generics); - debug!(?arg_idx); - generics - .params - .iter() - .filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. })) - .nth(match generics.has_self && generics.parent.is_none() { - true => arg_idx + 1, - false => arg_idx, - }) - .and_then(|param| match param.kind { - ty::GenericParamDefKind::Const { .. } => { - debug!(?param); - Some(param.def_id) - } - _ => None, - }) - } else { - None - } + _ => None, + }) } fn get_path_containing_arg_in_pat<'hir>( From 61c07a9a23d8967564bdddb5137efadeb48df271 Mon Sep 17 00:00:00 2001 From: Ellen Date: Fri, 14 Jan 2022 13:44:52 +0000 Subject: [PATCH 3/3] reviews ish --- compiler/rustc_hir/src/hir.rs | 7 +++++++ compiler/rustc_middle/src/ty/generics.rs | 7 +++++++ compiler/rustc_typeck/src/collect/type_of.rs | 11 +++++------ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7a348a2c94aed..76f4df6ec2da8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -314,6 +314,13 @@ impl GenericArg<'_> { GenericArg::Infer(_) => ast::ParamKindOrd::Infer, } } + + pub fn is_ty_or_const(&self) -> bool { + match self { + GenericArg::Lifetime(_) => false, + GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true, + } + } } #[derive(Debug, HashStable_Generic)] diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 1c3a01e2cfadf..0bd96f8f865fc 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -31,6 +31,13 @@ impl GenericParamDefKind { GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, } } + + pub fn is_ty_or_const(&self) -> bool { + match self { + GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true, + } + } } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index effe31e4ee70c..5ff2a74754117 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -80,7 +80,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .and_then(|args| { args.args .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .filter(|arg| arg.is_ty_or_const()) .position(|arg| arg.id() == hir_id) }) .unwrap_or_else(|| { @@ -113,7 +113,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .and_then(|args| { args.args .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .filter(|arg| arg.is_ty_or_const()) .position(|arg| arg.id() == hir_id) }) .unwrap_or_else(|| { @@ -169,7 +169,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .filter_map(|seg| seg.args.map(|args| (args.args, seg))) .find_map(|(args, seg)| { args.iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .filter(|arg| arg.is_ty_or_const()) .position(|arg| arg.id() == hir_id) .map(|index| (index, seg)) }); @@ -232,12 +232,11 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< }; debug!(?parent_node); - debug!(?generics); - debug!(?arg_idx); + debug!(?generics, ?arg_idx); generics .params .iter() - .filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. })) + .filter(|param| param.kind.is_ty_or_const()) .nth(match generics.has_self && generics.parent.is_none() { true => arg_idx + 1, false => arg_idx,