about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir/src/hir.rs5
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl6
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs1
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--tests/ui/impl-trait/precise-capturing/apit.rs7
-rw-r--r--tests/ui/impl-trait/precise-capturing/apit.stderr17
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.rs3
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.stderr8
-rw-r--r--tests/ui/impl-trait/precise-capturing/elided.rs8
-rw-r--r--tests/ui/impl-trait/precise-capturing/elided.stderr11
12 files changed, 79 insertions, 5 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 00b1ea061cc..b39056d8690 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2568,6 +2568,11 @@ pub enum PreciseCapturingArg<'hir> {
     Param(PreciseCapturingNonLifetimeArg),
 }
 
+/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param
+/// resolution to. Lifetimes don't have this problem, and for them, it's actually
+/// kind of detrimental to use a custom node type versus just using [`Lifetime`],
+/// since resolve_bound_vars operates on `Lifetime`s.
+// FIXME(precise_capturing): Investigate storing this as a path instead?
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct PreciseCapturingNonLifetimeArg {
     pub hir_id: HirId,
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index bc6583444c3..0ff78ebff99 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -39,9 +39,6 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
 
 hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
 
-hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
-    .label = `Self` is not a generic argument, but an alias to the type of the {$what}
-
 hir_analysis_cannot_capture_late_bound_const =
     cannot capture late-bound const parameter in {$what}
     .label = parameter defined here
@@ -374,6 +371,9 @@ hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pa
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
 
+hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
+    .label = `Self` is not a generic argument, but an alias to the type of the {$what}
+
 hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
     .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 1e8cd50ca0d..8c85d13650b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -475,6 +475,14 @@ fn sanity_check_found_hidden_type<'tcx>(
     }
 }
 
+/// Check that the opaque's precise captures list is valid (if present).
+/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
+/// are technically GATs.
+///
+/// This function is responsible for:
+/// 1. Checking that all type/const params are mention in the captures list.
+/// 2. Checking that all lifetimes that are implicitly captured are mentioned.
+/// 3. Asserting that all parameters mentioned in the captures list are invariant.
 fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
     let hir::OpaqueTy { precise_capturing_args, .. } =
         *tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index fe70b631cdb..0bbabefaf95 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -283,6 +283,7 @@ pub fn suggest_new_region_bound(
             continue;
         }
         match fn_return.kind {
+            // FIXME(precise_captures): Suggest adding to `use<...>` list instead.
             TyKind::OpaqueDef(item_id, _, _) => {
                 let item = tcx.hir().item(item_id);
                 let ItemKind::OpaqueTy(opaque) = &item.kind else {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index f78a039394b..a6195fa7693 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -669,7 +669,9 @@ impl<'a> Parser<'a> {
             })
         }
 
-        // parse precise captures, if any.
+        // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
+        // lifetimes and ident params (including SelfUpper). These are validated later
+        // for order, duplication, and whether they actually reference params.
         let precise_capturing = if self.eat_keyword(kw::Use) {
             let use_span = self.prev_token.span;
             self.psess.gated_spans.gate(sym::precise_capturing, use_span);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 64434412886..ba1391bc378 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1059,6 +1059,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
             PreciseCapturingArg::Lifetime(_) => {}
 
             PreciseCapturingArg::Arg(path, id) => {
+                // we want `impl use<C>` to try to resolve `C` as both a type parameter or
+                // a const parameter. Since the resolver specifically doesn't allow having
+                // two generic params with the same name, even if they're a different namespace,
+                // it doesn't really matter which we try resolving first, but just like
+                // `Ty::Param` we just fall back to the value namespace only if it's missing
+                // from the type namespace.
                 let mut check_ns = |ns| {
                     self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
                 };
diff --git a/tests/ui/impl-trait/precise-capturing/apit.rs b/tests/ui/impl-trait/precise-capturing/apit.rs
new file mode 100644
index 00000000000..efcac9ebb0b
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/apit.rs
@@ -0,0 +1,7 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn hello(_: impl use<> Sized) {}
+//~^ ERROR `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/apit.stderr b/tests/ui/impl-trait/precise-capturing/apit.stderr
new file mode 100644
index 00000000000..36bf80d9e2f
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/apit.stderr
@@ -0,0 +1,17 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/apit.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
+  --> $DIR/apit.rs:4:18
+   |
+LL | fn hello(_: impl use<> Sized) {}
+   |                  ^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs
index 195bd1b67ae..7970d49bf7c 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-params.rs
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs
@@ -13,4 +13,7 @@ impl MyType {
     //~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias
 }
 
+fn hello() -> impl use<hello> Sized {}
+//~^ ERROR expected type or const parameter in `use<...>` precise captures list, found function
+
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr
index 09694a800c4..27bf05302f9 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr
@@ -34,7 +34,13 @@ LL | impl MyType {
 LL |     fn self_is_not_param() -> impl use<Self> Sized {}
    |                                        ^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: expected type or const parameter in `use<...>` precise captures list, found function
+  --> $DIR/bad-params.rs:16:24
+   |
+LL | fn hello() -> impl use<hello> Sized {}
+   |                        ^^^^^
+
+error: aborting due to 4 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0411, E0412.
 For more information about an error, try `rustc --explain E0411`.
diff --git a/tests/ui/impl-trait/precise-capturing/elided.rs b/tests/ui/impl-trait/precise-capturing/elided.rs
new file mode 100644
index 00000000000..de80e8a5d58
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/elided.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn elided(x: &()) -> impl use<'_> Sized { x }
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/elided.stderr b/tests/ui/impl-trait/precise-capturing/elided.stderr
new file mode 100644
index 00000000000..38da0828de9
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/elided.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/elided.rs:3:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+