about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-04-04 20:23:52 -0400
committerMichael Goulet <michael@errs.io>2024-04-15 16:45:26 -0400
commit52c6b101ea18ed6f09367bf459ac55ffe473cd9c (patch)
tree4bd7b7084b701a4c3e9deb299db09c209b5a7dbc
parentce8961039e244b1e4e0fa02fc10d59a22abc9ea3 (diff)
downloadrust-52c6b101ea18ed6f09367bf459ac55ffe473cd9c.tar.gz
rust-52c6b101ea18ed6f09367bf459ac55ffe473cd9c.zip
Use a path instead of an ident (and stop manually resolving)
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs4
-rw-r--r--compiler/rustc_ast/src/visit.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs11
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/errors/precise_captures.rs10
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs7
-rw-r--r--compiler/rustc_resolve/src/late.rs66
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.rs6
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.stderr32
12 files changed, 81 insertions, 84 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ace20a005ee..0cf96797028 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2188,12 +2188,12 @@ pub enum TraitObjectSyntax {
     None,
 }
 
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum PreciseCapturingArg {
     /// Lifetime parameter
     Lifetime(Lifetime),
     /// Type or const parameter
-    Arg(Ident, NodeId),
+    Arg(Path, NodeId),
 }
 
 /// Inline assembly operand explicit register or register class.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 204f33cab34..c4e49d7dbea 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -928,8 +928,8 @@ pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturin
         PreciseCapturingArg::Lifetime(lt) => {
             vis.visit_lifetime(lt);
         }
-        PreciseCapturingArg::Arg(ident, id) => {
-            vis.visit_ident(ident);
+        PreciseCapturingArg::Arg(path, id) => {
+            vis.visit_path(path);
             vis.visit_id(id);
         }
     }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a9c29e077d1..968d10ad487 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -653,8 +653,8 @@ pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
         PreciseCapturingArg::Lifetime(lt) => {
             visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
         }
-        PreciseCapturingArg::Arg(ident, _) => {
-            visitor.visit_ident(*ident);
+        PreciseCapturingArg::Arg(path, id) => {
+            visitor.visit_path(path, *id);
         }
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 84776f920c4..a21d6019cf1 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1790,13 +1790,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             PreciseCapturingArg::Lifetime(lt) => {
                 hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
             }
-            PreciseCapturingArg::Arg(ident, node_id) => {
-                let res = self.resolver.get_partial_res(*node_id).map_or(Res::Err, |partial_res| {
+            PreciseCapturingArg::Arg(path, id) => {
+                let [segment] = path.segments.as_slice() else {
+                    panic!();
+                };
+                let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| {
                     partial_res.full_res().expect("no partial res expected for precise capture arg")
                 });
                 hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
-                    hir_id: self.lower_node_id(*node_id),
-                    ident: self.lower_ident(*ident),
+                    hir_id: self.lower_node_id(*id),
+                    ident: self.lower_ident(segment.ident),
                     res: self.lower_res(res),
                 })
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index db9633bb1cb..96909940972 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1156,7 +1156,7 @@ impl<'a> State<'a> {
                     self.word("use");
                     self.word("<");
                     self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg {
-                        ast::PreciseCapturingArg::Arg(a, _) => s.print_ident(*a),
+                        ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0),
                         ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt),
                     });
                     self.word(">")
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 4ac2965bd5f..bc6583444c3 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -39,6 +39,9 @@ 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
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 fb3713140ff..78c2665fd1f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -583,9 +583,19 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     self.resolve_type_ref(def_id.expect_local(), param.hir_id);
                 }
                 Res::Err => {}
-                _ => {
-                    // This is handled in resolve
-                    self.tcx.dcx().delayed_bug(format!("parameter should have been resolved"));
+                Res::SelfTyAlias { alias_to, .. } => {
+                    self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
+                        span: param.ident.span,
+                        self_span: self.tcx.def_span(alias_to),
+                        what: self.tcx.def_descr(alias_to),
+                    });
+                }
+                res => {
+                    self.tcx.dcx().emit_err(errors::BadPreciseCapture {
+                        span: param.ident.span,
+                        kind: "type or const",
+                        found: res.descr().to_string(),
+                    });
                 }
             },
         }
diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
index e2eb9c72bf2..520bf1d9f40 100644
--- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
+++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
@@ -33,6 +33,16 @@ pub struct BadPreciseCapture {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_precise_capture_self_alias)]
+pub struct PreciseCaptureSelfAlias {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub self_span: Span,
+    pub what: &'static str,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_duplicate_precise_capture)]
 pub struct DuplicatePreciseCapture {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 91f4823f65d..f78a039394b 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -697,11 +697,14 @@ impl<'a> Parser<'a> {
                     if self_.check_keyword(kw::SelfUpper) {
                         self_.bump();
                         Ok(PreciseCapturingArg::Arg(
-                            self_.prev_token.ident().unwrap().0,
+                            ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
                             DUMMY_NODE_ID,
                         ))
                     } else if self_.check_ident() {
-                        Ok(PreciseCapturingArg::Arg(self_.parse_ident().unwrap(), DUMMY_NODE_ID))
+                        Ok(PreciseCapturingArg::Arg(
+                            ast::Path::from_ident(self_.parse_ident()?),
+                            DUMMY_NODE_ID,
+                        ))
                     } else if self_.check_lifetime() {
                         Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
                     } else {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 7203adab135..64434412886 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1056,64 +1056,22 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
         match arg {
             // Lower the lifetime regularly; we'll resolve the lifetime and check
             // it's a parameter later on in HIR lowering.
-            PreciseCapturingArg::Lifetime(_) => visit::walk_precise_capturing_arg(self, arg),
+            PreciseCapturingArg::Lifetime(_) => {}
 
-            PreciseCapturingArg::Arg(ident, node_id) => {
-                let ident = ident.normalize_to_macros_2_0();
-                'found: {
-                    for (rib_t, rib_v) in
-                        std::iter::zip(&self.ribs.type_ns, &self.ribs.value_ns).rev()
-                    {
-                        if let Some(res) = rib_t.bindings.get(&ident).or(rib_v.bindings.get(&ident))
-                        {
-                            self.r.record_partial_res(*node_id, PartialRes::new(*res));
-
-                            // Validate that this is a parameter
-                            match res {
-                                Res::Def(DefKind::TyParam | DefKind::ConstParam, _)
-                                | Res::SelfTyParam { .. } => {}
-                                Res::SelfTyAlias { .. } => {
-                                    self.report_error(
-                                        ident.span,
-                                        ResolutionError::FailedToResolve {
-                                            segment: Some(ident.name),
-                                            label: "`Self` cannot be captured because it is not a type parameter".to_string(),
-                                            suggestion: None,
-                                            module: None,
-                                        },
-                                    );
-                                }
-                                _ => {
-                                    self.report_error(
-                                        ident.span,
-                                        ResolutionError::FailedToResolve {
-                                            segment: Some(ident.name),
-                                            label: format!(
-                                                "expected type or const parameter, found {}",
-                                                res.descr()
-                                            ),
-                                            suggestion: None,
-                                            module: None,
-                                        },
-                                    );
-                                }
-                            }
-
-                            break 'found;
-                        }
-                    }
-                    self.report_error(
-                        ident.span,
-                        ResolutionError::FailedToResolve {
-                            segment: Some(ident.name),
-                            label: "could not find type or const parameter".to_string(),
-                            suggestion: None,
-                            module: None,
-                        },
-                    );
+            PreciseCapturingArg::Arg(path, id) => {
+                let mut check_ns = |ns| {
+                    self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
+                };
+                // Like `Ty::Param`, we try resolving this as both a const and a type.
+                if !check_ns(TypeNS) && check_ns(ValueNS) {
+                    self.smart_resolve_path(*id, &None, path, PathSource::Expr(None));
+                } else {
+                    self.smart_resolve_path(*id, &None, path, PathSource::Type);
                 }
             }
         }
+
+        visit::walk_precise_capturing_arg(self, arg)
     }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs
index c600fa96f79..195bd1b67ae 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-params.rs
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs
@@ -2,15 +2,15 @@
 //~^ WARN the feature `precise_capturing` is incomplete
 
 fn missing() -> impl use<T> Sized {}
-//~^ ERROR could not find type or const parameter
+//~^ ERROR cannot find type `T` in this scope
 
 fn missing_self() -> impl use<Self> Sized {}
-//~^ ERROR could not find type or const parameter
+//~^ ERROR cannot find type `Self` in this scope
 
 struct MyType;
 impl MyType {
     fn self_is_not_param() -> impl use<Self> Sized {}
-    //~^ ERROR `Self` cannot be captured because it is not a type parameter
+    //~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias
 }
 
 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 bb5fe76ae3e..09694a800c4 100644
--- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr
@@ -1,20 +1,21 @@
-error[E0433]: failed to resolve: could not find type or const parameter
+error[E0412]: cannot find type `T` in this scope
   --> $DIR/bad-params.rs:4:26
    |
 LL | fn missing() -> impl use<T> Sized {}
-   |                          ^ could not find type or const parameter
+   |                          ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn missing<T>() -> impl use<T> Sized {}
+   |           +++
 
-error[E0433]: failed to resolve: could not find type or const parameter
+error[E0411]: cannot find type `Self` in this scope
   --> $DIR/bad-params.rs:7:31
    |
 LL | fn missing_self() -> impl use<Self> Sized {}
-   |                               ^^^^ could not find type or const parameter
-
-error[E0433]: failed to resolve: `Self` cannot be captured because it is not a type parameter
-  --> $DIR/bad-params.rs:12:40
-   |
-LL |     fn self_is_not_param() -> impl use<Self> Sized {}
-   |                                        ^^^^ `Self` cannot be captured because it is not a type parameter
+   |    ------------               ^^^^ `Self` is only available in impls, traits, and type definitions
+   |    |
+   |    `Self` not allowed in a function
 
 warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bad-params.rs:1:12
@@ -25,6 +26,15 @@ 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: `Self` can't be captured in `use<...>` precise captures list, since it is an alias
+  --> $DIR/bad-params.rs:12:40
+   |
+LL | impl MyType {
+   | ----------- `Self` is not a generic argument, but an alias to the type of the implementation
+LL |     fn self_is_not_param() -> impl use<Self> Sized {}
+   |                                        ^^^^
+
 error: aborting due to 3 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0411, E0412.
+For more information about an error, try `rustc --explain E0411`.