Add ConstnessAnd that implements ToPredicate

This commit is contained in:
Dylan MacKenzie 2020-01-13 20:30:32 -08:00
parent ab3081a70e
commit d2aefbb286
21 changed files with 155 additions and 74 deletions

View File

@ -1,6 +1,6 @@
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::Obligation; use crate::traits::Obligation;
use crate::ty::{self, ToPredicate, Ty, TyCtxt}; use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError}; use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
cause, cause,
recursion_depth: 0, recursion_depth: 0,
param_env, param_env,
predicate: trait_ref.to_predicate(), predicate: trait_ref.without_const().to_predicate(),
}, },
); );
} }

View File

@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound;
use crate::ty::fast_reject; use crate::ty::fast_reject;
use crate::ty::fold::TypeFolder; use crate::ty::fold::TypeFolder;
use crate::ty::SubtypePredicate; use crate::ty::SubtypePredicate;
use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::ty::{
self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
@ -130,7 +132,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
let (cond, error) = match (cond, error) { let (cond, error) = match (cond, error) {
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error), (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
_ => { _ => {
// FIXME: make this work in other cases too. // FIXME: make this work in other cases too.
return false; return false;
@ -138,7 +140,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}; };
for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) { for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
if let ty::Predicate::Trait(implication) = implication { if let ty::Predicate::Trait(implication, _) = implication {
let error = error.to_poly_trait_ref(); let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref(); let implication = implication.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here. // FIXME: I'm just not taking associated types at all here.
@ -530,7 +532,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return; return;
} }
match obligation.predicate { match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => { ty::Predicate::Trait(ref trait_predicate, _) => {
let trait_predicate = self.resolve_vars_if_possible(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
if self.tcx.sess.has_errors() && trait_predicate.references_error() { if self.tcx.sess.has_errors() && trait_predicate.references_error() {
@ -583,7 +585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"{}", "{}",
message.unwrap_or_else(|| format!( message.unwrap_or_else(|| format!(
"the trait bound `{}` is not satisfied{}", "the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(), trait_ref.without_const().to_predicate(),
post_message, post_message,
)) ))
); );
@ -695,7 +697,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
trait_pred trait_pred
}); });
let unit_obligation = Obligation { let unit_obligation = Obligation {
predicate: ty::Predicate::Trait(predicate), predicate: ty::Predicate::Trait(
predicate,
ast::Constness::NotConst,
),
..obligation.clone() ..obligation.clone()
}; };
if self.predicate_may_hold(&unit_obligation) { if self.predicate_may_hold(&unit_obligation) {
@ -988,7 +993,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> PredicateObligation<'tcx> { ) -> PredicateObligation<'tcx> {
let new_trait_ref = let new_trait_ref =
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) }; ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
Obligation::new(cause, param_env, new_trait_ref.to_predicate()) Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
} }
} }
@ -1076,7 +1081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
let mut err = match predicate { let mut err = match predicate {
ty::Predicate::Trait(ref data) => { ty::Predicate::Trait(ref data, _) => {
let trait_ref = data.to_poly_trait_ref(); let trait_ref = data.to_poly_trait_ref();
let self_ty = trait_ref.self_ty(); let self_ty = trait_ref.self_ty();
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref); debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
@ -1269,8 +1274,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) )
.value; .value;
let obligation = let obligation = Obligation::new(
Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate()); ObligationCause::dummy(),
param_env,
cleaned_pred.without_const().to_predicate(),
);
self.predicate_may_hold(&obligation) self.predicate_may_hold(&obligation)
}) })

View File

