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
This commit is contained in:
commit
e0543409d5
7 changed files with 135 additions and 13 deletions
|
@ -442,7 +442,7 @@ impl<'a> Resolver<'a> {
|
|||
);
|
||||
err
|
||||
}
|
||||
ResolutionError::ParamInTyOfConstArg(name) => {
|
||||
ResolutionError::ParamInTyOfConstParam(name) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
|
@ -455,6 +455,17 @@ 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::SelfInTyParamDefault => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
|
|
|
@ -570,7 +570,15 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
|
||||
if let Some(ref ty) = default {
|
||||
self.ribs[TypeNS].push(default_ban_rib);
|
||||
self.visit_ty(ty);
|
||||
self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| {
|
||||
// HACK: We use an empty `ForwardTyParamBanRibKind` 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();
|
||||
}
|
||||
|
||||
|
@ -1081,7 +1089,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
debug!("with_constant_rib");
|
||||
self.with_rib(ValueNS, ConstantItemRibKind, |this| {
|
||||
this.with_label_rib(ConstantItemRibKind, f);
|
||||
this.with_rib(TypeNS, ConstantItemRibKind, |this| {
|
||||
this.with_label_rib(ConstantItemRibKind, f);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,9 @@ enum ResolutionError<'a> {
|
|||
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
|
||||
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
|
||||
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
||||
ParamInTyOfConstArg(Symbol),
|
||||
ParamInTyOfConstParam(Symbol),
|
||||
/// constant values inside of type parameter defaults must not depend on generic parameters.
|
||||
ParamInAnonConstInTyDefault(Symbol),
|
||||
/// Error E0735: type parameters with a default cannot use `Self`
|
||||
SelfInTyParamDefault,
|
||||
/// Error E0767: use of unreachable label
|
||||
|
@ -2514,7 +2516,7 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
ConstParamTyRibKind => {
|
||||
if record_used {
|
||||
self.report_error(span, ParamInTyOfConstArg(rib_ident.name));
|
||||
self.report_error(span, ParamInTyOfConstParam(rib_ident.name));
|
||||
}
|
||||
return Res::Err;
|
||||
}
|
||||
|
@ -2526,18 +2528,40 @@ 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 {
|
||||
NormalRibKind
|
||||
| ClosureOrAsyncRibKind
|
||||
| AssocItemRibKind
|
||||
| ModuleRibKind(..)
|
||||
| MacroDefinition(..)
|
||||
| ForwardTyParamBanRibKind
|
||||
| ConstantItemRibKind => {
|
||||
| MacroDefinition(..) => {
|
||||
// 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>()]>`
|
||||
ForwardTyParamBanRibKind => {
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
ConstantItemRibKind => {
|
||||
if in_ty_param_default {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInAnonConstInTyDefault(
|
||||
rib_ident.name,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// This was an attempt to use a type parameter outside its scope.
|
||||
ItemRibKind(has_generic_params) => has_generic_params,
|
||||
FnItemRibKind => HasGenericParams::Yes,
|
||||
|
@ -2545,7 +2569,7 @@ impl<'a> Resolver<'a> {
|
|||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
|
||||
ResolutionError::ParamInTyOfConstParam(rib_ident.name),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
@ -2572,22 +2596,45 @@ impl<'a> Resolver<'a> {
|
|||
// (spuriously) conflicting with the const param.
|
||||
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(..)
|
||||
| ForwardTyParamBanRibKind
|
||||
| ConstantItemRibKind => continue,
|
||||
| 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>()]>`
|
||||
ForwardTyParamBanRibKind => {
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
ConstantItemRibKind => {
|
||||
if in_ty_param_default {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInAnonConstInTyDefault(
|
||||
rib_ident.name,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ItemRibKind(has_generic_params) => has_generic_params,
|
||||
FnItemRibKind => HasGenericParams::Yes,
|
||||
ConstParamTyRibKind => {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
|
||||
ResolutionError::ParamInTyOfConstParam(rib_ident.name),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
|
||||
|
||||
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
|
||||
//~^ ERROR constant values inside of type parameter defaults
|
||||
|
||||
// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
|
||||
struct Bar<T = [u8; N], const N: usize>(T);
|
||||
//~^ ERROR constant values inside of type parameter defaults
|
||||
//~| ERROR type parameters with a default
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,31 @@
|
|||
error: type parameters with a default must be trailing
|
||||
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:12
|
||||
|
|
||||
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
|
||||
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:3: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:7:21
|
||||
|
|
||||
LL | struct Bar<T = [u8; N], const N: usize>(T);
|
||||
| ^ the anonymous constant must not depend on the parameter `N`
|
||||
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
4
src/test/ui/generic/param-in-ct-in-ty-param-default.rs
Normal file
4
src/test/ui/generic/param-in-ct-in-ty-param-default.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
|
||||
//~^ ERROR constant values inside of type parameter defaults
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,8 @@
|
|||
error: constant values inside of type parameter defaults must not depend on generic parameters
|
||||
--> $DIR/param-in-ct-in-ty-param-default.rs:1: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: aborting due to previous error
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue