Skip to content

Commit be656cf

Browse files
committed
Deny defaults for higher-ranked generic parameters
1 parent 88d69b7 commit be656cf

9 files changed

+105
-48
lines changed

compiler/rustc_ast_lowering/messages.ftl

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ ast_lowering_closure_cannot_be_static = closures cannot be static
4545
ast_lowering_coroutine_too_many_parameters =
4646
too many parameters for a coroutine (expected 0 or 1 parameters)
4747
48-
ast_lowering_default_parameter_in_binder = default parameter is not allowed in this binder
49-
5048
ast_lowering_does_not_support_modifiers =
5149
the `{$class_name}` register class does not support template modifiers
5250
@@ -62,6 +60,9 @@ ast_lowering_generic_type_with_parentheses =
6260
parenthesized type parameters may only be used with a `Fn` trait
6361
.label = only `Fn` traits may use parentheses
6462
63+
ast_lowering_higher_ranked_gen_param_with_default =
64+
higher-ranked generic parameters may not have defaults
65+
6566
ast_lowering_inclusive_range_with_no_end = inclusive range with no end
6667
6768
ast_lowering_inline_asm_unsupported_target =

compiler/rustc_ast_lowering/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,8 @@ pub enum BadReturnTypeNotation {
397397
}
398398

399399
#[derive(Diagnostic)]
400-
#[diag(ast_lowering_default_parameter_in_binder)]
401-
pub(crate) struct UnexpectedDefaultParameterInBinder {
400+
#[diag(ast_lowering_higher_ranked_gen_param_with_default)]
401+
pub(crate) struct HigherRankedGenParamWithDefault {
402402
#[primary_span]
403403
pub span: Span,
404404
}

compiler/rustc_ast_lowering/src/lib.rs

+40-30
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ use rustc_session::parse::{add_feature_diagnostics, feature_err};
6666
use rustc_span::symbol::{kw, sym, Ident, Symbol};
6767
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
6868
use smallvec::SmallVec;
69-
use std::borrow::Cow;
7069
use std::collections::hash_map::Entry;
7170
use thin_vec::ThinVec;
7271

@@ -884,27 +883,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
884883
binder: NodeId,
885884
generic_params: &[GenericParam],
886885
) -> &'hir [hir::GenericParam<'hir>] {
887-
let mut generic_params: Vec<_> = generic_params
888-
.iter()
889-
.map(|param| {
890-
let param = match param.kind {
891-
GenericParamKind::Type { ref default } if let Some(ty) = default => {
892-
// Default type is not permitted in non-lifetime binders.
893-
// So we emit an error and default to `None` to prevent
894-
// potential ice.
895-
self.dcx().emit_err(errors::UnexpectedDefaultParameterInBinder {
896-
span: ty.span(),
897-
});
898-
let param = GenericParam {
899-
kind: GenericParamKind::Type { default: None },
900-
..param.clone()
901-
};
902-
Cow::Owned(param)
903-
}
904-
_ => Cow::Borrowed(param),
905-
};
906-
self.lower_generic_param(param.as_ref(), hir::GenericParamSource::Binder)
907-
})
886+
let mut generic_params: Vec<_> = self
887+
.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
908888
.collect();
909889
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
910890
debug!(?extra_lifetimes);
@@ -2136,7 +2116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21362116
param: &GenericParam,
21372117
source: hir::GenericParamSource,
21382118
) -> hir::GenericParam<'hir> {
2139-
let (name, kind) = self.lower_generic_param_kind(param);
2119+
let (name, kind) = self.lower_generic_param_kind(param, source);
21402120

21412121
let hir_id = self.lower_node_id(param.id);
21422122
self.lower_attrs(hir_id, &param.attrs);
@@ -2155,6 +2135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21552135
fn lower_generic_param_kind(
21562136
&mut self,
21572137
param: &GenericParam,
2138+
source: hir::GenericParamSource,
21582139
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
21592140
match &param.kind {
21602141
GenericParamKind::Lifetime => {
@@ -2173,22 +2154,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21732154
(param_name, kind)
21742155
}
21752156
GenericParamKind::Type { default, .. } => {
2176-
let kind = hir::GenericParamKind::Type {
2177-
default: default.as_ref().map(|x| {
2157+
// Not only do we deny type param defaults in binders but we also map them to `None`
2158+
// since later compiler stages cannot handle them (and shouldn't need to be able to).
2159+
let default = default
2160+
.as_ref()
2161+
.filter(|_| match source {
2162+
hir::GenericParamSource::Generics => true,
2163+
hir::GenericParamSource::Binder => {
2164+
self.dcx().emit_err(errors::HigherRankedGenParamWithDefault {
2165+
span: param.span(),
2166+
});
2167+
2168+
false
2169+
}
2170+
})
2171+
.map(|def| {
21782172
self.lower_ty(
2179-
x,
2173+
def,
21802174
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
21812175
)
2182-
}),
2183-
synthetic: false,
2184-
};
2176+
});
2177+
2178+
let kind = hir::GenericParamKind::Type { default, synthetic: false };
21852179

21862180
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
21872181
}
21882182
GenericParamKind::Const { ty, kw_span: _, default } => {
21892183
let ty = self
21902184
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
2191-
let default = default.as_ref().map(|def| self.lower_anon_const(def));
2185+
2186+
// Not only do we deny const param defaults in binders but we also map them to `None`
2187+
// since later compiler stages cannot handle them (and shouldn't need to be able to).
2188+
let default = default
2189+
.as_ref()
2190+
.filter(|_| match source {
2191+
hir::GenericParamSource::Generics => true,
2192+
hir::GenericParamSource::Binder => {
2193+
self.dcx().emit_err(errors::HigherRankedGenParamWithDefault {
2194+
span: param.span(),
2195+
});
2196+
2197+
false
2198+
}
2199+
})
2200+
.map(|def| self.lower_anon_const(def));
2201+
21922202
(
21932203
hir::ParamName::Plain(self.lower_ident(param.ident)),
21942204
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Check that defaults for generic parameters in `for<...>` binders are
2+
// syntactically valid. See also PR #119042.
3+
4+
// check-pass
5+
6+
macro_rules! a { ($ty:ty) => {} }
7+
8+
a! { for<T = &i32> fn() }
9+
10+
fn main() {}

tests/ui/parser/issue-119042.rs

-7
This file was deleted.

tests/ui/traits/non_lifetime_binders/issue-118697.rs tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![feature(non_lifetime_binders)]
33

44
type T = dyn for<V = A(&())> Fn(());
5-
//~^ ERROR default parameter is not allowed in this binder
5+
//~^ ERROR higher-ranked generic parameters may not have defaults
66
//~| ERROR cannot find type `A` in this scope
77
//~| ERROR late-bound type parameter not allowed on trait object types
88

tests/ui/traits/non_lifetime_binders/issue-118697.stderr tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
error[E0412]: cannot find type `A` in this scope
2-
--> $DIR/issue-118697.rs:4:22
2+
--> $DIR/binder-defaults-118697.rs:4:22
33
|
44
LL | type T = dyn for<V = A(&())> Fn(());
55
| ^ not found in this scope
66

7-
error: default parameter is not allowed in this binder
8-
--> $DIR/issue-118697.rs:4:22
7+
error: higher-ranked generic parameters may not have defaults
8+
--> $DIR/binder-defaults-118697.rs:4:18
99
|
1010
LL | type T = dyn for<V = A(&())> Fn(());
11-
| ^^^^^^
11+
| ^^^^^^^^^^
1212

1313
error: late-bound type parameter not allowed on trait object types
14-
--> $DIR/issue-118697.rs:4:18
14+
--> $DIR/binder-defaults-118697.rs:4:18
1515
|
1616
LL | type T = dyn for<V = A(&())> Fn(());
17-
| ^
17+
| ^^^^^^^^^^
1818

1919
error: aborting due to 3 previous errors
2020

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(non_lifetime_binders, generic_const_exprs)]
2+
//~^ WARN the feature `non_lifetime_binders` is incomplete
3+
//~| WARN the feature `generic_const_exprs` is incomplete
4+
5+
fn fun()
6+
where
7+
for<T = (), const N: usize = 1> ():,
8+
//~^ ERROR higher-ranked generic parameters may not have defaults
9+
//~| ERROR higher-ranked generic parameters may not have defaults
10+
{}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/binder-defaults-119489.rs:1:12
3+
|
4+
LL | #![feature(non_lifetime_binders, generic_const_exprs)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/binder-defaults-119489.rs:1:34
12+
|
13+
LL | #![feature(non_lifetime_binders, generic_const_exprs)]
14+
| ^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
17+
18+
error: higher-ranked generic parameters may not have defaults
19+
--> $DIR/binder-defaults-119489.rs:7:9
20+
|
21+
LL | for<T = (), const N: usize = 1> ():,
22+
| ^^^^^^
23+
24+
error: higher-ranked generic parameters may not have defaults
25+
--> $DIR/binder-defaults-119489.rs:7:17
26+
|
27+
LL | for<T = (), const N: usize = 1> ():,
28+
| ^^^^^^^^^^^^^^^^^^
29+
30+
error: aborting due to 2 previous errors; 2 warnings emitted
31+

0 commit comments

Comments
 (0)