@ -6,7 +6,7 @@ use super::{
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::object_safety::object_safety_violations; use crate::traits::object_safety::object_safety_violations;
use crate::ty::TypeckTables; use crate::ty::TypeckTables;
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_errors::{ use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
@ -50,7 +50,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} else { } else {
" where" " where"
}, },
trait_ref.to_predicate(), trait_ref.without_const().to_predicate(),
), ),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
@ -340,8 +340,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty); let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
let substs = self.tcx.mk_substs_trait(new_self_ty, &[]); let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs); let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
let new_obligation = let new_obligation = Obligation::new(
Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate()); ObligationCause::dummy(),
param_env,
new_trait_ref.without_const().to_predicate(),
);
if self.predicate_must_hold_modulo_regions(&new_obligation) { if self.predicate_must_hold_modulo_regions(&new_obligation) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
// We have a very specific type of error, where just borrowing this argument // We have a very specific type of error, where just borrowing this argument
@ -1122,7 +1125,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// the type. The last generator has information about where the bound was introduced. At // the type. The last generator has information about where the bound was introduced. At
// least one generator should be present for this diagnostic to be modified. // least one generator should be present for this diagnostic to be modified.
let (mut trait_ref, mut target_ty) = match obligation.predicate { let (mut trait_ref, mut target_ty) = match obligation.predicate {
ty::Predicate::Trait(p) => { ty::Predicate::Trait(p, _) => {
(Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())) (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
} }
_ => (None, None), _ => (None, None),
@ -1545,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.note(&format!("required because it appears within the type `{}`", ty)); err.note(&format!("required because it appears within the type `{}`", ty));
obligated_types.push(ty); obligated_types.push(ty);
let parent_predicate = parent_trait_ref.to_predicate(); let parent_predicate = parent_trait_ref.without_const().to_predicate();
if !self.is_recursive_obligation(obligated_types, &data.parent_code) { if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
@ -1562,7 +1565,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
parent_trait_ref.print_only_trait_path(), parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty() parent_trait_ref.skip_binder().self_ty()
)); ));
let parent_predicate = parent_trait_ref.to_predicate(); let parent_predicate = parent_trait_ref.without_const().to_predicate();
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,

View File

@ -29,7 +29,7 @@ use crate::mir::interpret::ErrorHandled;
use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt}; use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
use crate::util::common::ErrorReported; use crate::util::common::ErrorReported;
use chalk_engine; use chalk_engine;
use rustc_hir as hir; use rustc_hir as hir;
@ -732,7 +732,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
param_env, param_env,
cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID), cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
recursion_depth: 0, recursion_depth: 0,
predicate: trait_ref.to_predicate(), predicate: trait_ref.without_const().to_predicate(),
}; };
let result = infcx.predicate_must_hold_modulo_regions(&obligation); let result = infcx.predicate_must_hold_modulo_regions(&obligation);

View File

@ -12,7 +12,7 @@ use super::elaborate_predicates;
use crate::traits::{self, Obligation, ObligationCause}; use crate::traits::{self, Obligation, ObligationCause};
use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
@ -585,6 +585,7 @@ fn receiver_is_dispatchable<'tcx>(
def_id: unsize_did, def_id: unsize_did,
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]), substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
} }
.without_const()
.to_predicate(); .to_predicate();
// U: Trait<Arg1, ..., ArgN> // U: Trait<Arg1, ..., ArgN>
@ -598,7 +599,7 @@ fn receiver_is_dispatchable<'tcx>(
} }
}); });
ty::TraitRef { def_id: unsize_did, substs }.to_predicate() ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
}; };
let caller_bounds: Vec<Predicate<'tcx>> = param_env let caller_bounds: Vec<Predicate<'tcx>> = param_env
@ -620,6 +621,7 @@ fn receiver_is_dispatchable<'tcx>(
def_id: dispatch_from_dyn_did, def_id: dispatch_from_dyn_did,
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
} }
.without_const()
.to_predicate(); .to_predicate();
Obligation::new(ObligationCause::dummy(), param_env, predicate) Obligation::new(ObligationCause::dummy(), param_env, predicate)

View File

