From f7bf282d9be6a0917f950e83f1856e1c5ede1a33 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 15 Nov 2020 12:58:34 -0800 Subject: [PATCH 01/16] MIR visitor: Don't treat debuginfo field access as a use of the struct --- compiler/rustc_middle/src/mir/visit.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index d8d639ab73451..e9a27c82af2b2 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1017,11 +1017,13 @@ macro_rules! visit_place_fns { let mut context = context; if !place.projection.is_empty() { - context = if context.is_mutating_use() { - PlaceContext::MutatingUse(MutatingUseContext::Projection) - } else { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) - }; + if context.is_use() { + context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; + } } self.visit_local(&place.local, context, location); From 34ea5d02ddaacfedd2d60460bf080b988b941d94 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 20 Nov 2020 17:03:12 +0100 Subject: [PATCH 02/16] const_generics: assert resolve hack causes an error --- compiler/rustc_resolve/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d18335ef2e63a..e8a06265adaf3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2539,6 +2539,7 @@ impl<'a> Resolver<'a> { span: Span, all_ribs: &[Rib<'a>], ) -> Res { + const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation"; debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; @@ -2639,6 +2640,8 @@ impl<'a> Resolver<'a> { }, ); } + + self.session.delay_span_bug(span, CG_BUG_STR); return Res::Err; } } @@ -2720,6 +2723,8 @@ impl<'a> Resolver<'a> { }, ); } + + self.session.delay_span_bug(span, CG_BUG_STR); return Res::Err; } From c85af74fcd5434e22790047b067120b8aba179d5 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 20 Nov 2020 23:31:36 +0100 Subject: [PATCH 03/16] update bug message for cg --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 2cca1a6ee5979..67491b5bf7e4e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -143,7 +143,7 @@ impl<'a> Resolver<'a> { _ => { bug!( "GenericParamsFromOuterFunction should only be used with Res::SelfTy, \ - DefKind::TyParam" + DefKind::TyParam or DefKind::ConstParam" ); } } From ee6f42ba94abc9db168da2949d110728761ba444 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 22 Nov 2020 02:13:53 +0100 Subject: [PATCH 04/16] Thread `Constness` through selection --- compiler/rustc_infer/src/traits/util.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 9 +++++---- compiler/rustc_middle/src/traits/select.rs | 2 +- compiler/rustc_middle/src/traits/structural_impls.rs | 4 +++- compiler/rustc_middle/src/ty/context.rs | 6 +++++- compiler/rustc_middle/src/ty/mod.rs | 8 +++++--- .../src/traits/select/candidate_assembly.rs | 4 ++-- .../src/traits/select/confirmation.rs | 12 +++++++----- .../rustc_trait_selection/src/traits/select/mod.rs | 6 +++--- .../src/traits/specialize/mod.rs | 4 ++-- compiler/rustc_trait_selection/src/traits/util.rs | 4 ++-- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 4 +++- src/tools/clippy/clippy_lints/src/future_not_send.rs | 2 +- 14 files changed, 41 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index b0b0e4372b8cd..8273c2d291d09 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -309,7 +309,7 @@ impl<'tcx, I: Iterator>> Iterator for FilterToT fn next(&mut self) -> Option> { while let Some(obligation) = self.base_iterator.next() { if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { - return Some(data); + return Some(data.value); } } None diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 4deb7225dcb61..1902a97e21c01 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -16,6 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::Constness; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; @@ -457,7 +458,7 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec), + Param(Vec, Constness), /// Virtual calls through an object. Object(ImplSourceObjectData<'tcx, N>), @@ -487,7 +488,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n) => n, + ImplSource::Param(n, _) => n, ImplSource::Builtin(i) => i.nested, ImplSource::AutoImpl(d) => d.nested, ImplSource::Closure(c) => c.nested, @@ -502,7 +503,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match &self { ImplSource::UserDefined(i) => &i.nested[..], - ImplSource::Param(n) => &n[..], + ImplSource::Param(n, _) => &n[..], ImplSource::Builtin(i) => &i.nested[..], ImplSource::AutoImpl(d) => &d.nested[..], ImplSource::Closure(c) => &c.nested[..], @@ -524,7 +525,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { substs: i.substs, nested: i.nested.into_iter().map(f).collect(), }), - ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()), + ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData { nested: i.nested.into_iter().map(f).collect(), }), diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index c570ad3273d4e..e056240f94150 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> { /// `false` if there are no *further* obligations. has_nested: bool, }, - ParamCandidate(ty::PolyTraitRef<'tcx>), + ParamCandidate(ty::ConstnessAnd>), ImplCandidate(DefId), AutoImplCandidate(DefId), diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 194e275496e95..5a17d38c73460 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -21,7 +21,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { super::ImplSource::Object(ref d) => write!(f, "{:?}", d), - super::ImplSource::Param(ref n) => write!(f, "ImplSourceParamData({:?})", n), + super::ImplSource::Param(ref n, ct) => { + write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) + } super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 36cbd36a7705f..a6f91278a3bc4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -42,7 +42,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathHash, Definitions}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate}; +use rustc_hir::{ + Constness, HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate, +}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; @@ -1635,6 +1637,8 @@ nop_list_lift! {projs; ProjectionKind => ProjectionKind} // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} +CloneLiftImpls! { for<'tcx> { Constness, } } + pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6a67935cd98fe..5d8edcf70bfd3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1503,9 +1503,11 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_ref(self) -> Option> { + pub fn to_opt_poly_trait_ref(self) -> Option>> { match self.skip_binders() { - PredicateAtom::Trait(t, _) => Some(ty::Binder::bind(t.trait_ref)), + PredicateAtom::Trait(t, constness) => { + Some(ConstnessAnd { constness, value: ty::Binder::bind(t.trait_ref) }) + } PredicateAtom::Projection(..) | PredicateAtom::Subtype(..) | PredicateAtom::RegionOutlives(..) @@ -1947,7 +1949,7 @@ impl<'tcx> ParamEnv<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ConstnessAnd { pub constness: Constness, pub value: T, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d2556c44fb453..ca3369b8f1e9d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -350,11 +350,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = - all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); + all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - let wc = self.evaluate_where_clause(stack, bound)?; + let wc = self.evaluate_where_clause(stack, bound.value)?; if wc.may_apply() { candidates.vec.push(ParamCandidate(bound)); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7c155c7684ec2..a42c802134649 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,6 +8,7 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; +use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; @@ -55,8 +56,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param); - Ok(ImplSource::Param(obligations)) + let obligations = self.confirm_param_candidate(obligation, param.value); + Ok(ImplSource::Param(obligations, param.constness)) } ImplCandidate(impl_def_id) => { @@ -70,7 +71,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ProjectionCandidate(idx) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; - Ok(ImplSource::Param(obligations)) + // FIXME(jschievink): constness + Ok(ImplSource::Param(obligations, Constness::NotConst)) } ObjectCandidate(idx) => { @@ -106,7 +108,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - Ok(ImplSource::Param(Vec::new())) + Ok(ImplSource::Param(Vec::new(), Constness::NotConst)) } BuiltinUnsizeCandidate => { @@ -151,7 +153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate) + .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 05ff9a6fb9ca6..63870d9714635 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1354,11 +1354,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(cand), + ) => !is_global(&cand.value), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(cand) + is_global(&cand.value) } ( ImplCandidate(_) @@ -1373,7 +1373,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(cand) && other.evaluation.must_apply_modulo_regions() + is_global(&cand.value) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 512591960f551..0133a961c11a7 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -498,8 +498,8 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option for (p, _) in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { - if Some(poly_trait_ref.def_id()) == sized_trait { - types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder()); + if Some(poly_trait_ref.value.def_id()) == sized_trait { + types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder()); continue; } } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 2430620323f72..ab4a81c7d152e 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref, *span)) + .map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone()); @@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'tcx> { .predicates .iter() .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.def_id()) + .map(|trait_ref| trait_ref.value.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); Some(def_id) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e5a792f229d19..5bcb16d21e09c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let mut cause = cause.clone(); if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { let derived_cause = traits::DerivedObligationCause { - parent_trait_ref, + parent_trait_ref: parent_trait_ref.value, parent_code: Rc::new(obligation.cause.code.clone()), }; cause.make_mut().code = diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 89c5adfa14c67..b011e26d64b9a 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1364,7 +1364,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { || { traits::transitive_bounds( tcx, - predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()), + predicates.iter().filter_map(|(p, _)| { + p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) + }), ) }, || param_name.to_string(), diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index d2a322e1223c6..f9697afe40525 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { for &(p, _span) in preds { let p = p.subst(cx.tcx, subst); if let Some(trait_ref) = p.to_opt_poly_trait_ref() { - if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() { + if Some(trait_ref.value.def_id()) == cx.tcx.lang_items().future_trait() { is_future = true; break; } From 71d350e33ad652fe925431a322dd9a554919dfc1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 22 Nov 2020 04:04:49 +0100 Subject: [PATCH 05/16] winnow: drop non-const cand. in favor of const --- .../rustc_trait_selection/src/traits/select/mod.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 63870d9714635..4189a81632aaa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -31,6 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::Constness; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; @@ -1335,7 +1336,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true, (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false, - (ParamCandidate(..), ParamCandidate(..)) => false, + (ParamCandidate(other), ParamCandidate(victim)) => { + if other.value == victim.value && victim.constness == Constness::NotConst { + // Drop otherwise equivalent non-const candidates in favor of const candidates. + true + } else { + false + } + } // Global bounds from the where clause should be ignored // here (see issue #50825). Otherwise, we have a where From e69fcea6094e89253e1412a99f890c6db5ea62ef Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 22 Nov 2020 04:19:46 +0100 Subject: [PATCH 06/16] const fn: allow use of trait impls from bounds --- .../src/transform/check_consts/validation.rs | 40 +++++++++++++++++-- .../call-generic-method-fail.rs | 11 +++++ .../call-generic-method-fail.stderr | 9 +++++ .../call-generic-method-nonconst-opt-out.rs | 24 +++++++++++ .../call-generic-method-nonconst.rs | 26 ++++++++++++ .../call-generic-method-pass.rs | 23 +++++++++++ 6 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index e4893044a1599..d00038f345c99 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -4,6 +4,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::cast::CastTy; @@ -11,9 +12,10 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{ self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt, TypeAndMut, }; +use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; -use rustc_trait_selection::traits::{self, TraitEngine}; +use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine}; use std::mem; use std::ops::Deref; @@ -765,9 +767,39 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { } }; - // Resolve a trait method call to its concrete implementation, which may be in a - // `const` trait impl. - if self.tcx.features().const_trait_impl { + // Attempting to call a trait method? + if let Some(trait_id) = tcx.trait_of_item(callee) { + if !self.tcx.features().const_trait_impl { + self.check_op(ops::FnCallNonConst(callee)); + return; + } + + let trait_ref = TraitRef::from_method(tcx, trait_id, substs); + let obligation = Obligation::new( + ObligationCause::dummy(), + param_env, + Binder::bind(TraitPredicate { + trait_ref: TraitRef::from_method(tcx, trait_id, substs), + }), + ); + + let implsrc = tcx.infer_ctxt().enter(|infcx| { + let mut selcx = SelectionContext::new(&infcx); + selcx.select(&obligation).unwrap() + }); + + // If the method is provided via a where-clause that does not use the `?const` + // opt-out, the call is allowed. + if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc { + debug!( + "const_trait_impl: provided {:?} via where-clause in {:?}", + trait_ref, param_env + ); + return; + } + + // Resolve a trait method call to its concrete implementation, which may be in a + // `const` trait impl. let instance = Instance::resolve(tcx, param_env, callee, substs); debug!("Resolving ({:?}) -> {:?}", callee, instance); if let Ok(Some(func)) = instance { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs new file mode 100644 index 0000000000000..6d4bfe722dee7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -0,0 +1,11 @@ +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![feature(const_trait_bound_opt_out)] +#![allow(incomplete_features)] + +pub const fn equals_self(t: &T) -> bool { + *t == *t + //~^ ERROR calls in constant functions are limited to constant functions +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr new file mode 100644 index 0000000000000..4b2fc56aaa78a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/call-generic-method-fail.rs:7:5 + | +LL | *t == *t + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs new file mode 100644 index 0000000000000..f0e3214222154 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![feature(const_trait_bound_opt_out)] +#![allow(incomplete_features)] + +struct S; + +impl PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + true +} + +pub const EQ: bool = equals_self(&S); + +// Calling `equals_self` with a type that only has a non-const impl is fine, because we opted out. + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs new file mode 100644 index 0000000000000..2c8f6354dc60f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -0,0 +1,26 @@ +// FIXME(jschievink): this is not rejected correctly (only when the non-const impl is actually used) +// ignore-test + +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +struct S; + +impl PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + true +} + +// Calling `equals_self` with something that has a non-const impl should throw an error, despite +// it not using the impl. + +pub const EQ: bool = equals_self(&S); +//~^ ERROR + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs new file mode 100644 index 0000000000000..e968e6ec7bb80 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -0,0 +1,23 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} From cb406848eccc3665dfadb241d94fe27137bd0dcb Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 22 Nov 2020 15:51:05 +0100 Subject: [PATCH 07/16] Add some more tests --- .../call-generic-method-chain.rs | 27 +++++++++++++++++++ .../call-generic-method-dup-bound.rs | 24 +++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs new file mode 100644 index 0000000000000..6a511f4ed3ed8 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -0,0 +1,27 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + *t == *t +} + +const fn equals_self_wrapper(t: &T) -> bool { + equals_self(t) +} + +pub const EQ: bool = equals_self_wrapper(&S); + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs new file mode 100644 index 0000000000000..b39d27779f45f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(const_fn)] +#![feature(const_trait_impl)] +#![feature(const_trait_bound_opt_out)] +#![allow(incomplete_features)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +// This duplicate bound should not result in ambiguities. It should be equivalent to a single const +// bound. +const fn equals_self(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} From 674f196c50240f462f4c6909d40d9d1ded845d66 Mon Sep 17 00:00:00 2001 From: LingMan Date: Sun, 11 Oct 2020 08:32:19 +0200 Subject: [PATCH 08/16] Use Option::and_then instead of open-coding it --- compiler/rustc_codegen_ssa/src/mir/block.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index fd20709f5d80f..9651d0505e684 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -37,12 +37,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { /// `funclet_bb` member if it is not `None`. fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>( &self, - fx: &'b mut FunctionCx<'a, 'tcx, Bx>, + fx: &'b FunctionCx<'a, 'tcx, Bx>, ) -> Option<&'b Bx::Funclet> { - match self.funclet_bb { - Some(funcl) => fx.funclets[funcl].as_ref(), - None => None, - } + self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref()) } fn lltarget>( From e0871cc0bedc9e7c6b0104600727a7109a2a0659 Mon Sep 17 00:00:00 2001 From: LingMan Date: Sun, 11 Oct 2020 20:52:48 +0200 Subject: [PATCH 09/16] Reduce boilerplate with the `?` operator --- .../rustc_builtin_macros/src/format_foreign.rs | 16 ++++++---------- .../src/traits/select/mod.rs | 10 +++------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index b69b00d65f2be..f00dfd1241fbb 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -649,17 +649,13 @@ pub mod shell { impl<'a> Iterator for Substitutions<'a> { type Item = Substitution<'a>; fn next(&mut self) -> Option { - match parse_next_substitution(self.s) { - Some((mut sub, tail)) => { - self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } - Some(sub) - } - None => None, + let (mut sub, tail) = parse_next_substitution(self.s)?; + self.s = tail; + if let Some(InnerSpan { start, end }) = sub.position() { + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; } + Some(sub) } fn size_hint(&self) -> (usize, Option) { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 05ff9a6fb9ca6..e9e7e9520eee4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2364,13 +2364,9 @@ impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> { type Item = &'o TraitObligationStack<'o, 'tcx>; fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> { - match self.head { - Some(o) => { - *self = o.previous; - Some(o) - } - None => None, - } + let o = self.head?; + *self = o.previous; + Some(o) } } From aca37b65f10e9aff3dfc04dcf273b6cd2112b052 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 2 Oct 2020 19:30:16 +0200 Subject: [PATCH 10/16] stabilize const_int_pow Also stabilize constctlz for const ctlz_nonzero. The public methods stabilized const by this commit are: * `{i*,u*}::checked_pow` * `{i*,u*}::saturating_pow` * `{i*,u*}::wrapping_pow` * `{i*,u*}::overflowing_pow` * `{i*,u*}::pow` * `u*::next_power_of_two` * `u*::checked_next_power_of_two` * `u*::wrapping_next_power_of_two` (the method itself is still unstable) --- library/core/src/intrinsics.rs | 2 +- library/core/src/lib.rs | 2 -- library/core/src/num/int_macros.rs | 10 +++++----- library/core/src/num/uint_macros.rs | 18 +++++++++--------- src/test/ui/consts/const-int-pow-rpass.rs | 1 - 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 433f0129306bd..c5b4a0abdb537 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1486,7 +1486,7 @@ extern "rust-intrinsic" { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` - #[rustc_const_unstable(feature = "constctlz", issue = "none")] + #[rustc_const_stable(feature = "constctlz", since = "1.49.0")] pub fn ctlz_nonzero(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0f91ff418e3ac..cb4c24c39677d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -78,8 +78,6 @@ #![feature(const_overflowing_int_methods)] #![feature(const_int_unchecked_arith)] #![feature(const_mut_refs)] -#![feature(const_int_pow)] -#![feature(constctlz)] #![feature(const_cttz)] #![feature(const_panic)] #![feature(const_pin)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 289f14a360a34..ee309775bae11 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -791,7 +791,7 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -974,7 +974,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1340,7 +1340,7 @@ assert_eq!(3i8.wrapping_pow(6), -39);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1707,7 +1707,7 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1757,7 +1757,7 @@ assert_eq!(x.pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index dbdc9c0fb5fcc..4e2691c0df07b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -749,7 +749,7 @@ Basic usage: assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -865,7 +865,7 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1159,7 +1159,7 @@ Basic usage: assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1484,7 +1484,7 @@ Basic usage: assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1532,7 +1532,7 @@ Basic usage: ", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1648,7 +1648,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } @@ -1677,7 +1677,7 @@ Basic usage: assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] #[inline] #[rustc_inherit_overflow_checks] pub const fn next_power_of_two(self) -> Self { @@ -1703,7 +1703,7 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] pub const fn checked_next_power_of_two(self) -> Option { self.one_less_than_next_power_of_two().checked_add(1) } @@ -1728,7 +1728,7 @@ $EndFeature, " ```"), #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] pub const fn wrapping_next_power_of_two(self) -> Self { self.one_less_than_next_power_of_two().wrapping_add(1) } diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs index 4f936236dbb20..30bcb78bcf270 100644 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -1,6 +1,5 @@ // run-pass -#![feature(const_int_pow)] #![feature(wrapping_next_power_of_two)] const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); From a6bcf7a2b6c6bc9557791d3075bb376196945727 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Mon, 23 Nov 2020 02:04:37 +0100 Subject: [PATCH 11/16] const_int_pow will be stabilized in 1.50.0, not in 1.49.0 Same for constctlz. --- library/core/src/intrinsics.rs | 2 +- library/core/src/num/int_macros.rs | 10 +++++----- library/core/src/num/uint_macros.rs | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index c5b4a0abdb537..5a5aa76a07627 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1486,7 +1486,7 @@ extern "rust-intrinsic" { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` - #[rustc_const_stable(feature = "constctlz", since = "1.49.0")] + #[rustc_const_stable(feature = "constctlz", since = "1.50.0")] pub fn ctlz_nonzero(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index ee309775bae11..33eefe5d26580 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -791,7 +791,7 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -974,7 +974,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1340,7 +1340,7 @@ assert_eq!(3i8.wrapping_pow(6), -39);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1707,7 +1707,7 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1757,7 +1757,7 @@ assert_eq!(x.pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 4e2691c0df07b..390c1b7e9e871 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -749,7 +749,7 @@ Basic usage: assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -865,7 +865,7 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1159,7 +1159,7 @@ Basic usage: assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1484,7 +1484,7 @@ Basic usage: assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1532,7 +1532,7 @@ Basic usage: ", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1648,7 +1648,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } @@ -1677,7 +1677,7 @@ Basic usage: assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[inline] #[rustc_inherit_overflow_checks] pub const fn next_power_of_two(self) -> Self { @@ -1703,7 +1703,7 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] pub const fn checked_next_power_of_two(self) -> Option { self.one_less_than_next_power_of_two().checked_add(1) } @@ -1728,7 +1728,7 @@ $EndFeature, " ```"), #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.49.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] pub const fn wrapping_next_power_of_two(self) -> Self { self.one_less_than_next_power_of_two().wrapping_add(1) } From 432a33e1e291191f551dc1e748bd477ba9ca8f21 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 22 Nov 2020 20:32:36 -0500 Subject: [PATCH 12/16] Fix typo in comment --- compiler/rustc_privacy/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4a0d356d3377b..b8fa9081aa34b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -691,7 +691,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::OpaqueTy(..) => { // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general) - // Since rustdoc never need to do codegen and doesn't care about link-time reachability, + // Since rustdoc never needs to do codegen and doesn't care about link-time reachability, // mark this as unreachable. // See https://github.com/rust-lang/rust/issues/75100 if !self.tcx.sess.opts.actually_rustdoc { From b196bec2362b1e17b15635da12cea173315e2b8c Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 22 Nov 2020 17:33:06 -0800 Subject: [PATCH 13/16] Add comment and remove obsolete special case --- compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_mir/src/transform/validate.rs | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index e9a27c82af2b2..a470c4547851f 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1018,6 +1018,7 @@ macro_rules! visit_place_fns { if !place.projection.is_empty() { if context.is_use() { + // ^ Only change the context if it is a real use, not a "use" in debuginfo. context = if context.is_mutating_use() { PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index 75399e9c32cc7..037c446d82f59 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef, - Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo, + Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable}; @@ -198,12 +198,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } - fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) { - // Debuginfo can contain field projections, which count as a use of the base local. Skip - // debuginfo so that we avoid the storage liveness assertion in that case. - self.visit_source_info(&var_debug_info.source_info); - } - fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed. if self.tcx.sess.opts.debugging_opts.validate_mir { From a804e38ddece7a3b1d8a1d5d4e197f747056ac49 Mon Sep 17 00:00:00 2001 From: oliver <16816606+o752d@users.noreply.github.com> Date: Mon, 23 Nov 2020 02:47:45 +0000 Subject: [PATCH 14/16] doc typo plus a small edit for clarity --- library/alloc/src/collections/btree/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 383f4487aff3d..eb32cef24a1ea 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1551,12 +1551,12 @@ where pred: F, inner: DrainFilterInner<'a, K, V>, } -/// Most of the implementation of DrainFilter, independent of the type +/// Most of the implementation of DrainFilter are generic over the type /// of the predicate, thus also serving for BTreeSet::DrainFilter. pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> { /// Reference to the length field in the borrowed map, updated live. length: &'a mut usize, - /// Burried reference to the root field in the borrowed map. + /// Buried reference to the root field in the borrowed map. /// Wrapped in `Option` to allow drop handler to `take` it. dormant_root: Option>>, /// Contains a leaf edge preceding the next element to be returned, or the last leaf edge. From cd8973250dff50a2b71641659baa36c70ab3d57e Mon Sep 17 00:00:00 2001 From: LingMan Date: Mon, 23 Nov 2020 04:58:21 +0100 Subject: [PATCH 15/16] Use Option::map instead of open coding it --- compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 5 +---- compiler/rustc_middle/src/ty/sty.rs | 5 +---- compiler/rustc_typeck/src/check/demand.rs | 10 ++++++---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 5e8ff14f0aaa6..96484034da7cd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1152,10 +1152,7 @@ impl<'ll> MemberDescription<'ll> { self.size.bits(), self.align.bits() as u32, self.offset.bits(), - match self.discriminant { - None => None, - Some(value) => Some(cx.const_u64(value)), - }, + self.discriminant.map(|v| cx.const_u64(v)), self.flags, self.type_metadata, ) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 4bf16436855f4..c906b8ac901a5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1106,10 +1106,7 @@ impl Binder { impl Binder> { pub fn transpose(self) -> Option> { - match self.0 { - Some(v) => Some(Binder(v)), - None => None, - } + self.0.map(Binder) } } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 241803fab1e68..d12d2cb59a5a9 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -810,10 +810,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // can be given the suggestion "u32::from(x) > y" rather than // "x > y.try_into().unwrap()". let lhs_expr_and_src = expected_ty_expr.and_then(|expr| { - match self.tcx.sess.source_map().span_to_snippet(expr.span).ok() { - Some(src) => Some((expr, src)), - None => None, - } + self.tcx + .sess + .source_map() + .span_to_snippet(expr.span) + .ok() + .map(|src| (expr, src)) }); let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) = (lhs_expr_and_src, exp_to_found_is_fallible) From c7d1189738f10ae80c804d1f977ace0179210615 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 23 Nov 2020 14:11:56 +0100 Subject: [PATCH 16/16] Add my (@flip1995) work mail to the mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index d3e400e5f9061..94f2938f11c26 100644 --- a/.mailmap +++ b/.mailmap @@ -230,6 +230,7 @@ Phil Dawes Phil Dawes Philipp Brüschweiler Philipp Brüschweiler Philipp Krones flip1995 +Philipp Krones Philipp Matthias Schäfer Przemysław Wesołek Przemek Wesołek Rafael Ávila de Espíndola Rafael Avila de Espindola