rustc_hir_analysis/check/
always_applicable.rs1use rustc_attr_ir::find_attr;
8use rustc_data_structures::fx::FxHashSet;
9use rustc_errors::codes::*;
10use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
11use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
12use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
13use rustc_middle::ty::util::CheckRegions;
14use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt, TypingMode};
15use rustc_span::{span_bug, sym};
16use rustc_trait_selection::regions::InferCtxtRegionExt;
17use rustc_trait_selection::traits::{self, ObligationCtxt};
18
19use crate::check::missing_items_must_implement_one_of_err;
20use crate::diagnostics;
21use crate::hir::def_id::{DefId, LocalDefId};
22
23pub(crate) fn check_drop_impl(
40 tcx: TyCtxt<'_>,
41 drop_impl_did: LocalDefId,
42) -> Result<(), ErrorGuaranteed> {
43 match tcx.impl_polarity(drop_impl_did) {
44 ty::ImplPolarity::Positive => {}
45 ty::ImplPolarity::Negative => {
46 return Err(tcx.dcx().emit_err(diagnostics::NegativeDropImplPolarity {
47 span: tcx.def_span(drop_impl_did),
48 }));
49 }
50 }
51
52 tcx.ensure_result().orphan_check_impl(drop_impl_did)?;
53
54 let self_ty = tcx.type_of(drop_impl_did).instantiate_identity().skip_norm_wip();
55
56 match self_ty.kind() {
57 ty::Adt(adt_def, adt_to_impl_args) => {
58 ensure_impl_params_and_item_params_correspond(
59 tcx,
60 drop_impl_did,
61 adt_def.did(),
62 *adt_to_impl_args,
63 )?;
64
65 ensure_all_fields_are_const_destruct(tcx, drop_impl_did, adt_def.did())?;
66
67 ensure_impl_predicates_are_implied_by_item_defn(
68 tcx,
69 drop_impl_did,
70 adt_def.did(),
71 *adt_to_impl_args,
72 )?;
73
74 check_drop_xor_pin_drop(tcx, adt_def.did(), drop_impl_did)?;
75
76 Ok(())
77 }
78 _ => {
79 ::rustc_span::macros::bug_impl(Some(tcx.def_span(drop_impl_did)),
format_args!("incoherent impl of Drop"), Location::caller());span_bug!(tcx.def_span(drop_impl_did), "incoherent impl of Drop");
80 }
81 }
82}
83
84pub(crate) fn check_negative_auto_trait_impl<'tcx>(
85 tcx: TyCtxt<'tcx>,
86 impl_def_id: LocalDefId,
87 impl_trait_ref: ty::TraitRef<'tcx>,
88 polarity: ty::ImplPolarity,
89) -> Result<(), ErrorGuaranteed> {
90 let ty::ImplPolarity::Negative = polarity else {
91 return Ok(());
92 };
93
94 if !tcx.trait_is_auto(impl_trait_ref.def_id) {
95 return Ok(());
96 }
97
98 if tcx.defaultness(impl_def_id).is_default() {
99 tcx.dcx().span_delayed_bug(tcx.def_span(impl_def_id), "default impl cannot be negative");
100 }
101
102 tcx.ensure_result().orphan_check_impl(impl_def_id)?;
103
104 match impl_trait_ref.self_ty().kind() {
105 ty::Adt(adt_def, adt_to_impl_args) => {
106 ensure_impl_params_and_item_params_correspond(
107 tcx,
108 impl_def_id,
109 adt_def.did(),
110 *adt_to_impl_args,
111 )?;
112
113 ensure_impl_predicates_are_implied_by_item_defn(
114 tcx,
115 impl_def_id,
116 adt_def.did(),
117 *adt_to_impl_args,
118 )
119 }
120 _ => {
121 if tcx.features().auto_traits() {
122 Ok(())
127 } else {
128 Err(tcx.dcx().span_delayed_bug(
129 tcx.def_span(impl_def_id),
130 "incoherent impl of negative auto trait",
131 ))
132 }
133 }
134 }
135}
136
137fn ensure_impl_params_and_item_params_correspond<'tcx>(
138 tcx: TyCtxt<'tcx>,
139 impl_def_id: LocalDefId,
140 adt_def_id: DefId,
141 adt_to_impl_args: ty::GenericArgs<'tcx>,
142) -> Result<(), ErrorGuaranteed> {
143 let Err(arg) =
144 tcx.uses_unique_generic_params(adt_to_impl_args.as_slice(), CheckRegions::OnlyParam)
145 else {
146 return Ok(());
147 };
148
149 let impl_span = tcx.def_span(impl_def_id);
150 let item_span = tcx.def_span(adt_def_id);
151 let self_descr = tcx.def_descr(adt_def_id);
152 let polarity = match tcx.impl_polarity(impl_def_id) {
153 ty::ImplPolarity::Positive => "",
154 ty::ImplPolarity::Negative => "!",
155 };
156 let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id()));
157 let mut err = {
tcx.dcx().struct_span_err(impl_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}{1}` impls cannot be specialized",
polarity, trait_name))
})).with_code(E0366)
}struct_span_code_err!(
158 tcx.dcx(),
159 impl_span,
160 E0366,
161 "`{polarity}{trait_name}` impls cannot be specialized",
162 );
163 match arg {
164 ty::util::NotUniqueParam::DuplicateParam(arg) => {
165 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is mentioned multiple times",
arg))
})format!("`{arg}` is mentioned multiple times"))
166 }
167 ty::util::NotUniqueParam::NotParam(arg) => {
168 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is not a generic parameter",
arg))
})format!("`{arg}` is not a generic parameter"))
169 }
170 };
171 err.span_note(
172 item_span,
173 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use the same sequence of generic lifetime, type and const parameters as the {0} definition",
self_descr))
})format!(
174 "use the same sequence of generic lifetime, type and const parameters \
175 as the {self_descr} definition",
176 ),
177 );
178 Err(err.emit_err())
179}
180
181fn ensure_all_fields_are_const_destruct<'tcx>(
182 tcx: TyCtxt<'tcx>,
183 impl_def_id: LocalDefId,
184 adt_def_id: DefId,
185) -> Result<(), ErrorGuaranteed> {
186 if !tcx.is_conditionally_const(impl_def_id) {
187 return Ok(());
188 }
189 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
190 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
191
192 let impl_span = tcx.def_span(impl_def_id.to_def_id());
193 let env = ty::EarlyBinder::bind(tcx, tcx.param_env(impl_def_id))
194 .instantiate_identity()
195 .skip_norm_wip();
196 let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
197 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
198 for field in tcx.adt_def(adt_def_id).all_fields() {
199 let field_ty = field.ty(tcx, args).skip_norm_wip();
200 let cause = traits::ObligationCause::new(
201 tcx.def_span(field.did),
202 impl_def_id,
203 ObligationCauseCode::Misc,
204 );
205 ocx.register_obligation(traits::Obligation::new(
206 tcx,
207 cause,
208 env,
209 ty::ClauseKind::HostEffect(ty::HostEffectClause {
210 trait_ref: ty::TraitRef::new(tcx, destruct_trait, [field_ty]),
211 constness: ty::BoundConstness::Maybe,
212 }),
213 ));
214 }
215 ocx.evaluate_obligations_error_on_ambiguity()
216 .into_iter()
217 .map(|error| {
218 let ty::ClauseKind::HostEffect(eff) =
219 error.root_obligation.predicate.expect_clause().kind().no_bound_vars().unwrap()
220 else {
221 ::core::panicking::unreachable_default_msg()unreachable!()
222 };
223 let field_ty = eff.trait_ref.self_ty();
224 let mut diag = {
tcx.dcx().struct_span_err(error.root_obligation.cause.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` does not implement `[const] Destruct`",
field_ty))
})).with_code(E0367)
}struct_span_code_err!(
225 tcx.dcx(),
226 error.root_obligation.cause.span,
227 E0367,
228 "`{field_ty}` does not implement `[const] Destruct`",
229 )
230 .with_span_note(impl_span, "required for this `Drop` impl");
231 if field_ty.has_param()
232 && let Some(generics) = tcx.hir_node_by_def_id(impl_def_id).generics()
233 {
234 let destruct_def_id = tcx.lang_items().destruct_trait();
235 ty::suggest_constraining_type_param(
236 tcx,
237 generics,
238 &mut diag,
239 &field_ty.to_string(),
240 "[const] Destruct",
241 destruct_def_id,
242 None,
243 );
244 }
245 Err(diag.emit_err())
246 })
247 .collect()
248}
249
250fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
254 tcx: TyCtxt<'tcx>,
255 impl_def_id: LocalDefId,
256 adt_def_id: DefId,
257 adt_to_impl_args: GenericArgs<'tcx>,
258) -> Result<(), ErrorGuaranteed> {
259 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
260 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
261
262 let impl_span = tcx.def_span(impl_def_id.to_def_id());
263 let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id()));
264 let polarity = match tcx.impl_polarity(impl_def_id) {
265 ty::ImplPolarity::Positive => "",
266 ty::ImplPolarity::Negative => "!",
267 };
268 let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args);
283 let adt_env = ty::EarlyBinder::bind_unchecked(tcx.param_env(adt_def_id))
284 .instantiate(tcx, adt_to_impl_args)
285 .skip_norm_wip();
286
287 let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
288 let fresh_adt_ty =
289 tcx.impl_trait_ref(impl_def_id).instantiate(tcx, fresh_impl_args).skip_norm_wip().self_ty();
290
291 ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
292 .expect("equating fully generic trait ref should never fail");
293
294 for (clause, span) in tcx.clauses_of(impl_def_id).instantiate(tcx, fresh_impl_args) {
295 let normalize_cause = traits::ObligationCause::misc(span, impl_def_id);
296 let pred = ocx.normalize(&normalize_cause, adt_env, clause);
297 let cause = traits::ObligationCause::new(
298 span,
299 impl_def_id,
300 ObligationCauseCode::AlwaysApplicableImpl,
301 );
302 ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
303 }
304
305 let errors = ocx.evaluate_obligations_error_on_ambiguity();
312 if !errors.no_errors() {
313 let mut guar = None;
314 let mut root_predicates = FxHashSet::default();
315 for error in errors {
316 let root_predicate = error.root_obligation.predicate;
317 if root_predicates.insert(root_predicate) {
318 let item_span = tcx.def_span(adt_def_id);
319 let self_descr = tcx.def_descr(adt_def_id);
320 guar = Some(
321 {
tcx.dcx().struct_span_err(error.root_obligation.cause.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}{1}` impl requires `{2}` but the {3} it is implemented for does not",
polarity, trait_name, root_predicate, self_descr))
})).with_code(E0367)
}struct_span_code_err!(
322 tcx.dcx(),
323 error.root_obligation.cause.span,
324 E0367,
325 "`{polarity}{trait_name}` impl requires `{root_predicate}` \
326 but the {self_descr} it is implemented for does not",
327 )
328 .with_span_note(item_span, "the implementor must specify the same requirement")
329 .emit_err(),
330 );
331 }
332 }
333 return Err(guar.unwrap());
334 }
335
336 let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []);
337 if !errors.is_empty() {
338 let mut guar = None;
339 for error in errors {
340 let item_span = tcx.def_span(adt_def_id);
341 let self_descr = tcx.def_descr(adt_def_id);
342 let outlives = match error {
343 RegionResolutionError::ConcreteFailure(_, a, b) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", b, a))
})format!("{b}: {a}"),
344 RegionResolutionError::GenericBoundFailure(_, generic, r) => {
345 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", generic, r))
})format!("{generic}: {r}")
346 }
347 RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", b, a))
})format!("{b}: {a}"),
348 RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
349 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}: {0}",
ty::Region::new_var(tcx, a), b))
})format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
350 }
351 RegionResolutionError::CannotNormalize(..) => ::core::panicking::unreachable_default_msg()unreachable!(),
352 };
353 guar = Some(
354 {
tcx.dcx().struct_span_err(error.origin().span(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}{1}` impl requires `{2}` but the {3} it is implemented for does not",
polarity, trait_name, outlives, self_descr))
})).with_code(E0367)
}struct_span_code_err!(
355 tcx.dcx(),
356 error.origin().span(),
357 E0367,
358 "`{polarity}{trait_name}` impl requires `{outlives}` \
359 but the {self_descr} it is implemented for does not",
360 )
361 .with_span_note(item_span, "the implementor must specify the same requirement")
362 .emit_err(),
363 );
364 }
365 return Err(guar.unwrap());
366 }
367
368 Ok(())
369}
370
371fn check_drop_xor_pin_drop<'tcx>(
374 tcx: TyCtxt<'tcx>,
375 adt_def_id: DefId,
376 drop_impl_did: LocalDefId,
377) -> Result<(), ErrorGuaranteed> {
378 let mut drop_span = None;
379 let mut pin_drop_span = None;
380 for item in tcx.associated_items(drop_impl_did).in_definition_order() {
381 match item.kind {
382 ty::AssocKind::Fn { name: sym::drop, .. } => {
383 drop_span = Some(tcx.def_span(item.def_id))
384 }
385 ty::AssocKind::Fn { name: sym::pin_drop, .. } => {
386 pin_drop_span = Some(tcx.def_span(item.def_id))
387 }
388 _ => {}
389 }
390 }
391
392 match (drop_span, pin_drop_span) {
393 (None, None) => {
394 if tcx.features().pin_ergonomics() {
395 return Err(missing_items_must_implement_one_of_err(
396 tcx,
397 drop_impl_did,
398 [sym::drop, sym::pin_drop].into_iter(),
399 None,
400 ));
401 } else {
402 return Err(tcx
403 .dcx()
404 .span_delayed_bug(tcx.def_span(drop_impl_did), "missing `Drop::drop`"));
405 }
406 }
407 (Some(span), None) => {
408 if tcx.adt_def(adt_def_id).is_pin_project() {
409 let pin_v2_span = {
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(adt_def_id, &tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(PinV2(attr)) => {
break 'done Some(*attr);
}
::rustc_attr_ir::Attribute::Tool(..) |
::rustc_attr_ir::Attribute::DeriveHelper(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(tcx, adt_def_id, PinV2(attr) => *attr);
410 let adt_name = tcx.item_name(adt_def_id);
411 return Err(tcx.dcx().emit_err(crate::diagnostics::PinV2WithoutPinDrop {
412 span,
413 pin_v2_span,
414 adt_name,
415 }));
416 }
417 }
418 (None, Some(span)) => {
419 if !tcx.features().pin_ergonomics() {
420 return Err(tcx.dcx().span_delayed_bug(
421 span,
422 "`Drop::pin_drop` should be guarded by the library feature gate",
423 ));
424 }
425 }
426 (Some(drop_span), Some(pin_drop_span)) => {
427 return Err(tcx.dcx().emit_err(crate::diagnostics::ConflictImplDropAndPinDrop {
428 span: tcx.def_span(drop_impl_did),
429 drop_span,
430 pin_drop_span,
431 }));
432 }
433 }
434 Ok(())
435}