From fa0428c9d0f336cf51748621543679736f04cce6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 19 Apr 2024 15:18:00 -0400 Subject: [PATCH 1/2] Flip spans for precise capturing syntax not capturing a ty/ct param --- .../rustc_hir_analysis/src/check/check.rs | 29 ++++++++++++------- .../src/errors/precise_captures.rs | 6 ++-- .../precise-capturing/capture-parent-arg.rs | 2 +- .../capture-parent-arg.stderr | 7 ++--- .../forgot-to-capture-const.stderr | 6 ++-- .../forgot-to-capture-type.rs | 2 +- .../forgot-to-capture-type.stderr | 13 +++++---- 7 files changed, 37 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 36553591de8..8dfbcbfd76f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -580,10 +580,11 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe match param.kind { ty::GenericParamDefKind::Lifetime => { + let use_span = tcx.def_span(param.def_id); + let opaque_span = tcx.def_span(opaque_def_id); // Check if the lifetime param was captured but isn't named in the precise captures list. if variances[param.index as usize] == ty::Invariant { - let param_span = if let DefKind::OpaqueTy = - tcx.def_kind(tcx.parent(param.def_id)) + if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id)) && let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) | ty::ReLateParam(ty::LateParamRegion { bound_region: ty::BoundRegionKind::BrNamed(def_id, _), @@ -591,16 +592,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe }) = *tcx .map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()) { - Some(tcx.def_span(def_id)) + tcx.dcx().emit_err(errors::LifetimeNotCaptured { + opaque_span, + use_span, + param_span: tcx.def_span(def_id), + }); } else { - None - }; - // FIXME(precise_capturing): Structured suggestion for this would be useful - tcx.dcx().emit_err(errors::LifetimeNotCaptured { - use_span: tcx.def_span(param.def_id), - param_span, - opaque_span: tcx.def_span(opaque_def_id), - }); + // If the `use_span` is actually just the param itself, then we must + // have not duplicated the lifetime but captured the original. + // The "effective" `use_span` will be the span of the opaque itself, + // and the param span will be the def span of the param. + tcx.dcx().emit_err(errors::LifetimeNotCaptured { + opaque_span, + use_span: opaque_span, + param_span: use_span, + }); + } continue; } } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index 520bf1d9f40..d1b2205dd9a 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -6,9 +6,9 @@ #[note] pub struct ParamNotCaptured { #[primary_span] - pub param_span: Span, - #[label] pub opaque_span: Span, + #[label] + pub param_span: Span, pub kind: &'static str, } @@ -18,7 +18,7 @@ pub struct LifetimeNotCaptured { #[primary_span] pub use_span: Span, #[label(hir_analysis_param_label)] - pub param_span: Option, + pub param_span: Span, #[label] pub opaque_span: Span, } diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs index f880bb038d5..35b28d0e6fb 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs @@ -31,8 +31,8 @@ fn bad1() -> impl use<> Into< as Tr>::Assoc> {} // But also make sure that we error here... impl<'a> W<'a> { -//~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list fn bad2() -> impl use<> Into<::Assoc> {} + //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr index 85790d57163..13aaa999707 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr @@ -16,13 +16,12 @@ LL | fn bad1() -> impl use<> Into< as Tr>::Assoc> {} | -------------------^^---------------- lifetime captured due to being mentioned in the bounds of the `impl Trait` error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/capture-parent-arg.rs:33:6 + --> $DIR/capture-parent-arg.rs:34:18 | LL | impl<'a> W<'a> { - | ^^ -LL | + | -- this lifetime parameter is captured LL | fn bad2() -> impl use<> Into<::Assoc> {} - | ------------------------------------ lifetime captured due to being mentioned in the bounds of the `impl Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr index 9c99f2b711e..8eeedc4db44 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr @@ -8,10 +8,12 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `impl Trait` must mention all const parameters in scope - --> $DIR/forgot-to-capture-const.rs:4:13 + --> $DIR/forgot-to-capture-const.rs:4:34 | LL | fn constant() -> impl use<> Sized {} - | ^^^^^^^^^^^^^^ ---------------- const parameter is implicitly captured by this `impl Trait` + | -------------- ^^^^^^^^^^^^^^^^ + | | + | const parameter is implicitly captured by this `impl Trait` | = note: currently, all const parameters are required to be mentioned in the precise captures list diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 6eaff01183d..4c04d177b06 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -5,8 +5,8 @@ fn type_param() -> impl use<> Sized {} //~^ ERROR `impl Trait` must mention all type parameters in scope trait Foo { -//~^ ERROR `impl Trait` must mention all type parameters in scope fn bar() -> impl use<> Sized; + //~^ ERROR `impl Trait` must mention all type parameters in scope } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index a8eb4547dcd..8cd873ea46d 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -8,21 +8,22 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `impl Trait` must mention all type parameters in scope - --> $DIR/forgot-to-capture-type.rs:4:15 + --> $DIR/forgot-to-capture-type.rs:4:23 | LL | fn type_param() -> impl use<> Sized {} - | ^ ---------------- type parameter is implicitly captured by this `impl Trait` + | - ^^^^^^^^^^^^^^^^ + | | + | type parameter is implicitly captured by this `impl Trait` | = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention all type parameters in scope - --> $DIR/forgot-to-capture-type.rs:7:1 + --> $DIR/forgot-to-capture-type.rs:8:17 | LL | trait Foo { - | ^^^^^^^^^ -LL | + | --------- type parameter is implicitly captured by this `impl Trait` LL | fn bar() -> impl use<> Sized; - | ---------------- type parameter is implicitly captured by this `impl Trait` + | ^^^^^^^^^^^^^^^^ | = note: currently, all type parameters are required to be mentioned in the precise captures list From 57085a06d9279173aac3d45a1a56c728047f45a3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 20 Apr 2024 11:39:43 -0400 Subject: [PATCH 2/2] Explicitly mention `Self` --- compiler/rustc_hir_analysis/messages.ftl | 6 +++++- .../rustc_hir_analysis/src/check/check.rs | 20 +++++++++++++------ .../src/errors/precise_captures.rs | 10 ++++++++++ .../forgot-to-capture-const.stderr | 2 +- .../forgot-to-capture-type.rs | 2 +- .../forgot-to-capture-type.stderr | 6 +++--- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 0ff78ebff99..06b5ee299b8 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -351,7 +351,7 @@ hir_analysis_param_in_ty_of_assoc_const_binding = *[normal] the {$param_def_kind} `{$param_name}` is defined here } -hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope +hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope in `use<...>` .label = {$kind} parameter is implicitly captured by this `impl Trait` .note = currently, all {$kind} parameters are required to be mentioned in the precise captures list @@ -405,6 +405,10 @@ hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type +hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>` + .label = `Self` type parameter is implicitly captured by this `impl Trait` + .note = currently, all type parameters are required to be mentioned in the precise captures list + hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code .help = add `#![feature(simd_ffi)]` to the crate attributes to enable diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8dfbcbfd76f..a43a67d50d8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -612,12 +612,20 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe } } ty::GenericParamDefKind::Type { .. } => { - // FIXME(precise_capturing): Structured suggestion for this would be useful - tcx.dcx().emit_err(errors::ParamNotCaptured { - param_span: tcx.def_span(param.def_id), - opaque_span: tcx.def_span(opaque_def_id), - kind: "type", - }); + if matches!(tcx.def_kind(param.def_id), DefKind::Trait | DefKind::TraitAlias) { + // FIXME(precise_capturing): Structured suggestion for this would be useful + tcx.dcx().emit_err(errors::SelfTyNotCaptured { + trait_span: tcx.def_span(param.def_id), + opaque_span: tcx.def_span(opaque_def_id), + }); + } else { + // FIXME(precise_capturing): Structured suggestion for this would be useful + tcx.dcx().emit_err(errors::ParamNotCaptured { + param_span: tcx.def_span(param.def_id), + opaque_span: tcx.def_span(opaque_def_id), + kind: "type", + }); + } } ty::GenericParamDefKind::Const { .. } => { // FIXME(precise_capturing): Structured suggestion for this would be useful diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index d1b2205dd9a..8a9b5fe6369 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -12,6 +12,16 @@ pub struct ParamNotCaptured { pub kind: &'static str, } +#[derive(Diagnostic)] +#[diag(hir_analysis_self_ty_not_captured)] +#[note] +pub struct SelfTyNotCaptured { + #[primary_span] + pub opaque_span: Span, + #[label] + pub trait_span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_lifetime_not_captured)] pub struct LifetimeNotCaptured { diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr index 8eeedc4db44..3f78e7c56b6 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr @@ -7,7 +7,7 @@ LL | #![feature(precise_capturing)] = note: see issue #123432 for more information = note: `#[warn(incomplete_features)]` on by default -error: `impl Trait` must mention all const parameters in scope +error: `impl Trait` must mention all const parameters in scope in `use<...>` --> $DIR/forgot-to-capture-const.rs:4:34 | LL | fn constant() -> impl use<> Sized {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 4c04d177b06..d359ea5e26d 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -6,7 +6,7 @@ fn type_param() -> impl use<> Sized {} trait Foo { fn bar() -> impl use<> Sized; - //~^ ERROR `impl Trait` must mention all type parameters in scope + //~^ ERROR `impl Trait` must mention the `Self` type of the trait } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 8cd873ea46d..26994d0bdbf 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -7,7 +7,7 @@ LL | #![feature(precise_capturing)] = note: see issue #123432 for more information = note: `#[warn(incomplete_features)]` on by default -error: `impl Trait` must mention all type parameters in scope +error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:4:23 | LL | fn type_param() -> impl use<> Sized {} @@ -17,11 +17,11 @@ LL | fn type_param() -> impl use<> Sized {} | = note: currently, all type parameters are required to be mentioned in the precise captures list -error: `impl Trait` must mention all type parameters in scope +error: `impl Trait` must mention the `Self` type of the trait in `use<...>` --> $DIR/forgot-to-capture-type.rs:8:17 | LL | trait Foo { - | --------- type parameter is implicitly captured by this `impl Trait` + | --------- `Self` type parameter is implicitly captured by this `impl Trait` LL | fn bar() -> impl use<> Sized; | ^^^^^^^^^^^^^^^^ |