Skip to content

Commit 5bc82c0

Browse files
committed
Auto merge of rust-lang#98152 - JohnTitor:rollup-osr17j6, r=JohnTitor
Rollup of 7 pull requests Successful merges: - rust-lang#97202 (os str capacity documentation) - rust-lang#97964 (Fix suggestions for `&a: T` parameters) - rust-lang#98053 (Fix generic impl rustdoc json output) - rust-lang#98059 (Inline `const_eval_select`) - rust-lang#98092 (Fix sidebar items expand collapse) - rust-lang#98119 (Refactor path segment parameter error) - rust-lang#98135 (Add regression test for rust-lang#93775) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents b31f9cc + 4ab704e commit 5bc82c0

26 files changed

+697
-143
lines changed

compiler/rustc_ast_lowering/src/path.rs

+26-19
Original file line numberDiff line numberDiff line change
@@ -196,25 +196,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
196196
ParenthesizedGenericArgs::Err => {
197197
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
198198
err.span_label(data.span, "only `Fn` traits may use parentheses");
199-
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
200-
// Do not suggest going from `Trait()` to `Trait<>`
201-
if !data.inputs.is_empty() {
202-
// Suggest replacing `(` and `)` with `<` and `>`
203-
// The snippet may be missing the closing `)`, skip that case
204-
if snippet.ends_with(')') {
205-
if let Some(split) = snippet.find('(') {
206-
let trait_name = &snippet[0..split];
207-
let args = &snippet[split + 1..snippet.len() - 1];
208-
err.span_suggestion(
209-
data.span,
210-
"use angle brackets instead",
211-
format!("{}<{}>", trait_name, args),
212-
Applicability::MaybeIncorrect,
213-
);
214-
}
215-
}
216-
}
217-
};
199+
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
200+
if !data.inputs.is_empty() {
201+
// Start of the span to the 1st character of 1st argument
202+
let open_param = data.inputs_span.shrink_to_lo().to(data
203+
.inputs
204+
.first()
205+
.unwrap()
206+
.span
207+
.shrink_to_lo());
208+
// Last character position of last argument to the end of the span
209+
let close_param = data
210+
.inputs
211+
.last()
212+
.unwrap()
213+
.span
214+
.shrink_to_hi()
215+
.to(data.inputs_span.shrink_to_hi());
216+
err.multipart_suggestion(
217+
&format!("use angle brackets instead",),
218+
vec![
219+
(open_param, String::from("<")),
220+
(close_param, String::from(">")),
221+
],
222+
Applicability::MaybeIncorrect,
223+
);
224+
}
218225
err.emit();
219226
(
220227
self.lower_angle_bracketed_parameter_data(

compiler/rustc_typeck/src/check/pat.rs

+31-28
Original file line numberDiff line numberDiff line change
@@ -649,39 +649,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
649649
}
650650
}
651651

