Skip to content

Rollup of 6 pull requests #103921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ Language
- [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/)
- [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/)
- [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/)
- [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
- [Add lints `let_underscore_drop` and `let_underscore_lock` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
- [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/)
- [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/).
Usage of `MaybeUninit` is the correct way to work with uninitialized memory.
11 changes: 11 additions & 0 deletions compiler/rustc_data_structures/src/sync.rs
Original file line number Diff line number Diff line change
@@ -410,6 +410,7 @@ impl<T> Lock<T> {

#[cfg(parallel_compiler)]
#[inline(always)]
#[track_caller]
pub fn lock(&self) -> LockGuard<'_, T> {
if ERROR_CHECKING {
self.0.try_lock().expect("lock was already held")
@@ -420,21 +421,25 @@ impl<T> Lock<T> {

#[cfg(not(parallel_compiler))]
#[inline(always)]
#[track_caller]
pub fn lock(&self) -> LockGuard<'_, T> {
self.0.borrow_mut()
}

#[inline(always)]
#[track_caller]
pub fn with_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
f(&mut *self.lock())
}

#[inline(always)]
#[track_caller]
pub fn borrow(&self) -> LockGuard<'_, T> {
self.lock()
}

#[inline(always)]
#[track_caller]
pub fn borrow_mut(&self) -> LockGuard<'_, T> {
self.lock()
}
@@ -476,6 +481,7 @@ impl<T> RwLock<T> {

#[cfg(not(parallel_compiler))]
#[inline(always)]
#[track_caller]
pub fn read(&self) -> ReadGuard<'_, T> {
self.0.borrow()
}
@@ -491,6 +497,7 @@ impl<T> RwLock<T> {
}

#[inline(always)]
#[track_caller]
pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
f(&*self.read())
}
@@ -509,6 +516,7 @@ impl<T> RwLock<T> {

#[cfg(not(parallel_compiler))]
#[inline(always)]
#[track_caller]
pub fn write(&self) -> WriteGuard<'_, T> {
self.0.borrow_mut()
}
@@ -524,16 +532,19 @@ impl<T> RwLock<T> {
}

#[inline(always)]
#[track_caller]
pub fn with_write_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
f(&mut *self.write())
}

#[inline(always)]
#[track_caller]
pub fn borrow(&self) -> ReadGuard<'_, T> {
self.read()
}

#[inline(always)]
#[track_caller]
pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
self.write()
}
2 changes: 0 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -220,7 +220,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Hide the outer diverging and has_errors flags.
let old_diverges = self.diverges.replace(Diverges::Maybe);
let old_has_errors = self.has_errors.replace(false);

let ty = ensure_sufficient_stack(|| match &expr.kind {
hir::ExprKind::Path(
@@ -259,7 +258,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Combine the diverging and has_error flags.
self.diverges.set(self.diverges.get() | old_diverges);
self.has_errors.set(self.has_errors.get() | old_has_errors);

debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id));
debug!("... {:?}, expected is {:?}", ty, expected);
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -143,7 +143,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results.borrow_mut().node_types_mut().insert(id, ty);

if ty.references_error() {
self.has_errors.set(true);
self.set_tainted_by_errors();
}
}
8 changes: 1 addition & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
@@ -1334,7 +1334,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Hide the outer diverging and `has_errors` flags.
let old_diverges = self.diverges.replace(Diverges::Maybe);
let old_has_errors = self.has_errors.replace(false);

match stmt.kind {
hir::StmtKind::Local(l) => {
@@ -1364,7 +1363,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Combine the diverging and `has_error` flags.
self.diverges.set(self.diverges.get() | old_diverges);
self.has_errors.set(self.has_errors.get() | old_has_errors);
}

pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
@@ -1544,11 +1542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.diverges.set(prev_diverges);
}

let mut ty = ctxt.coerce.unwrap().complete(self);

if self.has_errors.get() || ty.references_error() {
ty = self.tcx.ty_error()
}
let ty = ctxt.coerce.unwrap().complete(self);

self.write_ty(blk.hir_id, ty);

4 changes: 0 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
@@ -112,9 +112,6 @@ pub struct FnCtxt<'a, 'tcx> {
/// the diverges flag is set to something other than `Maybe`.
pub(super) diverges: Cell<Diverges>,

/// Whether any child nodes have any type errors.
pub(super) has_errors: Cell<bool>,

pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,

pub(super) inh: &'a Inherited<'tcx>,
@@ -145,7 +142,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
resume_yield_tys: None,
ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
diverges: Cell::new(Diverges::Maybe),
has_errors: Cell::new(false),
enclosing_breakables: RefCell::new(EnclosingBreakables {
stack: Vec::new(),
by_id: Default::default(),
6 changes: 6 additions & 0 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -1865,6 +1865,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::Str
| ty::Projection(_)
| ty::Param(_) => format!("{deref_ty}"),
// we need to test something like <&[_]>::len
// and Vec::function();
// <&[_]>::len doesn't need an extra "<>" between
// but for Adt type like Vec::function()
// we would suggest <[_]>::function();
_ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
_ => format!("<{deref_ty}>"),
};
err.span_suggestion_verbose(
44 changes: 44 additions & 0 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
@@ -753,6 +753,50 @@ impl SourceMap {
}
}

/// Given a 'Span', tries to tell if the next character is '>'
/// and the previous charactoer is '<' after skipping white space
/// return true if wrapped by '<>'
pub fn span_wrapped_by_angle_bracket(&self, span: Span) -> bool {
self.span_to_source(span, |src, start_index, end_index| {
if src.get(start_index..end_index).is_none() {
return Ok(false);
}
// test the right side to match '>' after skipping white space
let end_src = &src[end_index..];
let mut i = 0;
while let Some(cc) = end_src.chars().nth(i) {
if cc == ' ' {
i = i + 1;
} else if cc == '>' {
// found > in the right;
break;
} else {
// failed to find '>' return false immediately
return Ok(false);
}
}
// test the left side to match '<' after skipping white space
i = start_index;
let start_src = &src[0..start_index];
while let Some(cc) = start_src.chars().nth(i) {
if cc == ' ' {
if i == 0 {
return Ok(false);
}
i = i - 1;
} else if cc == '<' {
// found < in the left
break;
} else {
// failed to find '<' return false immediately
return Ok(false);
}
}
return Ok(true);
})
.map_or(false, |is_accessible| is_accessible)
}

/// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
/// `c`.
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
2 changes: 1 addition & 1 deletion compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -413,7 +413,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
/// Check if a function is async.
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
let node = tcx.hir().get_by_def_id(def_id.expect_local());
if let Some(fn_kind) = node.fn_kind() { fn_kind.asyncness() } else { hir::IsAsync::NotAsync }
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
}

/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.
32 changes: 19 additions & 13 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -880,7 +880,7 @@ fn clean_fn_or_proc_macro<'tcx>(
ProcMacroItem(ProcMacro { kind, helpers })
}
None => {
let mut func = clean_function(cx, sig, generics, body_id);
let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
clean_fn_decl_legacy_const_generics(&mut func, attrs);
FunctionItem(func)
}
@@ -917,16 +917,28 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attrib
}
}

enum FunctionArgs<'tcx> {
Body(hir::BodyId),
Names(&'tcx [Ident]),
}

