Skip to content

Commit 259a368

Browse files
committed
fix name resolution for param defaults
1 parent d7c3386 commit 259a368

15 files changed

+141
-104
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -472,17 +472,6 @@ impl<'a> Resolver<'a> {
472472
);
473473
err
474474
}
475-
ResolutionError::ParamInAnonConstInTyDefault(name) => {
476-
let mut err = self.session.struct_span_err(
477-
span,
478-
"constant values inside of type parameter defaults must not depend on generic parameters",
479-
);
480-
err.span_label(
481-
span,
482-
format!("the anonymous constant must not depend on the parameter `{}`", name),
483-
);
484-
err
485-
}
486475
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
487476
let mut err = self.session.struct_span_err(
488477
span,

compiler/rustc_resolve/src/late.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
555555
// provide previous type parameters as they're built. We
556556
// put all the parameters on the ban list and then remove
557557
// them one by one as they are processed and become available.
558-
let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
559-
let mut found_default = false;
560-
default_ban_rib.bindings.extend(generics.params.iter().filter_map(
561-
|param| match param.kind {
562-
GenericParamKind::Type { default: Some(_), .. }
563-
| GenericParamKind::Const { default: Some(_), .. } => {
564-
found_default = true;
565-
Some((Ident::with_dummy_span(param.ident.name), Res::Err))
558+
let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
559+
let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
560+
for param in generics.params.iter() {
561+
match param.kind {
562+
GenericParamKind::Type { .. } => {
563+
forward_ty_ban_rib
564+
.bindings
565+
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
566566
}
567-
_ => None,
568-
},
569-
));
567+
GenericParamKind::Const { .. } => {
568+
forward_const_ban_rib
569+
.bindings
570+
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
571+
}
572+
GenericParamKind::Lifetime => {}
573+
}
574+
}
570575

571576
// rust-lang/rust#61631: The type `Self` is essentially
572577
// another type parameter. For ADTs, we consider it
@@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
579584
// such as in the case of `trait Add<Rhs = Self>`.)
580585
if self.diagnostic_metadata.current_self_item.is_some() {
581586
// (`Some` if + only if we are in ADT's generics.)
582-
default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
587+
forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
583588
}
584589

585590
for param in &generics.params {
@@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
591596
}
592597

593598
if let Some(ref ty) = default {
594-
self.ribs[TypeNS].push(default_ban_rib);
595-
self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| {
596-
// HACK: We use an empty `ForwardGenericParamBanRibKind` here which
597-
// is only used to forbid the use of const parameters inside of
598-
// type defaults.
599-
//
600-
// While the rib name doesn't really fit here, it does allow us to use the same
601-
// code for both const and type parameters.
602-
this.visit_ty(ty);
603-
});
604-
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
599+
self.ribs[TypeNS].push(forward_ty_ban_rib);
600+
self.ribs[ValueNS].push(forward_const_ban_rib);
601+
self.visit_ty(ty);
602+
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
603+
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
605604
}
606605

607606
// Allow all following defaults to refer to this type parameter.
608-
default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
607+
forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
609608
}
610-
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
611-
// FIXME(const_generics_defaults): handle `default` value here
612-
for bound in &param.bounds {
613-
self.visit_param_bound(bound);
614-
}
609+
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
610+
// Const parameters can't have param bounds.
611+
assert!(param.bounds.is_empty());
612+
615613
self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
616614
self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
617615
self.visit_ty(ty);
618616
self.ribs[TypeNS].pop().unwrap();
619617
self.ribs[ValueNS].pop().unwrap();
618+
619+
if let Some(ref expr) = default {
620+
self.ribs[TypeNS].push(forward_ty_ban_rib);
621+
self.ribs[ValueNS].push(forward_const_ban_rib);
622+
self.visit_anon_const(expr);
623+
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
624+
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
625+
}
626+
627+
// Allow all following defaults to refer to this const parameter.
628+
forward_const_ban_rib
629+
.bindings
630+
.remove(&Ident::with_dummy_span(param.ident.name));
620631
}
621632
}
622633
}

compiler/rustc_resolve/src/lib.rs

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,6 @@ enum ResolutionError<'a> {
239239
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
240240
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
241241
ParamInTyOfConstParam(Symbol),
242-
/// constant values inside of type parameter defaults must not depend on generic parameters.
243-
ParamInAnonConstInTyDefault(Symbol),
244242
/// generic parameters must not be used inside const evaluations.
245243
///
246244
/// This error is only emitted when using `min_const_generics`.
@@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> {
26722670
}
26732671
}
26742672
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
2675-
let mut in_ty_param_default = false;
26762673
for rib in ribs {
2677-
let has_generic_params = match rib.kind {
2674+
let has_generic_params: HasGenericParams = match rib.kind {
26782675
NormalRibKind
26792676
| ClosureOrAsyncRibKind
26802677
| AssocItemRibKind
26812678
| ModuleRibKind(..)
2682-
| MacroDefinition(..) => {
2679+
| MacroDefinition(..)
2680+
| ForwardGenericParamBanRibKind => {
26832681
// Nothing to do. Continue.
26842682
continue;
26852683
}
26862684

2687-
// We only forbid constant items if we are inside of type defaults,
2688-
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
2689-
ForwardGenericParamBanRibKind => {
2690-
// FIXME(const_generic_defaults): we may need to distinguish between
2691-
// being in type parameter defaults and const parameter defaults
2692-
in_ty_param_default = true;
2693-
continue;
2694-
}
26952685
ConstantItemRibKind(trivial, _) => {
26962686
let features = self.session.features_untracked();
26972687
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> {
27202710
}
27212711
}
27222712

2723-
if in_ty_param_default {
2724-
if record_used {
2725-
self.report_error(
2726-
span,
2727-
ResolutionError::ParamInAnonConstInTyDefault(
2728-
rib_ident.name,
2729-
),
2730-
);
2731-
}
2732-
return Res::Err;
2733-
} else {
2734-
continue;
2735-
}
2713+
continue;
27362714
}
27372715

27382716
// This was an attempt to use a type parameter outside its scope.
@@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> {
27702748
ribs.next();
27712749
}
27722750

2773-
let mut in_ty_param_default = false;
27742751
for rib in ribs {
27752752
let has_generic_params = match rib.kind {
27762753
NormalRibKind
27772754
| ClosureOrAsyncRibKind
27782755
| AssocItemRibKind
27792756
| ModuleRibKind(..)
2780-
| MacroDefinition(..) => continue,
2781-
2782-
// We only forbid constant items if we are inside of type defaults,
2783-
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
2784-
ForwardGenericParamBanRibKind => {
2785-
// FIXME(const_generic_defaults): we may need to distinguish between
2786-
// being in type parameter defaults and const parameter defaults
2787-
in_ty_param_default = true;
2788-
continue;
2789-
}
2757+
| MacroDefinition(..)
2758+
| ForwardGenericParamBanRibKind => continue,
2759+
27902760
ConstantItemRibKind(trivial, _) => {
27912761
let features = self.session.features_untracked();
27922762
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> {
28082778
return Res::Err;
28092779
}
28102780

2811-
if in_ty_param_default {
2812-
if record_used {
2813-
self.report_error(
2814-
span,
2815-
ResolutionError::ParamInAnonConstInTyDefault(
2816-
rib_ident.name,
2817-
),
2818-
);
2819-
}
2820-
return Res::Err;
2821-
} else {
2822-
continue;
2823-
}
2781+
continue;
28242782
}
28252783

28262784
ItemRibKind(has_generic_params) => has_generic_params,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(const_generics, const_generics_defaults)]
2+
#![allow(incomplete_features)]
3+
4+
struct Foo<const N: usize, const M: usize = { N + 1 }>;
5+
6+
struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
7+
//~^ ERROR the size for values of type `T` cannot be known at compilation time
8+
9+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0277]: the size for values of type `T` cannot be known at compilation time
2+
--> $DIR/complex-generic-default-expr.rs:6:62
3+
|
4+
LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
5+
| - ^ doesn't have a size known at compile-time
6+
| |
7+
| this type parameter needs to be `std::marker::Sized`
8+
|
9+
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
10+
|
11+
LL | pub const fn size_of<T>() -> usize {
12+
| - required by this bound in `std::mem::size_of`
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(const_generics, const_generics_defaults)]
2+
#![allow(incomplete_features)]
3+
4+
struct Foo<const N: usize>;
5+
6+
impl<const N: usize = 1> Foo<N> {}
7+
//~^ ERROR defaults for const parameters are only allowed
8+
9+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
2+
--> $DIR/default-on-impl.rs:6:12
3+
|
4+
LL | impl<const N: usize = 1> Foo<N> {}
5+
| ^
6+
7+
error: aborting due to previous error
8+

src/test/ui/const-generics/defaults/pretty-printing-ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ trait Foo<const KIND: bool = true> {}
1010

1111
fn foo<const SIZE: usize = 5>() {}
1212

13-
struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = {FROM + LEN}>;
13+
struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>;
14+

src/test/ui/const-generics/defaults/pretty-printing-ast.stdout

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ trait Foo<const KIND : bool = true> { }
1717
fn foo<const SIZE : usize = 5>() { }
1818

1919
struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
20-
{ FROM + LEN }>;
20+
FROM>;
21+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// check-pass
2+
#![feature(const_generics, const_generics_defaults)]
3+
#![allow(incomplete_features)]
4+
5+
struct N;
6+
7+
struct Foo<const N: usize = 1, T = N>(T);
8+
9+
impl Foo {
10+
fn new() -> Self {
11+
Foo(N)
12+
}
13+
}
14+
15+
fn main() {
16+
let Foo::<1, N>(N) = Foo::new();
17+
}

src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,26 @@ LL | struct Bar<T = [u8; N], const N: usize>(T);
66
|
77
= note: using type defaults and const parameters in the same parameter list is currently not permitted
88

9-
error: constant values inside of type parameter defaults must not depend on generic parameters
9+
error[E0128]: generic parameters with a default cannot use forward declared identifiers
10+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
11+
|
12+
LL | struct Bar<T = [u8; N], const N: usize>(T);
13+
| ^ defaulted generic parameters cannot be forward declared
14+
15+
error[E0277]: the size for values of type `T` cannot be known at compilation time
1016
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
1117
|
1218
LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
13-
| ^ the anonymous constant must not depend on the parameter `T`
14-
15-
error: constant values inside of type parameter defaults must not depend on generic parameters
16-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
19+
| - ^ doesn't have a size known at compile-time
20+
| |
21+
| this type parameter needs to be `std::marker::Sized`
22+
|
23+
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
1724
|
18-
LL | struct Bar<T = [u8; N], const N: usize>(T);
19-
| ^ the anonymous constant must not depend on the parameter `N`
25+
LL | pub const fn size_of<T>() -> usize {
26+
| - required by this bound in `std::mem::size_of`
2027

2128
error: aborting due to 3 previous errors
2229

30+
Some errors have detailed explanations: E0128, E0277.
31+
For more information about an error, try `rustc --explain E0128`.

src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
1515
= note: type parameters may not be used in const expressions
1616
= help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
1717

18-
error: constant values inside of type parameter defaults must not depend on generic parameters
18+
error[E0128]: generic parameters with a default cannot use forward declared identifiers
1919
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
2020
|
2121
LL | struct Bar<T = [u8; N], const N: usize>(T);
22-
| ^ the anonymous constant must not depend on the parameter `N`
22+
| ^ defaulted generic parameters cannot be forward declared
2323

2424
error: aborting due to 3 previous errors
2525

26+
For more information about this error, try `rustc --explain E0128`.

src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
#![cfg_attr(full, allow(incomplete_features))]
55

66
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
7-
//[full]~^ ERROR constant values inside of type parameter defaults
7+
//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time
88
//[min]~^^ ERROR generic parameters may not be used in const operations
99

1010
// FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
1111
struct Bar<T = [u8; N], const N: usize>(T);
12-
//~^ ERROR constant values inside of type parameter defaults
12+
//~^ ERROR generic parameters with a default cannot use forward declared identifiers
1313
//~| ERROR generic parameters with a default
1414

1515
fn main() {}

src/test/ui/generics/generic-non-trailing-defaults.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ struct Vec<A = Heap, T>(A, T);
55

66
struct Foo<A, B = Vec<C>, C>(A, B, C);
77
//~^ ERROR generic parameters with a default must be trailing
8+
//~| ERROR generic parameters with a default cannot use
89

910
fn main() {}

src/test/ui/generics/generic-non-trailing-defaults.stderr

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing
1010
LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
1111
| ^
1212

13-
error: aborting due to 2 previous errors
13+
error[E0128]: generic parameters with a default cannot use forward declared identifiers
14+
--> $DIR/generic-non-trailing-defaults.rs:6:23
15+
|
16+
LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
17+
| ^ defaulted generic parameters cannot be forward declared
18+
19+
error: aborting due to 3 previous errors
1420

21+
For more information about this error, try `rustc --explain E0128`.

0 commit comments

Comments
 (0)