rustc_hir_analysis/check/
always_applicable.rs1use rustc_data_structures::fx::FxHashSet;
8use rustc_errors::codes::*;
9use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
10use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
11use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
12use rustc_middle::span_bug;
13use rustc_middle::ty::util::CheckRegions;
14use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
15use rustc_trait_selection::regions::InferCtxtRegionExt;
16use rustc_trait_selection::traits::{self, ObligationCtxt};
17
18use crate::errors;
19use crate::hir::def_id::{DefId, LocalDefId};
20
21pub(crate) fn check_drop_impl(
38 tcx: TyCtxt<'_>,
39 drop_impl_did: LocalDefId,
40) -> Result<(), ErrorGuaranteed> {
41 match tcx.impl_polarity(drop_impl_did) {
42 ty::ImplPolarity::Positive => {}
43 ty::ImplPolarity::Negative => {
44 return Err(tcx.dcx().emit_err(errors::DropImplPolarity::Negative {
45 span: tcx.def_span(drop_impl_did),
46 }));
47 }
48 ty::ImplPolarity::Reservation => {
49 return Err(tcx.dcx().emit_err(errors::DropImplPolarity::Reservation {
50 span: tcx.def_span(drop_impl_did),
51 }));
52 }
53 }
54
55 tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
56
57 let self_ty = tcx.type_of(drop_impl_did).instantiate_identity();
58
59 match self_ty.kind() {
60 ty::Adt(adt_def, adt_to_impl_args) => {
61 ensure_impl_params_and_item_params_correspond(
62 tcx,
63 drop_impl_did,
64 adt_def.did(),
65 adt_to_impl_args,
66 )?;
67
68 ensure_impl_predicates_are_implied_by_item_defn(
69 tcx,
70 drop_impl_did,
71 adt_def.did(),
72 adt_to_impl_args,
73 )
74 }
75 _ => {
76 span_bug!(tcx.def_span(drop_impl_did), "incoherent impl of Drop");
77 }
78 }
79}
80
81pub(crate) fn check_negative_auto_trait_impl<'tcx>(
82 tcx: TyCtxt<'tcx>,
83 impl_def_id: LocalDefId,
84 impl_trait_ref: ty::TraitRef<'tcx>,
85 polarity: ty::ImplPolarity,
86) -> Result<(), ErrorGuaranteed> {
87 let ty::ImplPolarity::Negative = polarity else {
88 return Ok(());
89 };
90
91 if !tcx.trait_is_auto(impl_trait_ref.def_id) {
92 return Ok(());
93 }
94
95 if tcx.defaultness(impl_def_id).is_default() {
96 tcx.dcx().span_delayed_bug(tcx.def_span(impl_def_id), "default impl cannot be negative");
97 }
98
99 tcx.ensure_ok().orphan_check_impl(impl_def_id)?;
100
101 match impl_trait_ref.self_ty().kind() {
102 ty::Adt(adt_def, adt_to_impl_args) => {
103 ensure_impl_params_and_item_params_correspond(
104 tcx,
105 impl_def_id,
106 adt_def.did(),
107 adt_to_impl_args,
108 )?;
109
110 ensure_impl_predicates_are_implied_by_item_defn(
111 tcx,
112 impl_def_id,
113 adt_def.did(),
114 adt_to_impl_args,
115 )
116 }
117 _ => {
118 if tcx.features().auto_traits() {
119 Ok(())
124 } else {
125 Err(tcx.dcx().span_delayed_bug(
126 tcx.def_span(impl_def_id),
127 "incoherent impl of negative auto trait",
128 ))
129 }
130 }
131 }
132}
133
134fn ensure_impl_params_and_item_params_correspond<'tcx>(
135 tcx: TyCtxt<'tcx>,
136 impl_def_id: LocalDefId,
137 adt_def_id: DefId,
138 adt_to_impl_args: GenericArgsRef<'tcx>,
139) -> Result<(), ErrorGuaranteed> {
140 let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else {
141 return Ok(());
142 };
143
144 let impl_span = tcx.def_span(impl_def_id);
145 let item_span = tcx.def_span(adt_def_id);
146 let self_descr = tcx.def_descr(adt_def_id);
147 let polarity = match tcx.impl_polarity(impl_def_id) {
148 ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
149 ty::ImplPolarity::Negative => "!",
150 };
151 let trait_name = tcx
152 .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
153 let mut err = struct_span_code_err!(
154 tcx.dcx(),
155 impl_span,
156 E0366,
157 "`{polarity}{trait_name}` impls cannot be specialized",
158 );
159 match arg {
160 ty::util::NotUniqueParam::DuplicateParam(arg) => {
161 err.note(format!("`{arg}` is mentioned multiple times"))
162 }
163 ty::util::NotUniqueParam::NotParam(arg) => {
164 err.note(format!("`{arg}` is not a generic parameter"))
165 }
166 };
167 err.span_note(
168 item_span,
169 format!(
170 "use the same sequence of generic lifetime, type and const parameters \
171 as the {self_descr} definition",
172 ),
173 );
174 Err(err.emit())
175}
176
177fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
181 tcx: TyCtxt<'tcx>,
182 impl_def_id: LocalDefId,
183 adt_def_id: DefId,
184 adt_to_impl_args: GenericArgsRef<'tcx>,
185) -> Result<(), ErrorGuaranteed> {
186 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
187 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
188
189 let impl_span = tcx.def_span(impl_def_id.to_def_id());
190 let trait_name = tcx
191 .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
192 let polarity = match tcx.impl_polarity(impl_def_id) {
193 ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
194 ty::ImplPolarity::Negative => "!",
195 };
196 let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args);
211 let adt_env =
212 ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
213
214 let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
215 let fresh_adt_ty =
216 tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
217
218 ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
219 .expect("equating fully generic trait ref should never fail");
220
221 for (clause, span) in tcx.predicates_of(impl_def_id).instantiate(tcx, fresh_impl_args) {
222 let normalize_cause = traits::ObligationCause::misc(span, impl_def_id);
223 let pred = ocx.normalize(&normalize_cause, adt_env, clause);
224 let cause = traits::ObligationCause::new(
225 span,
226 impl_def_id,
227 ObligationCauseCode::AlwaysApplicableImpl,
228 );
229 ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
230 }
231
232 let errors = ocx.select_all_or_error();
239 if !errors.is_empty() {
240 let mut guar = None;
241 let mut root_predicates = FxHashSet::default();
242 for error in errors {
243 let root_predicate = error.root_obligation.predicate;
244 if root_predicates.insert(root_predicate) {
245 let item_span = tcx.def_span(adt_def_id);
246 let self_descr = tcx.def_descr(adt_def_id);
247 guar = Some(
248 struct_span_code_err!(
249 tcx.dcx(),
250 error.root_obligation.cause.span,
251 E0367,
252 "`{polarity}{trait_name}` impl requires `{root_predicate}` \
253 but the {self_descr} it is implemented for does not",
254 )
255 .with_span_note(item_span, "the implementor must specify the same requirement")
256 .emit(),
257 );
258 }
259 }
260 return Err(guar.unwrap());
261 }
262
263 let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []);
264 if !errors.is_empty() {
265 let mut guar = None;
266 for error in errors {
267 let item_span = tcx.def_span(adt_def_id);
268 let self_descr = tcx.def_descr(adt_def_id);
269 let outlives = match error {
270 RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
271 RegionResolutionError::GenericBoundFailure(_, generic, r) => {
272 format!("{generic}: {r}")
273 }
274 RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
275 RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
276 format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
277 }
278 RegionResolutionError::CannotNormalize(..) => unreachable!(),
279 };
280 guar = Some(
281 struct_span_code_err!(
282 tcx.dcx(),
283 error.origin().span(),
284 E0367,
285 "`{polarity}{trait_name}` impl requires `{outlives}` \
286 but the {self_descr} it is implemented for does not",
287 )
288 .with_span_note(item_span, "the implementor must specify the same requirement")
289 .emit(),
290 );
291 }
292 return Err(guar.unwrap());
293 }
294
295 Ok(())
296}