summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/object_safety.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:21 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:21 +0000
commit4e8199b572f2035b7749cba276ece3a26630d23e (patch)
treef09feeed6a0fe39d027b1908aa63ea6b35e4b631 /compiler/rustc_trait_selection/src/traits/object_safety.rs
parentAdding upstream version 1.66.0+dfsg1. (diff)
downloadrustc-4e8199b572f2035b7749cba276ece3a26630d23e.tar.xz
rustc-4e8199b572f2035b7749cba276ece3a26630d23e.zip
Adding upstream version 1.67.1+dfsg1.upstream/1.67.1+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/object_safety.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs78
1 files changed, 35 insertions, 43 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0bb25a74d..a45749fe4 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -17,11 +17,10 @@ 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::abstract_const::{walk_abstract_const, AbstractConst};
+use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
-use rustc_middle::ty::{GenericArg, InternalSubsts};
use rustc_middle::ty::{Predicate, ToPredicate};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
@@ -288,11 +287,11 @@ fn predicate_references_self<'tcx>(
let self_ty = tcx.types.self_param;
let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into());
match predicate.kind().skip_binder() {
- ty::PredicateKind::Trait(ref data) => {
+ ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
// In the case of a trait predicate, we can skip the "self" type.
if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
}
- ty::PredicateKind::Projection(ref data) => {
+ ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
// And similarly for projections. This should be redundant with
// the previous check because any projection should have a
// matching `Trait` predicate with the same inputs, but we do
@@ -312,13 +311,14 @@ fn predicate_references_self<'tcx>(
}
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::TypeOutlives(..)
- | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
+ | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
@@ -337,19 +337,20 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Trait(ref trait_pred) => {
+ 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::Projection(..)
+ ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}
})
@@ -375,6 +376,7 @@ fn object_safety_violation_for_method(
let span = match (&v, node) {
(MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
(MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
+ (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span())
}
@@ -437,8 +439,8 @@ fn virtual_call_violation_for_method<'tcx>(
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
return Some(MethodViolationCode::ReferencesSelfOutput);
}
- if contains_illegal_impl_trait_in_trait(tcx, sig.output()) {
- return Some(MethodViolationCode::ReferencesImplTraitInTrait);
+ if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
+ return Some(code);
}
// We can't monomorphize things like `fn foo<A>(...)`.
@@ -684,10 +686,9 @@ fn receiver_is_dispatchable<'tcx>(
let param_env = tcx.param_env(method.def_id);
// Self: Unsize<U>
- let unsize_predicate = ty::Binder::dummy(ty::TraitRef {
- def_id: unsize_did,
- substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
- })
+ let unsize_predicate = ty::Binder::dummy(
+ tcx.mk_trait_ref(unsize_did, [tcx.types.self_param, unsized_self_ty]),
+ )
.without_const()
.to_predicate(tcx);
@@ -719,14 +720,11 @@ fn receiver_is_dispatchable<'tcx>(
// Receiver: DispatchFromDyn<Receiver[Self => U]>
let obligation = {
- let predicate = ty::Binder::dummy(ty::TraitRef {
- def_id: dispatch_from_dyn_did,
- substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
- })
- .without_const()
- .to_predicate(tcx);
+ let predicate = ty::Binder::dummy(
+ tcx.mk_trait_ref(dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]),
+ );
- Obligation::new(ObligationCause::dummy(), param_env, predicate)
+ Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
};
let infcx = tcx.infer_ctxt().build();
@@ -838,23 +836,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- // Constants can only influence object safety if they reference `Self`.
+ // Constants can only influence object safety if they are generic and reference `Self`.
// This is only possible for unevaluated constants, so we walk these here.
- //
- // If `AbstractConst::from_const` returned an error we already failed compilation
- // so we don't have to emit an additional error here.
- use rustc_middle::ty::abstract_const::Node;
- if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
- walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
- Node::Leaf(leaf) => self.visit_const(leaf),
- Node::Cast(_, _, ty) => self.visit_ty(ty),
- Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
- ControlFlow::CONTINUE
- }
- })
- } else {
- ct.super_visit_with(self)
- }
+ self.tcx.expand_abstract_consts(ct).super_visit_with(self)
}
}
@@ -865,16 +849,24 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
pub fn contains_illegal_impl_trait_in_trait<'tcx>(
tcx: TyCtxt<'tcx>,
+ fn_def_id: DefId,
ty: ty::Binder<'tcx, Ty<'tcx>>,
-) -> bool {
+) -> Option<MethodViolationCode> {
+ // This would be caught below, but rendering the error as a separate
+ // `async-specific` message is better.
+ if tcx.asyncness(fn_def_id).is_async() {
+ return Some(MethodViolationCode::AsyncFn);
+ }
+
// FIXME(RPITIT): Perhaps we should use a visitor here?
- ty.skip_binder().walk().any(|arg| {
+ ty.skip_binder().walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Projection(proj) = ty.kind()
+ && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
{
- tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+ Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
} else {
- false
+ None
}
})
}