Skip to content

Commit

Permalink
Auto merge of rust-lang#128093 - matthiaskrgr:rollup-1snye4b, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#125834 (treat `&raw (const|mut) UNSAFE_STATIC` implied deref as safe)
 - rust-lang#127962 (Cleanup compiletest dylib name calculation)
 - rust-lang#128049 (Reword E0626 to mention static coroutine, add structured suggestion for adding `static`)
 - rust-lang#128067 (Get rid of `can_eq_shallow`)
 - rust-lang#128076 (Get rid of `InferCtxtExt` from `error_reporting::traits`)
 - rust-lang#128089 (std: Unsafe-wrap actually-universal platform code)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 23, 2024
2 parents d111ccd + f8373ad commit d53dc75
Show file tree
Hide file tree
Showing 33 changed files with 567 additions and 366 deletions.
30 changes: 27 additions & 3 deletions compiler/rustc_borrowck/src/borrowck_errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]

use rustc_errors::Applicability;
use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
use rustc_hir as hir;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
Expand Down Expand Up @@ -382,13 +384,35 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
yield_span: Span,
) -> Diag<'infcx> {
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
struct_span_code_err!(
let mut diag = struct_span_code_err!(
self.dcx(),
span,
E0626,
"borrow may still be in use when {coroutine_kind:#} yields",
)
.with_span_label(yield_span, "possible yield occurs here")
);
diag.span_label(
self.infcx.tcx.def_span(self.body.source.def_id()),
format!("within this {coroutine_kind:#}"),
);
diag.span_label(yield_span, "possible yield occurs here");
if matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) {
let hir::Closure { capture_clause, fn_decl_span, .. } = self
.infcx
.tcx
.hir_node_by_def_id(self.body.source.def_id().expect_local())
.expect_closure();
let span = match capture_clause {
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
};
diag.span_suggestion_verbose(
span,
"add `static` to mark this coroutine as unmovable",
"static ",
Applicability::MaybeIncorrect,
);
}
diag
}

pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
Expand Down
32 changes: 24 additions & 8 deletions compiler/rustc_error_codes/src/error_codes/E0626.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This error occurs because a borrow in a coroutine persists across a
This error occurs because a borrow in a movable coroutine persists across a
yield point.

Erroneous code example:
Expand All @@ -15,19 +15,35 @@ let mut b = #[coroutine] || {
Pin::new(&mut b).resume(());
```

At present, it is not permitted to have a yield that occurs while a
borrow is still in scope. To resolve this error, the borrow must
either be "contained" to a smaller scope that does not overlap the
yield or else eliminated in another way. So, for example, we might
resolve the previous example by removing the borrow and just storing
the integer by value:
Coroutines may be either unmarked, or marked with `static`. If it is unmarked,
then the coroutine is considered "movable". At present, it is not permitted to
have a yield in a movable coroutine that occurs while a borrow is still in
scope. To resolve this error, the coroutine may be marked `static`:

```
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
# use std::ops::Coroutine;
# use std::pin::Pin;
let mut b = #[coroutine] static || { // <-- note the static keyword
let a = &String::from("hello, world");
yield ();
println!("{}", a);
};
let mut b = std::pin::pin!(b);
b.as_mut().resume(());
```

If the coroutine must remain movable, for example to be used as `Unpin`
without pinning it on the stack or in an allocation, we can alternatively
resolve the previous example by removing the borrow and just storing the
type by value:

```
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
# use std::ops::Coroutine;
# use std::pin::Pin;
let mut b = #[coroutine] || {
let a = 3;
let a = String::from("hello, world");
yield ();
println!("{}", a);
};
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::ArgKind;
use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _;
use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind;
use std::iter;
Expand Down Expand Up @@ -734,13 +733,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.map(|ty| ArgKind::from_expected_ty(*ty, None))
.collect();
let (closure_span, closure_arg_span, found_args) =
match self.get_fn_like_arguments(expr_map_node) {
match self.err_ctxt().get_fn_like_arguments(expr_map_node) {
Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args),
None => (None, None, Vec::new()),
};
let expected_span =
expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
let guar = self
.err_ctxt()
.report_arg_count_mismatch(
expected_span,
closure_span,
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,18 +755,6 @@ impl<'tcx> InferCtxt<'tcx> {
.collect()
}

// FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
// or we need to process the obligations.
pub fn can_eq_shallow<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
// We're only answering whether the types could be the same, and with
// opaque types, "they can be the same", via registering a hidden type.
self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::Yes, a, b).is_ok())
}

#[instrument(skip(self), level = "debug")]
pub fn sub_regions(
&self,
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}
}
}
ExprKind::AddressOf { arg, .. } => {
if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind
// THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where
// UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps
&& let ExprKind::Deref { arg } = self.thir[arg].kind
// FIXME(workingjubiee): we lack a clear reason to reject ThreadLocalRef here,
// but we also have no conclusive reason to allow it either!
&& let ExprKind::StaticRef { .. } = self.thir[arg].kind
{
// A raw ref to a place expr, even an "unsafe static", is okay!
// We short-circuit to not recursively traverse this expression.
return;
// note: const_mut_refs enables this code, and it currently remains unsafe:
// static mut BYTE: u8 = 0;
// static mut BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(BYTE) };
// static mut DEREF_BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(*BYTE_PTR) };
}
}
ExprKind::Deref { arg } => {
if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
self.thir[arg].kind
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -939,9 +939,11 @@ impl<'tcx> Cx<'tcx> {
}
}

// We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
// a constant reference (or constant raw pointer for `static mut`) in MIR
// A source Rust `path::to::STATIC` is a place expr like *&ident is.
// In THIR, we make them exactly equivalent by inserting the implied *& or *&raw,
// but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
Res::Def(DefKind::Static { .. }, id) => {
// this is &raw for extern static or static mut, and & for other statics
let ty = self.tcx.static_ptr_ty(id);
let temp_lifetime = self
.rvalue_scopes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use rustc_middle::{
use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};

use crate::error_reporting::TypeErrCtxt;
use crate::infer::InferCtxtExt;

impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub fn note_and_explain_type_err(
Expand Down Expand Up @@ -821,7 +822,7 @@ fn foo(&self) -> Self::T { String::new() }
tcx.defaultness(item.id.owner_id)
{
let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
if self.infcx.can_eq_shallow(param_env, assoc_ty, found) {
if self.infcx.can_eq(param_env, assoc_ty, found) {
diag.span_label(
item.span,
"associated type defaults can't be assumed inside the \
Expand All @@ -844,7 +845,7 @@ fn foo(&self) -> Self::T { String::new() }
let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
if let hir::Defaultness::Default { has_value: true } =
tcx.defaultness(item.id.owner_id)
&& self.infcx.can_eq_shallow(param_env, assoc_ty, found)
&& self.infcx.can_eq(param_env, assoc_ty, found)
{
diag.span_label(
item.span,
Expand Down
Loading

0 comments on commit d53dc75

Please sign in to comment.