dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"syntax 0.0.0",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_cratesio_shim 0.0.0",
+ "rustc_data_structures 0.0.0",
"serialize 0.0.0",
]
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
+ "rustc_target 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
}
};
- tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
+ tcx.replace_escaping_bound_vars(value, fld_r, fld_t).0
}
}
// with a fresh region variable. These region variables --
// but no other pre-existing region variables -- can name
// the placeholders.
- let (a_prime, _) =
- self.infcx.replace_late_bound_regions_with_fresh_var(
- span,
- HigherRankedType,
- a);
+ let (a_prime, _) = self.infcx.replace_bound_vars_with_fresh_vars(
+ span,
+ HigherRankedType,
+ a
+ );
debug!("a_prime={:?}", a_prime);
debug!("b_prime={:?}", b_prime);
self.report_and_explain_type_error(trace, &err)
}
- pub fn replace_late_bound_regions_with_fresh_var<T>(
+ pub fn replace_bound_vars_with_fresh_vars<T>(
&self,
span: Span,
lbrct: LateBoundRegionConversionTime,
- value: &ty::Binder<T>,
+ value: &ty::Binder<T>
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<'tcx>
{
- self.tcx.replace_late_bound_regions(value, |br| {
- self.next_region_var(LateBoundRegion(span, br, lbrct))
- })
+ let fld_r = |br| self.next_region_var(LateBoundRegion(span, br, lbrct));
+ let fld_t = |_| self.next_ty_var(TypeVariableOrigin::MiscVariable(span));
+ self.tcx.replace_bound_vars(value, fld_r, fld_t)
}
/// Given a higher-ranked projection predicate like:
use hir::def::Def;
use hir::def_id::DefId;
use ty::{self, Ty, TyCtxt};
-use ty::layout::{LayoutError, Pointer, SizeSkeleton};
+use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
use rustc_target::spec::abi::Abi::RustIntrinsic;
+use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use hir;
if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() {
let data_idx;
- if def.variants[0].fields.is_empty() {
- data_idx = 1;
- } else if def.variants[1].fields.is_empty() {
- data_idx = 0;
+ let one = VariantIdx::new(1);
+ let zero = VariantIdx::new(0);
+
+ if def.variants[zero].fields.is_empty() {
+ data_idx = one;
+ } else if def.variants[one].fields.is_empty() {
+ data_idx = zero;
} else {
return ty;
}
use ty::adjustment;
use ty::{self, Ty, TyCtxt};
use ty::fold::TypeFoldable;
+use ty::layout::VariantIdx;
use hir::{MutImmutable, MutMutable, PatKind};
use hir::pat_util::EnumerateAndAdjustIterator;
use std::fmt;
use std::hash::{Hash, Hasher};
use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
use std::rc::Rc;
use util::nodemap::ItemLocalSet;
}
_ => {
assert_eq!(adt_def.variants.len(), 1);
- &adt_def.variants[0]
+ &adt_def.variants[VariantIdx::new(0)]
}
};
Some((adt_def, &variant_def.fields[field_index]))
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::subst::{CanonicalUserSubsts, Subst, Substs};
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
+use ty::layout::VariantIdx;
use util::ppaux;
pub use mir::interpret::AssertMessage;
/// Write the discriminant for a variant to the enum Place.
SetDiscriminant {
place: Place<'tcx>,
- variant_index: usize,
+ variant_index: VariantIdx,
},
/// Start a live range for the storage of the local.
/// "Downcast" to a variant of an ADT. Currently, we only introduce
/// this for ADTs with more than one variant. It may be better to
/// just introduce it always, or always for enums.
- Downcast(&'tcx AdtDef, usize),
+ Downcast(&'tcx AdtDef, VariantIdx),
}
/// Alias for projections as they appear in places, where the base is a place
/// and the index is a local.
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
+// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
+static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
+ mem::size_of::<PlaceElem<'_>>() <= 16
+);
+
/// Alias for projections as they appear in `UserTypeProjection`, where we
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
self.elem(ProjectionElem::Deref)
}
- pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
+ pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(adt_def, variant_index))
}
/// active field index would identity the field `c`
Adt(
&'tcx AdtDef,
- usize,
+ VariantIdx,
&'tcx Substs<'tcx>,
Option<UserTypeAnnotation<'tcx>>,
Option<usize>,
use mir::*;
use ty::subst::{Subst, Substs};
use ty::{self, AdtDef, Ty, TyCtxt};
+use ty::layout::VariantIdx;
use hir;
use ty::util::IntTypeExt;
/// Downcast to a particular variant of an enum.
Downcast { adt_def: &'tcx AdtDef,
substs: &'tcx Substs<'tcx>,
- variant_index: usize },
+ variant_index: VariantIdx },
}
+static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
+ mem::size_of::<PlaceTy<'_>>() <= 24
+);
+
impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
PlaceTy::Ty { ty }
pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
{
// Pass `0` here so it can be used as a "default" variant_index in first arm below
- let answer = match (self, 0) {
+ let answer = match (self, VariantIdx::new(0)) {
(PlaceTy::Ty {
ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
(PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
match self.to_ty(tcx).sty {
ty::Adt(adt_def, substs) => {
assert!(adt_def.is_enum());
- assert!(index < adt_def.variants.len());
+ assert!(index.as_usize() < adt_def.variants.len());
assert_eq!(adt_def, adt_def1);
PlaceTy::Downcast { adt_def,
substs,
) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
let tcx = infcx.tcx;
- let mut select = SelectionContext::new(&infcx);
+ let mut select = SelectionContext::with_negative(&infcx, true);
let mut already_visited = FxHashSet::default();
let mut predicates = VecDeque::new();
match &result {
&Ok(Some(ref vtable)) => {
+ // If we see an explicit negative impl (e.g. 'impl !Send for MyStruct'),
+ // we immediately bail out, since it's impossible for us to continue.
+ match vtable {
+ Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
+ // Blame tidy for the weird bracket placement
+ if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative
+ {
+ debug!("evaluate_nested_obligations: Found explicit negative impl\
+ {:?}, bailing out", impl_def_id);
+ return None;
+ }
+ },
+ _ => {}
+ }
+
let obligations = vtable.clone().nested_obligations().into_iter();
if !self.evaluate_nested_obligations(
// cause I have no idea for a good error message.
if let ty::Predicate::Projection(ref data) = predicate {
let mut selcx = SelectionContext::new(self);
- let (data, _) = self.replace_late_bound_regions_with_fresh_var(
+ let (data, _) = self.replace_bound_vars_with_fresh_vars(
obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType,
- data);
+ data
+ );
let mut obligations = vec![];
let normalized_ty = super::normalize_projection_type(
&mut selcx,
use traits::project::Normalized;
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::{self, Lift, TyCtxt};
+use syntax::symbol::InternedString;
use std::fmt;
use std::rc::Rc;
+use std::collections::{BTreeSet, BTreeMap};
// structural impls for the structs in traits
}
}
+impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::WhereClause::*;
+
+ // Bypass ppaux because it does not print out anonymous regions.
+ fn write_region_name<'tcx>(
+ r: ty::Region<'tcx>,
+ fmt: &mut fmt::Formatter<'_>
+ ) -> fmt::Result {
+ match r {
+ ty::ReLateBound(index, br) => match br {
+ ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
+ ty::BoundRegion::BrAnon(var) => {
+ if *index == ty::INNERMOST {
+ write!(fmt, "'^{}", var)
+ } else {
+ write!(fmt, "'^{}_{}", index.index(), var)
+ }
+ }
+ _ => write!(fmt, "'_"),
+ }
+
+ _ => write!(fmt, "{}", r),
+ }
+ }
+
+ match self {
+ Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+ ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+ RegionOutlives(predicate) => {
+ write!(fmt, "RegionOutlives({}: ", predicate.0)?;
+ write_region_name(predicate.1, fmt)?;
+ write!(fmt, ")")
+ }
+ TypeOutlives(predicate) => {
+ write!(fmt, "TypeOutlives({}: ", predicate.0)?;
+ write_region_name(predicate.1, fmt)?;
+ write!(fmt, ")")
+ }
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::WellFormed::*;
+
+ match self {
+ Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
+ Ty(ty) => write!(fmt, "WellFormed({})", ty),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::FromEnv::*;
+
+ match self {
+ Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
+ Ty(ty) => write!(fmt, "FromEnv({})", ty),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::DomainGoal::*;
+
+ match self {
+ Holds(wc) => write!(fmt, "{}", wc),
+ WellFormed(wf) => write!(fmt, "{}", wf),
+ FromEnv(from_env) => write!(fmt, "{}", from_env),
+ Normalize(projection) => write!(
+ fmt,
+ "Normalize({} -> {})",
+ projection.projection_ty,
+ projection.ty
+ ),
+ }
+ }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::QuantifierKind::*;
+
+ match self {
+ Universal => write!(fmt, "forall"),
+ Existential => write!(fmt, "exists"),
+ }
+ }
+}
+
+/// Collect names for regions / types bound by a quantified goal / clause.
+/// This collector does not try to do anything clever like in ppaux, it's just used
+/// for debug output in tests anyway.
+struct BoundNamesCollector {
+ // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
+ regions: BTreeSet<InternedString>,
+
+ // Sort by `BoundVar` index, so usually this should be equivalent to the order given
+ // by the list of type parameters.
+ types: BTreeMap<u32, InternedString>,
+
+ binder_index: ty::DebruijnIndex,
+}
+
+impl BoundNamesCollector {
+ fn new() -> Self {
+ BoundNamesCollector {
+ regions: BTreeSet::new(),
+ types: BTreeMap::new(),
+ binder_index: ty::INNERMOST,
+ }
+ }
+
+ fn is_empty(&self) -> bool {
+ self.regions.is_empty() && self.types.is_empty()
+ }
+
+ fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut start = true;
+ for r in &self.regions {
+ if !start {
+ write!(fmt, ", ")?;
+ }
+ start = false;
+ write!(fmt, "{}", r)?;
+ }
+ for (_, t) in &self.types {
+ if !start {
+ write!(fmt, ", ")?;
+ }
+ start = false;
+ write!(fmt, "{}", t)?;
+ }
+ Ok(())
+ }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
+ fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+ self.binder_index.shift_in(1);
+ let result = t.super_visit_with(self);
+ self.binder_index.shift_out(1);
+ result
+ }
+
+ fn visit_ty(&mut self, t: ty::Ty<'tcx>) -> bool {
+ use syntax::symbol::Symbol;
+
+ match t.sty {
+ ty::Bound(bound_ty) if bound_ty.index == self.binder_index => {
+ self.types.insert(
+ bound_ty.var.as_u32(),
+ match bound_ty.kind {
+ ty::BoundTyKind::Param(name) => name,
+ ty::BoundTyKind::Anon => Symbol::intern(
+ &format!("^{}", bound_ty.var.as_u32())
+ ).as_interned_str(),
+ }
+ );
+ }
+
+ _ => (),
+ };
+
+ t.super_visit_with(self)
+ }
+
+ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+ use syntax::symbol::Symbol;
+
+ match r {
+ ty::ReLateBound(index, br) if *index == self.binder_index => {
+ match br {
+ ty::BoundRegion::BrNamed(_, name) => {
+ self.regions.insert(*name);
+ }
+
+ ty::BoundRegion::BrAnon(var) => {
+ self.regions.insert(Symbol::intern(
+ &format!("'^{}", var)
+ ).as_interned_str());
+ }
+
+ _ => (),
+ }
+ }
+
+ _ => (),
+ };
+
+ r.super_visit_with(self)
+ }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::GoalKind::*;
+
+ match self {
+ Implies(hypotheses, goal) => {
+ write!(fmt, "if (")?;
+ for (index, hyp) in hypotheses.iter().enumerate() {
+ if index > 0 {
+ write!(fmt, ", ")?;
+ }
+ write!(fmt, "{}", hyp)?;
+ }
+ write!(fmt, ") {{ {} }}", goal)
+ }
+ And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+ Not(goal) => write!(fmt, "not {{ {} }}", goal),
+ DomainGoal(goal) => write!(fmt, "{}", goal),
+ Quantified(qkind, goal) => {
+ let mut collector = BoundNamesCollector::new();
+ goal.skip_binder().visit_with(&mut collector);
+
+ if !collector.is_empty() {
+ write!(fmt, "{}<", qkind)?;
+ collector.write_names(fmt)?;
+ write!(fmt, "> {{ ")?;
+ }
+
+ write!(fmt, "{}", goal.skip_binder())?;
+
+ if !collector.is_empty() {
+ write!(fmt, " }}")?;
+ }
+
+ Ok(())
+ }
+ CannotProve => write!(fmt, "CannotProve"),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let traits::ProgramClause { goal, hypotheses, .. } = self;
+ write!(fmt, "{}", goal)?;
+ if !hypotheses.is_empty() {
+ write!(fmt, " :- ")?;
+ for (index, condition) in hypotheses.iter().enumerate() {
+ if index > 0 {
+ write!(fmt, ", ")?;
+ }
+ write!(fmt, "{}", condition)?;
+ }
+ }
+ write!(fmt, ".")
+ }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ use traits::Clause::*;
+
+ match self {
+ Implies(clause) => write!(fmt, "{}", clause),
+ ForAll(clause) => {
+ let mut collector = BoundNamesCollector::new();
+ clause.skip_binder().visit_with(&mut collector);
+
+ if !collector.is_empty() {
+ write!(fmt, "forall<")?;
+ collector.write_names(fmt)?;
+ write!(fmt, "> {{ ")?;
+ }
+
+ write!(fmt, "{}", clause.skip_binder())?;
+
+ if !collector.is_empty() {
+ write!(fmt, " }}")?;
+ }
+
+ Ok(())
+ }
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// Lift implementations
}
}
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
+ type Lifted = traits::WhereClause<'tcx>;
+ (traits::WhereClause::Implemented)(trait_ref),
+ (traits::WhereClause::ProjectionEq)(projection),
+ (traits::WhereClause::TypeOutlives)(ty_outlives),
+ (traits::WhereClause::RegionOutlives)(region_outlives),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
+ type Lifted = traits::WellFormed<'tcx>;
+ (traits::WellFormed::Trait)(trait_ref),
+ (traits::WellFormed::Ty)(ty),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
+ type Lifted = traits::FromEnv<'tcx>;
+ (traits::FromEnv::Trait)(trait_ref),
+ (traits::FromEnv::Ty)(ty),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
+ type Lifted = traits::DomainGoal<'tcx>;
+ (traits::DomainGoal::Holds)(wc),
+ (traits::DomainGoal::WellFormed)(wf),
+ (traits::DomainGoal::FromEnv)(from_env),
+ (traits::DomainGoal::Normalize)(projection),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
+ type Lifted = traits::GoalKind<'tcx>;
+ (traits::GoalKind::Implies)(hypotheses, goal),
+ (traits::GoalKind::And)(goal1, goal2),
+ (traits::GoalKind::Not)(goal),
+ (traits::GoalKind::DomainGoal)(domain_goal),
+ (traits::GoalKind::Quantified)(kind, goal),
+ (traits::GoalKind::CannotProve),
+ }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
+ type Lifted = traits::Environment<'tcx>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&self.clauses).map(|clauses| {
+ traits::Environment {
+ clauses,
+ }
+ })
+ }
+}
+
+impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
+ type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&self.environment).and_then(|environment| {
+ tcx.lift(&self.goal).map(|goal| {
+ traits::InEnvironment {
+ environment,
+ goal,
+ }
+ })
+ })
+ }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
+where
+ C: chalk_engine::context::Context + Clone,
+ C: traits::ExClauseLift<'tcx>,
+{
+ type Lifted = C::LiftedExClause;
+
+ fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ <C as traits::ExClauseLift>::lift_ex_clause_to_tcx(self, tcx)
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// TypeFoldable implementations.
} where T: TypeFoldable<'tcx>
}
-impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::WhereClause::*;
-
- match self {
- Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
- ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
- RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
- TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
- }
- }
-}
-
-impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::WellFormed::*;
-
- match self {
- Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
- Ty(ty) => write!(fmt, "WellFormed({})", ty),
- }
- }
-}
-
-impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::FromEnv::*;
-
- match self {
- Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
- Ty(ty) => write!(fmt, "FromEnv({})", ty),
- }
- }
-}
-
-impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::DomainGoal::*;
-
- match self {
- Holds(wc) => write!(fmt, "{}", wc),
- WellFormed(wf) => write!(fmt, "{}", wf),
- FromEnv(from_env) => write!(fmt, "{}", from_env),
- Normalize(projection) => write!(fmt, "Normalize({})", projection),
- }
- }
-}
-
-impl fmt::Display for traits::QuantifierKind {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::QuantifierKind::*;
-
- match self {
- Universal => write!(fmt, "forall"),
- Existential => write!(fmt, "exists"),
- }
- }
-}
-
-impl<'tcx> fmt::Display for traits::Goal<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::GoalKind::*;
-
- match self {
- Implies(hypotheses, goal) => {
- write!(fmt, "if (")?;
- for (index, hyp) in hypotheses.iter().enumerate() {
- if index > 0 {
- write!(fmt, ", ")?;
- }
- write!(fmt, "{}", hyp)?;
- }
- write!(fmt, ") {{ {} }}", goal)
- }
- And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
- Not(goal) => write!(fmt, "not {{ {} }}", goal),
- DomainGoal(goal) => write!(fmt, "{}", goal),
- Quantified(qkind, goal) => {
- // FIXME: appropriate binder names
- write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
- }
- CannotProve => write!(fmt, "CannotProve"),
- }
- }
-}
-
-impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- let traits::ProgramClause { goal, hypotheses, .. } = self;
- write!(fmt, "{}", goal)?;
- if !hypotheses.is_empty() {
- write!(fmt, " :- ")?;
- for (index, condition) in hypotheses.iter().enumerate() {
- if index > 0 {
- write!(fmt, ", ")?;
- }
- write!(fmt, "{}", condition)?;
- }
- }
- write!(fmt, ".")
- }
-}
-
-impl<'tcx> fmt::Display for traits::Clause<'tcx> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- use traits::Clause::*;
-
- match self {
- Implies(clause) => write!(fmt, "{}", clause),
- ForAll(clause) => {
- // FIXME: appropriate binder names
- write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
- }
- }
- }
-}
-
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for traits::WhereClause<'tcx> {
(traits::WhereClause::Implemented)(trait_ref),
}
}
-EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
- type Lifted = traits::WhereClause<'tcx>;
- (traits::WhereClause::Implemented)(trait_ref),
- (traits::WhereClause::ProjectionEq)(projection),
- (traits::WhereClause::TypeOutlives)(ty_outlives),
- (traits::WhereClause::RegionOutlives)(region_outlives),
- }
-}
-
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for traits::WellFormed<'tcx> {
(traits::WellFormed::Trait)(trait_ref),
}
}
-EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
- type Lifted = traits::WellFormed<'tcx>;
- (traits::WellFormed::Trait)(trait_ref),
- (traits::WellFormed::Ty)(ty),
- }
-}
-
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for traits::FromEnv<'tcx> {
(traits::FromEnv::Trait)(trait_ref),
}
}
-EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
- type Lifted = traits::FromEnv<'tcx>;
- (traits::FromEnv::Trait)(trait_ref),
- (traits::FromEnv::Ty)(ty),
- }
-}
-
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
(traits::DomainGoal::Holds)(wc),
}
}
-EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
- type Lifted = traits::DomainGoal<'tcx>;
- (traits::DomainGoal::Holds)(wc),
- (traits::DomainGoal::WellFormed)(wf),
- (traits::DomainGoal::FromEnv)(from_env),
- (traits::DomainGoal::Normalize)(projection),
- }
-}
-
CloneTypeFoldableAndLiftImpls! {
traits::QuantifierKind,
}
}
}
-EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
- type Lifted = traits::GoalKind<'tcx>;
- (traits::GoalKind::Implies)(hypotheses, goal),
- (traits::GoalKind::And)(goal1, goal2),
- (traits::GoalKind::Not)(goal),
- (traits::GoalKind::DomainGoal)(domain_goal),
- (traits::GoalKind::Quantified)(kind, goal),
- (traits::GoalKind::CannotProve),
- }
-}
-
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter()
} where G: TypeFoldable<'tcx>
}
-impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
- type Lifted = traits::Environment<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- tcx.lift(&self.clauses).map(|clauses| {
- traits::Environment {
- clauses,
- }
- })
- }
-}
-
-impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
- type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- tcx.lift(&self.environment).and_then(|environment| {
- tcx.lift(&self.goal).map(|goal| {
- traits::InEnvironment {
- environment,
- goal,
- }
- })
- })
- }
-}
-
impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter()
}
}
-impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
-where
- C: chalk_engine::context::Context + Clone,
- C: traits::ExClauseLift<'tcx>,
-{
- type Lifted = C::LiftedExClause;
-
- fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- <C as traits::ExClauseLift>::lift_ex_clause_to_tcx(self, tcx)
- }
-}
-
EnumTypeFoldableImpl! {
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
(chalk_engine::DelayedLiteral::CannotProve)(a),
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TyKind::*;
use ty::GenericParamDefKind;
-use ty::layout::{LayoutDetails, TargetDataLayout};
+use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
use ty::query;
use ty::steal::Steal;
use ty::BindingMode;
pub fn alloc_adt_def(self,
did: DefId,
kind: AdtKind,
- variants: Vec<ty::VariantDef>,
+ variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions)
-> &'gcx ty::AdtDef {
let def = ty::AdtDef::new(self, did, kind, variants, repr);
pub fn replace_late_bound_regions<T, F>(
self,
value: &Binder<T>,
- mut fld_r: F
+ fld_r: F
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
T: TypeFoldable<'tcx>
{
- let mut map = BTreeMap::new();
- let mut real_fldr = |br| {
- *map.entry(br).or_insert_with(|| fld_r(br))
- };
-
// identity for bound types
- let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
-
- let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
- let result = value.skip_binder().fold_with(&mut replacer);
- (result, map)
+ let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+ self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
}
/// Replace all escaping bound vars. The `fld_r` closure replaces escaping
value: &T,
mut fld_r: F,
mut fld_t: G
- ) -> T
+ ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
T: TypeFoldable<'tcx>
{
+ let mut map = BTreeMap::new();
+
if !value.has_escaping_bound_vars() {
- value.clone()
+ (value.clone(), map)
} else {
- let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
+ let mut real_fld_r = |br| {
+ *map.entry(br).or_insert_with(|| fld_r(br))
+ };
+
+ let mut replacer = BoundVarReplacer::new(self, &mut real_fld_r, &mut fld_t);
let result = value.fold_with(&mut replacer);
- result
+ (result, map)
}
}
value: &Binder<T>,
fld_r: F,
fld_t: G
- ) -> T
+ ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
T: TypeFoldable<'tcx>
use std::ops::Bound;
use ich::StableHashingContext;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
let size = (b_offset + b.value.size(dl)).abi_align(align);
LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Arbitrary {
offsets: vec![Size::ZERO, b_offset],
memory_index: vec![0, 1]
}
Ok(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Arbitrary {
offsets,
memory_index
// The never type.
ty::Never => {
tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Union(0),
abi: Abi::Uninhabited,
align: dl.i8_align,
.ok_or(LayoutError::SizeOverflow(ty))?;
tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array {
stride: element.size,
count
ty::Slice(element) => {
let element = self.layout_of(element)?;
tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array {
stride: element.size,
count: 0
}
ty::Str => {
tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array {
stride: Size::from_bytes(1),
count: 0
let size = size.abi_align(align);
tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array {
stride: element.size,
count
v.fields.iter().map(|field| {
self.layout_of(field.ty(tcx, substs))
}).collect::<Result<Vec<_>, _>>()
- }).collect::<Result<Vec<_>, _>>()?;
+ }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
if def.is_union() {
let packed = def.repr.packed();
}
let mut size = Size::ZERO;
- for field in &variants[0] {
+ let index = VariantIdx::new(0);
+ for field in &variants[index] {
assert!(!field.is_unsized());
if packed {
}
return Ok(tcx.intern_layout(LayoutDetails {
- variants: Variants::Single { index: 0 },
- fields: FieldPlacement::Union(variants[0].len()),
+ variants: Variants::Single { index },
+ fields: FieldPlacement::Union(variants[index].len()),
abi: Abi::Aggregate { sized: true },
align,
size: size.abi_align(align)
uninhabited && is_zst
};
let (present_first, present_second) = {
- let mut present_variants = (0..variants.len()).filter(|&v| {
- !absent(&variants[v])
+ let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| {
+ if absent(v) {
+ None
+ } else {
+ Some(i)
+ }
});
(present_variants.next(), present_variants.next())
};
// The current code for niche-filling relies on variant indices
// instead of actual discriminants, so dataful enums with
// explicit discriminants (RFC #2363) would misbehave.
- let no_explicit_discriminants = def.variants.iter().enumerate()
- .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
+ let no_explicit_discriminants = def.variants.iter_enumerated()
+ .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
// Niche-filling enum optimization.
if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
let mut dataful_variant = None;
- let mut niche_variants = usize::max_value()..=0;
+ let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
// Find one non-ZST variant.
- 'variants: for (v, fields) in variants.iter().enumerate() {
+ 'variants: for (v, fields) in variants.iter_enumerated() {
if absent(fields) {
continue 'variants;
}
}
if let Some(i) = dataful_variant {
- let count = (niche_variants.end() - niche_variants.start() + 1) as u128;
+ let count = (
+ niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1
+ ) as u128;
for (field_index, &field) in variants[i].iter().enumerate() {
let niche = match self.find_niche(field)? {
Some(niche) => niche,
};
let mut align = dl.aggregate_align;
- let st = variants.iter().enumerate().map(|(j, v)| {
+ let st = variants.iter_enumerated().map(|(j, v)| {
let mut st = univariant_uninterned(v,
&def.repr, StructKind::AlwaysSized)?;
st.variants = Variants::Single { index: j };
align = align.max(st.align);
Ok(st)
- }).collect::<Result<Vec<_>, _>>()?;
+ }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
let offset = st[i].fields.offset(field_index) + niche.offset;
let size = st[i].size;
let (mut min, mut max) = (i128::max_value(), i128::min_value());
let discr_type = def.repr.discr_type();
let bits = Integer::from_attr(self, discr_type).size().bits();
- for (i, discr) in def.discriminants(tcx).enumerate() {
+ for (i, discr) in def.discriminants(tcx) {
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
continue;
}
}
// Create the set of structs that represent each variant.
- let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| {
+ let mut layout_variants = variants.iter_enumerated().map(|(i, field_layouts)| {
let mut st = univariant_uninterned(&field_layouts,
&def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
st.variants = Variants::Single { index: i };
size = cmp::max(size, st.size);
align = align.max(st.align);
Ok(st)
- }).collect::<Result<Vec<_>, _>>()?;
+ }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
// Align the maximum variant size to the largest alignment.
size = size.abi_align(align);
debug!("print-type-size `{:#?}` adt general variants def {}",
layout.ty, adt_def.variants.len());
let variant_infos: Vec<_> =
- adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
+ adt_def.variants.iter_enumerated().map(|(i, variant_def)| {
let fields: Vec<_> =
variant_def.fields.iter().map(|f| f.ident.name).collect();
build_variant_info(Some(variant_def.name),
}
// Get a zero-sized variant or a pointer newtype.
- let zero_or_ptr_variant = |i: usize| {
+ let zero_or_ptr_variant = |i| {
+ let i = VariantIdx::new(i);
let fields = def.variants[i].fields.iter().map(|field| {
SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
});
where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
C::TyLayout: MaybeResult<TyLayout<'tcx>>
{
- fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: usize) -> TyLayout<'tcx> {
+ fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
let details = match this.variants {
Variants::Single { index } if index == variant_index => this.details,
}
}
+impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx {
+ fn hash_stable<W: StableHasherResult>(
+ &self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>,
+ ) {
+ self.as_u32().hash_stable(hcx, hasher)
+ }
+}
+
impl<'a> HashStable<StableHashingContext<'a>> for Abi {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
use session::CrateDisambiguator;
use traits::{self, Reveal};
use ty;
+use ty::layout::VariantIdx;
use ty::subst::{Subst, Substs};
use ty::util::{IntTypeExt, Discr};
use ty::walk::TypeWalker;
use syntax_pos::{DUMMY_SP, Span};
use smallvec;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
/// For efficiency reasons, the distance from the
/// last `Explicit` discriminant is being stored,
/// or `0` for the first variant, if it has none.
- Relative(usize),
+ Relative(u32),
}
#[derive(Debug)]
/// table.
pub struct AdtDef {
pub did: DefId,
- pub variants: Vec<VariantDef>,
+ pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
flags: AdtFlags,
pub repr: ReprOptions,
}
fn new(tcx: TyCtxt<'_, '_, '_>,
did: DefId,
kind: AdtKind,
- variants: Vec<VariantDef>,
+ variants: IndexVec<VariantIdx, VariantDef>,
repr: ReprOptions) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
/// Asserts this is a struct or union and returns its unique variant.
pub fn non_enum_variant(&self) -> &VariantDef {
assert!(self.is_struct() || self.is_union());
- &self.variants[0]
+ &self.variants[VariantIdx::new(0)]
}
#[inline]
.expect("variant_with_id: unknown variant")
}
- pub fn variant_index_with_id(&self, vid: DefId) -> usize {
+ pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
self.variants
- .iter()
- .position(|v| v.did == vid)
+ .iter_enumerated()
+ .find(|(_, v)| v.did == vid)
.expect("variant_index_with_id: unknown variant")
+ .0
}
pub fn variant_of_def(&self, def: Def) -> &VariantDef {
pub fn discriminants(
&'a self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
+ ) -> impl Iterator<Item=(VariantIdx, Discr<'tcx>)> + Captures<'gcx> + 'a {
let repr_type = self.repr.discr_type();
let initial = repr_type.initial_discriminant(tcx.global_tcx());
let mut prev_discr = None::<Discr<'tcx>>;
- self.variants.iter().map(move |v| {
+ self.variants.iter_enumerated().map(move |(i, v)| {
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
if let VariantDiscr::Explicit(expr_did) = v.discr {
if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
}
prev_discr = Some(discr);
- discr
+ (i, discr)
})
}
/// assuming there are no constant-evaluation errors there.
pub fn discriminant_for_variant(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- variant_index: usize)
+ variant_index: VariantIdx)
-> Discr<'tcx> {
let (val, offset) = self.discriminant_def_for_variant(variant_index);
let explicit_value = val
/// inferred discriminant directly
pub fn discriminant_def_for_variant(
&self,
- variant_index: usize,
- ) -> (Option<DefId>, usize) {
- let mut explicit_index = variant_index;
+ variant_index: VariantIdx,
+ ) -> (Option<DefId>, u32) {
+ let mut explicit_index = variant_index.as_u32();
let expr_did;
loop {
- match self.variants[explicit_index].discr {
+ match self.variants[VariantIdx::from_u32(explicit_index)].discr {
ty::VariantDiscr::Relative(0) => {
expr_did = None;
break;
}
}
}
- (expr_did, variant_index - explicit_index)
+ (expr_did, variant_index.as_u32() - explicit_index)
}
pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
) -> Clauses<'tcx>,
// Get the chalk-style environment of the given item.
- [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
+ [] fn environment: Environment(DefId) -> ty::Binder<traits::Environment<'tcx>>,
},
Linking {
(),
bool,
usize,
+ ::ty::layout::VariantIdx,
u64,
::middle::region::Scope,
::syntax::ast::FloatTy,
})
}
+ /// Creates a `Substs` that maps each generic parameter to a higher-ranked
+ /// var bound at index `0`. For types, we use a `BoundVar` index equal to
+ /// the type parameter index. For regions, we use the `BoundRegion::BrNamed`
+ /// variant (which has a def-id).
+ pub fn bound_vars_for_item(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ def_id: DefId
+ ) -> &'tcx Substs<'tcx> {
+ Substs::for_item(tcx, def_id, |param, _| {
+ match param.kind {
+ ty::GenericParamDefKind::Type { .. } => {
+ tcx.mk_ty(ty::Bound(ty::BoundTy {
+ index: ty::INNERMOST,
+ var: ty::BoundVar::from(param.index),
+ kind: ty::BoundTyKind::Param(param.name),
+ })).into()
+ }
+
+ ty::GenericParamDefKind::Lifetime => {
+ tcx.mk_region(ty::RegionKind::ReLateBound(
+ ty::INNERMOST,
+ ty::BoundRegion::BrNamed(param.def_id, param.name)
+ )).into()
+ }
+ }
+ })
+ }
+
/// Creates a `Substs` for generic parameter definitions,
/// by calling closures to obtain each kind.
/// The closures get to observe the `Substs` as they're
match bound_ty.kind {
ty::BoundTyKind::Anon => {
if bound_ty.index == ty::INNERMOST {
- write!(f, "?{}", bound_ty.var.index())
+ write!(f, "^{}", bound_ty.var.index())
} else {
- write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index())
+ write!(f, "^{}_{}", bound_ty.index.index(), bound_ty.var.index())
}
}
use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
use rustc::middle::cstore::{EncodedMetadata};
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx};
use rustc::ty::query::Providers;
use rustc::middle::cstore::{self, LinkagePreference};
use rustc::middle::exported_symbols;
use CrateInfo;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
use std::any::Any;
use std::cmp;
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b);
- for i in 0..def_a.variants[0].fields.len() {
+ for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
let src_f = src.project_field(bx, i);
let dst_f = dst.project_field(bx, i);
use rustc::mir::mono::Stats;
use rustc::session::config::{self, DebugInfo};
use rustc::session::Session;
-use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
+use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::FxHashMap;
use rustc_target::spec::{HasTargetSpec, Target};
/// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
pub used_statics: RefCell<Vec<&'a Value>>,
- pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), &'a Type>>,
+ pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'a Type>>,
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>,
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
pub isize_ty: &'a Type,
// This doesn't matter in this case.
NoDiscriminant
};
- (0..variants.len()).map(|i| {
+ variants.iter_enumerated().map(|(i, _)| {
let variant = self.layout.for_variant(cx, i);
let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx,
}
]
} else {
- (0..variants.len()).map(|i| {
+ variants.iter_enumerated().map(|(i, _)| {
let variant = self.layout.for_variant(cx, i);
let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx,
let niche_value = if i == dataful_variant {
None
} else {
- let value = (i as u128)
- .wrapping_sub(*niche_variants.start() as u128)
+ let value = (i.as_u32() as u128)
+ .wrapping_sub(niche_variants.start().as_u32() as u128)
.wrapping_add(niche_start);
let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
Some(value as u64)
let def = enum_type.ty_adt_def().unwrap();
let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
.zip(&def.variants)
- .map(|(discr, v)| {
+ .map(|((_, discr), v)| {
let name = SmallCStr::new(&v.name.as_str());
unsafe {
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
use llvm::{self, LLVMConstInBoundsGEP};
use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size, VariantIdx};
use rustc::mir;
use rustc::mir::tcx::PlaceTy;
use base;
match self.layout.variants {
layout::Variants::Single { index } => {
let discr_val = self.layout.ty.ty_adt_def().map_or(
- index as u128,
+ index.as_u32() as u128,
|def| def.discriminant_for_variant(bx.cx.tcx, index).val);
return C_uint_big(cast_to, discr_val);
}
C_uint_big(niche_llty, niche_start)
};
bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
- C_uint(cast_to, *niche_variants.start() as u64),
- C_uint(cast_to, dataful_variant as u64))
+ C_uint(cast_to, niche_variants.start().as_u32() as u64),
+ C_uint(cast_to, dataful_variant.as_u32() as u64))
} else {
// Rebase from niche values to discriminant values.
- let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
+ let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
- let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64);
+ let lldiscr_max = C_uint(niche_llty, niche_variants.end().as_u32() as u64);
bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
bx.intcast(lldiscr, cast_to, false),
- C_uint(cast_to, dataful_variant as u64))
+ C_uint(cast_to, dataful_variant.as_u32() as u64))
}
}
}
/// Set the discriminant for a new value of the given case of the given
/// representation.
- pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
+ pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx) {
if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
return;
}
let niche = self.project_field(bx, 0);
let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
- let niche_value = ((variant_index - *niche_variants.start()) as u128)
+ let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+ let niche_value = (niche_value as u128)
.wrapping_add(niche_start);
// FIXME(eddyb) Check the actual primitive type here.
let niche_llval = if niche_value == 0 {
}
}
- pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
+ pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx)
-> PlaceRef<'ll, 'tcx> {
let mut downcast = *self;
downcast.layout = self.layout.for_variant(bx.cx, variant_index);
rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
+rustc_data_structures = { path = "../librustc_data_structures" }
extern crate rustc_mir;
extern crate rustc_target;
extern crate syntax_pos;
+extern crate rustc_data_structures;
use rustc::lint;
use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray};
use rustc::hir::Node;
use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, IntegerExt, LayoutOf};
+use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
+use rustc_data_structures::indexed_vec::Idx;
use util::nodemap::FxHashSet;
use lint::{LateContext, LintContext, LintArray};
use lint::{LintPass, LateLintPass};
if def.variants.len() == 2 {
let data_idx;
- if def.variants[0].fields.is_empty() {
- data_idx = 1;
- } else if def.variants[1].fields.is_empty() {
- data_idx = 0;
+ let zero = VariantIdx::new(0);
+ let one = VariantIdx::new(1);
+
+ if def.variants[zero].fields.is_empty() {
+ data_idx = one;
+ } else if def.variants[one].fields.is_empty() {
+ data_idx = zero;
} else {
return false;
}
})
.collect()
} else {
- vec![self.get_variant(tcx, &item, item_id, kind)]
+ std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect()
};
tcx.alloc_adt_def(did, kind, variants, repr)
use rustc::traits::specialization_graph;
use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
use rustc::ty::codec::{self as ty_codec, TyEncoder};
+use rustc::ty::layout::VariantIdx;
use rustc::session::config::{self, CrateType};
use rustc::util::nodemap::FxHashMap;
/// the right to access any information in the adt-def (including,
/// e.g., the length of the various vectors).
fn encode_enum_variant_info(&mut self,
- (enum_did, Untracked(index)): (DefId, Untracked<usize>))
+ (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>))
-> Entry<'tcx> {
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
/// vectors).
fn encode_field(&mut self,
(adt_def_id, Untracked((variant_index, field_index))): (DefId,
- Untracked<(usize,
+ Untracked<(VariantIdx,
usize)>))
-> Entry<'tcx> {
let tcx = self.tcx;
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
fn encode_fields(&mut self, adt_def_id: DefId) {
let def = self.tcx.adt_def(adt_def_id);
- for (variant_index, variant) in def.variants.iter().enumerate() {
+ for (variant_index, variant) in def.variants.iter_enumerated() {
for (field_index, field) in variant.fields.iter().enumerate() {
self.record(field.did,
IsolatedEncoder::encode_field,
self.encode_fields(def_id);
let def = self.tcx.adt_def(def_id);
- for (i, variant) in def.variants.iter().enumerate() {
+ for (i, variant) in def.variants.iter_enumerated() {
self.record(variant.did,
IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i)));
// "inside" the closure.
Some(
self.infcx
- .replace_late_bound_regions_with_fresh_var(
+ .replace_bound_vars_with_fresh_vars(
mir.span,
LateBoundRegionConversionTime::FnCall,
&poly_sig,
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc::ty::layout::VariantIdx;
use std::rc::Rc;
use std::{fmt, iter};
use syntax_pos::{Span, DUMMY_SP};
},
ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
- if index >= adt_def.variants.len() {
+ if index.as_usize() >= adt_def.variants.len() {
PlaceTy::Ty {
ty: span_mirbug_and_err!(
self,
variant_index,
} => (&adt_def.variants[variant_index], substs),
PlaceTy::Ty { ty } => match ty.sty {
- ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
+ ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
+ (&adt_def.variants[VariantIdx::new(0)], substs),
ty::Closure(def_id, substs) => {
return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
Some(ty) => Ok(ty),
);
}
};
- if variant_index >= adt.variants.len() {
+ if variant_index.as_usize() >= adt.variants.len() {
span_bug!(
stmt.source_info.span,
"bad set discriminant ({:?} = {:?}): value of of range",
return;
}
};
- let (sig, map) = self.infcx.replace_late_bound_regions_with_fresh_var(
+ let (sig, map) = self.infcx.replace_bound_vars_with_fresh_vars(
term.source_info.span,
LateBoundRegionConversionTime::FnCall,
&sig,
use rustc::hir;
use rustc::mir::*;
use rustc::ty::{self, Ty};
+use rustc::ty::layout::VariantIdx;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Name, NodeId};
// test the branches of enum
Switch {
adt_def: &'tcx ty::AdtDef,
- variants: BitSet<usize>,
+ variants: BitSet<VariantIdx>,
},
// test the branches of enum
}
PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
- let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
+ let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| {
i == variant_index || {
self.hir.tcx().features().never_type &&
self.hir.tcx().features().exhaustive_patterns &&
use rustc_data_structures::fx::FxHashMap;
use rustc::ty::{self, Ty};
use rustc::ty::util::IntTypeExt;
+use rustc::ty::layout::VariantIdx;
use rustc::mir::*;
use rustc::hir::{RangeEnd, Mutability};
use syntax_pos::Span;
pub fn add_variants_to_switch<'pat>(&mut self,
test_place: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
- variants: &mut BitSet<usize>)
+ variants: &mut BitSet<VariantIdx>)
-> bool
{
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
let mut targets = Vec::with_capacity(used_variants + 1);
let mut values = Vec::with_capacity(used_variants);
let tcx = self.hir.tcx();
- for (idx, discr) in adt_def.discriminants(tcx).enumerate() {
+ for (idx, discr) in adt_def.discriminants(tcx) {
target_blocks.push(if variants.contains(idx) {
values.push(discr.val);
targets.push(self.cfg.start_new_block());
variant_index,
subpatterns,
candidate);
- resulting_candidates[variant_index].push(new_candidate);
+ resulting_candidates[variant_index.as_usize()].push(new_candidate);
true
}
(&TestKind::Switch { .. }, _) => false,
fn candidate_after_variant_switch<'pat>(&mut self,
match_pair_index: usize,
adt_def: &'tcx ty::AdtDef,
- variant_index: usize,
+ variant_index: VariantIdx,
subpatterns: &'pat [FieldPattern<'tcx>],
candidate: &Candidate<'pat, 'tcx>)
-> Candidate<'pat, 'tcx> {
use hair::*;
use rustc::mir::*;
use std::u32;
+use std::convert::TryInto;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn field_match_pairs<'pat>(&mut self,
opt_slice: Option<&'pat Pattern<'tcx>>,
suffix: &'pat [Pattern<'tcx>]) {
let min_length = prefix.len() + suffix.len();
- assert!(min_length < u32::MAX as usize);
- let min_length = min_length as u32;
+ let min_length = min_length.try_into().unwrap();
match_pairs.extend(
prefix.iter()
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
use rustc::mir;
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
-use rustc::ty::layout::{self, LayoutOf, TyLayout};
+use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
use rustc::ty::subst::Subst;
use rustc::traits::Reveal;
use rustc_data_structures::indexed_vec::IndexVec;
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
- variant: Option<usize>,
+ variant: Option<VariantIdx>,
field: mir::Field,
value: &'tcx ty::Const<'tcx>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
val: &'tcx ty::Const<'tcx>,
-) -> EvalResult<'tcx, usize> {
+) -> EvalResult<'tcx, VariantIdx> {
trace!("const_variant_index: {:?}, {:?}", instance, val);
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let op = ecx.const_to_op(val)?;
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
}
Def::StructCtor(_, CtorKind::Fn) |
- Def::SelfCtor(..) => Some((adt_def, 0)),
+ Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
_ => None,
}
})
AdtKind::Struct | AdtKind::Union => {
ExprKind::Adt {
adt_def: adt,
- variant_index: 0,
+ variant_index: VariantIdx::new(0),
substs,
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields),
use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::layout::VariantIdx;
use syntax::ast::{self, LitKind};
use syntax::attr;
use syntax::symbol::Symbol;
bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
}
- pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: usize) -> Vec<Field> {
+ pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
(0..adt_def.variants[variant_index].fields.len())
.map(Field::new)
.collect()
use rustc::middle::region;
use rustc::ty::subst::Substs;
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
+use rustc::ty::layout::VariantIdx;
use rustc::hir;
use syntax::ast;
use syntax_pos::Span;
},
Adt {
adt_def: &'tcx AdtDef,
- variant_index: usize,
+ variant_index: VariantIdx,
substs: &'tcx Substs<'tcx>,
/// Optional user-given substs: for something like `let x =
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::layout::{Integer, IntegerExt};
+use rustc::ty::layout::{Integer, IntegerExt, VariantIdx};
use rustc::mir::Field;
use rustc::mir::interpret::ConstValue;
}
impl<'tcx> Constructor<'tcx> {
- fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize {
+ fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
match self {
&Variant(vid) => adt.variant_index_with_id(vid),
&Single => {
assert!(!adt.is_enum());
- 0
+ VariantIdx::new(0)
}
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
}
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
use rustc::ty::subst::{Substs, Kind};
+use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
pub(crate) fn variant(&self,
adt_def: &'tcx AdtDef,
- variant_index: usize,
+ variant_index: VariantIdx,
field: Field) -> Self {
self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
}
pub(crate) fn variant(&self,
adt_def: &'tcx AdtDef,
- variant_index: usize,
+ variant_index: VariantIdx,
field: Field) -> Self {
let mut new = self.clone();
new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
Variant {
adt_def: &'tcx AdtDef,
substs: &'tcx Substs<'tcx>,
- variant_index: usize,
+ variant_index: VariantIdx,
subpatterns: Vec<FieldPattern<'tcx>>,
},
}
_ => if let ty::Adt(adt, _) = self.ty.sty {
if !adt.is_enum() {
- Some(&adt.variants[0])
+ Some(&adt.variants[VariantIdx::new(0)])
} else {
None
}
} => PatternKind::Variant {
adt_def: adt_def.fold_with(folder),
substs: substs.fold_with(folder),
- variant_index: variant_index.fold_with(folder),
+ variant_index,
subpatterns: subpatterns.fold_with(folder)
},
PatternKind::Leaf {
use std::convert::TryInto;
use rustc::{mir, ty};
-use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
+use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx};
use rustc::mir::interpret::{
GlobalId, AllocId,
pub fn operand_downcast(
&self,
op: OpTy<'tcx, M::PointerTag>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
// Downcasts only change the layout
Ok(match op.try_as_mplace() {
pub fn read_discriminant(
&self,
rval: OpTy<'tcx, M::PointerTag>,
- ) -> EvalResult<'tcx, (u128, usize)> {
+ ) -> EvalResult<'tcx, (u128, VariantIdx)> {
trace!("read_discriminant_value {:#?}", rval.layout);
match rval.layout.variants {
layout::Variants::Single { index } => {
let discr_val = rval.layout.ty.ty_adt_def().map_or(
- index as u128,
+ index.as_u32() as u128,
|def| def.discriminant_for_variant(*self.tcx, index).val);
return Ok((discr_val, index));
}
.ty_adt_def()
.expect("tagged layout for non adt")
.discriminants(self.tcx.tcx)
- .position(|var| var.val == real_discr)
+ .find(|(_, var)| var.val == real_discr)
.ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
- (real_discr, index)
+ (real_discr, index.0)
},
layout::Variants::NicheFilling {
dataful_variant,
niche_start,
..
} => {
- let variants_start = *niche_variants.start() as u128;
- let variants_end = *niche_variants.end() as u128;
- let real_discr = match raw_discr {
+ let variants_start = niche_variants.start().as_u32() as u128;
+ let variants_end = niche_variants.end().as_u32() as u128;
+ match raw_discr {
Scalar::Ptr(_) => {
// The niche must be just 0 (which a pointer value never is)
assert!(niche_start == 0);
assert!(variants_start == variants_end);
- dataful_variant as u128
+ (dataful_variant.as_u32() as u128, dataful_variant)
},
Scalar::Bits { bits: raw_discr, size } => {
assert_eq!(size as u64, discr_val.layout.size.bytes());
let discr = raw_discr.wrapping_sub(niche_start)
.wrapping_add(variants_start);
if variants_start <= discr && discr <= variants_end {
- discr
+ let index = discr as usize;
+ assert_eq!(index as u128, discr);
+ assert!(index < rval.layout.ty
+ .ty_adt_def()
+ .expect("tagged layout for non adt")
+ .variants.len());
+ (discr, VariantIdx::from_usize(index))
} else {
- dataful_variant as u128
+ (dataful_variant.as_u32() as u128, dataful_variant)
}
},
- };
- let index = real_discr as usize;
- assert_eq!(index as u128, real_discr);
- assert!(index < rval.layout.ty
- .ty_adt_def()
- .expect("tagged layout for non adt")
- .variants.len());
- (real_discr, index)
+ }
}
})
}
use rustc::hir;
use rustc::mir;
use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
+use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
use rustc::mir::interpret::{
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
pub fn mplace_downcast(
&self,
base: MPlaceTy<'tcx, M::PointerTag>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
// Downcasts only change the layout
assert!(base.meta.is_none());
pub fn place_downcast(
&self,
base: PlaceTy<'tcx, M::PointerTag>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
// Downcast just changes the layout
Ok(match base.place {
pub fn write_discriminant_index(
&mut self,
- variant_index: usize,
+ variant_index: VariantIdx,
dest: PlaceTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx> {
match dest.layout.variants {
}
layout::Variants::Tagged { ref tag, .. } => {
let adt_def = dest.layout.ty.ty_adt_def().unwrap();
- assert!(variant_index < adt_def.variants.len());
+ assert!(variant_index.as_usize() < adt_def.variants.len());
let discr_val = adt_def
.discriminant_for_variant(*self.tcx, variant_index)
.val;
niche_start,
..
} => {
- assert!(variant_index < dest.layout.ty.ty_adt_def().unwrap().variants.len());
+ assert!(
+ variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(),
+ );
if variant_index != dataful_variant {
let niche_dest =
self.place_field(dest, 0)?;
- let niche_value = ((variant_index - niche_variants.start()) as u128)
+ let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+ let niche_value = (niche_value as u128)
.wrapping_add(niche_start);
self.write_scalar(
Scalar::from_uint(niche_value, niche_dest.layout.size),
use std::ops::RangeInclusive;
use syntax_pos::symbol::Symbol;
-use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
use rustc::ty;
use rustc_data_structures::fx::FxHashSet;
use rustc::mir::interpret::{
#[derive(Copy, Clone, Debug)]
pub enum PathElem {
Field(Symbol),
+ Variant(Symbol),
ClosureVar(Symbol),
ArrayElem(usize),
TupleElem(usize),
for elem in path.iter() {
match elem {
Field(name) => write!(out, ".{}", name),
+ Variant(name) => write!(out, ".<downcast-variant({})>", name),
ClosureVar(name) => write!(out, ".<closure-var({})>", name),
TupleElem(idx) => write!(out, ".{}", idx),
ArrayElem(idx) => write!(out, "[{}]", idx),
}
impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> {
- fn push_aggregate_field_path_elem(
+ fn aggregate_field_path_elem(
&mut self,
layout: TyLayout<'tcx>,
field: usize,
- ) {
- let elem = match layout.ty.sty {
+ ) -> PathElem {
+ match layout.ty.sty {
// generators and closures.
ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
if let Some(upvar) = self.ecx.tcx.optimized_mir(def_id).upvar_decls.get(field) {
layout::Variants::Single { index } =>
// Inside a variant
PathElem::Field(def.variants[index].fields[field].ident.name),
- _ =>
- // To a variant
- PathElem::Field(def.variants[field].name)
+ _ => bug!(),
}
}
// nothing else has an aggregate layout
_ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
- };
+ }
+ }
+
+ fn visit_elem(
+ &mut self,
+ new_op: OpTy<'tcx, M::PointerTag>,
+ elem: PathElem,
+ ) -> EvalResult<'tcx> {
+ // Remember the old state
+ let path_len = self.path.len();
+ // Perform operation
self.path.push(elem);
+ self.visit_value(new_op)?;
+ // Undo changes
+ self.path.truncate(path_len);
+ Ok(())
}
}
field: usize,
new_op: OpTy<'tcx, M::PointerTag>
) -> EvalResult<'tcx> {
- // Remember the old state
- let path_len = self.path.len();
- // Perform operation
- self.push_aggregate_field_path_elem(old_op.layout, field);
- self.visit_value(new_op)?;
- // Undo changes
- self.path.truncate(path_len);
- Ok(())
+ let elem = self.aggregate_field_path_elem(old_op.layout, field);
+ self.visit_elem(new_op, elem)
+ }
+
+ #[inline]
+ fn visit_variant(
+ &mut self,
+ old_op: OpTy<'tcx, M::PointerTag>,
+ variant_id: VariantIdx,
+ new_op: OpTy<'tcx, M::PointerTag>
+ ) -> EvalResult<'tcx> {
+ let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name;
+ self.visit_elem(new_op, PathElem::Variant(name))
}
#[inline]
//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.
-use rustc::ty::layout::{self, TyLayout};
+use rustc::ty::layout::{self, TyLayout, VariantIdx};
use rustc::ty;
use rustc::mir::interpret::{
EvalResult,
fn project_downcast(
self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, Self>;
/// Project to the n-th field.
fn project_downcast(
self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, Self> {
ecx.operand_downcast(self, variant)
}
fn project_downcast(
self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
- variant: usize,
+ variant: VariantIdx,
) -> EvalResult<'tcx, Self> {
ecx.mplace_downcast(self, variant)
}
self.visit_value(new_val)
}
+ #[inline(always)]
+ fn visit_variant(
+ &mut self,
+ _old_val: Self::V,
+ _variant: VariantIdx,
+ new_val: Self::V,
+ ) -> EvalResult<'tcx> {
+ self.visit_value(new_val)
+ }
+
/// Called whenever we reach a value with uninhabited layout.
/// Recursing to fields will *always* continue after this! This is not meant to control
/// whether and how we descend recursively/ into the scalar's fields if there are any,
let inner = v.project_downcast(self.ecx(), idx)?;
trace!("walk_value: variant layout: {:#?}", inner.layout());
// recurse with the inner type
- return self.visit_field(v, idx, inner);
+ return self.visit_variant(v, idx, inner);
}
layout::Variants::Single { .. } => {}
}
use rustc::infer;
use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
+use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::query::Providers;
fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
None
}
- fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
+ fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
Some(())
}
fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> {
let variant_no = if adt_def.is_enum() {
adt_def.variant_index_with_id(def_id)
} else {
- 0
+ VariantIdx::new(0)
};
// return = ADT(arg0, arg1, ...); return
use dataflow::MoveDataParamEnv;
use dataflow::{self, do_dataflow, DebugFormatted};
use rustc::ty::{self, TyCtxt};
+use rustc::ty::layout::VariantIdx;
use rustc::mir::*;
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::bit_set::BitSet;
})
}
- fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path> {
+ fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
match p {
&Projection {
use rustc::mir::*;
use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
+use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::Substs;
use util::dump_mir;
use util::liveness::{self, IdentityMap};
impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
// Make a GeneratorState rvalue
- fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> {
+ fn make_state(&self, idx: VariantIdx, val: Operand<'tcx>) -> Rvalue<'tcx> {
let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None);
Rvalue::Aggregate(box adt, vec![val])
}
});
let ret_val = match data.terminator().kind {
- TerminatorKind::Return => Some((1,
+ TerminatorKind::Return => Some((VariantIdx::new(1),
None,
Operand::Move(Place::Local(self.new_ret_local)),
None)),
- TerminatorKind::Yield { ref value, resume, drop } => Some((0,
+ TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
Some(resume),
value.clone(),
drop)),
use rustc::middle::lang_items;
use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::Substs;
use rustc::ty::util::IntTypeExt;
use rustc_data_structures::indexed_vec::Idx;
fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path>;
- fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path>;
+ fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path>;
fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path>;
}
let fields = self.move_paths_for_fields(
self.place,
self.path,
- &adt.variants[0],
+ &adt.variants[VariantIdx::new(0)],
substs
);
self.drop_ladder(fields, succ, unwind)
let mut have_otherwise = false;
- for (variant_index, discr) in adt.discriminants(self.tcx()).enumerate() {
+ for (variant_index, discr) in adt.discriminants(self.tcx()) {
let subpath = self.elaborator.downcast_subpath(
self.path, variant_index);
if let Some(variant_path) = subpath {
let tcx = self.tcx();
let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
- let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
+ let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty))
bitflags = "1.0"
log = "0.4"
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
+rustc_data_structures = { path = "../librustc_data_structures" }
serialize = { path = "../libserialize" }
use std::{cmp, fmt};
use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+
pub mod call;
/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
}
}
+newtype_index! {
+ pub struct VariantIdx { .. }
+}
+
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Variants {
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single {
- index: usize
+ index: VariantIdx,
},
/// General-case enums: for each case there is a struct, and they all have
/// at a non-0 offset, after where the tag would go.
Tagged {
tag: Scalar,
- variants: Vec<LayoutDetails>,
+ variants: IndexVec<VariantIdx, LayoutDetails>,
},
/// Multiple cases distinguished by a niche (values invalid for a type):
/// `None` has a null pointer for the second tuple field, and
/// `Some` is the identity function (with a non-null reference).
NicheFilling {
- dataful_variant: usize,
- niche_variants: RangeInclusive<usize>,
+ dataful_variant: VariantIdx,
+ niche_variants: RangeInclusive<VariantIdx>,
niche: Scalar,
niche_start: u128,
- variants: Vec<LayoutDetails>,
+ variants: IndexVec<VariantIdx, LayoutDetails>,
}
}
let size = scalar.value.size(cx);
let align = scalar.value.align(cx);
LayoutDetails {
- variants: Variants::Single { index: 0 },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Union(0),
abi: Abi::Scalar(scalar),
size,
}
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
- fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: usize) -> TyLayout<'a, Self>;
+ fn for_variant(
+ this: TyLayout<'a, Self>,
+ cx: &C,
+ variant_index: VariantIdx,
+ ) -> TyLayout<'a, Self>;
fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
}
impl<'a, Ty> TyLayout<'a, Ty> {
- pub fn for_variant<C>(self, cx: &C, variant_index: usize) -> Self
+ pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
Ty::for_variant(self, cx, variant_index)
}
#![feature(box_syntax)]
#![feature(nll)]
+#![feature(rustc_attrs)]
#![feature(slice_patterns)]
+#![feature(step_trait)]
#[macro_use]
extern crate bitflags;
#[allow(unused_extern_crates)]
extern crate rustc_cratesio_shim;
+#[macro_use]
+extern crate rustc_data_structures;
+
pub mod abi;
pub mod spec;
log = { version = "0.4" }
rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
chalk-engine = { version = "0.8.0", default-features=false }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use chalk_engine::fallible::Fallible as ChalkEngineFallible;
-use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
-use rustc::infer::canonical::{
- Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
-};
-use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::traits::{
- WellFormed,
- FromEnv,
- DomainGoal,
- ExClauseFold,
- ExClauseLift,
- Goal,
- GoalKind,
- Clause,
- ProgramClauseCategory,
- QuantifierKind,
- Environment,
- InEnvironment,
-};
-use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc::ty::subst::Kind;
-use rustc::ty::{self, TyCtxt};
-use rustc::hir::def_id::DefId;
-
-use std::fmt::{self, Debug};
-use std::marker::PhantomData;
-
-use syntax_pos::DUMMY_SP;
-
-#[derive(Copy, Clone, Debug)]
-crate struct ChalkArenas<'gcx> {
- _phantom: PhantomData<&'gcx ()>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkContext<'cx, 'gcx: 'cx> {
- _arenas: ChalkArenas<'gcx>,
- _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkInferenceContext<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
- infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-}
-
-#[derive(Copy, Clone, Debug)]
-crate struct UniverseMap;
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-crate struct ConstrainedSubst<'tcx> {
- subst: CanonicalVarValues<'tcx>,
- constraints: Vec<QueryRegionConstraint<'tcx>>,
-}
-
-BraceStructTypeFoldableImpl! {
- impl<'tcx> TypeFoldable<'tcx> for ConstrainedSubst<'tcx> {
- subst, constraints
- }
-}
-
-impl context::Context for ChalkArenas<'tcx> {
- type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
-
- type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
- // u-canonicalization not yet implemented
- type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
- type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
-
- // u-canonicalization not yet implemented
- type UniverseMap = UniverseMap;
-
- type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
-
- type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
-
- type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
-
- type RegionConstraint = QueryRegionConstraint<'tcx>;
-
- type Substitution = CanonicalVarValues<'tcx>;
-
- type Environment = Environment<'tcx>;
-
- type Goal = Goal<'tcx>;
-
- type DomainGoal = DomainGoal<'tcx>;
-
- type BindersGoal = ty::Binder<Goal<'tcx>>;
-
- type Parameter = Kind<'tcx>;
-
- type ProgramClause = Clause<'tcx>;
-
- type ProgramClauses = Vec<Clause<'tcx>>;
-
- type UnificationResult = InferOk<'tcx, ()>;
-
- fn goal_in_environment(
- env: &Environment<'tcx>,
- goal: Goal<'tcx>,
- ) -> InEnvironment<'tcx, Goal<'tcx>> {
- env.with(goal)
- }
-}
-
-impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
- fn make_solution(
- &self,
- _root_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- _simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
- ) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
- unimplemented!()
- }
-}
-
-impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
- /// True if this is a coinductive goal -- e.g., proving an auto trait.
- fn is_coinductive(
- &self,
- _goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
- ) -> bool {
- unimplemented!()
- }
-
- /// Create an inference table for processing a new goal and instantiate that goal
- /// in that context, returning "all the pieces".
- ///
- /// More specifically: given a u-canonical goal `arg`, creates a
- /// new inference table `T` and populates it with the universes
- /// found in `arg`. Then, creates a substitution `S` that maps
- /// each bound variable in `arg` to a fresh inference variable
- /// from T. Returns:
- ///
- /// - the table `T`
- /// - the substitution `S`
- /// - the environment and goal found by substitution `S` into `arg`
- fn instantiate_ucanonical_goal<R>(
- &self,
- _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
- ) -> R {
- unimplemented!()
- }
-
- fn instantiate_ex_clause<R>(
- &self,
- _num_universes: usize,
- _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
- _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
- ) -> R {
- unimplemented!()
- }
-
- /// True if this solution has no region constraints.
- fn empty_constraints(ccs: &Canonical<'gcx, ConstrainedSubst<'gcx>>) -> bool {
- ccs.value.constraints.is_empty()
- }
-
- fn inference_normalized_subst_from_ex_clause(
- canon_ex_clause: &'a Canonical<'gcx, ChalkExClause<'gcx>>,
- ) -> &'a CanonicalVarValues<'gcx> {
- &canon_ex_clause.value.subst
- }
-
- fn inference_normalized_subst_from_subst(
- canon_subst: &'a Canonical<'gcx, ConstrainedSubst<'gcx>>,
- ) -> &'a CanonicalVarValues<'gcx> {
- &canon_subst.value.subst
- }
-
- fn canonical(
- u_canon: &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- ) -> &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
- u_canon
- }
-
- fn is_trivial_substitution(
- _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
- ) -> bool {
- unimplemented!()
- }
-
- fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
- 0 // FIXME
- }
-
- /// Convert a goal G *from* the canonical universes *into* our
- /// local universes. This will yield a goal G' that is the same
- /// but for the universes of universally quantified names.
- fn map_goal_from_canonical(
- _map: &UniverseMap,
- value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
- *value // FIXME universe maps not implemented yet
- }
-
- fn map_subst_from_canonical(
- _map: &UniverseMap,
- value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
- ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
- value.clone() // FIXME universe maps not implemented yet
- }
-}
-
-//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
-// for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
-//{
-// fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
-// self
-// }
-//
-// fn is_trivial_substitution(
-// &self,
-// canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-// ) -> bool {
-// let subst = &canonical_subst.value.subst;
-// assert_eq!(self.canonical.variables.len(), subst.var_values.len());
-// subst
-// .var_values
-// .iter_enumerated()
-// .all(|(cvar, kind)| match kind.unpack() {
-// Kind::Lifetime(r) => match r {
-// ty::ReCanonical(cvar1) => cvar == cvar1,
-// _ => false,
-// },
-// Kind::Type(ty) => match ty.sty {
-// ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
-// _ => false,
-// },
-// })
-// }
-//
-// fn num_universes(&self) -> usize {
-// 0 // FIXME
-// }
-//}
-
-impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
- for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
- fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
- self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
- }
-
- fn cannot_prove(&self) -> Goal<'tcx> {
- self.infcx.tcx.mk_goal(GoalKind::CannotProve)
- }
-
- fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
- match *goal {
- GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
- GoalKind::And(left, right) => HhGoal::And(left, right),
- GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
- GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
- GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
- GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
- GoalKind::CannotProve => HhGoal::CannotProve,
- }
- }
-
- fn add_clauses(
- &mut self,
- env: &Environment<'tcx>,
- clauses: Vec<Clause<'tcx>>,
- ) -> Environment<'tcx> {
- Environment {
- clauses: self.infcx.tcx.mk_clauses(
- env.clauses.iter().cloned().chain(clauses.into_iter())
- )
- }
- }
-}
-
-impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
- for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
- fn resolvent_clause(
- &mut self,
- _environment: &Environment<'tcx>,
- _goal: &DomainGoal<'tcx>,
- _subst: &CanonicalVarValues<'tcx>,
- _clause: &Clause<'tcx>,
- ) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
- panic!()
- }
-
- fn apply_answer_subst(
- &mut self,
- _ex_clause: ChalkExClause<'tcx>,
- _selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
- _answer_table_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- _canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
- ) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
- panic!()
- }
-}
-
-impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
- for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
- fn truncate_goal(
- &mut self,
- subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
- ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
- Some(*subgoal) // FIXME we should truncate at some point!
- }
-
- fn truncate_answer(
- &mut self,
- subst: &CanonicalVarValues<'tcx>,
- ) -> Option<CanonicalVarValues<'tcx>> {
- Some(subst.clone()) // FIXME we should truncate at some point!
- }
-}
-
-impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
- for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
- fn program_clauses(
- &self,
- environment: &Environment<'tcx>,
- goal: &DomainGoal<'tcx>,
- ) -> Vec<Clause<'tcx>> {
- use rustc::traits::WhereClause::*;
-
- fn assemble_clauses_from_impls<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- trait_def_id: DefId,
- clauses: &mut Vec<Clause<'tcx>>
- ) {
- tcx.for_each_impl(trait_def_id, |impl_def_id| {
- clauses.extend(
- tcx.program_clauses_for(impl_def_id)
- .into_iter()
- .cloned()
- );
- });
- }
-
- fn assemble_clauses_from_assoc_ty_values<'tcx>(
- tcx: ty::TyCtxt<'_, '_, 'tcx>,
- trait_def_id: DefId,
- clauses: &mut Vec<Clause<'tcx>>
- ) {
- tcx.for_each_impl(trait_def_id, |impl_def_id| {
- for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
- clauses.extend(
- tcx.program_clauses_for(*def_id)
- .into_iter()
- .cloned()
- );
- }
- });
- }
-
- let mut clauses = match goal {
- DomainGoal::Holds(Implemented(trait_predicate)) => {
- // These come from:
- // * implementations of the trait itself (rule `Implemented-From-Impl`)
- // * the trait decl (rule `Implemented-From-Env`)
-
- let mut clauses = vec![];
- assemble_clauses_from_impls(
- self.infcx.tcx,
- trait_predicate.def_id(),
- &mut clauses
- );
-
- // FIXME: we need to add special rules for builtin impls:
- // * `Copy` / `Clone`
- // * `Sized`
- // * `Unsize`
- // * `Generator`
- // * `FnOnce` / `FnMut` / `Fn`
- // * trait objects
- // * auto traits
-
- // Rule `Implemented-From-Env` will be computed from the environment.
- clauses
- }
-
- DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
- // These come from:
- // * the assoc type definition (rule `ProjectionEq-Placeholder`)
- // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- let clauses = self.infcx.tcx.program_clauses_for(
- projection_predicate.projection_ty.item_def_id
- ).into_iter()
-
- // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
- .filter(|clause| clause.category() == ProgramClauseCategory::Other)
-
- .cloned()
- .collect::<Vec<_>>();
-
- // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
- // from the environment.
- clauses
- }
-
- DomainGoal::Holds(RegionOutlives(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::Holds(TypeOutlives(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
- // These come from -- the trait decl (rule `WellFormed-TraitRef`).
- self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
- .into_iter()
-
- // only select `WellFormed-TraitRef`
- .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-
- .cloned()
- .collect()
- }
-
- DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
- // These come from:
- // * the associated type definition if `ty` refers to an unnormalized
- // associated type (rule `WellFormed-AssocTy`)
- // * custom rules for built-in types
- // * the type definition otherwise (rule `WellFormed-Type`)
- let clauses = match ty.sty {
- ty::Projection(data) => {
- self.infcx.tcx.program_clauses_for(data.item_def_id)
- }
-
- // These types are always WF (recall that we do not check
- // for parameters to be WF)
- ty::Bool |
- ty::Char |
- ty::Int(..) |
- ty::Uint(..) |
- ty::Float(..) |
- ty::Str |
- ty::RawPtr(..) |
- ty::FnPtr(..) |
- ty::Param(..) |
- ty::Never => {
- ty::List::empty()
- }
-
- // WF if inner type is `Sized`
- ty::Slice(..) |
- ty::Array(..) => {
- ty::List::empty()
- }
-
- ty::Tuple(..) => {
- ty::List::empty()
- }
-
- // WF if `sub_ty` outlives `region`
- ty::Ref(..) => {
- ty::List::empty()
- }
-
- ty::Dynamic(..) => {
- // FIXME: no rules yet for trait objects
- ty::List::empty()
- }
-
- ty::Adt(def, ..) => {
- self.infcx.tcx.program_clauses_for(def.did)
- }
-
- ty::Foreign(def_id) |
- ty::FnDef(def_id, ..) |
- ty::Closure(def_id, ..) |
- ty::Generator(def_id, ..) |
- ty::Opaque(def_id, ..) => {
- self.infcx.tcx.program_clauses_for(def_id)
- }
-
- ty::GeneratorWitness(..) |
- ty::UnnormalizedProjection(..) |
- ty::Infer(..) |
- ty::Bound(..) |
- ty::Error => {
- bug!("unexpected type {:?}", ty)
- }
- };
-
- clauses.into_iter()
- .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
- .cloned()
- .collect()
- }
-
- DomainGoal::FromEnv(FromEnv::Trait(..)) => {
- // These come from:
- // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
- // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
- // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
- // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
-
- // All of these rules are computed in the environment.
- vec![]
- }
-
- DomainGoal::FromEnv(FromEnv::Ty(..)) => {
- // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
- // comes from the environment).
- vec![]
- }
-
- DomainGoal::Normalize(projection_predicate) => {
- // These come from -- assoc ty values (rule `Normalize-From-Impl`).
- let mut clauses = vec![];
-
- assemble_clauses_from_assoc_ty_values(
- self.infcx.tcx,
- projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
- &mut clauses
- );
-
- clauses
- }
- };
-
- let environment = self.infcx.tcx.lift_to_global(environment)
- .expect("environment is not global");
- clauses.extend(
- self.infcx.tcx.program_clauses_for_env(environment)
- .into_iter()
- .cloned()
- );
- clauses
- }
-
- fn instantiate_binders_universally(
- &mut self,
- _arg: &ty::Binder<Goal<'tcx>>,
- ) -> Goal<'tcx> {
- panic!("FIXME -- universal instantiation needs sgrif's branch")
- }
-
- fn instantiate_binders_existentially(
- &mut self,
- arg: &ty::Binder<Goal<'tcx>>,
- ) -> Goal<'tcx> {
- let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
- DUMMY_SP,
- LateBoundRegionConversionTime::HigherRankedType,
- arg,
- );
- value
- }
-
- fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
- let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
- Box::new(string)
- }
-
- fn canonicalize_goal(
- &mut self,
- value: &InEnvironment<'tcx, Goal<'tcx>>,
- ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
- let mut _orig_values = OriginalQueryValues::default();
- self.infcx.canonicalize_query(value, &mut _orig_values)
- }
-
- fn canonicalize_ex_clause(
- &mut self,
- value: &ChalkExClause<'tcx>,
- ) -> Canonical<'gcx, ChalkExClause<'gcx>> {
- self.infcx.canonicalize_response(value)
- }
-
- fn canonicalize_constrained_subst(
- &mut self,
- subst: CanonicalVarValues<'tcx>,
- constraints: Vec<QueryRegionConstraint<'tcx>>,
- ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
- self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
- }
-
- fn u_canonicalize_goal(
- &mut self,
- value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- ) -> (
- Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
- UniverseMap,
- ) {
- (value.clone(), UniverseMap)
- }
-
- fn invert_goal(
- &mut self,
- _value: &InEnvironment<'tcx, Goal<'tcx>>,
- ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
- panic!("goal inversion not yet implemented")
- }
-
- fn unify_parameters(
- &mut self,
- _environment: &Environment<'tcx>,
- _a: &Kind<'tcx>,
- _b: &Kind<'tcx>,
- ) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
- panic!()
- }
-
- fn sink_answer_subset(
- &self,
- value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
- ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
- value.clone()
- }
-
- fn lift_delayed_literal(
- &self,
- _value: DelayedLiteral<ChalkArenas<'tcx>>,
- ) -> DelayedLiteral<ChalkArenas<'gcx>> {
- panic!("lift")
- }
-
- fn into_ex_clause(&mut self, _result: InferOk<'tcx, ()>, _ex_clause: &mut ChalkExClause<'tcx>) {
- panic!("TBD")
- }
-}
-
-type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
-
-type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
-
-impl Debug for ChalkContext<'cx, 'gcx> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ChalkContext")
- }
-}
-
-impl Debug for ChalkInferenceContext<'cx, 'gcx, 'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ChalkInferenceContext")
- }
-}
-
-impl ExClauseLift<'gcx> for ChalkArenas<'a> {
- type LiftedExClause = ChalkExClause<'gcx>;
-
- fn lift_ex_clause_to_tcx(
- _ex_clause: &ChalkExClause<'a>,
- _tcx: TyCtxt<'_, '_, 'tcx>,
- ) -> Option<Self::LiftedExClause> {
- panic!()
- }
-}
-
-impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
- fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(
- ex_clause: &ChalkExClause<'tcx>,
- folder: &mut F,
- ) -> ChalkExClause<'tcx> {
- ExClause {
- subst: ex_clause.subst.fold_with(folder),
- delayed_literals: ex_clause.delayed_literals.fold_with(folder),
- constraints: ex_clause.constraints.fold_with(folder),
- subgoals: ex_clause.subgoals.fold_with(folder),
- }
- }
-
- fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>(
- ex_clause: &ExClause<Self>,
- visitor: &mut V,
- ) -> bool {
- let ExClause {
- subst,
- delayed_literals,
- constraints,
- subgoals,
- } = ex_clause;
- subst.visit_with(visitor)
- && delayed_literals.visit_with(visitor)
- && constraints.visit_with(visitor)
- && subgoals.visit_with(visitor)
- }
-}
-
-BraceStructLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
- type Lifted = ConstrainedSubst<'tcx>;
-
- subst, constraints
- }
-}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod program_clauses;
+
+use chalk_engine::fallible::Fallible as ChalkEngineFallible;
+use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
+use rustc::infer::canonical::{
+ Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
+};
+use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use rustc::traits::{
+ DomainGoal,
+ ExClauseFold,
+ ExClauseLift,
+ Goal,
+ GoalKind,
+ Clause,
+ QuantifierKind,
+ Environment,
+ InEnvironment,
+};
+use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use rustc::ty::subst::Kind;
+use rustc::ty::{self, TyCtxt};
+
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+
+use syntax_pos::DUMMY_SP;
+
+#[derive(Copy, Clone, Debug)]
+crate struct ChalkArenas<'gcx> {
+ _phantom: PhantomData<&'gcx ()>,
+}
+
+#[derive(Copy, Clone)]
+crate struct ChalkContext<'cx, 'gcx: 'cx> {
+ _arenas: ChalkArenas<'gcx>,
+ _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
+}
+
+#[derive(Copy, Clone)]
+crate struct ChalkInferenceContext<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+ infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+}
+
+#[derive(Copy, Clone, Debug)]
+crate struct UniverseMap;
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+crate struct ConstrainedSubst<'tcx> {
+ subst: CanonicalVarValues<'tcx>,
+ constraints: Vec<QueryRegionConstraint<'tcx>>,
+}
+
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for ConstrainedSubst<'tcx> {
+ subst, constraints
+ }
+}
+
+impl context::Context for ChalkArenas<'tcx> {
+ type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
+
+ type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
+
+ // u-canonicalization not yet implemented
+ type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
+
+ type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
+
+ // u-canonicalization not yet implemented
+ type UniverseMap = UniverseMap;
+
+ type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
+
+ type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
+
+ type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
+
+ type RegionConstraint = QueryRegionConstraint<'tcx>;
+
+ type Substitution = CanonicalVarValues<'tcx>;
+
+ type Environment = Environment<'tcx>;
+
+ type Goal = Goal<'tcx>;
+
+ type DomainGoal = DomainGoal<'tcx>;
+
+ type BindersGoal = ty::Binder<Goal<'tcx>>;
+
+ type Parameter = Kind<'tcx>;
+
+ type ProgramClause = Clause<'tcx>;
+
+ type ProgramClauses = Vec<Clause<'tcx>>;
+
+ type UnificationResult = InferOk<'tcx, ()>;
+
+ fn goal_in_environment(
+ env: &Environment<'tcx>,
+ goal: Goal<'tcx>,
+ ) -> InEnvironment<'tcx, Goal<'tcx>> {
+ env.with(goal)
+ }
+}
+
+impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
+ fn make_solution(
+ &self,
+ _root_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ _simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
+ ) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
+ unimplemented!()
+ }
+}
+
+impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
+ /// True if this is a coinductive goal -- e.g., proving an auto trait.
+ fn is_coinductive(
+ &self,
+ _goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
+ ) -> bool {
+ unimplemented!()
+ }
+
+ /// Create an inference table for processing a new goal and instantiate that goal
+ /// in that context, returning "all the pieces".
+ ///
+ /// More specifically: given a u-canonical goal `arg`, creates a
+ /// new inference table `T` and populates it with the universes
+ /// found in `arg`. Then, creates a substitution `S` that maps
+ /// each bound variable in `arg` to a fresh inference variable
+ /// from T. Returns:
+ ///
+ /// - the table `T`
+ /// - the substitution `S`
+ /// - the environment and goal found by substitution `S` into `arg`
+ fn instantiate_ucanonical_goal<R>(
+ &self,
+ _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
+ ) -> R {
+ unimplemented!()
+ }
+
+ fn instantiate_ex_clause<R>(
+ &self,
+ _num_universes: usize,
+ _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
+ _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
+ ) -> R {
+ unimplemented!()
+ }
+
+ /// True if this solution has no region constraints.
+ fn empty_constraints(ccs: &Canonical<'gcx, ConstrainedSubst<'gcx>>) -> bool {
+ ccs.value.constraints.is_empty()
+ }
+
+ fn inference_normalized_subst_from_ex_clause(
+ canon_ex_clause: &'a Canonical<'gcx, ChalkExClause<'gcx>>,
+ ) -> &'a CanonicalVarValues<'gcx> {
+ &canon_ex_clause.value.subst
+ }
+
+ fn inference_normalized_subst_from_subst(
+ canon_subst: &'a Canonical<'gcx, ConstrainedSubst<'gcx>>,
+ ) -> &'a CanonicalVarValues<'gcx> {
+ &canon_subst.value.subst
+ }
+
+ fn canonical(
+ u_canon: &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ ) -> &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+ u_canon
+ }
+
+ fn is_trivial_substitution(
+ _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+ ) -> bool {
+ unimplemented!()
+ }
+
+ fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
+ 0 // FIXME
+ }
+
+ /// Convert a goal G *from* the canonical universes *into* our
+ /// local universes. This will yield a goal G' that is the same
+ /// but for the universes of universally quantified names.
+ fn map_goal_from_canonical(
+ _map: &UniverseMap,
+ value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+ *value // FIXME universe maps not implemented yet
+ }
+
+ fn map_subst_from_canonical(
+ _map: &UniverseMap,
+ value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+ ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
+ value.clone() // FIXME universe maps not implemented yet
+ }
+}
+
+//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
+// for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
+//{
+// fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
+// self
+// }
+//
+// fn is_trivial_substitution(
+// &self,
+// canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
+// ) -> bool {
+// let subst = &canonical_subst.value.subst;
+// assert_eq!(self.canonical.variables.len(), subst.var_values.len());
+// subst
+// .var_values
+// .iter_enumerated()
+// .all(|(cvar, kind)| match kind.unpack() {
+// Kind::Lifetime(r) => match r {
+// ty::ReCanonical(cvar1) => cvar == cvar1,
+// _ => false,
+// },
+// Kind::Type(ty) => match ty.sty {
+// ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
+// _ => false,
+// },
+// })
+// }
+//
+// fn num_universes(&self) -> usize {
+// 0 // FIXME
+// }
+//}
+
+impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+ for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+ fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
+ self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+ }
+
+ fn cannot_prove(&self) -> Goal<'tcx> {
+ self.infcx.tcx.mk_goal(GoalKind::CannotProve)
+ }
+
+ fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
+ match *goal {
+ GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
+ GoalKind::And(left, right) => HhGoal::And(left, right),
+ GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
+ GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
+ GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
+ GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
+ GoalKind::CannotProve => HhGoal::CannotProve,
+ }
+ }
+
+ fn add_clauses(
+ &mut self,
+ env: &Environment<'tcx>,
+ clauses: Vec<Clause<'tcx>>,
+ ) -> Environment<'tcx> {
+ Environment {
+ clauses: self.infcx.tcx.mk_clauses(
+ env.clauses.iter().cloned().chain(clauses.into_iter())
+ )
+ }
+ }
+}
+
+impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+ for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+ fn resolvent_clause(
+ &mut self,
+ _environment: &Environment<'tcx>,
+ _goal: &DomainGoal<'tcx>,
+ _subst: &CanonicalVarValues<'tcx>,
+ _clause: &Clause<'tcx>,
+ ) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
+ panic!()
+ }
+
+ fn apply_answer_subst(
+ &mut self,
+ _ex_clause: ChalkExClause<'tcx>,
+ _selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
+ _answer_table_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ _canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+ ) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
+ panic!()
+ }
+}
+
+impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+ for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+ fn truncate_goal(
+ &mut self,
+ subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
+ ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
+ Some(*subgoal) // FIXME we should truncate at some point!
+ }
+
+ fn truncate_answer(
+ &mut self,
+ subst: &CanonicalVarValues<'tcx>,
+ ) -> Option<CanonicalVarValues<'tcx>> {
+ Some(subst.clone()) // FIXME we should truncate at some point!
+ }
+}
+
+impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+ for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+ fn program_clauses(
+ &self,
+ environment: &Environment<'tcx>,
+ goal: &DomainGoal<'tcx>,
+ ) -> Vec<Clause<'tcx>> {
+ self.program_clauses_impl(environment, goal)
+ }
+
+ fn instantiate_binders_universally(
+ &mut self,
+ _arg: &ty::Binder<Goal<'tcx>>,
+ ) -> Goal<'tcx> {
+ panic!("FIXME -- universal instantiation needs sgrif's branch")
+ }
+
+ fn instantiate_binders_existentially(
+ &mut self,
+ arg: &ty::Binder<Goal<'tcx>>,
+ ) -> Goal<'tcx> {
+ self.infcx.replace_bound_vars_with_fresh_vars(
+ DUMMY_SP,
+ LateBoundRegionConversionTime::HigherRankedType,
+ arg
+ ).0
+ }
+
+ fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
+ let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
+ Box::new(string)
+ }
+
+ fn canonicalize_goal(
+ &mut self,
+ value: &InEnvironment<'tcx, Goal<'tcx>>,
+ ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+ let mut _orig_values = OriginalQueryValues::default();
+ self.infcx.canonicalize_query(value, &mut _orig_values)
+ }
+
+ fn canonicalize_ex_clause(
+ &mut self,
+ value: &ChalkExClause<'tcx>,
+ ) -> Canonical<'gcx, ChalkExClause<'gcx>> {
+ self.infcx.canonicalize_response(value)
+ }
+
+ fn canonicalize_constrained_subst(
+ &mut self,
+ subst: CanonicalVarValues<'tcx>,
+ constraints: Vec<QueryRegionConstraint<'tcx>>,
+ ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
+ self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
+ }
+
+ fn u_canonicalize_goal(
+ &mut self,
+ value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ ) -> (
+ Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+ UniverseMap,
+ ) {
+ (value.clone(), UniverseMap)
+ }
+
+ fn invert_goal(
+ &mut self,
+ _value: &InEnvironment<'tcx, Goal<'tcx>>,
+ ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
+ panic!("goal inversion not yet implemented")
+ }
+
+ fn unify_parameters(
+ &mut self,
+ _environment: &Environment<'tcx>,
+ _a: &Kind<'tcx>,
+ _b: &Kind<'tcx>,
+ ) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
+ panic!()
+ }
+
+ fn sink_answer_subset(
+ &self,
+ value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+ ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
+ value.clone()
+ }
+
+ fn lift_delayed_literal(
+ &self,
+ _value: DelayedLiteral<ChalkArenas<'tcx>>,
+ ) -> DelayedLiteral<ChalkArenas<'gcx>> {
+ panic!("lift")
+ }
+
+ fn into_ex_clause(&mut self, _result: InferOk<'tcx, ()>, _ex_clause: &mut ChalkExClause<'tcx>) {
+ panic!("TBD")
+ }
+}
+
+type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
+
+type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
+
+impl Debug for ChalkContext<'cx, 'gcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ChalkContext")
+ }
+}
+
+impl Debug for ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ChalkInferenceContext")
+ }
+}
+
+impl ExClauseLift<'gcx> for ChalkArenas<'a> {
+ type LiftedExClause = ChalkExClause<'gcx>;
+
+ fn lift_ex_clause_to_tcx(
+ _ex_clause: &ChalkExClause<'a>,
+ _tcx: TyCtxt<'_, '_, 'tcx>,
+ ) -> Option<Self::LiftedExClause> {
+ panic!()
+ }
+}
+
+impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
+ fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(
+ ex_clause: &ChalkExClause<'tcx>,
+ folder: &mut F,
+ ) -> ChalkExClause<'tcx> {
+ ExClause {
+ subst: ex_clause.subst.fold_with(folder),
+ delayed_literals: ex_clause.delayed_literals.fold_with(folder),
+ constraints: ex_clause.constraints.fold_with(folder),
+ subgoals: ex_clause.subgoals.fold_with(folder),
+ }
+ }
+
+ fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>(
+ ex_clause: &ExClause<Self>,
+ visitor: &mut V,
+ ) -> bool {
+ let ExClause {
+ subst,
+ delayed_literals,
+ constraints,
+ subgoals,
+ } = ex_clause;
+ subst.visit_with(visitor)
+ && delayed_literals.visit_with(visitor)
+ && constraints.visit_with(visitor)
+ && subgoals.visit_with(visitor)
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
+ type Lifted = ConstrainedSubst<'tcx>;
+
+ subst, constraints
+ }
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::traits::{
+ WellFormed,
+ FromEnv,
+ DomainGoal,
+ GoalKind,
+ Clause,
+ Clauses,
+ ProgramClause,
+ ProgramClauseCategory,
+ Environment,
+};
+use rustc::ty;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc_target::spec::abi;
+use super::ChalkInferenceContext;
+use crate::lowering::Lower;
+use std::iter;
+
+fn assemble_clauses_from_impls<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ trait_def_id: DefId,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ tcx.for_each_impl(trait_def_id, |impl_def_id| {
+ clauses.extend(
+ tcx.program_clauses_for(impl_def_id)
+ .into_iter()
+ .cloned()
+ );
+ });
+}
+
+fn assemble_clauses_from_assoc_ty_values<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ trait_def_id: DefId,
+ clauses: &mut Vec<Clause<'tcx>>
+) {
+ tcx.for_each_impl(trait_def_id, |impl_def_id| {
+ for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
+ clauses.extend(
+ tcx.program_clauses_for(*def_id)
+ .into_iter()
+ .cloned()
+ );
+ }
+ });
+}
+
+fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+ let ty = ty::Bound(
+ ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+ );
+ let ty = tcx.mk_ty(ty);
+
+ let ptr_ty = tcx.mk_ptr(ty::TypeAndMut {
+ ty,
+ mutbl: hir::Mutability::MutImmutable,
+ });
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<T> { WellFormed(*const T). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_fn_ptr<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ arity_and_output: usize,
+ variadic: bool,
+ unsafety: hir::Unsafety,
+ abi: abi::Abi
+) -> Clauses<'tcx> {
+ let inputs_and_output = tcx.mk_type_list(
+ (0..arity_and_output).into_iter()
+ // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
+ .map(|i| ty::BoundTy::new(ty::DebruijnIndex::from(1usize), ty::BoundVar::from(i)))
+ .map(|t| tcx.mk_ty(ty::Bound(t)))
+ );
+
+ let fn_sig = ty::Binder::bind(ty::FnSig {
+ inputs_and_output,
+ variadic,
+ unsafety,
+ abi,
+ });
+ let fn_ptr = tcx.mk_fn_ptr(fn_sig);
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
+ // where `n + 1` == `arity_and_output`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+ let ty = ty::Bound(
+ ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+ );
+ let ty = tcx.mk_ty(ty);
+
+ let slice_ty = tcx.mk_slice(ty);
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+ let sized_implemented = ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+ };
+ let sized_implemented: DomainGoal = ty::TraitPredicate {
+ trait_ref: sized_implemented
+ }.lower();
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_array<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ length: &'tcx ty::Const<'tcx>
+) -> Clauses<'tcx> {
+ let ty = ty::Bound(
+ ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+ );
+ let ty = tcx.mk_ty(ty);
+
+ let array_ty = tcx.mk_ty(ty::Array(ty, length));
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+ let sized_implemented = ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+ };
+ let sized_implemented: DomainGoal = ty::TraitPredicate {
+ trait_ref: sized_implemented
+ }.lower();
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_tuple<'tcx>(
+ tcx: ty::TyCtxt<'_, '_, 'tcx>,
+ arity: usize
+) -> Clauses<'tcx> {
+ let type_list = tcx.mk_type_list(
+ (0..arity).into_iter()
+ .map(|i| ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from(i)))
+ .map(|t| tcx.mk_ty(ty::Bound(t)))
+ );
+
+ let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
+
+ let sized_trait = match tcx.lang_items().sized_trait() {
+ Some(def_id) => def_id,
+ None => return ty::List::empty(),
+ };
+ let sized_implemented = type_list[0..arity - 1].iter()
+ .map(|ty| ty::TraitRef {
+ def_id: sized_trait,
+ substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
+ })
+ .map(|trait_ref| ty::TraitPredicate { trait_ref })
+ .map(|predicate| predicate.lower());
+
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
+ hypotheses: tcx.mk_goals(
+ sized_implemented.map(|domain_goal| {
+ tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+ })
+ ),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // ```
+ // forall<T1, ..., Tn-1, Tn> {
+ // WellFormed((T1, ..., Tn)) :-
+ // Implemented(T1: Sized),
+ // ...
+ // Implemented(Tn-1: Sized).
+ // }
+ // ```
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+ let region = tcx.mk_region(
+ ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+ );
+ let ty = tcx.mk_ty(
+ ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+ );
+
+ let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
+ ty,
+ mutbl: hir::Mutability::MutImmutable,
+ });
+
+ let outlives: DomainGoal = ty::OutlivesPredicate(ty, region).lower();
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
+ hypotheses: tcx.mk_goals(
+ iter::once(tcx.mk_goal(outlives.into_goal()))
+ ),
+ category: ProgramClauseCategory::ImpliedBound,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+ // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
+ tcx.mk_clauses(iter::once(wf_clause))
+}
+
+impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+ pub(super) fn program_clauses_impl(
+ &self,
+ environment: &Environment<'tcx>,
+ goal: &DomainGoal<'tcx>,
+ ) -> Vec<Clause<'tcx>> {
+ use rustc::traits::WhereClause::*;
+
+ let mut clauses = match goal {
+ DomainGoal::Holds(Implemented(trait_predicate)) => {
+ // These come from:
+ // * implementations of the trait itself (rule `Implemented-From-Impl`)
+ // * the trait decl (rule `Implemented-From-Env`)
+
+ let mut clauses = vec![];
+ assemble_clauses_from_impls(
+ self.infcx.tcx,
+ trait_predicate.def_id(),
+ &mut clauses
+ );
+
+ // FIXME: we need to add special rules for builtin impls:
+ // * `Copy` / `Clone`
+ // * `Sized`
+ // * `Unsize`
+ // * `Generator`
+ // * `FnOnce` / `FnMut` / `Fn`
+ // * trait objects
+ // * auto traits
+
+ // Rule `Implemented-From-Env` will be computed from the environment.
+ clauses
+ }
+
+ DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
+ // These come from:
+ // * the assoc type definition (rule `ProjectionEq-Placeholder`)
+ // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+ let clauses = self.infcx.tcx.program_clauses_for(
+ projection_predicate.projection_ty.item_def_id
+ ).into_iter()
+
+ // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
+ .filter(|clause| clause.category() == ProgramClauseCategory::Other)
+
+ .cloned()
+ .collect::<Vec<_>>();
+
+ // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
+ // from the environment.
+ clauses
+ }
+
+ DomainGoal::Holds(RegionOutlives(..)) => {
+ // These come from:
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+ // All of these rules are computed in the environment.
+ vec![]
+ }
+
+ DomainGoal::Holds(TypeOutlives(..)) => {
+ // These come from:
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+ // All of these rules are computed in the environment.
+ vec![]
+ }
+
+ DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
+ // These come from -- the trait decl (rule `WellFormed-TraitRef`).
+ self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
+ .into_iter()
+
+ // only select `WellFormed-TraitRef`
+ .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+
+ .cloned()
+ .collect()
+ }
+
+ DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
+ // These come from:
+ // * the associated type definition if `ty` refers to an unnormalized
+ // associated type (rule `WellFormed-AssocTy`)
+ // * custom rules for built-in types
+ // * the type definition otherwise (rule `WellFormed-Type`)
+ let clauses = match ty.sty {
+ ty::Projection(data) => {
+ self.infcx.tcx.program_clauses_for(data.item_def_id)
+ }
+
+ // These types are always WF and non-parametric.
+ ty::Bool |
+ ty::Char |
+ ty::Int(..) |
+ ty::Uint(..) |
+ ty::Float(..) |
+ ty::Str |
+ ty::Never => {
+ let wf_clause = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
+ hypotheses: ty::List::empty(),
+ category: ProgramClauseCategory::WellFormed,
+ };
+ let wf_clause = Clause::ForAll(ty::Binder::dummy(wf_clause));
+
+ self.infcx.tcx.mk_clauses(iter::once(wf_clause))
+ }
+
+ // Always WF (recall that we do not check for parameters to be WF).
+ ty::RawPtr(..) => program_clauses_for_raw_ptr(self.infcx.tcx),
+
+ // Always WF (recall that we do not check for parameters to be WF).
+ ty::FnPtr(fn_ptr) => {
+ let fn_ptr = fn_ptr.skip_binder();
+ program_clauses_for_fn_ptr(
+ self.infcx.tcx,
+ fn_ptr.inputs_and_output.len(),
+ fn_ptr.variadic,
+ fn_ptr.unsafety,
+ fn_ptr.abi
+ )
+ }
+
+ // WF if inner type is `Sized`.
+ ty::Slice(..) => program_clauses_for_slice(self.infcx.tcx),
+
+ // WF if inner type is `Sized`.
+ ty::Array(_, length) => program_clauses_for_array(self.infcx.tcx, length),
+
+ // WF if all types but the last one are `Sized`.
+ ty::Tuple(types) => program_clauses_for_tuple(
+ self.infcx.tcx,
+ types.len()
+ ),
+
+ // WF if `sub_ty` outlives `region`.
+ ty::Ref(..) => program_clauses_for_ref(self.infcx.tcx),
+
+ ty::Dynamic(..) => {
+ // FIXME: no rules yet for trait objects
+ ty::List::empty()
+ }
+
+ ty::Adt(def, ..) => {
+ self.infcx.tcx.program_clauses_for(def.did)
+ }
+
+ ty::Foreign(def_id) |
+ ty::FnDef(def_id, ..) |
+ ty::Closure(def_id, ..) |
+ ty::Generator(def_id, ..) |
+ ty::Opaque(def_id, ..) => {
+ self.infcx.tcx.program_clauses_for(def_id)
+ }
+
+ ty::GeneratorWitness(..) |
+ ty::UnnormalizedProjection(..) |
+ ty::Infer(..) |
+ ty::Bound(..) |
+ ty::Param(..) |
+ ty::Error => {
+ bug!("unexpected type {:?}", ty)
+ }
+ };
+
+ clauses.into_iter()
+ .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+ .cloned()
+ .collect()
+ }
+
+ DomainGoal::FromEnv(FromEnv::Trait(..)) => {
+ // These come from:
+ // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+ // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+ // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
+ // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
+
+ // All of these rules are computed in the environment.
+ vec![]
+ }
+
+ DomainGoal::FromEnv(FromEnv::Ty(..)) => {
+ // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
+ // comes from the environment).
+ vec![]
+ }
+
+ DomainGoal::Normalize(projection_predicate) => {
+ // These come from -- assoc ty values (rule `Normalize-From-Impl`).
+ let mut clauses = vec![];
+
+ assemble_clauses_from_assoc_ty_values(
+ self.infcx.tcx,
+ projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
+ &mut clauses
+ );
+
+ clauses
+ }
+ };
+
+ let environment = self.infcx.tcx.lift_to_global(environment)
+ .expect("environment is not global");
+ clauses.extend(
+ self.infcx.tcx.program_clauses_for_env(environment)
+ .into_iter()
+ .cloned()
+ );
+ clauses
+ }
+}
#[macro_use]
extern crate rustc;
extern crate rustc_data_structures;
+extern crate rustc_target;
extern crate syntax;
extern crate syntax_pos;
extern crate smallvec;
use rustc::ty::{self, TyCtxt, Ty};
use rustc::hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet;
+use super::Lower;
+use std::iter;
struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
);
}
- // forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
- ty::Ref(_region, _sub_ty, ..) => {
- // FIXME: we'd need bound tys in order to properly write the above rule
+ // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` }
+ ty::Ref(..) => {
+ use rustc::hir;
+
+ let region = self.tcx.mk_region(
+ ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+ );
+ let ty = self.tcx.mk_ty(
+ ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+ );
+
+ let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
+ ty,
+ mutbl: hir::Mutability::MutImmutable,
+ });
+ let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
+
+ let clause = ProgramClause {
+ goal: ty::OutlivesPredicate(ty, region).lower(),
+ hypotheses: self.tcx.mk_goals(
+ iter::once(self.tcx.mk_goal(from_env.into_goal()))
+ ),
+ category: ProgramClauseCategory::ImpliedBound,
+ };
+ let clause = Clause::ForAll(ty::Binder::bind(clause));
+ self.round.insert(clause);
}
ty::Dynamic(..) => {
ty::FnPtr(..) |
ty::Tuple(..) |
ty::Never |
- ty::Param(..) => (),
+ ty::Infer(..) |
+ ty::Bound(..) => (),
ty::GeneratorWitness(..) |
ty::UnnormalizedProjection(..) |
- ty::Infer(..) |
- ty::Bound(..) |
+ ty::Param(..) |
ty::Error => {
bug!("unexpected type {:?}", ty);
}
);
}
-crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
+crate fn environment<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId
+) -> ty::Binder<Environment<'tcx>> {
use super::{Lower, IntoFromEnvGoal};
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
+ use rustc::ty::subst::{Subst, Substs};
// The environment of an impl Trait type is its defining function's environment.
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
return environment(tcx, parent);
}
+ let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
// Compute the bounds on `Self` and the type parameters.
- let ty::InstantiatedPredicates { predicates } =
- tcx.predicates_of(def_id).instantiate_identity(tcx);
+ let ty::InstantiatedPredicates { predicates } = tcx.predicates_of(def_id)
+ .instantiate_identity(tcx);
let clauses = predicates.into_iter()
.map(|predicate| predicate.lower())
+ .map(|predicate| predicate.subst(tcx, bound_vars))
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
let mut input_tys = FxHashSet::default();
- // In an impl, we assume that the receiver type and all its constituents
+ // In an impl, we assume that the header trait ref and all its constituents
// are well-formed.
if is_impl {
- let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
- input_tys.extend(trait_ref.self_ty().walk());
+ let trait_ref = tcx.impl_trait_ref(def_id)
+ .expect("not an impl")
+ .subst(tcx, bound_vars);
+
+ input_tys.extend(
+ trait_ref.substs.types().flat_map(|ty| ty.walk())
+ );
}
// In an fn, we assume that the arguments and all their constituents are
// well-formed.
if is_fn {
- let fn_sig = tcx.fn_sig(def_id);
+ // `skip_binder` because we move region parameters to the root binder,
+ // restored in the return type of this query
+ let fn_sig = tcx.fn_sig(def_id).skip_binder().subst(tcx, bound_vars);
+
input_tys.extend(
- // FIXME: `skip_binder` seems ok for now? In a real setting,
- // the late bound regions would next be instantiated with things
- // in the inference table.
- fn_sig.skip_binder().inputs().iter().flat_map(|ty| ty.walk())
+ fn_sig.inputs().iter().flat_map(|ty| ty.walk())
);
}
let clauses = clauses.chain(
input_tys.into_iter()
+ // Filter out type parameters
+ .filter(|ty| match ty.sty {
+ ty::Bound(..) => false,
+ _ => true,
+ })
.map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
.map(|domain_goal| domain_goal.into_program_clause())
.map(Clause::Implies)
);
- Environment {
+ ty::Binder::bind(Environment {
clauses: tcx.mk_clauses(clauses),
- }
+ })
}
};
use rustc::ty::query::Providers;
use rustc::ty::{self, List, TyCtxt};
+use rustc::ty::subst::{Subst, Substs};
use syntax::ast;
use std::iter;
Predicate::RegionOutlives(predicate) => predicate.lower(),
Predicate::TypeOutlives(predicate) => predicate.lower(),
Predicate::Projection(predicate) => predicate.lower(),
- Predicate::WellFormed(ty) => {
- ty::Binder::dummy(DomainGoal::WellFormed(WellFormed::Ty(*ty)))
+
+ Predicate::WellFormed(..) |
+ Predicate::ObjectSafe(..) |
+ Predicate::ClosureKind(..) |
+ Predicate::Subtype(..) |
+ Predicate::ConstEvaluatable(..) => {
+ bug!("unexpected predicate {}", self)
}
- Predicate::ObjectSafe(..)
- | Predicate::ClosureKind(..)
- | Predicate::Subtype(..)
- | Predicate::ConstEvaluatable(..) => unimplemented!(),
}
}
}
// }
// ```
+ let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
// `Self: Trait<P1..Pn>`
let trait_pred = ty::TraitPredicate {
- trait_ref: ty::TraitRef::identity(tcx, def_id),
+ trait_ref: ty::TraitRef {
+ def_id,
+ substs: bound_vars,
+ },
};
// `Implemented(Self: Trait<P1..Pn>)`
category: ProgramClauseCategory::ImpliedBound,
};
- let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
+ let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env));
let where_clauses = &tcx.predicates_defined_on(def_id).predicates
.into_iter()
.map(|(wc, _)| wc.lower())
+ .map(|wc| wc.subst(tcx, bound_vars))
.collect::<Vec<_>>();
// Rule Implied-Bound-From-Trait
.cloned()
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
- .map(|wc| wc.map_bound(|goal| ProgramClause {
- goal: goal.into_from_env_goal(),
- hypotheses,
- category: ProgramClauseCategory::ImpliedBound,
- }))
+ .map(|wc| {
+ // we move binders to the left
+ wc.map_bound(|goal| ProgramClause {
+ goal: goal.into_from_env_goal(),
+
+ // FIXME: As where clauses can only bind lifetimes for now,
+ // and that named bound regions have a def-id, it is safe
+ // to just inject `hypotheses` (which contains named vars bound at index `0`)
+ // into this binding level. This may change if we ever allow where clauses
+ // to bind types (e.g. for GATs things), because bound types only use a `BoundVar`
+ // index (no def-id).
+ hypotheses,
+
+ category: ProgramClauseCategory::ImpliedBound,
+ })
+ })
.map(Clause::ForAll);
// Rule WellFormed-TraitRef
// }
// ```
- // `Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
- let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower()))
- .chain(
- where_clauses
- .into_iter()
- .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()))
- );
+ // `WellFormed(WC)`
+ let wf_conditions = where_clauses
+ .into_iter()
+ .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()));
// `WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)),
hypotheses: tcx.mk_goals(
- wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(impl_trait))).chain(
+ wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx)))
+ )
),
category: ProgramClauseCategory::WellFormed,
};
- let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
tcx.mk_clauses(
- clauses
+ iter::once(implemented_from_env)
.chain(implied_bound_clauses)
- .chain(wf_clause)
+ .chain(iter::once(wf_clause))
)
}
// }
// ```
- let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+ let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
+ let trait_ref = tcx.impl_trait_ref(def_id)
+ .expect("not an impl")
+ .subst(tcx, bound_vars);
// `Implemented(A0: Trait<A1..An>)`
let trait_pred = ty::TraitPredicate { trait_ref }.lower();
// `WC`
let where_clauses = tcx.predicates_of(def_id).predicates
.into_iter()
- .map(|(wc, _)| wc.lower());
+ .map(|(wc, _)| wc.lower())
+ .map(|wc| wc.subst(tcx, bound_vars));
// `Implemented(A0: Trait<A1..An>) :- WC`
let clause = ProgramClause {
),
category: ProgramClauseCategory::Other,
};
- tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
+ tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::bind(clause))))
}
pub fn program_clauses_for_type_def<'a, 'tcx>(
// }
// ```
+ let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
// `Ty<...>`
- let ty = tcx.type_of(def_id);
+ let ty = tcx.type_of(def_id).subst(tcx, bound_vars);
// `WC`
let where_clauses = tcx.predicates_of(def_id).predicates
.into_iter()
.map(|(wc, _)| wc.lower())
+ .map(|wc| wc.subst(tcx, bound_vars))
.collect::<Vec<_>>();
// `WellFormed(Ty<...>) :- WC1, ..., WCm`
- let well_formed = ProgramClause {
+ let well_formed_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
hypotheses: tcx.mk_goals(
where_clauses
),
category: ProgramClauseCategory::WellFormed,
};
+ let well_formed_clause = Clause::ForAll(ty::Binder::bind(well_formed_clause));
- let well_formed_clause = iter::once(Clause::ForAll(ty::Binder::dummy(well_formed)));
-
- // Rule FromEnv-Type
+ // Rule Implied-Bound-From-Type
//
// For each where clause `WC`:
// ```
.into_iter()
// `FromEnv(WC) :- FromEnv(Ty<...>)`
- .map(|wc| wc.map_bound(|goal| ProgramClause {
- goal: goal.into_from_env_goal(),
- hypotheses,
- category: ProgramClauseCategory::ImpliedBound,
- }))
+ .map(|wc| {
+ // move the binders to the left
+ wc.map_bound(|goal| ProgramClause {
+ goal: goal.into_from_env_goal(),
+
+ // FIXME: we inject `hypotheses` into this binding level,
+ // which may be incorrect in the future: see the FIXME in
+ // `program_clauses_for_trait`
+ hypotheses,
+
+ category: ProgramClauseCategory::ImpliedBound,
+ })
+ })
.map(Clause::ForAll);
- tcx.mk_clauses(well_formed_clause.chain(from_env_clauses))
+ tcx.mk_clauses(iter::once(well_formed_clause).chain(from_env_clauses))
}
pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
item_id: DefId,
) -> Clauses<'tcx> {
- // Rule ProjectionEq-Skolemize
+ // Rule ProjectionEq-Placeholder
//
// ```
// trait Trait<P1..Pn> {
ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id,
_ => bug!("not an trait container"),
};
- let trait_ref = ty::TraitRef::identity(tcx, trait_id);
+
+ let trait_bound_vars = Substs::bound_vars_for_item(tcx, trait_id);
+ let trait_ref = ty::TraitRef {
+ def_id: trait_id,
+ substs: trait_bound_vars,
+ };
let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty));
hypotheses: ty::List::empty(),
category: ProgramClauseCategory::Other,
};
+ let projection_eq_clause = Clause::ForAll(ty::Binder::bind(projection_eq_clause));
// Rule WellFormed-AssocTy
// ```
let hypothesis = tcx.mk_goal(
DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
);
+
let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
category: ProgramClauseCategory::WellFormed,
};
+ let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
// Rule Implied-Trait-From-AssocTy
// ```
let hypothesis = tcx.mk_goal(
DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal()
);
+
let from_env_clause = ProgramClause {
goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
category: ProgramClauseCategory::ImpliedBound,
};
+ let from_env_clause = Clause::ForAll(ty::Binder::bind(from_env_clause));
let clauses = iter::once(projection_eq_clause)
.chain(iter::once(wf_clause))
.chain(iter::once(from_env_clause));
- let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause)));
tcx.mk_clauses(clauses)
}
_ => bug!("not an impl container"),
};
+ let impl_bound_vars = Substs::bound_vars_for_item(tcx, impl_id);
+
// `A0 as Trait<A1..An>`
- let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
+ let trait_ref = tcx.impl_trait_ref(impl_id)
+ .unwrap()
+ .subst(tcx, impl_bound_vars);
// `T`
let ty = tcx.type_of(item_id);
// `Implemented(A0: Trait<A1..An>)`
- let trait_implemented = ty::Binder::dummy(ty::TraitPredicate { trait_ref }.lower());
-
- // `Implemented(A0: Trait<A1..An>)`
- let hypotheses = vec![trait_implemented];
+ let trait_implemented: DomainGoal = ty::TraitPredicate { trait_ref }.lower();
// `<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm>`
let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
let normalize_goal = DomainGoal::Normalize(ty::ProjectionPredicate { projection_ty, ty });
// `Normalize(... -> T) :- ...`
- let clause = ProgramClause {
+ let normalize_clause = ProgramClause {
goal: normalize_goal,
hypotheses: tcx.mk_goals(
- hypotheses
- .into_iter()
- .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
+ iter::once(tcx.mk_goal(GoalKind::DomainGoal(trait_implemented)))
),
category: ProgramClauseCategory::Other,
};
- tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
+ let normalize_clause = Clause::ForAll(ty::Binder::bind(normalize_clause));
+
+ tcx.mk_clauses(iter::once(normalize_clause))
}
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
if attr.check_name("rustc_dump_env_program_clauses") {
let environment = self.tcx.environment(def_id);
- clauses = Some(self.tcx.program_clauses_for_env(environment));
+ clauses = Some(self.tcx.program_clauses_for_env(*environment.skip_binder()));
}
if let Some(clauses) = clauses {
let mut strings: Vec<_> = clauses
.iter()
- .map(|clause| {
- // Skip the top-level binder for a less verbose output
- let program_clause = match clause {
- Clause::Implies(program_clause) => program_clause,
- Clause::ForAll(program_clause) => program_clause.skip_binder(),
- };
- program_clause.to_string()
- })
+ .map(|clause| clause.to_string())
.collect();
strings.sort();
// fnmut vs fnonce. If so, we have to defer further processing.
if self.closure_kind(def_id, substs).is_none() {
let closure_ty = self.closure_sig(def_id, substs);
- let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
- infer::FnCall,
- &closure_ty)
- .0;
+ let fn_sig = self.replace_bound_vars_with_fresh_vars(
+ call_expr.span,
+ infer::FnCall,
+ &closure_ty
+ ).0;
let adjustments = autoderef.adjust_steps(Needs::None);
self.record_deferred_call_resolution(def_id, DeferredCallResolution {
call_expr,
// previously appeared within a `Binder<>` and hence would not
// have been normalized before.
let fn_sig =
- self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
+ self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig)
.0;
let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
// `liberated_sig` is E'.
{
// Instantiate (this part of..) S to S', i.e., with fresh variables.
- let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+ let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
hir_ty.span,
LateBoundRegionConversionTime::FnCall,
&ty::Binder::bind(supplied_ty),
);
}
- let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+ let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
decl.output.span(),
LateBoundRegionConversionTime::FnCall,
&supplied_sig.output(),
let mut selcx = traits::SelectionContext::new(&infcx);
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
- let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(
+ let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
impl_m_span,
infer::HigherRankedType,
&ty::Binder::bind(impl_m_own_bounds.predicates)
// Compute placeholder form of impl and trait method tys.
let tcx = infcx.tcx;
- let (impl_sig, _) =
- infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
- infer::HigherRankedType,
- &tcx.fn_sig(impl_m.def_id));
+ let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
+ impl_m_span,
+ infer::HigherRankedType,
+ &tcx.fn_sig(impl_m.def_id)
+ );
let impl_sig =
inh.normalize_associated_types_in(impl_m_span,
impl_m_node_id,
let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
let upcast_trait_ref =
- this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
+ this.replace_bound_vars_with_fresh_vars(&upcast_poly_trait_ref);
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
original_poly_trait_ref,
upcast_trait_ref,
probe::WhereClausePick(ref poly_trait_ref) => {
// Where clauses can have bound regions in them. We need to instantiate
// those to convert from a poly-trait-ref to a trait-ref.
- self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs
+ self.replace_bound_vars_with_fresh_vars(&poly_trait_ref).substs
}
}
}
// NB: Instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
- let method_sig = self.replace_late_bound_regions_with_fresh_var(&sig);
+ let method_sig = self.replace_bound_vars_with_fresh_vars(&sig);
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
method_sig);
upcast_trait_refs.into_iter().next().unwrap()
}
- fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
+ fn replace_bound_vars_with_fresh_vars<T>(&self, value: &ty::Binder<T>) -> T
where T: TypeFoldable<'tcx>
{
- self.fcx
- .replace_late_bound_regions_with_fresh_var(self.span, infer::FnCall, value)
- .0
+ self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value).0
}
}
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let fn_sig = tcx.fn_sig(def_id);
- let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
- infer::FnCall,
- &fn_sig).0;
+ let fn_sig = self.replace_bound_vars_with_fresh_vars(
+ span,
+ infer::FnCall,
+ &fn_sig
+ ).0;
let fn_sig = fn_sig.subst(self.tcx, substs);
let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) {
InferOk { value, obligations: o } => {
self.probe(|_| {
let substs = self.fresh_substs_for_item(self.span, method.def_id);
let fty = fty.subst(self.tcx, substs);
- let (fty, _) = self.replace_late_bound_regions_with_fresh_var(
- self.span, infer::FnCall, &fty);
+ let (fty, _) = self.replace_bound_vars_with_fresh_vars(
+ self.span,
+ infer::FnCall,
+ &fty
+ );
if let Some(self_ty) = self_ty {
if self.at(&ObligationCause::dummy(), self.param_env)
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
use rustc::ty::util::{Representability, IntTypeExt, Discr};
+use rustc::ty::layout::VariantIdx;
+use rustc_data_structures::indexed_vec::Idx;
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use require_c_abi_if_variadic;
}
let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
- for (discr, v) in def.discriminants(tcx).zip(vs) {
+ for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
// Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
- let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
+ let variant_did = def.variants[VariantIdx::new(i)].did;
+ let variant_i_node_id = tcx.hir.as_local_node_id(variant_did).unwrap();
let variant_i = tcx.hir.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr {
Some(ref expr) => tcx.hir.span(expr.id),
poly_trait_ref: ty::PolyTraitRef<'tcx>)
-> Ty<'tcx>
{
- let (trait_ref, _) =
- self.replace_late_bound_regions_with_fresh_var(
- span,
- infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
- &poly_trait_ref);
+ let (trait_ref, _) = self.replace_bound_vars_with_fresh_vars(
+ span,
+ infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
+ &poly_trait_ref
+ );
self.tcx().mk_projection(item_def_id, trait_ref.substs)
}
};
(
AdtKind::Struct,
- vec![convert_variant(
+ std::iter::once(convert_variant(
tcx,
ctor_id.unwrap_or(def_id),
item.name,
def,
AdtKind::Struct,
def_id
- )],
+ )).collect(),
)
}
ItemKind::Union(ref def, _) => (
AdtKind::Union,
- vec![convert_variant(
+ std::iter::once(convert_variant(
tcx,
def_id,
item.name,
def,
AdtKind::Union,
def_id
- )],
+ )).collect(),
),
_ => bug!(),
};
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {
let ty = icx.to_ty(&bound_pred.bounded_ty);
- // Keep the type around in a WF predicate, in case of no bounds.
- // That way, `where Ty:` is not a complete noop (see #53696).
+ // Keep the type around in a dummy predicate, in case of no bounds.
+ // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
+ // is still checked for WF.
if bound_pred.bounds.is_empty() {
if let ty::Param(_) = ty.sty {
// This is a `where T:`, which can be in the HIR from the
// compiler/tooling bugs from not handling WF predicates.
} else {
let span = bound_pred.bounded_ty.span;
- predicates.push((ty::Predicate::WellFormed(ty), span));
+ let predicate = ty::OutlivesPredicate(ty, tcx.mk_region(ty::ReEmpty));
+ predicates.push(
+ (ty::Predicate::TypeOutlives(ty::Binder::dummy(predicate)), span)
+ );
}
}
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::ty::subst::Substs;
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::ty::layout::VariantIdx;
use rustc::middle::stability;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_typeck::hir_ty_to_ty;
use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use std::collections::hash_map::Entry;
use std::fmt;
}
}
+impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
+ fn clean(&self, cx: &DocContext) -> IndexVec<V, U> {
+ self.iter().map(|x| x.clean(cx)).collect()
+ }
+}
+
impl<T: Clean<U>, U> Clean<U> for P<T> {
fn clean(&self, cx: &DocContext) -> U {
(**self).clean(cx)
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
Predicate::Projection(ref pred) => pred.clean(cx),
- Predicate::WellFormed(ty) => {
- // This comes from `where Ty:` (i.e. no bounds) (see #53696).
- WherePredicate::BoundPredicate {
- ty: ty.clean(cx),
- bounds: vec![],
- }
- }
- Predicate::ObjectSafe(_) => panic!("not user writable"),
- Predicate::ClosureKind(..) => panic!("not user writable"),
+
+ Predicate::WellFormed(..) |
+ Predicate::ObjectSafe(..) |
+ Predicate::ClosureKind(..) |
Predicate::ConstEvaluatable(..) => panic!("not user writable"),
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Enum {
- pub variants: Vec<Item>,
+ pub variants: IndexVec<VariantIdx, Item>,
pub generics: Generics,
pub variants_stripped: bool,
}
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: EnumItem(Enum {
- variants: self.variants.clean(cx),
+ variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
generics: self.generics.clean(cx),
variants_stripped: false,
}),
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(optin_builtin_traits)]
+
+// @has issue_55321/struct.A.html
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Send for A"
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Sync for A"
+pub struct A();
+
+impl !Send for A {}
+impl !Sync for A {}
+
+// @has issue_55321/struct.B.html
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
+// B<T>"
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Sync for \
+// B<T>"
+pub struct B<T: ?Sized>(A, Box<T>);
trait Bar where Self: Foo { }
#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<T: Bar>() {
+fn bar<T: Bar + ?Sized>() {
}
fn main() {
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
- = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
- = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
+ = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+ = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+ = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). }
error: program clause dump
--> $DIR/lower_env1.rs:19:1
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
- = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
- = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
- = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+ = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+ = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+ = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
error: aborting due to 2 previous errors
trait Foo { }
#[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct S<'a, T> where T: Foo {
+struct S<'a, T: ?Sized> where T: Foo {
data: &'a T,
}
#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<'a, T: Foo>(x: S<T>) {
+fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound
}
fn main() {
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
- = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
- = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
- = note: WellFormed(S<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(T: Foo), TypeOutlives(T : 'a).
+ = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+ = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+ = note: forall<'a, T> { WellFormed(S<'a, T>) :- Implemented(T: Foo), TypeOutlives(T: 'a). }
error: program clause dump
--> $DIR/lower_env2.rs:21:1
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
- = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
- = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
- = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
- = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
+ = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+ = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+ = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+ = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
error: aborting due to 2 previous errors
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+ = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
+ = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
error: program clause dump
--> $DIR/lower_env3.rs:20:5
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone).
- = note: Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone).
- = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+ = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
+ = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
+ = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
+ = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
error: aborting due to 2 previous errors
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+ = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }
error: program clause dump
--> $DIR/lower_impl.rs:23:5
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
+ = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). }
error: aborting due to 2 previous errors
#![feature(rustc_attrs)]
#[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct Foo<T> where Box<T>: Clone {
- _x: std::marker::PhantomData<T>,
+struct Foo<'a, T> where Box<T>: Clone {
+ _x: std::marker::PhantomData<&'a T>,
}
fn main() { }
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(T: std::marker::Sized) :- FromEnv(Foo<T>).
- = note: FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<T>).
- = note: WellFormed(Foo<T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone).
+ = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
+ = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
+ = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
+ = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
error: aborting due to previous error
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
- = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
- = note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
- = note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
+ = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). }
+ = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). }
+ = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). }
+ = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). }
error: program clause dump
--> $DIR/lower_trait.rs:17:5
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
- = note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
- = note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
+ = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+ = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+ = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }
error: aborting due to 2 previous errors
#![feature(rustc_attrs)]
#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
{
- fn s(_: F) -> F;
}
fn main() {
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
- = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
- = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
- = note: ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
- = note: WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }.
+ = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). }
+ = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). }
+ = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). }
+ = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. }
error: aborting due to previous error
#![feature(rustc_attrs)]
-use std::fmt::{Debug, Display};
use std::borrow::Borrow;
#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<'a, 'b, S, T, U>
+trait Foo<'a, 'b, T, U>
where
- S: Debug,
- T: Borrow<U>,
- U: ?Sized,
+ T: Borrow<U> + ?Sized,
+ U: ?Sized + 'b,
'a: 'b,
- U: 'b,
- Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
+ Box<T>:, // NOTE(#53696) this checks an empty list of bounds.
{
- fn s(_: S) -> S;
- fn t(_: T) -> T;
- fn u(_: U) -> U;
}
fn main() {
error: program clause dump
- --> $DIR/lower_trait_where_clause.rs:16:1
+ --> $DIR/lower_trait_where_clause.rs:15:1
|
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
- = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec<T>).
- = note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+ = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+ = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+ = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+ = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+ = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box<T>: '<empty>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+ = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box<T>: '<empty>). }
error: aborting due to previous error
--> $DIR/ub-enum.rs:61:1
|
LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something less or equal to 1114111
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
// Here: we only want the `T` to be given, the rest should be variables.
//
// (`T` refers to the declaration of `Bazoom`)
- let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+ let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
x(&22, 44, 66);
// Here: all are given
//
// (`U` refers to the declaration of `Bazoom`)
let y = 22_u32;
- y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+ y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
// Here: nothing is given, so we don't have any annotation.
let y = 22_u32;
LL | let x = foo::<u32>; //~ ERROR [u32]
| ^^^^^^^^^^
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [?0, u32, ?1], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
--> $DIR/dump-fn-method.rs:42:13
|
-LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } }
LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [?0, ?1, u32], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
--> $DIR/dump-fn-method.rs:54:5
|
-LL | y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors