about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2024-01-01 19:29:27 +0100
committerLeón Orell Valerian Liehr <me@fmease.dev>2024-01-01 21:58:25 +0100
commit3d0297a1e1b74ab50b97f78cf4fd056cb0ed51a7 (patch)
tree4a95288e44ac128aa9396c3e67e80da8aa4d14b5
parent88d69b72b4ccfd4e4b64451a7a5d9fd23d2249a3 (diff)
downloadrust-3d0297a1e1b74ab50b97f78cf4fd056cb0ed51a7.tar.gz
rust-3d0297a1e1b74ab50b97f78cf4fd056cb0ed51a7.zip
Deny defaults for higher-ranked generic parameters
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl5
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs70
-rw-r--r--tests/ui/closures/issue-112547.rs15
-rw-r--r--tests/ui/parser/generic-param-default-in-binder.rs10
-rw-r--r--tests/ui/parser/issue-119042.rs7
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs16
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr (renamed from tests/ui/closures/issue-112547.stderr)15
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs (renamed from tests/ui/traits/non_lifetime_binders/issue-118697.rs)2
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr (renamed from tests/ui/traits/non_lifetime_binders/issue-118697.stderr)12
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs12
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr31
12 files changed, 133 insertions, 66 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 5a1b1c799eb..fd94e7e9341 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -45,8 +45,6 @@ ast_lowering_closure_cannot_be_static = closures cannot be static
 ast_lowering_coroutine_too_many_parameters =
     too many parameters for a coroutine (expected 0 or 1 parameters)
 
-ast_lowering_default_parameter_in_binder = default parameter is not allowed in this binder
-
 ast_lowering_does_not_support_modifiers =
     the `{$class_name}` register class does not support template modifiers
 
@@ -58,6 +56,9 @@ ast_lowering_functional_record_update_destructuring_assignment =
     functional record updates are not allowed in destructuring assignments
     .suggestion = consider removing the trailing pattern
 
+ast_lowering_generic_param_default_in_binder =
+    defaults for generic parameters are not allowed in `for<...>` binders
+
 ast_lowering_generic_type_with_parentheses =
     parenthesized type parameters may only be used with a `Fn` trait
     .label = only `Fn` traits may use parentheses
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 718a5b03cf2..710690d0d86 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -397,8 +397,8 @@ pub enum BadReturnTypeNotation {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_default_parameter_in_binder)]
-pub(crate) struct UnexpectedDefaultParameterInBinder {
+#[diag(ast_lowering_generic_param_default_in_binder)]
+pub(crate) struct GenericParamDefaultInBinder {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 92fd29c47af..c7c77bf56b7 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -66,7 +66,6 @@ use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{DesugaringKind, Span, DUMMY_SP};
 use smallvec::SmallVec;
-use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use thin_vec::ThinVec;
 
@@ -884,27 +883,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         binder: NodeId,
         generic_params: &[GenericParam],
     ) -> &'hir [hir::GenericParam<'hir>] {
-        let mut generic_params: Vec<_> = generic_params
-            .iter()
-            .map(|param| {
-                let param = match param.kind {
-                    GenericParamKind::Type { ref default } if let Some(ty) = default => {
-                        // Default type is not permitted in non-lifetime binders.
-                        // So we emit an error and default to `None` to prevent
-                        // potential ice.
-                        self.dcx().emit_err(errors::UnexpectedDefaultParameterInBinder {
-                            span: ty.span(),
-                        });
-                        let param = GenericParam {
-                            kind: GenericParamKind::Type { default: None },
-                            ..param.clone()
-                        };
-                        Cow::Owned(param)
-                    }
-                    _ => Cow::Borrowed(param),
-                };
-                self.lower_generic_param(param.as_ref(), hir::GenericParamSource::Binder)
-            })
+        let mut generic_params: Vec<_> = self
+            .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
             .collect();
         let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
         debug!(?extra_lifetimes);
@@ -2136,7 +2116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         param: &GenericParam,
         source: hir::GenericParamSource,
     ) -> hir::GenericParam<'hir> {
-        let (name, kind) = self.lower_generic_param_kind(param);
+        let (name, kind) = self.lower_generic_param_kind(param, source);
 
         let hir_id = self.lower_node_id(param.id);
         self.lower_attrs(hir_id, &param.attrs);
