Skip to content

Commit c934ce9

Browse files
committed
Auto merge of #110024 - matthiaskrgr:rollup-mydkufd, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #109806 (Workaround #109797 on windows-gnu) - #109957 (diagnostics: account for self type when looking for source of unsolved type variable) - #109960 (Fix buffer overrun in bootstrap and (test-only) symlink_junction) - #110013 (Label `non_exhaustive` attribute on privacy errors from non-local items) - #110016 (Run collapsed GUI test in mobile mode as well) - #110022 (fix: fix regression in #109203) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 28a2928 + 903b439 commit c934ce9

File tree

17 files changed

+183
-133
lines changed

17 files changed

+183
-133
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
11911191
have_turbofish,
11921192
} = args;
11931193
let generics = tcx.generics_of(generics_def_id);
1194-
if let Some(argument_index) = generics
1194+
if let Some(mut argument_index) = generics
11951195
.own_substs(substs)
11961196
.iter()
11971197
.position(|&arg| self.generic_arg_contains_target(arg))
11981198
{
1199+
if generics.parent.is_none() && generics.has_self {
1200+
argument_index += 1;
1201+
}
11991202
let substs = self.infcx.resolve_vars_if_possible(substs);
12001203
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
12011204
[generics.own_counts().lifetimes..];

compiler/rustc_parse/src/parser/diagnostics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -423,11 +423,11 @@ impl<'a> Parser<'a> {
423423
if let token::Literal(Lit {
424424
kind: token::LitKind::Integer | token::LitKind::Float,
425425
symbol,
426-
suffix,
426+
suffix: Some(suffix), // no suffix makes it a valid literal
427427
}) = self.token.kind
428428
&& rustc_ast::MetaItemLit::from_token(&self.token).is_none()
429429
{
430-
Some((symbol.as_str().len(), suffix.unwrap()))
430+
Some((symbol.as_str().len(), suffix))
431431
} else {
432432
None
433433
}

compiler/rustc_resolve/src/diagnostics.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1607,7 +1607,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16071607
let mut err =
16081608
struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
16091609
err.span_label(ident.span, &format!("private {}", descr));
1610-
if let Some(span) = ctor_fields_span {
1610+
1611+
let mut non_exhaustive = None;
1612+
// If an ADT is foreign and marked as `non_exhaustive`, then that's
1613+
// probably why we have the privacy error.
1614+
// Otherwise, point out if the struct has any private fields.
1615+
if let Some(def_id) = res.opt_def_id()
1616+
&& !def_id.is_local()
1617+
&& let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
1618+
{
1619+
non_exhaustive = Some(attr.span);
1620+
} else if let Some(span) = ctor_fields_span {
16111621
err.span_label(span, "a constructor is private if any of the fields is private");
16121622
if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
16131623
err.multipart_suggestion_verbose(
@@ -1656,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16561666
if !first && binding.vis.is_public() {
16571667
note_span.push_span_label(def_span, "consider importing it directly");
16581668
}
1669+
// Final step in the import chain, point out if the ADT is `non_exhaustive`
1670+
// which is probably why this privacy violation occurred.
1671+
if next_binding.is_none() && let Some(span) = non_exhaustive {
1672+
note_span.push_span_label(
1673+
span,
1674+
format!("cannot be constructed because it is `#[non_exhaustive]`"),
1675+
);
1676+
}
16591677
err.span_note(note_span, &msg);
16601678
}
16611679

library/std/src/sys/common/thread_local/os_local.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ macro_rules! __thread_local_inner {
4949
#[inline]
5050
fn __init() -> $t { $init }
5151

52-
#[cfg_attr(not(bootstrap), inline)]
52+
// `#[inline] does not work on windows-gnu due to linking errors around dllimports.
53+
// See https://github.com/rust-lang/rust/issues/109797.
54+
#[cfg_attr(not(windows), inline)]
5355
unsafe fn __getit(
5456
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
5557
) -> $crate::option::Option<&'static $t> {

library/std/src/sys/windows/fs.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
14031403
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
14041404
let f = File::open(junction, &opts)?;
14051405
let h = f.as_inner().as_raw_handle();
1406-
14071406
unsafe {
14081407
let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
14091408
let data_ptr = data.0.as_mut_ptr();
1409+
let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
14101410
let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
14111411
// Zero the header to ensure it's fully initialized, including reserved parameters.
14121412
*db = mem::zeroed();
1413-
let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
1414-
let mut i = 0;
1413+
let reparse_target_slice = {
1414+
let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
1415+
// Compute offset in bytes and then divide so that we round down
1416+
// rather than hit any UB (admittedly this arithmetic should work
1417+
// out so that this isn't necessary)
1418+
let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap();
1419+
let buf_len_wchars = buf_len_bytes / core::mem::size_of::<c::WCHAR>();
1420+
core::slice::from_raw_parts_mut(buf_start, buf_len_wchars)
1421+
};
1422+
14151423
// FIXME: this conversion is very hacky
1416-
let v = br"\??\";
1417-
let v = v.iter().map(|x| *x as u16);
1418-
for c in v.chain(original.as_os_str().encode_wide()) {
1419-
*buf.add(i) = c;
1424+
let iter = br"\??\"
1425+
.iter()
1426+
.map(|x| *x as u16)
1427+
.chain(original.as_os_str().encode_wide())
1428+
.chain(core::iter::once(0));
1429+
let mut i = 0;
1430+
for c in iter {
1431+
if i >= reparse_target_slice.len() {
1432+
return Err(crate::io::const_io_error!(
1433+
crate::io::ErrorKind::InvalidFilename,
1434+
"Input filename is too long"
1435+
));
1436+
}
1437+
reparse_target_slice[i] = c;
14201438
i += 1;
14211439
}
1422-
*buf.add(i) = 0;
1423-
i += 1;
14241440
(*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
14251441
(*db).ReparseTargetMaximumLength = (i * 2) as c::WORD;
14261442
(*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD;

src/bootstrap/Cargo.lock

+11
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ dependencies = [
4545
"hex",
4646
"ignore",
4747
"is-terminal",
48+
"junction",
4849
"libc",
4950
"object",
5051
"once_cell",
@@ -349,6 +350,16 @@ version = "1.0.2"
349350
source = "registry+https://github.com/rust-lang/crates.io-index"
350351
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
351352

353+
[[package]]
354+
name = "junction"
355+
version = "1.0.0"
356+
source = "registry+https://github.com/rust-lang/crates.io-index"
357+
checksum = "ca39ef0d69b18e6a2fd14c2f0a1d593200f4a4ed949b240b5917ab51fac754cb"
358+
dependencies = [
359+
"scopeguard",
360+
"winapi",
361+
]
362+
352363
[[package]]
353364
name = "lazy_static"
354365
version = "1.4.0"

src/bootstrap/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ sysinfo = { version = "0.26.0", optional = true }
6161
[target.'cfg(not(target_os = "solaris"))'.dependencies]
6262
fd-lock = "3.0.8"
6363

64+
[target.'cfg(windows)'.dependencies.junction]
65+
version = "1.0.0"
66+
6467
[target.'cfg(windows)'.dependencies.windows]
6568
version = "0.46.0"
6669
features = [

src/bootstrap/util.rs

+1-98
Original file line numberDiff line numberDiff line change
@@ -146,106 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
146146
fs::symlink(src, dest)
147147
}
148148

149-
// Creating a directory junction on windows involves dealing with reparse
150-
// points and the DeviceIoControl function, and this code is a skeleton of
151-
// what can be found here:
152-
//
153-
// http://www.flexhex.com/docs/articles/hard-links.phtml
154149
#[cfg(windows)]
155150
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
156-
use std::ffi::OsStr;
157-
use std::os::windows::ffi::OsStrExt;
158-
159-
use windows::{
160-
core::PCWSTR,
161-
Win32::Foundation::{CloseHandle, HANDLE},
162-
Win32::Storage::FileSystem::{
163-
CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS,
164-
FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
165-
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING,
166-
},
167-
Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT,
168-
Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT},
169-
Win32::System::IO::DeviceIoControl,
170-
};
171-
172-
#[allow(non_snake_case)]
173-
#[repr(C)]
174-
struct REPARSE_MOUNTPOINT_DATA_BUFFER {
175-
ReparseTag: u32,
176-
ReparseDataLength: u32,
177-
Reserved: u16,
178-
ReparseTargetLength: u16,
179-
ReparseTargetMaximumLength: u16,
180-
Reserved1: u16,
181-
ReparseTarget: u16,
182-
}
183-
184-
fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
185-
Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
186-
}
187-
188-
// We're using low-level APIs to create the junction, and these are more
189-
// picky about paths. For example, forward slashes cannot be used as a
190-
// path separator, so we should try to canonicalize the path first.
191-
let target = fs::canonicalize(target)?;
192-
193-
fs::create_dir(junction)?;
194-
195-
let path = to_u16s(junction)?;
196-
197-
let h = unsafe {
198-
CreateFileW(
199-
PCWSTR(path.as_ptr()),
200-
FILE_ACCESS_FLAGS(GENERIC_WRITE),
201-
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
202-
None,
203-
OPEN_EXISTING,
204-
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
205-
HANDLE::default(),
206-
)
207-
}
208-
.map_err(|_| io::Error::last_os_error())?;
209-
210-
unsafe {
211-
#[repr(C, align(8))]
212-
struct Align8<T>(T);
213-
let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
214-
let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
215-
let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16;
216-
let mut i = 0;
217-
// FIXME: this conversion is very hacky
218-
let v = br"\??\";
219-
let v = v.iter().map(|x| *x as u16);
220-
for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
221-
*buf.offset(i) = c;
222-
i += 1;
223-
}
224-
*buf.offset(i) = 0;
225-
i += 1;
226-
227-
(*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
228-
(*db).ReparseTargetMaximumLength = (i * 2) as u16;
229-
(*db).ReparseTargetLength = ((i - 1) * 2) as u16;
230-
(*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32;
231-
232-
let mut ret = 0u32;
233-
DeviceIoControl(
234-
h,
235-
FSCTL_SET_REPARSE_POINT,
236-
Some(db.cast()),
237-
(*db).ReparseDataLength + 8,
238-
None,
239-
0,
240-
Some(&mut ret),
241-
None,
242-
)
243-
.ok()
244-
.map_err(|_| io::Error::last_os_error())?;
245-
}
246-
247-
unsafe { CloseHandle(h) };
248-
Ok(())
151+
junction::create(&target, &junction)
249152
}
250153
}
251154

tests/rustdoc-gui/go-to-collapsed-elem.goml

+26-7
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,32 @@ property: ("#implementations-list .implementors-toggle", {"open": "false"})
99
click: "//*[@class='sidebar']//a[@href='#method.must_use']"
1010
assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
1111

12-
// Now we do the same through search result.
13-
// First we reload the page without the anchor in the URL.
12+
define-function: ("collapsed-from-search", (), block {
13+
// Now we do the same through search result.
14+
// First we reload the page without the anchor in the URL.
15+
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
16+
// Then we collapse the section again...
17+
property: ("#implementations-list .implementors-toggle", {"open": "false"})
18+
// Then we run the search.
19+
write: (".search-input", "foo::must_use")
20+
wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
21+
click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
22+
assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
23+
})
24+
25+
call-function: ("collapsed-from-search", {})
26+
27+
// Now running the same check but with mobile.
28+
size: (600, 600)
1429
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
15-
// Then we collapse the section again...
30+
// We check that the implementors block is expanded.
31+
assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
32+
// We now collapse the implementors block.
1633
property: ("#implementations-list .implementors-toggle", {"open": "false"})
17-
// Then we run the search.
18-
write: (".search-input", "foo::must_use")
19-
wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
20-
click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
34+
// First we expand the mobile menu.
35+
click: ".sidebar-menu-toggle"
36+
// Then we click on the link to the method to ensure it'll expand the implementors block.
37+
click: "//*[@class='sidebar shown']//a[@href='#method.must_use']"
2138
assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
39+
40+
call-function: ("collapsed-from-search", {})

tests/ui/inference/need_type_info/concrete-impl.rs

+3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ struct Two;
77
struct Struct;
88

99
impl Ambiguous<One> for Struct {}
10+
//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found
1011
impl Ambiguous<Two> for Struct {}
1112

1213
fn main() {
1314
<Struct as Ambiguous<_>>::method();
1415
//~^ ERROR type annotations needed
16+
//~| NOTE cannot infer type of the type parameter `A`
1517
//~| ERROR type annotations needed
18+
//~| NOTE infer type of the type parameter `A`
1619
}

tests/ui/inference/need_type_info/concrete-impl.stderr

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
error[E0282]: type annotations needed
2-
--> $DIR/concrete-impl.rs:13:5
2+
--> $DIR/concrete-impl.rs:14:5
33
|
44
LL | <Struct as Ambiguous<_>>::method();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
66

77
error[E0283]: type annotations needed
8-
--> $DIR/concrete-impl.rs:13:5
8+
--> $DIR/concrete-impl.rs:14:5
99
|
1010
LL | <Struct as Ambiguous<_>>::method();
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
1212
|
1313
note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
1414
--> $DIR/concrete-impl.rs:9:1
1515
|
1616
LL | impl Ambiguous<One> for Struct {}
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
LL |
1819
LL | impl Ambiguous<Two> for Struct {}
1920
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2021

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Test that we show the correct type parameter that couldn't be inferred and that we don't
2+
// end up stating nonsense like "type parameter `'a`" which we used to do.
3+
4+
trait Trait<'a, T> {
5+
fn m(self);
6+
}
7+
8+
impl<'a, A> Trait<'a, A> for () {
9+
fn m(self) {}
10+
}
11+
12+
fn qualified() {
13+
<() as Trait<'static, _>>::m(());
14+
//~^ ERROR type annotations needed
15+
//~| NOTE cannot infer type of the type parameter `T`
16+
17+
}
18+
19+
fn unqualified() {
20+
Trait::<'static, _>::m(());
21+
//~^ ERROR type annotations needed
22+
//~| NOTE cannot infer type of the type parameter `T`
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/issue-109905.rs:13:5
3+
|
4+
LL | <() as Trait<'static, _>>::m(());
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
6+
7+
error[E0282]: type annotations needed
8+
--> $DIR/issue-109905.rs:20:5
9+
|
10+
LL | Trait::<'static, _>::m(());
11+
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0282`.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn`2222222222222222222222222222222222222222() {}
2+
//~^ ERROR unknown start of token: `
3+
//~^^ ERROR expected identifier, found `2222222222222222222222222222222222222222`

0 commit comments

Comments
 (0)