From 02d7317af218343818dcb107cda80750e9604a3a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 4 Apr 2024 14:46:26 -0400 Subject: [PATCH] Add hir::Node::PreciseCapturingNonLifetimeArg --- compiler/rustc_ast_lowering/src/index.rs | 17 ++++++++++ compiler/rustc_ast_lowering/src/lib.rs | 8 +++-- compiler/rustc_hir/src/hir.rs | 11 ++++++- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 4 ++- .../src/collect/resolve_bound_vars.rs | 4 +-- compiler/rustc_hir_pretty/src/lib.rs | 1 + compiler/rustc_middle/src/hir/map/mod.rs | 2 ++ .../forgot-to-capture-lifetime.rs | 7 ++-- .../forgot-to-capture-lifetime.stderr | 28 ++++++++++++---- .../forgot-to-capture-type.rs | 10 +++--- .../forgot-to-capture-type.stderr | 33 ++++++++----------- .../precise-capturing/self-capture.rs | 10 ++++++ .../precise-capturing/self-capture.stderr | 11 +++++++ 14 files changed, 110 insertions(+), 38 deletions(-) create mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.rs create mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 4c552289a81..93be9b9b8cf 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -385,4 +385,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) { self.visit_pat(p) } + + fn visit_precise_capturing_arg( + &mut self, + arg: &'hir PreciseCapturingArg<'hir>, + ) -> Self::Result { + match arg { + PreciseCapturingArg::Lifetime(_) => { + // This is represented as a `Node::Lifetime`, intravisit will get to it below. + } + PreciseCapturingArg::Param(param) => self.insert( + param.ident.span, + param.hir_id, + Node::PreciseCapturingNonLifetimeArg(param), + ), + } + intravisit::walk_precise_capturing_arg(self, arg); + } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b586d2a1bf5..84776f920c4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1790,11 +1790,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { PreciseCapturingArg::Lifetime(lt) => { hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt)) } - PreciseCapturingArg::Arg(_, node_id) => { + PreciseCapturingArg::Arg(ident, node_id) => { let res = self.resolver.get_partial_res(*node_id).map_or(Res::Err, |partial_res| { partial_res.full_res().expect("no partial res expected for precise capture arg") }); - hir::PreciseCapturingArg::Param(self.lower_res(res), self.lower_node_id(*node_id)) + hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg { + hir_id: self.lower_node_id(*node_id), + ident: self.lower_ident(*ident), + res: self.lower_res(res), + }) } })) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index dc76deb1815..00b1ea061cc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2565,7 +2565,14 @@ pub struct OpaqueTy<'hir> { pub enum PreciseCapturingArg<'hir> { Lifetime(&'hir Lifetime), /// Non-lifetime argument (type or const) - Param(Res, HirId), + Param(PreciseCapturingNonLifetimeArg), +} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct PreciseCapturingNonLifetimeArg { + pub hir_id: HirId, + pub ident: Ident, + pub res: Res, } /// From whence the opaque type came. @@ -3544,6 +3551,7 @@ pub enum Node<'hir> { WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), // FIXME: Merge into `Node::Infer`. ArrayLenInfer(&'hir InferArg), + PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, // Span by reference to minimize `Node`'s size @@ -3580,6 +3588,7 @@ impl<'hir> Node<'hir> { Node::TypeBinding(b) => Some(b.ident), Node::PatField(f) => Some(f.ident), Node::ExprField(f) => Some(f.ident), + Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), Node::Param(..) | Node::AnonConst(..) | Node::ConstBlock(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index d3ede3a904f..cd9f9ff9109 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1151,7 +1151,7 @@ pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>( ) -> V::Result { match *arg { PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt), - PreciseCapturingArg::Param(_, hir_id) => visitor.visit_id(hir_id), + PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id), } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f4d443c324a..592a8648f14 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -487,7 +487,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe for arg in precise_capturing_args { match *arg { hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, .. }) - | hir::PreciseCapturingArg::Param(_, hir_id) => match tcx.named_bound_var(hir_id) { + | hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg { + hir_id, .. + }) => match tcx.named_bound_var(hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => { expected_captures.insert(def_id); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8d5f4c13721..fb3713140ff 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -577,10 +577,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }); } }, - hir::PreciseCapturingArg::Param(res, hir_id) => match res { + hir::PreciseCapturingArg::Param(param) => match param.res { Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id) | Res::SelfTyParam { trait_: def_id } => { - self.resolve_type_ref(def_id.expect_local(), hir_id); + self.resolve_type_ref(def_id.expect_local(), param.hir_id); } Res::Err => {} _ => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 39312614c1b..3d3b16baf69 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -99,6 +99,7 @@ impl<'a> State<'a> { Node::PatField(a) => self.print_patfield(a), Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), + Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 72f849b534a..88de834c436 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -909,6 +909,7 @@ impl<'hir> Map<'hir> { Node::Crate(item) => item.spans.inner_span, Node::WhereBoundPredicate(pred) => pred.span, Node::ArrayLenInfer(inf) => inf.span, + Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::Synthetic => unreachable!(), Node::Err(span) => *span, } @@ -1176,6 +1177,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::ArrayLenInfer(_) => node_str("array len infer"), Node::Synthetic => unreachable!(), Node::Err(_) => node_str("error"), + Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), } } diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs index 7e856ba9517..cc86bf83107 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs @@ -1,7 +1,10 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn type_param() -> impl use<> Sized {} -//~^ ERROR `impl Trait` must mention all type parameters in scope +fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } +//~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + +fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } +//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr index 1ef46a36e46..e472c898050 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr @@ -7,13 +7,29 @@ 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 - --> $DIR/forgot-to-capture-lifetime.rs:4:15 +error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + --> $DIR/forgot-to-capture-lifetime.rs:4:58 | -LL | fn type_param() -> impl use<> Sized {} - | ^ ---------------- type parameter is implicitly captured by this `impl Trait` +LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } + | -- -----------------^^---- + | | | + | | lifetime captured due to being mentioned in the bounds of the `impl Trait` + | this lifetime parameter is captured + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/forgot-to-capture-lifetime.rs:7:60 | - = note: currently, all type parameters are required to be mentioned in the precise captures list +LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } + | -- ---------------- ^ + | | | + | | opaque type defined here + | hidden type `&'a ()` captures the lifetime `'a` as defined here + | +help: to declare that `impl Sized` captures `'a`, you can add an explicit `'a` lifetime bound + | +LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized + 'a { x } + | ++++ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0700`. 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 cc86bf83107..6eaff01183d 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 @@ -1,10 +1,12 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } -//~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list +fn type_param() -> impl use<> Sized {} +//~^ ERROR `impl Trait` must mention all type parameters in scope -fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } -//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds +trait Foo { +//~^ ERROR `impl Trait` must mention all type parameters in scope + fn bar() -> impl use<> Sized; +} 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 58f284ec6bc..a8eb4547dcd 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,29 +7,24 @@ LL | #![feature(precise_capturing)] = note: see issue #123432 for more information = note: `#[warn(incomplete_features)]` on by default -error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/forgot-to-capture-type.rs:4:58 +error: `impl Trait` must mention all type parameters in scope + --> $DIR/forgot-to-capture-type.rs:4:15 | -LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } - | -- -----------------^^---- - | | | - | | lifetime captured due to being mentioned in the bounds of the `impl Trait` - | this lifetime parameter is captured +LL | fn type_param() -> 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 -error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/forgot-to-capture-type.rs:7:60 +error: `impl Trait` must mention all type parameters in scope + --> $DIR/forgot-to-capture-type.rs:7:1 | -LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } - | -- ---------------- ^ - | | | - | | opaque type defined here - | hidden type `&'a ()` captures the lifetime `'a` as defined here +LL | trait Foo { + | ^^^^^^^^^ +LL | +LL | fn bar() -> impl use<> Sized; + | ---------------- type parameter is implicitly captured by this `impl Trait` | -help: to declare that `impl Sized` captures `'a`, you can add an explicit `'a` lifetime bound - | -LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized + 'a { x } - | ++++ + = note: currently, all type parameters are required to be mentioned in the precise captures list error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs new file mode 100644 index 00000000000..ecbc388e27b --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![feature(precise_capturing)] +//~^ WARN the feature `precise_capturing` is incomplete + +trait Foo { + fn bar<'a>() -> impl use Sized; +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr new file mode 100644 index 00000000000..5a058c6826d --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -0,0 +1,11 @@ +warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/self-capture.rs:3:12 + | +LL | #![feature(precise_capturing)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #123432 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted +