about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-12-29 19:40:06 +0000
committerbors <bors@rust-lang.org>2022-12-29 19:40:06 +0000
commitad8ae0504c54bc2bd8306abfcfe8546c1bb16a49 (patch)
treef86627123dc427614f56aca1c7cfd2c221bb7b34 /compiler
parente37ff7e71a087fcd799d3e59bcd63e3732d351d3 (diff)
parent65fb70304a758db5696f20f077bdb1c2620fc31c (diff)
downloadrust-ad8ae0504c54bc2bd8306abfcfe8546c1bb16a49.tar.gz
rust-ad8ae0504c54bc2bd8306abfcfe8546c1bb16a49.zip
Auto merge of #106266 - matthiaskrgr:rollup-cxrdbzy, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #104531 (Provide a better error and a suggestion for `Fn` traits with lifetime params)
 - #105899 (`./x doc library --open` opens `std`)
 - #106190 (Account for multiple multiline spans with empty padding)
 - #106202 (Trim more paths in obligation types)
 - #106234 (rustdoc: simplify settings, help, and copy button CSS by not reusing)
 - #106236 (docs/test: add docs and a UI test for `E0514` and `E0519`)
 - #106259 (Update Clippy)
 - #106260 (Fix index out of bounds issues in rustdoc)
 - #106263 (Formatter should not try to format non-Rust files)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0514.md33
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0519.md40
-rw-r--r--compiler/rustc_errors/src/emitter.rs22
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs95
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs14
7 files changed, 198 insertions, 12 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index e6d26240e24..5a1670f06fc 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -276,10 +276,12 @@ E0509: include_str!("./error_codes/E0509.md"),
 E0510: include_str!("./error_codes/E0510.md"),
 E0511: include_str!("./error_codes/E0511.md"),
 E0512: include_str!("./error_codes/E0512.md"),
+E0514: include_str!("./error_codes/E0514.md"),
 E0515: include_str!("./error_codes/E0515.md"),
 E0516: include_str!("./error_codes/E0516.md"),
 E0517: include_str!("./error_codes/E0517.md"),
 E0518: include_str!("./error_codes/E0518.md"),
+E0519: include_str!("./error_codes/E0519.md"),
 E0520: include_str!("./error_codes/E0520.md"),
 E0521: include_str!("./error_codes/E0521.md"),
 E0522: include_str!("./error_codes/E0522.md"),
@@ -615,8 +617,6 @@ E0791: include_str!("./error_codes/E0791.md"),
 //  E0488, // lifetime of variable does not enclose its declaration
 //  E0489, // type/lifetime parameter not in scope here
     E0490, // a value of type `..` is borrowed for too long
-    E0514, // metadata version mismatch
-    E0519, // local crate and dependency have same (crate-name, disambiguator)
     E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
 //  E0526, // shuffle indices are not constant
 //  E0540, // multiple rustc_deprecated attributes
