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
This commit is contained in:
commit
ad8ae0504c
128 changed files with 2905 additions and 436 deletions
|
@ -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
|
||||
|
|
33
compiler/rustc_error_codes/src/error_codes/E0514.md
Normal file
33
compiler/rustc_error_codes/src/error_codes/E0514.md
Normal file
|
@ -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.
|
40
compiler/rustc_error_codes/src/error_codes/E0519.md
Normal file
40
compiler/rustc_error_codes/src/error_codes/E0519.md
Normal file
|
@ -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`).
|
|
@ -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,11 +856,24 @@ 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:
|
||||
//
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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",
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue