Skip to content

Commit ad8ae05

Browse files
committed
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
2 parents e37ff7e + 65fb703 commit ad8ae05

File tree

128 files changed

+2902
-433
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+2902
-433
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,12 @@ E0509: include_str!("./error_codes/E0509.md"),
276276
E0510: include_str!("./error_codes/E0510.md"),
277277
E0511: include_str!("./error_codes/E0511.md"),
278278
E0512: include_str!("./error_codes/E0512.md"),
279+
E0514: include_str!("./error_codes/E0514.md"),
279280
E0515: include_str!("./error_codes/E0515.md"),
280281
E0516: include_str!("./error_codes/E0516.md"),
281282
E0517: include_str!("./error_codes/E0517.md"),
282283
E0518: include_str!("./error_codes/E0518.md"),
284+
E0519: include_str!("./error_codes/E0519.md"),
283285
E0520: include_str!("./error_codes/E0520.md"),
284286
E0521: include_str!("./error_codes/E0521.md"),
285287
E0522: include_str!("./error_codes/E0522.md"),
@@ -615,8 +617,6 @@ E0791: include_str!("./error_codes/E0791.md"),
615617
// E0488, // lifetime of variable does not enclose its declaration
616618
// E0489, // type/lifetime parameter not in scope here
617619
E0490, // a value of type `..` is borrowed for too long
618-
E0514, // metadata version mismatch
619-
E0519, // local crate and dependency have same (crate-name, disambiguator)
620620
E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
621621
// E0526, // shuffle indices are not constant
622622
// E0540, // multiple rustc_deprecated attributes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Dependency compiled with different version of `rustc`.
2+
3+
Example of erroneous code:
4+
5+
`a.rs`
6+
```ignore (cannot-link-with-other-tests)
7+
// compiled with stable `rustc`
8+
9+
#[crate_type = "lib"]
10+
```
11+
12+
`b.rs`
13+
```ignore (cannot-link-with-other-tests)
14+
// compiled with nightly `rustc`
15+
16+
#[crate_type = "lib"]
17+
18+
extern crate a; // error: found crate `a` compiled by an incompatible version
19+
// of rustc
20+
```
21+
22+
This error is caused when the version of `rustc` used to compile a crate, as
23+
stored in the binary's metadata, differs from the version of one of its
24+
dependencies. Many parts of Rust binaries are considered unstable. For
25+
instance, the Rust ABI is not stable between compiler versions. This means that
26+
the compiler cannot be sure about *how* to call a function between compiler
27+
versions, and therefore this error occurs.
28+
29+
This error can be fixed by:
30+
* Using [Cargo](../cargo/index.html), the Rust package manager and
31+
[Rustup](https://rust-lang.github.io/rustup/), the Rust toolchain installer,
32+
automatically fixing this issue.
33+
* Recompiling the crates with a uniform `rustc` version.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
The current crate is indistinguishable from one of its dependencies, in terms
2+
of metadata.
3+
4+
Example of erroneous code:
5+
6+
`a.rs`
7+
```ignore (cannot-link-with-other-tests)
8+
#![crate_name = "a"]
9+
#![crate_type = "lib"]
10+
11+
pub fn foo() {}
12+
```
13+
14+
`b.rs`
15+
```ignore (cannot-link-with-other-tests)
16+
#![crate_name = "a"]
17+
#![crate_type = "lib"]
18+
19+
// error: the current crate is indistinguishable from one of its dependencies:
20+
// it has the same crate-name `a` and was compiled with the same
21+
// `-C metadata` arguments. This will result in symbol conflicts between
22+
// the two.
23+
extern crate a;
24+
25+
pub fn foo() {}
26+
27+
fn bar() {
28+
a::foo(); // is this calling the local crate or the dependency?
29+
}
30+
```
31+
32+
The above example compiles two crates with exactly the same name and
33+
`crate_type` (plus any other metadata). This causes an error because it becomes
34+
impossible for the compiler to distinguish between symbols (`pub` item names).
35+
36+
This error can be fixed by:
37+
* Using [Cargo](../cargo/index.html), the Rust package manager, automatically
38+
fixing this issue.
39+
* Recompiling the crate with different metadata (different name/
40+
`crate_type`).

compiler/rustc_errors/src/emitter.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -845,18 +845,34 @@ impl EmitterWriter {
845845
// 3 | |
846846
// 4 | | }
847847
// | |_^ test
848-
if let [ann] = &line.annotations[..] {
848+
let mut buffer_ops = vec![];
849+
let mut annotations = vec![];
850+
let mut short_start = true;
851+
for ann in &line.annotations {
849852
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
850853
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
851854
let style = if ann.is_primary {
852855
Style::UnderlinePrimary
853856
} else {
854857
Style::UnderlineSecondary
855858
};
856-
buffer.putc(line_offset, width_offset + depth - 1, '/', style);
857-
return vec![(depth, style)];
859+
annotations.push((depth, style));
860+
buffer_ops.push((line_offset, width_offset + depth - 1, '/', style));
861+
} else {
862+
short_start = false;
863+
break;
858864
}
865+
} else if let AnnotationType::MultilineLine(_) = ann.annotation_type {
866+
} else {
867+
short_start = false;
868+
break;
869+
}
870+
}
871+
if short_start {
872+
for (y, x, c, s) in buffer_ops {
873+
buffer.putc(y, x, c, s);
859874
}
875+
return annotations;
860876
}
861877

862878
// We want to display like this:

compiler/rustc_parse/src/parser/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2456,7 +2456,7 @@ impl<'a> Parser<'a> {
24562456
}
24572457

24582458
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
2459-
fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> {
2459+
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> {
24602460
let mut first_param = true;
24612461
// Parse the arguments, starting out with `self` being allowed...
24622462
let (mut params, _) = self.parse_paren_comma_seq(|p| {

compiler/rustc_parse/src/parser/ty.rs

+93-2
Original file line numberDiff line numberDiff line change
@@ -933,15 +933,20 @@ impl<'a> Parser<'a> {
933933
has_parens: bool,
934934
modifiers: BoundModifiers,
935935
) -> PResult<'a, GenericBound> {
936-
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
937-
let path = if self.token.is_keyword(kw::Fn)
936+
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
937+
let mut path = if self.token.is_keyword(kw::Fn)
938938
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
939939
&& let Some(path) = self.recover_path_from_fn()
940940
{
941941
path
942942
} else {
943943
self.parse_path(PathStyle::Type)?
944944
};
945+
946+
if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {
947+
self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
948+
}
949+
945950
if has_parens {
946951
if self.token.is_like_plus() {
947952
// Someone has written something like `&dyn (Trait + Other)`. The correct code
@@ -1016,6 +1021,92 @@ impl<'a> Parser<'a> {
10161021
}
10171022
}
10181023

1024+
/// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1025+
/// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1026+
/// been eaten.
1027+
fn recover_fn_trait_with_lifetime_params(
1028+
&mut self,
1029+
fn_path: &mut ast::Path,
1030+
lifetime_defs: &mut Vec<GenericParam>,
1031+
) -> PResult<'a, ()> {
1032+
let fn_path_segment = fn_path.segments.last_mut().unwrap();
1033+
let generic_args = if let Some(p_args) = &fn_path_segment.args {
1034+
p_args.clone().into_inner()
1035+
} else {
1036+
// Normally it wouldn't come here because the upstream should have parsed
1037+
// generic parameters (otherwise it's impossible to call this function).
1038+
return Ok(());
1039+
};
1040+
let lifetimes =
1041+
if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1042+
&generic_args
1043+
{
1044+
args.into_iter()
1045+
.filter_map(|arg| {
1046+
if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1047+
&& let ast::GenericArg::Lifetime(lifetime) = generic_arg {
1048+
Some(lifetime)
1049+
} else {
1050+
None
1051+
}
1052+
})
1053+
.collect()
1054+
} else {
1055+
Vec::new()
1056+
};
1057+
// Only try to recover if the trait has lifetime params.
1058+
if lifetimes.is_empty() {
1059+
return Ok(());
1060+
}
1061+
1062+
// Parse `(T, U) -> R`.
1063+
let inputs_lo = self.token.span;
1064+
let inputs: Vec<_> =
1065+
self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1066+
let inputs_span = inputs_lo.to(self.prev_token.span);
1067+
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1068+
let args = ast::ParenthesizedArgs {
1069+
span: fn_path_segment.span().to(self.prev_token.span),
1070+
inputs,
1071+
inputs_span,
1072+
output,
1073+
}
1074+
.into();
1075+
*fn_path_segment =
1076+
ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID };
1077+
1078+
// Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1079+
let mut generic_params = lifetimes
1080+
.iter()
1081+
.map(|lt| GenericParam {
1082+
id: lt.id,
1083+
ident: lt.ident,
1084+
attrs: ast::AttrVec::new(),
1085+
bounds: Vec::new(),
1086+
is_placeholder: false,
1087+
kind: ast::GenericParamKind::Lifetime,
1088+
colon_span: None,
1089+
})
1090+
.collect::<Vec<GenericParam>>();
1091+
lifetime_defs.append(&mut generic_params);
1092+
1093+
let generic_args_span = generic_args.span();
1094+
let mut err =
1095+
self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
1096+
let snippet = format!(
1097+
"for<{}> ",
1098+
lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1099+
);
1100+
let before_fn_path = fn_path.span.shrink_to_lo();
1101+
err.multipart_suggestion(
1102+
"consider using a higher-ranked trait bound instead",
1103+
vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1104+
Applicability::MaybeIncorrect,
1105+
)
1106+
.emit();
1107+
Ok(())
1108+
}
1109+
10191110
pub(super) fn check_lifetime(&mut self) -> bool {
10201111
self.expected_tokens.push(TokenType::Lifetime);
10211112
self.token.is_lifetime()

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -2692,7 +2692,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
26922692
// Don't print the tuple of capture types
26932693
'print: {
26942694
if !is_upvar_tys_infer_tuple {
2695-
let msg = format!("required because it appears within the type `{}`", ty);
2695+
let msg = with_forced_trimmed_paths!(format!(
2696+
"required because it appears within the type `{ty}`",
2697+
));
26962698
match ty.kind() {
26972699
ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
26982700
Some(ident) => err.span_note(ident.span, &msg),
@@ -2733,7 +2735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
27332735
let mut msg =
27342736
"required because it captures the following types: ".to_owned();
27352737
for ty in bound_tys.skip_binder() {
2736-
write!(msg, "`{}`, ", ty).unwrap();
2738+
with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
27372739
}
27382740
err.note(msg.trim_end_matches(", "))
27392741
}
@@ -2744,7 +2746,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
27442746
let kind = tcx.generator_kind(def_id).unwrap().descr();
27452747
err.span_note(
27462748
sp,
2747-
&format!("required because it's used within this {}", kind),
2749+
with_forced_trimmed_paths!(&format!(
2750+
"required because it's used within this {kind}",
2751+
)),
27482752
)
27492753
}
27502754
ty::Closure(def_id, _) => err.span_note(
@@ -2968,7 +2972,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29682972
let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
29692973
err.span_label(
29702974
expr_span,
2971-
format!("return type was inferred to be `{expr_ty}` here"),
2975+
with_forced_trimmed_paths!(format!(
2976+
"return type was inferred to be `{expr_ty}` here",
2977+
)),
29722978
);
29732979
}
29742980
}

src/bootstrap/doc.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,11 @@ impl Step for Std {
506506
// Look for library/std, library/core etc in the `x.py doc` arguments and
507507
// open the corresponding rendered docs.
508508
for requested_crate in requested_crates {
509-
if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) {
509+
if requested_crate == "library" {
510+
// For `x.py doc library --open`, open `std` by default.
511+
let index = out.join("std").join("index.html");
512+
builder.open_in_browser(index);
513+
} else if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
510514
let index = out.join(requested_crate).join("index.html");
511515
builder.open_in_browser(index);
512516
}

src/bootstrap/format.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ fn update_rustfmt_version(build: &Builder<'_>) {
7474
t!(std::fs::write(stamp_file, version))
7575
}
7676

77-
/// Returns the files modified between the `merge-base` of HEAD and
77+
/// Returns the Rust files modified between the `merge-base` of HEAD and
7878
/// rust-lang/master and what is now on the disk.
7979
///
8080
/// Returns `None` if all files should be formatted.
81-
fn get_modified_files(build: &Builder<'_>) -> Option<Vec<String>> {
81+
fn get_modified_rs_files(build: &Builder<'_>) -> Option<Vec<String>> {
8282
let Ok(remote) = get_rust_lang_rust_remote() else {return None;};
8383
if !verify_rustfmt_version(build) {
8484
return None;
@@ -95,6 +95,7 @@ fn get_modified_files(build: &Builder<'_>) -> Option<Vec<String>> {
9595
)
9696
.lines()
9797
.map(|s| s.trim().to_owned())
98+
.filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs"))
9899
.collect(),
99100
)
100101
}
@@ -195,7 +196,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
195196
ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
196197
}
197198
if !check && paths.is_empty() {
198-
if let Some(files) = get_modified_files(build) {
199+
if let Some(files) = get_modified_rs_files(build) {
199200
for file in files {
200201
println!("formatting modified file {file}");
201202
ignore_fmt.add(&format!("/{file}")).expect(&file);

src/librustdoc/clean/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1740,7 +1740,7 @@ impl Type {
17401740
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
17411741
let t: PrimitiveType = match *self {
17421742
Type::Path { ref path } => return Some(path.def_id()),
1743-
DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1743+
DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()),
17441744
Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
17451745
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
17461746
BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),

src/librustdoc/html/render/search_index.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option<RenderTypeId> {
322322
match *clean_type {
323323
clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())),
324324
clean::DynTrait(ref bounds, _) => {
325-
let path = &bounds[0].trait_;
326-
Some(RenderTypeId::DefId(path.def_id()))
325+
bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id()))
327326
}
328327
clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
329328
clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => {

src/librustdoc/html/static/css/rustdoc.css

+3-5
Original file line numberDiff line numberDiff line change
@@ -1317,15 +1317,11 @@ a.test-arrow:hover {
13171317
-webkit-appearance: none;
13181318
opacity: 1;
13191319
}
1320+
13201321
#settings-menu, #help-button {
13211322
margin-left: 4px;
13221323
display: flex;
13231324
}
1324-
1325-
#settings-menu > a, #help-button > a, #copy-path {
1326-
width: 33px;
1327-
}
1328-
13291325
#settings-menu > a, #help-button > a {
13301326
display: flex;
13311327
align-items: center;
@@ -1337,6 +1333,7 @@ a.test-arrow:hover {
13371333
/* Rare exception to specifying font sizes in rem. Since this is acting
13381334
as an icon, it's okay to specify their sizes in pixels. */
13391335
font-size: 20px;
1336+
width: 33px;
13401337
}
13411338

13421339
#settings-menu > a:hover, #settings-menu > a:focus,
@@ -1352,6 +1349,7 @@ a.test-arrow:hover {
13521349
padding: 0;
13531350
padding-left: 2px;
13541351
border: 0;
1352+
width: 33px;
13551353
}
13561354
#copy-path > img {
13571355
filter: var(--copy-path-img-filter);

0 commit comments

Comments
 (0)