Skip to content

Commit d53dc75

Browse files
committed
Auto merge of #128093 - matthiaskrgr:rollup-1snye4b, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #125834 (treat `&raw (const|mut) UNSAFE_STATIC` implied deref as safe) - #127962 (Cleanup compiletest dylib name calculation) - #128049 (Reword E0626 to mention static coroutine, add structured suggestion for adding `static`) - #128067 (Get rid of `can_eq_shallow`) - #128076 (Get rid of `InferCtxtExt` from `error_reporting::traits`) - #128089 (std: Unsafe-wrap actually-universal platform code) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d111ccd + f8373ad commit d53dc75

33 files changed

+567
-366
lines changed

compiler/rustc_borrowck/src/borrowck_errors.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![allow(rustc::diagnostic_outside_of_impl)]
22
#![allow(rustc::untranslatable_diagnostic)]
33

4+
use rustc_errors::Applicability;
45
use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
6+
use rustc_hir as hir;
57
use rustc_middle::span_bug;
68
use rustc_middle::ty::{self, Ty, TyCtxt};
79
use rustc_span::Span;
@@ -382,13 +384,35 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
382384
yield_span: Span,
383385
) -> Diag<'infcx> {
384386
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
385-
struct_span_code_err!(
387+
let mut diag = struct_span_code_err!(
386388
self.dcx(),
387389
span,
388390
E0626,
389391
"borrow may still be in use when {coroutine_kind:#} yields",
390-
)
391-
.with_span_label(yield_span, "possible yield occurs here")
392+
);
393+
diag.span_label(
394+
self.infcx.tcx.def_span(self.body.source.def_id()),
395+
format!("within this {coroutine_kind:#}"),
396+
);
397+
diag.span_label(yield_span, "possible yield occurs here");
398+
if matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) {
399+
let hir::Closure { capture_clause, fn_decl_span, .. } = self
400+
.infcx
401+
.tcx
402+
.hir_node_by_def_id(self.body.source.def_id().expect_local())
403+
.expect_closure();
404+
let span = match capture_clause {
405+
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
406+
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
407+
};
408+
diag.span_suggestion_verbose(
409+
span,
410+
"add `static` to mark this coroutine as unmovable",
411+
"static ",
412+
Applicability::MaybeIncorrect,
413+
);
414+
}
415+
diag
392416
}
393417

