Auto merge of #104481 - matthiaskrgr:rollup-hf8rev0, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #103484 (Add `rust` to `let_underscore_lock` example)
 - #103489 (Make `pointer::byte_offset_from` more generic)
 - #104193 (Shift no characters when using raw string literals)
 - #104348 (Respect visibility & stability of inherent associated types)
 - #104401 (avoid memory leak in mpsc test)
 - #104419 (Fix test/ui/issues/issue-30490.rs)
 - #104424 (rustdoc: remove no-op CSS `.popover { font-size: 1rem }`)
 - #104425 (rustdoc: remove no-op CSS `.main-header { justify-content }`)
 - #104450 (Fuchsia test suite script fix)
 - #104471 (Update PROBLEMATIC_CONSTS in style.rs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-11-16 10:27:24 +00:00
commit 63c748ee23
25 changed files with 291 additions and 155 deletions

View file

@ -1917,17 +1917,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// see if we can satisfy using an inherent associated type
for impl_ in tcx.inherent_impls(adt_def.did()) {
let assoc_ty = tcx.associated_items(impl_).find_by_name_and_kind(
tcx,
assoc_ident,
ty::AssocKind::Type,
*impl_,
);
if let Some(assoc_ty) = assoc_ty {
let ty = tcx.type_of(assoc_ty.def_id);
return Ok((ty, DefKind::AssocTy, assoc_ty.def_id));
}
for &impl_ in tcx.inherent_impls(adt_def.did()) {
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
continue;
};
// FIXME(inherent_associated_types): This does not substitute parameters.
let ty = tcx.type_of(assoc_ty_did);
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
}
}
@ -2014,37 +2010,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
let trait_did = bound.def_id();
let (assoc_ident, def_scope) =
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
// of calling `filter_by_name_and_kind`.
let item = tcx.associated_items(trait_did).in_definition_order().find(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
});
// Assume that if it's not matched, there must be a const defined with the same name
// but it was used in a type position.
let Some(item) = item else {
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) else {
// Assume that if it's not matched, there must be a const defined with the same name
// but it was used in a type position.
let msg = format!("found associated const `{assoc_ident}` when type was expected");
let guar = tcx.sess.struct_span_err(span, &msg).emit();
return Err(guar);
};
let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
let ty = self.normalize_ty(span, ty);
let kind = DefKind::AssocTy;
if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
let kind = kind.descr(item.def_id);
let msg = format!("{} `{}` is private", kind, assoc_ident);
tcx.sess
.struct_span_err(span, &msg)
.span_label(span, &format!("private {}", kind))
.emit();
}
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
if let Some(variant_def_id) = variant_resolution {
tcx.struct_span_lint_hir(
AMBIGUOUS_ASSOCIATED_ITEMS,
@ -2063,7 +2039,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
could_refer_to(DefKind::Variant, variant_def_id, "");
could_refer_to(kind, item.def_id, " also");
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
lint.span_suggestion(
span,
@ -2076,7 +2052,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
},
);
}
Ok((ty, kind, item.def_id))
Ok((ty, DefKind::AssocTy, assoc_ty_did))
}
fn lookup_assoc_ty(
&self,
ident: Ident,
block: hir::HirId,
span: Span,
scope: DefId,
) -> Option<DefId> {
let tcx = self.tcx();
let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block);
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
// of calling `find_by_name_and_kind`.
let item = tcx.associated_items(scope).in_definition_order().find(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == ident
})?;
let kind = DefKind::AssocTy;
if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
let kind = kind.descr(item.def_id);
let msg = format!("{kind} `{ident}` is private");
let def_span = self.tcx().def_span(item.def_id);
tcx.sess
.struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
.span_label(span, &format!("private {kind}"))
.span_label(def_span, &format!("{kind} defined here"))
.emit();
}
tcx.check_stability(item.def_id, Some(block), span, None);
Some(item.def_id)
}
fn qpath_to_ty(

View file

@ -57,7 +57,7 @@ declare_lint! {
/// of at end of scope, which is typically incorrect.
///
/// ### Example
/// ```compile_fail
/// ```rust,compile_fail
/// use std::sync::{Arc, Mutex};
/// use std::thread;
/// let data = Arc::new(Mutex::new(0));

View file

@ -26,19 +26,23 @@ declare_lint! {
///
/// ### Example
///
/// ```
/// ```rust
/// trait Duh {}
///
/// impl Duh for i32 {}
///
/// trait Trait {
/// type Assoc: Send;
/// type Assoc: Duh;
/// }
///
/// struct Struct;
///
/// impl Trait for Struct {
/// type Assoc = i32;
/// impl<F: Duh> Trait for F {
/// type Assoc = F;
/// }
///
/// fn test() -> impl Trait<Assoc = impl Sized> {
/// Struct
/// 42
/// }
/// ```
///

View file

@ -605,7 +605,7 @@ declare_lint! {
///
/// ### Example
///
/// ```
/// ```rust
/// #[warn(unused_tuple_struct_fields)]
/// struct S(i32, i32, i32);
/// let s = S(1, 2, 3);
@ -1154,7 +1154,7 @@ declare_lint! {
///
/// ### Example
///
/// ```compile_fail
/// ```rust,compile_fail
/// #[repr(packed)]
/// pub struct Foo {
/// field1: u64,
@ -2548,7 +2548,7 @@ declare_lint! {
///
/// ### Example
///
/// ```compile_fail
/// ```rust,compile_fail
/// # #![allow(unused)]
/// enum E {
/// A,
@ -3918,7 +3918,7 @@ declare_lint! {
///
/// ### Example
///
/// ```
/// ```rust
/// #![allow(test_unstable_lint)]
/// ```
///

View file

@ -818,96 +818,94 @@ fn find_skips_from_snippet(
_ => return (vec![], false),
};
fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> {
let mut s = snippet.char_indices();
let mut skips = vec![];
while let Some((pos, c)) = s.next() {
match (c, s.clone().next()) {
// skip whitespace and empty lines ending in '\\'
('\\', Some((next_pos, '\n'))) if !is_raw => {
skips.push(pos);
skips.push(next_pos);
let _ = s.next();
while let Some((pos, c)) = s.clone().next() {
if matches!(c, ' ' | '\n' | '\t') {
skips.push(pos);
let _ = s.next();
} else {
break;
}
}
}
('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
skips.push(next_pos);
let _ = s.next();
}
('\\', Some((_, 'x'))) if !is_raw => {
for _ in 0..3 {
// consume `\xAB` literal
if let Some((pos, _)) = s.next() {
skips.push(pos);
} else {
break;
}
}
}
('\\', Some((_, 'u'))) if !is_raw => {
if let Some((pos, _)) = s.next() {
skips.push(pos);
}
if let Some((next_pos, next_c)) = s.next() {
if next_c == '{' {
// consume up to 6 hexanumeric chars
let digits_len =
s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
let len_utf8 = s
.as_str()
.get(..digits_len)
.and_then(|digits| u32::from_str_radix(digits, 16).ok())
.and_then(char::from_u32)
.map_or(1, char::len_utf8);
// Skip the digits, for chars that encode to more than 1 utf-8 byte
// exclude as many digits as it is greater than 1 byte
//
// So for a 3 byte character, exclude 2 digits
let required_skips =
digits_len.saturating_sub(len_utf8.saturating_sub(1));
// skip '{' and '}' also
for pos in (next_pos..).take(required_skips + 2) {
skips.push(pos)
}
s.nth(digits_len);
} else if next_c.is_digit(16) {
skips.push(next_pos);
// We suggest adding `{` and `}` when appropriate, accept it here as if
// it were correct
let mut i = 0; // consume up to 6 hexanumeric chars
while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
if c.is_digit(16) {
skips.push(next_pos);
} else {
break;
}
i += 1;
}
}
}
}
_ => {}
}
}
skips
if str_style.is_some() {
return (vec![], true);
}
let r_start = str_style.map_or(0, |r| r + 1);
let r_end = str_style.unwrap_or(0);
let s = &snippet[r_start + 1..snippet.len() - r_end - 1];
(find_skips(s, str_style.is_some()), true)
let snippet = &snippet[1..snippet.len() - 1];
let mut s = snippet.char_indices();
let mut skips = vec![];
while let Some((pos, c)) = s.next() {
match (c, s.clone().next()) {
// skip whitespace and empty lines ending in '\\'
('\\', Some((next_pos, '\n'))) => {
skips.push(pos);
skips.push(next_pos);
let _ = s.next();
while let Some((pos, c)) = s.clone().next() {
if matches!(c, ' ' | '\n' | '\t') {
skips.push(pos);
let _ = s.next();
} else {
break;
}
}
}
('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
skips.push(next_pos);
let _ = s.next();
}
('\\', Some((_, 'x'))) => {
for _ in 0..3 {
// consume `\xAB` literal
if let Some((pos, _)) = s.next() {
skips.push(pos);
} else {
break;
}
}
}
('\\', Some((_, 'u'))) => {
if let Some((pos, _)) = s.next() {
skips.push(pos);
}
if let Some((next_pos, next_c)) = s.next() {
if next_c == '{' {
// consume up to 6 hexanumeric chars
let digits_len =
s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
let len_utf8 = s
.as_str()
.get(..digits_len)
.and_then(|digits| u32::from_str_radix(digits, 16).ok())
.and_then(char::from_u32)
.map_or(1, char::len_utf8);
// Skip the digits, for chars that encode to more than 1 utf-8 byte
// exclude as many digits as it is greater than 1 byte
//
// So for a 3 byte character, exclude 2 digits
let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1));
// skip '{' and '}' also
for pos in (next_pos..).take(required_skips + 2) {
skips.push(pos)
}
s.nth(digits_len);
} else if next_c.is_digit(16) {
skips.push(next_pos);
// We suggest adding `{` and `}` when appropriate, accept it here as if
// it were correct
let mut i = 0; // consume up to 6 hexanumeric chars
while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
if c.is_digit(16) {
skips.push(next_pos);
} else {
break;
}
i += 1;
}
}
}
}
_ => {}
}
}
(skips, true)
}
#[cfg(test)]

View file

@ -709,7 +709,7 @@ impl<T: ?Sized> *const T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize {
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: *const U) -> isize {
// SAFETY: the caller must uphold the safety contract for `offset_from`.
unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
}

View file

@ -889,7 +889,7 @@ impl<T: ?Sized> *mut T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset_from(self, origin: *const T) -> isize {
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: *const U) -> isize {
// SAFETY: the caller must uphold the safety contract for `offset_from`.
unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
}

View file

@ -713,10 +713,11 @@ fn issue_39364() {
let t = thread::spawn(move || {
thread::sleep(Duration::from_millis(300));
let _ = tx.clone();
crate::mem::forget(tx);
// Don't drop; hand back to caller.
tx
});
let _ = rx.recv_timeout(Duration::from_millis(500));
t.join().unwrap();
let _tx = t.join().unwrap(); // delay dropping until end of test
let _ = rx.recv_timeout(Duration::from_millis(500));
}

View file

@ -675,12 +675,18 @@ run the tests on our emulator. To run the full `src/test/ui` test suite:
test src/test/ui \
--target x86_64-fuchsia \
--run=always --jobs 1 \
--test-args --target-rustcflags -L \
--test-args --target-rustcflags ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \
--test-args --target-rustcflags -L \
--test-args --target-rustcflags ${SDK_PATH}/arch/{x64|arm64}/lib \
--test-args --target-rustcflags -Cpanic=abort \
--test-args --target-rustcflags -Zpanic_abort_tests \
--test-args --target-rustcflags \
--test-args -L \
--test-args --target-rustcflags \
--test-args ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \
--test-args --target-rustcflags \
--test-args -L \
--test-args --target-rustcflags \
--test-args ${SDK_PATH}/arch/{x64|arm64}/lib \
--test-args --target-rustcflags \
--test-args -Cpanic=abort \
--test-args --target-rustcflags \
--test-args -Zpanic_abort_tests \
--test-args --remote-test-client \
--test-args src/ci/docker/scripts/fuchsia-test-runner.py \
)

View file

@ -159,7 +159,6 @@ h1.fqn {
.main-heading {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding-bottom: 6px;
margin-bottom: 15px;
}
@ -920,7 +919,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
}
.popover {
font-size: 1rem;
position: absolute;
right: 0;
z-index: 2;
@ -928,7 +926,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
margin-top: 7px;
border-radius: 3px;
border: 1px solid var(--border-color);
font-size: 1rem;
--popover-arrow-offset: 11px;
}

View file

@ -3,6 +3,7 @@ goto: "file://" + |DOC_PATH| + "/help.html"
size: (1000, 1000) // Try desktop size first.
wait-for: "#help"
assert-css: ("#help", {"display": "block"})
assert-css: ("#help dd", {"font-size": "16px"})
click: "#help-button > a"
assert-css: ("#help", {"display": "block"})
compare-elements-property: (".sub", "#help", ["offsetWidth"])
@ -18,6 +19,7 @@ size: (1000, 1000) // Only supported on desktop.
assert-false: "#help"
click: "#help-button > a"
assert-css: ("#help", {"display": "block"})
assert-css: ("#help dd", {"font-size": "16px"})
click: "#help-button > a"
assert-css: ("#help", {"display": "none"})
compare-elements-property-false: (".sub", "#help", ["offsetWidth"])

View file

@ -41,3 +41,20 @@ goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLon
store-property: (scrollWidth, ".mobile-topbar h2", "scrollWidth")
assert-property: (".mobile-topbar h2", {"clientWidth": |scrollWidth|})
assert-css: (".mobile-topbar h2", {"overflow-x": "hidden"})
// Check wrapping for top main-heading h1 and out-of-band.
// On desktop, they wrap when too big.
size: (1100, 800)
goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
goto: "file://" + |DOC_PATH| + "/lib2/index.html"
compare-elements-position: (".main-heading h1", ".main-heading .out-of-band", ("y"))
// make sure there is a gap between them
compare-elements-position-near-false: (".main-heading h1", ".main-heading .out-of-band", {"x": 550})
// On mobile, they always wrap.
size: (600, 600)
goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
goto: "file://" + |DOC_PATH| + "/lib2/index.html"
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))

