rustc_hir_analysis/check/
always_applicable.rs
1use 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: DefId,
40) -> Result<(), ErrorGuaranteed> {
41 let drop_impl_did = drop_impl_did.expect_local();
42
43 match tcx.impl_polarity(drop_impl_did) {
44 ty::ImplPolarity::Positive => {}
45 ty::ImplPolarity::Negative => {
46 return Err(tcx.dcx().emit_err(errors::DropImplPolarity::Negative {
47 span: tcx.def_span(drop_impl_did),
48 }));
49 }
50 ty::ImplPolarity::Reservation => {
51 return Err(tcx.dcx().emit_err(errors::DropImplPolarity::Reservation {
52 span: tcx.def_span(drop_impl_did),
53 }));
54 }
55 }
56
57 tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
58
59 let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
60
61 match dtor_impl_trait_ref.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_impl_predicates_are_implied_by_item_defn(
71 tcx,
72 drop_impl_did,
73 adt_def.did(),
74 adt_to_impl_args,
75 )
76 }
77 _ => {
78 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_ok().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 | ty::ImplPolarity::Reservation => "",
151 ty::ImplPolarity::Negative => "!",
152 };
153 let trait_name = tcx
154 .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
155 let mut err = struct_span_code_err!(
156 tcx.dcx(),
157 impl_span,
158 E0366,
159 "`{polarity}{trait_name}` impls cannot be specialized",
160 );
161 match arg {
162 ty::util::NotUniqueParam::DuplicateParam(arg) => {
163 err.note(format!("`{arg}` is mentioned multiple times"))
164 }
165 ty::util::NotUniqueParam::NotParam(arg) => {
166 err.note(format!("`{arg}` is not a generic parameter"))
167 }
168 };
169 err.span_note(
170 item_span,
171 format!(
172 "use the same sequence of generic lifetime, type and const parameters \
173 as the {self_descr} definition",
174 ),
175 );
176 Err(err.emit())
177}
178
179fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
183 tcx: TyCtxt<'tcx>,
184 impl_def_id: LocalDefId,
185 adt_def_id: DefId,
186 adt_to_impl_args: GenericArgsRef<'tcx>,
187) -> Result<(), ErrorGuaranteed> {
188 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
189 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
190
191 let impl_span = tcx.def_span(impl_def_id.to_def_id());
192 let trait_name = tcx
193 .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
194 let polarity = match tcx.impl_polarity(impl_def_id) {
195 ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
196 ty::ImplPolarity::Negative => "!",
197 };
198 let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args);
213 let adt_env =
214 ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
215
216 let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
217 let fresh_adt_ty =
218 tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
219
220 ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
221 .expect("equating fully generic trait ref should never fail");
222
223 for (clause, span) in tcx.predicates_of(impl_def_id).instantiate(tcx, fresh_impl_args) {
224 let normalize_cause = traits::ObligationCause::misc(span, impl_def_id);
225 let pred = ocx.normalize(&normalize_cause, adt_env, clause);
226 let cause = traits::ObligationCause::new(
227 span,
228 impl_def_id,
229 ObligationCauseCode::AlwaysApplicableImpl,
230 );
231 ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
232 }
233
234 let errors = ocx.select_all_or_error();
241 if !errors.is_empty() {
242 let mut guar = None;
243 let mut root_predicates = FxHashSet::default();
244 for error in errors {
245 let root_predicate = error.root_obligation.predicate;
246 if root_predicates.insert(root_predicate) {
247 let item_span = tcx.def_span(adt_def_id);
248 let self_descr = tcx.def_descr(adt_def_id);
249 guar = Some(
250 struct_span_code_err!(
251 tcx.dcx(),
252 error.root_obligation.cause.span,
253 E0367,
254 "`{polarity}{trait_name}` impl requires `{root_predicate}` \
255 but the {self_descr} it is implemented for does not",
256 )
257 .with_span_note(item_span, "the implementor must specify the same requirement")
258 .emit(),
259 );
260 }
261 }
262 return Err(guar.unwrap());
263 }
264
265 let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []);
266 if !errors.is_empty() {
267 let mut guar = None;
268 for error in errors {
269 let item_span = tcx.def_span(adt_def_id);
270 let self_descr = tcx.def_descr(adt_def_id);
271 let outlives = match error {
272 RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
273 RegionResolutionError::GenericBoundFailure(_, generic, r) => {
274 format!("{generic}: {r}")
275 }
276 RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
277 RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
278 format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
279 }
280 RegionResolutionError::CannotNormalize(..) => unreachable!(),
281 };
282 guar = Some(
283 struct_span_code_err!(
284 tcx.dcx(),
285 error.origin().span(),
286 E0367,
287 "`{polarity}{trait_name}` impl requires `{outlives}` \
288 but the {self_descr} it is implemented for does not",
289 )
290 .with_span_note(item_span, "the implementor must specify the same requirement")
291 .emit(),
292 );
293 }
294 return Err(guar.unwrap());
295 }
296
297 Ok(())
298}