Skip to content
Closed
Show file tree
Hide file tree
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
15 changes: 11 additions & 4 deletions compiler/rustc_errors/src/decorate_diag.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// This module provides types and traits for buffering lints until later in compilation.
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::DynSend;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_error_messages::MultiSpan;
use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId};

Expand All @@ -10,7 +10,14 @@ use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
/// We can't implement `Diagnostic` for `BuiltinLintDiag`, because decorating some of its
/// variants requires types we don't have yet. So, handle that case separately.
pub enum DecorateDiagCompat {
Dynamic(Box<dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>),
Dynamic(
Box<
dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()>
+ DynSync
+ DynSend
+ 'static,
>,
),
Builtin(BuiltinLintDiag),
}

Expand All @@ -20,7 +27,7 @@ impl std::fmt::Debug for DecorateDiagCompat {
}
}

impl<D: for<'a> Diagnostic<'a, ()> + DynSend + 'static> From<D> for DecorateDiagCompat {
impl<D: for<'a> Diagnostic<'a, ()> + DynSync + DynSend + 'static> From<D> for DecorateDiagCompat {
#[inline]
fn from(d: D) -> Self {
Self::Dynamic(Box::new(|dcx, level| d.into_diag(dcx, level)))
Expand Down Expand Up @@ -83,7 +90,7 @@ impl LintBuffer {
}

pub fn dyn_buffer_lint<
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static,
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
>(
&mut self,
lint: &'static Lint,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::panic;
use std::path::PathBuf;
use std::thread::panicking;

use rustc_data_structures::sync::DynSend;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg};
use rustc_lint_defs::{Applicability, LintExpectationId};
use rustc_macros::{Decodable, Encodable};
Expand Down Expand Up @@ -120,7 +120,9 @@ where
}

