1
Fork 0

rustc: keep a Span for each predicate in ty::GenericPredicates.

This commit is contained in:
Eduard-Mihai Burtescu 2018-09-16 20:15:49 +03:00
parent c222479c6f
commit 7020326bea
33 changed files with 265 additions and 290 deletions

View file

@ -297,12 +297,15 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let assoc_item = tcx.associated_item(assoc_item_def_id); let assoc_item = tcx.associated_item(assoc_item_def_id);
let trait_def_id = assoc_item.container.assert_trait(); let trait_def_id = assoc_item.container.assert_trait();
let trait_predicates = tcx.predicates_of(trait_def_id); let trait_predicates = tcx.predicates_of(trait_def_id).predicates
.into_iter()
.map(|(p, _)| p)
.collect();
let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id); let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
self.collect_outlives_from_predicate_list( self.collect_outlives_from_predicate_list(
move |ty| ty == identity_proj, move |ty| ty == identity_proj,
traits::elaborate_predicates(tcx, trait_predicates.predicates), traits::elaborate_predicates(tcx, trait_predicates),
).map(|b| b.1) ).map(|b| b.1)
} }

View file

@ -96,10 +96,10 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, '
let header = ty::ImplHeader { let header = ty::ImplHeader {
impl_def_id, impl_def_id,
self_ty: tcx.type_of(impl_def_id), self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
trait_ref: tcx.impl_trait_ref(impl_def_id), trait_ref: tcx.impl_trait_ref(impl_def_id).subst(tcx, impl_substs),
predicates: tcx.predicates_of(impl_def_id).predicates predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
}.subst(tcx, impl_substs); };
let Normalized { value: mut header, obligations } = let Normalized { value: mut header, obligations } =
traits::normalize(selcx, param_env, ObligationCause::dummy(), &header); traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);

View file