652-
fn borrow_pat_suggestion(
653-
&self,
654-
err: &mut Diagnostic,
655-
pat: &Pat<'_>,
656-
inner: &Pat<'_>,
657-
expected: Ty<'tcx>,
658-
) {
652+
// Precondition: pat is a Ref(_) pattern
653+
fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) {
659654
let tcx = self.tcx;
660-
if let PatKind::Binding(..) = inner.kind {
655+
if let PatKind::Ref(inner, mutbl) = pat.kind
656+
&& let PatKind::Binding(_, _, binding, ..) = inner.kind {
661657
let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
662658
let binding_parent = tcx.hir().get(binding_parent_id);
663-
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
659+
debug!(?inner, ?pat, ?binding_parent);
660+
661+
let mutability = match mutbl {
662+
ast::Mutability::Mut => "mut",
663+
ast::Mutability::Not => "",
664+
};
665+
664666
match binding_parent {
665-
hir::Node::Param(hir::Param { span, .. })
666-
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) =>
667-
{
668-
err.span_suggestion(
669-
*span,
670-
&format!("did you mean `{snippet}`"),
671-
format!(" &{expected}"),
672-
Applicability::MachineApplicable,
667+
// Check that there is explicit type (ie this is not a closure param with inferred type)
668+
// so we don't suggest moving something to the type that does not exist
669+
hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => {
670+
err.multipart_suggestion_verbose(
671+
format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
672+
vec![
673+
(pat.span.until(inner.span), "".to_owned()),
674+
(ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())),
675+
],
676+
Applicability::MachineApplicable
673677
);
674678
}
675-
hir::Node::Arm(_) | hir::Node::Pat(_) => {
679+
hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
676680
// rely on match ergonomics or it might be nested `&&pat`
677-
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
678-
err.span_suggestion(
679-
pat.span,
680-
"you can probably remove the explicit borrow",
681-
snippet,
682-
Applicability::MaybeIncorrect,
683-
);
684-
}
681+
err.span_suggestion_verbose(
682+
pat.span.until(inner.span),
683+
format!("consider removing `&{mutability}` from the pattern"),
684+
"",
685+
Applicability::MaybeIncorrect,
686+
);
685687
}
686688
_ => {} // don't provide suggestions in other cases #55175
687689
}
@@ -1836,6 +1838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18361838
box_ty
18371839
}
18381840

1841+
// Precondition: Pat is Ref(inner)
18391842
fn check_pat_ref(
18401843
&self,
18411844
pat: &'tcx Pat<'tcx>,
@@ -1853,7 +1856,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18531856

18541857
// Take region, inner-type from expected type if we can,
18551858
// to avoid creating needless variables. This also helps with
1856-
// the bad interactions of the given hack detailed in (note_1).
1859+
// the bad interactions of the given hack detailed in (note_1).
18571860
debug!("check_pat_ref: expected={:?}", expected);
18581861
match *expected.kind() {
18591862
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
@@ -1869,7 +1872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18691872
// Look for a case like `fn foo(&foo: u32)` and suggest
18701873
// `fn foo(foo: &u32)`
18711874
if let Some(mut err) = err {
1872-
self.borrow_pat_suggestion(&mut err, pat, inner, expected);
1875+
self.borrow_pat_suggestion(&mut err, pat);
18731876
err.emit();
18741877
}
18751878
(rptr_ty, inner_ty)

library/core/src/intrinsics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2363,6 +2363,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
23632363
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
23642364
#[lang = "const_eval_select"]
23652365
#[rustc_do_not_const_check]
2366+
#[inline]
23662367
pub const unsafe fn const_eval_select<ARG, F, G, RET>(
23672368
arg: ARG,
23682369
_called_in_const: F,

library/std/src/ffi/os_str.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
4545
/// values, encoded in a less-strict variant of UTF-8. This is useful to
4646
/// understand when handling capacity and length values.
4747
///
48+
/// # Capacity of `OsString`
49+
///
50+
/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
51+
/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
52+
/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
53+
/// ```
54+
/// use std::ffi::{OsStr, OsString};
55+
///
56+
/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
57+
/// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
58+
/// ret.push(a); // This will not allocate further
59+
/// ret.push(b); // This will not allocate further
60+
/// ret
61+
/// }
62+
/// ```
63+
///
4864
/// # Creating an `OsString`
4965
///
5066
/// **From a Rust string**: `OsString` implements
@@ -186,7 +202,7 @@ impl OsString {
186202
/// OS strings without reallocating. If `capacity` is 0, the string will not
187203
/// allocate.
188204
///
189-
/// See main `OsString` documentation information about encoding.
205+
/// See the main `OsString` documentation information about encoding and capacity units.
190206
///
191207
/// # Examples
192208
///
@@ -229,7 +245,7 @@ impl OsString {
229245

230246
/// Returns the capacity this `OsString` can hold without reallocating.
231247
///
232-
/// See `OsString` introduction for information about encoding.
248+
/// See the main `OsString` documentation information about encoding and capacity units.
233249
///
234250
/// # Examples
235251
///
@@ -251,6 +267,8 @@ impl OsString {
251267
///
252268
/// The collection may reserve more space to avoid frequent reallocations.
253269
///
270+
/// See the main `OsString` documentation information about encoding and capacity units.
271+
///
254272
/// # Examples
255273
///
256274
/// ```
@@ -272,6 +290,8 @@ impl OsString {
272290
/// greater than or equal to `self.len() + additional`. Does nothing if
273291
/// capacity is already sufficient.
274292
///
293+
/// See the main `OsString` documentation information about encoding and capacity units.
294+
///
275295
/// # Errors
276296
///
277297
/// If the capacity overflows, or the allocator reports a failure, then an error
@@ -313,6 +333,8 @@ impl OsString {
313333
///
314334
/// [`reserve`]: OsString::reserve
315335
///
336+
/// See the main `OsString` documentation information about encoding and capacity units.
337+
///
316338
/// # Examples
317339
///
318340
/// ```
@@ -340,6 +362,8 @@ impl OsString {
340362
///
341363
/// [`try_reserve`]: OsString::try_reserve
342364
///
365+
/// See the main `OsString` documentation information about encoding and capacity units.
366+
///
343367
/// # Errors
344368
///
345369
/// If the capacity overflows, or the allocator reports a failure, then an error
@@ -373,6 +397,8 @@ impl OsString {
373397

374398
/// Shrinks the capacity of the `OsString` to match its length.
375399
///
400+
/// See the main `OsString` documentation information about encoding and capacity units.
401+
///
376402
/// # Examples
377403
///
378404
/// ```
@@ -399,6 +425,8 @@ impl OsString {
399425
///
400426
/// If the current capacity is less than the lower limit, this is a no-op.
401427
///
428+
/// See the main `OsString` documentation information about encoding and capacity units.
429+
///
402430
/// # Examples
403431
///
404432
/// ```
@@ -773,6 +801,8 @@ impl OsStr {
773801
/// This number is simply useful for passing to other methods, like
774802
/// [`OsString::with_capacity`] to avoid reallocations.
775803
///
804+
/// See the main `OsString` documentation information about encoding and capacity units.
805+
///
776806
/// # Examples
777807
///
778808
/// ```

src/librustdoc/html/static/js/source-script.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
3232
fullPath += elem["name"] + "/";
3333

3434
name.onclick = () => {
35-
if (hasClass(this, "expand")) {
36-
removeClass(this, "expand");
35+
if (hasClass(name, "expand")) {
36+
removeClass(name, "expand");
3737
} else {
38-
addClass(this, "expand");
38+
addClass(name, "expand");
3939
}
4040
};
4141
name.innerText = elem["name"];

src/librustdoc/json/mod.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,44 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
181181
let name = item.name;
182182
let item_id = item.item_id;
183183
if let Some(mut new_item) = self.convert_item(item) {
184-
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
185-
t.implementations = self.get_trait_implementors(item_id.expect_def_id())
186-
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
187-
s.impls = self.get_impls(item_id.expect_def_id())
188-
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
189-
e.impls = self.get_impls(item_id.expect_def_id())
190-
} else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
191-
u.impls = self.get_impls(item_id.expect_def_id())
192-
}
184+
let can_be_ignored = match new_item.inner {
185+
types::ItemEnum::Trait(ref mut t) => {
186+
t.implementations = self.get_trait_implementors(item_id.expect_def_id());
187+
false
188+
}
189+
types::ItemEnum::Struct(ref mut s) => {
190+
s.impls = self.get_impls(item_id.expect_def_id());
191+
false
192+
}
193+
types::ItemEnum::Enum(ref mut e) => {
194+
e.impls = self.get_impls(item_id.expect_def_id());
195+
false
196+
}
197+
types::ItemEnum::Union(ref mut u) => {
198+
u.impls = self.get_impls(item_id.expect_def_id());
199+
false
200+
}
201+
202+
types::ItemEnum::Method(_)
203+
| types::ItemEnum::AssocConst { .. }
204+
| types::ItemEnum::AssocType { .. } => true,
205+
types::ItemEnum::Module(_)
206+
| types::ItemEnum::ExternCrate { .. }
207+
| types::ItemEnum::Import(_)
208+
| types::ItemEnum::StructField(_)
209+
| types::ItemEnum::Variant(_)
210+
| types::ItemEnum::Function(_)
211+
| types::ItemEnum::TraitAlias(_)
212+
| types::ItemEnum::Impl(_)
213+
| types::ItemEnum::Typedef(_)
214+
| types::ItemEnum::OpaqueTy(_)
215+
| types::ItemEnum::Constant(_)
216+
| types::ItemEnum::Static(_)
217+
| types::ItemEnum::ForeignType
218+
| types::ItemEnum::Macro(_)
219+
| types::ItemEnum::ProcMacro(_)
220+
| types::ItemEnum::PrimitiveType(_) => false,
221+
};
193222
let removed = self
194223
.index
195224
.borrow_mut()
@@ -199,7 +228,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
199228
// to make sure the items are unique. The main place this happens is when an item, is
200229
// reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
201230
if let Some(old_item) = removed {
202-
assert_eq!(old_item, new_item);
231+
// In case of generic implementations (like `impl<T> Trait for T {}`), all the
232+
// inner items will be duplicated so we can ignore if they are slightly different.
233+
if !can_be_ignored {
234+
assert_eq!(old_item, new_item);
235+
}
203236
}
204237
}
205238

src/test/rustdoc-gui/source-code-page.goml

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Checks that the interactions with the source code pages are workined as expected.
1+
// Checks that the interactions with the source code pages are working as expected.
22
goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
33
// Check that we can click on the line number.
44
click: ".line-numbers > span:nth-child(4)" // This is the span for line 4.
@@ -27,3 +27,26 @@ assert-position: ("//*[@id='1']", {"x": 104, "y": 103})
2727
// We click on the left of the "1" span but still in the "line-number" `<pre>`.
2828
click: (103, 103)
2929
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
30+
31+
// Checking the source code sidebar.
32+
33+
// First we "open" it.
34+
click: "#sidebar-toggle"
35+
assert: ".sidebar.expanded"
36+
37+
// We check that the first entry of the sidebar is collapsed (which, for whatever reason,
38+
// is number 2 and not 1...).
39+
assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"})
40+
assert-text: ("#source-sidebar .name:nth-child(2)", "implementors")
41+
// We also check its children are hidden too.
42+
assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"})
43+
// We now click on it.
44+
click: "#source-sidebar .name:nth-child(2)"
45+
assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name expand"})
46+
// Checking that its children are displayed as well.
47+
assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "block"})
48+
49+
// And now we collapse it again.
50+
click: "#source-sidebar .name:nth-child(2)"
51+
assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"})
52+
assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"})

src/test/rustdoc-json/generic_impl.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/97986>.
2+
3+
// @has generic_impl.json
4+
// @has - "$.index[*][?(@.name=='f')]"
5+
// @has - "$.index[*][?(@.name=='AssocTy')]"
6+
// @has - "$.index[*][?(@.name=='AssocConst')]"
7+
8+
pub mod m {
9+
pub struct S;
10+
}
11+
12+
pub trait F {
13+
type AssocTy;
14+
const AssocConst: usize;
15+
fn f() -> m::S;
16+
}
17+
18+
impl<T> F for T {
19+
type AssocTy = u32;
20+
const AssocConst: usize = 0;
21+
fn f() -> m::S {
22+
m::S
23+
}
24+
}

0 commit comments

Comments
 (0)