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