rustc_hir_analysis/
impl_wf_check.rs1use std::assert_matches::debug_assert_matches;
12
13use min_specialization::check_min_specialization;
14use rustc_data_structures::fx::FxHashSet;
15use rustc_errors::codes::*;
16use rustc_hir::def::DefKind;
17use rustc_hir::def_id::LocalDefId;
18use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
19use rustc_span::ErrorGuaranteed;
20
21use crate::constrained_generic_params as cgp;
22use crate::errors::UnconstrainedGenericParameter;
23
24mod min_specialization;
25
26pub(crate) fn check_impl_wf(
57 tcx: TyCtxt<'_>,
58 impl_def_id: LocalDefId,
59 of_trait: bool,
60) -> Result<(), ErrorGuaranteed> {
61 debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
62
63 let mut res = tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id);
67 res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id, of_trait));
68
69 if of_trait && tcx.features().min_specialization() {
70 res = res.and(check_min_specialization(tcx, impl_def_id));
71 }
72 res
73}
74
75pub(crate) fn enforce_impl_lifetime_params_are_constrained(
76 tcx: TyCtxt<'_>,
77 impl_def_id: LocalDefId,
78 of_trait: bool,
79) -> Result<(), ErrorGuaranteed> {
80 let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
81
82 impl_self_ty.error_reported()?;
85
86 let impl_generics = tcx.generics_of(impl_def_id);
87 let impl_predicates = tcx.predicates_of(impl_def_id);
88 let impl_trait_ref = of_trait.then(|| tcx.impl_trait_ref(impl_def_id).instantiate_identity());
89
90 impl_trait_ref.error_reported()?;
91
92 let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
93 cgp::identify_constrained_generic_params(
94 tcx,
95 impl_predicates,
96 impl_trait_ref,
97 &mut input_parameters,
98 );
99
100 let lifetimes_in_associated_types: FxHashSet<_> = tcx
102 .associated_item_def_ids(impl_def_id)
103 .iter()
104 .flat_map(|def_id| {
105 let item = tcx.associated_item(def_id);
106 match item.kind {
107 ty::AssocKind::Type { .. } => {
108 if item.defaultness(tcx).has_value() {
109 cgp::parameters_for(tcx, tcx.type_of(def_id).instantiate_identity(), true)
110 } else {
111 vec![]
112 }
113 }
114 ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => vec![],
115 }
116 })
117 .collect();
118
119 let mut res = Ok(());
120 for param in &impl_generics.own_params {
121 match param.kind {
122 ty::GenericParamDefKind::Lifetime => {
123 let param_lt = cgp::Parameter::from(param.to_early_bound_region_data());
142 if lifetimes_in_associated_types.contains(¶m_lt)
143 && !input_parameters.contains(¶m_lt)
144 {
145 let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
146 span: tcx.def_span(param.def_id),
147 param_name: tcx.item_ident(param.def_id),
148 param_def_kind: tcx.def_descr(param.def_id),
149 const_param_note: false,
150 const_param_note2: false,
151 });
152 diag.code(E0207);
153 res = Err(diag.emit());
154 }
155 }
156 ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => {
157 }
159 }
160 }
161 res
162}
163
164pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
165 tcx: TyCtxt<'_>,
166 impl_def_id: LocalDefId,
167) -> Result<(), ErrorGuaranteed> {
168 let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
169
170 impl_self_ty.error_reported()?;
173
174 let impl_generics = tcx.generics_of(impl_def_id);
175 let impl_predicates = tcx.predicates_of(impl_def_id);
176 let impl_trait_ref =
177 tcx.impl_opt_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
178
179 impl_trait_ref.error_reported()?;
180
181 let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
182 cgp::identify_constrained_generic_params(
183 tcx,
184 impl_predicates,
185 impl_trait_ref,
186 &mut input_parameters,
187 );
188
189 let mut res = Ok(());
190 for param in &impl_generics.own_params {
191 let err = match param.kind {
192 ty::GenericParamDefKind::Type { .. } => {
194 let param_ty = ty::ParamTy::for_def(param);
195 !input_parameters.contains(&cgp::Parameter::from(param_ty))
196 }
197 ty::GenericParamDefKind::Const { .. } => {
198 let param_ct = ty::ParamConst::for_def(param);
199 !input_parameters.contains(&cgp::Parameter::from(param_ct))
200 }
201 ty::GenericParamDefKind::Lifetime => {
202 false
204 }
205 };
206 if err {
207 let const_param_note = matches!(param.kind, ty::GenericParamDefKind::Const { .. });
208 let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
209 span: tcx.def_span(param.def_id),
210 param_name: tcx.item_ident(param.def_id),
211 param_def_kind: tcx.def_descr(param.def_id),
212 const_param_note,
213 const_param_note2: const_param_note,
214 });
215 diag.code(E0207);
216 res = Err(diag.emit());
217 }
218 }
219 res
220}