From 73945fd6200521c5e2d18b2e0ec4cbd5f9d3762b Mon Sep 17 00:00:00 2001 From: Ellen Date: Fri, 14 Jan 2022 00:17:09 +0000 Subject: [PATCH] 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 f03d8eea40b..7a348a2c94a 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 ae8d262fcf1..06f22480204 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 00000000000..23c8d753752 --- /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 f074a65313f..3a2b291d7ba 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 previous error -error: aborting due to 2 previous errors - -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 38f5ff77b56..578ce765b2f 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] }>(); }