]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_analysis/src/check/dropck.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_hir_analysis / src / check / dropck.rs
CommitLineData
2b03887a 1// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
064997fb
FG
2//
3// We don't do any drop checking during hir typeck.
49aad941 4use rustc_data_structures::fx::FxHashSet;
5e7ed085 5use rustc_errors::{struct_span_err, ErrorGuaranteed};
49aad941
FG
6use rustc_infer::infer::outlives::env::OutlivesEnvironment;
7use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
923072b8 8use rustc_middle::ty::subst::SubstsRef;
49aad941
FG
9use rustc_middle::ty::util::CheckRegions;
10use rustc_middle::ty::{self, TyCtxt};
11use rustc_trait_selection::traits::{self, ObligationCtxt};
12
13use crate::errors;
14use crate::hir::def_id::{DefId, LocalDefId};
60c5eb7d 15
9fa01778 16/// This function confirms that the `Drop` implementation identified by
c34b1796
AL
17/// `drop_impl_did` is not any more specialized than the type it is
18/// attached to (Issue #8142).
19///
20/// This means:
21///
22/// 1. The self type must be nominal (this is already checked during
23/// coherence),
24///
9fa01778 25/// 2. The generic region/type parameters of the impl's self type must
0731742a 26/// all be parameters of the Drop impl itself (i.e., no
c34b1796
AL
27/// specialization like `impl Drop for Foo<i32>`), and,
28///
29/// 3. Any bounds on the generic parameters must be reflected in the
30/// struct/enum definition for the nominal type itself (i.e.
31/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
32///
5e7ed085 33pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
49aad941
FG
34 match tcx.impl_polarity(drop_impl_did) {
35 ty::ImplPolarity::Positive => {}
36 ty::ImplPolarity::Negative => {
37 return Err(tcx.sess.emit_err(errors::DropImplPolarity::Negative {
38 span: tcx.def_span(drop_impl_did),
39 }));
40 }
41 ty::ImplPolarity::Reservation => {
42 return Err(tcx.sess.emit_err(errors::DropImplPolarity::Reservation {
43 span: tcx.def_span(drop_impl_did),
44 }));
45 }
46 }
9ffffee4 47 let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
1b1a35ee 48 match dtor_self_type.kind() {
49aad941 49 ty::Adt(adt_def, adt_to_impl_substs) => {
0bf4aa26
XL
50 ensure_drop_params_and_item_params_correspond(
51 tcx,
f9f354fc 52 drop_impl_did.expect_local(),
5e7ed085 53 adt_def.did(),
49aad941 54 adt_to_impl_substs,
0bf4aa26 55 )?;
c34b1796 56
0bf4aa26
XL
57 ensure_drop_predicates_are_implied_by_item_defn(
58 tcx,
49aad941 59 drop_impl_did.expect_local(),
5e7ed085 60 adt_def.did().expect_local(),
49aad941 61 adt_to_impl_substs,
0bf4aa26 62 )
c34b1796
AL
63 }
64 _ => {
9c376795 65 // Destructors only work on nominal types. This was
2c00a5a8
XL
66 // already checked by coherence, but compilation may
67 // not have been terminated.
8bb4bdeb 68 let span = tcx.def_span(drop_impl_did);
5e7ed085 69 let reported = tcx.sess.delay_span_bug(
dfeec247 70 span,
49aad941 71 format!("should have been rejected by coherence check: {dtor_self_type}"),
dfeec247 72 );
5e7ed085 73 Err(reported)
c34b1796
AL
74 }
75 }
76}
77
dc9dc135
XL
78fn ensure_drop_params_and_item_params_correspond<'tcx>(
79 tcx: TyCtxt<'tcx>,
f9f354fc 80 drop_impl_did: LocalDefId,
0bf4aa26 81 self_type_did: DefId,
49aad941 82 adt_to_impl_substs: SubstsRef<'tcx>,
5e7ed085 83) -> Result<(), ErrorGuaranteed> {
49aad941 84 let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
923072b8
FG
85 return Ok(())
86 };
e9174d1e 87
923072b8
FG
88 let drop_impl_span = tcx.def_span(drop_impl_did);
89 let item_span = tcx.def_span(self_type_did);
9ffffee4 90 let self_descr = tcx.def_descr(self_type_did);
923072b8
FG
91 let mut err =
92 struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized");
93 match arg {
94 ty::util::NotUniqueParam::DuplicateParam(arg) => {
49aad941 95 err.note(format!("`{arg}` is mentioned multiple times"))
a7813a04 96 }
923072b8 97 ty::util::NotUniqueParam::NotParam(arg) => {
49aad941 98 err.note(format!("`{arg}` is not a generic parameter"))
a7813a04 99 }
923072b8
FG
100 };
101 err.span_note(
102 item_span,
49aad941 103 format!(
923072b8
FG
104 "use the same sequence of generic lifetime, type and const parameters \
105 as the {self_descr} definition",
106 ),
107 );
108 Err(err.emit())
c34b1796
AL
109}
110
111/// Confirms that every predicate imposed by dtor_predicates is
112/// implied by assuming the predicates attached to self_type_did.
dc9dc135
XL
113fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
114 tcx: TyCtxt<'tcx>,
49aad941
FG
115 drop_impl_def_id: LocalDefId,
116 adt_def_id: LocalDefId,
117 adt_to_impl_substs: SubstsRef<'tcx>,
5e7ed085 118) -> Result<(), ErrorGuaranteed> {
49aad941
FG
119 let infcx = tcx.infer_ctxt().build();
120 let ocx = ObligationCtxt::new(&infcx);
121
122 // Take the param-env of the adt and substitute the substs that show up in
123 // the implementation's self type. This gives us the assumptions that the
124 // self ty of the implementation is allowed to know just from it being a
125 // well-formed adt, since that's all we're allowed to assume while proving
126 // the Drop implementation is not specialized.
c34b1796 127 //
49aad941
FG
128 // We don't need to normalize this param-env or anything, since we're only
129 // substituting it with free params, so no additional param-env normalization
130 // can occur on top of what has been done in the param_env query itself.
131 let param_env = ty::EarlyBinder(tcx.param_env(adt_def_id))
132 .subst(tcx, adt_to_impl_substs)
133 .with_constness(tcx.constness(drop_impl_def_id));
134
135 for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
136 let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
137 let pred = ocx.normalize(&normalize_cause, param_env, pred);
138 let cause = traits::ObligationCause::new(span, adt_def_id, traits::DropImpl);
139 ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred));
140 }
c34b1796 141
49aad941
FG
142 // All of the custom error reporting logic is to preserve parity with the old
143 // error messages.
144 //
145 // They can probably get removed with better treatment of the new `DropImpl`
146 // obligation cause code, and perhaps some custom logic in `report_region_errors`.
147
148 let errors = ocx.select_all_or_error();
149 if !errors.is_empty() {
150 let mut guar = None;
151 let mut root_predicates = FxHashSet::default();
152 for error in errors {
153 let root_predicate = error.root_obligation.predicate;
154 if root_predicates.insert(root_predicate) {
155 let item_span = tcx.def_span(adt_def_id);
156 let self_descr = tcx.def_descr(adt_def_id.to_def_id());
157 guar = Some(
158 struct_span_err!(
159 tcx.sess,
160 error.root_obligation.cause.span,
161 E0367,
162 "`Drop` impl requires `{root_predicate}` \
163 but the {self_descr} it is implemented for does not",
164 )
165 .span_note(item_span, "the implementor must specify the same requirement")
166 .emit(),
167 );
dfeec247 168 }
c34b1796 169 }
49aad941 170 return Err(guar.unwrap());
c34b1796 171 }
85aaf69f 172
49aad941
FG
173 let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env));
174 if !errors.is_empty() {
175 let mut guar = None;
176 for error in errors {
177 let item_span = tcx.def_span(adt_def_id);
178 let self_descr = tcx.def_descr(adt_def_id.to_def_id());
179 let outlives = match error {
180 RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
181 RegionResolutionError::GenericBoundFailure(_, generic, r) => {
182 format!("{generic}: {r}")
183 }
184 RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
185 RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
186 format!("{b}: {a}", a = tcx.mk_re_var(a))
187 }
188 };
189 guar = Some(
190 struct_span_err!(
191 tcx.sess,
192 error.origin().span(),
193 E0367,
194 "`Drop` impl requires `{outlives}` \
195 but the {self_descr} it is implemented for does not",
196 )
197 .span_note(item_span, "the implementor must specify the same requirement")
198 .emit(),
199 );
dfeec247 200 }
49aad941 201 return Err(guar.unwrap());
dfeec247
XL
202 }
203
49aad941 204 Ok(())
dfeec247 205}