]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_ast_lowering/src/path.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / compiler / rustc_ast_lowering / src / path.rs
index 929f427484dba4ac28ba65fd7bf931c067c46376..46928a1846540f13859f74c2f6df5ce4023dd67b 100644 (file)
@@ -7,8 +7,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
-use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
-use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::symbol::Ident;
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
@@ -231,15 +229,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
                             // Do not suggest going from `Trait()` to `Trait<>`
                             if !data.inputs.is_empty() {
-                                if let Some(split) = snippet.find('(') {
-                                    let trait_name = &snippet[0..split];
-                                    let args = &snippet[split + 1..snippet.len() - 1];
-                                    err.span_suggestion(
-                                        data.span,
-                                        "use angle brackets instead",
-                                        format!("{}<{}>", trait_name, args),
-                                        Applicability::MaybeIncorrect,
-                                    );
+                                // Suggest replacing `(` and `)` with `<` and `>`
+                                // The snippet may be missing the closing `)`, skip that case
+                                if snippet.ends_with(')') {
+                                    if let Some(split) = snippet.find('(') {
+                                        let trait_name = &snippet[0..split];
+                                        let args = &snippet[split + 1..snippet.len() - 1];
+                                        err.span_suggestion(
+                                            data.span,
+                                            "use angle brackets instead",
+                                            format!("{}<{}>", trait_name, args),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                    }
                                 }
                             }
                         };
@@ -270,12 +272,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let has_lifetimes =
             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
-        if !generic_args.parenthesized && !has_lifetimes {
+        if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 {
             // Note: these spans are used for diagnostics when they can't be inferred.
             // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
             let elided_lifetime_span = if generic_args.span.is_empty() {
                 // If there are no brackets, use the identifier span.
-                segment.ident.span
+                // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
+                // originating from macros, since the segment's span might be from a macro arg.
+                segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
             } else if generic_args.is_empty() {
                 // If there are brackets, but not generic arguments, then use the opening bracket
                 generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
@@ -284,67 +288,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
             };
             generic_args.args = self
-                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
+                .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode)
                 .map(GenericArg::Lifetime)
                 .chain(generic_args.args.into_iter())
                 .collect();
-            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
+            // In create-parameter mode we error here because we don't want to support
+            // deprecated impl elision in new features like impl elision and `async fn`,
+            // both of which work using the `CreateParameter` mode:
+            //
+            //     impl Foo for std::cell::Ref<u32> // note lack of '_
+            //     async fn foo(_: std::cell::Ref<u32>) { ... }
+            if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
+                (param_mode, self.anonymous_lifetime_mode)
+            {
                 let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
                 let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
                 let no_bindings = generic_args.bindings.is_empty();
-                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
+                let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings {
                     // If there are no generic args, our suggestion can include the angle brackets.
-                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
+                    (true, format!("<{}>", anon_lt_suggestion))
                 } else {
                     // Otherwise we'll insert a `'_, ` right after the opening bracket.
-                    let span = generic_args
-                        .span
-                        .with_lo(generic_args.span.lo() + BytePos(1))
-                        .shrink_to_lo();
-                    (false, span, format!("{}, ", anon_lt_suggestion))
+                    (false, format!("{}, ", anon_lt_suggestion))
                 };
-                match self.anonymous_lifetime_mode {
-                    // In create-parameter mode we error here because we don't want to support
-                    // deprecated impl elision in new features like impl elision and `async fn`,
-                    // both of which work using the `CreateParameter` mode:
-                    //
-                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
-                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
-                    AnonymousLifetimeMode::CreateParameter => {
-                        let mut err = struct_span_err!(
-                            self.sess,
-                            path_span,
-                            E0726,
-                            "implicit elided lifetime not allowed here"
-                        );
-                        rustc_errors::add_elided_lifetime_in_path_suggestion(
-                            &self.sess.source_map(),
-                            &mut err,
-                            expected_lifetimes,
-                            path_span,
-                            incl_angl_brckt,
-                            insertion_sp,
-                            suggestion,
-                        );
-                        err.note("assuming a `'static` lifetime...");
-                        err.emit();
-                    }
-                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
-                            ELIDED_LIFETIMES_IN_PATHS,
-                            CRATE_NODE_ID,
-                            path_span,
-                            "hidden lifetime parameters in types are deprecated",
-                            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                                expected_lifetimes,
-                                path_span,
-                                incl_angl_brckt,
-                                insertion_sp,
-                                suggestion,
-                            ),
-                        );
-                    }
-                }
+                let insertion_sp = elided_lifetime_span.shrink_to_hi();
+                let mut err = struct_span_err!(
+                    self.sess,
+                    path_span,
+                    E0726,
+                    "implicit elided lifetime not allowed here"
+                );
+                rustc_errors::add_elided_lifetime_in_path_suggestion(
+                    &self.sess.source_map(),
+                    &mut err,
+                    expected_lifetimes,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_sp,
+                    suggestion,
+                );
+                err.note("assuming a `'static` lifetime...");
+                err.emit();
             }
         }