View file

@ -0,0 +1,23 @@
#![feature(inherent_associated_types)]
#![allow(incomplete_features)]
mod m {
pub struct T;
impl T {
type P = ();
}
}
type U = m::T::P; //~ ERROR associated type `P` is private
mod n {
pub mod n {
pub struct T;
impl T {
pub(super) type P = bool;
}
}
type U = n::T::P;
}
type V = n::n::T::P; //~ ERROR associated type `P` is private
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0624]: associated type `P` is private
--> $DIR/assoc-inherent-private.rs:10:10
|
LL | type P = ();
| ------ associated type defined here
...
LL | type U = m::T::P;
| ^^^^^^^ private associated type
error[E0624]: associated type `P` is private
--> $DIR/assoc-inherent-private.rs:21:10
|
LL | pub(super) type P = bool;
| ----------------- associated type defined here
...
LL | type V = n::n::T::P;
| ^^^^^^^^^^ private associated type
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0624`.

View file

@ -0,0 +1,6 @@
// aux-crate:aux=assoc-inherent-unstable.rs
// edition: 2021
type Data = aux::Owner::Data; //~ ERROR use of unstable library feature 'data'
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0658]: use of unstable library feature 'data'
--> $DIR/assoc-inherent-unstable.rs:4:13
|
LL | type Data = aux::Owner::Data;
| ^^^^^^^^^^^^^^^^
|
= help: add `#![feature(data)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,11 @@
#![feature(staged_api)]
#![feature(inherent_associated_types)]
#![stable(feature = "main", since = "1.0.0")]
#[stable(feature = "main", since = "1.0.0")]
pub struct Owner;
impl Owner {
#[unstable(feature = "data", issue = "none")]
pub type Data = ();
}

