From 33788c252c83aeea913482b283e33ccc41bd2860 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 24 Aug 2019 14:49:17 +0200 Subject: [PATCH 01/29] Added table containing the system calls used by Instant and SystemTime. --- src/libstd/time.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 98371b9ba3d7e..f03020bb4954e 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -59,6 +59,21 @@ pub use core::time::Duration; /// println!("{}", now.elapsed().as_secs()); /// } /// ``` +/// +/// # Underlying System calls +/// Currently, the following system calls are being used to get the current time using `now()`: +/// +/// | Platform | System call | +/// |:---------:|:------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Monotonic Clock)](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt) | +/// | SGX | Not implemented | +/// | UNIX | [mach_absolute_time](https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html) | +/// | VXWorks | [clock_gettime (Monotonic Clock)](https://linux.die.net/man/3/clock_gettime) | +/// | WASI | [__wasi_clock_time_get (Monotonic Clock)](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get) | +/// | Windows | [QueryPerformanceCounter](https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter) | +/// +/// **Disclaimer:** These system calls might change over time. +/// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct Instant(time::Instant); @@ -114,6 +129,21 @@ pub struct Instant(time::Instant); /// } /// } /// ``` +/// +/// # Underlying System calls +/// Currently, the following system calls are being used to get the current time using `now()`: +/// +/// | Platform | System call | +/// |:---------:|:------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Realtime Clock)](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt) | +/// | SGX | Not implemented | +/// | UNIX | [gettimeofday](http://man7.org/linux/man-pages/man2/gettimeofday.2.html) | +/// | VXWorks | [clock_gettime (Realtime Clock)](https://linux.die.net/man/3/clock_gettime) | +/// | WASI | [__wasi_clock_time_get (Realtime Clock)](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get) | +/// | Windows | [GetSystemTimeAsFileTime](https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime) | +/// +/// **Disclaimer:** These system calls might change over time. +/// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTime(time::SystemTime); From 1478ef45287c4da0da0daf1715d00e8b06fa333b Mon Sep 17 00:00:00 2001 From: Christian Veenman <46896178+DevQps@users.noreply.github.com> Date: Mon, 26 Aug 2019 22:05:26 +0200 Subject: [PATCH 02/29] Update src/libstd/time.rs Co-Authored-By: lzutao --- src/libstd/time.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index f03020bb4954e..c05f02389dfa0 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -70,7 +70,9 @@ pub use core::time::Duration; /// | UNIX | [mach_absolute_time](https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html) | /// | VXWorks | [clock_gettime (Monotonic Clock)](https://linux.die.net/man/3/clock_gettime) | /// | WASI | [__wasi_clock_time_get (Monotonic Clock)](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get) | -/// | Windows | [QueryPerformanceCounter](https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter) | +/// | Windows | [QueryPerformanceCounter] | + +[QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter /// /// **Disclaimer:** These system calls might change over time. /// From ff63bf8fc7a19ca27b3d43aa36036f8e77567b20 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Tue, 3 Sep 2019 01:28:33 -0600 Subject: [PATCH 03/29] Fix minor typo in docs. --- src/librustc_mir/const_eval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 5aa487d901663..a745559d8514d 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -589,7 +589,7 @@ pub fn const_eval_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { - // see comment in const_eval_provider for what we're doing here + // see comment in const_eval_raw_provider for what we're doing here if key.param_env.reveal == Reveal::All { let mut key = key.clone(); key.param_env.reveal = Reveal::UserFacing; From 7589d3a400dfaa13027232ef0a5352fd20680193 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Tue, 3 Sep 2019 01:54:48 -0600 Subject: [PATCH 04/29] Update other doc. Value was renamed to Operand in https://github.com/rust-lang/rust/commit/ad2de8b4ee099916113b7b3577ac86857b1568be ScalarPair to Slice in https://github.com/rust-lang/rust/commit/fe50b4eb1d6f7a31c53798bca3d0fa2b0670fa3d Not familiar enough with rustc's source to know if the comment is even still applicable. --- src/librustc/mir/interpret/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 3da5a65c37932..811c872968a56 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -17,8 +17,8 @@ pub struct RawConst<'tcx> { pub ty: Ty<'tcx>, } -/// Represents a constant value in Rust. `Scalar` and `ScalarPair` are optimizations that -/// match the `LocalState` optimizations for easy conversions between `Value` and `ConstValue`. +/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations that +/// match the `LocalState` optimizations for easy conversions between `Operand` and `ConstValue`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, HashStable)] pub enum ConstValue<'tcx> { From 36b37e22de92b584b9cf4464ed1d4ad317b798be Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Sep 2019 08:25:54 +1000 Subject: [PATCH 05/29] Remove two unnecessary `clone()` calls. --- src/librustc_typeck/check/closure.rs | 6 +++--- src/librustc_typeck/check/compare_method.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index e9370429f3f55..d626bff150020 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -529,11 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); // recreated from (*) above // Check that E' = S'. - let cause = &self.misc(hir_ty.span); + let cause = self.misc(hir_ty.span); let InferOk { value: (), obligations, - } = self.at(cause, self.param_env) + } = self.at(&cause, self.param_env) .eq(*expected_ty, supplied_ty)?; all_obligations.extend(obligations); @@ -549,7 +549,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); all_obligations.push( Obligation::new( - cause.clone(), + cause, self.param_env, ty::Predicate::TypeOutlives( ty::Binder::dummy( diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8e187b7e05b51..74ea93fc44270 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -308,7 +308,7 @@ fn compare_predicate_entailment<'tcx>( let cause = ObligationCause { span: impl_err_span, - ..cause.clone() + ..cause }; let mut diag = struct_span_err!(tcx.sess, From c1b9a46f60440e2207f458e276b38239b1651a22 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Sep 2019 14:06:14 +1000 Subject: [PATCH 06/29] Add some assertions on obligation type sizes. These are types that get memcpy'd a lot. --- src/librustc/traits/fulfill.rs | 4 ++++ src/librustc/traits/mod.rs | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index c1de4939c1d91..a59ea19896364 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -68,6 +68,10 @@ pub struct PendingPredicateObligation<'tcx> { pub stalled_on: Vec>, } +// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PendingPredicateObligation<'_>, 160); + impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. pub fn new() -> FulfillmentContext<'tcx> { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1ca92d79fa5f6..f43fbbfee3e91 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -123,6 +123,10 @@ pub struct Obligation<'tcx, T> { pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PredicateObligation<'_>, 136); + /// The reason why we incurred this obligation; used for error reporting. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ObligationCause<'tcx> { @@ -269,6 +273,10 @@ pub enum ObligationCauseCode<'tcx> { TrivialBound, } +// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(ObligationCauseCode<'_>, 56); + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DerivedObligationCause<'tcx> { /// The trait reference of the parent obligation that led to the From b972ac818c98373b6d045956b049dc34932c41be Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2019 16:55:19 +1000 Subject: [PATCH 07/29] Shrink `ObligationCauseCode` by boxing `MatchExpressionArm`. The reduction in `memcpy` calls greatly outweighs the cost of the extra allocations, for a net performance win. --- src/librustc/infer/error_reporting/mod.rs | 24 ++++++++++++----------- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/mod.rs | 24 +++++++++++++---------- src/librustc/traits/structural_impls.rs | 8 ++++---- src/librustc_typeck/check/_match.rs | 18 +++++++++-------- 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 5883be6e26883..684e799b40319 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,7 @@ use crate::hir::def_id::DefId; use crate::hir::Node; use crate::infer::opaque_types; use crate::middle::region; -use crate::traits::{ObligationCause, ObligationCauseCode}; +use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; @@ -624,13 +624,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } } - ObligationCauseCode::MatchExpressionArm { + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { source, ref prior_arms, last_ty, discrim_hir_id, .. - } => match source { + }) => match source { hir::MatchSource::IfLetDesugar { .. } => { let msg = "`if let` arms have incompatible types"; err.span_label(cause.span, msg); @@ -1622,13 +1622,15 @@ impl<'tcx> ObligationCause<'tcx> { use crate::traits::ObligationCauseCode::*; match self.code { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), - MatchExpressionArm { source, .. } => Error0308(match source { - hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types", - hir::MatchSource::TryDesugar => { - "try expression alternatives have incompatible types" - } - _ => "match arms have incompatible types", - }), + MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => + Error0308(match source { + hir::MatchSource::IfLetDesugar { .. } => + "`if let` arms have incompatible types", + hir::MatchSource::TryDesugar => { + "try expression alternatives have incompatible types" + } + _ => "match arms have incompatible types", + }), IfExpression { .. } => Error0308("if and else have incompatible types"), IfExpressionWithNoElse => Error0317("if may be missing an else clause"), MainFunctionType => Error0580("main function has wrong type"), @@ -1656,7 +1658,7 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { CompareImplMethodObligation { .. } => "method type is compatible with trait", ExprAssignable => "expression is assignable", - MatchExpressionArm { source, .. } => match source { + MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source { hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types", _ => "match arms have compatible types", }, diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index a59ea19896364..0b8de1f13d384 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -70,7 +70,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PendingPredicateObligation<'_>, 160); +static_assert_size!(PendingPredicateObligation<'_>, 144); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index f43fbbfee3e91..548fb55098af1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -125,7 +125,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PredicateObligation<'_>, 136); +static_assert_size!(PredicateObligation<'_>, 120); /// The reason why we incurred this obligation; used for error reporting. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -151,7 +151,8 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::StartFunctionType => { tcx.sess.source_map().def_span(self.span) } - ObligationCauseCode::MatchExpressionArm { arm_span, .. } => arm_span, + ObligationCauseCode::MatchExpressionArm( + box MatchExpressionArmCause { arm_span, .. }) => arm_span, _ => self.span, } } @@ -227,13 +228,7 @@ pub enum ObligationCauseCode<'tcx> { ExprAssignable, /// Computing common supertype in the arms of a match expression - MatchExpressionArm { - arm_span: Span, - source: hir::MatchSource, - prior_arms: Vec, - last_ty: Ty<'tcx>, - discrim_hir_id: hir::HirId, - }, + MatchExpressionArm(Box>), /// Computing common supertype in the pattern guard for the arms of a match expression MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> }, @@ -275,7 +270,16 @@ pub enum ObligationCauseCode<'tcx> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(ObligationCauseCode<'_>, 56); +static_assert_size!(ObligationCauseCode<'_>, 40); + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct MatchExpressionArmCause<'tcx> { + pub arm_span: Span, + pub source: hir::MatchSource, + pub prior_arms: Vec, + pub last_ty: Ty<'tcx>, + pub discrim_hir_id: hir::HirId, +} #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DerivedObligationCause<'tcx> { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 05b698eb4c4ea..56324baffa038 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -508,21 +508,21 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { trait_item_def_id, }), super::ExprAssignable => Some(super::ExprAssignable), - super::MatchExpressionArm { + super::MatchExpressionArm(box super::MatchExpressionArmCause { arm_span, source, ref prior_arms, last_ty, discrim_hir_id, - } => { + }) => { tcx.lift(&last_ty).map(|last_ty| { - super::MatchExpressionArm { + super::MatchExpressionArm(box super::MatchExpressionArmCause { arm_span, source, prior_arms: prior_arms.clone(), last_ty, discrim_hir_id, - } + }) }) } super::MatchExpressionArmPattern { span, ty } => { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 7427ae9ce8de3..8ce08f523a1b0 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -2,7 +2,7 @@ use crate::check::{FnCtxt, Expectation, Diverges, Needs}; use crate::check::coercion::CoerceMany; use rustc::hir::{self, ExprKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::traits::{ObligationCause, ObligationCauseCode}; +use rustc::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; use rustc::ty::Ty; use syntax_pos::Span; @@ -146,13 +146,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The reason for the first arm to fail is not that the match arms diverge, // but rather that there's a prior obligation that doesn't hold. 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), - _ => (expr.span, ObligationCauseCode::MatchExpressionArm { - arm_span, - source: match_src, - prior_arms: other_arms.clone(), - last_ty: prior_arm_ty.unwrap(), - discrim_hir_id: discrim.hir_id, - }), + _ => (expr.span, + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + arm_span, + source: match_src, + prior_arms: other_arms.clone(), + last_ty: prior_arm_ty.unwrap(), + discrim_hir_id: discrim.hir_id, + }) + ), }; let cause = self.cause(span, code); coercion.coerce(self, &cause, &arm.body, arm_ty); From 2e3b079836823446eb014c69866d6a0f8cca4ef2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Sep 2019 12:40:54 +1000 Subject: [PATCH 08/29] Shrink `ObligationCauseCode` by boxing `IfExpression`. The reduction in `memcpy` calls outweighs the cost of the extra allocations, for a net performance win. --- src/librustc/infer/error_reporting/mod.rs | 5 +++-- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/mod.rs | 17 ++++++++++------- src/librustc/traits/structural_impls.rs | 12 +++++++----- src/librustc_typeck/check/_match.rs | 7 ++++--- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 684e799b40319..ab24b3f2f059f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,8 @@ use crate::hir::def_id::DefId; use crate::hir::Node; use crate::infer::opaque_types; use crate::middle::region; -use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; +use crate::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; +use crate::traits::{ObligationCauseCode}; use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; @@ -681,7 +682,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } }, - ObligationCauseCode::IfExpression { then, outer, semicolon } => { + ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => { err.span_label(then, "expected because of this"); outer.map(|sp| err.span_label(sp, "if and else have incompatible types")); if let Some(sp) = semicolon { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 0b8de1f13d384..4494c034d51e2 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -70,7 +70,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PendingPredicateObligation<'_>, 144); +static_assert_size!(PendingPredicateObligation<'_>, 136); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 548fb55098af1..d2683090add40 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -125,7 +125,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PredicateObligation<'_>, 120); +static_assert_size!(PredicateObligation<'_>, 112); /// The reason why we incurred this obligation; used for error reporting. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -234,11 +234,7 @@ pub enum ObligationCauseCode<'tcx> { MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> }, /// Computing common supertype in an if expression - IfExpression { - then: Span, - outer: Option, - semicolon: Option, - }, + IfExpression(Box), /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, @@ -270,7 +266,7 @@ pub enum ObligationCauseCode<'tcx> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(ObligationCauseCode<'_>, 40); +static_assert_size!(ObligationCauseCode<'_>, 32); #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct MatchExpressionArmCause<'tcx> { @@ -281,6 +277,13 @@ pub struct MatchExpressionArmCause<'tcx> { pub discrim_hir_id: hir::HirId, } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct IfExpressionCause { + pub then: Span, + pub outer: Option, + pub semicolon: Option, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DerivedObligationCause<'tcx> { /// The trait reference of the parent obligation that led to the diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 56324baffa038..6930c9368282b 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -528,11 +528,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::MatchExpressionArmPattern { span, ty } => { tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty }) } - super::IfExpression { then, outer, semicolon } => Some(super::IfExpression { - then, - outer, - semicolon, - }), + super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => { + Some(super::IfExpression(box super::IfExpressionCause { + then, + outer, + semicolon, + })) + } super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), super::MainFunctionType => Some(super::MainFunctionType), super::StartFunctionType => Some(super::StartFunctionType), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 8ce08f523a1b0..308a3d8ebc2cf 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -2,7 +2,8 @@ use crate::check::{FnCtxt, Expectation, Diverges, Needs}; use crate::check::coercion::CoerceMany; use rustc::hir::{self, ExprKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; +use rustc::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; +use rustc::traits::{ObligationCauseCode}; use rustc::ty::Ty; use syntax_pos::Span; @@ -347,11 +348,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Finally construct the cause: - self.cause(error_sp, ObligationCauseCode::IfExpression { + self.cause(error_sp, ObligationCauseCode::IfExpression(box IfExpressionCause { then: then_sp, outer: outer_sp, semicolon: remove_semicolon, - }) + })) } fn demand_discriminant_type( From 3dd0e2b89eec3970467dc10b919923e94a02e258 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 9 Sep 2019 22:10:53 +0200 Subject: [PATCH 09/29] Added some context on SGX. Lists Darwin separately. --- src/libstd/time.rs | 50 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index c05f02389dfa0..f276ab4200525 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -63,16 +63,23 @@ pub use core::time::Duration; /// # Underlying System calls /// Currently, the following system calls are being used to get the current time using `now()`: /// -/// | Platform | System call | -/// |:---------:|:------------------------------------------------:| -/// | Cloud ABI | [clock_time_get (Monotonic Clock)](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt) | -/// | SGX | Not implemented | -/// | UNIX | [mach_absolute_time](https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html) | -/// | VXWorks | [clock_gettime (Monotonic Clock)](https://linux.die.net/man/3/clock_gettime) | -/// | WASI | [__wasi_clock_time_get (Monotonic Clock)](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get) | -/// | Windows | [QueryPerformanceCounter] | - -[QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter +/// | Platform | System call | +/// |:---------:|:--------------------------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Monotonic Clock)] | +/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | +/// | UNIX | [clock_time_get (Monotonic Clock)] | +/// | Darwin | [mach_absolute_time] | +/// | VXWorks | [clock_gettime (Monotonic Clock)] | +/// | WASI | [__wasi_clock_time_get (Monotonic Clock)] | +/// | Windows | [QueryPerformanceCounter] | + +/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter +/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time +/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode +/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get +/// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime +/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html +/// [clock_time_get (Monotonic Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt /// /// **Disclaimer:** These system calls might change over time. /// @@ -135,14 +142,21 @@ pub struct Instant(time::Instant); /// # Underlying System calls /// Currently, the following system calls are being used to get the current time using `now()`: /// -/// | Platform | System call | -/// |:---------:|:------------------------------------------------:| -/// | Cloud ABI | [clock_time_get (Realtime Clock)](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt) | -/// | SGX | Not implemented | -/// | UNIX | [gettimeofday](http://man7.org/linux/man-pages/man2/gettimeofday.2.html) | -/// | VXWorks | [clock_gettime (Realtime Clock)](https://linux.die.net/man/3/clock_gettime) | -/// | WASI | [__wasi_clock_time_get (Realtime Clock)](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get) | -/// | Windows | [GetSystemTimeAsFileTime](https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime) | +/// | Platform | System call | +/// |:---------:|:--------------------------------------------------------------------:| +/// | Cloud ABI | [clock_time_get (Realtime Clock)] | +/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | +/// | UNIX | [clock_gettime (Realtime Clock)] | +/// | DARWIN | [gettimeofday] | +/// | VXWorks | [clock_gettime (Realtime Clock)] | +/// | WASI | [__wasi_clock_time_get (Realtime Clock)] | +/// | Windows | [GetSystemTimeAsFileTime] | +/// +/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt +/// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html +/// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime +/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get +/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime /// /// **Disclaimer:** These system calls might change over time. /// From 5287885481c018eeef3ee815f9ceab4b4106d5a2 Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Tue, 10 Sep 2019 14:58:31 -0700 Subject: [PATCH 10/29] use randSecure and randABytes --- src/libstd/sys/vxworks/rand.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/libstd/sys/vxworks/rand.rs b/src/libstd/sys/vxworks/rand.rs index 1ec0cbe4dcf5b..c22880db2bf03 100644 --- a/src/libstd/sys/vxworks/rand.rs +++ b/src/libstd/sys/vxworks/rand.rs @@ -14,17 +14,24 @@ pub fn hashmap_random_keys() -> (u64, u64) { mod imp { use libc; use crate::io; - - extern "C" { - fn randBytes (randBuf: *mut libc::c_uchar, - numOfBytes: libc::c_int) -> libc::c_int; - } + use core::sync::atomic::{AtomicBool, Ordering::Relaxed}; pub fn fill_bytes(v: &mut [u8]) { + static RNG_INIT: AtomicBool = AtomicBool::new(false); + while !RNG_INIT.load(Relaxed) { + let ret = unsafe { libc::randSecure() }; + if ret < 0 { + panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); + } else if ret > 0 { + RNG_INIT.store(true, Relaxed); + break; + } + unsafe { libc::usleep(10) }; + } let ret = unsafe { - randBytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) + libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) }; - if ret == -1 { + if ret < 0 { panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); } } From b731e11d527639a0d297db9c6ef9ab5a5da1fb5d Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Tue, 10 Sep 2019 21:35:01 -0700 Subject: [PATCH 11/29] declare EnvKey before use to fix build error --- src/libstd/sys/vxworks/process/mod.rs | 1 + src/libstd/sys/vxworks/process/process_common.rs | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/sys/vxworks/process/mod.rs b/src/libstd/sys/vxworks/process/mod.rs index 4dc706006f4ce..1fc88fbde742f 100644 --- a/src/libstd/sys/vxworks/process/mod.rs +++ b/src/libstd/sys/vxworks/process/mod.rs @@ -1,5 +1,6 @@ pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; +pub use crate::ffi::OsString as EnvKey; mod process_common; #[path = "process_vxworks.rs"] diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index 509140229fd3a..13648abd1e447 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -12,8 +12,6 @@ use crate::collections::BTreeMap; use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; -pub use crate::ffi::OsString as EnvKey; - //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// From a8c5f90b06c9bf2bfa2c2f4aedd7c395cb92195d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Wed, 11 Sep 2019 14:03:40 +0200 Subject: [PATCH 12/29] Fix inconsistent link formatting. --- src/libstd/io/stdio.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 990c0eb8955e4..c798ee0e2209a 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -201,9 +201,9 @@ pub struct StdinLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [`lock() method`][lock]. +/// locking, see the [`Stdin::lock`] method. /// -/// [lock]: struct.Stdin.html#method.lock +/// [`Stdin::lock`]: struct.Stdin.html#method.lock /// /// ### Note: Windows Portability Consideration /// When operating in a console, the Windows implementation of this stream does not support @@ -425,9 +425,9 @@ pub struct StdoutLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [Stdout::lock] method. +/// locking, see the [`Stdout::lock`] method. /// -/// [Stdout::lock]: struct.Stdout.html#method.lock +/// [`Stdout::lock`]: struct.Stdout.html#method.lock /// /// ### Note: Windows Portability Consideration /// When operating in a console, the Windows implementation of this stream does not support From 223600ac2c23715f350ceae7f315f5056aae6fc0 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 11 Sep 2019 11:46:53 +0100 Subject: [PATCH 13/29] Guarantee vec.clear/truncate is O(1) for trivial types --- src/liballoc/vec.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d5dc2d4b8688d..c513658c842e5 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -685,21 +685,25 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { - let current_len = self.len; - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len); - // Set the final length at the end, keeping in mind that - // dropping an element might panic. Works around a missed - // optimization, as seen in the following issue: - // https://github.com/rust-lang/rust/issues/51802 - let mut local_len = SetLenOnDrop::new(&mut self.len); + if mem::needs_drop::() { + let current_len = self.len; + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); - // drop any extra elements - for _ in len..current_len { - local_len.decrement_len(1); - ptr = ptr.offset(-1); - ptr::drop_in_place(ptr); + // drop any extra elements + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); + } } + } else if len <= self.len { + self.len = len; } } From 2fcd870711ce267c79408ec631f7eba8e0afcdf6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Sep 2019 08:29:17 +1000 Subject: [PATCH 14/29] Box `DiagnosticBuilder`. It's a large type -- 176 bytes on 64-bit. And it's passed around and returned from a lot of functions, including within PResult. This commit boxes it, which reduces memory traffic. In particular, `PResult` shrinks to 16 bytes in the best case; this reduces instruction counts by up to 2% on various workloads. --- .../annotate_snippet_emitter_writer.rs | 2 +- src/librustc_errors/diagnostic_builder.rs | 81 +++++++++++-------- src/librustc_errors/emitter.rs | 2 +- src/libsyntax/parse/mod.rs | 7 ++ 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 39b906141f74c..c626dd0434d52 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -37,7 +37,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { &mut primary_span, &mut children, &db.level, - db.handler.flags.external_macro_backtrace); + db.handler().flags.external_macro_backtrace); self.emit_messages_default(&db.level, db.message(), diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 41d0638f7c6bd..7b8902f125aee 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -18,8 +18,17 @@ use log::debug; /// extending `HandlerFlags`, accessed via `self.handler.flags`. #[must_use] #[derive(Clone)] -pub struct DiagnosticBuilder<'a> { - pub handler: &'a Handler, +pub struct DiagnosticBuilder<'a>(Box>); + +/// This is a large type, and often used as a return value, especially within +/// the frequently-used `PResult` type. In theory, return value optimization +/// (RVO) should avoid unnecessary copying. In practice, it does not (at the +/// time of writing). The split between `DiagnosticBuilder` and +/// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls. +#[must_use] +#[derive(Clone)] +struct DiagnosticBuilderInner<'a> { + handler: &'a Handler, diagnostic: Diagnostic, allow_suggestions: bool, } @@ -52,7 +61,7 @@ macro_rules! forward { ) => { $(#[$attrs])* pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.diagnostic.$n($($name),*); + self.0.diagnostic.$n($($name),*); self } }; @@ -69,7 +78,7 @@ macro_rules! forward { ) => { $(#[$attrs])* pub fn $n>(&mut self, $($name: $ty),*) -> &mut Self { - self.diagnostic.$n($($name),*); + self.0.diagnostic.$n($($name),*); self } }; @@ -79,24 +88,28 @@ impl<'a> Deref for DiagnosticBuilder<'a> { type Target = Diagnostic; fn deref(&self) -> &Diagnostic { - &self.diagnostic + &self.0.diagnostic } } impl<'a> DerefMut for DiagnosticBuilder<'a> { fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.diagnostic + &mut self.0.diagnostic } } impl<'a> DiagnosticBuilder<'a> { + pub fn handler(&self) -> &'a Handler{ + self.0.handler + } + /// Emit the diagnostic. pub fn emit(&mut self) { if self.cancelled() { return; } - self.handler.emit_db(&self); + self.0.handler.emit_db(&self); self.cancel(); } @@ -115,8 +128,8 @@ impl<'a> DiagnosticBuilder<'a> { /// Buffers the diagnostic for later emission, unless handler /// has disabled such buffering. pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { - if self.handler.flags.dont_buffer_diagnostics || - self.handler.flags.treat_err_as_bug.is_some() + if self.0.handler.flags.dont_buffer_diagnostics || + self.0.handler.flags.treat_err_as_bug.is_some() { self.emit(); return; @@ -126,7 +139,7 @@ impl<'a> DiagnosticBuilder<'a> { // implements `Drop`. let diagnostic; unsafe { - diagnostic = std::ptr::read(&self.diagnostic); + diagnostic = std::ptr::read(&self.0.diagnostic); std::mem::forget(self); }; // Logging here is useful to help track down where in logs an error was @@ -144,7 +157,7 @@ impl<'a> DiagnosticBuilder<'a> { span: Option, ) -> &mut Self { let span = span.map(|s| s.into()).unwrap_or_else(|| MultiSpan::new()); - self.diagnostic.sub(level, message, span, None); + self.0.diagnostic.sub(level, message, span, None); self } @@ -160,7 +173,7 @@ impl<'a> DiagnosticBuilder<'a> { /// locally in whichever way makes the most sense. pub fn delay_as_bug(&mut self) { self.level = Level::Bug; - self.handler.delay_as_bug(self.diagnostic.clone()); + self.0.handler.delay_as_bug(self.0.diagnostic.clone()); self.cancel(); } @@ -171,7 +184,7 @@ impl<'a> DiagnosticBuilder<'a> { /// then the snippet will just include that `Span`, which is /// called the primary span. pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { - self.diagnostic.span_label(span, label); + self.0.diagnostic.span_label(span, label); self } @@ -208,10 +221,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.multipart_suggestion( + self.0.diagnostic.multipart_suggestion( msg, suggestion, applicability, @@ -225,10 +238,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.tool_only_multipart_suggestion( + self.0.diagnostic.tool_only_multipart_suggestion( msg, suggestion, applicability, @@ -236,7 +249,6 @@ impl<'a> DiagnosticBuilder<'a> { self } - pub fn span_suggestion( &mut self, sp: Span, @@ -244,10 +256,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion( + self.0.diagnostic.span_suggestion( sp, msg, suggestion, @@ -263,10 +275,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestions: impl Iterator, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestions( + self.0.diagnostic.span_suggestions( sp, msg, suggestions, @@ -282,10 +294,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion_short( + self.0.diagnostic.span_suggestion_short( sp, msg, suggestion, @@ -301,10 +313,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.span_suggestion_hidden( + self.0.diagnostic.span_suggestion_hidden( sp, msg, suggestion, @@ -320,10 +332,10 @@ impl<'a> DiagnosticBuilder<'a> { suggestion: String, applicability: Applicability, ) -> &mut Self { - if !self.allow_suggestions { + if !self.0.allow_suggestions { return self } - self.diagnostic.tool_only_span_suggestion( + self.0.diagnostic.tool_only_span_suggestion( sp, msg, suggestion, @@ -336,7 +348,7 @@ impl<'a> DiagnosticBuilder<'a> { forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self { - self.allow_suggestions = allow; + self.0.allow_suggestions = allow; self } @@ -359,19 +371,18 @@ impl<'a> DiagnosticBuilder<'a> { /// Creates a new `DiagnosticBuilder` with an already constructed /// diagnostic. - pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) - -> DiagnosticBuilder<'a> { - DiagnosticBuilder { + pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { + DiagnosticBuilder(Box::new(DiagnosticBuilderInner { handler, diagnostic, allow_suggestions: true, - } + })) } } impl<'a> Debug for DiagnosticBuilder<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.diagnostic.fmt(f) + self.0.diagnostic.fmt(f) } } @@ -381,7 +392,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> { fn drop(&mut self) { if !panicking() && !self.cancelled() { let mut db = DiagnosticBuilder::new( - self.handler, + self.0.handler, Level::Bug, "the following error was constructed but not emitted", ); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 0ce69eecc6b1e..66608361c8d44 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -385,7 +385,7 @@ impl Emitter for EmitterWriter { &mut primary_span, &mut children, &db.level, - db.handler.flags.external_macro_backtrace); + db.handler().flags.external_macro_backtrace); self.emit_messages_default(&db.level, &db.styled_message(), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index bc1bc00ac8405..2441a027f9940 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -13,6 +13,8 @@ use crate::symbol::Symbol; use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +#[cfg(target_arch = "x86_64")] +use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::{Lrc, Lock, Once}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use syntax_pos::edition::Edition; @@ -38,6 +40,11 @@ crate mod unescape_error_reporting; pub type PResult<'a, T> = Result>; +// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. +// (See also the comment on `DiagnosticBuilderInner`.) +#[cfg(target_arch = "x86_64")] +static_assert_size!(PResult<'_, bool>, 16); + /// Collected spans during parsing for places where a certain feature was /// used and should be feature gated accordingly in `check_crate`. #[derive(Default)] From 612c3947b4550fb093f54ce56b1580685bfe92fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 11 Sep 2019 20:50:53 +0200 Subject: [PATCH 15/29] Trim rustc-workspace-hack --- Cargo.lock | 4 ---- src/tools/rustc-workspace-hack/Cargo.toml | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27ee38146097b..bd9dd49eeba13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3250,13 +3250,9 @@ version = "1.0.0" dependencies = [ "byteorder", "crossbeam-utils 0.6.5", - "parking_lot 0.7.1", - "rand 0.6.1", - "scopeguard 0.3.3", "serde", "serde_json", "smallvec", - "syn 0.15.35", "winapi 0.3.6", ] diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 4ce411223de43..d068e1cf307b8 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -14,12 +14,6 @@ path = "lib.rs" # For documentation about what this is and why in the world these dependencies # are appearing, see `README.md`. -[build-dependencies] -# Currently Cargo/RLS depend on `failure` which depends on `synstructure` which -# enables this feature. Clippy, however, does not depend on anything that -# enables this feature. Enable it unconditionally. -syn = { version = "0.15", features = ['extra-traits'] } - [target.'cfg(windows)'.dependencies.winapi] version = "0.3" features = [ @@ -65,14 +59,10 @@ features = [ [dependencies] curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } crossbeam-utils = { version = "0.6.5", features = ["nightly"] } -parking_lot = { version = "0.7", features = ['nightly'] } -rand = { version = "0.6.1", features = ["i128_support"] } serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value"] } smallvec = { version = "0.6", features = ['union', 'may_dangle'] } -scopeguard = { version = "0.3.3", features = ["use_std", "default"] } byteorder = { version = "1.2.7", features = ["i128"] } -syn = { version = "0.15.35", features = ["extra-traits", "full"] } [target.'cfg(not(windows))'.dependencies] From e9214a147b09f8020f82b450e7c9e16290649909 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 12 Sep 2019 19:04:30 +0300 Subject: [PATCH 16/29] codegen: be more explicit about setting giving names to allocas. --- src/librustc_codegen_llvm/abi.rs | 2 +- src/librustc_codegen_llvm/builder.rs | 23 +++++-------------- src/librustc_codegen_llvm/intrinsic.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 18 +++++++-------- src/librustc_codegen_ssa/mir/mod.rs | 26 +++++++++++++--------- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 8 ++----- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_ssa/traits/builder.rs | 5 ++--- src/test/codegen/personality_lifetimes.rs | 9 ++++---- 10 files changed, 42 insertions(+), 55 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index ff87afe0c444b..2ca517dc3b1a7 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -229,7 +229,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { // We instead thus allocate some scratch space... let scratch_size = cast.size(bx); let scratch_align = cast.align(bx); - let llscratch = bx.alloca(cast.llvm_type(bx), "abi_cast", scratch_align); + let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); bx.lifetime_start(llscratch, scratch_size); // ...where we first store the value... diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index e13a5ecc2ebfd..423a01ad1f937 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -387,23 +387,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) } - fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); - bx.dynamic_alloca(ty, name, align) + bx.dynamic_alloca(ty, align) } - fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { unsafe { - let alloca = if name.is_empty() { - llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED) - } else { - let name = SmallCStr::new(name); - llvm::LLVMBuildAlloca(self.llbuilder, ty, - name.as_ptr()) - }; + let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } @@ -412,16 +406,9 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, - name: &str, align: Align) -> &'ll Value { unsafe { - let alloca = if name.is_empty() { - llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED) - } else { - let name = SmallCStr::new(name); - llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, - name.as_ptr()) - }; + let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index fc0b9ffd11d83..5fbfe9138f2a4 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -871,7 +871,7 @@ fn codegen_msvc_try( // More information can be found in libstd's seh.rs implementation. let i64p = bx.type_ptr_to(bx.type_i64()); let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let slot = bx.alloca(i64p, "slot", ptr_align); + let slot = bx.alloca(i64p, ptr_align); bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); normal.ret(bx.const_i32(0)); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index c41e46398467a..d3c59c526c8ad 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -276,7 +276,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llslot = match op.val { Immediate(_) | Pair(..) => { let scratch = - PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout, "ret"); + PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout); op.val.store(&mut bx, scratch); scratch.llval } @@ -767,7 +767,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match (arg, op.val) { (&mir::Operand::Copy(_), Ref(_, None, _)) | (&mir::Operand::Constant(_), Ref(_, None, _)) => { - let tmp = PlaceRef::alloca(&mut bx, op.layout, "const"); + let tmp = PlaceRef::alloca(&mut bx, op.layout); op.val.store(&mut bx, tmp); op.val = Ref(tmp.llval, None, tmp.align); } @@ -925,7 +925,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Immediate(_) | Pair(..) => { match arg.mode { PassMode::Indirect(..) | PassMode::Cast(_) => { - let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); + let scratch = PlaceRef::alloca(bx, arg.layout); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) } @@ -940,7 +940,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't // have scary latent bugs around. - let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); + let scratch = PlaceRef::alloca(bx, arg.layout); base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align, op.layout, MemFlags::empty()); (scratch.llval, scratch.align, true) @@ -1017,7 +1017,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cx.tcx().mk_mut_ptr(cx.tcx().types.u8), cx.tcx().types.i32 ])); - let slot = PlaceRef::alloca(bx, layout, "personalityslot"); + let slot = PlaceRef::alloca(bx, layout); self.personality_slot = Some(slot); slot } @@ -1116,7 +1116,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return if fn_ret.is_indirect() { // Odd, but possible, case, we have an operand temporary, // but the calling convention has an indirect return. - let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, fn_ret.layout); tmp.storage_live(bx); llargs.push(tmp.llval); ReturnDest::IndirectOperand(tmp, index) @@ -1124,7 +1124,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Currently, intrinsics always need a location to store // the result, so we create a temporary `alloca` for the // result. - let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, fn_ret.layout); tmp.storage_live(bx); ReturnDest::IndirectOperand(tmp, index) } else { @@ -1174,7 +1174,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Operand(None) => { let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); assert!(!dst_layout.ty.has_erasable_regions()); - let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp"); + let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); self.codegen_transmute_into(bx, src, place); let op = bx.load_operand(place); @@ -1227,7 +1227,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { DirectOperand(index) => { // If there is a cast, we have to store and reload. let op = if let PassMode::Cast(_) = ret_ty.mode { - let tmp = PlaceRef::alloca(bx, ret_ty.layout, "tmp_ret"); + let tmp = PlaceRef::alloca(bx, ret_ty.layout); tmp.storage_live(bx); bx.store_arg_ty(&ret_ty, llval, tmp); let op = bx.load_operand(tmp); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 00e9ca01f4dd2..df72980383e29 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -268,11 +268,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug!("alloc: {:?} ({}) -> place", local, name); if layout.is_unsized() { let indirect_place = - PlaceRef::alloca_unsized_indirect(&mut bx, layout, &name.as_str()); + PlaceRef::alloca_unsized_indirect(&mut bx, layout); + bx.set_var_name(indirect_place.llval, name); // FIXME: add an appropriate debuginfo LocalRef::UnsizedPlace(indirect_place) } else { - let place = PlaceRef::alloca(&mut bx, layout, &name.as_str()); + let place = PlaceRef::alloca(&mut bx, layout); + bx.set_var_name(place.llval, name); if dbg { let (scope, span) = fx.debug_loc(mir::SourceInfo { span: decl.source_info.span, @@ -293,14 +295,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } else if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); if layout.is_unsized() { - let indirect_place = PlaceRef::alloca_unsized_indirect( - &mut bx, - layout, - &format!("{:?}", local), - ); + let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout); + bx.set_var_name(indirect_place.llval, format_args!("{:?}", local)); LocalRef::UnsizedPlace(indirect_place) } else { - LocalRef::Place(PlaceRef::alloca(&mut bx, layout, &format!("{:?}", local))) + let place = PlaceRef::alloca(&mut bx, layout); + bx.set_var_name(place.llval, format_args!("{:?}", local)); + LocalRef::Place(place) } } else { // If this is an immediate local, we do not create an @@ -470,7 +471,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( _ => bug!("spread argument isn't a tuple?!") }; - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty), &name); + let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + bx.set_var_name(place.llval, name); for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_ty.args[idx]; idx += 1; @@ -558,11 +560,13 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( llarg_idx += 1; let indirect_operand = OperandValue::Pair(llarg, llextra); - let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout, &name); + let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); + bx.set_var_name(tmp.llval, name); indirect_operand.store(bx, tmp); tmp } else { - let tmp = PlaceRef::alloca(bx, arg.layout, &name); + let tmp = PlaceRef::alloca(bx, arg.layout); + bx.set_var_name(tmp.llval, name); if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) { let va_list_did = match tcx.lang_items().va_list() { Some(did) => did, diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index a8ab3ea10ed16..aa85d0284f7f9 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -367,7 +367,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); - let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, "unsized_tmp", max_align); + let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align); bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags); // Store the allocated region and the extra to the indirect place. diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index b8e10d3430292..d3e6cef8195d7 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -71,11 +71,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn alloca>( bx: &mut Bx, layout: TyLayout<'tcx>, - name: &str ) -> Self { - debug!("alloca({:?}: {:?})", name, layout); assert!(!layout.is_unsized(), "tried to statically allocate unsized place"); - let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align.abi); + let tmp = bx.alloca(bx.cx().backend_type(layout), layout.align.abi); Self::new_sized(tmp, layout) } @@ -83,13 +81,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn alloca_unsized_indirect>( bx: &mut Bx, layout: TyLayout<'tcx>, - name: &str, ) -> Self { - debug!("alloca_unsized_indirect({:?}: {:?})", name, layout); assert!(layout.is_unsized(), "tried to allocate indirect place for sized values"); let ptr_ty = bx.cx().tcx().mk_mut_ptr(layout.ty); let ptr_layout = bx.cx().layout_of(ptr_ty); - Self::alloca(bx, ptr_layout, name) + Self::alloca(bx, ptr_layout) } pub fn len>( diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index e0ad2527229ba..da8a7971107be 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // index into the struct, and this case isn't // important enough for it. debug!("codegen_rvalue: creating ugly alloca"); - let scratch = PlaceRef::alloca(&mut bx, operand.layout, "__unsize_temp"); + let scratch = PlaceRef::alloca(&mut bx, operand.layout); scratch.storage_live(&mut bx); operand.val.store(&mut bx, scratch); base::coerce_unsized_into(&mut bx, scratch, dest); diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 3a144f0b0e0aa..1886701fb3a88 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -109,13 +109,12 @@ pub trait BuilderMethods<'a, 'tcx>: rhs: Self::Value, ) -> (Self::Value, Self::Value); - fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; + fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; + fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; fn array_alloca( &mut self, ty: Self::Type, len: Self::Value, - name: &str, align: Align, ) -> Self::Value; diff --git a/src/test/codegen/personality_lifetimes.rs b/src/test/codegen/personality_lifetimes.rs index 0d3d537a2723d..05888c0e733ad 100644 --- a/src/test/codegen/personality_lifetimes.rs +++ b/src/test/codegen/personality_lifetimes.rs @@ -20,12 +20,13 @@ pub fn test() { let _s = S; // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just // in the first one. + // CHECK: [[SLOT:%[0-9]+]] = alloca { i8*, i32 } // CHECK-LABEL: cleanup: - // CHECK: bitcast{{.*}}personalityslot - // CHECK-NEXT: call void @llvm.lifetime.start + // CHECK: [[BITCAST:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST]]) // CHECK-LABEL: cleanup1: - // CHECK: bitcast{{.*}}personalityslot - // CHECK-NEXT: call void @llvm.lifetime.start + // CHECK: [[BITCAST1:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST1]]) might_unwind(); let _t = S; might_unwind(); From 6dc14833e002e462c121627a54b5fea09335716a Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 8 Sep 2019 13:06:49 -0400 Subject: [PATCH 17/29] Provide a span if main function is not present in crate Unfortunately, the diagnotic machinery does not cope well with an empty span which can happen if the crate is empty, in which case we merely set a spanless note. --- src/librustc/middle/entry.rs | 74 +++++++++++-------- .../ui-fulldeps/hash-stable-is-unstable.rs | 2 + .../hash-stable-is-unstable.stderr | 9 +-- .../ui/associated-type-bounds/inside-adt.rs | 2 + .../associated-type-bounds/inside-adt.stderr | 7 +- .../cfg-attr-cfg-2.stderr | 5 +- .../cfg-in-crate-1.stderr | 4 +- .../ui/continue-after-missing-main.stderr | 10 ++- src/test/ui/elided-test.stderr | 6 +- src/test/ui/error-codes/E0138.stderr | 2 +- src/test/ui/error-codes/E0601.rs | 2 +- src/test/ui/error-codes/E0601.stderr | 4 +- src/test/ui/issues/issue-46101.rs | 2 + src/test/ui/issues/issue-46101.stderr | 9 +-- src/test/ui/issues/issue-49040.rs | 1 + src/test/ui/issues/issue-49040.stderr | 6 +- src/test/ui/issues/issue-60057.rs | 2 + src/test/ui/issues/issue-60057.stderr | 9 +-- src/test/ui/json-short.stderr | 2 +- src/test/ui/lifetime-before-type-params.rs | 2 + .../ui/lifetime-before-type-params.stderr | 7 +- src/test/ui/main-wrong-location.rs | 1 + src/test/ui/main-wrong-location.stderr | 16 +++- src/test/ui/missing/missing-main.stderr | 4 +- src/test/ui/parser-recovery-1.rs | 1 + src/test/ui/parser-recovery-1.stderr | 19 +++-- src/test/ui/parser/issue-2354.rs | 5 +- src/test/ui/parser/issue-2354.stderr | 20 ++++- src/test/ui/parser/lex-bad-char-literals-2.rs | 2 + .../ui/parser/lex-bad-char-literals-2.stderr | 7 +- .../parser/unclosed-delimiter-in-dep.stderr | 2 +- src/test/ui/parser/unclosed_delim_mod.rs | 2 + src/test/ui/parser/unclosed_delim_mod.stderr | 9 +-- .../ui/resolve/visibility-indeterminate.rs | 2 + .../resolve/visibility-indeterminate.stderr | 7 +- .../ui/tool-attributes/diagnostic_item.rs | 1 + .../ui/tool-attributes/diagnostic_item.stderr | 9 +-- .../ui/type-alias-impl-trait/issue-60564.rs | 2 + .../type-alias-impl-trait/issue-60564.stderr | 7 +- src/test/ui/type/ascription/issue-34255-1.rs | 1 + .../ui/type/ascription/issue-34255-1.stderr | 8 +- 41 files changed, 167 insertions(+), 125 deletions(-) diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 93bb301f0951a..ba27d332e43f7 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -16,16 +16,16 @@ struct EntryContext<'a, 'tcx> { map: &'a hir_map::Map<'tcx>, - /// The top-level function called 'main'. + /// The top-level function called `main`. main_fn: Option<(HirId, Span)>, - /// The function that has attribute named 'main'. + /// The function that has attribute named `main`. attr_main_fn: Option<(HirId, Span)>, /// The function that has the attribute 'start' on it. start_fn: Option<(HirId, Span)>, - /// The functions that one might think are 'main' but aren't, e.g. + /// The functions that one might think are `main` but aren't, e.g. /// main functions not defined at the top level. For diagnostics. non_main_fns: Vec<(HirId, Span)> , } @@ -88,7 +88,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { - // This is a top-level function so can be 'main'. + // This is a top-level function so can be `main`. EntryPointType::MainNamed } else { EntryPointType::OtherMain @@ -109,7 +109,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { ctxt.main_fn = Some((item.hir_id, item.span)); } else { span_err!(ctxt.session, item.span, E0136, - "multiple 'main' functions"); + "multiple `main` functions"); } }, EntryPointType::OtherMain => { @@ -130,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { if ctxt.start_fn.is_none() { ctxt.start_fn = Some((item.hir_id, item.span)); } else { - struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions") + struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions") .span_label(ctxt.start_fn.unwrap().1, "previous `start` function here") .span_label(item.span, "multiple `start` functions") .emit(); @@ -148,34 +148,48 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } else if let Some((hir_id, _)) = visitor.main_fn { Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) } else { - // There is no main function. - let mut err = struct_err!(tcx.sess, E0601, - "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); - if !visitor.non_main_fns.is_empty() { - // There were some functions named 'main' though. Try to give the user a hint. - err.note("the main function must be defined at the crate level \ - but you have one or more functions named 'main' that are not \ - defined at the crate level. Either move the definition or \ - attach the `#[main]` attribute to override this behavior."); - for &(_, span) in &visitor.non_main_fns { - err.span_note(span, "here is a function named 'main'"); - } - err.emit(); - } else { - if let Some(ref filename) = tcx.sess.local_crate_source_file { - err.note(&format!("consider adding a `main` function to `{}`", filename.display())); - } - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note("If you don't know the basics of Rust, you can go look to the Rust Book \ - to get started: https://doc.rust-lang.org/book/"); - } - err.emit(); - } - + no_main_err(tcx, visitor); None } } +fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { + // There is no main function. + let mut err = struct_err!(tcx.sess, E0601, + "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); + let filename = &tcx.sess.local_crate_source_file; + let note = if !visitor.non_main_fns.is_empty() { + for &(_, span) in &visitor.non_main_fns { + err.span_note(span, "here is a function named `main`"); + } + err.note("you have one or more functions named `main` not defined at the crate level"); + err.help("either move the `main` function definitions or attach the `#[main]` attribute \ + to one of them"); + // There were some functions named `main` though. Try to give the user a hint. + format!("the main function must be defined at the crate level{}", + filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()) + } else if let Some(filename) = filename { + format!("consider adding a `main` function to `{}`", filename.display()) + } else { + String::from("consider adding a `main` function at the crate level") + }; + let sp = tcx.hir().krate().span; + // The file may be empty, which leads to the diagnostic machinery not emitting this + // note. This is a relatively simple way to detect that case and emit a span-less + // note instead. + if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) { + err.set_span(sp); + err.span_label(sp, ¬e); + } else { + err.note(¬e); + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note("If you don't know the basics of Rust, you can go look to the Rust Book \ + to get started: https://doc.rust-lang.org/book/"); + } + err.emit(); +} + pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> { tcx.entry_fn(LOCAL_CRATE) } diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs index 9f67f642df1ce..d79ef62c31207 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs @@ -13,3 +13,5 @@ use rustc_macros::HashStable; #[derive(HashStable)] //~^ use of unstable library feature 'rustc_private' struct Test; + +fn main() {} diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr index 02056d30eae9c..e2dc0c3be725f 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `hash_stable_is_unstable` - | - = note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs` - error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? --> $DIR/hash-stable-is-unstable.rs:3:1 | @@ -47,7 +43,6 @@ LL | #[derive(HashStable)] = note: for more information, see https://github.com/rust-lang/rust/issues/27812 = help: add `#![feature(rustc_private)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0601, E0658. -For more information about an error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs index 83a60825d84cd..59ce9496d28f0 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.rs +++ b/src/test/ui/associated-type-bounds/inside-adt.rs @@ -31,3 +31,5 @@ union U2 { f: Box> } union U3 { f: dyn Iterator } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions //~| ERROR could not find defining uses + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr index d0e0ceccd3725..9c4d03e900940 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.stderr +++ b/src/test/ui/associated-type-bounds/inside-adt.stderr @@ -52,10 +52,6 @@ error: associated type bounds are not allowed within structs, enums, or unions LL | union U3 { f: dyn Iterator } | ^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `inside_adt` - | - = note: consider adding a `main` function to `$DIR/inside-adt.rs` - error: could not find defining uses --> $DIR/inside-adt.rs:5:29 | @@ -110,6 +106,5 @@ error: could not find defining uses LL | union U3 { f: dyn Iterator } | ^^^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr index db3c7acff151c..e9df780def5df 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,6 +1,9 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` + --> $DIR/cfg-attr-cfg-2.rs:8:1 | - = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` +LL | / #[cfg_attr(foo, cfg(bar))] +LL | | fn main() { } + | |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr index c6d42c732c934..0b5c3e0335586 100644 --- a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` + --> $DIR/cfg-in-crate-1.rs:3:1 | - = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` +LL | #![cfg(bar)] + | ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` error: aborting due to previous error diff --git a/src/test/ui/continue-after-missing-main.stderr b/src/test/ui/continue-after-missing-main.stderr index cc5f87659079e..d764e7d860af6 100644 --- a/src/test/ui/continue-after-missing-main.stderr +++ b/src/test/ui/continue-after-missing-main.stderr @@ -1,6 +1,14 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` + --> $DIR/continue-after-missing-main.rs:1:1 | - = note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs` +LL | / #![allow(dead_code)] +LL | | +LL | | // error-pattern:`main` function not found in crate +LL | | +... | +LL | | +LL | | } + | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` error[E0623]: lifetime mismatch --> $DIR/continue-after-missing-main.rs:30:56 diff --git a/src/test/ui/elided-test.stderr b/src/test/ui/elided-test.stderr index d22eee4e8bde7..175bd033067bc 100644 --- a/src/test/ui/elided-test.stderr +++ b/src/test/ui/elided-test.stderr @@ -1,6 +1,10 @@ error[E0601]: `main` function not found in crate `elided_test` + --> $DIR/elided-test.rs:5:1 | - = note: consider adding a `main` function to `$DIR/elided-test.rs` +LL | / #[test] +LL | | fn main() { +LL | | } + | |_^ consider adding a `main` function to `$DIR/elided-test.rs` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr index 745dccfb17571..445053a4a89e3 100644 --- a/src/test/ui/error-codes/E0138.stderr +++ b/src/test/ui/error-codes/E0138.stderr @@ -1,4 +1,4 @@ -error[E0138]: multiple 'start' functions +error[E0138]: multiple `start` functions --> $DIR/E0138.rs:7:1 | LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/src/test/ui/error-codes/E0601.rs b/src/test/ui/error-codes/E0601.rs index 47feb7f836722..4380ddeac0aac 100644 --- a/src/test/ui/error-codes/E0601.rs +++ b/src/test/ui/error-codes/E0601.rs @@ -1 +1 @@ -// Test for main function not found. +//~ ERROR `main` function not found diff --git a/src/test/ui/error-codes/E0601.stderr b/src/test/ui/error-codes/E0601.stderr index cbc20db35da77..a687f575615d7 100644 --- a/src/test/ui/error-codes/E0601.stderr +++ b/src/test/ui/error-codes/E0601.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `E0601` + --> $DIR/E0601.rs:1:37 | - = note: consider adding a `main` function to `$DIR/E0601.rs` +LL | + | ^ consider adding a `main` function to `$DIR/E0601.rs` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs index 2d9111e9b3a98..8b1343b1326b4 100644 --- a/src/test/ui/issues/issue-46101.rs +++ b/src/test/ui/issues/issue-46101.rs @@ -2,3 +2,5 @@ trait Foo {} #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro struct S; + +fn main() {} diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr index 772d4bfeb30a7..9c88d3b87c907 100644 --- a/src/test/ui/issues/issue-46101.stderr +++ b/src/test/ui/issues/issue-46101.stderr @@ -4,11 +4,6 @@ error[E0433]: failed to resolve: partially resolved path in a derive macro LL | #[derive(Foo::Anything)] | ^^^^^^^^^^^^^ partially resolved path in a derive macro -error[E0601]: `main` function not found in crate `issue_46101` - | - = note: consider adding a `main` function to `$DIR/issue-46101.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0433, E0601. -For more information about an error, try `rustc --explain E0433`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs index a5f05d2824eb8..b7a541dd6642a 100644 --- a/src/test/ui/issues/issue-49040.rs +++ b/src/test/ui/issues/issue-49040.rs @@ -1,2 +1,3 @@ #![allow(unused_variables)]; //~ ERROR expected item, found `;` +//~^ ERROR `main` function fn foo() {} diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr index de78b8d3c14af..4134d6aa54468 100644 --- a/src/test/ui/issues/issue-49040.stderr +++ b/src/test/ui/issues/issue-49040.stderr @@ -5,8 +5,12 @@ LL | #![allow(unused_variables)]; | ^ help: remove this semicolon error[E0601]: `main` function not found in crate `issue_49040` + --> $DIR/issue-49040.rs:1:1 | - = note: consider adding a `main` function to `$DIR/issue-49040.rs` +LL | / #![allow(unused_variables)]; +LL | | +LL | | fn foo() {} + | |__^ consider adding a `main` function to `$DIR/issue-49040.rs` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-60057.rs b/src/test/ui/issues/issue-60057.rs index 3027d01c5325b..b52343adaee71 100644 --- a/src/test/ui/issues/issue-60057.rs +++ b/src/test/ui/issues/issue-60057.rs @@ -15,3 +15,5 @@ impl A { } } } + +fn main() {} diff --git a/src/test/ui/issues/issue-60057.stderr b/src/test/ui/issues/issue-60057.stderr index 6b967204ce6fb..4d915fcd9fe3d 100644 --- a/src/test/ui/issues/issue-60057.stderr +++ b/src/test/ui/issues/issue-60057.stderr @@ -10,11 +10,6 @@ error[E0425]: cannot find value `banana` in this scope LL | banana: banana | ^^^^^^ help: you might have meant to use the available field: `self.banana` -error[E0601]: `main` function not found in crate `issue_60057` - | - = note: consider adding a `main` function to `$DIR/issue-60057.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0425, E0601. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr index dffbdb7e4802d..86cb2f0a3a813 100644 --- a/src/test/ui/json-short.stderr +++ b/src/test/ui/json-short.stderr @@ -11,7 +11,7 @@ fn main() { If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ -"},"level":"error","spans":[],"children":[{"message":"consider adding a `main` function to `$DIR/json-short.rs`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0601]: `main` function not found in crate `json_short` +"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":76,"byte_end":76,"line_start":2,"line_end":2,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:2:63: error[E0601]: `main` function not found in crate `json_short` "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error "} diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs index 9b905d4883a16..5a71d6efeda62 100644 --- a/src/test/ui/lifetime-before-type-params.rs +++ b/src/test/ui/lifetime-before-type-params.rs @@ -7,3 +7,5 @@ fn third() {} //~^ ERROR lifetime parameters must be declared prior to type parameters fn fourth<'a, T, 'b, U, 'c, V>() {} //~^ ERROR lifetime parameters must be declared prior to type parameters + +fn main() {} diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr index ffc6784bafed8..76d7d0f024d65 100644 --- a/src/test/ui/lifetime-before-type-params.stderr +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -22,10 +22,5 @@ error: lifetime parameters must be declared prior to type parameters LL | fn fourth<'a, T, 'b, U, 'c, V>() {} | --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` -error[E0601]: `main` function not found in crate `lifetime_before_type_params` - | - = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs index d7ed5128195e9..f75d08813cdcd 100644 --- a/src/test/ui/main-wrong-location.rs +++ b/src/test/ui/main-wrong-location.rs @@ -1,4 +1,5 @@ mod m { +//~^ ERROR `main` function not found // An inferred main entry point (that doesn't use #[main]) // must appear at the top of the crate fn main() { } diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index b30931f2f2301..e301c2ff09ad7 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -1,11 +1,21 @@ error[E0601]: `main` function not found in crate `main_wrong_location` + --> $DIR/main-wrong-location.rs:1:1 | - = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. -note: here is a function named 'main' - --> $DIR/main-wrong-location.rs:4:5 +LL | / mod m { +LL | | +LL | | // An inferred main entry point (that doesn't use #[main]) +LL | | // must appear at the top of the crate +LL | | fn main() { } +LL | | } + | |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`) + | +note: here is a function named `main` + --> $DIR/main-wrong-location.rs:5:5 | LL | fn main() { } | ^^^^^^^^^^^^^ + = note: you have one or more functions named `main` not defined at the crate level + = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them error: aborting due to previous error diff --git a/src/test/ui/missing/missing-main.stderr b/src/test/ui/missing/missing-main.stderr index 34b03ada3d295..6a35f5117efd6 100644 --- a/src/test/ui/missing/missing-main.stderr +++ b/src/test/ui/missing/missing-main.stderr @@ -1,6 +1,8 @@ error[E0601]: `main` function not found in crate `missing_main` + --> $DIR/missing-main.rs:2:1 | - = note: consider adding a `main` function to `$DIR/missing-main.rs` +LL | fn mian() { } + | ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs` error: aborting due to previous error diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs index 21d36048e6703..8126525c34f95 100644 --- a/src/test/ui/parser-recovery-1.rs +++ b/src/test/ui/parser-recovery-1.rs @@ -3,6 +3,7 @@ // Test that we can recover from missing braces in the parser. trait Foo { +//~^ ERROR `main` function not found fn bar() { let x = foo(); //~^ ERROR cannot find function `foo` in this scope diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr index c29f42759178e..ffe2b3322fc81 100644 --- a/src/test/ui/parser-recovery-1.stderr +++ b/src/test/ui/parser-recovery-1.stderr @@ -1,8 +1,9 @@ error: this file contains an un-closed delimiter - --> $DIR/parser-recovery-1.rs:15:55 + --> $DIR/parser-recovery-1.rs:16:55 | LL | trait Foo { | - un-closed delimiter +LL | LL | fn bar() { | - this delimiter might not be properly closed... ... @@ -13,26 +14,34 @@ LL | } | ^ error: unexpected token: `;` - --> $DIR/parser-recovery-1.rs:12:15 + --> $DIR/parser-recovery-1.rs:13:15 | LL | let x = y.; | ^ error[E0425]: cannot find function `foo` in this scope - --> $DIR/parser-recovery-1.rs:7:17 + --> $DIR/parser-recovery-1.rs:8:17 | LL | let x = foo(); | ^^^ not found in this scope error[E0425]: cannot find value `y` in this scope - --> $DIR/parser-recovery-1.rs:12:13 + --> $DIR/parser-recovery-1.rs:13:13 | LL | let x = y.; | ^ not found in this scope error[E0601]: `main` function not found in crate `parser_recovery_1` + --> $DIR/parser-recovery-1.rs:5:1 | - = note: consider adding a `main` function to `$DIR/parser-recovery-1.rs` +LL | / trait Foo { +LL | | +LL | | fn bar() { +LL | | let x = foo(); +... | +LL | | +LL | | } + | |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs` error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issue-2354.rs index 565f84822f7d6..a14eb6e32fc91 100644 --- a/src/test/ui/parser/issue-2354.rs +++ b/src/test/ui/parser/issue-2354.rs @@ -1,4 +1,7 @@ fn foo() { //~ NOTE un-closed delimiter +//~^ ERROR `main` function not found +//~^^ NOTE main function must be defined +//~^^^ NOTE you have one or more functions match Some(10) { //~^ NOTE this delimiter might not be properly closed... Some(y) => { panic!(); } @@ -11,5 +14,5 @@ fn bar() { while (i < 1000) {} } -fn main() {} //~ NOTE here is a function named 'main' +fn main() {} //~ NOTE here is a function named `main` //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issue-2354.stderr index 7098da738b8df..038e3dcfa40a9 100644 --- a/src/test/ui/parser/issue-2354.stderr +++ b/src/test/ui/parser/issue-2354.stderr @@ -1,8 +1,9 @@ error: this file contains an un-closed delimiter - --> $DIR/issue-2354.rs:15:66 + --> $DIR/issue-2354.rs:18:66 | LL | fn foo() { | - un-closed delimiter +... LL | match Some(10) { | - this delimiter might not be properly closed... ... @@ -13,13 +14,24 @@ LL | | ^ error[E0601]: `main` function not found in crate `issue_2354` + --> $DIR/issue-2354.rs:1:1 + | +LL | / fn foo() { +LL | | +LL | | +LL | | +... | +LL | | fn main() {} +LL | | + | |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`) | - = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. -note: here is a function named 'main' - --> $DIR/issue-2354.rs:14:1 +note: here is a function named `main` + --> $DIR/issue-2354.rs:17:1 | LL | fn main() {} | ^^^^^^^^^^^^ + = note: you have one or more functions named `main` not defined at the crate level + = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs index 1e180f87fc186..d35dafd9a3443 100644 --- a/src/test/ui/parser/lex-bad-char-literals-2.rs +++ b/src/test/ui/parser/lex-bad-char-literals-2.rs @@ -2,3 +2,5 @@ static c: char = 'nope' //~ ERROR: character literal may only contain one codepoint ; + +fn main() {} diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr index b0a4ed02434b4..5653d4ea672af 100644 --- a/src/test/ui/parser/lex-bad-char-literals-2.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr @@ -8,10 +8,5 @@ help: if you meant to write a `str` literal, use double quotes LL | "nope" | ^^^^^^ -error[E0601]: `main` function not found in crate `lex_bad_char_literals_2` - | - = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr index 633c63bea9105..818f61b4d2229 100644 --- a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr +++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr @@ -1,5 +1,5 @@ error: incorrect close delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:5:1 + --> $DIR/unclosed_delim_mod.rs:7:1 | LL | pub fn new() -> Result { | - close delimiter possibly meant for this diff --git a/src/test/ui/parser/unclosed_delim_mod.rs b/src/test/ui/parser/unclosed_delim_mod.rs index b1664f49dc591..486e23312819d 100644 --- a/src/test/ui/parser/unclosed_delim_mod.rs +++ b/src/test/ui/parser/unclosed_delim_mod.rs @@ -1,3 +1,5 @@ +fn main() {} + pub struct Value {} pub fn new() -> Result { Ok(Value { diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr index cc04eb531cbea..fe2d968af0f32 100644 --- a/src/test/ui/parser/unclosed_delim_mod.stderr +++ b/src/test/ui/parser/unclosed_delim_mod.stderr @@ -1,5 +1,5 @@ error: incorrect close delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:5:1 + --> $DIR/unclosed_delim_mod.rs:7:1 | LL | pub fn new() -> Result { | - close delimiter possibly meant for this @@ -9,10 +9,5 @@ LL | } LL | } | ^ incorrect close delimiter -error[E0601]: `main` function not found in crate `unclosed_delim_mod` - | - = note: consider adding a `main` function to `$DIR/unclosed_delim_mod.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs index 595eaf440c9f4..198ea752881f1 100644 --- a/src/test/ui/resolve/visibility-indeterminate.rs +++ b/src/test/ui/resolve/visibility-indeterminate.rs @@ -3,3 +3,5 @@ foo!(); //~ ERROR cannot find macro `foo!` in this scope pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility + +fn main() {} diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr index a259c8090b35d..17927a5967dcb 100644 --- a/src/test/ui/resolve/visibility-indeterminate.stderr +++ b/src/test/ui/resolve/visibility-indeterminate.stderr @@ -10,10 +10,5 @@ error: cannot find macro `foo!` in this scope LL | foo!(); | ^^^ -error[E0601]: `main` function not found in crate `visibility_indeterminate` - | - = note: consider adding a `main` function to `$DIR/visibility-indeterminate.rs` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/tool-attributes/diagnostic_item.rs b/src/test/ui/tool-attributes/diagnostic_item.rs index 1d35422ed6241..26a52ce60cfd8 100644 --- a/src/test/ui/tool-attributes/diagnostic_item.rs +++ b/src/test/ui/tool-attributes/diagnostic_item.rs @@ -1,2 +1,3 @@ #[rustc_diagnostic_item = "foomp"] //~ ERROR compiler internal support for linting struct Foomp; +fn main() {} diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr index deff4da6b8052..5432f8dea8606 100644 --- a/src/test/ui/tool-attributes/diagnostic_item.stderr +++ b/src/test/ui/tool-attributes/diagnostic_item.stderr @@ -7,11 +7,6 @@ LL | #[rustc_diagnostic_item = "foomp"] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error[E0601]: `main` function not found in crate `diagnostic_item` - | - = note: consider adding a `main` function to `$DIR/diagnostic_item.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0601, E0658. -For more information about an error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 91c4576597ea4..9e96b1cf7b05f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -24,3 +24,5 @@ where .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) } } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index ebb13fca1da92..b838c06cadee3 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_60564` - | - = note: consider adding a `main` function to `$DIR/issue-60564.rs` - error: type parameter `E` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-60564.rs:20:49 | @@ -20,6 +16,5 @@ error: could not find defining uses LL | type IterBitsIter = impl std::iter::Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs index c11a248d3c7d1..c21d9f3d97cbb 100644 --- a/src/test/ui/type/ascription/issue-34255-1.rs +++ b/src/test/ui/type/ascription/issue-34255-1.rs @@ -13,3 +13,4 @@ impl Reactor { } // This case isn't currently being handled gracefully, including for completeness. +fn main() {} diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr index 531455b82b424..195b393b2f609 100644 --- a/src/test/ui/type/ascription/issue-34255-1.stderr +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -14,17 +14,13 @@ LL | input_cells: Vec::new() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error[E0601]: `main` function not found in crate `issue_34255_1` - | - = note: consider adding a `main` function to `$DIR/issue-34255-1.rs` - error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/issue-34255-1.rs:7:22 | LL | input_cells: Vec::new() | ^^^^^^^^^^ expected 1 type argument -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0425, E0601. +Some errors have detailed explanations: E0107, E0425. For more information about an error, try `rustc --explain E0107`. From a2261ad66400c3145f96ebff0d9b75e910fa89dd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Sep 2019 10:46:05 +1000 Subject: [PATCH 18/29] Inline `mark_neighbours_as_waiting_from`. This function is very hot, doesn't get inlined because it's recursive, and the function calls are significant. This commit splits it into inlined and uninlined variants, and uses the inlined variant for the hot call site. This wins several percent on a few benchmarks. --- .../obligation_forest/mod.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 04d2b23ab1a1c..6c52e626ababd 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -559,13 +559,20 @@ impl ObligationForest { trace } - #[inline] - fn mark_neighbors_as_waiting_from(&self, node: &Node) { + // This always-inlined function is for the hot call site. + #[inline(always)] + fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node) { for dependent in node.parent.iter().chain(node.dependents.iter()) { self.mark_as_waiting_from(&self.nodes[dependent.get()]); } } + // This never-inlined function is for the cold call site. + #[inline(never)] + fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node) { + self.inlined_mark_neighbors_as_waiting_from(node) + } + /// Marks all nodes that depend on a pending node as `NodeState::Waiting`. fn mark_as_waiting(&self) { for node in &self.nodes { @@ -576,7 +583,8 @@ impl ObligationForest { for node in &self.nodes { if node.state.get() == NodeState::Pending { - self.mark_neighbors_as_waiting_from(node); + // This call site is hot. + self.inlined_mark_neighbors_as_waiting_from(node); } } } @@ -588,7 +596,8 @@ impl ObligationForest { NodeState::Pending | NodeState::Done => {}, } - self.mark_neighbors_as_waiting_from(node); + // This call site is cold. + self.uninlined_mark_neighbors_as_waiting_from(node); } /// Compresses the vector, removing all popped nodes. This adjusts From a47a5c3a629429526c06f92555394484eedf8277 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Mon, 9 Sep 2019 23:44:11 +0800 Subject: [PATCH 19/29] typo fix --- src/librustc/hir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f5e644625729b..2c8590aa4e3fa 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -190,7 +190,7 @@ pub enum ParamName { Fresh(usize), /// Indicates an illegal name was given and an error has been - /// repored (so we should squelch other derived errors). Occurs + /// reported (so we should squelch other derived errors). Occurs /// when, e.g., `'_` is used in the wrong place. Error, } From bd25507f0e6501abb8bb1ee79330bf76136d393f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 13 Sep 2019 11:37:29 +0100 Subject: [PATCH 20/29] Remove raw string literal quotes from error index descriptions --- src/tools/error_index_generator/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index 832aa3b1c8dfd..592b3f14c85af 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs @@ -35,7 +35,7 @@ fn register_all() -> Vec<(&'static str, Option<&'static str>)> { ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( $( {long_codes.extend([ - (stringify!($ecode), Some(stringify!($message))), + (stringify!($ecode), Some($message)), ].iter());} )* $( From 69112a27fba9c2b36d6969cf79191045ed780014 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 13 Sep 2019 11:42:31 +0100 Subject: [PATCH 21/29] Add self to .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index da8044de405a6..9587aaab35945 100644 --- a/.mailmap +++ b/.mailmap @@ -184,6 +184,7 @@ Neil Pankey Nick Platt Nicole Mazzuca Nif Ward +Oliver Middleton Oliver Scherer Oliver Scherer Oliver Scherer From b3b671366bc98017fcac7bcfae0d46d038575aa3 Mon Sep 17 00:00:00 2001 From: Christian Veenman <46896178+DevQps@users.noreply.github.com> Date: Fri, 13 Sep 2019 16:29:06 +0200 Subject: [PATCH 22/29] Update src/libstd/time.rs Co-Authored-By: Robin Kruppe --- src/libstd/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index f276ab4200525..ff209785a935d 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -72,7 +72,7 @@ pub use core::time::Duration; /// | VXWorks | [clock_gettime (Monotonic Clock)] | /// | WASI | [__wasi_clock_time_get (Monotonic Clock)] | /// | Windows | [QueryPerformanceCounter] | - +/// /// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode From 7437f770251f6c3c76f75891d48db4d1e26fc0c2 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 13 Sep 2019 17:06:09 +0200 Subject: [PATCH 23/29] Make fn ptr always structural match, regardless of whether formal types are. Fix #63479. --- src/librustc_mir/hair/pattern/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 6caccfddfa422..4aaa5e8ee259a 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -1229,7 +1229,13 @@ fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, ty::RawPtr(..) => { // `#[structural_match]` ignores substructure of // `*const _`/`*mut _`, so skip super_visit_with - + // + // (But still tell caller to continue search.) + return false; + } + ty::FnDef(..) | ty::FnPtr(..) => { + // types of formals and return in `fn(_) -> _` are also irrelevant + // // (But still tell caller to continue search.) return false; } From c529294535fc748f29a9e2182a56e4ef9b4ba000 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 13 Sep 2019 17:08:01 +0200 Subject: [PATCH 24/29] Regression tests for fn ptr and `#[structural_match]` as discussed in #63479. --- .../fn-ptr-is-structurally-matchable.rs | 135 ++++++++++++++++++ .../ui/rfc1445/issue-63479-match-fnptr.rs | 36 +++++ 2 files changed, 171 insertions(+) create mode 100644 src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs create mode 100644 src/test/ui/rfc1445/issue-63479-match-fnptr.rs diff --git a/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs b/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs new file mode 100644 index 0000000000000..5b378fb2a5928 --- /dev/null +++ b/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs @@ -0,0 +1,135 @@ +// run-pass + +// This file checks that fn ptrs are considered structurally matchable. +// See also rust-lang/rust#63479. + +fn main() { + let mut count = 0; + + // A type which is not structurally matchable: + struct NotSM; + + // And one that is: + #[derive(PartialEq, Eq)] + struct SM; + + fn trivial() {} + + fn sm_to(_: SM) {} + fn not_sm_to(_: NotSM) {} + fn to_sm() -> SM { SM } + fn to_not_sm() -> NotSM { NotSM } + + // To recreate the scenario of interest in #63479, we need to add + // a ref-level-of-indirection so that we descend into the type. + + fn r_sm_to(_: &SM) {} + fn r_not_sm_to(_: &NotSM) {} + fn r_to_r_sm(_: &()) -> &SM { &SM } + fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM } + + #[derive(PartialEq, Eq)] + struct Wrap(T); + + // In the code below, we put the match input into a local so that + // we can assign it an explicit type that is an fn ptr instead of + // a singleton type of the fn itself that the type inference would + // otherwise assign. + + // Check that fn() is #[structural_match] + const CFN1: Wrap = Wrap(trivial); + let input: Wrap = Wrap(trivial); + match Wrap(input) { + Wrap(CFN1) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is #[structural_match] when T is too. + const CFN2: Wrap = Wrap(sm_to); + let input: Wrap = Wrap(sm_to); + match Wrap(input) { + Wrap(CFN2) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is #[structural_match] when T is too. + const CFN3: Wrap SM> = Wrap(to_sm); + let input: Wrap SM> = Wrap(to_sm); + match Wrap(input) { + Wrap(CFN3) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is #[structural_match] even if T is not. + const CFN4: Wrap = Wrap(not_sm_to); + let input: Wrap = Wrap(not_sm_to); + match Wrap(input) { + Wrap(CFN4) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is #[structural_match] even if T is not. + const CFN5: Wrap NotSM> = Wrap(to_not_sm); + let input: Wrap NotSM> = Wrap(to_not_sm); + match Wrap(input) { + Wrap(CFN5) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(&T) is #[structural_match] when T is too. + const CFN6: Wrap = Wrap(r_sm_to); + let input: Wrap = Wrap(r_sm_to); + match Wrap(input) { + Wrap(CFN6) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> &T is #[structural_match] when T is too. + const CFN7: Wrap &SM> = Wrap(r_to_r_sm); + let input: Wrap &SM> = Wrap(r_to_r_sm); + match Wrap(input) { + Wrap(CFN7) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is #[structural_match] even if T is not. + const CFN8: Wrap = Wrap(r_not_sm_to); + let input: Wrap = Wrap(r_not_sm_to); + match Wrap(input) { + Wrap(CFN8) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is #[structural_match] even if T is not. + const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); + let input: Wrap &NotSM> = Wrap(r_to_r_not_sm); + match Wrap(input) { + Wrap(CFN9) => count += 1, + Wrap(_) => {} + }; + + // Check that a type which has fn ptrs is `#[structural_match]`. + #[derive(PartialEq, Eq)] + struct Foo { + alpha: fn(NotSM), + beta: fn() -> NotSM, + gamma: fn(SM), + delta: fn() -> SM, + } + + const CFOO: Foo = Foo { + alpha: not_sm_to, + beta: to_not_sm, + gamma: sm_to, + delta: to_sm, + }; + + let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm }; + match input { + CFOO => count += 1, + Foo { .. } => {} + }; + + // Final count must be 10 now if all + assert_eq!(count, 10); +} diff --git a/src/test/ui/rfc1445/issue-63479-match-fnptr.rs b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs new file mode 100644 index 0000000000000..b3c91cec580bf --- /dev/null +++ b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs @@ -0,0 +1,36 @@ +// run-pass + +// The actual regression test from #63479. (Including this because my +// first draft at fn-ptr-is-structurally-matchable.rs failed to actually +// cover the case this hit; I've since expanded it accordingly, but the +// experience left me wary of leaving this regression test out.) + +#[derive(Eq)] +struct A { + a: i64 +} + +impl PartialEq for A { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) + } +} + +type Fn = fn(&[A]); + +fn my_fn(_args: &[A]) { + println!("hello world"); +} + +const TEST: Fn = my_fn; + +struct B(Fn); + +fn main() { + let s = B(my_fn); + match s { + B(TEST) => println!("matched"), + _ => panic!("didn't match") + }; +} From bdad2c52a538206a2f1c154bb5d5c3d7cb6b5d6f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 13 Sep 2019 19:25:05 +0300 Subject: [PATCH 25/29] codegen: use "_N" (like for other locals) instead of "argN", for argument names. --- src/librustc_codegen_ssa/mir/mod.rs | 3 ++- src/test/codegen/adjustments.rs | 2 +- src/test/codegen/fastcall-inreg.rs | 12 ++++----- src/test/codegen/function-arguments.rs | 28 ++++++++++----------- src/test/codegen/refs.rs | 2 +- src/test/codegen/repeat-trusted-len.rs | 2 +- src/test/codegen/repr-transparent.rs | 34 +++++++++++++------------- src/test/codegen/scalar-pair-bool.rs | 12 ++++----- src/test/codegen/union-abi.rs | 16 ++++++------ 9 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index df72980383e29..aa3971a1da81a 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -453,10 +453,11 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; + // FIXME(eddyb) don't allocate a `String` unless it gets used. let name = if let Some(name) = arg_decl.name { name.as_str().to_string() } else { - format!("arg{}", arg_index) + format!("{:?}", local) }; if Some(local) == mir.spread_arg { diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs index ae2ff9994fdf0..ded310d0aebb1 100644 --- a/src/test/codegen/adjustments.rs +++ b/src/test/codegen/adjustments.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs index e152e6e9d1333..f67487c83ba23 100644 --- a/src/test/codegen/fastcall-inreg.rs +++ b/src/test/codegen/fastcall-inreg.rs @@ -49,27 +49,27 @@ #![crate_type = "lib"] pub mod tests { - // CHECK: @f1(i32 inreg %arg0, i32 inreg %arg1, i32 %arg2) + // CHECK: @f1(i32 inreg %_1, i32 inreg %_2, i32 %_3) #[no_mangle] pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {} - // CHECK: @f2(i32* inreg %arg0, i32* inreg %arg1, i32* %arg2) + // CHECK: @f2(i32* inreg %_1, i32* inreg %_2, i32* %_3) #[no_mangle] pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {} - // CHECK: @f3(float %arg0, i32 inreg %arg1, i32 inreg %arg2, i32 %arg3) + // CHECK: @f3(float %_1, i32 inreg %_2, i32 inreg %_3, i32 %_4) #[no_mangle] pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {} - // CHECK: @f4(i32 inreg %arg0, float %arg1, i32 inreg %arg2, i32 %arg3) + // CHECK: @f4(i32 inreg %_1, float %_2, i32 inreg %_3, i32 %_4) #[no_mangle] pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {} - // CHECK: @f5(i64 %arg0, i32 %arg1) + // CHECK: @f5(i64 %_1, i32 %_2) #[no_mangle] pub extern "fastcall" fn f5(_: i64, _: i32) {} - // CHECK: @f6(i1 inreg zeroext %arg0, i32 inreg %arg1, i32 %arg2) + // CHECK: @f6(i1 inreg zeroext %_1, i32 inreg %_2, i32 %_3) #[no_mangle] pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {} } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index bd121ef24adae..7e1791cd4f296 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -18,48 +18,48 @@ pub fn boolean(x: bool) -> bool { x } -// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn readonly_borrow(_: &i32) { } -// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // static borrow may be captured #[no_mangle] pub fn static_borrow(_: &'static i32) { } -// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) +// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1) // borrow with named lifetime may be captured #[no_mangle] pub fn named_borrow<'r>(_: &'r i32) { } -// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) +// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) { } -// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) +// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %_1) // ... unless this is a mutable borrow, those never alias #[no_mangle] pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { } -// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %arg0) +// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_borrow(_: &mut i32) { } -// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %arg0) +// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { } -// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %arg0) +// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn borrowed_struct(_: &S) { @@ -80,36 +80,36 @@ pub fn struct_return() -> S { } // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } -// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn slice(_: &[u8]) { } -// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_slice(_: &mut [u8]) { } -// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %_1.0, [[USIZE]] %_1.1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_slice(_: &[UnsafeInner]) { } -// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn str(_: &[u8]) { } -// CHECK: @trait_borrow({}* nonnull align 1 %arg0.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %arg0.1) +// CHECK: @trait_borrow({}* nonnull align 1 %_1.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn trait_borrow(_: &Drop) { diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs index cbb9942347673..15f99fd0c22a0 100644 --- a/src/test/codegen/refs.rs +++ b/src/test/codegen/refs.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] // Hack to get the correct size for the length part in slices -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index c348a8f7b8b8f..87f29f6047c6a 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -6,7 +6,7 @@ use std::iter; -// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs index c9f3837565808..e705d5ce3cd72 100644 --- a/src/test/codegen/repr-transparent.rs +++ b/src/test/codegen/repr-transparent.rs @@ -14,21 +14,21 @@ pub struct Zst2(()); #[repr(transparent)] pub struct F32(f32); -// CHECK: define float @test_F32(float %arg0) +// CHECK: define float @test_F32(float %_1) #[no_mangle] pub extern fn test_F32(_: F32) -> F32 { loop {} } #[repr(transparent)] pub struct Ptr(*mut u8); -// CHECK: define i8* @test_Ptr(i8* %arg0) +// CHECK: define i8* @test_Ptr(i8* %_1) #[no_mangle] pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} } #[repr(transparent)] pub struct WithZst(u64, Zst1); -// CHECK: define i64 @test_WithZst(i64 %arg0) +// CHECK: define i64 @test_WithZst(i64 %_1) #[no_mangle] pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} } @@ -36,14 +36,14 @@ pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} } pub struct WithZeroSizedArray(*const f32, [i8; 0]); // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. -// CHECK: define i32* @test_WithZeroSizedArray(i32* %arg0) +// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1) #[no_mangle] pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } #[repr(transparent)] pub struct Generic(T); -// CHECK: define double @test_Generic(double %arg0) +// CHECK: define double @test_Generic(double %_1) #[no_mangle] pub extern fn test_Generic(_: Generic) -> Generic { loop {} } @@ -53,14 +53,14 @@ pub struct GenericPlusZst(T, Zst2); #[repr(u8)] pub enum Bool { True, False, FileNotFound } -// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %arg0) +// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1) #[no_mangle] pub extern fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } #[repr(transparent)] pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); -// CHECK: define i16* @test_LifetimePhantom(i16* %arg0) +// CHECK: define i16* @test_LifetimePhantom(i16* %_1) #[no_mangle] pub extern fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { loop {} } @@ -70,28 +70,28 @@ pub struct UnitPhantom { val: T, unit: PhantomData } pub struct Px; -// CHECK: define float @test_UnitPhantom(float %arg0) +// CHECK: define float @test_UnitPhantom(float %_1) #[no_mangle] pub extern fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { loop {} } #[repr(transparent)] pub struct TwoZsts(Zst1, i8, Zst2); -// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %arg0) +// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1) #[no_mangle] pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } #[repr(transparent)] pub struct Nested1(Zst2, Generic); -// CHECK: define double @test_Nested1(double %arg0) +// CHECK: define double @test_Nested1(double %_1) #[no_mangle] pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} } #[repr(transparent)] pub struct Nested2(Nested1, Zst1); -// CHECK: define double @test_Nested2(double %arg0) +// CHECK: define double @test_Nested2(double %_1) #[no_mangle] pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} } @@ -101,7 +101,7 @@ struct f32x4(f32, f32, f32, f32); #[repr(transparent)] pub struct Vector(f32x4); -// CHECK: define <4 x float> @test_Vector(<4 x float> %arg0) +// CHECK: define <4 x float> @test_Vector(<4 x float> %_1) #[no_mangle] pub extern fn test_Vector(_: Vector) -> Vector { loop {} } @@ -111,7 +111,7 @@ impl Mirror for T { type It = Self; } #[repr(transparent)] pub struct StructWithProjection(::It); -// CHECK: define float @test_Projection(float %arg0) +// CHECK: define float @test_Projection(float %_1) #[no_mangle] pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } @@ -120,7 +120,7 @@ pub enum EnumF32 { Variant(F32) } -// CHECK: define float @test_EnumF32(float %arg0) +// CHECK: define float @test_EnumF32(float %_1) #[no_mangle] pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } @@ -129,7 +129,7 @@ pub enum EnumF32WithZsts { Variant(Zst1, F32, Zst2) } -// CHECK: define float @test_EnumF32WithZsts(float %arg0) +// CHECK: define float @test_EnumF32WithZsts(float %_1) #[no_mangle] pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } @@ -138,7 +138,7 @@ pub union UnionF32 { field: F32, } -// CHECK: define float @test_UnionF32(float %arg0) +// CHECK: define float @test_UnionF32(float %_1) #[no_mangle] pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } @@ -149,7 +149,7 @@ pub union UnionF32WithZsts { zst2: Zst2, } -// CHECK: define float @test_UnionF32WithZsts(float %arg0) +// CHECK: define float @test_UnionF32WithZsts(float %_1) #[no_mangle] pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } diff --git a/src/test/codegen/scalar-pair-bool.rs b/src/test/codegen/scalar-pair-bool.rs index 78d1025b13c77..d91ee7f816ded 100644 --- a/src/test/codegen/scalar-pair-bool.rs +++ b/src/test/codegen/scalar-pair-bool.rs @@ -20,24 +20,24 @@ pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) { pair } -// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.1) +// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) { // Make sure it can operate directly on the unpacked args - // CHECK: and i1 %arg0.0, %arg0.1 - // CHECK: or i1 %arg0.0, %arg0.1 + // CHECK: and i1 %_1.0, %_1.1 + // CHECK: or i1 %_1.0, %_1.1 (a && b, a || b) } -// CHECK: define void @pair_branches(i1 zeroext %arg0.0, i1 zeroext %arg0.1) +// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_branches((a, b): (bool, bool)) { // Make sure it can branch directly on the unpacked bool args - // CHECK: br i1 %arg0.0 + // CHECK: br i1 %_1.0 if a { println!("Hello!"); } - // CHECK: br i1 %arg0.1 + // CHECK: br i1 %_1.1 if b { println!("Goodbye!"); } diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index b7baffe16695a..7339df17b057a 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -16,38 +16,38 @@ pub struct i64x4(i64, i64, i64, i64); #[derive(Copy, Clone)] pub union UnionI64x4{ a:(), b: i64x4 } -// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4(_: UnionI64x4) { loop {} } pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } -// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} } pub union UnionI64x4I64{ a: i64x4, b: i64 } -// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} } pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) } -// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0) +// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %_1) #[no_mangle] pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} } pub union UnionF32{a:f32} -// CHECK: define float @test_UnionF32(float %arg0) +// CHECK: define float @test_UnionF32(float %_1) #[no_mangle] pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } pub union UnionF32F32{a:f32, b:f32} -// CHECK: define float @test_UnionF32F32(float %arg0) +// CHECK: define float @test_UnionF32F32(float %_1) #[no_mangle] pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } @@ -58,13 +58,13 @@ pub union UnionF32U32{a:f32, b:u32} pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } pub union UnionU128{a:u128} -// CHECK: define i128 @test_UnionU128(i128 %arg0) +// CHECK: define i128 @test_UnionU128(i128 %_1) #[no_mangle] pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} } #[repr(C)] pub union CUnionU128{a:u128} -// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0) +// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %_1) #[no_mangle] pub fn test_CUnionU128(_: CUnionU128) { loop {} } From 57e82878c0c18d920b5fb0df11bff6aa2e2abca5 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Sat, 14 Sep 2019 02:40:20 +0800 Subject: [PATCH 26/29] fix #64430 --- src/librustc/ty/context.rs | 6 ++--- src/librustc_typeck/check/expr.rs | 41 ++++++++++++++----------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8e8472a5aacc9..25d921b7cea4c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2396,9 +2396,9 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem) -> Ty<'tcx> { - let def_id = self.require_lang_item(item, None); - self.mk_generic_adt(def_id, ty) + pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem) -> Option> { + let def_id = self.lang_items().require(item).ok()?; + Some(self.mk_generic_adt(def_id, ty)) } #[inline] diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index da72dfd155182..56bd903040ab4 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -813,18 +813,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: MethodError<'tcx> ) { let rcvr = &args[0]; - let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { - if let Ok(pick) = self.lookup_probe( - span, - segment.ident, - new_rcvr_t, - rcvr, - probe::ProbeScope::AllTraits, - ) { - err.span_label( - pick.item.ident.span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); + let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, rcvr_t, lang_item| { + if let Some(new_rcvr_t) = self.tcx.mk_lang_item(rcvr_t, lang_item) { + if let Ok(pick) = self.lookup_probe( + span, + segment.ident, + new_rcvr_t, + rcvr, + probe::ProbeScope::AllTraits, + ) { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + } } }; @@ -840,17 +842,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not // just this whitelist. - let box_rcvr_t = self.tcx.mk_box(rcvr_t); - try_alt_rcvr(&mut err, box_rcvr_t); - let pin_rcvr_t = self.tcx.mk_lang_item( - rcvr_t, - lang_items::PinTypeLangItem, - ); - try_alt_rcvr(&mut err, pin_rcvr_t); - let arc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Arc); - try_alt_rcvr(&mut err, arc_rcvr_t); - let rc_rcvr_t = self.tcx.mk_lang_item(rcvr_t, lang_items::Rc); - try_alt_rcvr(&mut err, rc_rcvr_t); + try_alt_rcvr(&mut err, rcvr_t, lang_items::OwnedBoxLangItem); + try_alt_rcvr(&mut err, rcvr_t, lang_items::PinTypeLangItem); + try_alt_rcvr(&mut err, rcvr_t, lang_items::Arc); + try_alt_rcvr(&mut err, rcvr_t, lang_items::Rc); } err.emit(); } From b98a844cf300779d7c103ccf7812e312f021c86f Mon Sep 17 00:00:00 2001 From: 12101111 Date: Sat, 14 Sep 2019 03:13:51 +0800 Subject: [PATCH 27/29] add ui test for #64430 --- src/test/ui/issues/issue-64430.rs | 14 ++++++++++++++ src/test/ui/issues/issue-64430.stderr | 12 ++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/issues/issue-64430.rs create mode 100644 src/test/ui/issues/issue-64430.stderr diff --git a/src/test/ui/issues/issue-64430.rs b/src/test/ui/issues/issue-64430.rs new file mode 100644 index 0000000000000..8e58d0dda0e1b --- /dev/null +++ b/src/test/ui/issues/issue-64430.rs @@ -0,0 +1,14 @@ +// compile-flags:-C panic=abort + +#![no_std] +pub struct Foo; + +fn main() { + Foo.bar() + //~^ ERROR E0599 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop{} +} \ No newline at end of file diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr new file mode 100644 index 0000000000000..f1b2de8d8b36f --- /dev/null +++ b/src/test/ui/issues/issue-64430.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `bar` found for type `Foo` in the current scope + --> $DIR/issue-64430.rs:7:9 + | +LL | pub struct Foo; + | --------------- method `bar` not found for this +... +LL | Foo.bar() + | ^^^ method not found in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From e484f213eebd2a61870eb25a6cee0992eab6275c Mon Sep 17 00:00:00 2001 From: 12101111 Date: Sat, 14 Sep 2019 03:23:58 +0800 Subject: [PATCH 28/29] add trailing newline --- src/test/ui/issues/issue-64430.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-64430.rs b/src/test/ui/issues/issue-64430.rs index 8e58d0dda0e1b..0bc66e06e6731 100644 --- a/src/test/ui/issues/issue-64430.rs +++ b/src/test/ui/issues/issue-64430.rs @@ -11,4 +11,4 @@ fn main() { #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { loop{} -} \ No newline at end of file +} From 094af9743bd8a2b7cc2ae3b81b8110de9a93ea95 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Fri, 13 Sep 2019 20:37:38 -0600 Subject: [PATCH 29/29] Update value.rs --- src/librustc/mir/interpret/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 811c872968a56..11e7db5804c6a 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -17,8 +17,8 @@ pub struct RawConst<'tcx> { pub ty: Ty<'tcx>, } -/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations that -/// match the `LocalState` optimizations for easy conversions between `Operand` and `ConstValue`. +/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for +/// array length computations, enum discriminants and the pattern matching logic. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, HashStable)] pub enum ConstValue<'tcx> {