|
6 | 6 | //!
|
7 | 7 | //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
|
8 | 8 | use rustc_hir as hir;
|
| 9 | +use rustc_hir::def_id::DefId; |
| 10 | +use rustc_infer::traits::TraitEngine; |
9 | 11 | use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
|
| 12 | +use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; |
10 | 13 | use rustc_middle::ty::print::with_no_trimmed_paths;
|
11 |
| -use rustc_middle::ty::{self, Ty, TypeFoldable}; |
| 14 | +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; |
12 | 15 | use rustc_target::spec::abi::Abi;
|
13 | 16 |
|
| 17 | +use crate::traits; |
14 | 18 | use crate::traits::coherence::Conflict;
|
| 19 | +use crate::traits::query::evaluate_obligation::InferCtxtExt; |
15 | 20 | use crate::traits::{util, SelectionResult};
|
16 | 21 | use crate::traits::{Overflow, Unimplemented};
|
17 | 22 |
|
@@ -672,6 +677,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
672 | 677 | })
|
673 | 678 | }
|
674 | 679 |
|
| 680 | + /// Temporary migration for #89190 |
| 681 | + fn need_migrate_deref_output_trait_object( |
| 682 | + &mut self, |
| 683 | + ty: Ty<'tcx>, |
| 684 | + cause: &traits::ObligationCause<'tcx>, |
| 685 | + param_env: ty::ParamEnv<'tcx>, |
| 686 | + ) -> Option<(Ty<'tcx>, DefId)> { |
| 687 | + let tcx = self.tcx(); |
| 688 | + if tcx.features().trait_upcasting { |
| 689 | + return None; |
| 690 | + } |
| 691 | + |
| 692 | + // <ty as Deref> |
| 693 | + let trait_ref = ty::TraitRef { |
| 694 | + def_id: tcx.lang_items().deref_trait()?, |
| 695 | + substs: tcx.mk_substs_trait(ty, &[]), |
| 696 | + }; |
| 697 | + |
| 698 | + let obligation = traits::Obligation::new( |
| 699 | + cause.clone(), |
| 700 | + param_env, |
| 701 | + ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), |
| 702 | + ); |
| 703 | + if !self.infcx.predicate_may_hold(&obligation) { |
| 704 | + return None; |
| 705 | + } |
| 706 | + |
| 707 | + let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); |
| 708 | + let normalized_ty = fulfillcx.normalize_projection_type( |
| 709 | + &self.infcx, |
| 710 | + param_env, |
| 711 | + ty::ProjectionTy { |
| 712 | + item_def_id: tcx.lang_items().deref_target()?, |
| 713 | + substs: trait_ref.substs, |
| 714 | + }, |
| 715 | + cause.clone(), |
| 716 | + ); |
| 717 | + |
| 718 | + let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() { |
| 719 | + data |
| 720 | + } else { |
| 721 | + return None; |
| 722 | + }; |
| 723 | + |
| 724 | + let def_id = data.principal_def_id()?; |
| 725 | + |
| 726 | + return Some((normalized_ty, def_id)); |
| 727 | + } |
| 728 | + |
675 | 729 | /// Searches for unsizing that might apply to `obligation`.
|
676 | 730 | fn assemble_candidates_for_unsizing(
|
677 | 731 | &mut self,
|
@@ -732,6 +786,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
732 | 786 | let principal_a = data_a.principal().unwrap();
|
733 | 787 | let target_trait_did = principal_def_id_b.unwrap();
|
734 | 788 | let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
|
| 789 | + if let Some((deref_output_ty, deref_output_trait_did)) = self |
| 790 | + .need_migrate_deref_output_trait_object( |
| 791 | + source, |
| 792 | + &obligation.cause, |
| 793 | + obligation.param_env, |
| 794 | + ) |
| 795 | + { |
| 796 | + if deref_output_trait_did == target_trait_did { |
| 797 | + self.tcx().struct_span_lint_hir( |
| 798 | + DEREF_INTO_DYN_SUPERTRAIT, |
| 799 | + obligation.cause.body_id, |
| 800 | + obligation.cause.span, |
| 801 | + |lint| { |
| 802 | + lint.build(&format!( |
| 803 | + "`{}` implements `Deref` with supertrait `{}` as output", |
| 804 | + source, |
| 805 | + deref_output_ty |
| 806 | + )).emit(); |
| 807 | + }, |
| 808 | + ); |
| 809 | + return; |
| 810 | + } |
| 811 | + } |
| 812 | + |
735 | 813 | for (idx, upcast_trait_ref) in
|
736 | 814 | util::supertraits(self.tcx(), source_trait_ref).enumerate()
|
737 | 815 | {
|
|
0 commit comments