View file

@ -0,0 +1,3 @@
fn main() {
println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); //~ ERROR invalid format string: unmatched `}` found
}

View file

@ -0,0 +1,10 @@
error: invalid format string: unmatched `}` found
--> $DIR/format-raw-string-error.rs:2:45
|
LL | println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#);
| ^ unmatched `}` in format string
|
= note: if you intended to print `}`, you can escape it using `}}`
error: aborting due to previous error

View file

@ -0,0 +1,6 @@
fn main() {
println!(
r#"
\"\'}、"# //~ ERROR invalid format string: unmatched `}` found
);
}

View file

@ -0,0 +1,10 @@
error: invalid format string: unmatched `}` found
--> $DIR/issue-104142.rs:4:9
|
LL | \"\'}、"#
| ^ unmatched `}` in format string
|
= note: if you intended to print `}`, you can escape it using `}}`
error: aborting due to previous error

View file

@ -10,7 +10,7 @@
// This test checks to avoid that regression.
#![cfg_attr(unix, feature(rustc_private))]
#![cfg_attr(windows, allow(unused_imports))]
#![cfg_attr(not(unix), allow(unused_imports))]
#[cfg(unix)]
extern crate libc;

View file

@ -162,9 +162,12 @@ error[E0223]: ambiguous associated type
LL | let _: S::C;
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
error: associated type `A` is private
error[E0624]: associated type `A` is private
--> $DIR/item-privacy.rs:119:12
|
LL | type A = u8;
| ------ associated type defined here
...
LL | let _: T::A;
| ^^^^ private associated type

View file

@ -37,10 +37,8 @@ impl Lint {
}
fn is_ignored(&self) -> bool {
self.doc
.iter()
.filter(|line| line.starts_with("```rust"))
.all(|line| line.contains(",ignore"))
let blocks: Vec<_> = self.doc.iter().filter(|line| line.starts_with("```rust")).collect();
!blocks.is_empty() && blocks.iter().all(|line| line.contains(",ignore"))
}
/// Checks the doc style of the lint.

View file

@ -60,7 +60,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
// Intentionally written in decimal rather than hex
const PROBLEMATIC_CONSTS: &[u32] = &[
184594741, 2880289470, 2881141438, 2965027518, 2976579765, 3203381950, 3405691582, 3405697037,
3735927486, 4027431614, 4276992702,
3735927486, 3735932941, 4027431614, 4276992702,
];
/// Parser states for `line_is_url`.