@@ -2155,6 +2135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_generic_param_kind(
         &mut self,
         param: &GenericParam,
+        source: hir::GenericParamSource,
     ) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
         match &param.kind {
             GenericParamKind::Lifetime => {
@@ -2173,22 +2154,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 (param_name, kind)
             }
             GenericParamKind::Type { default, .. } => {
-                let kind = hir::GenericParamKind::Type {
-                    default: default.as_ref().map(|x| {
+                // Not only do we deny type param defaults in binders but we also map them to `None`
+                // since later compiler stages cannot handle them (and shouldn't need to be able to).
+                let default = default
+                    .as_ref()
+                    .filter(|_| match source {
+                        hir::GenericParamSource::Generics => true,
+                        hir::GenericParamSource::Binder => {
+                            self.dcx().emit_err(errors::GenericParamDefaultInBinder {
+                                span: param.span(),
+                            });
+
+                            false
+                        }
+                    })
+                    .map(|def| {
                         self.lower_ty(
-                            x,
+                            def,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
                         )
-                    }),
-                    synthetic: false,
-                };
+                    });
+
+                let kind = hir::GenericParamKind::Type { default, synthetic: false };
 
                 (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
             }
             GenericParamKind::Const { ty, kw_span: _, default } => {
                 let ty = self
                     .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
-                let default = default.as_ref().map(|def| self.lower_anon_const(def));
+
+                // Not only do we deny const param defaults in binders but we also map them to `None`
+                // since later compiler stages cannot handle them (and shouldn't need to be able to).
+                let default = default
+                    .as_ref()
+                    .filter(|_| match source {
+                        hir::GenericParamSource::Generics => true,
+                        hir::GenericParamSource::Binder => {
+                            self.dcx().emit_err(errors::GenericParamDefaultInBinder {
+                                span: param.span(),
+                            });
+
+                            false
+                        }
+                    })
+                    .map(|def| self.lower_anon_const(def));
+
                 (
                     hir::ParamName::Plain(self.lower_ident(param.ident)),
                     hir::GenericParamKind::Const { ty, default, is_host_effect: false },
diff --git a/tests/ui/closures/issue-112547.rs b/tests/ui/closures/issue-112547.rs
deleted file mode 100644
index 8ecb2abccd4..00000000000
--- a/tests/ui/closures/issue-112547.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(non_lifetime_binders)]
-        //~^ WARNING the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-
-pub fn bar()
-where
-    for<const N: usize = {
-    (||1usize)()
-}> V: IntoIterator
-//~^ ERROR cannot find type `V` in this scope [E0412]
-{
-}
-
-fn main() {
-    bar();
-}
diff --git a/tests/ui/parser/generic-param-default-in-binder.rs b/tests/ui/parser/generic-param-default-in-binder.rs
new file mode 100644
index 00000000000..78dc4186b3a
--- /dev/null
+++ b/tests/ui/parser/generic-param-default-in-binder.rs
@@ -0,0 +1,10 @@
+// Check that defaults for generic parameters in `for<...>` binders are
+// syntactically valid. See also PR #119042.
+
+// check-pass
+
+macro_rules! a { ($ty:ty) => {} }
+
+a! { for<T = &i32> fn() }
+
+fn main() {}
diff --git a/tests/ui/parser/issue-119042.rs b/tests/ui/parser/issue-119042.rs
deleted file mode 100644
index a4fee169d1c..00000000000
--- a/tests/ui/parser/issue-119042.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// check-pass
-
-macro_rules! a { ($ty:ty) => {} }
-
-a! { for<T = &i32> fn() }
-
-fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
new file mode 100644
index 00000000000..c6bf0dc1f72
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
@@ -0,0 +1,16 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+pub fn bar()
+where
+    for<const N: usize = {
+    (||1usize)()
+}> V: IntoIterator
+//~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+//~^^ ERROR cannot find type `V` in this scope
+{
+}
+
+fn main() {
+    bar();
+}
diff --git a/tests/ui/closures/issue-112547.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
index f47ea607297..edc55a3c8e6 100644
--- a/tests/ui/closures/issue-112547.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `V` in this scope
-  --> $DIR/issue-112547.rs:8:4
+  --> $DIR/binder-defaults-112547.rs:8:4
    |
 LL | }> V: IntoIterator
    |    ^ not found in this scope
@@ -10,7 +10,7 @@ LL | pub fn bar<V>()
    |           +++
 
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-112547.rs:1:12
+  --> $DIR/binder-defaults-112547.rs:1:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -18,6 +18,15 @@ LL | #![feature(non_lifetime_binders)]
    = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-112547.rs:6:9
+   |
+LL |       for<const N: usize = {
+   |  _________^
+LL | |     (||1usize)()
+LL | | }> V: IntoIterator
+   | |_^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/non_lifetime_binders/issue-118697.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs
index a282d0c5a40..2dc9fb98b15 100644
--- a/tests/ui/traits/non_lifetime_binders/issue-118697.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs
@@ -2,7 +2,7 @@
 #![feature(non_lifetime_binders)]
 
 type T = dyn for<V = A(&())> Fn(());
-//~^ ERROR default parameter is not allowed in this binder
+//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
 //~| ERROR cannot find type `A` in this scope
 //~| ERROR late-bound type parameter not allowed on trait object types
 
diff --git a/tests/ui/traits/non_lifetime_binders/issue-118697.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr
index 52ce568d69d..6b93f52dbfc 100644
--- a/tests/ui/traits/non_lifetime_binders/issue-118697.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr
@@ -1,20 +1,20 @@
 error[E0412]: cannot find type `A` in this scope
-  --> $DIR/issue-118697.rs:4:22
+  --> $DIR/binder-defaults-118697.rs:4:22
    |
 LL | type T = dyn for<V = A(&())> Fn(());
    |                      ^ not found in this scope
 
-error: default parameter is not allowed in this binder
-  --> $DIR/issue-118697.rs:4:22
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-118697.rs:4:18
    |
 LL | type T = dyn for<V = A(&())> Fn(());
-   |                      ^^^^^^
+   |                  ^^^^^^^^^^
 
 error: late-bound type parameter not allowed on trait object types
-  --> $DIR/issue-118697.rs:4:18
+  --> $DIR/binder-defaults-118697.rs:4:18
    |
 LL | type T = dyn for<V = A(&())> Fn(());
-   |                  ^
+   |                  ^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
new file mode 100644
index 00000000000..f33da416ad8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
@@ -0,0 +1,12 @@
+#![feature(non_lifetime_binders, generic_const_exprs)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+//~| WARN the feature `generic_const_exprs` is incomplete
+
+fn fun()
+where
+    for<T = (), const N: usize = 1> ():,
+//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+//~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
new file mode 100644
index 00000000000..7fe82f1f097
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
@@ -0,0 +1,31 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/binder-defaults-119489.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/binder-defaults-119489.rs:1:34
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-119489.rs:7:9
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |         ^^^^^^
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-119489.rs:7:17
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+