Auto merge of #51895 - nikomatsakis:move-self-trait-predicate-to-items, r=scalexm
Move self trait predicate to items This is a "reimagination" of @tmandry's PR #50183. The main effect is described in this comment from one of the commits: --- Before we had the following results for `predicates_of`: ```rust trait Foo { // predicates_of: Self: Foo fn bar(); // predicates_of: Self: Foo (inherited from trait) } ``` Now we have removed the `Self: Foo` from the trait. However, we still add it to the trait ITEM. This is because when people do things like `<T as Foo>::bar()`, they still need to prove that `T: Foo`, and having it in the `predicates_of` seems to be the cleanest way to ensure that happens right now (otherwise, we'd need special case code in various places): ```rust trait Foo { // predicates_of: [] fn bar(); // predicates_of: Self: Foo } ``` However, we sometimes want to get the list of *just* the predicates truly defined on a trait item (e.g., for chalk, but also for a few other bits of code). For that, we define `predicates_defined_on`, which does not contain the `Self: Foo` predicate yet, and we plumb that through metadata and so forth. --- I'm assigning @eddyb as the main reviewer, but I thought I might delegate to scalexm for this one in any case. I also want to post an alternative that I'll leave in the comments; it occurred to me as I was writing. =) r? @eddyb cc @scalexm @tmandry @leodasvacas
This commit is contained in:
commit
8dd715ee5e
@ -504,6 +504,7 @@ define_dep_nodes!( <'tcx>
|
|||||||
[] GenericsOfItem(DefId),
|
[] GenericsOfItem(DefId),
|
||||||
[] PredicatesOfItem(DefId),
|
[] PredicatesOfItem(DefId),
|
||||||
[] ExplicitPredicatesOfItem(DefId),
|
[] ExplicitPredicatesOfItem(DefId),
|
||||||
|
[] PredicatesDefinedOnItem(DefId),
|
||||||
[] InferredOutlivesOf(DefId),
|
[] InferredOutlivesOf(DefId),
|
||||||
[] InferredOutlivesCrate(CrateNum),
|
[] InferredOutlivesCrate(CrateNum),
|
||||||
[] SuperPredicatesOfItem(DefId),
|
[] SuperPredicatesOfItem(DefId),
|
||||||
|
@ -23,7 +23,6 @@ use hir::def_id::DefId;
|
|||||||
use lint;
|
use lint;
|
||||||
use traits;
|
use traits;
|
||||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
use ty::subst::Substs;
|
|
||||||
use ty::util::ExplicitSelf;
|
use ty::util::ExplicitSelf;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
@ -173,10 +172,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
supertraits_only: bool) -> bool
|
supertraits_only: bool) -> bool
|
||||||
{
|
{
|
||||||
let trait_ref = ty::Binder::dummy(ty::TraitRef {
|
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
|
||||||
def_id: trait_def_id,
|
|
||||||
substs: Substs::identity_for_item(self, trait_def_id)
|
|
||||||
});
|
|
||||||
let predicates = if supertraits_only {
|
let predicates = if supertraits_only {
|
||||||
self.super_predicates_of(trait_def_id)
|
self.super_predicates_of(trait_def_id)
|
||||||
} else {
|
} else {
|
||||||
@ -391,10 +387,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
// Compute supertraits of current trait lazily.
|
// Compute supertraits of current trait lazily.
|
||||||
if supertraits.is_none() {
|
if supertraits.is_none() {
|
||||||
let trait_ref = ty::Binder::bind(ty::TraitRef {
|
let trait_ref = ty::Binder::bind(
|
||||||
def_id: trait_def_id,
|
ty::TraitRef::identity(self, trait_def_id),
|
||||||
substs: Substs::identity_for_item(self, trait_def_id)
|
);
|
||||||
});
|
|
||||||
supertraits = Some(traits::supertraits(self, trait_ref).collect());
|
supertraits = Some(traits::supertraits(self, trait_ref).collect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,6 +1237,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||||||
let mut candidates: Vec<EvaluatedCandidate> =
|
let mut candidates: Vec<EvaluatedCandidate> =
|
||||||
candidates?.into_iter().filter_map(|c| c).collect();
|
candidates?.into_iter().filter_map(|c| c).collect();
|
||||||
|
|
||||||
|
debug!("winnowed to {} candidates for {:?}: {:?}",
|
||||||
|
candidates.len(),
|
||||||
|
stack,
|
||||||
|
candidates);
|
||||||
|
|
||||||
// If there are STILL multiple candidate, we can further
|
// If there are STILL multiple candidate, we can further
|
||||||
// reduce the list by dropping duplicates -- including
|
// reduce the list by dropping duplicates -- including
|
||||||
// resolving specializations.
|
// resolving specializations.
|
||||||
|
@ -2862,8 +2862,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
// Compute the bounds on Self and the type parameters.
|
// Compute the bounds on Self and the type parameters.
|
||||||
|
|
||||||
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
|
let InstantiatedPredicates { predicates } =
|
||||||
let predicates = bounds.predicates;
|
tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||||
|
|
||||||
// Finally, we have to normalize the bounds in the environment, in
|
// Finally, we have to normalize the bounds in the environment, in
|
||||||
// case they contain any associated type projections. This process
|
// case they contain any associated type projections. This process
|
||||||
|
@ -101,11 +101,39 @@ define_queries! { <'tcx>
|
|||||||
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
|
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
|
||||||
|
|
||||||
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
|
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
|
||||||
/// associated generics and predicates.
|
/// associated generics.
|
||||||
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
|
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
|
||||||
|
|
||||||
|
/// Maps from the def-id of an item (trait/struct/enum/fn) to the
|
||||||
|
/// predicates (where clauses) that must be proven true in order
|
||||||
|
/// to reference it. This is almost always the "predicates query"
|
||||||
|
/// that you want.
|
||||||
|
///
|
||||||
|
/// `predicates_of` builds on `predicates_defined_on` -- in fact,
|
||||||
|
/// it is almost always the same as that query, except for the
|
||||||
|
/// case of traits. For traits, `predicates_of` contains
|
||||||
|
/// an additional `Self: Trait<...>` predicate that users don't
|
||||||
|
/// actually write. This reflects the fact that to invoke the
|
||||||
|
/// trait (e.g., via `Default::default`) you must supply types
|
||||||
|
/// that actually implement the trait. (However, this extra
|
||||||
|
/// predicate gets in the way of some checks, which are intended
|
||||||
|
/// to operate over only the actual where-clauses written by the
|
||||||
|
/// user.)
|
||||||
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
||||||
|
|
||||||
|
/// Maps from the def-id of an item (trait/struct/enum/fn) to the
|
||||||
|
/// predicates (where clauses) directly defined on it. This is
|
||||||
|
/// equal to the `explicit_predicates_of` predicates plus the
|
||||||
|
/// `inferred_outlives_of` predicates.
|
||||||
|
[] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>,
|
||||||
|
|
||||||
|
/// Returns the predicates written explicit by the user.
|
||||||
[] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
[] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
||||||
|
|
||||||
|
/// Returns the inferred outlives predicates (e.g., for `struct
|
||||||
|
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
|
||||||
|
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
|
||||||
|
|
||||||
/// Maps from the def-id of a trait to the list of
|
/// Maps from the def-id of a trait to the list of
|
||||||
/// super-predicates. This is a subset of the full list of
|
/// super-predicates. This is a subset of the full list of
|
||||||
/// predicates. We store these in a separate map because we must
|
/// predicates. We store these in a separate map because we must
|
||||||
@ -141,9 +169,6 @@ define_queries! { <'tcx>
|
|||||||
/// (inferred) variance.
|
/// (inferred) variance.
|
||||||
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
|
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
|
||||||
|
|
||||||
/// Maps from def-id of a type to its (inferred) outlives.
|
|
||||||
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
|
|
||||||
|
|
||||||
/// Maps from def-id of a type to its (inferred) outlives.
|
/// Maps from def-id of a type to its (inferred) outlives.
|
||||||
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
|
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
|
||||||
-> Lrc<ty::CratePredicatesMap<'tcx>>,
|
-> Lrc<ty::CratePredicatesMap<'tcx>>,
|
||||||
|
@ -1074,6 +1074,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
|||||||
DepKind::TypeOfItem => { force!(type_of, def_id!()); }
|
DepKind::TypeOfItem => { force!(type_of, def_id!()); }
|
||||||
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
|
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
|
||||||
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
|
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
|
||||||
|
DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
|
||||||
DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
|
DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
|
||||||
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
|
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
|
||||||
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
|
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
|
||||||
|
@ -614,6 +614,15 @@ impl<'tcx> TraitRef<'tcx> {
|
|||||||
TraitRef { def_id: def_id, substs: substs }
|
TraitRef { def_id: def_id, substs: substs }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a TraitRef of the form `P0: Foo<P1..Pn>` where `Pi`
|
||||||
|
/// are the parameters defined on trait.
|
||||||
|
pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
|
||||||
|
TraitRef {
|
||||||
|
def_id,
|
||||||
|
substs: Substs::identity_for_item(tcx, def_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn self_ty(&self) -> Ty<'tcx> {
|
pub fn self_ty(&self) -> Ty<'tcx> {
|
||||||
self.substs.type_at(0)
|
self.substs.type_at(0)
|
||||||
}
|
}
|
||||||
|
@ -518,10 +518,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
|
||||||
|
/// that closures have a def-id, but the closure *expression* also
|
||||||
|
/// has a `HirId` that is located within the context where the
|
||||||
|
/// closure appears (and, sadly, a corresponding `NodeId`, since
|
||||||
|
/// those are not yet phased out). The parent of the closure's
|
||||||
|
/// def-id will also be the context where it appears.
|
||||||
pub fn is_closure(self, def_id: DefId) -> bool {
|
pub fn is_closure(self, def_id: DefId) -> bool {
|
||||||
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
|
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`).
|
||||||
|
pub fn is_trait(self, def_id: DefId) -> bool {
|
||||||
|
if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// True if this def-id refers to the implicit constructor for
|
/// True if this def-id refers to the implicit constructor for
|
||||||
/// a tuple struct like `struct Foo(u32)`.
|
/// a tuple struct like `struct Foo(u32)`.
|
||||||
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
|
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
|
||||||
|
@ -107,6 +107,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
|||||||
tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
|
tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
|
||||||
}
|
}
|
||||||
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
|
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
|
||||||
|
predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) }
|
||||||
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
|
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
|
||||||
trait_def => {
|
trait_def => {
|
||||||
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
|
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
|
||||||
|
@ -563,6 +563,13 @@ impl<'a, 'tcx> CrateMetadata {
|
|||||||
self.entry(item_id).predicates.unwrap().decode((self, tcx))
|
self.entry(item_id).predicates.unwrap().decode((self, tcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_predicates_defined_on(&self,
|
||||||
|
item_id: DefIndex,
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
|
-> ty::GenericPredicates<'tcx> {
|
||||||
|
self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_super_predicates(&self,
|
pub fn get_super_predicates(&self,
|
||||||
item_id: DefIndex,
|
item_id: DefIndex,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
|
@ -629,6 +629,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
},
|
},
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: self.encode_optimized_mir(def_id),
|
mir: self.encode_optimized_mir(def_id),
|
||||||
}
|
}
|
||||||
@ -666,6 +667,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: None,
|
generics: None,
|
||||||
predicates: None,
|
predicates: None,
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: None
|
mir: None
|
||||||
}
|
}
|
||||||
@ -706,6 +708,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: None,
|
mir: None,
|
||||||
}
|
}
|
||||||
@ -763,6 +766,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
},
|
},
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: self.encode_optimized_mir(def_id),
|
mir: self.encode_optimized_mir(def_id),
|
||||||
}
|
}
|
||||||
@ -780,6 +784,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
self.lazy(&tcx.predicates_of(def_id))
|
self.lazy(&tcx.predicates_of(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
|
||||||
|
debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
|
||||||
|
let tcx = self.tcx;
|
||||||
|
self.lazy(&tcx.predicates_defined_on(def_id))
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||||
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
|
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
@ -869,6 +879,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
},
|
},
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: self.encode_optimized_mir(def_id),
|
mir: self.encode_optimized_mir(def_id),
|
||||||
}
|
}
|
||||||
@ -965,6 +976,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
},
|
},
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: if mir { self.encode_optimized_mir(def_id) } else { None },
|
mir: if mir { self.encode_optimized_mir(def_id) } else { None },
|
||||||
}
|
}
|
||||||
@ -1228,6 +1240,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// The only time that `predicates_defined_on` is used (on
|
||||||
|
// an external item) is for traits, during chalk lowering,
|
||||||
|
// so only encode it in that case as an efficiency
|
||||||
|
// hack. (No reason not to expand it in the future if
|
||||||
|
// necessary.)
|
||||||
|
predicates_defined_on: match item.node {
|
||||||
|
hir::ItemTrait(..) => Some(self.encode_predicates_defined_on(def_id)),
|
||||||
|
_ => None, // not *wrong* for other kinds of items, but not needed
|
||||||
|
},
|
||||||
|
|
||||||
mir: match item.node {
|
mir: match item.node {
|
||||||
hir::ItemStatic(..) => {
|
hir::ItemStatic(..) => {
|
||||||
self.encode_optimized_mir(def_id)
|
self.encode_optimized_mir(def_id)
|
||||||
@ -1278,6 +1300,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: None,
|
generics: None,
|
||||||
predicates: None,
|
predicates: None,
|
||||||
|
predicates_defined_on: None,
|
||||||
mir: None,
|
mir: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1305,6 +1328,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: None,
|
generics: None,
|
||||||
predicates: None,
|
predicates: None,
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: None,
|
mir: None,
|
||||||
}
|
}
|
||||||
@ -1349,6 +1373,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: None,
|
predicates: None,
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: self.encode_optimized_mir(def_id),
|
mir: self.encode_optimized_mir(def_id),
|
||||||
}
|
}
|
||||||
@ -1376,6 +1401,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: self.encode_optimized_mir(def_id),
|
mir: self.encode_optimized_mir(def_id),
|
||||||
}
|
}
|
||||||
@ -1577,6 +1603,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
},
|
},
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
predicates: Some(self.encode_predicates(def_id)),
|
predicates: Some(self.encode_predicates(def_id)),
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
mir: None,
|
mir: None,
|
||||||
}
|
}
|
||||||
|
@ -273,6 +273,7 @@ pub struct Entry<'tcx> {
|
|||||||
pub variances: LazySeq<ty::Variance>,
|
pub variances: LazySeq<ty::Variance>,
|
||||||
pub generics: Option<Lazy<ty::Generics>>,
|
pub generics: Option<Lazy<ty::Generics>>,
|
||||||
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
|
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
|
||||||
|
pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
|
||||||
|
|
||||||
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
|
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
|
||||||
}
|
}
|
||||||
@ -290,6 +291,7 @@ impl_stable_hash_for!(struct Entry<'tcx> {
|
|||||||
variances,
|
variances,
|
||||||
generics,
|
generics,
|
||||||
predicates,
|
predicates,
|
||||||
|
predicates_defined_on,
|
||||||
mir
|
mir
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ use rustc::hir::{self, ImplPolarity};
|
|||||||
use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
|
use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
|
||||||
WhereClause, FromEnv, WellFormed};
|
WhereClause, FromEnv, WellFormed};
|
||||||
use rustc::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
use rustc::ty::subst::Substs;
|
|
||||||
use rustc::ty::{self, Slice, TyCtxt};
|
use rustc::ty::{self, Slice, TyCtxt};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -225,10 +224,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
|
|||||||
|
|
||||||
// `Self: Trait<P1..Pn>`
|
// `Self: Trait<P1..Pn>`
|
||||||
let trait_pred = ty::TraitPredicate {
|
let trait_pred = ty::TraitPredicate {
|
||||||
trait_ref: ty::TraitRef {
|
trait_ref: ty::TraitRef::identity(tcx, def_id),
|
||||||
def_id,
|
|
||||||
substs: Substs::identity_for_item(tcx, def_id),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// `Implemented(Self: Trait<P1..Pn>)`
|
// `Implemented(Self: Trait<P1..Pn>)`
|
||||||
@ -256,10 +252,8 @@ fn program_clauses_for_trait<'a, 'tcx>(
|
|||||||
// ```
|
// ```
|
||||||
|
|
||||||
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
|
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
|
||||||
// FIXME: Remove the [1..] slice; this is a hack because the query
|
let where_clauses = &tcx.predicates_defined_on(def_id).predicates;
|
||||||
// predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
|
let implied_bound_clauses = where_clauses
|
||||||
let where_clauses = &tcx.predicates_of(def_id).predicates;
|
|
||||||
let implied_bound_clauses = where_clauses[1..]
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|wc| wc.lower())
|
.map(|wc| wc.lower())
|
||||||
|
|
||||||
|
@ -364,15 +364,16 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks where clauses and inline bounds that are declared on def_id.
|
/// Checks where clauses and inline bounds that are declared on def_id.
|
||||||
fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
|
||||||
|
tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||||
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
|
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
def_id: DefId) {
|
def_id: DefId,
|
||||||
|
) {
|
||||||
use ty::subst::Subst;
|
use ty::subst::Subst;
|
||||||
use rustc::ty::TypeFoldable;
|
use rustc::ty::TypeFoldable;
|
||||||
|
|
||||||
let mut predicates = fcx.tcx.predicates_of(def_id);
|
let predicates = fcx.tcx.predicates_of(def_id);
|
||||||
let mut substituted_predicates = Vec::new();
|
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
let is_our_default = |def: &ty::GenericParamDef| {
|
let is_our_default = |def: &ty::GenericParamDef| {
|
||||||
@ -433,7 +434,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Now we build the substituted predicates.
|
// Now we build the substituted predicates.
|
||||||
for &pred in predicates.predicates.iter() {
|
let default_obligations = predicates.predicates.iter().flat_map(|&pred| {
|
||||||
struct CountParams { params: FxHashSet<u32> }
|
struct CountParams { params: FxHashSet<u32> }
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||||
@ -455,21 +456,37 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||||||
let substituted_pred = pred.subst(fcx.tcx, substs);
|
let substituted_pred = pred.subst(fcx.tcx, substs);
|
||||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||||
// or preds with multiple params.
|
// or preds with multiple params.
|
||||||
if substituted_pred.references_error() || param_count.params.len() > 1
|
if {
|
||||||
|| has_region {
|
substituted_pred.references_error() || param_count.params.len() > 1
|
||||||
continue;
|
|| has_region
|
||||||
}
|
} {
|
||||||
|
None
|
||||||
|
} else if predicates.predicates.contains(&substituted_pred) {
|
||||||
// Avoid duplication of predicates that contain no parameters, for example.
|
// Avoid duplication of predicates that contain no parameters, for example.
|
||||||
if !predicates.predicates.contains(&substituted_pred) {
|
None
|
||||||
substituted_predicates.push(substituted_pred);
|
} else {
|
||||||
}
|
Some(substituted_pred)
|
||||||
}
|
}
|
||||||
|
}).map(|pred| {
|
||||||
|
// convert each of those into an obligation. So if you have
|
||||||
|
// something like `struct Foo<T: Copy = String>`, we would
|
||||||
|
// take that predicate `T: Copy`, substitute to `String: Copy`
|
||||||
|
// (actually that happens in the previous `flat_map` call),
|
||||||
|
// and then try to prove it (in this case, we'll fail).
|
||||||
|
//
|
||||||
|
// Note the subtle difference from how we handle `predicates`
|
||||||
|
// below: there, we are not trying to prove those predicates
|
||||||
|
// to be *true* but merely *well-formed*.
|
||||||
|
let pred = fcx.normalize_associated_types_in(span, &pred);
|
||||||
|
let cause = traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def_id));
|
||||||
|
traits::Obligation::new(cause, fcx.param_env, pred)
|
||||||
|
});
|
||||||
|
|
||||||
predicates.predicates.extend(substituted_predicates);
|
|
||||||
let predicates = predicates.instantiate_identity(fcx.tcx);
|
let predicates = predicates.instantiate_identity(fcx.tcx);
|
||||||
let predicates = fcx.normalize_associated_types_in(span, &predicates);
|
let predicates = fcx.normalize_associated_types_in(span, &predicates);
|
||||||
|
|
||||||
let obligations =
|
debug!("check_where_clauses: predicates={:?}", predicates.predicates);
|
||||||
|
let wf_obligations =
|
||||||
predicates.predicates
|
predicates.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|p| ty::wf::predicate_obligations(fcx,
|
.flat_map(|p| ty::wf::predicate_obligations(fcx,
|
||||||
@ -478,7 +495,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||||||
p,
|
p,
|
||||||
span));
|
span));
|
||||||
|
|
||||||
for obligation in obligations {
|
for obligation in wf_obligations.chain(default_obligations) {
|
||||||
|
debug!("next obligation cause: {:?}", obligation.cause);
|
||||||
fcx.register_predicate(obligation);
|
fcx.register_predicate(obligation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
type_of,
|
type_of,
|
||||||
generics_of,
|
generics_of,
|
||||||
predicates_of,
|
predicates_of,
|
||||||
|
predicates_defined_on,
|
||||||
explicit_predicates_of,
|
explicit_predicates_of,
|
||||||
super_predicates_of,
|
super_predicates_of,
|
||||||
type_param_predicates,
|
type_param_predicates,
|
||||||
@ -274,10 +275,9 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
ItemTrait(_, _, ref generics, ..) => {
|
ItemTrait(_, _, ref generics, ..) => {
|
||||||
// Implied `Self: Trait` and supertrait bounds.
|
// Implied `Self: Trait` and supertrait bounds.
|
||||||
if param_id == item_node_id {
|
if param_id == item_node_id {
|
||||||
result.predicates.push(ty::TraitRef {
|
result.predicates.push(
|
||||||
def_id: item_def_id,
|
ty::TraitRef::identity(tcx, item_def_id).to_predicate()
|
||||||
substs: Substs::identity_for_item(tcx, item_def_id)
|
);
|
||||||
}.to_predicate());
|
|
||||||
}
|
}
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
@ -1306,10 +1306,10 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> ty::GenericPredicates<'tcx> {
|
-> ty::GenericPredicates<'tcx> {
|
||||||
let explicit = explicit_predicates_of(tcx, def_id);
|
let explicit = tcx.explicit_predicates_of(def_id);
|
||||||
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
|
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
|
||||||
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
|
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
|
||||||
} else { explicit.predicates };
|
} else { explicit.predicates };
|
||||||
@ -1320,9 +1320,35 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> ty::GenericPredicates<'tcx> {
|
-> ty::GenericPredicates<'tcx> {
|
||||||
|
let ty::GenericPredicates { parent, mut predicates } =
|
||||||
|
tcx.predicates_defined_on(def_id);
|
||||||
|
|
||||||
|
if tcx.is_trait(def_id) {
|
||||||
|
// For traits, add `Self: Trait` predicate. This is
|
||||||
|
// not part of the predicates that a user writes, but it
|
||||||
|
// is something that one must prove in order to invoke a
|
||||||
|
// method or project an associated type.
|
||||||
|
//
|
||||||
|
// In the chalk setup, this predicate is not part of the
|
||||||
|
// "predicates" for a trait item. But it is useful in
|
||||||
|
// rustc because if you directly (e.g.) invoke a trait
|
||||||
|
// method like `Trait::method(...)`, you must naturally
|
||||||
|
// prove that the trait applies to the types that were
|
||||||
|
// used, and adding the predicate into this list ensures
|
||||||
|
// that this is done.
|
||||||
|
predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::GenericPredicates { parent, predicates }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_predicates_of<'a, 'tcx>(
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> ty::GenericPredicates<'tcx> {
|
||||||
use rustc::hir::map::*;
|
use rustc::hir::map::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
|
|
||||||
@ -1337,7 +1363,10 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
let no_generics = hir::Generics::empty();
|
let no_generics = hir::Generics::empty();
|
||||||
let ast_generics = match node {
|
let ast_generics = match node {
|
||||||
NodeTraitItem(item) => &item.generics,
|
NodeTraitItem(item) => {
|
||||||
|
&item.generics
|
||||||
|
}
|
||||||
|
|
||||||
NodeImplItem(item) => &item.generics,
|
NodeImplItem(item) => &item.generics,
|
||||||
|
|
||||||
NodeItem(item) => {
|
NodeItem(item) => {
|
||||||
@ -1355,10 +1384,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
ItemUnion(_, ref generics) => generics,
|
ItemUnion(_, ref generics) => generics,
|
||||||
|
|
||||||
ItemTrait(_, _, ref generics, .., ref items) => {
|
ItemTrait(_, _, ref generics, .., ref items) => {
|
||||||
is_trait = Some((ty::TraitRef {
|
is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
|
||||||
def_id,
|
|
||||||
substs: Substs::identity_for_item(tcx, def_id)
|
|
||||||
}, items));
|
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
ItemExistential(ref exist_ty) => {
|
ItemExistential(ref exist_ty) => {
|
||||||
@ -1405,12 +1431,8 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
// and the explicit where-clauses, but to get the full set of predicates
|
// and the explicit where-clauses, but to get the full set of predicates
|
||||||
// on a trait we need to add in the supertrait bounds and bounds found on
|
// on a trait we need to add in the supertrait bounds and bounds found on
|
||||||
// associated types.
|
// associated types.
|
||||||
if let Some((trait_ref, _)) = is_trait {
|
if let Some((_trait_ref, _)) = is_trait {
|
||||||
predicates = tcx.super_predicates_of(def_id).predicates;
|
predicates = tcx.super_predicates_of(def_id).predicates;
|
||||||
|
|
||||||
// Add in a predicate that `Self:Trait` (where `Trait` is the
|
|
||||||
// current trait). This is needed for builtin bounds.
|
|
||||||
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// In default impls, we can assume that the self type implements
|
// In default impls, we can assume that the self type implements
|
||||||
|
@ -4,7 +4,7 @@ error: program clause dump
|
|||||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
||||||
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
||||||
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
|
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ error: program clause dump
|
|||||||
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
|
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
||||||
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
|
||||||
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
|
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
|
||||||
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
|
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
|
||||||
|
@ -30,7 +30,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa
|
|||||||
LL | struct Bounds<T:Copy=String>(T);
|
LL | struct Bounds<T:Copy=String>(T);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
||||||
|
|
|
|
||||||
= note: required by `std::marker::Copy`
|
note: required by `Bounds`
|
||||||
|
--> $DIR/type-check-defaults.rs:21:1
|
||||||
|
|
|
||||||
|
LL | struct Bounds<T:Copy=String>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
||||||
--> $DIR/type-check-defaults.rs:24:1
|
--> $DIR/type-check-defaults.rs:24:1
|
||||||
@ -38,7 +42,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa
|
|||||||
LL | struct WhereClause<T=String>(T) where T: Copy;
|
LL | struct WhereClause<T=String>(T) where T: Copy;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
||||||
|
|
|
|
||||||
= note: required by `std::marker::Copy`
|
note: required by `WhereClause`
|
||||||
|
--> $DIR/type-check-defaults.rs:24:1
|
||||||
|
|
|
||||||
|
LL | struct WhereClause<T=String>(T) where T: Copy;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
||||||
--> $DIR/type-check-defaults.rs:27:1
|
--> $DIR/type-check-defaults.rs:27:1
|
||||||
@ -46,7 +54,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa
|
|||||||
LL | trait TraitBound<T:Copy=String> {}
|
LL | trait TraitBound<T:Copy=String> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
||||||
|
|
|
|
||||||
= note: required by `std::marker::Copy`
|
note: required by `TraitBound`
|
||||||
|
--> $DIR/type-check-defaults.rs:27:1
|
||||||
|
|
|
||||||
|
LL | trait TraitBound<T:Copy=String> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||||
--> $DIR/type-check-defaults.rs:31:1
|
--> $DIR/type-check-defaults.rs:31:1
|
||||||
@ -68,7 +80,11 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
|
||||||
|
|
|
|
||||||
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
|
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
|
||||||
= note: required by `std::ops::Add`
|
note: required by `ProjectionPred`
|
||||||
|
--> $DIR/type-check-defaults.rs:34:1
|
||||||
|
|
|
||||||
|
LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user