@ -16,7 +16,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::fold::{TypeFoldable, TypeFolder};
use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt}; use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_macros::HashStable; use rustc_macros::HashStable;
@ -738,7 +738,12 @@ fn get_paranoid_cache_value_obligation<'a, 'tcx>(
depth: usize, depth: usize,
) -> PredicateObligation<'tcx> { ) -> PredicateObligation<'tcx> {
let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref(); let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() } Obligation {
cause,
recursion_depth: depth,
param_env,
predicate: trait_ref.without_const().to_predicate(),
}
} }
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
@ -772,7 +777,7 @@ fn normalize_to_error<'a, 'tcx>(
cause, cause,
recursion_depth: depth, recursion_depth: depth,
param_env, param_env,
predicate: trait_ref.to_predicate(), predicate: trait_ref.without_const().to_predicate(),
}; };
let tcx = selcx.infcx().tcx; let tcx = selcx.infcx().tcx;
let def_id = projection_ty.item_def_id; let def_id = projection_ty.item_def_id;

View File

@ -37,7 +37,7 @@ use crate::middle::lang_items;
use crate::ty::fast_reject; use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation; use crate::ty::relate::TypeRelation;
use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -3368,7 +3368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
tcx.require_lang_item(lang_items::SizedTraitLangItem, None), tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
tcx.mk_substs_trait(source, &[]), tcx.mk_substs_trait(source, &[]),
); );
nested.push(predicate_to_obligation(tr.to_predicate())); nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
// If the type is `Foo + 'a`, ensure that the type // If the type is `Foo + 'a`, ensure that the type
// being cast to `Foo + 'a` outlives `'a`: // being cast to `Foo + 'a` outlives `'a`:

View File

@ -4,7 +4,7 @@ use smallvec::SmallVec;
use crate::ty::outlives::Component; use crate::ty::outlives::Component;
use crate::ty::subst::{GenericArg, Subst, SubstsRef}; use crate::ty::subst::{GenericArg, Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt}; use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -99,14 +99,14 @@ pub fn elaborate_trait_ref<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> { ) -> Elaborator<'tcx> {
elaborate_predicates(tcx, vec![trait_ref.to_predicate()]) elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
} }
pub fn elaborate_trait_refs<'tcx>( pub fn elaborate_trait_refs<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> { ) -> Elaborator<'tcx> {
let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect(); let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
elaborate_predicates(tcx, predicates) elaborate_predicates(tcx, predicates)
} }
@ -358,7 +358,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
let tcx = self.tcx; let tcx = self.tcx;
let trait_ref = item.trait_ref(); let trait_ref = item.trait_ref();
let pred = trait_ref.to_predicate(); let pred = trait_ref.without_const().to_predicate();
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
@ -370,13 +370,9 @@ impl<'tcx> TraitAliasExpander<'tcx> {
// Don't recurse if this trait alias is already on the stack for the DFS search. // Don't recurse if this trait alias is already on the stack for the DFS search.
let anon_pred = anonymize_predicate(tcx, &pred); let anon_pred = anonymize_predicate(tcx, &pred);
if item if item.path.iter().rev().skip(1).any(|(tr, _)| {
.path anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
.iter() }) {
.rev()
.skip(1)
.any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred)
{
return false; return false;
} }
@ -545,7 +541,12 @@ pub fn predicate_for_trait_ref<'tcx>(
trait_ref: ty::TraitRef<'tcx>, trait_ref: ty::TraitRef<'tcx>,
recursion_depth: usize, recursion_depth: usize,
) -> PredicateObligation<'tcx> { ) -> PredicateObligation<'tcx> {
Obligation { cause, param_env, recursion_depth, predicate: trait_ref.to_predicate() } Obligation {
cause,
param_env,
recursion_depth,
predicate: trait_ref.without_const().to_predicate(),
}
} }
pub fn predicate_for_trait_def( pub fn predicate_for_trait_def(

View File

@ -3,7 +3,7 @@ use crate::infer::InferCtxt;
use crate::middle::lang_items; use crate::middle::lang_items;
use crate::traits::{self, AssocTypeBoundData}; use crate::traits::{self, AssocTypeBoundData};
use crate::ty::subst::SubstsRef; use crate::ty::subst::SubstsRef;
use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_span::symbol::{kw, Ident}; use rustc_span::symbol::{kw, Ident};
@ -350,7 +350,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.compute_trait_ref(&trait_ref, Elaborate::None); self.compute_trait_ref(&trait_ref, Elaborate::None);
if !data.has_escaping_bound_vars() { if !data.has_escaping_bound_vars() {
let predicate = trait_ref.to_predicate(); let predicate = trait_ref.without_const().to_predicate();
let cause = self.cause(traits::ProjectionWf(data)); let cause = self.cause(traits::ProjectionWf(data));
self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
} }
@ -378,7 +378,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
substs: self.infcx.tcx.mk_substs_trait(subty, &[]), substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
}; };
self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate())); self.out.push(traits::Obligation::new(
cause,
self.param_env,
trait_ref.without_const().to_predicate(),
));
} }
} }

View File

@ -52,7 +52,7 @@ use std::ops::Deref;
use std::ops::Range; use std::ops::Range;
use std::slice; use std::slice;
use std::{mem, ptr}; use std::{mem, ptr};
use syntax::ast::{self, Ident, Name, NodeId}; use syntax::ast::{self, Constness, Ident, Name, NodeId};
use syntax::attr; use syntax::attr;
pub use self::sty::BoundRegion::*; pub use self::sty::BoundRegion::*;
@ -1072,7 +1072,7 @@ pub enum Predicate<'tcx> {
/// A trait predicate will have `Constness::Const` if it originates /// A trait predicate will have `Constness::Const` if it originates
/// from a bound on a `const fn` without the `?const` opt-out (e.g., /// from a bound on a `const fn` without the `?const` opt-out (e.g.,
/// `const fn foobar<Foo: Bar>() {}`). /// `const fn foobar<Foo: Bar>() {}`).
Trait(PolyTraitPredicate<'tcx>, ast::Constness), Trait(PolyTraitPredicate<'tcx>, Constness),
/// `where 'a: 'b` /// `where 'a: 'b`
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
@ -1340,18 +1340,33 @@ pub trait ToPredicate<'tcx> {
fn to_predicate(&self) -> Predicate<'tcx>; fn to_predicate(&self) -> Predicate<'tcx>;
} }
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> { fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait( ty::Predicate::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() }), ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
ast::Constness::NotConst, self.constness,
) )
} }
} }
impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> { fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(self.to_poly_trait_predicate(), ast::Constness::NotConst) ty::Predicate::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
self.constness,
)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&PolyTraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
} }
} }
@ -1707,6 +1722,33 @@ impl<'tcx> ParamEnv<'tcx> {
} }
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ConstnessAnd<T> {
pub constness: Constness,
pub value: T,
}
// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate()` to ensure that
// the constness of trait bounds is being propagated correctly.
pub trait WithConstness: Sized {
#[inline]
fn with_constness(self, constness: Constness) -> ConstnessAnd<Self> {
ConstnessAnd { constness, value: self }
}
#[inline]
fn with_const(self) -> ConstnessAnd<Self> {
self.with_constness(Constness::Const)
}
#[inline]
fn without_const(self) -> ConstnessAnd<Self> {
self.with_constness(Constness::NotConst)
}
}
impl<T> WithConstness for T {}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
pub struct ParamEnvAnd<'tcx, T> { pub struct ParamEnvAnd<'tcx, T> {
pub param_env: ParamEnv<'tcx>, pub param_env: ParamEnv<'tcx>,

View File

@ -12,7 +12,9 @@ use crate::mir::interpret::Scalar;
use crate::mir::Promoted; use crate::mir::Promoted;
use crate::ty::layout::VariantIdx; use crate::ty::layout::VariantIdx;
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; use crate::ty::{
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
};
use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS}; use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS};
use polonius_engine::Atom; use polonius_engine::Atom;
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
@ -665,14 +667,16 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
use crate::ty::ToPredicate; use crate::ty::ToPredicate;
match *self.skip_binder() { match *self.skip_binder() {
ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(), ExistentialPredicate::Trait(tr) => {
Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate()
}
ExistentialPredicate::Projection(p) => { ExistentialPredicate::Projection(p) => {
ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))) ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
} }
ExistentialPredicate::AutoTrait(did) => { ExistentialPredicate::AutoTrait(did) => {
let trait_ref = let trait_ref =
Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) }); Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
trait_ref.to_predicate() trait_ref.without_const().to_predicate()
} }
} }
} }

