Rollup merge of #144977 - fmease:fortify-param-default-checks, r=compiler-errors

Fortify generic param default checks

* Hard-reject instead of lint-reject type param defaults in generic assoc consts (GACs) (feature: `generic_const_items`).
  * In https://github.com/rust-lang/rust/pull/113522, I explicitly handled the free const item case and forgot about the assoc const one.
  * This led rustc to assume the default of emitting the deny-by-default lint `invalid_type_param_default`.
  * GCIs are unstable, thus we're not bound by backward compat
* Hard-reject instead of lint-reject type param defaults in foreign items.
  * We already hard-reject generic params on foreign items, so this isn't a breaking change.
  * There's no reason why we need to lint-reject.
* Refactor the way we determine where generic param defaults are allowed:
  * Don't default to emitting lint `invalid_type_param_defaults` for nodes that aren't explicitly handled but instead panic.
  * This would've caught my GAC oversight from above much earlier via fuzzing
  * Prevents us from accidentally stabilizing more invalid type param defaults in the future
* Streamline the phrasing of the diagnostic
This commit is contained in:
Guillaume Gomez
2025-08-06 21:29:32 +02:00
committed by GitHub
30 changed files with 298 additions and 286 deletions

View File

@@ -223,60 +223,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
"synthetic HIR should have its `generics_of` explicitly fed" "synthetic HIR should have its `generics_of` explicitly fed"
), ),
_ => span_bug!(tcx.def_span(def_id), "unhandled node {node:?}"), _ => span_bug!(tcx.def_span(def_id), "generics_of: unexpected node kind {node:?}"),
}; };
enum Defaults {
Allowed,
// See #36887
FutureCompatDisallowed,
Deny,
}
let hir_generics = node.generics().unwrap_or(hir::Generics::empty());
let (opt_self, allow_defaults) = match node {
Node::Item(item) => {
match item.kind {
ItemKind::Trait(..) | ItemKind::TraitAlias(..) => {
// Add in the self type parameter. // Add in the self type parameter.
// let opt_self = if let Node::Item(item) = node
// Something of a hack: use the node id for the trait, also as && let ItemKind::Trait(..) | ItemKind::TraitAlias(..) = item.kind
// the node id for the Self type parameter. {
let opt_self = Some(ty::GenericParamDef { // Something of a hack: We reuse the node ID of the trait for the self type parameter.
Some(ty::GenericParamDef {
index: 0, index: 0,
name: kw::SelfUpper, name: kw::SelfUpper,
def_id: def_id.to_def_id(), def_id: def_id.to_def_id(),
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
has_default: false, })
synthetic: false, } else {
}, None
});
(opt_self, Defaults::Allowed)
}
ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::Union(..) => (None, Defaults::Allowed),
ItemKind::Const(..) => (None, Defaults::Deny),
_ => (None, Defaults::FutureCompatDisallowed),
}
}
Node::OpaqueTy(..) => (None, Defaults::Allowed),
// GATs
Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
(None, Defaults::Deny)
}
Node::ImplItem(item) if matches!(item.kind, ImplItemKind::Type(..)) => {
(None, Defaults::Deny)
}
_ => (None, Defaults::FutureCompatDisallowed),
}; };
let param_default_policy = param_default_policy(node);
let hir_generics = node.generics().unwrap_or(hir::Generics::empty());
let has_self = opt_self.is_some(); let has_self = opt_self.is_some();
let mut parent_has_self = false; let mut parent_has_self = false;
let mut own_start = has_self as u32; let mut own_start = has_self as u32;
@@ -312,33 +279,46 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
prev + type_start prev + type_start
}; };
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \ own_params.extend(hir_generics.params.iter().filter_map(|param| {
`struct`, `enum`, `type`, or `trait` definitions"; const MESSAGE: &str = "defaults for generic parameters are not allowed here";
let kind = match param.kind {
own_params.extend(hir_generics.params.iter().filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => return None,
GenericParamKind::Lifetime { .. } => None, GenericParamKind::Type { default, synthetic } => {
GenericParamKind::Type { default, synthetic, .. } => {
if default.is_some() { if default.is_some() {
match allow_defaults { match param_default_policy.expect("no policy for generic param default") {
Defaults::Allowed => {} ParamDefaultPolicy::Allowed => {}
Defaults::FutureCompatDisallowed => { ParamDefaultPolicy::FutureCompatForbidden => {
tcx.node_span_lint( tcx.node_span_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT, lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id, param.hir_id,
param.span, param.span,
|lint| { |lint| {
lint.primary_message(TYPE_DEFAULT_NOT_ALLOWED); lint.primary_message(MESSAGE);
}, },
); );
} }
Defaults::Deny => { ParamDefaultPolicy::Forbidden => {
tcx.dcx().span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED); tcx.dcx().span_err(param.span, MESSAGE);
} }
} }
} }
let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }; ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }
}
GenericParamKind::Const { ty: _, default, synthetic } => {
if default.is_some() {
match param_default_policy.expect("no policy for generic param default") {
ParamDefaultPolicy::Allowed => {}
ParamDefaultPolicy::FutureCompatForbidden
| ParamDefaultPolicy::Forbidden => {
tcx.dcx().span_err(param.span, MESSAGE);
}
}
}
ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic }
}
};
Some(ty::GenericParamDef { Some(ty::GenericParamDef {
index: next_index(), index: next_index(),
name: param.name.ident().name, name: param.name.ident().name,
@@ -346,26 +326,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
pure_wrt_drop: param.pure_wrt_drop, pure_wrt_drop: param.pure_wrt_drop,
kind, kind,
}) })
}
GenericParamKind::Const { ty: _, default, synthetic } => {
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
tcx.dcx().span_err(
param.span,
"defaults for const parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions",
);
}
let index = next_index();
Some(ty::GenericParamDef {
index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic },
})
}
})); }));
// provide junk type parameter defs - the only place that // provide junk type parameter defs - the only place that
@@ -438,6 +398,48 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
} }
} }
#[derive(Clone, Copy)]
enum ParamDefaultPolicy {
Allowed,
/// Tracked in <https://github.com/rust-lang/rust/issues/36887>.
FutureCompatForbidden,
Forbidden,
}
fn param_default_policy(node: Node<'_>) -> Option<ParamDefaultPolicy> {
use rustc_hir::*;
Some(match node {
Node::Item(item) => match item.kind {
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
| ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::Union(..) => ParamDefaultPolicy::Allowed,
ItemKind::Fn { .. } | ItemKind::Impl(_) => ParamDefaultPolicy::FutureCompatForbidden,
// Re. GCI, we're not bound by backward compatibility.
ItemKind::Const(..) => ParamDefaultPolicy::Forbidden,
_ => return None,
},
Node::TraitItem(item) => match item.kind {
// Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility.
TraitItemKind::Const(..) | TraitItemKind::Type(..) => ParamDefaultPolicy::Forbidden,
TraitItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden,
},
Node::ImplItem(item) => match item.kind {
// Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility.
ImplItemKind::Const(..) | ImplItemKind::Type(..) => ParamDefaultPolicy::Forbidden,
ImplItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden,
},
// Generic params are (semantically) invalid on foreign items. Still, for maximum forward
// compatibility, let's hard-reject defaults on them.
Node::ForeignItem(_) => ParamDefaultPolicy::Forbidden,
Node::OpaqueTy(..) => ParamDefaultPolicy::Allowed,
_ => return None,
})
}
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> { fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
struct LateBoundRegionsDetector<'tcx> { struct LateBoundRegionsDetector<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@@ -1,6 +1,6 @@
struct Foo<const N: usize>; struct Foo<const N: usize>;
impl<const N: usize = 1> Foo<N> {} impl<const N: usize = 1> Foo<N> {}
//~^ ERROR defaults for const parameters are only allowed //~^ ERROR defaults for generic parameters are not allowed here
fn main() {} fn main() {}

View File

@@ -1,4 +1,4 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/default-on-impl.rs:3:6 --> $DIR/default-on-impl.rs:3:6
| |
LL | impl<const N: usize = 1> Foo<N> {} LL | impl<const N: usize = 1> Foo<N> {}

View File

@@ -1,10 +1,10 @@
#![feature(generic_const_exprs)] #![feature(generic_const_exprs)]
#![allow(incomplete_features)] #![expect(incomplete_features)]
trait Trait<T> { trait Trait<T> {
fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for generic parameters are not allowed here
//~^ ERROR: mismatched types //~^ ERROR: mismatched types
fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for generic parameters are not allowed here
} }
fn main() {} fn main() {}

View File

@@ -1,10 +1,10 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/issue-105257.rs:5:12 --> $DIR/issue-105257.rs:5:12
| |
LL | fn fnc<const N: usize = "">(&self) {} LL | fn fnc<const N: usize = "">(&self) {}
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/issue-105257.rs:7:12 --> $DIR/issue-105257.rs:7:12
| |
LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {}

View File

@@ -1,4 +1,4 @@
#![crate_type = "lib"] #![crate_type = "lib"]
fn foo<const SIZE: usize = 5usize>() {} fn foo<const SIZE: usize = 5usize>() {}
//~^ ERROR defaults for const parameters are //~^ ERROR defaults for generic parameters are not allowed here

View File

@@ -1,4 +1,4 @@
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/default_function_param.rs:3:8 --> $DIR/default_function_param.rs:3:8
| |
LL | fn foo<const SIZE: usize = 5usize>() {} LL | fn foo<const SIZE: usize = 5usize>() {}

View File

@@ -4,17 +4,17 @@
trait Trait { trait Trait {
type Assoc<T = u32>; type Assoc<T = u32>;
//~^ ERROR defaults for type parameters are only allowed //~^ ERROR defaults for generic parameters are not allowed here
} }
impl Trait for () { impl Trait for () {
type Assoc<T = u32> = u64; type Assoc<T = u32> = u64;
//~^ ERROR defaults for type parameters are only allowed //~^ ERROR defaults for generic parameters are not allowed here
} }
impl Trait for u32 { impl Trait for u32 {
type Assoc<T = u32> = T; type Assoc<T = u32> = T;
//~^ ERROR defaults for type parameters are only allowed //~^ ERROR defaults for generic parameters are not allowed here
} }
trait Other {} trait Other {}

View File

@@ -1,16 +1,16 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:6:16 --> $DIR/type-param-defaults.rs:6:16
| |
LL | type Assoc<T = u32>; LL | type Assoc<T = u32>;
| ^^^^^^^ | ^^^^^^^
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:11:16 --> $DIR/type-param-defaults.rs:11:16
| |
LL | type Assoc<T = u32> = u64; LL | type Assoc<T = u32> = u64;
| ^^^^^^^ | ^^^^^^^
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/type-param-defaults.rs:16:16 --> $DIR/type-param-defaults.rs:16:16
| |
LL | type Assoc<T = u32> = T; LL | type Assoc<T = u32> = T;

View File

@@ -7,9 +7,17 @@
// FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly. // FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly.
const NONE<T = ()>: Option<T> = None::<T>; //~ ERROR defaults for type parameters are only allowed const NONE<T = ()>: Option<T> = None::<T>;
//~^ ERROR defaults for generic parameters are not allowed here
fn main() { impl Host {
let _ = NONE; const NADA<T = ()>: Option<T> = None::<T>;
//~^ ERROR type annotations needed //~^ ERROR defaults for generic parameters are not allowed here
} }
enum Host {}
fn body0() { let _ = NONE; } //~ ERROR type annotations needed
fn body1() { let _ = Host::NADA; } //~ ERROR type annotations needed
fn main() {}

View File

@@ -1,20 +1,37 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/parameter-defaults.rs:10:12 --> $DIR/parameter-defaults.rs:10:12
| |
LL | const NONE<T = ()>: Option<T> = None::<T>; LL | const NONE<T = ()>: Option<T> = None::<T>;
| ^^^^^^ | ^^^^^^
error[E0282]: type annotations needed for `Option<_>` error: defaults for generic parameters are not allowed here
--> $DIR/parameter-defaults.rs:13:9 --> $DIR/parameter-defaults.rs:14:16
| |
LL | let _ = NONE; LL | const NADA<T = ()>: Option<T> = None::<T>;
| ^^^^^^
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:20:18
|
LL | fn body0() { let _ = NONE; }
| ^ ---- type must be known at this point | ^ ---- type must be known at this point
| |
help: consider giving this pattern a type, where the type for type parameter `T` is specified help: consider giving this pattern a type, where the type for type parameter `T` is specified
| |
LL | let _: Option<T> = NONE; LL | fn body0() { let _: Option<T> = NONE; }
| +++++++++++ | +++++++++++
error: aborting due to 2 previous errors error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:21:18
|
LL | fn body1() { let _ = Host::NADA; }
| ^ ---------- type must be known at this point
|
help: consider giving this pattern a type, where the type for type parameter `T` is specified
|
LL | fn body1() { let _: Option<T> = Host::NADA; }
| +++++++++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0282`. For more information about this error, try `rustc --explain E0282`.

View File

@@ -1,7 +1,15 @@
// Ensure that we reject generic parameters on foreign items.
extern "C" { extern "C" {
fn foo<T>(); //~ ERROR foreign items may not have type parameters fn foo<T>(); //~ ERROR foreign items may not have type parameters
// Furthermore, check that type parameter defaults lead to a *hard* error,
// not just a lint error, for maximum forward compatibility.
#[allow(invalid_type_param_default)] // Should have no effect here.
fn bar<T = ()>(); //~ ERROR foreign items may not have type parameters
//~^ ERROR defaults for generic parameters are not allowed here
} }
fn main() { fn main() {
foo::<i32>(); //~ ERROR requires unsafe unsafe { foo::<i32>() };
} }

View File

@@ -1,20 +1,25 @@
error[E0044]: foreign items may not have type parameters error[E0044]: foreign items may not have type parameters
--> $DIR/generic-extern.rs:2:5 --> $DIR/generic-extern.rs:4:5
| |
LL | fn foo<T>(); LL | fn foo<T>();
| ^^^^^^^^^^^^ can't have type parameters | ^^^^^^^^^^^^ can't have type parameters
| |
= help: replace the type parameters with concrete types like `u32` = help: replace the type parameters with concrete types like `u32`
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block error: defaults for generic parameters are not allowed here
--> $DIR/generic-extern.rs:6:5 --> $DIR/generic-extern.rs:9:12
| |
LL | foo::<i32>(); LL | fn bar<T = ()>();
| ^^^^^^^^^^^^ call to unsafe function | ^^^^^^
error[E0044]: foreign items may not have type parameters
--> $DIR/generic-extern.rs:9:5
| |
= note: consult the function's documentation for information on how to avoid undefined behavior LL | fn bar<T = ()>();
| ^^^^^^^^^^^^^^^^^ can't have type parameters
|
= help: replace the type parameters with concrete types like `u32`
error: aborting due to 2 previous errors error: aborting due to 3 previous errors
Some errors have detailed explanations: E0044, E0133. For more information about this error, try `rustc --explain E0044`.
For more information about an error, try `rustc --explain E0044`.

View File

@@ -0,0 +1,22 @@
// Ensure that we emit the deny-by-default lint `invalid_type_param_default` in locations where
// type parameter defaults were accidentally allowed but don't have any effect whatsoever.
//
// Tracked in <https://github.com/rust-lang/rust/issues/36887>.
// FIXME(default_type_parameter_fallback): Consider reallowing them once they work properly.
fn avg<T = i32>(_: T) {}
//~^ ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
// issue: <https://github.com/rust-lang/rust/issues/26812>
fn mdn<T = T::Item>(_: T) {}
//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
//~| ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
struct S<T>(T);
impl<T = i32> S<T> {}
//~^ ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARN this was previously accepted
fn main() {}

View File

@@ -0,0 +1,70 @@
error[E0128]: generic parameter defaults cannot reference parameters before they are declared
--> $DIR/invalid-type-param-default.rs:12:12
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^ cannot reference `T` before it is declared
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:7:8
|
LL | fn avg<T = i32>(_: T) {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:12:8
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:18:6
|
LL | impl<T = i32> S<T> {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0128`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:7:8
|
LL | fn avg<T = i32>(_: T) {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:12:8
|
LL | fn mdn<T = T::Item>(_: T) {}
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for generic parameters are not allowed here
--> $DIR/invalid-type-param-default.rs:18:6
|
LL | impl<T = i32> S<T> {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View File

@@ -1,7 +1,7 @@
fn mainIterator<_ = _> {} fn mainIterator<_ = _> {}
//~^ ERROR expected identifier, found reserved identifier `_` //~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR missing parameters for function definition //~| ERROR missing parameters for function definition
//~| ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions [invalid_type_param_default] //~| ERROR defaults for generic parameters are not allowed here [invalid_type_param_default]
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121] //~| ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121]

View File

@@ -15,7 +15,7 @@ help: add a parameter list
LL | fn mainIterator<_ = _>() {} LL | fn mainIterator<_ = _>() {}
| ++ | ++
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/overlapping-errors-span-issue-123861.rs:1:17 --> $DIR/overlapping-errors-span-issue-123861.rs:1:17
| |
LL | fn mainIterator<_ = _> {} LL | fn mainIterator<_ = _> {}
@@ -35,7 +35,7 @@ error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0121`. For more information about this error, try `rustc --explain E0121`.
Future incompatibility report: Future breakage diagnostic: Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/overlapping-errors-span-issue-123861.rs:1:17 --> $DIR/overlapping-errors-span-issue-123861.rs:1:17
| |
LL | fn mainIterator<_ = _> {} LL | fn mainIterator<_ = _> {}

View File

@@ -236,17 +236,15 @@ type InTypeAliasGenericParamDefault<T = impl Debug> = T;
//~^ ERROR `impl Trait` is not allowed in generic parameter defaults //~^ ERROR `impl Trait` is not allowed in generic parameter defaults
// Disallowed // Disallowed
impl <T = impl Debug> T {} #[expect(invalid_type_param_default)]
//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions impl<T = impl Debug> T {}
//~| WARNING this was previously accepted by the compiler but is being phased out //~^ ERROR `impl Trait` is not allowed in generic parameter defaults
//~| ERROR `impl Trait` is not allowed in generic parameter defaults
//~| ERROR no nominal type found //~| ERROR no nominal type found
// Disallowed // Disallowed
#[expect(invalid_type_param_default)]
fn in_method_generic_param_default<T = impl Debug>(_: T) {} fn in_method_generic_param_default<T = impl Debug>(_: T) {}
//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~^ ERROR `impl Trait` is not allowed in generic parameter defaults
//~| WARNING this was previously accepted by the compiler but is being phased out
//~| ERROR `impl Trait` is not allowed in generic parameter defaults
fn main() { fn main() {
let _in_local_variable: impl Fn() = || {}; let _in_local_variable: impl Fn() = || {};

View File

@@ -311,9 +311,9 @@ LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in generic parameter defaults error[E0562]: `impl Trait` is not allowed in generic parameter defaults
--> $DIR/where-allowed.rs:239:11 --> $DIR/where-allowed.rs:240:10
| |
LL | impl <T = impl Debug> T {} LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
@@ -327,7 +327,7 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
= note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0562]: `impl Trait` is not allowed in the type of variable bindings error[E0562]: `impl Trait` is not allowed in the type of variable bindings
--> $DIR/where-allowed.rs:252:29 --> $DIR/where-allowed.rs:250:29
| |
LL | let _in_local_variable: impl Fn() = || {}; LL | let _in_local_variable: impl Fn() = || {};
| ^^^^^^^^^ | ^^^^^^^^^
@@ -338,7 +338,7 @@ LL | let _in_local_variable: impl Fn() = || {};
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0562]: `impl Trait` is not allowed in closure return types error[E0562]: `impl Trait` is not allowed in closure return types
--> $DIR/where-allowed.rs:254:46 --> $DIR/where-allowed.rs:252:46
| |
LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; LL | let _in_return_in_local_variable = || -> impl Fn() { || {} };
| ^^^^^^^^^ | ^^^^^^^^^
@@ -368,25 +368,6 @@ LL - fn in_trait_impl_return() -> impl Debug { () }
LL + fn in_trait_impl_return() -> <() as DummyTrait>::Out { () } LL + fn in_trait_impl_return() -> <() as DummyTrait>::Out { () }
| |
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:246:36
|
LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:239:7
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error[E0283]: type annotations needed error[E0283]: type annotations needed
--> $DIR/where-allowed.rs:46:57 --> $DIR/where-allowed.rs:46:57
| |
@@ -408,10 +389,10 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized; where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
error[E0118]: no nominal type found for inherent implementation error[E0118]: no nominal type found for inherent implementation
--> $DIR/where-allowed.rs:239:1 --> $DIR/where-allowed.rs:240:1
| |
LL | impl <T = impl Debug> T {} LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type | ^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
| |
= note: either implement a trait on it or create a newtype to wrap it instead = note: either implement a trait on it or create a newtype to wrap it instead
@@ -431,29 +412,21 @@ LL | type InTypeAlias<R> = impl Debug;
| |
= note: `InTypeAlias` must be used in combination with a concrete type within the same crate = note: `InTypeAlias` must be used in combination with a concrete type within the same crate
error: aborting due to 50 previous errors error: aborting due to 48 previous errors
Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666. Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666.
For more information about an error, try `rustc --explain E0053`. For more information about an error, try `rustc --explain E0053`.
Future incompatibility report: Future breakage diagnostic: Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions warning: defaults for generic parameters are not allowed here
--> $DIR/where-allowed.rs:246:36 --> $DIR/where-allowed.rs:246:36
| |
LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions warning: defaults for generic parameters are not allowed here
--> $DIR/where-allowed.rs:239:7 --> $DIR/where-allowed.rs:240:6
| |
LL | impl <T = impl Debug> T {} LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View File

@@ -1,6 +0,0 @@
fn avg<T=T::Item>(_: T) {}
//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
//~| ERROR defaults for type parameters
//~| WARN previously accepted
fn main() {}

View File

@@ -1,30 +0,0 @@
error[E0128]: generic parameter defaults cannot reference parameters before they are declared
--> $DIR/issue-26812.rs:1:10
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^ cannot reference `T` before it is declared
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/issue-26812.rs:1:8
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0128`.
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/issue-26812.rs:1:8
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View File

@@ -14,7 +14,7 @@ fn b<const C: u8()>() {}
// Paren generic args in AnonymousReportError // Paren generic args in AnonymousReportError
fn c<T = u8()>() {} fn c<T = u8()>() {}
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| ERROR defaults for type parameters are only allowed in //~| ERROR defaults for generic parameters are not allowed here
//~| WARN this was previously accepted //~| WARN this was previously accepted
// Elided lifetime in path in ConstGeneric // Elided lifetime in path in ConstGeneric

View File

@@ -22,7 +22,7 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
LL | fn c<T = u8()>() {} LL | fn c<T = u8()>() {}
| ^^^^ only `Fn` traits may use parentheses | ^^^^ only `Fn` traits may use parentheses
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/unusual-rib-combinations.rs:15:6 --> $DIR/unusual-rib-combinations.rs:15:6
| |
LL | fn c<T = u8()>() {} LL | fn c<T = u8()>() {}
@@ -43,7 +43,7 @@ error: aborting due to 6 previous errors
Some errors have detailed explanations: E0106, E0214, E0308, E0770. Some errors have detailed explanations: E0106, E0214, E0308, E0770.
For more information about an error, try `rustc --explain E0106`. For more information about an error, try `rustc --explain E0106`.
Future incompatibility report: Future breakage diagnostic: Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/unusual-rib-combinations.rs:15:6 --> $DIR/unusual-rib-combinations.rs:15:6
| |
LL | fn c<T = u8()>() {} LL | fn c<T = u8()>() {}

View File

@@ -5,7 +5,7 @@ impl X<N> {}
//~| ERROR unresolved item provided when a constant was expected //~| ERROR unresolved item provided when a constant was expected
impl<T, const A: u8 = 2> X<N> {} impl<T, const A: u8 = 2> X<N> {}
//~^ ERROR cannot find type `N` in this scope //~^ ERROR cannot find type `N` in this scope
//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| ERROR defaults for generic parameters are not allowed here
//~| ERROR unresolved item provided when a constant was expected //~| ERROR unresolved item provided when a constant was expected
fn foo(_: T) where T: Send {} fn foo(_: T) where T: Send {}

View File

@@ -103,7 +103,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | impl X<{ N }> {} LL | impl X<{ N }> {}
| + + | + +
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/missing-type-parameter2.rs:6:9 --> $DIR/missing-type-parameter2.rs:6:9
| |
LL | impl<T, const A: u8 = 2> X<N> {} LL | impl<T, const A: u8 = 2> X<N> {}

View File

@@ -13,7 +13,7 @@ error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`. For more information about this error, try `rustc --explain E0282`.
Future incompatibility report: Future breakage diagnostic: Future incompatibility report: Future breakage diagnostic:
warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions warning: defaults for generic parameters are not allowed here
--> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11 --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11
| |
LL | fn foo<T, U = u64>() -> (T, U) { LL | fn foo<T, U = u64>() -> (T, U) {

View File

@@ -1,12 +0,0 @@
#![allow(unused)]
fn avg<T=i32>(_: T) {}
//~^ ERROR defaults for type parameters are only allowed
//~| WARN this was previously accepted
struct S<T>(T);
impl<T=i32> S<T> {}
//~^ ERROR defaults for type parameters are only allowed
//~| WARN this was previously accepted
fn main() {}

View File

@@ -1,43 +0,0 @@
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
|
LL | fn avg<T=i32>(_: T) {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
|
LL | impl<T=i32> S<T> {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error: aborting due to 2 previous errors
Future incompatibility report: Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
|
LL | fn avg<T=i32>(_: T) {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default
Future breakage diagnostic:
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
|
LL | impl<T=i32> S<T> {}
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
= note: `#[deny(invalid_type_param_default)]` on by default

View File

@@ -4,7 +4,7 @@ trait Trait<const N: dyn Trait = bar> {
fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait { fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait {
//~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters
//~| ERROR expected value, found builtin type `u32` //~| ERROR expected value, found builtin type `u32`
//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| ERROR defaults for generic parameters are not allowed here
bar bar
//~^ ERROR cannot find value `bar` in this scope //~^ ERROR cannot find value `bar` in this scope
} }

View File

@@ -39,7 +39,7 @@ LL | trait Trait<const N: dyn Trait = bar> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions error: defaults for generic parameters are not allowed here
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:12 --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:12
| |
LL | fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait { LL | fn fnc<const N: dyn Trait = u32>(&self) -> dyn Trait {