Skip to content

Commit e054340

Browse files
authored
Rollup merge of #74487 - lcnr:const-in-ty-default, r=varkor
Forbid generic parameters in anon consts inside of type defaults Emit a resolution error for `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`. We are unable to support this with the way `ty::Generics` is currently used, so let's just forbid it entirely for now. Fixes some ICE on stable, e.g. ```rust struct Foo<T, U = [u8; std::mem::size_of::<*mut T>()]>(T, U); ``` r? @varkor @eddyb
2 parents 7864c3f + 952fd0c commit e054340

7 files changed

+135
-13
lines changed

src/librustc_resolve/diagnostics.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ impl<'a> Resolver<'a> {
442442
);
443443
err
444444
}
445-
ResolutionError::ParamInTyOfConstArg(name) => {
445+
ResolutionError::ParamInTyOfConstParam(name) => {
446446
let mut err = struct_span_err!(
447447
self.session,
448448
span,
@@ -455,6 +455,17 @@ impl<'a> Resolver<'a> {
455455
);
456456
err
457457
}
458+
ResolutionError::ParamInAnonConstInTyDefault(name) => {
459+
let mut err = self.session.struct_span_err(
460+
span,
461+
"constant values inside of type parameter defaults must not depend on generic parameters",
462+
);
463+
err.span_label(
464+
span,
465+
format!("the anonymous constant must not depend on the parameter `{}`", name),
466+
);
467+
err
468+
}
458469
ResolutionError::SelfInTyParamDefault => {
459470
let mut err = struct_span_err!(
460471
self.session,

src/librustc_resolve/late.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,15 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
570570

571571
if let Some(ref ty) = default {
572572
self.ribs[TypeNS].push(default_ban_rib);
573-
self.visit_ty(ty);
573+
self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| {
574+
// HACK: We use an empty `ForwardTyParamBanRibKind` here which
575+
// is only used to forbid the use of const parameters inside of
576+
// type defaults.
577+
//
578+
// While the rib name doesn't really fit here, it does allow us to use the same
579+
// code for both const and type parameters.
580+
this.visit_ty(ty);
581+
});
574582
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
575583
}
576584

@@ -1081,7 +1089,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
10811089
fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
10821090
debug!("with_constant_rib");
10831091
self.with_rib(ValueNS, ConstantItemRibKind, |this| {
1084-
this.with_label_rib(ConstantItemRibKind, f);
1092+
this.with_rib(TypeNS, ConstantItemRibKind, |this| {
1093+
this.with_label_rib(ConstantItemRibKind, f);
1094+
})
10851095
});
10861096
}
10871097

src/librustc_resolve/lib.rs

+57-10
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ enum ResolutionError<'a> {
215215
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
216216
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
217217
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
218-
ParamInTyOfConstArg(Symbol),
218+
ParamInTyOfConstParam(Symbol),
219+
/// constant values inside of type parameter defaults must not depend on generic parameters.
220+
ParamInAnonConstInTyDefault(Symbol),
219221
/// Error E0735: type parameters with a default cannot use `Self`
220222
SelfInTyParamDefault,
221223
/// Error E0767: use of unreachable label
@@ -2514,7 +2516,7 @@ impl<'a> Resolver<'a> {
25142516
}
25152517
ConstParamTyRibKind => {
25162518
if record_used {
2517-
self.report_error(span, ParamInTyOfConstArg(rib_ident.name));
2519+
self.report_error(span, ParamInTyOfConstParam(rib_ident.name));
25182520
}
25192521
return Res::Err;
25202522
}
@@ -2526,26 +2528,48 @@ impl<'a> Resolver<'a> {
25262528
}
25272529
}
25282530
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
2531+
let mut in_ty_param_default = false;
25292532
for rib in ribs {
25302533
let has_generic_params = match rib.kind {
25312534
NormalRibKind
25322535
| ClosureOrAsyncRibKind
25332536
| AssocItemRibKind
25342537
| ModuleRibKind(..)
2535-
| MacroDefinition(..)
2536-
| ForwardTyParamBanRibKind
2537-
| ConstantItemRibKind => {
2538+
| MacroDefinition(..) => {
25382539
// Nothing to do. Continue.
25392540
continue;
25402541
}
2542+
2543+
// We only forbid constant items if we are inside of type defaults,
2544+
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
2545+
ForwardTyParamBanRibKind => {
2546+
in_ty_param_default = true;
2547+
continue;
2548+
}
2549+
ConstantItemRibKind => {
2550+
if in_ty_param_default {
2551+
if record_used {
2552+
self.report_error(
2553+
span,
2554+
ResolutionError::ParamInAnonConstInTyDefault(
2555+
rib_ident.name,
2556+
),
2557+
);
2558+
}
2559+
return Res::Err;
2560+
} else {
2561+
continue;
2562+
}
2563+
}
2564+
25412565
// This was an attempt to use a type parameter outside its scope.
25422566
ItemRibKind(has_generic_params) => has_generic_params,
25432567
FnItemRibKind => HasGenericParams::Yes,
25442568
ConstParamTyRibKind => {
25452569
if record_used {
25462570
self.report_error(
25472571
span,
2548-
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
2572+
ResolutionError::ParamInTyOfConstParam(rib_ident.name),
25492573
);
25502574
}
25512575
return Res::Err;
@@ -2572,22 +2596,45 @@ impl<'a> Resolver<'a> {
25722596
// (spuriously) conflicting with the const param.
25732597
ribs.next();
25742598
}
2599+
2600+
let mut in_ty_param_default = false;
25752601
for rib in ribs {
25762602
let has_generic_params = match rib.kind {
25772603
NormalRibKind
25782604
| ClosureOrAsyncRibKind
25792605
| AssocItemRibKind
25802606
| ModuleRibKind(..)
2581-
| MacroDefinition(..)
2582-
| ForwardTyParamBanRibKind
2583-
| ConstantItemRibKind => continue,
2607+
| MacroDefinition(..) => continue,
2608+
2609+
// We only forbid constant items if we are inside of type defaults,
2610+
// for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
2611+
ForwardTyParamBanRibKind => {
2612+
in_ty_param_default = true;
2613+
continue;
2614+
}
2615+
ConstantItemRibKind => {
2616+
if in_ty_param_default {
2617+
if record_used {
2618+
self.report_error(
2619+
span,
2620+
ResolutionError::ParamInAnonConstInTyDefault(
2621+
rib_ident.name,
2622+
),
2623+
);
2624+
}
2625+
return Res::Err;
2626+
} else {
2627+
continue;
2628+
}
2629+
}
2630+
25842631
ItemRibKind(has_generic_params) => has_generic_params,
25852632
FnItemRibKind => HasGenericParams::Yes,
25862633
ConstParamTyRibKind => {
25872634
if record_used {
25882635
self.report_error(
25892636
span,
2590-
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
2637+
ResolutionError::ParamInTyOfConstParam(rib_ident.name),
25912638
);
25922639
}
25932640
return Res::Err;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
2+
3+
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
4+
//~^ ERROR constant values inside of type parameter defaults
5+
6+
// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
7+
struct Bar<T = [u8; N], const N: usize>(T);
8+
//~^ ERROR constant values inside of type parameter defaults
9+
//~| ERROR type parameters with a default
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: type parameters with a default must be trailing
2+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:12
3+
|
4+
LL | struct Bar<T = [u8; N], const N: usize>(T);
5+
| ^
6+
|
7+
= note: using type defaults and const parameters in the same parameter list is currently not permitted
8+
9+
error: constant values inside of type parameter defaults must not depend on generic parameters
10+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:3:44
11+
|
12+
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:7:21
17+
|
18+
LL | struct Bar<T = [u8; N], const N: usize>(T);
19+
| ^ the anonymous constant must not depend on the parameter `N`
20+
21+
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
22+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:1:12
23+
|
24+
LL | #![feature(const_generics)]
25+
| ^^^^^^^^^^^^^^
26+
|
27+
= note: `#[warn(incomplete_features)]` on by default
28+
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
29+
30+
error: aborting due to 3 previous errors; 1 warning emitted
31+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
2+
//~^ ERROR constant values inside of type parameter defaults
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: constant values inside of type parameter defaults must not depend on generic parameters
2+
--> $DIR/param-in-ct-in-ty-param-default.rs:1:44
3+
|
4+
LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
5+
| ^ the anonymous constant must not depend on the parameter `T`
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)