diff --git a/Cargo.lock b/Cargo.lock index e28397b391502..5c61069276591 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4335,7 +4335,6 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", - "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_serialize", @@ -4441,7 +4440,6 @@ dependencies = [ "rustc_hir", "rustc_interface", "rustc_middle", - "rustc_session", "rustc_span", "rustc_target", "stable_mir", diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 6f82d6f932330..f013ff45a4fe5 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -353,28 +353,28 @@ pub fn find_body_stability( body_stab } +fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option) -> Option<()> { + if item.is_some() { + handle_errors( + &sess.parse_sess, + meta.span, + AttrError::MultipleItem(pprust::path_to_string(&meta.path)), + ); + None + } else if let Some(v) = meta.value_str() { + *item = Some(v); + Some(()) + } else { + sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); + None + } +} + /// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and /// its stability information. fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> { let meta = attr.meta()?; let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None }; - let insert_or_error = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors( - &sess.parse_sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), - ); - return false; - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); - false - } - }; let mut feature = None; let mut since = None; @@ -389,16 +389,8 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit }; match mi.name_or_empty() { - sym::feature => { - if !insert_or_error(mi, &mut feature) { - return None; - } - } - sym::since => { - if !insert_or_error(mi, &mut since) { - return None; - } - } + sym::feature => insert_or_error(sess, mi, &mut feature)?, + sym::since => insert_or_error(sess, mi, &mut since)?, _ => { handle_errors( &sess.parse_sess, @@ -438,23 +430,6 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> { let meta = attr.meta()?; let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None }; - let insert_or_error = |meta: &MetaItem, item: &mut Option| { - if item.is_some() { - handle_errors( - &sess.parse_sess, - meta.span, - AttrError::MultipleItem(pprust::path_to_string(&meta.path)), - ); - return false; - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); - false - } - }; let mut feature = None; let mut reason = None; @@ -473,20 +448,10 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil }; match mi.name_or_empty() { - sym::feature => { - if !insert_or_error(mi, &mut feature) { - return None; - } - } - sym::reason => { - if !insert_or_error(mi, &mut reason) { - return None; - } - } + sym::feature => insert_or_error(sess, mi, &mut feature)?, + sym::reason => insert_or_error(sess, mi, &mut reason)?, sym::issue => { - if !insert_or_error(mi, &mut issue) { - return None; - } + insert_or_error(sess, mi, &mut issue)?; // These unwraps are safe because `insert_or_error` ensures the meta item // is a name/value pair string literal. @@ -515,11 +480,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil } is_soft = true; } - sym::implied_by => { - if !insert_or_error(mi, &mut implied_by) { - return None; - } - } + sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?, _ => { handle_errors( &sess.parse_sess, diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index 12aeae1772568..572751d951189 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -1,3 +1,8 @@ +//! "Hooks" provide a way for `tcx` functionality to be provided by some downstream crate without +//! everything in rustc having to depend on that crate. This is somewhat similar to queries, but +//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are +//! just plain function pointers without any of the query magic. + use crate::mir; use crate::query::TyCtxtAt; use crate::ty::{Ty, TyCtxt}; diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index a44dd5ede2fd2..a350e8b2e3a43 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } -rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d29ab02c1a6ac..e120f595d92ef 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -813,7 +813,6 @@ impl Input { FileName::Anon(_) => None, FileName::MacroExpansion(_) => None, FileName::ProcMacroSourceCode(_) => None, - FileName::CfgSpec(_) => None, FileName::CliCrateAttr(_) => None, FileName::Custom(_) => None, FileName::DocTest(path, _) => Some(path), diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 4c29f743708ac..3e0d6baab6aab 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,14 +4,13 @@ version = "0.0.0" edition = "2021" [dependencies] +rustc_driver = { path = "../rustc_driver" } rustc_hir = { path = "../rustc_hir" } +rustc_interface = { path = "../rustc_interface" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_driver = { path = "../rustc_driver" } -rustc_interface = { path = "../rustc_interface" } -rustc_session = {path = "../rustc_session" } -tracing = "0.1" stable_mir = {path = "../stable_mir" } +tracing = "0.1" [features] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index b6c36678db52f..d10f46fad9e28 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -10,10 +10,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] -#![feature(rustc_private)] -#![feature(ptr_metadata)] -#![feature(type_alias_impl_trait)] // Used to define opaque types. -#![feature(intra_doc_pointers)] pub mod rustc_internal; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 1a9dea99f643f..36eb2247253a0 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -11,7 +11,7 @@ use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; use rustc_middle::ty::TyCtxt; -pub use rustc_span::def_id::{CrateNum, DefId}; +use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; use stable_mir::CompilerError; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 36d7c7653eef9..6fd61e45fcc9c 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -280,8 +280,7 @@ impl RealFileName { } /// Differentiates between real files and common virtual files. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)] -#[derive(Decodable, Encodable)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)] pub enum FileName { Real(RealFileName), /// Call to `quote!`. @@ -292,8 +291,6 @@ pub enum FileName { // FIXME(jseyfried) MacroExpansion(Hash64), ProcMacroSourceCode(Hash64), - /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`. - CfgSpec(Hash64), /// Strings provided as crate attributes in the CLI. CliCrateAttr(Hash64), /// Custom sources for explicit parser calls from plugins and drivers. @@ -338,7 +335,6 @@ impl fmt::Display for FileNameDisplay<'_> { MacroExpansion(_) => write!(fmt, ""), Anon(_) => write!(fmt, ""), ProcMacroSourceCode(_) => write!(fmt, ""), - CfgSpec(_) => write!(fmt, ""), CliCrateAttr(_) => write!(fmt, ""), Custom(ref s) => write!(fmt, "<{s}>"), DocTest(ref path, _) => write!(fmt, "{}", path.display()), @@ -364,7 +360,6 @@ impl FileName { Anon(_) | MacroExpansion(_) | ProcMacroSourceCode(_) - | CfgSpec(_) | CliCrateAttr(_) | Custom(_) | QuoteExpansion(_) diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 6c49e94dc310b..4b55963201717 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -9,7 +9,7 @@ extern crate tracing; pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; pub mod layout; -pub(crate) mod maybe_transmutable; +mod maybe_transmutable; #[derive(Default)] pub struct Assume { @@ -19,7 +19,7 @@ pub struct Assume { pub validity: bool, } -/// Either we have an error, transmutation is allowed, or we have an optional +/// Either transmutation is allowed, we have an error, or we have an optional /// Condition that must hold. #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub enum Answer { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index c0141f1f84149..bf3c390c8008e 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -32,26 +32,6 @@ where ) -> Self { Self { src, dst, scope, assume, context } } - - // FIXME(bryangarza): Delete this when all usages are removed - pub(crate) fn map_layouts( - self, - f: F, - ) -> Result, Answer<::Ref>> - where - F: FnOnce( - L, - L, - ::Scope, - &C, - ) -> Result<(M, M), Answer<::Ref>>, - { - let Self { src, dst, scope, assume, context } = self; - - let (src, dst) = f(src, dst, scope, &context)?; - - Ok(MaybeTransmutableQuery { src, dst, scope, assume, context }) - } } // FIXME: Nix this cfg, so we can write unit tests independently of rustc @@ -107,42 +87,42 @@ where #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))] pub(crate) fn answer(self) -> Answer<::Ref> { let assume_visibility = self.assume.safety; - // FIXME(bryangarza): Refactor this code to get rid of `map_layouts` - let query_or_answer = self.map_layouts(|src, dst, scope, context| { - // Remove all `Def` nodes from `src`, without checking their visibility. - let src = src.prune(&|def| true); - trace!(?src, "pruned src"); + let Self { src, dst, scope, assume, context } = self; - // Remove all `Def` nodes from `dst`, additionally... - let dst = if assume_visibility { - // ...if visibility is assumed, don't check their visibility. - dst.prune(&|def| true) - } else { - // ...otherwise, prune away all unreachable paths through the `Dst` layout. - dst.prune(&|def| context.is_accessible_from(def, scope)) - }; + // Remove all `Def` nodes from `src`, without checking their visibility. + let src = src.prune(&|def| true); - trace!(?dst, "pruned dst"); + trace!(?src, "pruned src"); - // Convert `src` from a tree-based representation to an NFA-based representation. - // If the conversion fails because `src` is uninhabited, conclude that the transmutation - // is acceptable, because instances of the `src` type do not exist. - let src = Nfa::from_tree(src).map_err(|Uninhabited| Answer::Yes)?; + // Remove all `Def` nodes from `dst`, additionally... + let dst = if assume_visibility { + // ...if visibility is assumed, don't check their visibility. + dst.prune(&|def| true) + } else { + // ...otherwise, prune away all unreachable paths through the `Dst` layout. + dst.prune(&|def| context.is_accessible_from(def, scope)) + }; - // Convert `dst` from a tree-based representation to an NFA-based representation. - // If the conversion fails because `src` is uninhabited, conclude that the transmutation - // is unacceptable, because instances of the `dst` type do not exist. - let dst = - Nfa::from_tree(dst).map_err(|Uninhabited| Answer::No(Reason::DstIsPrivate))?; + trace!(?dst, "pruned dst"); - Ok((src, dst)) - }); + // Convert `src` from a tree-based representation to an NFA-based representation. + // If the conversion fails because `src` is uninhabited, conclude that the transmutation + // is acceptable, because instances of the `src` type do not exist. + let src = match Nfa::from_tree(src) { + Ok(src) => src, + Err(Uninhabited) => return Answer::Yes, + }; - match query_or_answer { - Ok(query) => query.answer(), - Err(answer) => answer, - } + // Convert `dst` from a tree-based representation to an NFA-based representation. + // If the conversion fails because `src` is uninhabited, conclude that the transmutation + // is unacceptable, because instances of the `dst` type do not exist. + let dst = match Nfa::from_tree(dst) { + Ok(dst) => dst, + Err(Uninhabited) => return Answer::No(Reason::DstIsPrivate), + }; + + MaybeTransmutableQuery { src, dst, scope, assume, context }.answer() } } @@ -156,14 +136,10 @@ where #[inline(always)] #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))] pub(crate) fn answer(self) -> Answer<::Ref> { - // FIXME(bryangarza): Refactor this code to get rid of `map_layouts` - let query_or_answer = self - .map_layouts(|src, dst, scope, context| Ok((Dfa::from_nfa(src), Dfa::from_nfa(dst)))); - - match query_or_answer { - Ok(query) => query.answer(), - Err(answer) => answer, - } + let Self { src, dst, scope, assume, context } = self; + let src = Dfa::from_nfa(src); + let dst = Dfa::from_nfa(dst); + MaybeTransmutableQuery { src, dst, scope, assume, context }.answer() } } @@ -171,26 +147,8 @@ impl MaybeTransmutableQuery::Ref>, C> where C: QueryContext, { - /// Answers whether a `Nfa` is transmutable into another `Nfa`. - /// - /// This method converts `src` and `dst` to DFAs, then computes an answer using those DFAs. + /// Answers whether a `Dfa` is transmutable into another `Dfa`. pub(crate) fn answer(self) -> Answer<::Ref> { - MaybeTransmutableQuery { - src: &self.src, - dst: &self.dst, - scope: self.scope, - assume: self.assume, - context: self.context, - } - .answer() - } -} - -impl<'l, C> MaybeTransmutableQuery<&'l Dfa<::Ref>, C> -where - C: QueryContext, -{ - pub(crate) fn answer(&mut self) -> Answer<::Ref> { self.answer_memo(&mut Map::default(), self.src.start, self.dst.start) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 9e4fdcda06e52..fc8d19d1a58e2 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -479,6 +479,46 @@ pub trait Into: Sized { /// - `From for U` implies [`Into`]` for T` /// - `From` is reflexive, which means that `From for T` is implemented /// +/// # When to implement `From` +/// +/// While there's no technical restrictions on which conversions can be done using +/// a `From` implementation, the general expectation is that the conversions +/// should typically be restricted as follows: +/// +/// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`] +/// instead; don't provide a `From` impl that panics. +/// +/// * The conversion is *lossless*: semantically, it should not lose or discard +/// information. For example, `i32: From` exists, where the original +/// value can be recovered using `u16: TryFrom`. And `String: From<&str>` +/// exists, where you can get something equivalent to the original value via +/// `Deref`. But `From` cannot be used to convert from `u32` to `u16`, since +/// that cannot succeed in a lossless way. (There's some wiggle room here for +/// information not considered semantically relevant. For example, +/// `Box<[T]>: From>` exists even though it might not preserve capacity, +/// like how two vectors can be equal despite differing capacities.) +/// +/// * The conversion is *value-preserving*: the conceptual kind and meaning of +/// the resulting value is the same, even though the Rust type and technical +/// representation might be different. For example `-1_i8 as u8` is *lossless*, +/// since `as` casting back can recover the original value, but that conversion +/// is *not* available via `From` because `-1` and `255` are different conceptual +/// values (despite being identical bit patterns technically). But +/// `f32: From` *is* available because `1_i16` and `1.0_f32` are conceptually +/// the same real number (despite having very different bit patterns technically). +/// `String: From` is available because they're both *text*, but +/// `String: From` is *not* available, since `1` (a number) and `"1"` +/// (text) are too different. (Converting values to text is instead covered +/// by the [`Display`](crate::fmt::Display) trait.) +/// +/// * The conversion is *obvious*: it's the only reasonable conversion between +/// the two types. Otherwise it's better to have it be a named method or +/// constructor, like how [`str::as_bytes`] is a method and how integers have +/// methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and +/// [`u32::from_be_bytes`], none of which are `From` implementations. Whereas +/// there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr) +/// into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From` exists. +/// /// # Examples /// /// [`String`] implements `From<&str>`: diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 9899014e85a75..bdaeea666221c 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1475,7 +1475,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] pub fn or(self, optb: Option) -> Option { match self { - Some(x) => Some(x), + x @ Some(_) => x, None => optb, } } @@ -1500,7 +1500,7 @@ impl Option { F: FnOnce() -> Option, { match self { - Some(x) => Some(x), + x @ Some(_) => x, None => f(), } } @@ -1530,8 +1530,8 @@ impl Option { #[stable(feature = "option_xor", since = "1.37.0")] pub fn xor(self, optb: Option) -> Option { match (self, optb) { - (Some(a), None) => Some(a), - (None, Some(b)) => Some(b), + (a @ Some(_), None) => a, + (None, b @ Some(_)) => b, _ => None, } } diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 8c46080e43b38..2bb4f3f9e0383 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -125,7 +125,7 @@ impl Once { /// /// # Panics /// - /// The closure `f` will only be executed once if this is called + /// The closure `f` will only be executed once even if this is called /// concurrently amongst many threads. If that closure panics, however, then /// it will *poison* this [`Once`] instance, causing all future invocations of /// `call_once` to also panic. diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 0546807bac4fb..db01ddbde04e3 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -183,7 +183,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for empty lines after documenation comments. + /// Checks for empty lines after documentation comments. /// /// ### Why is this bad? /// The documentation comment was most likely meant to be an inner attribute or regular comment. @@ -795,7 +795,7 @@ impl EarlyLintPass for EarlyAttributes { /// Check for empty lines after outer attributes. /// -/// Attributes and documenation comments are both considered outer attributes +/// Attributes and documentation comments are both considered outer attributes /// by the AST. However, the average user likely considers them to be different. /// Checking for empty lines after each of these attributes is split into two different /// lints but can share the same logic.