Skip to content

Rollup of 9 pull requests #103322

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

Merged
merged 21 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0b27164
fix `SelfVisitor::is_self_ty` ICE
TaKO8Ki Oct 19, 2022
cf13d91
Clarify `run_in_thread_pool_with_globals`.
nnethercote Oct 9, 2022
5d716fd
Add a comment to `Compiler`.
nnethercote Oct 11, 2022
a3ccb19
Fixed docs typo in `library/std/src/time.rs`
johnmatthiggins Oct 20, 2022
9a9e2fe
check if impl_self is `Some`
TaKO8Ki Oct 20, 2022
afd0817
Adjust `transmute{,_copy}` to be clearer about which of `T` and `U` i…
thomcc Oct 20, 2022
d3c37b1
+/- shortcut now only expand/collapse, not both
GuillaumeGomez Oct 20, 2022
8e3b891
Add GUI tests for collapse/expand actions
GuillaumeGomez Oct 20, 2022
ed1f02b
fix typo
cuishuang Oct 20, 2022
47f816c
no test in testsuite label
compiler-errors Oct 20, 2022
bf14e31
interpret: remove an incorrect assertion
RalfJung Oct 20, 2022
ebf5028
Improve "`~const` is not allowed here" message
fee1-dead Oct 20, 2022
7ee4b21
Rollup merge of #103221 - TaKO8Ki:fix-103202, r=oli-obk
matthiaskrgr Oct 20, 2022
be4816f
Rollup merge of #103230 - nnethercote:clarify-startup, r=jyn514
matthiaskrgr Oct 20, 2022
cfb424a
Rollup merge of #103281 - thomcc:long-overdue, r=jyn514
matthiaskrgr Oct 20, 2022
c6a680e
Rollup merge of #103288 - johnmatthiggins:master, r=thomcc
matthiaskrgr Oct 20, 2022
5bf18ad
Rollup merge of #103296 - GuillaumeGomez:collapse-expand-shortcuts, r…
matthiaskrgr Oct 20, 2022
1d97a58
Rollup merge of #103297 - catandcoder:master, r=JohnTitor
matthiaskrgr Oct 20, 2022
01111d4
Rollup merge of #103313 - compiler-errors:no-test, r=jyn514
matthiaskrgr Oct 20, 2022
801e326
Rollup merge of #103315 - RalfJung:interpret-switchint-ice, r=bjorn3
matthiaskrgr Oct 20, 2022
f9944a9
Rollup merge of #103319 - fee1-dead-contrib:improve_tilde_const_msg, …
matthiaskrgr Oct 20, 2022
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
63 changes: 43 additions & 20 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ enum SelfSemantic {
No,
}

/// What is the context that prevents using `~const`?
enum DisallowTildeConstContext<'a> {
TraitObject,
ImplTrait,
Fn(FnKind<'a>),
}

struct AstValidator<'a> {
session: &'a Session,

Expand All @@ -56,7 +63,7 @@ struct AstValidator<'a> {
/// e.g., `impl Iterator<Item = impl Debug>`.
outer_impl_trait: Option<Span>,

is_tilde_const_allowed: bool,
disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,

/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
Expand Down Expand Up @@ -93,18 +100,26 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old;
}

fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
fn with_tilde_const(
&mut self,
disallowed: Option<DisallowTildeConstContext<'a>>,
f: impl FnOnce(&mut Self),
) {
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
f(self);
self.is_tilde_const_allowed = old;
self.disallow_tilde_const = old;
}

fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
self.with_tilde_const(true, f)
self.with_tilde_const(None, f)
}

fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
self.with_tilde_const(false, f)
fn with_banned_tilde_const(
&mut self,
ctx: DisallowTildeConstContext<'a>,
f: impl FnOnce(&mut Self),
) {
self.with_tilde_const(Some(ctx), f)
}