View File

@ -2,7 +2,7 @@ use rustc::hir::map as hir_map;
use rustc::session::CrateDisambiguator; use rustc::session::CrateDisambiguator;
use rustc::traits::{self}; use rustc::traits::{self};
use rustc::ty::subst::Subst; use rustc::ty::subst::Subst;
use rustc::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@ -58,6 +58,7 @@ fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>)
def_id: sized_trait, def_id: sized_trait,
substs: tcx.mk_substs_trait(ty, &[]), substs: tcx.mk_substs_trait(ty, &[]),
}) })
.without_const()
.to_predicate(); .to_predicate();
let predicates = tcx.predicates_of(adtdef.did).predicates; let predicates = tcx.predicates_of(adtdef.did).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }

View File

@ -17,7 +17,7 @@ use rustc::traits::astconv_object_safety_violations;
use rustc::traits::error_reporting::report_object_safety_error; use rustc::traits::error_reporting::report_object_safety_error;
use rustc::traits::wf::object_region_bounds; use rustc::traits::wf::object_region_bounds;
use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::{GenericParamDef, GenericParamDefKind};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
@ -2980,7 +2980,7 @@ impl<'tcx> Bounds<'tcx> {
def_id: sized, def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]), substs: tcx.mk_substs_trait(param_ty, &[]),
}); });
(trait_ref.to_predicate(), span) (trait_ref.without_const().to_predicate(), span)
}) })
}); });

View File

@ -5,7 +5,7 @@ use rustc::infer::{InferCtxt, InferOk};
use rustc::session::DiagnosticMessageId; use rustc::session::DiagnosticMessageId;
use rustc::traits::{self, TraitEngine}; use rustc::traits::{self, TraitEngine};
use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc::ty::{self, TraitRef, Ty, TyCtxt}; use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
use rustc::ty::{ToPredicate, TypeFoldable}; use rustc::ty::{ToPredicate, TypeFoldable};
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
@ -124,8 +124,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
let cause = traits::ObligationCause::misc(self.span, self.body_id); let cause = traits::ObligationCause::misc(self.span, self.body_id);
let obligation = let obligation = traits::Obligation::new(
traits::Obligation::new(cause.clone(), self.param_env, trait_ref.to_predicate()); cause.clone(),
self.param_env,
trait_ref.without_const().to_predicate(),
);
if !self.infcx.predicate_may_hold(&obligation) { if !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation"); debug!("overloaded_deref_ty: cannot match obligation");
return None; return None;

View File

@ -17,7 +17,7 @@ use rustc::traits;
use rustc::ty::subst::Subst; use rustc::ty::subst::Subst;
use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::GenericParamDefKind; use rustc::ty::GenericParamDefKind;
use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable}; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
@ -322,7 +322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span, span,
self.body_id, self.body_id,
self.param_env, self.param_env,
poly_trait_ref.to_predicate(), poly_trait_ref.without_const().to_predicate(),
); );
// Now we want to know if this can be matched // Now we want to know if this can be matched

View File

@ -25,6 +25,7 @@ use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc::ty::GenericParamDefKind; use rustc::ty::GenericParamDefKind;
use rustc::ty::{ use rustc::ty::{
self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
WithConstness,
}; };
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -1396,7 +1397,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} }
TraitCandidate(trait_ref) => { TraitCandidate(trait_ref) => {
let predicate = trait_ref.to_predicate(); let predicate = trait_ref.without_const().to_predicate();
let obligation = traits::Obligation::new(cause, self.param_env, predicate); let obligation = traits::Obligation::new(cause, self.param_env, predicate);
if !self.predicate_may_hold(&obligation) { if !self.predicate_may_hold(&obligation) {
if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {

View File

@ -9,7 +9,7 @@ use rustc::hir::map::Map;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::traits::Obligation; use rustc::traits::Obligation;
use rustc::ty::print::with_crate_prefix; use rustc::ty::print::with_crate_prefix;
use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
@ -59,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span, span,
self.body_id, self.body_id,
self.param_env, self.param_env,
poly_trait_ref.to_predicate(), poly_trait_ref.without_const().to_predicate(),
); );
self.predicate_may_hold(&obligation) self.predicate_may_hold(&obligation)
}) })

