diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 87e28f7fcc5..c5f12c0c691 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -472,17 +472,6 @@ impl<'a> Resolver<'a> { ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9321f11f659..92f21191de4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Type { default: Some(_), .. } - | GenericParamKind::Const { default: Some(_), .. } => { - found_default = true; - Some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - _ => None, - }, - )); + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| { - // HACK: We use an empty `ForwardGenericParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 129954381c9..1d1969f7e78 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -239,8 +239,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. @@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> { } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> { } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> { ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> { return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 00000000000..ba00e4b15ca --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +struct Bar() }>(T); +//~^ ERROR the size for values of type `T` cannot be known at compilation time + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr new file mode 100644 index 00000000000..06865fdd8fd --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/complex-generic-default-expr.rs:6:62 + | +LL | struct Bar() }>(T); + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 00000000000..2555450a9e7 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.stderr new file mode 100644 index 00000000000..b30b18a7b3c --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:6:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index a25d4baca1a..12a92a10476 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -10,4 +10,5 @@ trait Foo {} fn foo() {} -struct Range; +struct Range; + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index f7a1d2ca4b2..c514bbe72e1 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -17,4 +17,5 @@ trait Foo { } fn foo() { } struct Range; + FROM>; + diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 00000000000..c0c83cda285 --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct N; + +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index c2b7b206653..d8bfab6aa52 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -6,17 +6,26 @@ LL | struct Bar(T); | = note: using type defaults and const parameters in the same parameter list is currently not permitted -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 - | -LL | struct Foo()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` - -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 + | +LL | struct Foo()]>(T, U); + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` error: aborting due to 3 previous errors +Some errors have detailed explanations: E0128, E0277. +For more information about an error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4a462c328bf..44393a30266 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -15,11 +15,12 @@ LL | struct Foo()]>(T, U); = note: type parameters may not be used in const expressions = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index c7be8bdaf9c..8a84afd065c 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -4,12 +4,12 @@ #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR constant values inside of type parameter defaults +//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time //[min]~^^ ERROR generic parameters may not be used in const operations // FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); -//~^ ERROR constant values inside of type parameter defaults +//~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index cb2bb2832b7..16ea71d48c8 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -5,5 +5,6 @@ struct Vec(A, T); struct Foo, C>(A, B, C); //~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index 6d768617503..713ba091b86 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing LL | struct Foo, C>(A, B, C); | ^ -error: aborting due to 2 previous errors +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-non-trailing-defaults.rs:6:23 + | +LL | struct Foo, C>(A, B, C); + | ^ defaulted generic parameters cannot be forward declared +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0128`.