fn with_let_management(
Expand Down Expand Up @@ -172,7 +187,7 @@ impl<'a> AstValidator<'a> {
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
if outer.is_some() {
self.with_banned_tilde_const(f);
self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
} else {
f(self);
}
Expand All @@ -197,7 +212,10 @@ impl<'a> AstValidator<'a> {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
TyKind::TraitObject(..) => self
.with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
visit::walk_ty(this, t)
}),
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
Expand Down Expand Up @@ -1411,13 +1429,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
err.emit();
}
(_, TraitBoundModifier::MaybeConst) => {
if !self.is_tilde_const_allowed {
self.err_handler()
.struct_span_err(bound.span(), "`~const` is not allowed here")
.note("only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions")
.emit();
}
(_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
match reason {
DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
};
err.emit();
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
self.err_handler()
Expand Down Expand Up @@ -1523,10 +1543,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}

let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
let tilde_const_allowed =
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));

let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));

self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
}

fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
Expand Down Expand Up @@ -1770,7 +1793,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
in_const_trait_impl: false,
has_proc_macro_decls: false,
outer_impl_trait: None,
is_tilde_const_allowed: false,
disallow_tilde_const: None,
is_impl_trait_banned: false,
is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(discr.layout.ty, switch_ty);

// Branch to the `otherwise` case by default, if no match is found.
assert!(!targets.iter().is_empty());
let mut target_block = targets.otherwise();

for (const_int, target) in targets.iter() {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ impl<'a, 'b> RunCompiler<'a, 'b> {
run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
}
}

