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