impl<'a> Diagnostic<'a, ()>
for Box<dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSend + 'static>
for Box<
dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSync + DynSend + 'static,
>
{
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
self(dcx, level)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ declare_features! (
/// Allows inconsistent bounds in where clauses.
(unstable, trivial_bounds, "1.28.0", Some(48214)),
/// Allows using `try {...}` expressions.
(unstable, try_blocks, "1.29.0", Some(31436)),
(unstable, try_blocks, "1.29.0", Some(154391)),
/// Allows using `try bikeshed TargetType {...}` expressions.
(unstable, try_blocks_heterogeneous, "1.94.0", Some(149488)),
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
Expand Down
24 changes: 18 additions & 6 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,37 @@

use std::ffi::OsStr;
use std::intrinsics::transmute_unchecked;
use std::marker::PhantomData;
use std::mem::MaybeUninit;

use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_span::{ErrorGuaranteed, Spanned};

use crate::mir::mono::{MonoItem, NormalizationErrorInMono};
use crate::ty::{self, Ty, TyCtxt};
use crate::{mir, thir, traits};

unsafe extern "C" {
type NoAutoTraits;
}

/// Internal implementation detail of [`Erased`].
#[derive(Copy, Clone)]
pub struct ErasedData<Storage: Copy> {
/// We use `MaybeUninit` here to make sure it's legal to store a transmuted
/// value that isn't actually of type `Storage`.
data: MaybeUninit<Storage>,
/// `Storage` is an erased type, so we use an external type here to opt-out of auto traits
/// as those would be incorrect.
no_auto_traits: PhantomData<NoAutoTraits>,
}

// SAFETY: The bounds on `erase_val` ensure the types we erase are `DynSync` and `DynSend`
unsafe impl<Storage: Copy> DynSync for ErasedData<Storage> {}
unsafe impl<Storage: Copy> DynSend for ErasedData<Storage> {}

/// Trait for types that can be erased into [`Erased<Self>`].
///
/// Erasing and unerasing values is performed by [`erase_val`] and [`restore_val`].
Expand Down Expand Up @@ -54,13 +67,11 @@ pub type Erased<T: Erasable> = ErasedData<impl Copy>;
///
/// `Erased<T>` and `Erased<U>` are type-checked as distinct types, but codegen
/// can see whether they actually have the same storage type.
///
/// FIXME: This might have soundness issues with erasable types that don't
/// implement the same auto-traits as `[u8; _]`; see
/// <https://github.com/rust-lang/rust/pull/151715#discussion_r2740113250>
#[inline(always)]
#[define_opaque(Erased)]
pub fn erase_val<T: Erasable>(value: T) -> Erased<T> {
// The `DynSend` and `DynSync` bounds on `T` are used to
// justify the safety of the implementations of these traits for `ErasedData`.
pub fn erase_val<T: Erasable + DynSend + DynSync>(value: T) -> Erased<T> {
// Ensure the sizes match
const {
if size_of::<T>() != size_of::<T::Storage>() {
Expand All @@ -78,6 +89,7 @@ pub fn erase_val<T: Erasable>(value: T) -> Erased<T> {
//
// SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Storage>>(value) },
no_auto_traits: PhantomData,
}
}

Expand All @@ -88,7 +100,7 @@ pub fn erase_val<T: Erasable>(value: T) -> Erased<T> {
#[inline(always)]
#[define_opaque(Erased)]
pub fn restore_val<T: Erasable>(erased_value: Erased<T>) -> T {
let ErasedData { data }: ErasedData<<T as Erasable>::Storage> = erased_value;
let ErasedData { data, .. }: ErasedData<<T as Erasable>::Storage> = erased_value;
// See comment in `erase_val` for why we use `transmute_unchecked`.
//
// SAFETY: Due to the use of impl Trait in `Erased` the only way to safely create an instance
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/large_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
// There are some differences in behavior on wasm and ARM that are not properly
// understood, so we conservatively treat this optimization as unsound:
// https://github.com/rust-lang/rust/pull/85158#issuecomment-1101836457
sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3
sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() >= 3
}

fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_session/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::sync::Arc;
use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sync::{AppendOnlyVec, DynSend, Lock};
use rustc_data_structures::sync::{AppendOnlyVec, DynSend, DynSync, Lock};
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
use rustc_errors::emitter::{EmitterWithNote, stderr_destination};
use rustc_errors::{
Expand Down Expand Up @@ -332,7 +332,7 @@ impl ParseSess {
}

pub fn dyn_buffer_lint<
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static,
F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
>(
&self,
lint: &'static Lint,
Expand Down
8 changes: 4 additions & 4 deletions src/doc/unstable-book/src/language-features/try-blocks.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# `try_blocks`

The tracking issue for this feature is: [#31436]
The tracking issue for this feature is: [#154391]

[#31436]: https://github.com/rust-lang/rust/issues/31436
[#154391]: https://github.com/rust-lang/rust/issues/154391

------------------------

Expand All @@ -14,14 +14,14 @@ block creates a new scope one can use the `?` operator in.
use std::num::ParseIntError;
let result: Result<i32, ParseIntError> = try {
let result = try {
"1".parse::<i32>()?
+ "2".parse::<i32>()?
+ "3".parse::<i32>()?
};
assert_eq!(result, Ok(6));
let result: Result<i32, ParseIntError> = try {
let result = try {
"1".parse::<i32>()?
+ "foo".parse::<i32>()?
+ "3".parse::<i32>()?
Expand Down
8 changes: 4 additions & 4 deletions src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11576,9 +11576,9 @@ The tracking issue for this feature is: [#85731]
label: "try_blocks",
description: r##"# `try_blocks`

The tracking issue for this feature is: [#31436]
The tracking issue for this feature is: [#154391]

[#31436]: https://github.com/rust-lang/rust/issues/31436
[#154391]: https://github.com/rust-lang/rust/issues/154391

------------------------

Expand All @@ -11590,14 +11590,14 @@ block creates a new scope one can use the `?` operator in.

use std::num::ParseIntError;

let result: Result<i32, ParseIntError> = try {
let result = try {
"1".parse::<i32>()?
+ "2".parse::<i32>()?
+ "3".parse::<i32>()?
};
assert_eq!(result, Ok(6));

let result: Result<i32, ParseIntError> = try {
let result = try {
"1".parse::<i32>()?
+ "foo".parse::<i32>()?
+ "3".parse::<i32>()?
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,7 @@ Tests for the `#[doc(hidden)]` items.

## `tests/ui/try-block/`

`#![feature(try_blocks)]`. See [Tracking issue for `?` operator and `try` blocks (RFC 243, `question_mark` & `try_blocks` features)](https://github.com/rust-lang/rust/issues/31436).
`#![feature(try_blocks)]` & `#![feature(try_blocks_heterogeneous)]`. See [Tracking Issue for homogeneous `try_blocks`](https://github.com/rust-lang/rust/issues/154391) & [Experimental Tracking Issue for Heterogeneous Try Blocks](https://github.com/rust-lang/rust/issues/149488).

## `tests/ui/try-trait/`

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/feature-gates/feature-gate-try_blocks.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | | x
LL | | };
| |_____^
|
= note: see issue #31436 <https://github.com/rust-lang/rust/issues/31436> for more information
= note: see issue #154391 <https://github.com/rust-lang/rust/issues/154391> for more information
= help: add `#![feature(try_blocks)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ warning: `try` blocks are unstable
LL | try {}
| ^^^^^^
|
= note: see issue #31436 <https://github.com/rust-lang/rust/issues/31436> for more information
= note: see issue #154391 <https://github.com/rust-lang/rust/issues/154391> for more information
= help: add `#![feature(try_blocks)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= warning: unstable syntax can change at any point in the future, causing a hard error!
Expand Down
Loading