fn clean_function<'tcx>(
cx: &mut DocContext<'tcx>,
sig: &hir::FnSig<'tcx>,
generics: &hir::Generics<'tcx>,
body_id: hir::BodyId,
args: FunctionArgs<'tcx>,
) -> Box<Function> {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
let generics = clean_generics(generics, cx);
let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id);
let args = match args {
FunctionArgs::Body(body_id) => {
clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id)
}
FunctionArgs::Names(names) => {
clean_args_from_types_and_names(cx, sig.decl.inputs, names)
}
};
let mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
if sig.header.is_async() {
decl.output = decl.sugared_async_return_type();
@@ -1051,18 +1063,12 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
),
hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, body);
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
MethodItem(m, None)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
let generics = clean_generics(trait_item.generics, cx);
let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
let decl = clean_fn_decl_with_args(cx, sig.decl, args);
(generics, decl)
});
TyMethodItem(Box::new(Function { decl, generics }))
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
TyMethodItem(m)
}
hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
@@ -1099,7 +1105,7 @@ pub(crate) fn clean_impl_item<'tcx>(
AssocConstItem(clean_ty(ty, cx), default)
}
hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, body);
let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
let defaultness = cx.tcx.impl_defaultness(impl_.owner_id);
MethodItem(m, Some(defaultness))
}
5 changes: 1 addition & 4 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
@@ -694,13 +694,10 @@ impl Item {
asyncness: hir::IsAsync::NotAsync,
}
}
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
let def_id = self.item_id.as_def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
}
ItemKind::TyMethodItem(_) => {
build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
}
_ => return None,
};
Some(header)
1 change: 0 additions & 1 deletion src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -1796,7 +1796,6 @@ in storage.js

.sidebar-elems {
margin-top: 1em;
background-color: var(--sidebar-background-color);
}

.content {
14 changes: 14 additions & 0 deletions src/test/rustdoc/async-trait-sig.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// edition:2021

#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]

pub trait Foo {
// @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn bar() -> i32"
async fn bar() -> i32;

// @has async_trait_sig/trait.Foo.html '//h4[@class="code-header"]' "async fn baz() -> i32"
async fn baz() -> i32 {
1
}
}
3 changes: 2 additions & 1 deletion src/test/ui/error-codes/E0767.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
fn main () {
fn main() {
'a: loop {
|| {
//~^ ERROR mismatched types
loop { break 'a; } //~ ERROR E0767
}
}
21 changes: 17 additions & 4 deletions src/test/ui/error-codes/E0767.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
error[E0767]: use of unreachable label `'a`
--> $DIR/E0767.rs:4:26
--> $DIR/E0767.rs:5:26
|
LL | 'a: loop {
| -- unreachable label defined here
LL | || {
...
LL | loop { break 'a; }
| ^^ unreachable label `'a`
|
= note: labels are unreachable through functions, closures, async blocks and modules

error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/E0767.rs:3:9
|
LL | / || {
LL | |
LL | | loop { break 'a; }
LL | | }
| |_________^ expected `()`, found closure
|
= note: expected unit type `()`
found closure `[closure@$DIR/E0767.rs:3:9: 3:11]`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0767`.
Some errors have detailed explanations: E0308, E0767.
For more information about an error, try `rustc --explain E0308`.
9 changes: 9 additions & 0 deletions src/test/ui/type/issue-103271.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn main() {
//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
let length = <&[_]>::len;
//~^ ERROR the function or associated item `len` exists for reference `&[_]`, but its trait bounds were not satisfied [E0599]
//~| function or associated item cannot be called on `&[_]` due to unsatisfied trait bounds
//~| HELP items from traits can only be used if the trait is in scope
//~| HELP the function `len` is implemented on `[_]`
assert_eq!(length(&[1,3]), 2);
}
22 changes: 22 additions & 0 deletions src/test/ui/type/issue-103271.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0599]: the function or associated item `len` exists for reference `&[_]`, but its trait bounds were not satisfied
--> $DIR/issue-103271.rs:3:26
|
LL | let length = <&[_]>::len;
| ^^^ function or associated item cannot be called on `&[_]` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`&[_]: ExactSizeIterator`
which is required by `&mut &[_]: ExactSizeIterator`
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
LL | use object::read::read_ref::ReadRef;
|
help: the function `len` is implemented on `[_]`
|
LL | let length = <[_]>::len;
| ~~~

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.