From cfca91db06d80616af0b5af22e40d1e76e1793c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Mar 2025 05:09:46 +0000 Subject: [PATCH] Don't lower anon const for default field value with type that references params --- .../rustc_hir_analysis/src/collect/type_of.rs | 23 +++++++++++++++---- .../do-not-ice-on-invalid-lifetime.rs | 7 ++++-- .../do-not-ice-on-invalid-lifetime.stderr | 15 ++++++++++-- .../field-references-param.rs | 16 +++++++++++++ .../field-references-param.stderr | 12 ++++++++++ 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 tests/ui/structs/default-field-values/field-references-param.rs create mode 100644 tests/ui/structs/default-field-values/field-references-param.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 6936544838c81..60a69372ec5c6 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -62,10 +62,25 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx return ty; } - Node::Field(&hir::FieldDef { default: Some(c), def_id: field_def_id, .. }) - if c.hir_id == hir_id => - { - tcx.type_of(field_def_id).instantiate_identity() + Node::Field(&hir::FieldDef { + default: Some(c), def_id: field_def_id, ty: hir_ty, .. + }) if c.hir_id == hir_id => { + let ty = tcx.type_of(field_def_id).instantiate_identity(); + if !ty.has_param() || tcx.features().generic_const_exprs() { + ty + } else { + let mut diag = tcx.dcx().struct_span_err( + c.span, + format!("default value for field cannot depend on generic parameters"), + ); + diag.span_label(hir_ty.span, "this field references generic parameters"); + let adt_def_id = tcx.parent(field_def_id.to_def_id()); + let adt = tcx.def_descr(adt_def_id); + diag.span_label(tcx.def_span(adt_def_id), format!("in this {adt}")); + // FIXME: We could give a feature error for GCE, but it's best not to point users + // to that feature since it's broken. + Ty::new_error(tcx, diag.emit()) + } } _ => Ty::new_error_with_message( diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs index 71d90ddd935ff..4f2b9971d9289 100644 --- a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs +++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs @@ -1,6 +1,9 @@ #![feature(default_field_values)] -struct A<'a> { //~ ERROR lifetime parameter `'a` is never used - x: Vec = Vec::new(), //~ ERROR missing lifetime specifier +struct A<'a> { + //~^ ERROR lifetime parameter `'a` is never used + x: Vec = Vec::new(), + //~^ ERROR missing lifetime specifier + //~| ERROR default value for field cannot depend on generic parameters } fn main() {} diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr index 20b9afe80cdc8..f83cb3f88b066 100644 --- a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr +++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/do-not-ice-on-invalid-lifetime.rs:3:12 + --> $DIR/do-not-ice-on-invalid-lifetime.rs:4:12 | LL | x: Vec = Vec::new(), | ^ expected named lifetime parameter @@ -9,6 +9,17 @@ help: consider using the `'a` lifetime LL | x: Vec> = Vec::new(), | ++++ +error: default value for field cannot depend on generic parameters + --> $DIR/do-not-ice-on-invalid-lifetime.rs:4:17 + | +LL | struct A<'a> { + | ------------ in this struct +LL | +LL | x: Vec = Vec::new(), + | ------ ^^^^^^^^^^ + | | + | this field references generic parameters + error[E0392]: lifetime parameter `'a` is never used --> $DIR/do-not-ice-on-invalid-lifetime.rs:2:10 | @@ -17,7 +28,7 @@ LL | struct A<'a> { | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0106, E0392. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/structs/default-field-values/field-references-param.rs b/tests/ui/structs/default-field-values/field-references-param.rs new file mode 100644 index 0000000000000..c0bb0b0df4850 --- /dev/null +++ b/tests/ui/structs/default-field-values/field-references-param.rs @@ -0,0 +1,16 @@ +// Make sure we don't ICE when a field default references a generic parameter via inference. + +#![feature(default_field_values)] + +struct W; + +impl W { + const fn new() -> Self { W } +} + +struct Z { + x: W = W::new(), + //~^ ERROR default value for field cannot depend on generic parameters +} + +fn main() {} diff --git a/tests/ui/structs/default-field-values/field-references-param.stderr b/tests/ui/structs/default-field-values/field-references-param.stderr new file mode 100644 index 0000000000000..13f0cdc3488a3 --- /dev/null +++ b/tests/ui/structs/default-field-values/field-references-param.stderr @@ -0,0 +1,12 @@ +error: default value for field cannot depend on generic parameters + --> $DIR/field-references-param.rs:12:15 + | +LL | struct Z { + | ------------------------ in this struct +LL | x: W = W::new(), + | ---- ^^^^^^^^ + | | + | this field references generic parameters + +error: aborting due to 1 previous error +