1
Fork 0

Thread Constness through selection

This commit is contained in:
Jonas Schievink 2020-11-22 02:13:53 +01:00
parent a1a13b2bc4
commit ee6f42ba94
14 changed files with 41 additions and 28 deletions

View file

@ -309,7 +309,7 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(obligation) = self.base_iterator.next() { while let Some(obligation) = self.base_iterator.next() {
if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
return Some(data); return Some(data.value);
} }
} }
None None

View file

@ -16,6 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::Constness;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -457,7 +458,7 @@ pub enum ImplSource<'tcx, N> {
/// for some type parameter. The `Vec<N>` represents the /// for some type parameter. The `Vec<N>` represents the
/// obligations incurred from normalizing the where-clause (if /// obligations incurred from normalizing the where-clause (if
/// any). /// any).
Param(Vec<N>), Param(Vec<N>, Constness),
/// Virtual calls through an object. /// Virtual calls through an object.
Object(ImplSourceObjectData<'tcx, N>), Object(ImplSourceObjectData<'tcx, N>),
@ -487,7 +488,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> { pub fn nested_obligations(self) -> Vec<N> {
match self { match self {
ImplSource::UserDefined(i) => i.nested, ImplSource::UserDefined(i) => i.nested,
ImplSource::Param(n) => n, ImplSource::Param(n, _) => n,
ImplSource::Builtin(i) => i.nested, ImplSource::Builtin(i) => i.nested,
ImplSource::AutoImpl(d) => d.nested, ImplSource::AutoImpl(d) => d.nested,
ImplSource::Closure(c) => c.nested, ImplSource::Closure(c) => c.nested,
@ -502,7 +503,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn borrow_nested_obligations(&self) -> &[N] { pub fn borrow_nested_obligations(&self) -> &[N] {
match &self { match &self {
ImplSource::UserDefined(i) => &i.nested[..], ImplSource::UserDefined(i) => &i.nested[..],
ImplSource::Param(n) => &n[..], ImplSource::Param(n, _) => &n[..],
ImplSource::Builtin(i) => &i.nested[..], ImplSource::Builtin(i) => &i.nested[..],
ImplSource::AutoImpl(d) => &d.nested[..], ImplSource::AutoImpl(d) => &d.nested[..],
ImplSource::Closure(c) => &c.nested[..], ImplSource::Closure(c) => &c.nested[..],
@ -524,7 +525,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
substs: i.substs, substs: i.substs,
nested: i.nested.into_iter().map(f).collect(), 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 { ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
nested: i.nested.into_iter().map(f).collect(), nested: i.nested.into_iter().map(f).collect(),
}), }),

View file

@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> {
/// `false` if there are no *further* obligations. /// `false` if there are no *further* obligations.
has_nested: bool, has_nested: bool,
}, },
ParamCandidate(ty::PolyTraitRef<'tcx>), ParamCandidate(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>),
ImplCandidate(DefId), ImplCandidate(DefId),
AutoImplCandidate(DefId), AutoImplCandidate(DefId),

View file

@ -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::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), super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),

View file

@ -42,7 +42,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::{DefPathHash, Definitions}; use rustc_hir::definitions::{DefPathHash, Definitions};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem; 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_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; 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>`. // This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
CloneLiftImpls! { for<'tcx> { Constness, } }
pub mod tls { pub mod tls {
use super::{ptr_eq, GlobalCtxt, TyCtxt}; use super::{ptr_eq, GlobalCtxt, TyCtxt};

View file

@ -1503,9 +1503,11 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
} }
impl<'tcx> Predicate<'tcx> { impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_ref(self) -> Option<PolyTraitRef<'tcx>> { pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
match self.skip_binders() { 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::Projection(..)
| PredicateAtom::Subtype(..) | PredicateAtom::Subtype(..)
| PredicateAtom::RegionOutlives(..) | 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<T> { pub struct ConstnessAnd<T> {
pub constness: Constness, pub constness: Constness,
pub value: T, pub value: T,

View file

@ -350,11 +350,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Micro-optimization: filter out predicates relating to different traits. // Micro-optimization: filter out predicates relating to different traits.
let matching_bounds = 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. // Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in matching_bounds { 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() { if wc.may_apply() {
candidates.vec.push(ParamCandidate(bound)); candidates.vec.push(ParamCandidate(bound));
} }

View file

@ -8,6 +8,7 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::Constness;
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@ -55,8 +56,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
ParamCandidate(param) => { ParamCandidate(param) => {
let obligations = self.confirm_param_candidate(obligation, param); let obligations = self.confirm_param_candidate(obligation, param.value);
Ok(ImplSource::Param(obligations)) Ok(ImplSource::Param(obligations, param.constness))
} }
ImplCandidate(impl_def_id) => { ImplCandidate(impl_def_id) => {
@ -70,7 +71,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ProjectionCandidate(idx) => { ProjectionCandidate(idx) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?; let obligations = self.confirm_projection_candidate(obligation, idx)?;
Ok(ImplSource::Param(obligations)) // FIXME(jschievink): constness
Ok(ImplSource::Param(obligations, Constness::NotConst))
} }
ObjectCandidate(idx) => { 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 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 // 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. // 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 => { BuiltinUnsizeCandidate => {
@ -151,7 +153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.extend(self.infcx.commit_if_ok(|_| { obligations.extend(self.infcx.commit_if_ok(|_| {
self.infcx self.infcx
.at(&obligation.cause, obligation.param_env) .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(|InferOk { obligations, .. }| obligations)
.map_err(|_| Unimplemented) .map_err(|_| Unimplemented)
})?); })?);

View file

@ -1354,11 +1354,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| TraitAliasCandidate(..) | TraitAliasCandidate(..)
| ObjectCandidate(_) | ObjectCandidate(_)
| ProjectionCandidate(_), | ProjectionCandidate(_),
) => !is_global(cand), ) => !is_global(&cand.value),
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
is_global(cand) is_global(&cand.value)
} }
( (
ImplCandidate(_) ImplCandidate(_)
@ -1373,7 +1373,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) => { ) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (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)) (ProjectionCandidate(i), ProjectionCandidate(j))

View file

@ -498,8 +498,8 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String>
for (p, _) in predicates { for (p, _) in predicates {
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
if Some(poly_trait_ref.def_id()) == sized_trait { if Some(poly_trait_ref.value.def_id()) == sized_trait {
types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder()); types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder());
continue; continue;
} }
} }

View file

@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
pred.subst_supertrait(tcx, &trait_ref) pred.subst_supertrait(tcx, &trait_ref)
.to_opt_poly_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()); debug!("expand_trait_aliases: items={:?}", items.clone());
@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'tcx> {
.predicates .predicates
.iter() .iter()
.filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) .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)), .filter(|&super_def_id| visited.insert(super_def_id)),
); );
Some(def_id) Some(def_id)

View file

@ -294,7 +294,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let mut cause = cause.clone(); let mut cause = cause.clone();
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
let derived_cause = traits::DerivedObligationCause { let derived_cause = traits::DerivedObligationCause {
parent_trait_ref, parent_trait_ref: parent_trait_ref.value,
parent_code: Rc::new(obligation.cause.code.clone()), parent_code: Rc::new(obligation.cause.code.clone()),
}; };
cause.make_mut().code = cause.make_mut().code =

View file

@ -1364,7 +1364,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|| { || {
traits::transitive_bounds( traits::transitive_bounds(
tcx, 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(), || param_name.to_string(),

View file

@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
for &(p, _span) in preds { for &(p, _span) in preds {
let p = p.subst(cx.tcx, subst); let p = p.subst(cx.tcx, subst);
if let Some(trait_ref) = p.to_opt_poly_trait_ref() { 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; is_future = true;
break; break;
} }