about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2021-04-18 13:57:22 +0200
committerlcnr <rust@lcnr.de>2021-04-21 15:25:32 +0200
commit259a368e9eae8e9952d18e211d2fe0a7e5fae714 (patch)
tree31e6a0e03f7c14403205f2fabcd6c28258bdcdde
parentd7c338641466d54bf8d4b2eae5d6865483e1d3f4 (diff)
downloadrust-259a368e9eae8e9952d18e211d2fe0a7e5fae714.tar.gz
rust-259a368e9eae8e9952d18e211d2fe0a7e5fae714.zip
fix name resolution for param defaults
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs11
-rw-r--r--compiler/rustc_resolve/src/late.rs69
-rw-r--r--compiler/rustc_resolve/src/lib.rs58
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.rs9
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr16
-rw-r--r--src/test/ui/const-generics/defaults/default-on-impl.rs9
-rw-r--r--src/test/ui/const-generics/defaults/default-on-impl.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/pretty-printing-ast.rs3
-rw-r--r--src/test/ui/const-generics/defaults/pretty-printing-ast.stdout3
-rw-r--r--src/test/ui/const-generics/defaults/type-default-const-param-name.rs17
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr23
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr5
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs4
-rw-r--r--src/test/ui/generics/generic-non-trailing-defaults.rs1
-rw-r--r--src/test/ui/generics/generic-non-trailing-defaults.stderr9
15 files changed, 141 insertions, 104 deletions
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<Rhs = Self>`.)
         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 &param.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<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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,
-
-                        // We only forbid constant items if we are inside of type defaults,
-                        // for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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;
-                        }
+                        | MacroDefinition(..)
+                        | ForwardGenericParamBanRibKind => 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<const N: usize, const M: usize = { N + 1 }>;
+
+struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(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, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(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<T>() -> 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<const N: usize>;
+
+impl<const N: usize = 1> Foo<N> {}
+//~^ 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<const N: usize = 1> Foo<N> {}
+   |            ^
+
+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<const KIND: bool = true> {}
 
 fn foo<const SIZE: usize = 5>() {}
 
-struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = {FROM + LEN}>;
+struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>;
+
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<const KIND : bool = true> { }
 fn foo<const SIZE : usize = 5>() { }
 
 struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
-             { FROM + LEN }>;
+             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<const N: usize = 1, T = N>(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 = [u8; N], const N: usize>(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
+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 = [u8; N], const N: usize>(T);
+   |                     ^ 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 = [u8; std::mem::size_of::<T>()]>(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
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
+   |            -                               ^ 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 | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
+LL | pub const fn size_of<T>() -> 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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; N], const N: usize>(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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; N], const N: usize>(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 = Heap, T>(A, T);
 
 struct Foo<A, B = Vec<C>, 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<A, B = Vec<C>, 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<A, B = Vec<C>, 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`.