394418
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {

compiler/rustc_error_codes/src/error_codes/E0626.md

+24-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
This error occurs because a borrow in a coroutine persists across a
1+
This error occurs because a borrow in a movable coroutine persists across a
22
yield point.
33

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

18-
At present, it is not permitted to have a yield that occurs while a
19-
borrow is still in scope. To resolve this error, the borrow must
20-
either be "contained" to a smaller scope that does not overlap the
21-
yield or else eliminated in another way. So, for example, we might
22-
resolve the previous example by removing the borrow and just storing
23-
the integer by value:
18+
Coroutines may be either unmarked, or marked with `static`. If it is unmarked,
19+
then the coroutine is considered "movable". At present, it is not permitted to
20+
have a yield in a movable coroutine that occurs while a borrow is still in
21+
scope. To resolve this error, the coroutine may be marked `static`:
22+
23+
```
24+
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
25+
# use std::ops::Coroutine;
26+
# use std::pin::Pin;
27+
let mut b = #[coroutine] static || { // <-- note the static keyword
28+
let a = &String::from("hello, world");
29+
yield ();
30+
println!("{}", a);
31+
};
32+
let mut b = std::pin::pin!(b);
33+
b.as_mut().resume(());
34+
```
35+
36+
If the coroutine must remain movable, for example to be used as `Unpin`
37+
without pinning it on the stack or in an allocation, we can alternatively
38+
resolve the previous example by removing the borrow and just storing the
39+
type by value:
2440

2541
```
2642
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
2743
# use std::ops::Coroutine;
2844
# use std::pin::Pin;
2945
let mut b = #[coroutine] || {
30-
let a = 3;
46+
let a = String::from("hello, world");
3147
yield ();
3248
println!("{}", a);
3349
};

compiler/rustc_hir_typeck/src/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc_span::def_id::LocalDefId;
1818
use rustc_span::Span;
1919
use rustc_target::spec::abi::Abi;
2020
use rustc_trait_selection::error_reporting::traits::ArgKind;
21-
use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _;
2221
use rustc_trait_selection::traits;
2322
use rustc_type_ir::ClosureKind;
2423
use std::iter;
@@ -734,13 +733,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
734733
.map(|ty| ArgKind::from_expected_ty(*ty, None))
735734
.collect();
736735
let (closure_span, closure_arg_span, found_args) =
737-
match self.get_fn_like_arguments(expr_map_node) {
736+
match self.err_ctxt().get_fn_like_arguments(expr_map_node) {
738737
Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args),
739738
None => (None, None, Vec::new()),
740739
};
741740
let expected_span =
742741
expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
743742
let guar = self
743+
.err_ctxt()
744744
.report_arg_count_mismatch(
745745
expected_span,
746746
closure_span,

compiler/rustc_infer/src/infer/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -755,18 +755,6 @@ impl<'tcx> InferCtxt<'tcx> {
755755
.collect()
756756
}
757757

758-
// FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
759-
// or we need to process the obligations.
760-
pub fn can_eq_shallow<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
761-
where
762-
T: at::ToTrace<'tcx>,
763-
{
764-
let origin = &ObligationCause::dummy();
765-
// We're only answering whether the types could be the same, and with
766-
// opaque types, "they can be the same", via registering a hidden type.
767-
self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::Yes, a, b).is_ok())
768-
}
769-
770758
#[instrument(skip(self), level = "debug")]
771759
pub fn sub_regions(
772760
&self,

compiler/rustc_mir_build/src/check_unsafety.rs

+18
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
466466
}
467467
}
468468
}
469+
ExprKind::AddressOf { arg, .. } => {
470+
if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind
471+
// THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where
472+
// UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps
473+
&& let ExprKind::Deref { arg } = self.thir[arg].kind
474+
// FIXME(workingjubiee): we lack a clear reason to reject ThreadLocalRef here,
475+
// but we also have no conclusive reason to allow it either!
476+
&& let ExprKind::StaticRef { .. } = self.thir[arg].kind
477+
{
478+
// A raw ref to a place expr, even an "unsafe static", is okay!
479+
// We short-circuit to not recursively traverse this expression.
480+
return;
481+
// note: const_mut_refs enables this code, and it currently remains unsafe:
482+
// static mut BYTE: u8 = 0;
483+
// static mut BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(BYTE) };
484+
// static mut DEREF_BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(*BYTE_PTR) };
485+
}
486+
}
469487
ExprKind::Deref { arg } => {
470488
if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
471489
self.thir[arg].kind

compiler/rustc_mir_build/src/thir/cx/expr.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -939,9 +939,11 @@ impl<'tcx> Cx<'tcx> {
939939
}
940940
}
941941

942-
// We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
943-
// a constant reference (or constant raw pointer for `static mut`) in MIR
942+
// A source Rust `path::to::STATIC` is a place expr like *&ident is.
943+
// In THIR, we make them exactly equivalent by inserting the implied *& or *&raw,
944+
// but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
944945
Res::Def(DefKind::Static { .. }, id) => {
946+
// this is &raw for extern static or static mut, and & for other statics
945947
let ty = self.tcx.static_ptr_ty(id);
946948
let temp_lifetime = self
947949
.rvalue_scopes

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_middle::{
1212
use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
1313

1414
use crate::error_reporting::TypeErrCtxt;
15+
use crate::infer::InferCtxtExt;
1516

1617
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
1718
pub fn note_and_explain_type_err(
@@ -821,7 +822,7 @@ fn foo(&self) -> Self::T { String::new() }
821822
tcx.defaultness(item.id.owner_id)
822823
{
823824
let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
824-
if self.infcx.can_eq_shallow(param_env, assoc_ty, found) {
825+
if self.infcx.can_eq(param_env, assoc_ty, found) {
825826
diag.span_label(
826827
item.span,
827828
"associated type defaults can't be assumed inside the \
@@ -844,7 +845,7 @@ fn foo(&self) -> Self::T { String::new() }
844845
let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
845846
if let hir::Defaultness::Default { has_value: true } =
846847
tcx.defaultness(item.id.owner_id)
847-
&& self.infcx.can_eq_shallow(param_env, assoc_ty, found)
848+
&& self.infcx.can_eq(param_env, assoc_ty, found)
848849
{
849850
diag.span_label(
850851
item.span,

0 commit comments

Comments
 (0)