summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/object_safety.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/object_safety.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs76
1 files changed, 47 insertions, 29 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 4eacb5211..b8ad1925e 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -8,20 +8,19 @@
//! - not reference the erased type `Self` except for in this receiver;
//! - not have generic type parameters.
-use super::{elaborate_predicates, elaborate_trait_ref};
+use super::elaborate;
use crate::infer::TyCtxtInferExt;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, Obligation, ObligationCause};
-use hir::def::DefKind;
use rustc_errors::{DelayDm, FatalError, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
-use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
+use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -140,6 +139,10 @@ fn object_safety_violations_for_trait(
if !spans.is_empty() {
violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
}
+ let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
+ if !spans.is_empty() {
+ violations.push(ObjectSafetyViolation::SupertraitNonLifetimeBinder(spans));
+ }
violations.extend(
tcx.associated_items(trait_def_id)
@@ -157,6 +160,7 @@ fn object_safety_violations_for_trait(
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
.filter(|item| !tcx.generics_of(item.def_id).params.is_empty())
+ .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none())
.map(|item| {
let ident = item.ident(tcx);
ObjectSafetyViolation::GAT(ident.name, ident.span)
@@ -331,7 +335,7 @@ fn predicate_references_self<'tcx>(
has_self_ty(&ty.into()).then_some(sp)
}
- ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
+ ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"),
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
@@ -348,6 +352,21 @@ fn predicate_references_self<'tcx>(
}
}
+fn super_predicates_have_non_lifetime_binders(
+ tcx: TyCtxt<'_>,
+ trait_def_id: DefId,
+) -> SmallVec<[Span; 1]> {
+ // If non_lifetime_binders is disabled, then exit early
+ if !tcx.features().non_lifetime_binders {
+ return SmallVec::new();
+ }
+ tcx.super_predicates_of(trait_def_id)
+ .predicates
+ .iter()
+ .filter_map(|(pred, span)| pred.has_non_region_late_bound().then_some(*span))
+ .collect()
+}
+
fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
generics_require_sized_self(tcx, trait_def_id)
}
@@ -360,26 +379,24 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// Search for a predicate like `Self : Sized` amongst the trait bounds.
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
- elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
- match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
- trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
- }
- ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::Subtype(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
- | ty::PredicateKind::WellFormed(..)
- | ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
- | ty::PredicateKind::ConstEvaluatable(..)
- | ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::AliasEq(..)
- | ty::PredicateKind::Ambiguous
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
+ elaborate(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
+ trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
}
+ ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Coerce(..)
+ | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::AliasRelate(..)
+ | ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
})
}
@@ -649,10 +666,11 @@ fn object_ty_for_trait<'tcx>(
});
debug!(?trait_predicate);
- let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
- .filter_map(|obligation| {
- debug!(?obligation);
- let pred = obligation.predicate.to_opt_poly_projection_pred()?;
+ let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx);
+ let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred])
+ .filter_map(|pred| {
+ debug!(?pred);
+ let pred = pred.to_opt_poly_projection_pred()?;
Some(pred.map_bound(|p| {
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
tcx, p,
@@ -854,7 +872,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
}
}
ty::Alias(ty::Projection, ref data)
- if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
+ if self.tcx.is_impl_trait_in_trait(data.def_id) =>
{
// We'll deny these later in their own pass
ControlFlow::Continue(())
@@ -921,7 +939,7 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
ty.skip_binder().walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Alias(ty::Projection, proj) = ty.kind()
- && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+ && tcx.is_impl_trait_in_trait(proj.def_id)
{
Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
} else {