diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_trait_selection/src/traits/object_safety.rs | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 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.rs | 78 |
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 } }) } |