From ee6f42ba94abc9db168da2949d110728761ba444 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 22 Nov 2020 02:13:53 +0100 Subject: [PATCH] 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 b0b0e4372b8..8273c2d291d 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 4deb7225dcb..1902a97e21c 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 c570ad3273d..e056240f941 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 194e275496e..5a17d38c734 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 36cbd36a770..a6f91278a3b 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 6a67935cd98..5d8edcf70bf 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 d2556c44fb4..ca3369b8f1e 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 7c155c7684e..a42c8021346 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 05ff9a6fb9c..63870d97146 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 512591960f5..0133a961c11 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 2430620323f..ab4a81c7d15 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 e5a792f229d..5bcb16d21e0 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 89c5adfa14c..b011e26d64b 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 d2a322e1223..f9697afe405 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; }