@ -816,11 +816,10 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
key: (DefId, &'tcx Substs<'tcx>)) key: (DefId, &'tcx Substs<'tcx>))
-> bool -> bool
{ {
use ty::subst::Subst;
debug!("substitute_normalize_and_test_predicates(key={:?})", debug!("substitute_normalize_and_test_predicates(key={:?})",
key); key);
let predicates = tcx.predicates_of(key.0).predicates.subst(tcx, key.1); let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
let result = normalize_and_test_predicates(tcx, predicates); let result = normalize_and_test_predicates(tcx, predicates);
debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}",

View file

@ -179,7 +179,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
predicates predicates
.predicates .predicates
.into_iter() .into_iter()
.map(|predicate| predicate.subst_supertrait(self, &trait_ref)) .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref))
.any(|predicate| { .any(|predicate| {
match predicate { match predicate {
ty::Predicate::Trait(ref data) => { ty::Predicate::Trait(ref data) => {
@ -311,7 +311,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
if self.predicates_of(method.def_id).predicates.into_iter() if self.predicates_of(method.def_id).predicates.into_iter()
// A trait object can't claim to live more than the concrete type, // A trait object can't claim to live more than the concrete type,
// so outlives predicates will always hold. // so outlives predicates will always hold.
.filter(|p| p.to_opt_type_outlives().is_none()) .filter(|(p, _)| p.to_opt_type_outlives().is_none())
.collect::<Vec<_>>() .collect::<Vec<_>>()
// Do a shallow visit so that `contains_illegal_self_type_reference` // Do a shallow visit so that `contains_illegal_self_type_reference`
// may apply it's custom visiting. // may apply it's custom visiting.

View file

@ -3401,7 +3401,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// that order. // that order.
let predicates = tcx.predicates_of(def_id); let predicates = tcx.predicates_of(def_id);
assert_eq!(predicates.parent, None); assert_eq!(predicates.parent, None);
let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|predicate| { let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|(predicate, _)| {
let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth, let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth,
&predicate.subst(tcx, substs)); &predicate.subst(tcx, substs));
predicate.obligations.into_iter().chain( predicate.obligations.into_iter().chain(

View file

@ -428,7 +428,7 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
let mut pretty_predicates = Vec::with_capacity( let mut pretty_predicates = Vec::with_capacity(
predicates.len() + types_without_default_bounds.len()); predicates.len() + types_without_default_bounds.len());
for p in predicates { for (p, _) in predicates {
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
if Some(poly_trait_ref.def_id()) == sized_trait { if Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(poly_trait_ref.self_ty()); types_without_default_bounds.remove(poly_trait_ref.self_ty());

View file

@ -137,7 +137,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
let mut predicates: Vec<_> = let mut predicates: Vec<_> =
predicates.predicates predicates.predicates
.iter() .iter()
.map(|p| p.subst_supertrait(tcx, &data.to_poly_trait_ref())) .map(|(p, _)| p.subst_supertrait(tcx, &data.to_poly_trait_ref()))
.collect(); .collect();
debug!("super_predicates: data={:?} predicates={:?}", debug!("super_predicates: data={:?} predicates={:?}",
@ -311,7 +311,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> {
self.stack.extend( self.stack.extend(
predicates.predicates predicates.predicates
.iter() .iter()
.filter_map(|p| p.to_opt_poly_trait_ref()) .filter_map(|(p, _)| p.to_opt_poly_trait_ref())
.map(|t| t.def_id()) .map(|t| t.def_id())
.filter(|&super_def_id| visited.insert(super_def_id))); .filter(|&super_def_id| visited.insert(super_def_id)));
Some(def_id) Some(def_id)

View file

@ -109,8 +109,9 @@ pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
{ {
predicates.parent.encode(encoder)?; predicates.parent.encode(encoder)?;
predicates.predicates.len().encode(encoder)?; predicates.predicates.len().encode(encoder)?;
for predicate in &predicates.predicates { for (predicate, span) in &predicates.predicates {
encode_with_shorthand(encoder, predicate, &cache)? encode_with_shorthand(encoder, predicate, &cache)?;
span.encode(encoder)?;
} }
Ok(()) Ok(())
} }
@ -178,7 +179,7 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
parent: Decodable::decode(decoder)?, parent: Decodable::decode(decoder)?,
predicates: (0..decoder.read_usize()?).map(|_| { predicates: (0..decoder.read_usize()?).map(|_| {
// Handle shorthands first, if we have an usize > 0x80. // Handle shorthands first, if we have an usize > 0x80.
if decoder.positioned_at_shorthand() { let predicate = if decoder.positioned_at_shorthand() {
let pos = decoder.read_usize()?; let pos = decoder.read_usize()?;
assert!(pos >= SHORTHAND_OFFSET); assert!(pos >= SHORTHAND_OFFSET);
let shorthand = pos - SHORTHAND_OFFSET; let shorthand = pos - SHORTHAND_OFFSET;
@ -186,7 +187,8 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
decoder.with_position(shorthand, ty::Predicate::decode) decoder.with_position(shorthand, ty::Predicate::decode)
} else { } else {
ty::Predicate::decode(decoder) ty::Predicate::decode(decoder)
} }?;
Ok((predicate, Decodable::decode(decoder)?))
}) })
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
}) })

View file

@ -982,7 +982,7 @@ impl<'a, 'gcx, 'tcx> Generics {
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct GenericPredicates<'tcx> { pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>, pub parent: Option<DefId>,
pub predicates: Vec<Predicate<'tcx>>, pub predicates: Vec<(Predicate<'tcx>, Span)>,
} }
impl<'tcx> serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} impl<'tcx> serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {}
@ -998,7 +998,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> { -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates { InstantiatedPredicates {
predicates: self.predicates.subst(tcx, substs) predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(),
} }
} }
@ -1008,7 +1008,9 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
if let Some(def_id) = self.parent { if let Some(def_id) = self.parent {
tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
} }
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs))) instantiated.predicates.extend(
self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)),
);
} }
pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
@ -1023,7 +1025,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
if let Some(def_id) = self.parent { if let Some(def_id) = self.parent {
tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
} }
instantiated.predicates.extend(&self.predicates) instantiated.predicates.extend(self.predicates.iter().map(|&(p, _)| p))
} }
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
@ -1032,7 +1034,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
{ {
assert_eq!(self.parent, None); assert_eq!(self.parent, None);
InstantiatedPredicates { InstantiatedPredicates {
predicates: self.predicates.iter().map(|pred| { predicates: self.predicates.iter().map(|(pred, _)| {
pred.subst_supertrait(tcx, poly_trait_ref) pred.subst_supertrait(tcx, poly_trait_ref)
}).collect() }).collect()
} }
@ -2351,7 +2353,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
substs: tcx.mk_substs_trait(ty, &[]) substs: tcx.mk_substs_trait(ty, &[])
}).to_predicate(); }).to_predicate();
let predicates = tcx.predicates_of(self.did).predicates; let predicates = tcx.predicates_of(self.did).predicates;
if predicates.into_iter().any(|p| p == sized_predicate) { if predicates.into_iter().any(|(p, _)| p == sized_predicate) {
vec![] vec![]
} else { } else {
vec![ty] vec![ty]

View file

@ -1736,8 +1736,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
if cx.tcx.features().trivial_bounds { if cx.tcx.features().trivial_bounds {
let def_id = cx.tcx.hir.local_def_id(item.id); let def_id = cx.tcx.hir.local_def_id(item.id);
let predicates = cx.tcx.predicates_of(def_id); let predicates = cx.tcx.predicates_of(def_id);
for predicate in &predicates.predicates { for &(predicate, span) in &predicates.predicates {
let predicate_kind_name = match *predicate { let predicate_kind_name = match predicate {
Trait(..) => "Trait", Trait(..) => "Trait",
TypeOutlives(..) | TypeOutlives(..) |
RegionOutlives(..) => "Lifetime", RegionOutlives(..) => "Lifetime",
@ -1755,7 +1755,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
if predicate.is_global() { if predicate.is_global() {
cx.span_lint( cx.span_lint(
TRIVIAL_BOUNDS, TRIVIAL_BOUNDS,
item.span, span,
&format!("{} bound {} does not depend on any type \ &format!("{} bound {} does not depend on any type \
or lifetime parameters", predicate_kind_name, predicate), or lifetime parameters", predicate_kind_name, predicate),
); );

View file

@ -15,7 +15,7 @@ pub fn is_min_const_fn(
let mut current = def_id; let mut current = def_id;
loop { loop {
let predicates = tcx.predicates_of(current); let predicates = tcx.predicates_of(current);
for predicate in &predicates.predicates { for (predicate, _) in &predicates.predicates {
match predicate { match predicate {
| Predicate::RegionOutlives(_) | Predicate::RegionOutlives(_)
| Predicate::TypeOutlives(_) | Predicate::TypeOutlives(_)

View file

@ -434,7 +434,7 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
fn predicates(&mut self) -> &mut Self { fn predicates(&mut self) -> &mut Self {
let predicates = self.ev.tcx.predicates_of(self.item_def_id); let predicates = self.ev.tcx.predicates_of(self.item_def_id);
for predicate in &predicates.predicates { for (predicate, _) in &predicates.predicates {
predicate.visit_with(self); predicate.visit_with(self);
match predicate { match predicate {
&ty::Predicate::Trait(poly_predicate) => { &ty::Predicate::Trait(poly_predicate) => {
@ -781,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
if self.check_trait_ref(*principal.skip_binder()) { if self.check_trait_ref(*principal.skip_binder()) {
return; return;
} }
for poly_predicate in projections { for (poly_predicate, _) in projections {
let tcx = self.tcx; let tcx = self.tcx;
if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) {
return; return;
@ -956,7 +956,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
} }
} }
ty::Opaque(def_id, ..) => { ty::Opaque(def_id, ..) => {
for predicate in &self.tcx.predicates_of(def_id).predicates { for (predicate, _) in &self.tcx.predicates_of(def_id).predicates {
let trait_ref = match *predicate { let trait_ref = match *predicate {
ty::Predicate::Trait(ref poly_trait_predicate) => { ty::Predicate::Trait(ref poly_trait_predicate) => {
Some(poly_trait_predicate.skip_binder().trait_ref) Some(poly_trait_predicate.skip_binder().trait_ref)
@ -1387,7 +1387,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
// for the inferred outlives rules; see // for the inferred outlives rules; see
// `src/test/ui/rfc-2093-infer-outlives/privacy.rs`. // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`.
let predicates = self.tcx.explicit_predicates_of(self.item_def_id); let predicates = self.tcx.explicit_predicates_of(self.item_def_id);
for predicate in &predicates.predicates { for (predicate, _) in &predicates.predicates {
predicate.visit_with(self); predicate.visit_with(self);
match predicate { match predicate {
&ty::Predicate::Trait(poly_predicate) => { &ty::Predicate::Trait(poly_predicate) => {

View file

@ -260,7 +260,10 @@ fn program_clauses_for_trait<'a, 'tcx>(
let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env))); let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
let where_clauses = &tcx.predicates_defined_on(def_id).predicates; let where_clauses = &tcx.predicates_defined_on(def_id).predicates
.into_iter()
.map(|(wc, _)| wc.lower())
.collect::<Vec<_>>();
// Rule Implied-Bound-From-Trait // Rule Implied-Bound-From-Trait
// //
@ -273,8 +276,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
let implied_bound_clauses = where_clauses let implied_bound_clauses = where_clauses
.into_iter() .iter()
.map(|wc| wc.lower()) .cloned()
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)` // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
.map(|wc| wc.map_bound(|goal| ProgramClause { .map(|wc| wc.map_bound(|goal| ProgramClause {
@ -296,8 +299,8 @@ fn program_clauses_for_trait<'a, 'tcx>(
let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower())) let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower()))
.chain( .chain(
where_clauses where_clauses
.into_iter() .iter()
.map(|wc| wc.lower()) .cloned()
.map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal())) .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()))
); );
@ -338,7 +341,10 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
let trait_pred = ty::TraitPredicate { trait_ref }.lower(); let trait_pred = ty::TraitPredicate { trait_ref }.lower();
// `WC` // `WC`
let where_clauses = tcx.predicates_of(def_id).predicates.lower(); let where_clauses = tcx.predicates_of(def_id).predicates
.into_iter()
.map(|(wc, _)| wc.lower())
.collect::<Vec<_>>();
// `Implemented(A0: Trait<A1..An>) :- WC` // `Implemented(A0: Trait<A1..An>) :- WC`
let clause = ProgramClause { let clause = ProgramClause {
@ -370,7 +376,10 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
let ty = tcx.type_of(def_id); let ty = tcx.type_of(def_id);
// `WC` // `WC`
let where_clauses = tcx.predicates_of(def_id).predicates.lower(); let where_clauses = tcx.predicates_of(def_id).predicates
.into_iter()
.map(|(wc, _)| wc.lower())
.collect::<Vec<_>>();
// `WellFormed(Ty<...>) :- WC1, ..., WCm` // `WellFormed(Ty<...>) :- WC1, ..., WCm`
let well_formed = ProgramClause { let well_formed = ProgramClause {

View file

@ -693,7 +693,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
pub(super) fn instantiate_poly_trait_ref_inner(&self, pub(super) fn instantiate_poly_trait_ref_inner(&self,
trait_ref: &hir::TraitRef, trait_ref: &hir::TraitRef,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>, poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
speculative: bool) speculative: bool)
-> ty::PolyTraitRef<'tcx> -> ty::PolyTraitRef<'tcx>
{ {
@ -716,7 +716,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let predicate: Result<_, ErrorReported> = let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate( self.ast_type_binding_to_poly_projection_predicate(
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings); trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
predicate.ok() // ok to ignore Err() because ErrorReported (see above) // ok to ignore Err() because ErrorReported (see above)
Some((predicate.ok()?, binding.span))
})); }));
debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}", debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
@ -727,7 +728,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
pub fn instantiate_poly_trait_ref(&self, pub fn instantiate_poly_trait_ref(&self,
poly_trait_ref: &hir::PolyTraitRef, poly_trait_ref: &hir::PolyTraitRef,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>) poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>)
-> ty::PolyTraitRef<'tcx> -> ty::PolyTraitRef<'tcx>
{ {
self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty,
@ -974,7 +975,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let existential_principal = principal.map_bound(|trait_ref| { let existential_principal = principal.map_bound(|trait_ref| {
self.trait_ref_to_existential(trait_ref) self.trait_ref_to_existential(trait_ref)
}); });
let existential_projections = projection_bounds.iter().map(|bound| { let existential_projections = projection_bounds.iter().map(|(bound, _)| {
bound.map_bound(|b| { bound.map_bound(|b| {
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
ty::ExistentialProjection { ty::ExistentialProjection {
@ -1006,7 +1007,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
.map(|item| item.def_id)); .map(|item| item.def_id));
} }
for projection_bound in &projection_bounds { for (projection_bound, _) in &projection_bounds {
associated_types.remove(&projection_bound.projection_def_id()); associated_types.remove(&projection_bound.projection_def_id());
} }
@ -1089,7 +1090,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let tcx = self.tcx(); let tcx = self.tcx();
let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id) let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id)
.predicates.into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect(); .predicates.into_iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()).collect();
// Check that there is exactly one way to find an associated type with the // Check that there is exactly one way to find an associated type with the
// correct name. // correct name.
@ -1701,42 +1702,41 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// and return from functions in multiple places. // and return from functions in multiple places.
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> { pub struct Bounds<'tcx> {
pub region_bounds: Vec<ty::Region<'tcx>>, pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
pub implicitly_sized: bool, pub implicitly_sized: Option<Span>,
pub trait_bounds: Vec<ty::PolyTraitRef<'tcx>>, pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>,
pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
} }
impl<'a, 'gcx, 'tcx> Bounds<'tcx> { impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>) pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
-> Vec<ty::Predicate<'tcx>> -> Vec<(ty::Predicate<'tcx>, Span)>
{ {
// If it could be sized, and is, add the sized predicate // If it could be sized, and is, add the sized predicate
let sized_predicate = if self.implicitly_sized { let sized_predicate = self.implicitly_sized.and_then(|span| {
tcx.lang_items().sized_trait().map(|sized| { tcx.lang_items().sized_trait().map(|sized| {
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: sized, def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]) substs: tcx.mk_substs_trait(param_ty, &[])
}; };
trait_ref.to_predicate() (trait_ref.to_predicate(), span)
}) })
} else { });
None
};
sized_predicate.into_iter().chain( sized_predicate.into_iter().chain(
self.region_bounds.iter().map(|&region_bound| { self.region_bounds.iter().map(|&(region_bound, span)| {
// account for the binder being introduced below; no need to shift `param_ty` // account for the binder being introduced below; no need to shift `param_ty`
// because, at present at least, it can only refer to early-bound regions // because, at present at least, it can only refer to early-bound regions
let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1)); let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
ty::Binder::dummy(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate() let outlives = ty::OutlivesPredicate(param_ty, region_bound);
(ty::Binder::dummy(outlives).to_predicate(), span)
}).chain( }).chain(
self.trait_bounds.iter().map(|bound_trait_ref| { self.trait_bounds.iter().map(|&(bound_trait_ref, span)| {
bound_trait_ref.to_predicate() (bound_trait_ref.to_predicate(), span)
}) })
).chain( ).chain(
self.projection_bounds.iter().map(|projection| { self.projection_bounds.iter().map(|&(projection, span)| {
projection.to_predicate() (projection.to_predicate(), span)
}) })
) )
).collect() ).collect()

View file

@ -212,7 +212,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
// just to look for all the predicates directly. // just to look for all the predicates directly.
assert_eq!(dtor_predicates.parent, None); assert_eq!(dtor_predicates.parent, None);
for predicate in &dtor_predicates.predicates { for (predicate, _) in &dtor_predicates.predicates {
// (We do not need to worry about deep analysis of type // (We do not need to worry about deep analysis of type
// expressions etc because the Drop impls are already forced // expressions etc because the Drop impls are already forced
// to take on a structure that is roughly an alpha-renaming of // to take on a structure that is roughly an alpha-renaming of

View file

@ -1875,14 +1875,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
let index = generics.param_def_id_to_index[&def_id]; let index = generics.param_def_id_to_index[&def_id];
ty::GenericPredicates { ty::GenericPredicates {
parent: None, parent: None,
predicates: self.param_env.caller_bounds.iter().filter(|predicate| { predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| {
match **predicate { match predicate {
ty::Predicate::Trait(ref data) => { ty::Predicate::Trait(ref data)
data.skip_binder().self_ty().is_param(index) if data.skip_binder().self_ty().is_param(index) => {
// HACK(eddyb) should get the original `Span`.
let span = tcx.def_span(def_id);
Some((predicate, span))
} }
_ => false _ => None
} }
}).cloned().collect() }).collect()
} }
} }

View file

@ -460,7 +460,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
} }
}); });
// Now we build the substituted predicates. // Now we build the substituted predicates.
let default_obligations = predicates.predicates.iter().flat_map(|&pred| { 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 {
@ -484,7 +484,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
// or preds with multiple params. // or preds with multiple params.
if substituted_pred.references_error() || param_count.params.len() > 1 || has_region { if substituted_pred.references_error() || param_count.params.len() > 1 || has_region {
None None
} else if predicates.predicates.contains(&substituted_pred) { } else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
// Avoid duplication of predicates that contain no parameters, for example. // Avoid duplication of predicates that contain no parameters, for example.
None None
} else { } else {
@ -674,10 +674,10 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
"check_existential_types may define. adding predicates: {:#?}", "check_existential_types may define. adding predicates: {:#?}",
predicates, predicates,
); );
for &pred in predicates.predicates.iter() { for &(pred, _) in predicates.predicates.iter() {
let substituted_pred = pred.subst(fcx.tcx, substs); let substituted_pred = pred.subst(fcx.tcx, substs);
// 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) { if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
substituted_predicates.push(substituted_pred); substituted_predicates.push(substituted_pred);
} }
} }
@ -806,7 +806,7 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.collect(); .collect();
identify_constrained_type_params(tcx, identify_constrained_type_params(tcx,
ty_predicates.predicates.as_slice(), &ty_predicates,
None, None,
&mut constrained_parameters); &mut constrained_parameters);
@ -874,7 +874,10 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>(
let empty_env = ty::ParamEnv::empty(); let empty_env = ty::ParamEnv::empty();
let def_id = fcx.tcx.hir.local_def_id(id); let def_id = fcx.tcx.hir.local_def_id(id);
let predicates = fcx.tcx.predicates_of(def_id).predicates; let predicates = fcx.tcx.predicates_of(def_id).predicates
.into_iter()
.map(|(p, _)| p)
.collect();
// Check elaborated bounds // Check elaborated bounds
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);

View file

@ -56,6 +56,8 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::hir::GenericParamKind; use rustc::hir::GenericParamKind;
use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety};
use std::iter;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Main entry point // Main entry point
@ -292,9 +294,10 @@ fn type_param_predicates<'a, 'tcx>(
ItemKind::Trait(_, _, ref generics, ..) => { ItemKind::Trait(_, _, 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 {
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
result result
.predicates .predicates
.push(ty::TraitRef::identity(tcx, item_def_id).to_predicate()); .push((identity_trait_ref.to_predicate(), item.span));
} }
generics generics
} }
@ -327,7 +330,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
ast_generics: &hir::Generics, ast_generics: &hir::Generics,
param_id: ast::NodeId, param_id: ast::NodeId,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Vec<ty::Predicate<'tcx>> { ) -> Vec<(ty::Predicate<'tcx>, Span)> {
let from_ty_params = ast_generics let from_ty_params = ast_generics
.params .params
.iter() .iter()
@ -705,8 +708,10 @@ fn super_predicates_of<'a, 'tcx>(
// Now require that immediate supertraits are converted, // Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits. // which will, in turn, reach indirect supertraits.
for bound in superbounds.iter().filter_map(|p| p.to_opt_poly_trait_ref()) { for &(pred, span) in &superbounds {
tcx.at(item.span).super_predicates_of(bound.def_id()); if let ty::Predicate::Trait(bound) = pred {
tcx.at(span).super_predicates_of(bound.def_id());
}
} }
ty::GenericPredicates { ty::GenericPredicates {
@ -1584,10 +1589,10 @@ fn predicates_defined_on<'a, 'tcx>(
def_id: DefId, def_id: DefId,
) -> ty::GenericPredicates<'tcx> { ) -> ty::GenericPredicates<'tcx> {
let explicit = tcx.explicit_predicates_of(def_id); let explicit = tcx.explicit_predicates_of(def_id);
let predicates = [ let span = tcx.def_span(def_id);
&explicit.predicates[..], let predicates = explicit.predicates.into_iter().chain(
&tcx.inferred_outlives_of(def_id)[..], tcx.inferred_outlives_of(def_id).iter().map(|&p| (p, span))
].concat(); ).collect();
ty::GenericPredicates { ty::GenericPredicates {
parent: explicit.parent, parent: explicit.parent,
@ -1617,7 +1622,8 @@ fn predicates_of<'a, 'tcx>(
// prove that the trait applies to the types that were // prove that the trait applies to the types that were
// used, and adding the predicate into this list ensures // used, and adding the predicate into this list ensures
// that this is done. // that this is done.
predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate()); let span = tcx.def_span(def_id);
predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
} }
ty::GenericPredicates { parent, predicates } ty::GenericPredicates { parent, predicates }
@ -1747,7 +1753,7 @@ fn explicit_predicates_of<'a, 'tcx>(
// (see below). Recall that a default impl is not itself an impl, but rather a // (see below). Recall that a default impl is not itself an impl, but rather a
// set of defaults that can be incorporated into another impl. // set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait { if let Some(trait_ref) = is_default_impl_trait {
predicates.push(trait_ref.to_poly_trait_ref().to_predicate()); predicates.push((trait_ref.to_poly_trait_ref().to_predicate(), tcx.def_span(def_id)));
} }
// Collect the region predicates that were declared inline as // Collect the region predicates that were declared inline as
@ -1768,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>(
hir::GenericBound::Outlives(lt) => { hir::GenericBound::Outlives(lt) => {
let bound = AstConv::ast_region_to_region(&icx, &lt, None); let bound = AstConv::ast_region_to_region(&icx, &lt, None);
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound)); let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound));
predicates.push(outlives.to_predicate()); predicates.push((outlives.to_predicate(), lt.span));
} }
_ => bug!(), _ => bug!(),
}); });
@ -1812,7 +1818,8 @@ fn explicit_predicates_of<'a, 'tcx>(
// users who never wrote `where Type:,` themselves, to // users who never wrote `where Type:,` themselves, to
// compiler/tooling bugs from not handling WF predicates. // compiler/tooling bugs from not handling WF predicates.
} else { } else {
predicates.push(ty::Predicate::WellFormed(ty)); let span = bound_pred.bounded_ty.span;
predicates.push((ty::Predicate::WellFormed(ty), span));
} }
} }
@ -1828,14 +1835,16 @@ fn explicit_predicates_of<'a, 'tcx>(
&mut projections, &mut projections,
); );
predicates.push(trait_ref.to_predicate()); predicates.push((trait_ref.to_predicate(), poly_trait_ref.span));
predicates.extend(projections.iter().map(|p| p.to_predicate())); predicates.extend(projections.iter().map(|&(p, span)| {
(p.to_predicate(), span)
}));
} }
&hir::GenericBound::Outlives(ref lifetime) => { &hir::GenericBound::Outlives(ref lifetime) => {
let region = AstConv::ast_region_to_region(&icx, lifetime, None); let region = AstConv::ast_region_to_region(&icx, lifetime, None);
let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region)); let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region));
predicates.push(ty::Predicate::TypeOutlives(pred)) predicates.push((ty::Predicate::TypeOutlives(pred), lifetime.span))
} }
} }
} }
@ -1844,14 +1853,14 @@ fn explicit_predicates_of<'a, 'tcx>(
&hir::WherePredicate::RegionPredicate(ref region_pred) => { &hir::WherePredicate::RegionPredicate(ref region_pred) => {
let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None); let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None);
for bound in &region_pred.bounds { for bound in &region_pred.bounds {
let r2 = match bound { let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => { hir::GenericBound::Outlives(lt) => {
AstConv::ast_region_to_region(&icx, lt, None) (AstConv::ast_region_to_region(&icx, lt, None), lt.span)
} }
_ => bug!(), _ => bug!(),
}; };
let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2)); let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
predicates.push(ty::Predicate::RegionOutlives(pred)) predicates.push((ty::Predicate::RegionOutlives(pred), span))
} }
} }
@ -1940,22 +1949,25 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
let mut projection_bounds = vec![]; let mut projection_bounds = vec![];
let mut trait_bounds: Vec<_> = trait_bounds let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
.iter() (astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
.map(|&bound| astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds)) }).collect();
.collect();
let region_bounds = region_bounds let region_bounds = region_bounds
.into_iter() .into_iter()
.map(|r| astconv.ast_region_to_region(r, None)) .map(|r| (astconv.ast_region_to_region(r, None), r.span))
.collect(); .collect();
trait_bounds.sort_by_key(|t| t.def_id()); trait_bounds.sort_by_key(|(t, _)| t.def_id());
let implicitly_sized = if let SizedByDefault::Yes = sized_by_default { let implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
!is_unsized(astconv, ast_bounds, span) if !is_unsized(astconv, ast_bounds, span) {
Some(span)
} else { } else {
false None
}
} else {
None
}; };
Bounds { Bounds {
@ -1975,21 +1987,21 @@ fn predicates_from_bound<'tcx>(
astconv: &dyn AstConv<'tcx, 'tcx>, astconv: &dyn AstConv<'tcx, 'tcx>,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
bound: &hir::GenericBound, bound: &hir::GenericBound,
) -> Vec<ty::Predicate<'tcx>> { ) -> Vec<(ty::Predicate<'tcx>, Span)> {
match *bound { match *bound {
hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
let mut projections = Vec::new(); let mut projections = Vec::new();
let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections); let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections);
iter::once((pred.to_predicate(), tr.span)).chain(
projections projections
.into_iter() .into_iter()
.map(|p| p.to_predicate()) .map(|(p, span)| (p.to_predicate(), span))
.chain(Some(pred.to_predicate())) ).collect()
.collect()
} }
hir::GenericBound::Outlives(ref lifetime) => { hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None); let region = astconv.ast_region_to_region(lifetime, None);
let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region)); let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
vec![ty::Predicate::TypeOutlives(pred)] vec![(ty::Predicate::TypeOutlives(pred), lifetime.span)]
} }
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![], hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![],
} }

View file

@ -11,6 +11,7 @@
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::fold::{TypeFoldable, TypeVisitor}; use rustc::ty::fold::{TypeFoldable, TypeVisitor};
use rustc::util::nodemap::FxHashSet; use rustc::util::nodemap::FxHashSet;
use syntax::source_map::Span;
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Parameter(pub u32); pub struct Parameter(pub u32);
@ -86,12 +87,12 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
} }
} }
pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt, pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
predicates: &[ty::Predicate<'tcx>], predicates: &ty::GenericPredicates<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>, impl_trait_ref: Option<ty::TraitRef<'tcx>>,
input_parameters: &mut FxHashSet<Parameter>) input_parameters: &mut FxHashSet<Parameter>)
{ {
let mut predicates = predicates.to_owned(); let mut predicates = predicates.predicates.clone();
setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters); setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters);
} }
@ -137,7 +138,7 @@ pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt,
/// by 0. I should probably pick a less tangled example, but I can't /// by 0. I should probably pick a less tangled example, but I can't
/// think of any. /// think of any.
pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt, pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt,
predicates: &mut [ty::Predicate<'tcx>], predicates: &mut [(ty::Predicate<'tcx>, Span)],
impl_trait_ref: Option<ty::TraitRef<'tcx>>, impl_trait_ref: Option<ty::TraitRef<'tcx>>,
input_parameters: &mut FxHashSet<Parameter>) input_parameters: &mut FxHashSet<Parameter>)
{ {
@ -169,7 +170,7 @@ pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt,
changed = false; changed = false;
for j in i..predicates.len() { for j in i..predicates.len() {
if let ty::Predicate::Projection(ref poly_projection) = predicates[j] { if let ty::Predicate::Projection(ref poly_projection) = predicates[j].0 {
// Note that we can skip binder here because the impl // Note that we can skip binder here because the impl
// trait ref never contains any late-bound regions. // trait ref never contains any late-bound regions.
let projection = poly_projection.skip_binder(); let projection = poly_projection.skip_binder();

View file

@ -100,7 +100,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref); let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref);
ctp::identify_constrained_type_params( ctp::identify_constrained_type_params(
tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); tcx, &impl_predicates, impl_trait_ref, &mut input_parameters);
// Disallow unconstrained lifetimes, but only if they appear in assoc types. // Disallow unconstrained lifetimes, but only if they appear in assoc types.
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter() let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()

View file

@ -392,7 +392,7 @@ pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) ->
} }
pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef) pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: &hir::TraitRef)
-> (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>) { -> (ty::PolyTraitRef<'tcx>, Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>) {
// In case there are any projections etc, find the "environment" // In case there are any projections etc, find the "environment"
// def-id that will be used to determine the traits/predicates in // def-id that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing. // scope. This is derived from the enclosing item-like thing.

View file

@ -40,7 +40,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
let mut required_predicates = RequiredPredicates::default(); let mut required_predicates = RequiredPredicates::default();
// process predicates and convert to `RequiredPredicates` entry, see below // process predicates and convert to `RequiredPredicates` entry, see below
for pred in predicates.into_iter() { for (pred, _) in predicates.into_iter() {
match pred { match pred {
ty::Predicate::TypeOutlives(predicate) => { ty::Predicate::TypeOutlives(predicate) => {
let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();

View file

@ -1571,7 +1571,9 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
} }
}).collect::<Vec<GenericParamDef>>(); }).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.to_vec().clean(cx); let mut where_predicates = preds.predicates.iter()
.map(|(p, _)| p.clean(cx))
.collect::<Vec<_>>();
// Type parameters and have a Sized bound by default unless removed with // Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with // ?Sized. Scan through the predicates and mark any type parameter with

View file

@ -157,7 +157,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId,
return true return true
} }
let predicates = cx.tcx.super_predicates_of(child).predicates; let predicates = cx.tcx.super_predicates_of(child).predicates;
predicates.iter().filter_map(|pred| { predicates.iter().filter_map(|(pred, _)| {
if let ty::Predicate::Trait(ref pred) = *pred { if let ty::Predicate::Trait(ref pred) = *pred {
if pred.skip_binder().trait_ref.self_ty().is_self() { if pred.skip_binder().trait_ref.self_ty().is_self() {
Some(pred.def_id()) Some(pred.def_id())

View file

@ -1,8 +1,8 @@
error[E0391]: cycle detected when computing the supertraits of `Chromosome` error[E0391]: cycle detected when computing the supertraits of `Chromosome`
--> $DIR/cycle-trait-supertrait-direct.rs:13:1 --> $DIR/cycle-trait-supertrait-direct.rs:13:19
| |
LL | trait Chromosome: Chromosome { LL | trait Chromosome: Chromosome {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
| |
= note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle = note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle

View file

@ -1,20 +1,20 @@
error[E0391]: cycle detected when computing the supertraits of `B` error[E0391]: cycle detected when computing the supertraits of `B`
--> $DIR/cycle-trait-supertrait-indirect.rs:17:1 --> $DIR/cycle-trait-supertrait-indirect.rs:17:10
| |
LL | trait B: C { LL | trait B: C {
| ^^^^^^^^^^ | ^
| |
note: ...which requires computing the supertraits of `C`... note: ...which requires computing the supertraits of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:21:1 --> $DIR/cycle-trait-supertrait-indirect.rs:21:10
| |
LL | trait C: B { } LL | trait C: B { }
| ^^^^^^^^^^ | ^
= note: ...which again requires computing the supertraits of `B`, completing the cycle = note: ...which again requires computing the supertraits of `B`, completing the cycle
note: cycle used when computing the supertraits of `A` note: cycle used when computing the supertraits of `A`
--> $DIR/cycle-trait-supertrait-indirect.rs:14:1 --> $DIR/cycle-trait-supertrait-indirect.rs:14:10
| |
LL | trait A: B { LL | trait A: B {
| ^^^^^^^^^^ | ^
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,14 +1,14 @@
error[E0391]: cycle detected when computing the supertraits of `t1` error[E0391]: cycle detected when computing the supertraits of `t1`
--> $DIR/issue-12511.rs:11:1 --> $DIR/issue-12511.rs:11:12
| |
LL | trait t1 : t2 { LL | trait t1 : t2 {
| ^^^^^^^^^^^^^ | ^^
| |
note: ...which requires computing the supertraits of `t2`... note: ...which requires computing the supertraits of `t2`...
--> $DIR/issue-12511.rs:15:1 --> $DIR/issue-12511.rs:15:12
| |
LL | trait t2 : t1 { LL | trait t2 : t1 {
| ^^^^^^^^^^^^^ | ^^
= note: ...which again requires computing the supertraits of `t1`, completing the cycle = note: ...which again requires computing the supertraits of `t1`, completing the cycle
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,41 +1,26 @@
warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-copy.rs:16:1 --> $DIR/trivial-bounds-inconsistent-copy.rs:16:51
| |
LL | / fn copy_string(t: String) -> String where String: Copy { LL | fn copy_string(t: String) -> String where String: Copy {
LL | | is_copy(&t); | ^^^^
LL | | let x = t;
LL | | drop(t);
LL | | t
LL | | }
| |_^
| |
= note: #[warn(trivial_bounds)] on by default = note: #[warn(trivial_bounds)] on by default
warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-copy.rs:23:1 --> $DIR/trivial-bounds-inconsistent-copy.rs:23:56
| |
LL | / fn copy_out_string(t: &String) -> String where String: Copy { LL | fn copy_out_string(t: &String) -> String where String: Copy {
LL | | *t | ^^^^
LL | | }
| |_^
warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-copy.rs:27:1 --> $DIR/trivial-bounds-inconsistent-copy.rs:27:55
| |
LL | / fn copy_string_with_param<T>(x: String) where String: Copy { LL | fn copy_string_with_param<T>(x: String) where String: Copy {
LL | | let y = x; | ^^^^
LL | | let z = x;
LL | | }
| |_^
warning: Trait bound for<'b> &'b mut i32: std::marker::Copy does not depend on any type or lifetime parameters warning: Trait bound for<'b> &'b mut i32: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-copy.rs:33:1 --> $DIR/trivial-bounds-inconsistent-copy.rs:33:76
| |
LL | / fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
LL | | is_copy(t); | ^^^^
LL | | let x = *t;
LL | | drop(x);
LL | | x
LL | | }
| |_^

View file

@ -1,57 +1,44 @@
warning: Trait bound B: A does not depend on any type or lifetime parameters warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:29:1 --> $DIR/trivial-bounds-inconsistent-projection.rs:31:8
| |
LL | / fn underspecified_bound() -> u8 LL | B: A
LL | | where | ^
LL | | B: A
LL | | {
LL | | B::get_x()
LL | | }
| |_^
| |
= note: #[warn(trivial_bounds)] on by default = note: #[warn(trivial_bounds)] on by default
warning: Trait bound B: A does not depend on any type or lifetime parameters warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:36:1 --> $DIR/trivial-bounds-inconsistent-projection.rs:38:8
| |
LL | / fn inconsistent_bound() -> i32 LL | B: A<X = i32>
LL | | where | ^^^^^^^^^^
LL | | B: A<X = i32>
LL | | {
LL | | B::get_x()
LL | | }
| |_^
warning: Trait bound B: A does not depend on any type or lifetime parameters warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:43:1 --> $DIR/trivial-bounds-inconsistent-projection.rs:45:8
| |
LL | / fn redundant_bound() -> u8 LL | B: A<X = u8>
LL | | where | ^^^^^^^^^
LL | | B: A<X = u8>
LL | | {
LL | | B::get_x()
LL | | }
| |_^
warning: Trait bound B: A does not depend on any type or lifetime parameters warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:50:1 --> $DIR/trivial-bounds-inconsistent-projection.rs:52:8
| |
LL | / fn inconsistent_dup_bound() -> i32 LL | B: A<X = i32> + A
LL | | where | ^^^^^^^^^^
LL | | B: A<X = i32> + A
LL | | {
LL | | B::get_x()
LL | | }
| |_^
warning: Trait bound B: A does not depend on any type or lifetime parameters warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:57:1 --> $DIR/trivial-bounds-inconsistent-projection.rs:52:21
| |
LL | / fn redundant_dup_bound() -> u8 LL | B: A<X = i32> + A
LL | | where | ^
LL | | B: A<X = u8> + A
LL | | { warning: Trait bound B: A does not depend on any type or lifetime parameters
LL | | B::get_x() --> $DIR/trivial-bounds-inconsistent-projection.rs:59:8
LL | | } |
| |_^ LL | B: A<X = u8> + A
| ^^^^^^^^^
warning: Trait bound B: A does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-projection.rs:59:20
|
LL | B: A<X = u8> + A
| ^

View file

@ -1,24 +1,20 @@
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:24:1 --> $DIR/trivial-bounds-inconsistent-sized.rs:24:31
| |
LL | struct S(str, str) where str: Sized; LL | struct S(str, str) where str: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^
| |
= note: #[warn(trivial_bounds)] on by default = note: #[warn(trivial_bounds)] on by default
warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:26:1 --> $DIR/trivial-bounds-inconsistent-sized.rs:26:45
| |
LL | / fn unsized_local() where for<'a> T<A + 'a>: Sized { LL | fn unsized_local() where for<'a> T<A + 'a>: Sized {
LL | | let x: T<A> = *(Box::new(T { x: 1 }) as Box<T<A>>); | ^^^^^
LL | | }
| |_^
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:30:1 --> $DIR/trivial-bounds-inconsistent-sized.rs:30:35
| |
LL | / fn return_str() -> str where str: Sized { LL | fn return_str() -> str where str: Sized {
LL | | *"Sized".to_string().into_boxed_str() | ^^^^^
LL | | }
| |_^

View file

@ -1,20 +1,14 @@
warning: Trait bound std::vec::Vec<str>: std::fmt::Debug does not depend on any type or lifetime parameters warning: Trait bound std::vec::Vec<str>: std::fmt::Debug does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:1 --> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:30
| |
LL | / pub fn foo() where Vec<str>: Debug, str: Copy { LL | pub fn foo() where Vec<str>: Debug, str: Copy {
LL | | let x = vec![*"1"]; | ^^^^^
LL | | println!("{:?}", x);
LL | | }
| |_^
| |
= note: #[warn(trivial_bounds)] on by default = note: #[warn(trivial_bounds)] on by default
warning: Trait bound str: std::marker::Copy does not depend on any type or lifetime parameters warning: Trait bound str: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:1 --> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:42
| |
LL | / pub fn foo() where Vec<str>: Debug, str: Copy { LL | pub fn foo() where Vec<str>: Debug, str: Copy {
LL | | let x = vec![*"1"]; | ^^^^
LL | | println!("{:?}", x);
LL | | }
| |_^

View file

@ -1,28 +1,28 @@
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:24:1 --> $DIR/trivial-bounds-inconsistent.rs:24:19
| |
LL | enum E where i32: Foo { V } LL | enum E where i32: Foo { V }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
| |
= note: #[warn(trivial_bounds)] on by default = note: #[warn(trivial_bounds)] on by default
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:26:1 --> $DIR/trivial-bounds-inconsistent.rs:26:21
| |
LL | struct S where i32: Foo; LL | struct S where i32: Foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:28:1 --> $DIR/trivial-bounds-inconsistent.rs:28:20
| |
LL | trait T where i32: Foo {} LL | trait T where i32: Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:30:1 --> $DIR/trivial-bounds-inconsistent.rs:30:20
| |
LL | union U where i32: Foo { f: i32 } LL | union U where i32: Foo { f: i32 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
warning: where clauses are not enforced in type aliases warning: where clauses are not enforced in type aliases
--> $DIR/trivial-bounds-inconsistent.rs:32:14 --> $DIR/trivial-bounds-inconsistent.rs:32:14
@ -34,79 +34,56 @@ LL | type Y where i32: Foo = ();
= help: the clause will not be checked when the type alias is used, and should be removed = help: the clause will not be checked when the type alias is used, and should be removed
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:32:1 --> $DIR/trivial-bounds-inconsistent.rs:32:19
| |
LL | type Y where i32: Foo = (); LL | type Y where i32: Foo = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:34:1 --> $DIR/trivial-bounds-inconsistent.rs:34:28
| |
LL | / impl Foo for () where i32: Foo { LL | impl Foo for () where i32: Foo {
LL | | fn test(&self) { | ^^^
LL | | 3i32.test();
LL | | Foo::test(&4i32);
LL | | generic_function(5i32);
LL | | }
LL | | }
| |_^
warning: Trait bound i32: Foo does not depend on any type or lifetime parameters warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:42:1 --> $DIR/trivial-bounds-inconsistent.rs:42:19
| |
LL | / fn f() where i32: Foo { LL | fn f() where i32: Foo {
LL | | let s = S; | ^^^
LL | | 3i32.test();
LL | | Foo::test(&4i32);
LL | | generic_function(5i32);
LL | | }
| |_^
warning: Trait bound &'static str: Foo does not depend on any type or lifetime parameters warning: Trait bound &'static str: Foo does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:49:1 --> $DIR/trivial-bounds-inconsistent.rs:49:28
| |
LL | / fn g() where &'static str: Foo { LL | fn g() where &'static str: Foo {
LL | | "Foo".test(); | ^^^
LL | | Foo::test(&"Foo");
LL | | generic_function("Foo");
LL | | }
| |_^
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:63:1 --> $DIR/trivial-bounds-inconsistent.rs:63:37
| |
LL | struct TwoStrs(str, str) where str: Sized; LL | struct TwoStrs(str, str) where str: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^
warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:65:1 --> $DIR/trivial-bounds-inconsistent.rs:65:47
| |
LL | / fn unsized_local() where for<'a> Dst<A + 'a>: Sized { LL | fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); | ^^^^^
LL | | }
| |_^
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:69:1 --> $DIR/trivial-bounds-inconsistent.rs:69:35
| |
LL | / fn return_str() -> str where str: Sized { LL | fn return_str() -> str where str: Sized {
LL | | *"Sized".to_string().into_boxed_str() | ^^^^^
LL | | }
| |_^
warning: Trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters warning: Trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:73:1 --> $DIR/trivial-bounds-inconsistent.rs:73:46
| |
LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { LL | fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
LL | | -s | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | | }
| |_^
warning: Trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters warning: Trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:77:1 --> $DIR/trivial-bounds-inconsistent.rs:77:25
| |
LL | / fn use_for() where i32: Iterator { LL | fn use_for() where i32: Iterator {
LL | | for _ in 2i32 {} | ^^^^^^^^
LL | | }
| |_^

View file

@ -1,8 +1,8 @@
error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:15:1 --> $DIR/trivial-bounds-lint.rs:15:21
| |
LL | struct A where i32: Copy; //~ ERROR LL | struct A where i32: Copy; //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^
| |
note: lint level defined here note: lint level defined here
--> $DIR/trivial-bounds-lint.rs:13:9 --> $DIR/trivial-bounds-lint.rs:13:9
@ -11,40 +11,40 @@ LL | #![deny(trivial_bounds)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: Trait bound i32: X<()> does not depend on any type or lifetime parameters error: Trait bound i32: X<()> does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:28:1 --> $DIR/trivial-bounds-lint.rs:28:30
| |
LL | fn global_param() where i32: X<()> {} //~ ERROR LL | fn global_param() where i32: X<()> {} //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^
error: Trait bound i32: Z does not depend on any type or lifetime parameters error: Trait bound i32: Z does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:32:1 --> $DIR/trivial-bounds-lint.rs:32:35
| |
LL | fn global_projection() where i32: Z<S = i32> {} //~ ERROR LL | fn global_projection() where i32: Z<S = i32> {} //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
error: Lifetime bound i32 : 'static does not depend on any type or lifetime parameters error: Lifetime bound i32 : 'static does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:39:1 --> $DIR/trivial-bounds-lint.rs:39:34
| |
LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^
error: Lifetime bound &'static str : 'static does not depend on any type or lifetime parameters error: Lifetime bound &'static str : 'static does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:39:1 --> $DIR/trivial-bounds-lint.rs:39:57
| |
LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^
error: Lifetime bound 'static : 'static does not depend on any type or lifetime parameters error: Lifetime bound 'static : 'static does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:45:1 --> $DIR/trivial-bounds-lint.rs:45:37
| |
LL | fn global_outlives() where 'static: 'static {} //~ ERROR LL | fn global_outlives() where 'static: 'static {} //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^
error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-lint.rs:48:1 --> $DIR/trivial-bounds-lint.rs:48:46
| |
LL | fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR LL | fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^
error: aborting due to 7 previous errors error: aborting due to 7 previous errors