From 6f5d8bf5c8ec9a62d62623e59fceb8abd0996f1b Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 9 Jul 2020 22:26:49 +0200 Subject: [PATCH] don't supply generics to AnonConsts in param lists --- src/librustc_typeck/collect.rs | 61 +++++++++++++++++-- ...const-param-type-depends-on-const-param.rs | 2 - ...t-param-type-depends-on-const-param.stderr | 33 +--------- .../ui/const-generics/issues/issue-74101.rs | 9 +++ 4 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/const-generics/issues/issue-74101.rs diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4354996614b..17212187e6a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items; -use rustc_hir::{GenericParamKind, Node}; +use rustc_hir::{GenericParamKind, HirId, Node}; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -1155,6 +1155,35 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamListDetector { + type Map = intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { + let prev = self.in_param_list; + self.in_param_list = true; + intravisit::walk_generic_param(self, p); + self.in_param_list = prev; + } + + fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { + if self.in_param_list && self.ct == c.hir_id { + self.found_anon_const_in_list = true; + } else { + intravisit::walk_anon_const(self, c) + } + } +} + fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { use rustc_hir::*; @@ -1176,10 +1205,32 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - // HACK(eddyb) this provides the correct generics when - // `feature(const_generics)` is enabled, so that const expressions - // used with const generics, e.g. `Foo<{N+1}>`, can work at all. - if tcx.lazy_normalization() { + let mut in_param_list = false; + for (_parent, node) in tcx.hir().parent_iter(hir_id) { + if let Some(generics) = node.generics() { + let mut visitor = AnonConstInParamListDetector { + in_param_list: false, + found_anon_const_in_list: false, + ct: hir_id, + }; + + visitor.visit_generics(generics); + in_param_list = visitor.found_anon_const_in_list; + break; + } + } + + if in_param_list { + // We do not allow generic parameters in anon consts if we are inside + // of a param list. + // + // This affects both default type bindings, e.g. `struct()]>(T, U)`, + // and the types of const parameters, e.g. `struct V();`. + None + } else if tcx.lazy_normalization() { + // HACK(eddyb) this provides the correct generics when + // `feature(const_generics)` is enabled, so that const expressions + // used with const generics, e.g. `Foo<{N+1}>`, can work at all. Some(parent_def_id.to_def_id()) } else { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs index 9aae73ca4b0..5aa3617d1d7 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.rs @@ -8,10 +8,8 @@ pub struct Dependent([(); N]); //~^ ERROR: the type of const parameters must not depend on other generic parameters -//~| ERROR: cycle detected when computing type of `Dependent::X` pub struct SelfDependent; //~^ ERROR: the type of const parameters must not depend on other generic parameters -//~| ERROR: cycle detected when computing type of `SelfDependent::N` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr index 22e55975dcd..a06bdea1b3c 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr @@ -4,8 +4,8 @@ error[E0770]: the type of const parameters must not depend on other generic para LL | pub struct Dependent([(); N]); | ^ const parameters must have a concrete type -error[E0769]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-const-param.rs:13:40 +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:12:40 | LL | pub struct SelfDependent; | ^ const parameters must have a concrete type @@ -19,32 +19,5 @@ LL | #![feature(const_generics)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0391]: cycle detected when computing type of `Dependent::X` - --> $DIR/const-param-type-depends-on-const-param.rs:9:44 - | -LL | pub struct Dependent([(); N]); - | ^ - | - = note: ...which again requires computing type of `Dependent::X`, completing the cycle -note: cycle used when computing type of `Dependent` - --> $DIR/const-param-type-depends-on-const-param.rs:9:1 - | -LL | pub struct Dependent([(); N]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors; 1 warning emitted -error[E0391]: cycle detected when computing type of `SelfDependent::N` - --> $DIR/const-param-type-depends-on-const-param.rs:13:32 - | -LL | pub struct SelfDependent; - | ^ - | - = note: ...which again requires computing type of `SelfDependent::N`, completing the cycle -note: cycle used when computing type of `SelfDependent` - --> $DIR/const-param-type-depends-on-const-param.rs:13:1 - | -LL | pub struct SelfDependent; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/const-generics/issues/issue-74101.rs b/src/test/ui/const-generics/issues/issue-74101.rs new file mode 100644 index 00000000000..2f427ef3a27 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-74101.rs @@ -0,0 +1,9 @@ +// check-pass +#![feature(const_generics)] +#![allow(incomplete_features)] + +fn test() {} + +struct Foo; + +fn main() {}