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