diff --git a/compiler/rustc_error_codes/src/error_codes/E0514.md b/compiler/rustc_error_codes/src/error_codes/E0514.md
new file mode 100644
index 00000000000..ce2bbc5c505
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0514.md
@@ -0,0 +1,33 @@
+Dependency compiled with different version of `rustc`.
+
+Example of erroneous code:
+
+`a.rs`
+```ignore (cannot-link-with-other-tests)
+// compiled with stable `rustc`
+
+#[crate_type = "lib"]
+```
+
+`b.rs`
+```ignore (cannot-link-with-other-tests)
+// compiled with nightly `rustc`
+
+#[crate_type = "lib"]
+
+extern crate a; // error: found crate `a` compiled by an incompatible version
+                //        of rustc
+```
+
+This error is caused when the version of `rustc` used to compile a crate, as
+stored in the binary's metadata, differs from the version of one of its
+dependencies. Many parts of Rust binaries are considered unstable. For
+instance, the Rust ABI is not stable between compiler versions. This means that
+the compiler cannot be sure about *how* to call a function between compiler
+versions, and therefore this error occurs.
+
+This error can be fixed by:
+ * Using [Cargo](../cargo/index.html), the Rust package manager and
+   [Rustup](https://rust-lang.github.io/rustup/), the Rust toolchain installer,
+   automatically fixing this issue.
+ * Recompiling the crates with a uniform `rustc` version.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0519.md b/compiler/rustc_error_codes/src/error_codes/E0519.md
new file mode 100644
index 00000000000..12876e2ad75
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0519.md
@@ -0,0 +1,40 @@
+The current crate is indistinguishable from one of its dependencies, in terms
+of metadata.
+
+Example of erroneous code:
+
+`a.rs`
+```ignore (cannot-link-with-other-tests)
+#![crate_name = "a"]
+#![crate_type = "lib"]
+
+pub fn foo() {}
+```
+
+`b.rs`
+```ignore (cannot-link-with-other-tests)
+#![crate_name = "a"]
+#![crate_type = "lib"]
+
+// error: the current crate is indistinguishable from one of its dependencies:
+//        it has the same crate-name `a` and was compiled with the same
+//        `-C metadata` arguments. This will result in symbol conflicts between
+//        the two.
+extern crate a;
+
+pub fn foo() {}
+
+fn bar() {
+    a::foo(); // is this calling the local crate or the dependency?
+}
+```
+
+The above example compiles two crates with exactly the same name and
+`crate_type` (plus any other metadata). This causes an error because it becomes
+impossible for the compiler to distinguish between symbols (`pub` item names).
+
+This error can be fixed by:
+ * Using [Cargo](../cargo/index.html), the Rust package manager, automatically
+   fixing this issue.
+ * Recompiling the crate with different metadata (different name/
+   `crate_type`).
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index e2a0e436fd5..0ca200abe19 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -845,7 +845,10 @@ impl EmitterWriter {
         // 3 | |
         // 4 | | }
         //   | |_^ test
-        if let [ann] = &line.annotations[..] {
+        let mut buffer_ops = vec![];
+        let mut annotations = vec![];
+        let mut short_start = true;
+        for ann in &line.annotations {
             if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
                 if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
                     let style = if ann.is_primary {
@@ -853,10 +856,23 @@ impl EmitterWriter {
                     } else {
                         Style::UnderlineSecondary
                     };
-                    buffer.putc(line_offset, width_offset + depth - 1, '/', style);
-                    return vec![(depth, style)];
+                    annotations.push((depth, style));
+                    buffer_ops.push((line_offset, width_offset + depth - 1, '/', style));
+                } else {
+                    short_start = false;
+                    break;
                 }
+            } else if let AnnotationType::MultilineLine(_) = ann.annotation_type {
+            } else {
+                short_start = false;
+                break;
+            }
+        }
+        if short_start {
+            for (y, x, c, s) in buffer_ops {
+                buffer.putc(y, x, c, s);
             }
+            return annotations;
         }
 
         // We want to display like this:
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c6b6c04de85..a958c294930 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2456,7 +2456,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses the parameter list of a function, including the `(` and `)` delimiters.
-    fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> {
+    pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> {
         let mut first_param = true;
         // Parse the arguments, starting out with `self` being allowed...
         let (mut params, _) = self.parse_paren_comma_seq(|p| {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index c50b2877bab..a6f702e5428 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -933,8 +933,8 @@ impl<'a> Parser<'a> {
         has_parens: bool,
         modifiers: BoundModifiers,
     ) -> PResult<'a, GenericBound> {
-        let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-        let path = if self.token.is_keyword(kw::Fn)
+        let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+        let mut path = if self.token.is_keyword(kw::Fn)
             && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
             && let Some(path) = self.recover_path_from_fn()
         {
@@ -942,6 +942,11 @@ impl<'a> Parser<'a> {
         } else {
             self.parse_path(PathStyle::Type)?
         };
+
+        if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {
+            self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
+        }
+
         if has_parens {
             if self.token.is_like_plus() {
                 // Someone has written something like `&dyn (Trait + Other)`. The correct code
@@ -1016,6 +1021,92 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
+    /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
+    /// been eaten.
+    fn recover_fn_trait_with_lifetime_params(
+        &mut self,
+        fn_path: &mut ast::Path,
+        lifetime_defs: &mut Vec<GenericParam>,
+    ) -> PResult<'a, ()> {
+        let fn_path_segment = fn_path.segments.last_mut().unwrap();
+        let generic_args = if let Some(p_args) = &fn_path_segment.args {
+            p_args.clone().into_inner()
+        } else {
+            // Normally it wouldn't come here because the upstream should have parsed
+            // generic parameters (otherwise it's impossible to call this function).
+            return Ok(());
+        };
+        let lifetimes =
+            if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
+                &generic_args
+            {
+                args.into_iter()
+                    .filter_map(|arg| {
+                        if let ast::AngleBracketedArg::Arg(generic_arg) = arg
+                            && let ast::GenericArg::Lifetime(lifetime) = generic_arg {
+                            Some(lifetime)
+                        } else {
+                            None
+                        }
+                    })
+                    .collect()
+            } else {
+                Vec::new()
+            };
+        // Only try to recover if the trait has lifetime params.
+        if lifetimes.is_empty() {
+            return Ok(());
+        }
+
+        // Parse `(T, U) -> R`.
+        let inputs_lo = self.token.span;
+        let inputs: Vec<_> =
+            self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
+        let inputs_span = inputs_lo.to(self.prev_token.span);
+        let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
+        let args = ast::ParenthesizedArgs {
+            span: fn_path_segment.span().to(self.prev_token.span),
+            inputs,
+            inputs_span,
+            output,
+        }
+        .into();
+        *fn_path_segment =
+            ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID };
+
+        // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
+        let mut generic_params = lifetimes
+            .iter()
+            .map(|lt| GenericParam {
+                id: lt.id,
+                ident: lt.ident,
+                attrs: ast::AttrVec::new(),
+                bounds: Vec::new(),
+                is_placeholder: false,
+                kind: ast::GenericParamKind::Lifetime,
+                colon_span: None,
+            })
+            .collect::<Vec<GenericParam>>();
+        lifetime_defs.append(&mut generic_params);
+
+        let generic_args_span = generic_args.span();
+        let mut err =
+            self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
+        let snippet = format!(
+            "for<{}> ",
+            lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
+        );
+        let before_fn_path = fn_path.span.shrink_to_lo();
+        err.multipart_suggestion(
+            "consider using a higher-ranked trait bound instead",
+            vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
+            Applicability::MaybeIncorrect,
+        )
+        .emit();
+        Ok(())
+    }
+
     pub(super) fn check_lifetime(&mut self) -> bool {
         self.expected_tokens.push(TokenType::Lifetime);
         self.token.is_lifetime()
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 26ba3d780d5..06ab0e8d944 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2692,7 +2692,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // Don't print the tuple of capture types
                 'print: {
                     if !is_upvar_tys_infer_tuple {
-                        let msg = format!("required because it appears within the type `{}`", ty);
+                        let msg = with_forced_trimmed_paths!(format!(
+                            "required because it appears within the type `{ty}`",
+                        ));
                         match ty.kind() {
                             ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
                                 Some(ident) => err.span_note(ident.span, &msg),
@@ -2733,7 +2735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let mut msg =
                                     "required because it captures the following types: ".to_owned();
                                 for ty in bound_tys.skip_binder() {
-                                    write!(msg, "`{}`, ", ty).unwrap();
+                                    with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
                                 }
                                 err.note(msg.trim_end_matches(", "))
                             }
@@ -2744,7 +2746,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let kind = tcx.generator_kind(def_id).unwrap().descr();
                                 err.span_note(
                                     sp,
-                                    &format!("required because it's used within this {}", kind),
+                                    with_forced_trimmed_paths!(&format!(
+                                        "required because it's used within this {kind}",
+                                    )),
                                 )
                             }
                             ty::Closure(def_id, _) => err.span_note(
@@ -2968,7 +2972,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
                     err.span_label(
                         expr_span,
-                        format!("return type was inferred to be `{expr_ty}` here"),
+                        with_forced_trimmed_paths!(format!(
+                            "return type was inferred to be `{expr_ty}` here",
+                        )),
                     );
                 }
             }