From 492826ac144666c75d68bc0a0121453ecc08561f Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sat, 5 Sep 2020 22:37:36 +0200 Subject: [PATCH 01/19] Add a note about the panic behavior of math operations on time objects --- library/std/src/time.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 73c0a7b403a..42f1cde3e1c 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -100,6 +100,11 @@ pub use core::time::Duration; /// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get /// /// **Disclaimer:** These system calls might change over time. +/// +/// > Note: mathematical operations like [`add`] may panic if the underlying +/// > structure cannot represent the new point in time. +/// +/// [`add`]: Instant::add #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct Instant(time::Instant); @@ -174,6 +179,11 @@ pub struct Instant(time::Instant); /// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime /// /// **Disclaimer:** These system calls might change over time. +/// +/// > Note: mathematical operations like [`add`] may panic if the underlying +/// > structure cannot represent the new point in time. +/// +/// [`add`]: SystemTime::add #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTime(time::SystemTime); From a6ff925f8b5598a1f6d84964525baa1d4a08fd63 Mon Sep 17 00:00:00 2001 From: LingMan Date: Mon, 21 Sep 2020 04:53:44 +0200 Subject: [PATCH 02/19] Reduce boilerplate with the matches! macro Replaces simple bool `match`es of the form match $expr { $pattern => true _ => false } and their inverse with invocations of the matches! macro. --- compiler/rustc_middle/src/hir/map/mod.rs | 16 +- .../rustc_middle/src/mir/interpret/mod.rs | 8 +- .../rustc_middle/src/mir/interpret/value.rs | 10 +- compiler/rustc_middle/src/mir/mod.rs | 73 ++++----- compiler/rustc_middle/src/mir/visit.rs | 63 +++----- .../src/traits/specialization_graph.rs | 5 +- compiler/rustc_middle/src/ty/adjustment.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 5 +- compiler/rustc_middle/src/ty/diagnostics.rs | 32 ++-- compiler/rustc_middle/src/ty/instance.rs | 8 +- compiler/rustc_middle/src/ty/layout.rs | 5 +- compiler/rustc_middle/src/ty/mod.rs | 34 ++-- compiler/rustc_middle/src/ty/sty.rs | 145 ++++-------------- 13 files changed, 140 insertions(+), 269 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1e57411f9c5..9ef1dd038d1 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -535,15 +535,15 @@ impl<'hir> Map<'hir> { Some(Node::Binding(_)) => (), _ => return false, } - match self.find(self.get_parent_node(id)) { + matches!( + self.find(self.get_parent_node(id)), Some( Node::Item(_) | Node::TraitItem(_) | Node::ImplItem(_) | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }), - ) => true, - _ => false, - } + ) + ) } /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. @@ -554,10 +554,10 @@ impl<'hir> Map<'hir> { /// Whether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { - match self.get_entry(hir_id).node { - Node::Item(Item { kind: ItemKind::Mod(_), .. }) | Node::Crate(..) => true, - _ => false, - } + matches!( + self.get_entry(hir_id).node, + Node::Item(Item { kind: ItemKind::Mod(_), .. }) | Node::Crate(..) + ) } /// Retrieves the `HirId` for `id`'s enclosing method, unless there's a diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 20363625e42..b5beb3babe2 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -486,10 +486,10 @@ impl<'tcx> TyCtxt<'tcx> { // `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. // However, formatting code relies on function identity (see #58320), so we only do // this for generic functions. Lifetime parameters are ignored. - let is_generic = instance.substs.into_iter().any(|kind| match kind.unpack() { - GenericArgKind::Lifetime(_) => false, - _ => true, - }); + let is_generic = instance + .substs + .into_iter() + .any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_))); if is_generic { // Get a fresh ID. let mut alloc_map = self.alloc_map.lock(); diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 1f547d9dc3a..e5c7d496bac 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -445,19 +445,13 @@ impl<'tcx, Tag> Scalar { /// Do not call this method! Dispatch based on the type instead. #[inline] pub fn is_bits(self) -> bool { - match self { - Scalar::Raw { .. } => true, - _ => false, - } + matches!(self, Scalar::Raw { .. }) } /// Do not call this method! Dispatch based on the type instead. #[inline] pub fn is_ptr(self) -> bool { - match self { - Scalar::Ptr(_) => true, - _ => false, - } + matches!(self, Scalar::Ptr(_)) } pub fn to_bool(self) -> InterpResult<'tcx, bool> { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 8ff75bf392e..03071e716e8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -935,67 +935,59 @@ impl<'tcx> LocalDecl<'tcx> { /// - `let x = ...`, /// - or `match ... { C(x) => ... }` pub fn can_be_made_mutable(&self) -> bool { - match self.local_info { - Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), - opt_ty_info: _, - opt_match_place: _, - pat_span: _, - })))) => true, - - Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( - ImplicitSelfKind::Imm, - )))) => true, - - _ => false, - } + matches!( + self.local_info, + Some(box LocalInfo::User(ClearCrossCrate::Set( + BindingForm::Var(VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info: _, + opt_match_place: _, + pat_span: _, + }) + | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), + ))) + ) } /// Returns `true` if local is definitely not a `ref ident` or /// `ref mut ident` binding. (Such bindings cannot be made into /// mutable bindings, but the inverse does not necessarily hold). pub fn is_nonref_binding(&self) -> bool { - match self.local_info { - Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), - opt_ty_info: _, - opt_match_place: _, - pat_span: _, - })))) => true, - - Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true, - - _ => false, - } + matches!( + self.local_info, + Some(box LocalInfo::User(ClearCrossCrate::Set( + BindingForm::Var(VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info: _, + opt_match_place: _, + pat_span: _, + }) + | BindingForm::ImplicitSelf(_), + ))) + ) } /// Returns `true` if this variable is a named variable or function /// parameter declared by the user. #[inline] pub fn is_user_variable(&self) -> bool { - match self.local_info { - Some(box LocalInfo::User(_)) => true, - _ => false, - } + matches!(self.local_info, Some(box LocalInfo::User(_))) } /// Returns `true` if this is a reference to a variable bound in a `match` /// expression that is used to access said variable for the guard of the /// match arm. pub fn is_ref_for_guard(&self) -> bool { - match self.local_info { - Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true, - _ => false, - } + matches!( + self.local_info, + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) + ) } /// Returns `Some` if this is a reference to a static item that is used to /// access that static pub fn is_ref_to_static(&self) -> bool { - match self.local_info { - Some(box LocalInfo::StaticRef { .. }) => true, - _ => false, - } + matches!(self.local_info, Some(box LocalInfo::StaticRef { .. })) } /// Returns `Some` if this is a reference to a static item that is used to @@ -2124,10 +2116,7 @@ pub enum BinOp { impl BinOp { pub fn is_checkable(self) -> bool { use self::BinOp::*; - match self { - Add | Sub | Mul | Shl | Shr => true, - _ => false, - } + matches!(self, Add | Sub | Mul | Shl | Shr) } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index a008bd5f75f..f4d57dffacf 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1164,82 +1164,63 @@ pub enum PlaceContext { impl PlaceContext { /// Returns `true` if this place context represents a drop. pub fn is_drop(&self) -> bool { - match *self { - PlaceContext::MutatingUse(MutatingUseContext::Drop) => true, - _ => false, - } + matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop)) } /// Returns `true` if this place context represents a borrow. pub fn is_borrow(&self) -> bool { - match *self { + matches!( + self, PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow - | NonMutatingUseContext::UniqueBorrow, - ) - | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true, - _ => false, - } + | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::UniqueBorrow + ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) + ) } /// Returns `true` if this place context represents a storage live or storage dead marker. pub fn is_storage_marker(&self) -> bool { - match *self { - PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => true, - _ => false, - } + matches!( + self, + PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) + ) } /// Returns `true` if this place context represents a storage live marker. pub fn is_storage_live_marker(&self) -> bool { - match *self { - PlaceContext::NonUse(NonUseContext::StorageLive) => true, - _ => false, - } + matches!(self, PlaceContext::NonUse(NonUseContext::StorageLive)) } /// Returns `true` if this place context represents a storage dead marker. pub fn is_storage_dead_marker(&self) -> bool { - match *self { - PlaceContext::NonUse(NonUseContext::StorageDead) => true, - _ => false, - } + matches!(self, PlaceContext::NonUse(NonUseContext::StorageDead)) } /// Returns `true` if this place context represents a use that potentially changes the value. pub fn is_mutating_use(&self) -> bool { - match *self { - PlaceContext::MutatingUse(..) => true, - _ => false, - } + matches!(self, PlaceContext::MutatingUse(..)) } /// Returns `true` if this place context represents a use that does not change the value. pub fn is_nonmutating_use(&self) -> bool { - match *self { - PlaceContext::NonMutatingUse(..) => true, - _ => false, - } + matches!(self, PlaceContext::NonMutatingUse(..)) } /// Returns `true` if this place context represents a use. pub fn is_use(&self) -> bool { - match *self { - PlaceContext::NonUse(..) => false, - _ => true, - } + !matches!(self, PlaceContext::NonUse(..)) } /// Returns `true` if this place context represents an assignment statement. pub fn is_place_assignment(&self) -> bool { - match *self { + matches!( + self, PlaceContext::MutatingUse( MutatingUseContext::Store - | MutatingUseContext::Call - | MutatingUseContext::AsmOutput, - ) => true, - _ => false, - } + | MutatingUseContext::Call + | MutatingUseContext::AsmOutput, + ) + ) } } diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 969404c68ca..ec6010e6eec 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -79,10 +79,7 @@ pub enum Node { impl<'tcx> Node { pub fn is_from_trait(&self) -> bool { - match *self { - Node::Trait(..) => true, - _ => false, - } + matches!(self, Node::Trait(..)) } /// Iterate over the items defined directly by the given (impl or trait) node. diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 46ef5ff7dd8..89d0e139551 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -85,10 +85,7 @@ pub struct Adjustment<'tcx> { impl Adjustment<'tcx> { pub fn is_region_borrow(&self) -> bool { - match self.kind { - Adjust::Borrow(AutoBorrow::Ref(..)) => true, - _ => false, - } + matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..))) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index cd8f12a4f35..d2c7d6e328f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -588,10 +588,7 @@ impl<'tcx> TypeckResults<'tcx> { return false; } - match self.type_dependent_defs().get(expr.hir_id) { - Some(Ok((DefKind::AssocFn, _))) => true, - _ => false, - } + matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _)))) } pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 715319747e3..65703d04c70 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -11,21 +11,16 @@ use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; impl<'tcx> TyS<'tcx> { /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. pub fn is_primitive_ty(&self) -> bool { - match self.kind() { - Bool - | Char - | Str - | Int(_) - | Uint(_) - | Float(_) + matches!( + self.kind(), + Bool | Char | Str | Int(_) | Uint(_) | Float(_) | Infer( InferTy::IntVar(_) | InferTy::FloatVar(_) | InferTy::FreshIntTy(_) - | InferTy::FreshFloatTy(_), - ) => true, - _ => false, - } + | InferTy::FreshFloatTy(_) + ) + ) } /// Whether the type is succinctly representable as a type instead of just referred to with a @@ -64,11 +59,16 @@ impl<'tcx> TyS<'tcx> { /// Whether the type can be safely suggested during error recovery. pub fn is_suggestable(&self) -> bool { - match self.kind() { - Opaque(..) | FnDef(..) | FnPtr(..) | Dynamic(..) | Closure(..) | Infer(..) - | Projection(..) => false, - _ => true, - } + !matches!( + self.kind(), + Opaque(..) + | FnDef(..) + | FnPtr(..) + | Dynamic(..) + | Closure(..) + | Infer(..) + | Projection(..) + ) } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index a6b62097d5b..e527d6dc34c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -183,10 +183,10 @@ impl<'tcx> InstanceDef<'tcx> { ty::InstanceDef::DropGlue(_, Some(_)) => return false, _ => return true, }; - match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::Ctor | DefPathData::ClosureExpr => true, - _ => false, - } + matches!( + tcx.def_key(def_id).disambiguated_data.data, + DefPathData::Ctor | DefPathData::ClosureExpr + ) } /// Returns `true` if the machine code for this instance is instantiated in diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b0a1413a9d6..4e2dac0fd8c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2628,10 +2628,7 @@ where target.target_os == "linux" && target.arch == "sparc64" && target_env_gnu_like; let linux_powerpc_gnu_like = target.target_os == "linux" && target.arch == "powerpc" && target_env_gnu_like; - let rust_abi = match sig.abi { - RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, - _ => false, - }; + let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); // Handle safe Rust thin and fat pointers. let adjust_for_rust_scalar = |attrs: &mut ArgAttributes, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f23d666cfcf..eaf8037d609 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2675,15 +2675,15 @@ impl<'tcx> ClosureKind { /// Returns `true` if this a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { - match (self, other) { - (ClosureKind::Fn, ClosureKind::Fn) => true, - (ClosureKind::Fn, ClosureKind::FnMut) => true, - (ClosureKind::Fn, ClosureKind::FnOnce) => true, - (ClosureKind::FnMut, ClosureKind::FnMut) => true, - (ClosureKind::FnMut, ClosureKind::FnOnce) => true, - (ClosureKind::FnOnce, ClosureKind::FnOnce) => true, - _ => false, - } + matches!( + (self, other), + (ClosureKind::Fn, ClosureKind::Fn) + | (ClosureKind::Fn, ClosureKind::FnMut) + | (ClosureKind::Fn, ClosureKind::FnOnce) + | (ClosureKind::FnMut, ClosureKind::FnMut) + | (ClosureKind::FnMut, ClosureKind::FnOnce) + | (ClosureKind::FnOnce, ClosureKind::FnOnce) + ) } /// Returns the representative scalar type for this closure kind. @@ -2809,15 +2809,15 @@ impl<'tcx> TyCtxt<'tcx> { pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> { let is_associated_item = if let Some(def_id) = def_id.as_local() { - match self.hir().get(self.hir().local_def_id_to_hir_id(def_id)) { - Node::TraitItem(_) | Node::ImplItem(_) => true, - _ => false, - } + matches!( + self.hir().get(self.hir().local_def_id_to_hir_id(def_id)), + Node::TraitItem(_) | Node::ImplItem(_) + ) } else { - match self.def_kind(def_id) { - DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true, - _ => false, - } + matches!( + self.def_kind(def_id), + DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy + ) }; is_associated_item.then(|| self.associated_item(def_id)) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 724ec101b23..5cba451ea6e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1763,10 +1763,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_never(&self) -> bool { - match self.kind() { - Never => true, - _ => false, - } + matches!(self.kind(), Never) } /// Checks whether a type is definitely uninhabited. This is @@ -1823,34 +1820,22 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_adt(&self) -> bool { - match self.kind() { - Adt(..) => true, - _ => false, - } + matches!(self.kind(), Adt(..)) } #[inline] pub fn is_ref(&self) -> bool { - match self.kind() { - Ref(..) => true, - _ => false, - } + matches!(self.kind(), Ref(..)) } #[inline] pub fn is_ty_var(&self) -> bool { - match self.kind() { - Infer(TyVar(_)) => true, - _ => false, - } + matches!(self.kind(), Infer(TyVar(_))) } #[inline] pub fn is_ty_infer(&self) -> bool { - match self.kind() { - Infer(_) => true, - _ => false, - } + matches!(self.kind(), Infer(_)) } #[inline] @@ -1880,20 +1865,14 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_slice(&self) -> bool { match self.kind() { - RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.kind() { - Slice(_) | Str => true, - _ => false, - }, + RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str), _ => false, } } #[inline] pub fn is_array(&self) -> bool { - match self.kind() { - Array(..) => true, - _ => false, - } + matches!(self.kind(), Array(..)) } #[inline] @@ -1940,27 +1919,21 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_region_ptr(&self) -> bool { - match self.kind() { - Ref(..) => true, - _ => false, - } + matches!(self.kind(), Ref(..)) } #[inline] pub fn is_mutable_ptr(&self) -> bool { - match self.kind() { + matches!( + self.kind(), RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. }) - | Ref(_, _, hir::Mutability::Mut) => true, - _ => false, - } + | Ref(_, _, hir::Mutability::Mut) + ) } #[inline] pub fn is_unsafe_ptr(&self) -> bool { - match self.kind() { - RawPtr(_) => true, - _ => false, - } + matches!(self.kind(), RawPtr(_)) } /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). @@ -1990,35 +1963,22 @@ impl<'tcx> TyS<'tcx> { /// contents are abstract to rustc.) #[inline] pub fn is_scalar(&self) -> bool { - match self.kind() { - Bool - | Char - | Int(_) - | Float(_) - | Uint(_) + matches!( + self.kind(), + Bool | Char | Int(_) | Float(_) | Uint(_) | FnDef(..) | FnPtr(_) | RawPtr(_) | Infer(IntVar(_) | FloatVar(_)) - | FnDef(..) - | FnPtr(_) - | RawPtr(_) => true, - _ => false, - } + ) } /// Returns `true` if this type is a floating point type. #[inline] pub fn is_floating_point(&self) -> bool { - match self.kind() { - Float(_) | Infer(FloatVar(_)) => true, - _ => false, - } + matches!(self.kind(), Float(_) | Infer(FloatVar(_))) } #[inline] pub fn is_trait(&self) -> bool { - match self.kind() { - Dynamic(..) => true, - _ => false, - } + matches!(self.kind(), Dynamic(..)) } #[inline] @@ -2031,52 +1991,32 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_closure(&self) -> bool { - match self.kind() { - Closure(..) => true, - _ => false, - } + matches!(self.kind(), Closure(..)) } #[inline] pub fn is_generator(&self) -> bool { - match self.kind() { - Generator(..) => true, - _ => false, - } + matches!(self.kind(), Generator(..)) } #[inline] pub fn is_integral(&self) -> bool { - match self.kind() { - Infer(IntVar(_)) | Int(_) | Uint(_) => true, - _ => false, - } + matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) } #[inline] pub fn is_fresh_ty(&self) -> bool { - match self.kind() { - Infer(FreshTy(_)) => true, - _ => false, - } + matches!(self.kind(), Infer(FreshTy(_))) } #[inline] pub fn is_fresh(&self) -> bool { - match self.kind() { - Infer(FreshTy(_)) => true, - Infer(FreshIntTy(_)) => true, - Infer(FreshFloatTy(_)) => true, - _ => false, - } + matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_))) } #[inline] pub fn is_char(&self) -> bool { - match self.kind() { - Char => true, - _ => false, - } + matches!(self.kind(), Char) } #[inline] @@ -2086,34 +2026,22 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_signed(&self) -> bool { - match self.kind() { - Int(_) => true, - _ => false, - } + matches!(self.kind(), Int(_)) } #[inline] pub fn is_ptr_sized_integral(&self) -> bool { - match self.kind() { - Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true, - _ => false, - } + matches!(self.kind(), Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize)) } #[inline] pub fn is_machine(&self) -> bool { - match self.kind() { - Int(..) | Uint(..) | Float(..) => true, - _ => false, - } + matches!(self.kind(), Int(..) | Uint(..) | Float(..)) } #[inline] pub fn has_concrete_skeleton(&self) -> bool { - match self.kind() { - Param(_) | Infer(_) | Error(_) => false, - _ => true, - } + !matches!(self.kind(), Param(_) | Infer(_) | Error(_)) } /// Returns the type and mutability of `*ty`. @@ -2156,26 +2084,17 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_fn(&self) -> bool { - match self.kind() { - FnDef(..) | FnPtr(_) => true, - _ => false, - } + matches!(self.kind(), FnDef(..) | FnPtr(_)) } #[inline] pub fn is_fn_ptr(&self) -> bool { - match self.kind() { - FnPtr(_) => true, - _ => false, - } + matches!(self.kind(), FnPtr(_)) } #[inline] pub fn is_impl_trait(&self) -> bool { - match self.kind() { - Opaque(..) => true, - _ => false, - } + matches!(self.kind(), Opaque(..)) } #[inline] From b4e77d21bcf8b15ef7d873005382ba8ca309faf5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 15 Jun 2020 11:50:58 -0400 Subject: [PATCH 03/19] rewrite old test so that its attributes are consistent with what we want in the language. (Note that the fact this test existed is a slight sign that we may need a crater run on this bugfix...) --- .../ui/rfc-2565-param-attrs/param-attrs-allowed.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs index 1217f89cb31..a547d09d048 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -8,8 +8,8 @@ extern "C" { #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(unused_mut)] d: i32, - #[forbid(unused_mut)] #[warn(unused_mut)] ... + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] ... ); } @@ -17,16 +17,16 @@ type FnType = fn( #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(unused_mut)] d: i32, - #[forbid(unused_mut)] #[warn(unused_mut)] e: i32 + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] e: i32 ); pub fn foo( #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(unused_mut)] d: i32, - #[forbid(unused_mut)] #[warn(unused_mut)] _e: i32 + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] _e: i32 ) {} // self From 9601724b11bbd9081b1bee6f7e478a5d2b9ace41 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 4 Oct 2020 12:39:39 +0000 Subject: [PATCH 04/19] Avoid unchecked casts in net parser --- library/std/src/net/parser.rs | 69 +++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index 0570a7c41bf..da94a573503 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -6,11 +6,34 @@ #[cfg(test)] mod tests; +use crate::convert::TryInto as _; use crate::error::Error; use crate::fmt; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::str::FromStr; +trait ReadNumberHelper: crate::marker::Sized { + const ZERO: Self; + fn checked_mul(&self, other: u32) -> Option; + fn checked_add(&self, other: u32) -> Option; +} + +macro_rules! impl_helper { + ($($t:ty)*) => ($(impl ReadNumberHelper for $t { + const ZERO: Self = 0; + #[inline] + fn checked_mul(&self, other: u32) -> Option { + Self::checked_mul(*self, other.try_into().ok()?) + } + #[inline] + fn checked_add(&self, other: u32) -> Option { + Self::checked_add(*self, other.try_into().ok()?) + } + })*) +} + +impl_helper! { u8 u16 } + struct Parser<'a> { // parsing as ASCII, so can use byte array state: &'a [u8], @@ -59,7 +82,7 @@ impl<'a> Parser<'a> { fn read_char(&mut self) -> Option { self.state.split_first().map(|(&b, tail)| { self.state = tail; - b as char + char::from(b) }) } @@ -84,25 +107,26 @@ impl<'a> Parser<'a> { }) } - // Read a single digit in the given radix. For instance, 0-9 in radix 10; - // 0-9A-F in radix 16. - fn read_digit(&mut self, radix: u32) -> Option { - self.read_atomically(move |p| p.read_char()?.to_digit(radix)) - } - // Read a number off the front of the input in the given radix, stopping // at the first non-digit character or eof. Fails if the number has more - // digits than max_digits, or the value is >= upto, or if there is no number. - fn read_number(&mut self, radix: u32, max_digits: u32, upto: u32) -> Option { + // digits than max_digits or if there is no number. + fn read_number( + &mut self, + radix: u32, + max_digits: Option, + ) -> Option { self.read_atomically(move |p| { - let mut result = 0; + let mut result = T::ZERO; let mut digit_count = 0; - while let Some(digit) = p.read_digit(radix) { - result = (result * radix) + digit; + while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { + result = result.checked_mul(radix)?; + result = result.checked_add(digit)?; digit_count += 1; - if digit_count > max_digits || result >= upto { - return None; + if let Some(max_digits) = max_digits { + if digit_count > max_digits { + return None; + } } } @@ -116,7 +140,7 @@ impl<'a> Parser<'a> { let mut groups = [0; 4]; for (i, slot) in groups.iter_mut().enumerate() { - *slot = p.read_separator('.', i, |p| p.read_number(10, 3, 0x100))? as u8; + *slot = p.read_separator('.', i, |p| p.read_number(10, None))?; } Some(groups.into()) @@ -140,17 +164,17 @@ impl<'a> Parser<'a> { let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr()); if let Some(v4_addr) = ipv4 { - let octets = v4_addr.octets(); - groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16); - groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16); + let [one, two, three, four] = v4_addr.octets(); + groups[i + 0] = u16::from_be_bytes([one, two]); + groups[i + 1] = u16::from_be_bytes([three, four]); return (i + 2, true); } } - let group = p.read_separator(':', i, |p| p.read_number(16, 4, 0x10000)); + let group = p.read_separator(':', i, |p| p.read_number(16, Some(4))); match group { - Some(g) => *slot = g as u16, + Some(g) => *slot = g, None => return (i, false), } } @@ -195,12 +219,11 @@ impl<'a> Parser<'a> { self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6)) } - /// Read a : followed by a port in base 10 + /// Read a : followed by a port in base 10. fn read_port(&mut self) -> Option { self.read_atomically(|p| { let _ = p.read_given_char(':')?; - let port = p.read_number(10, 5, 0x10000)?; - Some(port as u16) + p.read_number(10, None) }) } From f78a7ade61c1c218eead76854abb7d83bb6c6f75 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 4 Oct 2020 17:07:30 +0000 Subject: [PATCH 05/19] Inline "eof" methods --- library/std/src/net/parser.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index da94a573503..3a5fd8f6f5d 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -44,10 +44,6 @@ impl<'a> Parser<'a> { Parser { state: input.as_bytes() } } - fn is_eof(&self) -> bool { - self.state.is_empty() - } - /// Run a parser, and restore the pre-parse state if it fails fn read_atomically(&mut self, inner: F) -> Option where @@ -63,19 +59,12 @@ impl<'a> Parser<'a> { /// Run a parser, but fail if the entire input wasn't consumed. /// Doesn't run atomically. - fn read_till_eof(&mut self, inner: F) -> Option - where - F: FnOnce(&mut Parser<'_>) -> Option, - { - inner(self).filter(|_| self.is_eof()) - } - - /// Same as read_till_eof, but returns a Result on failure fn parse_with(&mut self, inner: F) -> Result where F: FnOnce(&mut Parser<'_>) -> Option, { - self.read_till_eof(inner).ok_or(AddrParseError(())) + let result = inner(self); + if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(())) } /// Read the next character from the input From afa2a675453091773eb9dd1b19389725526224b9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 15 Jun 2020 14:17:35 -0400 Subject: [PATCH 06/19] Prevent forbid from being ignored if overriden at the same level. That is, this changes `#[forbid(foo)] #[allow(foo)]` from allowing foo to forbidding foo. --- compiler/rustc_lint/src/levels.rs | 47 ++++++++++++++++-- compiler/rustc_middle/src/lint.rs | 20 +++++++- ...0819-dont-override-forbid-in-same-scope.rs | 49 +++++++++++++++++++ ...-dont-override-forbid-in-same-scope.stderr | 29 +++++++++++ src/tools/clippy/tests/ui/attrs.rs | 1 - src/tools/clippy/tests/ui/attrs.stderr | 16 ++---- 6 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs create mode 100644 src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 48254dcee82..222333a578b 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -10,6 +10,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::map::Map; +use rustc_middle::lint::LevelSource; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource}; use rustc_middle::ty::query::Providers; @@ -95,6 +96,44 @@ impl<'s> LintLevelsBuilder<'s> { self.sets.list.push(LintSet::CommandLine { specs }); } + /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful + /// (e.g. if a forbid was already inserted on the same scope), then emits a + /// diagnostic with no change to `specs`. + fn insert_spec( + &mut self, + specs: &mut FxHashMap, + id: LintId, + (level, src): LevelSource, + ) { + if let Some((old_level, old_src)) = specs.get(&id) { + if old_level == &Level::Forbid && level != Level::Forbid { + let mut diag_builder = struct_span_err!( + self.sess, + src.span(), + E0453, + "{}({}) incompatible with previous forbid in same scope", + level.as_str(), + src.name(), + ); + match *old_src { + LintSource::Default => {} + LintSource::Node(_, forbid_source_span, reason) => { + diag_builder.span_label(forbid_source_span, "`forbid` level set here"); + if let Some(rationale) = reason { + diag_builder.note(&rationale.as_str()); + } + } + LintSource::CommandLine(_) => { + diag_builder.note("`forbid` lint level was set on command line"); + } + } + diag_builder.emit(); + return; + } + } + specs.insert(id, (level, src)); + } + /// Pushes a list of AST lint attributes onto this context. /// /// This function will return a `BuilderPush` object which should be passed @@ -109,7 +148,7 @@ impl<'s> LintLevelsBuilder<'s> { /// `#[allow]` /// /// Don't forget to call `pop`! - pub fn push( + pub(crate) fn push( &mut self, attrs: &[ast::Attribute], store: &LintStore, @@ -221,7 +260,7 @@ impl<'s> LintLevelsBuilder<'s> { let src = LintSource::Node(name, li.span(), reason); for &id in ids { self.check_gated_lint(id, attr.span); - specs.insert(id, (level, src)); + self.insert_spec(&mut specs, id, (level, src)); } } @@ -235,7 +274,7 @@ impl<'s> LintLevelsBuilder<'s> { reason, ); for id in ids { - specs.insert(*id, (level, src)); + self.insert_spec(&mut specs, *id, (level, src)); } } Err((Some(ids), new_lint_name)) => { @@ -272,7 +311,7 @@ impl<'s> LintLevelsBuilder<'s> { reason, ); for id in ids { - specs.insert(*id, (level, src)); + self.insert_spec(&mut specs, *id, (level, src)); } } Err((None, _)) => { diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 25e5379881e..91e1d6e0b0b 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -9,7 +9,7 @@ use rustc_session::lint::{builtin, Level, Lint, LintId}; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; /// How a lint level was set. #[derive(Clone, Copy, PartialEq, Eq, HashStable)] @@ -25,6 +25,24 @@ pub enum LintSource { CommandLine(Symbol), } +impl LintSource { + pub fn name(&self) -> Symbol { + match *self { + LintSource::Default => symbol::kw::Default, + LintSource::Node(name, _, _) => name, + LintSource::CommandLine(name) => name, + } + } + + pub fn span(&self) -> Span { + match *self { + LintSource::Default => DUMMY_SP, + LintSource::Node(_, span, _) => span, + LintSource::CommandLine(_) => DUMMY_SP, + } + } +} + pub type LevelSource = (Level, LintSource); pub struct LintLevelSets { diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs new file mode 100644 index 00000000000..8e25227b59e --- /dev/null +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs @@ -0,0 +1,49 @@ +// This test is checking that you cannot override a `forbid` by adding in other +// attributes later in the same scope. (We already ensure that you cannot +// override it in nested scopes). + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and curretly that happens two or three different times, depending on +// compiler flags. +// +// I decided avoiding the redundant output was not worth the time in engineering +// effort for bug like this, which 1. end users are unlikely to run into in the +// first place, and 2. they won't see the redundant output anyway. + +// compile-flags: -Z deduplicate-diagnostics=yes + +fn forbid_first(num: i32) -> i32 { + #![forbid(unused)] + #![deny(unused)] + //~^ ERROR: deny(unused) incompatible with previous forbid in same scope [E0453] + #![warn(unused)] + //~^ ERROR: warn(unused) incompatible with previous forbid in same scope [E0453] + #![allow(unused)] + //~^ ERROR: allow(unused) incompatible with previous forbid in same scope [E0453] + + num * num +} + +fn forbid_last(num: i32) -> i32 { + #![deny(unused)] + #![warn(unused)] + #![allow(unused)] + #![forbid(unused)] + + num * num +} + +fn forbid_multiple(num: i32) -> i32 { + #![forbid(unused)] + #![forbid(unused)] + + num * num +} + +fn main() { + forbid_first(10); + forbid_last(10); + forbid_multiple(10); +} diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr new file mode 100644 index 00000000000..3951c511bf4 --- /dev/null +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -0,0 +1,29 @@ +error[E0453]: deny(unused) incompatible with previous forbid in same scope + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:19:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] + | ^^^^^^ + +error[E0453]: warn(unused) incompatible with previous forbid in same scope + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +... +LL | #![warn(unused)] + | ^^^^^^ + +error[E0453]: allow(unused) incompatible with previous forbid in same scope + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:23:14 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +... +LL | #![allow(unused)] + | ^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/src/tools/clippy/tests/ui/attrs.rs b/src/tools/clippy/tests/ui/attrs.rs index 908d063729f..32685038067 100644 --- a/src/tools/clippy/tests/ui/attrs.rs +++ b/src/tools/clippy/tests/ui/attrs.rs @@ -3,7 +3,6 @@ // Test that the whole restriction group is not enabled #![warn(clippy::restriction)] #![deny(clippy::restriction)] -#![forbid(clippy::restriction)] #![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)] #[inline(always)] diff --git a/src/tools/clippy/tests/ui/attrs.stderr b/src/tools/clippy/tests/ui/attrs.stderr index ef4b89eaa6d..4324984dd60 100644 --- a/src/tools/clippy/tests/ui/attrs.stderr +++ b/src/tools/clippy/tests/ui/attrs.stderr @@ -1,5 +1,5 @@ error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> $DIR/attrs.rs:9:1 + --> $DIR/attrs.rs:8:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[inline(always)] = note: `-D clippy::inline-always` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:29:14 + --> $DIR/attrs.rs:28:14 | LL | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[deprecated(since = "forever")] = note: `-D clippy::deprecated-semver` implied by `-D warnings` error: the since field must contain a semver-compliant version - --> $DIR/attrs.rs:32:14 + --> $DIR/attrs.rs:31:14 | LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ @@ -37,13 +37,5 @@ LL | #![deny(clippy::restriction)] | = help: try enabling only the lints you really need -error: restriction lints are not meant to be all enabled - --> $DIR/attrs.rs:6:11 - | -LL | #![forbid(clippy::restriction)] - | ^^^^^^^^^^^^^^^^^^^ - | - = help: try enabling only the lints you really need - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors From 5ab19676ed25ce52769b06a2fc7319b93d6c64dd Mon Sep 17 00:00:00 2001 From: Robin Schoonover Date: Wed, 16 Sep 2020 19:41:22 -0600 Subject: [PATCH 07/19] Remove extra indirection in LitKind::ByteStr --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/util/literal.rs | 5 ++--- compiler/rustc_builtin_macros/src/source_util.rs | 4 +--- compiler/rustc_mir_build/src/thir/constant.rs | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 95abf552915..492d5788fc0 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1606,7 +1606,7 @@ pub enum LitKind { /// A string literal (`"foo"`). Str(Symbol, StrStyle), /// A byte string (`b"foo"`). - ByteStr(Lrc>), + ByteStr(Lrc<[u8]>), /// A byte char (`b'f'`). Byte(u8), /// A character literal (`'a'`). diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 597e5b437fc..f6f1ad0a9c3 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -4,7 +4,6 @@ use crate::ast::{self, Lit, LitKind}; use crate::token::{self, Token}; use crate::tokenstream::TokenTree; -use rustc_data_structures::sync::Lrc; use rustc_lexer::unescape::{unescape_byte, unescape_char}; use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -108,7 +107,7 @@ impl LitKind { }); error?; buf.shrink_to_fit(); - LitKind::ByteStr(Lrc::new(buf)) + LitKind::ByteStr(buf.into()) } token::ByteStrRaw(_) => { let s = symbol.as_str(); @@ -128,7 +127,7 @@ impl LitKind { symbol.to_string().into_bytes() }; - LitKind::ByteStr(Lrc::new(bytes)) + LitKind::ByteStr(bytes.into()) } token::Err => LitKind::Err(symbol), }) diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 70753208af3..f76bbd83819 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -13,8 +13,6 @@ use rustc_span::{self, Pos, Span}; use smallvec::SmallVec; use std::rc::Rc; -use rustc_data_structures::sync::Lrc; - // These macros all relate to the file system; they either return // the column/row/filename of the expression, or they include // a given file into the current one. @@ -216,7 +214,7 @@ pub fn expand_include_bytes( } }; match cx.source_map().load_binary_file(&file) { - Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))), + Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(bytes.into()))), Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp) diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index a7bb2864daf..b71ff6e7557 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -31,7 +31,7 @@ crate fn lit_to_const<'tcx>( (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { - let allocation = Allocation::from_byte_aligned_bytes(data as &Vec); + let allocation = Allocation::from_byte_aligned_bytes(data as &[u8]); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: data.len() } } From 62f7712a1fd500604f76442f627ea35ce7217177 Mon Sep 17 00:00:00 2001 From: Robin Schoonover Date: Sun, 4 Oct 2020 15:53:37 -0600 Subject: [PATCH 08/19] Change clippy's Constant back to refcount clone byte strings --- src/tools/clippy/clippy_lints/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs index 0000d39263e..062c9bd2d9e 100644 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ b/src/tools/clippy/clippy_lints/src/consts.rs @@ -155,7 +155,7 @@ pub fn lit_to_constant(lit: &LitKind, ty: Option>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), - LitKind::ByteStr(ref s) => Constant::Binary(Lrc::from(s.as_slice())), + LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { From b205436ff66db720cb4b0c503d14ff0a571b14c7 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sun, 4 Oct 2020 16:57:32 -0700 Subject: [PATCH 09/19] Allow anyone to set regression labels --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index bcdc40017b5..8b7b536bcbf 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -3,6 +3,7 @@ allow-unauthenticated = [ "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "D-*", "requires-nightly", + "regression-*", # I-* without I-nominated "I-*", "!I-nominated", "AsyncAwait-OnDeck", From afe83d4c1ca70149b463ac7548cf5d204d3d5844 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sun, 4 Oct 2020 18:35:16 -0700 Subject: [PATCH 10/19] Rename bootstrap/defaults/{config.toml.PROFILE => config.PROFILE.toml} --- src/bootstrap/config.rs | 2 +- .../defaults/{config.toml.codegen => config.codegen.toml} | 0 .../defaults/{config.toml.compiler => config.compiler.toml} | 0 .../defaults/{config.toml.library => config.library.toml} | 0 src/bootstrap/defaults/{config.toml.user => config.user.toml} | 0 src/bootstrap/setup.rs | 4 ++-- 6 files changed, 3 insertions(+), 3 deletions(-) rename src/bootstrap/defaults/{config.toml.codegen => config.codegen.toml} (100%) rename src/bootstrap/defaults/{config.toml.compiler => config.compiler.toml} (100%) rename src/bootstrap/defaults/{config.toml.library => config.library.toml} (100%) rename src/bootstrap/defaults/{config.toml.user => config.user.toml} (100%) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5314398ce9a..6265bbaf5c2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -574,7 +574,7 @@ impl Config { include_path.push("src"); include_path.push("bootstrap"); include_path.push("defaults"); - include_path.push(format!("config.toml.{}", include)); + include_path.push(format!("config.{}.toml", include)); let included_toml = get_toml(&include_path); toml.merge(included_toml); } diff --git a/src/bootstrap/defaults/config.toml.codegen b/src/bootstrap/defaults/config.codegen.toml similarity index 100% rename from src/bootstrap/defaults/config.toml.codegen rename to src/bootstrap/defaults/config.codegen.toml diff --git a/src/bootstrap/defaults/config.toml.compiler b/src/bootstrap/defaults/config.compiler.toml similarity index 100% rename from src/bootstrap/defaults/config.toml.compiler rename to src/bootstrap/defaults/config.compiler.toml diff --git a/src/bootstrap/defaults/config.toml.library b/src/bootstrap/defaults/config.library.toml similarity index 100% rename from src/bootstrap/defaults/config.toml.library rename to src/bootstrap/defaults/config.library.toml diff --git a/src/bootstrap/defaults/config.toml.user b/src/bootstrap/defaults/config.user.toml similarity index 100% rename from src/bootstrap/defaults/config.toml.user rename to src/bootstrap/defaults/config.user.toml diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 9d3a889aa00..8a77641fbfe 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -20,7 +20,7 @@ pub fn setup(src_path: &Path, include_name: &str) { file.display() ); println!( - "note: this will use the configuration in {}/src/bootstrap/defaults/config.toml.{}", + "note: this will use the configuration in {}/src/bootstrap/defaults/config.{}.toml", src_path.display(), include_name ); @@ -36,7 +36,7 @@ pub fn setup(src_path: &Path, include_name: &str) { t!(fs::write(path, settings)); let include_path = - format!("{}/src/bootstrap/defaults/config.toml.{}", src_path.display(), include_name); + format!("{}/src/bootstrap/defaults/config.{}.toml", src_path.display(), include_name); println!("`x.py` will now use the configuration at {}", include_path); let suggestions = match include_name { From 5388eb41e940cddaf8ae4ea812c4e04a3e9d9401 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sun, 4 Oct 2020 18:39:59 -0700 Subject: [PATCH 11/19] Add changelog entry mentioning the renamed profile files --- src/bootstrap/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index d8c704f451b..7c12642da35 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -7,6 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Non-breaking changes since the last major version] - `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473) +- The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558) + ## [Version 2] - 2020-09-25 From c877ff3664abea60d69b8acf8e7dce85c2ffd859 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 4 Oct 2020 19:08:40 -0700 Subject: [PATCH 12/19] Fix rustdoc warnings about invalid Rust syntax --- compiler/rustc_mir/src/borrow_check/region_infer/mod.rs | 4 +++- compiler/rustc_mir/src/util/pretty.rs | 3 ++- compiler/rustc_trait_selection/src/opaque_types.rs | 7 +++++-- compiler/rustc_typeck/src/check/expr.rs | 4 ++-- compiler/rustc_typeck/src/check/pat.rs | 4 ++-- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index 3dc082a4413..053ca7c23d2 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -1225,7 +1225,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// it. However, it works pretty well in practice. In particular, /// this is needed to deal with projection outlives bounds like /// - /// >::Item: '1 + /// ```ignore (MIR syntax) + /// >::Item: '1 + /// ``` /// /// In particular, this routine winds up being important when /// there are bounds like `where >::Item: 'b` in the diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 49c644a20bf..67bc886b938 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -659,7 +659,8 @@ pub fn write_allocations<'tcx>( /// Dumps the size and metadata and content of an allocation to the given writer. /// The expectation is that the caller first prints other relevant metadata, so the exact /// format of this function is (*without* leading or trailing newline): -/// ``` +/// +/// ```text /// size: {}, align: {}) { /// /// } diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 28697ec4e3b..4f351ab176d 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -38,13 +38,16 @@ pub struct OpaqueTypeDecl<'tcx> { /// then `substs` would be `['a, T]`. pub substs: SubstsRef<'tcx>, - /// The span of this particular definition of the opaque type. So + /// The span of this particular definition of the opaque type. So /// for example: /// /// ``` /// type Foo = impl Baz; /// fn bar() -> Foo { - /// ^^^ This is the span we are looking for! + /// // ^^^ This is the span we are looking for! + /// // ... + /// # unimplemented!() + /// } /// ``` /// /// In cases where the fn returns `(impl Trait, impl Trait)` or diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index af800eab67a..179e383be2e 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1275,7 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Report an error for a struct field expression when there are fields which aren't provided. /// - /// ```ignore (diagnostic) + /// ```text /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo` /// --> src/main.rs:8:5 /// | @@ -1327,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Report an error for a struct field expression when there are no visible fields. /// - /// ```ignore (diagnostic) + /// ```text /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields /// --> src/main.rs:8:5 /// | diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 3e431a9c000..53bc2069b76 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1381,7 +1381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a diagnostic reporting a struct pattern which is missing an `..` due to /// inaccessible fields. /// - /// ```ignore (diagnostic) + /// ```text /// error: pattern requires `..` due to inaccessible fields /// --> src/main.rs:10:9 /// | @@ -1431,7 +1431,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a diagnostic reporting a struct pattern which does not mention some fields. /// - /// ```ignore (diagnostic) + /// ```text /// error[E0027]: pattern does not mention field `you_cant_use_this_field` /// --> src/main.rs:15:9 /// | From b1ce6190ae4cb412c21207932924889e7201d4df Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 26 Sep 2020 15:31:30 +0200 Subject: [PATCH 13/19] Add missing examples for MaybeUninit --- library/core/src/mem/maybe_uninit.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index e629d28eae1..862c452a434 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -246,6 +246,14 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. /// + /// # Example + /// + /// ``` + /// use std::mem::MaybeUninit; + /// + /// let v: MaybeUninit> = MaybeUninit::new(vec![42]); + /// ``` + /// /// [`assume_init`]: MaybeUninit::assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] @@ -259,9 +267,15 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. /// - /// See the [type-level documentation][type] for some examples. + /// See the [type-level documentation][MaybeUninit] for some examples. /// - /// [type]: union.MaybeUninit.html + /// # Example + /// + /// ``` + /// use std::mem::MaybeUninit; + /// + /// let v: MaybeUninit = MaybeUninit::uninit(); + /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] #[inline(always)] From 554145609484d111f6ca3acaca644ae881c20a10 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 5 Oct 2020 22:47:52 +0800 Subject: [PATCH 14/19] Hint doc use convert::identity relative link --- library/core/src/hint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 4eb47dd1378..5d8137f91ee 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -98,8 +98,6 @@ pub fn spin_loop() { /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what /// `black_box` could do. /// -/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html -/// /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can /// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined /// behavior in the calling code. This property makes `black_box` useful for writing code in which @@ -108,6 +106,8 @@ pub fn spin_loop() { /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness* in any way. +/// +/// [`std::convert::identity`]: ../convert/fn.identity.html #[cfg_attr(not(miri), inline)] #[cfg_attr(miri, inline(never))] #[unstable(feature = "test", issue = "50297")] From cb881d36ae0060e1dc6815e7caefe4e8df79dc09 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 5 Oct 2020 23:29:43 +0800 Subject: [PATCH 15/19] hint doc use intra-doc links Co-authored-by: Joshua Nelson --- library/core/src/hint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5d8137f91ee..454fb34e77e 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -107,7 +107,7 @@ pub fn spin_loop() { /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness* in any way. /// -/// [`std::convert::identity`]: ../convert/fn.identity.html +/// [`std::convert::identity`]: crate::convert::identity #[cfg_attr(not(miri), inline)] #[cfg_attr(miri, inline(never))] #[unstable(feature = "test", issue = "50297")] From 35192ff574c3706646e2f4be16d5c22c4f8b60b1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 5 Oct 2020 11:19:08 -0700 Subject: [PATCH 16/19] Fix span for unicode escape suggestion. --- compiler/rustc_parse/src/lexer/unescape_error_reporting.rs | 5 ++--- src/test/ui/fmt/format-string-error-2.stderr | 4 +--- src/test/ui/parser/issue-23620-invalid-escapes.stderr | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 6f249f491a6..47d317f9188 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -181,10 +181,9 @@ pub(crate) fn emit_unescape_error( if suggestion_len > 0 { suggestion.push('}'); - let lo = char_span.lo(); - let hi = lo + BytePos(suggestion_len as u32); + let hi = char_span.lo() + BytePos(suggestion_len as u32); diag.span_suggestion( - span.with_lo(lo).with_hi(hi), + span.with_hi(hi), "format of unicode escape sequences uses braces", suggestion, Applicability::MaybeIncorrect, diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index d202044a2bb..c421fe49ef0 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -2,9 +2,7 @@ error: incorrect unicode escape sequence --> $DIR/format-string-error-2.rs:77:20 | LL | println!("\x7B}\u8 {", 1); - | ^^- - | | - | help: format of unicode escape sequences uses braces: `\u{8}` + | ^^^ help: format of unicode escape sequences uses braces: `\u{8}` error: invalid format string: expected `'}'`, found `'a'` --> $DIR/format-string-error-2.rs:5:5 diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index b391ac75bf8..8c924ad0330 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -80,9 +80,9 @@ error: incorrect unicode escape sequence --> $DIR/issue-23620-invalid-escapes.rs:32:14 | LL | let _ = "\u8f"; - | ^^-- - | | - | help: format of unicode escape sequences uses braces: `\u{8f}` + | ^^^- + | | + | help: format of unicode escape sequences uses braces: `\u{8f}` error: aborting due to 13 previous errors From 8d11f90a16fb374d68b4aae5486c3e12c74c63b7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 5 Oct 2020 15:32:25 -0400 Subject: [PATCH 17/19] Record `expansion_that_defined` into crate metadata Fixes #77523 Now that hygiene serialization is implemented, we also need to record `expansion_that_defined` so that we properly handle a foreign `SyntaxContext`. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++++ .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 5 +++++ compiler/rustc_middle/src/ty/mod.rs | 6 ++++-- .../hygiene/auxiliary/def-site-async-await.rs | 7 +++++++ .../ui/hygiene/auxiliary/opaque-hygiene.rs | 21 +++++++++++++++++++ .../issue-77523-def-site-async-await.rs | 19 +++++++++++++++++ 9 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/hygiene/auxiliary/def-site-async-await.rs create mode 100644 src/test/ui/hygiene/auxiliary/opaque-hygiene.rs create mode 100644 src/test/ui/hygiene/issue-77523-def-site-async-await.rs diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c31e941b3ff..8b11d2c913a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1011,6 +1011,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) } + fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId { + self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) + } + /// Iterates over all the stability attributes in the given crate. fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 4102cf84a67..578ce382912 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -238,6 +238,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } crate_extern_paths => { cdata.source().paths().cloned().collect() } + expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f58a792ef58..4350ac5c27a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -747,6 +747,7 @@ impl EncodeContext<'a, 'tcx> { ty::Visibility::from_hir(enum_vis, enum_id, self.tcx)); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index @@ -883,6 +884,7 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.visibility[def_id] <- field.vis); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); self.encode_ident_span(def_id, field.ident); self.encode_stability(def_id); self.encode_deprecation(def_id); @@ -924,6 +926,7 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr)); record!(self.tables.visibility[def_id] <- ctor_vis); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); self.encode_stability(def_id); self.encode_deprecation(def_id); self.encode_item_type(def_id); @@ -1339,6 +1342,7 @@ impl EncodeContext<'a, 'tcx> { ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- item.attrs); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <- diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 1a127035d4f..9e26d02e4e1 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -294,6 +294,7 @@ define_tables! { variances: Table>, generics: Table>, explicit_predicates: Table)>, + expn_that_defined: Table>, // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate` // doesn't handle shorthands in its own (de)serialization impls, // as it's an `enum` for which we want to derive (de)serialization, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d5b99ea4d28..fe115bbb9c3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -191,6 +191,11 @@ rustc_queries! { eval_always desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) } } + + /// Internal helper query. Use `tcx.expansion_that_defined` instead + query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } + } } Codegen { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b7530c077cc..7f77334acee 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3034,10 +3034,12 @@ impl<'tcx> TyCtxt<'tcx> { .hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id)) } - fn expansion_that_defined(self, scope: DefId) -> ExpnId { + pub fn expansion_that_defined(self, scope: DefId) -> ExpnId { match scope.as_local() { + // Parsing and expansion aren't incremental, so we don't + // need to go through a query for the same-crate case. Some(scope) => self.hir().definitions().expansion_that_defined(scope), - None => ExpnId::root(), + None => self.expn_that_defined(scope), } } diff --git a/src/test/ui/hygiene/auxiliary/def-site-async-await.rs b/src/test/ui/hygiene/auxiliary/def-site-async-await.rs new file mode 100644 index 00000000000..f7e9b801318 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/def-site-async-await.rs @@ -0,0 +1,7 @@ +// edition:2018 + +extern crate opaque_hygiene; + +pub async fn serve() { + opaque_hygiene::make_it!(); +} diff --git a/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs b/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs new file mode 100644 index 00000000000..7730f91bd6a --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, quote}; + +#[proc_macro] +pub fn make_it(input: TokenStream) -> TokenStream { + // `quote!` applies def-site hygiene + quote! { + trait Foo { + fn my_fn(&self) {} + } + + impl Foo for T {} + "a".my_fn(); + } +} diff --git a/src/test/ui/hygiene/issue-77523-def-site-async-await.rs b/src/test/ui/hygiene/issue-77523-def-site-async-await.rs new file mode 100644 index 00000000000..2af60ff6f53 --- /dev/null +++ b/src/test/ui/hygiene/issue-77523-def-site-async-await.rs @@ -0,0 +1,19 @@ +// build-pass +// aux-build:opaque-hygiene.rs +// aux-build:def-site-async-await.rs + +// Regression test for issue #77523 +// Tests that we don't ICE when an unusual combination +// of def-site hygiene and cross-crate monomorphization occurs. + +extern crate def_site_async_await; + +use std::future::Future; + +fn mk_ctxt() -> std::task::Context<'static> { + panic!() +} + +fn main() { + Box::pin(def_site_async_await::serve()).as_mut().poll(&mut mk_ctxt()); +} From c8d25af6985c2c6be388fc198c2c7d50eb553fc4 Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 5 Oct 2020 15:07:27 -0700 Subject: [PATCH 18/19] Fixup --- compiler/rustc_mir/src/borrow_check/region_infer/mod.rs | 2 +- compiler/rustc_trait_selection/src/opaque_types.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index 053ca7c23d2..6264f521c62 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -1225,7 +1225,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// it. However, it works pretty well in practice. In particular, /// this is needed to deal with projection outlives bounds like /// - /// ```ignore (MIR syntax) + /// ```ignore (internal compiler representation so lifetime syntax is invalid) /// >::Item: '1 /// ``` /// diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 4f351ab176d..618f3e045e7 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -41,13 +41,10 @@ pub struct OpaqueTypeDecl<'tcx> { /// The span of this particular definition of the opaque type. So /// for example: /// - /// ``` + /// ```ignore (incomplete snippet) /// type Foo = impl Baz; /// fn bar() -> Foo { /// // ^^^ This is the span we are looking for! - /// // ... - /// # unimplemented!() - /// } /// ``` /// /// In cases where the fn returns `(impl Trait, impl Trait)` or From dc5a000d794329c1cac5dc94871329fcb8b30123 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 17 Sep 2020 18:05:56 -0400 Subject: [PATCH 19/19] Revamp rustdoc docs about documentation using `cfg` - Move `cfg(doc)` out of `unstable-features`. It's not unstable. - Remove outdated reference to `everybody_loops`. - Improve wording in various places - Give an example of code this allows (and does not allow) - Link to `cfg(doc)` in `doc(cfg)` documentation. Since one is stable and the other is not, don't combine them. - Cleanup wording for `doc(cfg)` - Incorporate changes from #76849 - Mention that `doc(cfg)` is also for features --- src/doc/rustdoc/src/advanced-features.md | 38 ++++++++++++++++++++++-- src/doc/rustdoc/src/unstable-features.md | 33 +++++++++----------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index c9a0dff5ab3..cad5648be48 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -2,7 +2,7 @@ The features listed on this page fall outside the rest of the main categories. -## `#[cfg(doc)]`: Documenting platform-/feature-specific information +## `#[cfg(doc)]`: Documenting platform-specific or feature-specific information For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things from the host target are available (or from the given `--target` if present), and everything else is @@ -17,7 +17,7 @@ with other `#[cfg]` filters on it, you can write something like `#[cfg(any(windo This will preserve the item either when built normally on Windows, or when being documented anywhere. -Please note that this feature is not passed to doctests. +Please note that this `cfg` is not passed to doctests. Example: @@ -33,6 +33,40 @@ pub struct UnixToken; Here, the respective tokens can only be used by dependent crates on their respective platforms, but they will both appear in documentation. +### Interactions between platform-specific docs + +Rustdoc does not have a magic way to compile documentation 'as-if' you'd run it once for each +platform (such a magic wand has been called the ['holy grail of rustdoc'][#1998]). Instead, +it sees *all* of your code at once, the same way the Rust compiler would if you passed it +`--cfg doc`. However, Rustdoc has a trick up its sleeve to handle platform-specific code if it +*does* receive it. + +To document your crate, Rustdoc only needs to know the public signature of your functions. +In particular, it doesn't have to know how any of your functions are implemented, so it ignores +all type errors and name resolution errors with function bodies. Note that this does *not* +work for anything outside a function body: since Rustdoc documents your types, it has to +know what those types are! For example, this code will work regardless of the platform: + + +```ignore +pub fn f() { + use std::os::windows::ffi::OsStrExt; +} +``` + +but this will not, because the unknown type is part of the function signature: + +```ignore +pub fn f() -> std::os::windows::ffi::EncodeWide<'static> { + unimplemented!() +} +``` + +For a more realistic example of code this allows, see [the rustdoc test suite][realistic-async]. + +[#1998]: https://github.com/rust-lang/rust/issues/1998 +[realistic-async]: https://github.com/rust-lang/rust/blob/b146000e910ccd60bdcde89363cb6aa14ecc0d95/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs + ## Add aliases for an item in documentation search This feature allows you to add alias(es) to an item when using the `rustdoc` search through the diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index e4d8818b56c..16157a4b080 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -43,28 +43,16 @@ plain text. These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler and enabled with a `#![feature(...)]` attribute in your crate. -### Documenting platform-/feature-specific information +### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present -Because of the way Rustdoc documents a crate, the documentation it creates is specific to the target -rustc compiles for. Anything that's specific to any other target is dropped via `#[cfg]` attribute -processing early in the compilation process. However, Rustdoc has a trick up its sleeve to handle -platform-specific code if it *does* receive it. +You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on. +This has two effects: -Because Rustdoc doesn't need to fully compile a crate to binary, it replaces function bodies with -`loop {}` to prevent having to process more than necessary. This means that any code within a -function that requires platform-specific pieces is ignored. Combined with a special attribute, -`#[doc(cfg(...))]`, you can tell Rustdoc exactly which platform something is supposed to run on, -ensuring that doctests are only run on the appropriate platforms. - -The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders documentation for that -item, it will be accompanied by a banner explaining that the item is only available on certain -platforms. - -For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently -running on. To aid this, Rustdoc sets the flag `#[cfg(doc)]` when running on your crate. -Combining this with the target platform of a given item allows it to appear when building your crate -normally on that platform, as well as when building documentation anywhere. +1. doctests will only run on the appropriate platforms, and +2. When Rustdoc renders documentation for that item, it will be accompanied by a banner explaining + that the item is only available on certain platforms. +`#[doc(cfg)]` is intended to be used alongside [`#[cfg(doc)]`][cfg-doc]. For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that the item is supposed to be used on Windows. For example: @@ -81,6 +69,12 @@ pub struct WindowsToken; #[cfg(any(unix, doc))] #[doc(cfg(unix))] pub struct UnixToken; + +/// Token struct that is only available with the `serde` feature +#[cfg(feature = "serde")] +#[doc(cfg(feature = "serde"))] +#[derive(serde::Deserialize)] +pub struct SerdeToken; ``` In this sample, the tokens will only appear on their respective platforms, but they will both appear @@ -90,6 +84,7 @@ in documentation. `#![feature(doc_cfg)]` feature gate. For more information, see [its chapter in the Unstable Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. +[cfg-doc]: ./advanced-features.md [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781