fn run_compiler(
at_args: &[String],
callbacks: &mut (dyn Callbacks + Send),
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ use std::result;

pub type Result<T> = result::Result<T, ErrorGuaranteed>;

/// Represents a compiler session.
/// Represents a compiler session. Note that every `Compiler` contains a
/// `Session`, but `Compiler` also contains some things that cannot be in
/// `Session`, due to `Session` being in a crate that has many fewer
/// dependencies than this crate.
///
/// Can be used to run `rustc_interface` queries.
/// Created by passing [`Config`] to [`run_compiler`].
Expand Down
89 changes: 45 additions & 44 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@ use libloading::Library;
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
#[cfg(parallel_compiler)]
use rustc_data_structures::jobserver;
use rustc_errors::registry::Registry;
#[cfg(parallel_compiler)]
use rustc_middle::ty::tls;
use rustc_parse::validate_attr;
#[cfg(parallel_compiler)]
use rustc_query_impl::{QueryContext, QueryCtxt};
use rustc_session as session;
use rustc_session::config::CheckCfg;
use rustc_session::config::{self, CrateType};
Expand All @@ -25,8 +19,6 @@ use rustc_span::symbol::{sym, Symbol};
use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::mem;
#[cfg(not(parallel_compiler))]
use std::panic;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;
Expand Down Expand Up @@ -135,13 +127,20 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
_threads: usize,
f: F,
) -> R {
// The thread pool is a single thread in the non-parallel compiler.
thread::scope(|s| {
let mut builder = thread::Builder::new().name("rustc".to_string());
if let Some(size) = get_stack_size() {
builder = builder.stack_size(size);
}
// The "thread pool" is a single spawned thread in the non-parallel
// compiler. We run on a spawned thread instead of the main thread (a) to
// provide control over the stack size, and (b) to increase similarity with
// the parallel compiler, in particular to ensure there is no accidental
// sharing of data between the main thread and the compilation thread
// (which might cause problems for the parallel compiler).
let mut builder = thread::Builder::new().name("rustc".to_string());
if let Some(size) = get_stack_size() {
builder = builder.stack_size(size);
}

// We build the session globals and run `f` on the spawned thread, because
// `SessionGlobals` does not impl `Send` in the non-parallel compiler.
thread::scope(|s| {
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
// name contains null bytes.
let r = builder
Expand All @@ -151,55 +150,57 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(

match r {
Ok(v) => v,
Err(e) => panic::resume_unwind(e),
Err(e) => std::panic::resume_unwind(e),
}
})
}

/// Creates a new thread and forwards information in thread locals to it.
/// The new thread runs the deadlock handler.
/// Must only be called when a deadlock is about to happen.
#[cfg(parallel_compiler)]
unsafe fn handle_deadlock() {
let registry = rustc_rayon_core::Registry::current();

let query_map = tls::with(|tcx| {
QueryCtxt::from_tcx(tcx)
.try_collect_active_jobs()
.expect("active jobs shouldn't be locked in deadlock handler")
});
thread::spawn(move || rustc_query_impl::deadlock(query_map, &registry));
}

#[cfg(parallel_compiler)]
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
threads: usize,
f: F,
) -> R {
let mut config = rayon::ThreadPoolBuilder::new()
use rustc_data_structures::jobserver;
use rustc_middle::ty::tls;
use rustc_query_impl::{deadlock, QueryContext, QueryCtxt};

let mut builder = rayon::ThreadPoolBuilder::new()
.thread_name(|_| "rustc".to_string())
.acquire_thread_handler(jobserver::acquire_thread)
.release_thread_handler(jobserver::release_thread)
.num_threads(threads)
.deadlock_handler(|| unsafe { handle_deadlock() });

.deadlock_handler(|| {
// On deadlock, creates a new thread and forwards information in thread
// locals to it. The new thread runs the deadlock handler.
let query_map = tls::with(|tcx| {
QueryCtxt::from_tcx(tcx)
.try_collect_active_jobs()
.expect("active jobs shouldn't be locked in deadlock handler")
});
let registry = rustc_rayon_core::Registry::current();
thread::spawn(move || deadlock(query_map, &registry));
});
if let Some(size) = get_stack_size() {
config = config.stack_size(size);
builder = builder.stack_size(size);
}

let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);

// We create the session globals on the main thread, then create the thread
// pool. Upon creation, each worker thread created gets a copy of the
// session globals in TLS. This is possible because `SessionGlobals` impls
// `Send` in the parallel compiler.
rustc_span::create_session_globals_then(edition, || {
rustc_span::with_session_globals(|session_globals| {
// The main handler runs for each Rayon worker thread and sets up
// the thread local rustc uses. `session_globals` is captured and set
// on the new threads.
let main_handler = move |thread: rayon::ThreadBuilder| {
rustc_span::set_session_globals_then(session_globals, || thread.run())
};

config.build_scoped(main_handler, with_pool).unwrap()
builder
.build_scoped(
// Initialize each new worker thread when created.
move |thread: rayon::ThreadBuilder| {
rustc_span::set_session_globals_then(session_globals, || thread.run())
},
// Run `f` on the first thread in the thread pool.
move |pool: &rayon::ThreadPool| pool.install(f),
)
.unwrap()
})
})
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1939,11 +1939,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
match ty.kind {
TyKind::ImplicitSelf => true,
TyKind::Path(None, _) => {
let path_res = self.r.partial_res_map[&ty.id].expect_full_res();
if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path_res {
let path_res = self.r.partial_res_map[&ty.id].full_res();
if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
return true;
}
Some(path_res) == self.impl_self
self.impl_self.is_some() && path_res == self.impl_self
}
_ => false,
}
Expand Down
8 changes: 4 additions & 4 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,14 +994,14 @@ extern "rust-intrinsic" {
/// `transmute` is semantically equivalent to a bitwise move of one type
/// into another. It copies the bits from the source value into the
/// destination value, then forgets the original. Note that source and destination
/// are passed by-value, which means if `T` or `U` contain padding, that padding
/// are passed by-value, which means if `Src` or `Dst` contain padding, that padding
/// is *not* guaranteed to be preserved by `transmute`.
///
/// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at
/// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler
/// will generate code *assuming that you, the programmer, ensure that there will never be
/// undefined behavior*. It is therefore your responsibility to guarantee that every value
/// passed to `transmute` is valid at both types `T` and `U`. Failing to uphold this condition
/// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition
/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
/// unsafe**. `transmute` should be the absolute last resort.
///
Expand All @@ -1012,7 +1012,7 @@ extern "rust-intrinsic" {
///
/// Because `transmute` is a by-value operation, alignment of the *transmuted values
/// themselves* is not a concern. As with any other function, the compiler already ensures
/// both `T` and `U` are properly aligned. However, when transmuting values that *point
/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
/// alignment of the pointed-to values.
///
Expand Down Expand Up @@ -1248,7 +1248,7 @@ extern "rust-intrinsic" {
#[rustc_allowed_through_unstable_modules]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
#[rustc_diagnostic_item = "transmute"]
pub fn transmute<T, U>(e: T) -> U;
pub fn transmute<Src, Dst>(src: Src) -> Dst;

/// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
Expand Down
Loading