View File

@ -112,7 +112,7 @@ use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSel
use rustc::ty::util::{Discr, IntTypeExt, Representability}; use rustc::ty::util::{Discr, IntTypeExt, Representability};
use rustc::ty::{ use rustc::ty::{
self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef, self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
ToPredicate, Ty, TyCtxt, UserType, ToPredicate, Ty, TyCtxt, UserType, WithConstness,
}; };
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -1423,7 +1423,7 @@ fn check_fn<'a, 'tcx>(
inherited.register_predicate(traits::Obligation::new( inherited.register_predicate(traits::Obligation::new(
cause, cause,
param_env, param_env,
trait_ref.to_predicate(), trait_ref.without_const().to_predicate(),
)); ));
} }
} }

View File

@ -6,7 +6,9 @@ use rustc::middle::lang_items;
use rustc::session::parse::feature_err; use rustc::session::parse::feature_err;
use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::subst::{InternalSubsts, Subst};
use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -955,7 +957,8 @@ fn receiver_is_implemented(
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]), substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
}; };
let obligation = traits::Obligation::new(cause, fcx.param_env, trait_ref.to_predicate()); let obligation =
traits::Obligation::new(cause, fcx.param_env, trait_ref.without_const().to_predicate());
if fcx.predicate_must_hold_modulo_regions(&obligation) { if fcx.predicate_must_hold_modulo_regions(&obligation) {
true true

View File

@ -30,7 +30,7 @@ use rustc::ty::subst::GenericArgKind;
use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::subst::{InternalSubsts, Subst};
use rustc::ty::util::Discr; use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt; use rustc::ty::util::IntTypeExt;
use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness};
use rustc::ty::{ReprOptions, ToPredicate}; use rustc::ty::{ReprOptions, ToPredicate};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
@ -411,7 +411,8 @@ fn type_param_predicates(
// Implied `Self: Trait` and supertrait bounds. // Implied `Self: Trait` and supertrait bounds.
if param_id == item_hir_id { if param_id == item_hir_id {
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
extend = Some((identity_trait_ref.to_predicate(), item.span)); extend =
Some((identity_trait_ref.without_const().to_predicate(), item.span));
} }
generics generics
} }
@ -2056,7 +2057,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);
result.predicates = result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
ty::TraitRef::identity(tcx, def_id).to_predicate(), ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(),
span, span,
)))); ))));
} }
@ -2230,7 +2231,10 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
// (see below). Recall that a default impl is not itself an impl, but rather a // (see below). Recall that a default impl is not itself an impl, but rather a
// set of defaults that can be incorporated into another impl. // set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait { if let Some(trait_ref) = is_default_impl_trait {
predicates.push((trait_ref.to_poly_trait_ref().to_predicate(), tcx.def_span(def_id))); predicates.push((
trait_ref.to_poly_trait_ref().without_const().to_predicate(),
tcx.def_span(def_id),
));
} }
// Collect the region predicates that were declared inline as // Collect the region predicates that were declared inline as

View File

@ -1,7 +1,7 @@
use rustc::infer::InferOk; use rustc::infer::InferOk;
use rustc::traits; use rustc::traits;
use rustc::ty::subst::Subst; use rustc::ty::subst::Subst;
use rustc::ty::ToPredicate; use rustc::ty::{ToPredicate, WithConstness};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -64,7 +64,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
match infcx.evaluate_obligation(&traits::Obligation::new( match infcx.evaluate_obligation(&traits::Obligation::new(
cause, cause,
param_env, param_env,
trait_ref.to_predicate(), trait_ref.without_const().to_predicate(),
)) { )) {
Ok(eval_result) => eval_result.may_apply(), Ok(eval_result) => eval_result.may_apply(),
Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no