1 use crate::constrained_generic_params
::{identify_constrained_generic_params, Parameter}
;
4 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet, FxIndexSet}
;
5 use rustc_errors
::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}
;
7 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
8 use rustc_hir
::lang_items
::LangItem
;
9 use rustc_hir
::ItemKind
;
10 use rustc_infer
::infer
::outlives
::env
::{OutlivesEnvironment, RegionBoundPairs}
;
11 use rustc_infer
::infer
::outlives
::obligations
::TypeOutlives
;
12 use rustc_infer
::infer
::{self, InferCtxt, TyCtxtInferExt}
;
13 use rustc_middle
::mir
::ConstraintCategory
;
14 use rustc_middle
::ty
::query
::Providers
;
15 use rustc_middle
::ty
::trait_def
::TraitSpecializationKind
;
16 use rustc_middle
::ty
::{
17 self, AdtKind
, DefIdTree
, GenericParamDefKind
, Ty
, TyCtxt
, TypeFoldable
, TypeSuperVisitable
,
18 TypeVisitable
, TypeVisitor
,
20 use rustc_middle
::ty
::{GenericArgKind, InternalSubsts}
;
21 use rustc_session
::parse
::feature_err
;
22 use rustc_span
::symbol
::{sym, Ident, Symbol}
;
23 use rustc_span
::{Span, DUMMY_SP}
;
24 use rustc_target
::spec
::abi
::Abi
;
25 use rustc_trait_selection
::autoderef
::Autoderef
;
26 use rustc_trait_selection
::traits
::error_reporting
::TypeErrCtxtExt
;
27 use rustc_trait_selection
::traits
::outlives_bounds
::InferCtxtExt
as _
;
28 use rustc_trait_selection
::traits
::query
::evaluate_obligation
::InferCtxtExt
as _
;
29 use rustc_trait_selection
::traits
::{
30 self, ObligationCause
, ObligationCauseCode
, ObligationCtxt
, WellFormedLoc
,
33 use std
::cell
::LazyCell
;
34 use std
::convert
::TryInto
;
36 use std
::ops
::{ControlFlow, Deref}
;
38 pub(super) struct WfCheckingCtxt
<'a
, 'tcx
> {
39 pub(super) ocx
: ObligationCtxt
<'a
, 'tcx
>,
42 param_env
: ty
::ParamEnv
<'tcx
>,
44 impl<'a
, 'tcx
> Deref
for WfCheckingCtxt
<'a
, 'tcx
> {
45 type Target
= ObligationCtxt
<'a
, 'tcx
>;
46 fn deref(&self) -> &Self::Target
{
51 impl<'tcx
> WfCheckingCtxt
<'_
, 'tcx
> {
52 fn tcx(&self) -> TyCtxt
<'tcx
> {
56 // Convenience function to normalize during wfcheck. This performs
57 // `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.
58 fn normalize
<T
>(&self, span
: Span
, loc
: Option
<WellFormedLoc
>, value
: T
) -> T
60 T
: TypeFoldable
<'tcx
>,
63 &ObligationCause
::new(span
, self.body_id
, ObligationCauseCode
::WellFormed(loc
)),
69 fn register_wf_obligation(
72 loc
: Option
<WellFormedLoc
>,
73 arg
: ty
::GenericArg
<'tcx
>,
76 traits
::ObligationCause
::new(span
, self.body_id
, ObligationCauseCode
::WellFormed(loc
));
77 // for a type to be WF, we do not need to check if const trait predicates satisfy.
78 let param_env
= self.param_env
.without_const();
79 self.ocx
.register_obligation(traits
::Obligation
::new(
83 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(arg
)),
88 pub(super) fn enter_wf_checking_ctxt
<'tcx
, F
>(
91 body_def_id
: LocalDefId
,
94 F
: for<'a
> FnOnce(&WfCheckingCtxt
<'a
, 'tcx
>),
96 let param_env
= tcx
.param_env(body_def_id
);
97 let body_id
= tcx
.hir().local_def_id_to_hir_id(body_def_id
);
98 let infcx
= &tcx
.infer_ctxt().build();
99 let ocx
= ObligationCtxt
::new(infcx
);
101 let assumed_wf_types
= ocx
.assumed_wf_types(param_env
, span
, body_def_id
);
103 let mut wfcx
= WfCheckingCtxt { ocx, span, body_id, param_env }
;
105 if !tcx
.features().trivial_bounds
{
106 wfcx
.check_false_global_bounds()
109 let errors
= wfcx
.select_all_or_error();
110 if !errors
.is_empty() {
111 infcx
.err_ctxt().report_fulfillment_errors(&errors
, None
);
115 let implied_bounds
= infcx
.implied_bounds_tys(param_env
, body_id
, assumed_wf_types
);
116 let outlives_environment
=
117 OutlivesEnvironment
::with_bounds(param_env
, Some(infcx
), implied_bounds
);
119 infcx
.check_region_obligations_and_report_errors(body_def_id
, &outlives_environment
);
122 fn check_well_formed(tcx
: TyCtxt
<'_
>, def_id
: hir
::OwnerId
) {
123 let node
= tcx
.hir().owner(def_id
);
125 hir
::OwnerNode
::Crate(_
) => {}
126 hir
::OwnerNode
::Item(item
) => check_item(tcx
, item
),
127 hir
::OwnerNode
::TraitItem(item
) => check_trait_item(tcx
, item
),
128 hir
::OwnerNode
::ImplItem(item
) => check_impl_item(tcx
, item
),
129 hir
::OwnerNode
::ForeignItem(item
) => check_foreign_item(tcx
, item
),
132 if let Some(generics
) = node
.generics() {
133 for param
in generics
.params
{
134 check_param_wf(tcx
, param
)
139 /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
140 /// well-formed, meaning that they do not require any constraints not declared in the struct
141 /// definition itself. For example, this definition would be illegal:
144 /// struct Ref<'a, T> { x: &'a T }
147 /// because the type did not declare that `T:'a`.
149 /// We do this check as a pre-pass before checking fn bodies because if these constraints are
150 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
152 #[instrument(skip(tcx), level = "debug")]
153 fn check_item
<'tcx
>(tcx
: TyCtxt
<'tcx
>, item
: &'tcx hir
::Item
<'tcx
>) {
154 let def_id
= item
.owner_id
.def_id
;
158 item
.name
= ? tcx
.def_path_str(def_id
.to_def_id())
162 // Right now we check that every default trait implementation
163 // has an implementation of itself. Basically, a case like:
165 // impl Trait for T {}
167 // has a requirement of `T: Trait` which was required for default
168 // method implementations. Although this could be improved now that
169 // there's a better infrastructure in place for this, it's being left
170 // for a follow-up work.
172 // Since there's such a requirement, we need to check *just* positive
173 // implementations, otherwise things like:
175 // impl !Send for T {}
177 // won't be allowed unless there's an *explicit* implementation of `Send`
179 hir
::ItemKind
::Impl(ref impl_
) => {
181 .impl_trait_ref(def_id
)
182 .map_or(false, |trait_ref
| tcx
.trait_is_auto(trait_ref
.def_id
));
183 if let (hir
::Defaultness
::Default { .. }
, true) = (impl_
.defaultness
, is_auto
) {
184 let sp
= impl_
.of_trait
.as_ref().map_or(item
.span
, |t
| t
.path
.span
);
186 tcx
.sess
.struct_span_err(sp
, "impls of auto traits cannot be default");
187 err
.span_labels(impl_
.defaultness_span
, "default because of this");
188 err
.span_label(sp
, "auto trait");
191 // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
192 match (tcx
.impl_polarity(def_id
), impl_
.polarity
) {
193 (ty
::ImplPolarity
::Positive
, _
) => {
194 check_impl(tcx
, item
, impl_
.self_ty
, &impl_
.of_trait
, impl_
.constness
);
196 (ty
::ImplPolarity
::Negative
, ast
::ImplPolarity
::Negative(span
)) => {
197 // FIXME(#27579): what amount of WF checking do we need for neg impls?
198 if let hir
::Defaultness
::Default { .. }
= impl_
.defaultness
{
199 let mut spans
= vec
![span
];
200 spans
.extend(impl_
.defaultness_span
);
205 "negative impls cannot be default impls"
210 (ty
::ImplPolarity
::Reservation
, _
) => {
211 // FIXME: what amount of WF checking do we need for reservation impls?
216 hir
::ItemKind
::Fn(ref sig
, ..) => {
217 check_item_fn(tcx
, def_id
, item
.ident
, item
.span
, sig
.decl
);
219 hir
::ItemKind
::Static(ty
, ..) => {
220 check_item_type(tcx
, def_id
, ty
.span
, false);
222 hir
::ItemKind
::Const(ty
, ..) => {
223 check_item_type(tcx
, def_id
, ty
.span
, false);
225 hir
::ItemKind
::Struct(_
, ref ast_generics
) => {
226 check_type_defn(tcx
, item
, false);
227 check_variances_for_type_defn(tcx
, item
, ast_generics
);
229 hir
::ItemKind
::Union(_
, ref ast_generics
) => {
230 check_type_defn(tcx
, item
, true);
231 check_variances_for_type_defn(tcx
, item
, ast_generics
);
233 hir
::ItemKind
::Enum(_
, ref ast_generics
) => {
234 check_type_defn(tcx
, item
, true);
235 check_variances_for_type_defn(tcx
, item
, ast_generics
);
237 hir
::ItemKind
::Trait(..) => {
238 check_trait(tcx
, item
);
240 hir
::ItemKind
::TraitAlias(..) => {
241 check_trait(tcx
, item
);
243 // `ForeignItem`s are handled separately.
244 hir
::ItemKind
::ForeignMod { .. }
=> {}
249 fn check_foreign_item(tcx
: TyCtxt
<'_
>, item
: &hir
::ForeignItem
<'_
>) {
250 let def_id
= item
.owner_id
.def_id
;
254 item
.name
= ? tcx
.def_path_str(def_id
.to_def_id())
258 hir
::ForeignItemKind
::Fn(decl
, ..) => {
259 check_item_fn(tcx
, def_id
, item
.ident
, item
.span
, decl
)
261 hir
::ForeignItemKind
::Static(ty
, ..) => check_item_type(tcx
, def_id
, ty
.span
, true),
262 hir
::ForeignItemKind
::Type
=> (),
266 fn check_trait_item(tcx
: TyCtxt
<'_
>, trait_item
: &hir
::TraitItem
<'_
>) {
267 let def_id
= trait_item
.owner_id
.def_id
;
269 let (method_sig
, span
) = match trait_item
.kind
{
270 hir
::TraitItemKind
::Fn(ref sig
, _
) => (Some(sig
), trait_item
.span
),
271 hir
::TraitItemKind
::Type(_bounds
, Some(ty
)) => (None
, ty
.span
),
272 _
=> (None
, trait_item
.span
),
274 check_object_unsafe_self_trait_by_name(tcx
, trait_item
);
275 check_associated_item(tcx
, def_id
, span
, method_sig
);
277 let encl_trait_def_id
= tcx
.local_parent(def_id
);
278 let encl_trait
= tcx
.hir().expect_item(encl_trait_def_id
);
279 let encl_trait_def_id
= encl_trait
.owner_id
.to_def_id();
280 let fn_lang_item_name
= if Some(encl_trait_def_id
) == tcx
.lang_items().fn_trait() {
282 } else if Some(encl_trait_def_id
) == tcx
.lang_items().fn_mut_trait() {
288 if let (Some(fn_lang_item_name
), "call") =
289 (fn_lang_item_name
, trait_item
.ident
.name
.to_ident_string().as_str())
291 // We are looking at the `call` function of the `fn` or `fn_mut` lang item.
292 // Do some rudimentary sanity checking to avoid an ICE later (issue #83471).
293 if let Some(hir
::FnSig { decl, span, .. }
) = method_sig
{
294 if let [self_ty
, _
] = decl
.inputs
{
295 if !matches
!(self_ty
.kind
, hir
::TyKind
::Rptr(_
, _
)) {
300 "first argument of `call` in `{fn_lang_item_name}` lang item must be a reference",
310 "`call` function in `{fn_lang_item_name}` lang item takes exactly two arguments",
320 "`call` trait item in `{fn_lang_item_name}` lang item must be a function",
328 /// Require that the user writes where clauses on GATs for the implicit
329 /// outlives bounds involving trait parameters in trait functions and
330 /// lifetimes passed as GAT substs. See `self-outlives-lint` test.
332 /// We use the following trait as an example throughout this function:
333 /// ```rust,ignore (this code fails due to this lint)
335 /// type Iter<'a>: Iterator<Item = Self::Item<'a>>;
337 /// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
340 fn check_gat_where_clauses(tcx
: TyCtxt
<'_
>, associated_items
: &[hir
::TraitItemRef
]) {
341 // Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.
342 let mut required_bounds_by_item
= FxHashMap
::default();
344 // Loop over all GATs together, because if this lint suggests adding a where-clause bound
345 // to one GAT, it might then require us to an additional bound on another GAT.
346 // In our `IntoIter` example, we discover a missing `Self: 'a` bound on `Iter<'a>`, which
347 // then in a second loop adds a `Self: 'a` bound to `Item` due to the relationship between
350 let mut should_continue
= false;
351 for gat_item
in associated_items
{
352 let gat_def_id
= gat_item
.id
.owner_id
;
353 let gat_item
= tcx
.associated_item(gat_def_id
);
354 // If this item is not an assoc ty, or has no substs, then it's not a GAT
355 if gat_item
.kind
!= ty
::AssocKind
::Type
{
358 let gat_generics
= tcx
.generics_of(gat_def_id
);
359 // FIXME(jackh726): we can also warn in the more general case
360 if gat_generics
.params
.is_empty() {
364 // Gather the bounds with which all other items inside of this trait constrain the GAT.
365 // This is calculated by taking the intersection of the bounds that each item
366 // constrains the GAT with individually.
367 let mut new_required_bounds
: Option
<FxHashSet
<ty
::Predicate
<'_
>>> = None
;
368 for item
in associated_items
{
369 let item_def_id
= item
.id
.owner_id
;
370 // Skip our own GAT, since it does not constrain itself at all.
371 if item_def_id
== gat_def_id
{
375 let item_hir_id
= item
.id
.hir_id();
376 let param_env
= tcx
.param_env(item_def_id
);
378 let item_required_bounds
= match item
.kind
{
379 // In our example, this corresponds to `into_iter` method
380 hir
::AssocItemKind
::Fn { .. }
=> {
381 // For methods, we check the function signature's return type for any GATs
382 // to constrain. In the `into_iter` case, we see that the return type
383 // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
384 let sig
: ty
::FnSig
<'_
> = tcx
.liberate_late_bound_regions(
385 item_def_id
.to_def_id(),
386 tcx
.fn_sig(item_def_id
),
392 sig
.inputs_and_output
,
393 // We also assume that all of the function signature's parameter types
395 &sig
.inputs().iter().copied().collect(),
400 // In our example, this corresponds to the `Iter` and `Item` associated types
401 hir
::AssocItemKind
::Type
=> {
402 // If our associated item is a GAT with missing bounds, add them to
403 // the param-env here. This allows this GAT to propagate missing bounds
405 let param_env
= augment_param_env(
408 required_bounds_by_item
.get(&item_def_id
),
414 tcx
.explicit_item_bounds(item_def_id
)
417 .collect
::<Vec
<_
>>(),
418 &FxIndexSet
::default(),
423 hir
::AssocItemKind
::Const
=> None
,
426 if let Some(item_required_bounds
) = item_required_bounds
{
427 // Take the intersection of the required bounds for this GAT, and
428 // the item_required_bounds which are the ones implied by just
430 // This is why we use an Option<_>, since we need to distinguish
431 // the empty set of bounds from the _uninitialized_ set of bounds.
432 if let Some(new_required_bounds
) = &mut new_required_bounds
{
433 new_required_bounds
.retain(|b
| item_required_bounds
.contains(b
));
435 new_required_bounds
= Some(item_required_bounds
);
440 if let Some(new_required_bounds
) = new_required_bounds
{
441 let required_bounds
= required_bounds_by_item
.entry(gat_def_id
).or_default();
442 if new_required_bounds
.into_iter().any(|p
| required_bounds
.insert(p
)) {
443 // Iterate until our required_bounds no longer change
444 // Since they changed here, we should continue the loop
445 should_continue
= true;
449 // We know that this loop will eventually halt, since we only set `should_continue` if the
450 // `required_bounds` for this item grows. Since we are not creating any new region or type
451 // variables, the set of all region and type bounds that we could ever insert are limited
452 // by the number of unique types and regions we observe in a given item.
453 if !should_continue
{
458 for (gat_def_id
, required_bounds
) in required_bounds_by_item
{
459 let gat_item_hir
= tcx
.hir().expect_trait_item(gat_def_id
.def_id
);
460 debug
!(?required_bounds
);
461 let param_env
= tcx
.param_env(gat_def_id
);
462 let gat_hir
= gat_item_hir
.hir_id();
464 let mut unsatisfied_bounds
: Vec
<_
> = required_bounds
466 .filter(|clause
| match clause
.kind().skip_binder() {
467 ty
::PredicateKind
::Clause(ty
::Clause
::RegionOutlives(ty
::OutlivesPredicate(
471 !region_known_to_outlive(tcx
, gat_hir
, param_env
, &FxIndexSet
::default(), a
, b
)
473 ty
::PredicateKind
::Clause(ty
::Clause
::TypeOutlives(ty
::OutlivesPredicate(
476 ))) => !ty_known_to_outlive(tcx
, gat_hir
, param_env
, &FxIndexSet
::default(), a
, b
),
477 _
=> bug
!("Unexpected PredicateKind"),
479 .map(|clause
| clause
.to_string())
482 // We sort so that order is predictable
483 unsatisfied_bounds
.sort();
485 if !unsatisfied_bounds
.is_empty() {
486 let plural
= pluralize
!(unsatisfied_bounds
.len());
487 let mut err
= tcx
.sess
.struct_span_err(
489 &format
!("missing required bound{} on `{}`", plural
, gat_item_hir
.ident
),
492 let suggestion
= format
!(
494 gat_item_hir
.generics
.add_where_or_trailing_comma(),
495 unsatisfied_bounds
.join(", "),
498 gat_item_hir
.generics
.tail_span_for_predicate_suggestion(),
499 &format
!("add the required where clause{plural}"),
501 Applicability
::MachineApplicable
,
505 if unsatisfied_bounds
.len() > 1 { "these bounds are" }
else { "this bound is" }
;
507 "{} currently required to ensure that impls have maximum flexibility",
511 "we are soliciting feedback, see issue #87479 \
512 <https://github.com/rust-lang/rust/issues/87479> \
513 for more information",
521 /// Add a new set of predicates to the caller_bounds of an existing param_env.
522 fn augment_param_env
<'tcx
>(
524 param_env
: ty
::ParamEnv
<'tcx
>,
525 new_predicates
: Option
<&FxHashSet
<ty
::Predicate
<'tcx
>>>,
526 ) -> ty
::ParamEnv
<'tcx
> {
527 let Some(new_predicates
) = new_predicates
else {
531 if new_predicates
.is_empty() {
536 tcx
.mk_predicates(param_env
.caller_bounds().iter().chain(new_predicates
.iter().cloned()));
537 // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
538 // i.e. traits::normalize_param_env_or_error
539 ty
::ParamEnv
::new(bounds
, param_env
.reveal(), param_env
.constness())
542 /// We use the following trait as an example throughout this function.
543 /// Specifically, let's assume that `to_check` here is the return type
544 /// of `into_iter`, and the GAT we are checking this for is `Iter`.
545 /// ```rust,ignore (this code fails due to this lint)
547 /// type Iter<'a>: Iterator<Item = Self::Item<'a>>;
549 /// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
552 fn gather_gat_bounds
<'tcx
, T
: TypeFoldable
<'tcx
>>(
554 param_env
: ty
::ParamEnv
<'tcx
>,
555 item_hir
: hir
::HirId
,
557 wf_tys
: &FxIndexSet
<Ty
<'tcx
>>,
558 gat_def_id
: LocalDefId
,
559 gat_generics
: &'tcx ty
::Generics
,
560 ) -> Option
<FxHashSet
<ty
::Predicate
<'tcx
>>> {
561 // The bounds we that we would require from `to_check`
562 let mut bounds
= FxHashSet
::default();
564 let (regions
, types
) = GATSubstCollector
::visit(gat_def_id
.to_def_id(), to_check
);
566 // If both regions and types are empty, then this GAT isn't in the
567 // set of types we are checking, and we shouldn't try to do clause analysis
568 // (particularly, doing so would end up with an empty set of clauses,
569 // since the current method would require none, and we take the
570 // intersection of requirements of all methods)
571 if types
.is_empty() && regions
.is_empty() {
575 for (region_a
, region_a_idx
) in ®ions
{
576 // Ignore `'static` lifetimes for the purpose of this lint: it's
577 // because we know it outlives everything and so doesn't give meaningful
579 if let ty
::ReStatic
= **region_a
{
582 // For each region argument (e.g., `'a` in our example), check for a
583 // relationship to the type arguments (e.g., `Self`). If there is an
584 // outlives relationship (`Self: 'a`), then we want to ensure that is
585 // reflected in a where clause on the GAT itself.
586 for (ty
, ty_idx
) in &types
{
587 // In our example, requires that `Self: 'a`
588 if ty_known_to_outlive(tcx
, item_hir
, param_env
, &wf_tys
, *ty
, *region_a
) {
589 debug
!(?ty_idx
, ?region_a_idx
);
590 debug
!("required clause: {ty} must outlive {region_a}");
591 // Translate into the generic parameters of the GAT. In
592 // our example, the type was `Self`, which will also be
593 // `Self` in the GAT.
594 let ty_param
= gat_generics
.param_at(*ty_idx
, tcx
);
596 .mk_ty(ty
::Param(ty
::ParamTy { index: ty_param.index, name: ty_param.name }
));
597 // Same for the region. In our example, 'a corresponds
598 // to the 'me parameter.
599 let region_param
= gat_generics
.param_at(*region_a_idx
, tcx
);
601 tcx
.mk_region(ty
::RegionKind
::ReEarlyBound(ty
::EarlyBoundRegion
{
602 def_id
: region_param
.def_id
,
603 index
: region_param
.index
,
604 name
: region_param
.name
,
606 // The predicate we expect to see. (In our example,
608 let clause
= ty
::PredicateKind
::Clause(ty
::Clause
::TypeOutlives(
609 ty
::OutlivesPredicate(ty_param
, region_param
),
611 let clause
= tcx
.mk_predicate(ty
::Binder
::dummy(clause
));
612 bounds
.insert(clause
);
616 // For each region argument (e.g., `'a` in our example), also check for a
617 // relationship to the other region arguments. If there is an outlives
618 // relationship, then we want to ensure that is reflected in the where clause
619 // on the GAT itself.
620 for (region_b
, region_b_idx
) in ®ions
{
621 // Again, skip `'static` because it outlives everything. Also, we trivially
622 // know that a region outlives itself.
623 if ty
::ReStatic
== **region_b
|| region_a
== region_b
{
626 if region_known_to_outlive(tcx
, item_hir
, param_env
, &wf_tys
, *region_a
, *region_b
) {
627 debug
!(?region_a_idx
, ?region_b_idx
);
628 debug
!("required clause: {region_a} must outlive {region_b}");
629 // Translate into the generic parameters of the GAT.
630 let region_a_param
= gat_generics
.param_at(*region_a_idx
, tcx
);
632 tcx
.mk_region(ty
::RegionKind
::ReEarlyBound(ty
::EarlyBoundRegion
{
633 def_id
: region_a_param
.def_id
,
634 index
: region_a_param
.index
,
635 name
: region_a_param
.name
,
637 // Same for the region.
638 let region_b_param
= gat_generics
.param_at(*region_b_idx
, tcx
);
640 tcx
.mk_region(ty
::RegionKind
::ReEarlyBound(ty
::EarlyBoundRegion
{
641 def_id
: region_b_param
.def_id
,
642 index
: region_b_param
.index
,
643 name
: region_b_param
.name
,
645 // The predicate we expect to see.
646 let clause
= ty
::PredicateKind
::Clause(ty
::Clause
::RegionOutlives(
647 ty
::OutlivesPredicate(region_a_param
, region_b_param
),
649 let clause
= tcx
.mk_predicate(ty
::Binder
::dummy(clause
));
650 bounds
.insert(clause
);
658 /// Given a known `param_env` and a set of well formed types, can we prove that
659 /// `ty` outlives `region`.
660 fn ty_known_to_outlive
<'tcx
>(
663 param_env
: ty
::ParamEnv
<'tcx
>,
664 wf_tys
: &FxIndexSet
<Ty
<'tcx
>>,
666 region
: ty
::Region
<'tcx
>,
668 resolve_regions_with_wf_tys(tcx
, id
, param_env
, &wf_tys
, |infcx
, region_bound_pairs
| {
669 let origin
= infer
::RelateParamBound(DUMMY_SP
, ty
, None
);
670 let outlives
= &mut TypeOutlives
::new(infcx
, tcx
, region_bound_pairs
, None
, param_env
);
671 outlives
.type_must_outlive(origin
, ty
, region
, ConstraintCategory
::BoringNoLocation
);
675 /// Given a known `param_env` and a set of well formed types, can we prove that
676 /// `region_a` outlives `region_b`
677 fn region_known_to_outlive
<'tcx
>(
680 param_env
: ty
::ParamEnv
<'tcx
>,
681 wf_tys
: &FxIndexSet
<Ty
<'tcx
>>,
682 region_a
: ty
::Region
<'tcx
>,
683 region_b
: ty
::Region
<'tcx
>,
685 resolve_regions_with_wf_tys(tcx
, id
, param_env
, &wf_tys
, |mut infcx
, _
| {
686 use rustc_infer
::infer
::outlives
::obligations
::TypeOutlivesDelegate
;
687 let origin
= infer
::RelateRegionParamBound(DUMMY_SP
);
688 // `region_a: region_b` -> `region_b <= region_a`
689 infcx
.push_sub_region_constraint(
693 ConstraintCategory
::BoringNoLocation
,
698 /// Given a known `param_env` and a set of well formed types, set up an
699 /// `InferCtxt`, call the passed function (to e.g. set up region constraints
700 /// to be tested), then resolve region and return errors
701 fn resolve_regions_with_wf_tys
<'tcx
>(
704 param_env
: ty
::ParamEnv
<'tcx
>,
705 wf_tys
: &FxIndexSet
<Ty
<'tcx
>>,
706 add_constraints
: impl for<'a
> FnOnce(&'a InferCtxt
<'tcx
>, &'a RegionBoundPairs
<'tcx
>),
708 // Unfortunately, we have to use a new `InferCtxt` each call, because
709 // region constraints get added and solved there and we need to test each
710 // call individually.
711 let infcx
= tcx
.infer_ctxt().build();
712 let outlives_environment
= OutlivesEnvironment
::with_bounds(
715 infcx
.implied_bounds_tys(param_env
, id
, wf_tys
.clone()),
717 let region_bound_pairs
= outlives_environment
.region_bound_pairs();
719 add_constraints(&infcx
, region_bound_pairs
);
721 infcx
.process_registered_region_obligations(
722 outlives_environment
.region_bound_pairs(),
725 let errors
= infcx
.resolve_regions(&outlives_environment
);
727 debug
!(?errors
, "errors");
729 // If we were able to prove that the type outlives the region without
730 // an error, it must be because of the implied or explicit bounds...
734 /// TypeVisitor that looks for uses of GATs like
735 /// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
736 /// the two vectors, `regions` and `types` (depending on their kind). For each
737 /// parameter `Pi` also track the index `i`.
738 struct GATSubstCollector
<'tcx
> {
740 // Which region appears and which parameter index its substituted for
741 regions
: FxHashSet
<(ty
::Region
<'tcx
>, usize)>,
742 // Which params appears and which parameter index its substituted for
743 types
: FxHashSet
<(Ty
<'tcx
>, usize)>,
746 impl<'tcx
> GATSubstCollector
<'tcx
> {
747 fn visit
<T
: TypeFoldable
<'tcx
>>(
750 ) -> (FxHashSet
<(ty
::Region
<'tcx
>, usize)>, FxHashSet
<(Ty
<'tcx
>, usize)>) {
752 GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() }
;
753 t
.visit_with(&mut visitor
);
754 (visitor
.regions
, visitor
.types
)
758 impl<'tcx
> TypeVisitor
<'tcx
> for GATSubstCollector
<'tcx
> {
761 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
763 ty
::Projection(p
) if p
.item_def_id
== self.gat
=> {
764 for (idx
, subst
) in p
.substs
.iter().enumerate() {
765 match subst
.unpack() {
766 GenericArgKind
::Lifetime(lt
) if !lt
.is_late_bound() => {
767 self.regions
.insert((lt
, idx
));
769 GenericArgKind
::Type(t
) => {
770 self.types
.insert((t
, idx
));
778 t
.super_visit_with(self)
782 fn could_be_self(trait_def_id
: LocalDefId
, ty
: &hir
::Ty
<'_
>) -> bool
{
784 hir
::TyKind
::TraitObject([trait_ref
], ..) => match trait_ref
.trait_ref
.path
.segments
{
785 [s
] => s
.res
.opt_def_id() == Some(trait_def_id
.to_def_id()),
792 /// Detect when an object unsafe trait is referring to itself in one of its associated items.
793 /// When this is done, suggest using `Self` instead.
794 fn check_object_unsafe_self_trait_by_name(tcx
: TyCtxt
<'_
>, item
: &hir
::TraitItem
<'_
>) {
795 let (trait_name
, trait_def_id
) =
796 match tcx
.hir().get_by_def_id(tcx
.hir().get_parent_item(item
.hir_id()).def_id
) {
797 hir
::Node
::Item(item
) => match item
.kind
{
798 hir
::ItemKind
::Trait(..) => (item
.ident
, item
.owner_id
),
803 let mut trait_should_be_self
= vec
![];
805 hir
::TraitItemKind
::Const(ty
, _
) | hir
::TraitItemKind
::Type(_
, Some(ty
))
806 if could_be_self(trait_def_id
.def_id
, ty
) =>
808 trait_should_be_self
.push(ty
.span
)
810 hir
::TraitItemKind
::Fn(sig
, _
) => {
811 for ty
in sig
.decl
.inputs
{
812 if could_be_self(trait_def_id
.def_id
, ty
) {
813 trait_should_be_self
.push(ty
.span
);
816 match sig
.decl
.output
{
817 hir
::FnRetTy
::Return(ty
) if could_be_self(trait_def_id
.def_id
, ty
) => {
818 trait_should_be_self
.push(ty
.span
);
825 if !trait_should_be_self
.is_empty() {
826 if tcx
.object_safety_violations(trait_def_id
).is_empty() {
829 let sugg
= trait_should_be_self
.iter().map(|span
| (*span
, "Self".to_string())).collect();
832 trait_should_be_self
,
833 "associated item referring to unboxed trait object for its own trait",
835 .span_label(trait_name
.span
, "in this trait")
836 .multipart_suggestion(
837 "you might have meant to use `Self` to refer to the implementing type",
839 Applicability
::MachineApplicable
,
845 fn check_impl_item(tcx
: TyCtxt
<'_
>, impl_item
: &hir
::ImplItem
<'_
>) {
846 let (method_sig
, span
) = match impl_item
.kind
{
847 hir
::ImplItemKind
::Fn(ref sig
, _
) => (Some(sig
), impl_item
.span
),
848 // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
849 hir
::ImplItemKind
::Type(ty
) if ty
.span
!= DUMMY_SP
=> (None
, ty
.span
),
850 _
=> (None
, impl_item
.span
),
853 check_associated_item(tcx
, impl_item
.owner_id
.def_id
, span
, method_sig
);
856 fn check_param_wf(tcx
: TyCtxt
<'_
>, param
: &hir
::GenericParam
<'_
>) {
858 // We currently only check wf of const params here.
859 hir
::GenericParamKind
::Lifetime { .. }
| hir
::GenericParamKind
::Type { .. }
=> (),
861 // Const parameters are well formed if their type is structural match.
862 hir
::GenericParamKind
::Const { ty: hir_ty, default: _ }
=> {
863 let ty
= tcx
.type_of(param
.def_id
);
865 if tcx
.features().adt_const_params
{
866 if let Some(non_structural_match_ty
) =
867 traits
::search_for_adt_const_param_violation(param
.span
, tcx
, ty
)
869 // We use the same error code in both branches, because this is really the same
870 // issue: we just special-case the message for type parameters to make it
872 match non_structural_match_ty
.kind() {
874 // Const parameters may not have type parameters as their types,
875 // because we cannot be sure that the type parameter derives `PartialEq`
876 // and `Eq` (just implementing them is not enough for `structural_match`).
881 "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
882 used as the type of a const parameter",
886 format
!("`{ty}` may not derive both `PartialEq` and `Eq`"),
889 "it is not currently possible to use a type parameter as the type of a \
899 "`{ty}` is forbidden as the type of a const generic parameter",
901 .note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
909 "using function pointers as const generic parameters is forbidden",
918 "using raw pointers as const generic parameters is forbidden",
923 let mut diag
= struct_span_err
!(
927 "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
928 the type of a const parameter",
929 non_structural_match_ty
,
932 if ty
== non_structural_match_ty
{
935 format
!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
945 let mut is_ptr
= true;
947 let err
= match ty
.kind() {
948 ty
::Bool
| ty
::Char
| ty
::Int(_
) | ty
::Uint(_
) | ty
::Error(_
) => None
,
949 ty
::FnPtr(_
) => Some("function pointers"),
950 ty
::RawPtr(_
) => Some("raw pointers"),
953 err_ty_str
= format
!("`{ty}`");
954 Some(err_ty_str
.as_str())
958 if let Some(unsupported_type
) = err
{
963 "using {unsupported_type} as const generic parameters is forbidden",
967 let mut err
= tcx
.sess
.struct_span_err(
970 "{unsupported_type} is forbidden as the type of a const generic parameter",
973 err
.note("the only supported types are integers, `bool` and `char`");
974 if tcx
.sess
.is_nightly_build() {
976 "more complex types are supported with `#![feature(adt_const_params)]`",
987 #[instrument(level = "debug", skip(tcx, span, sig_if_method))]
988 fn check_associated_item(
992 sig_if_method
: Option
<&hir
::FnSig
<'_
>>,
994 let loc
= Some(WellFormedLoc
::Ty(item_id
));
995 enter_wf_checking_ctxt(tcx
, span
, item_id
, |wfcx
| {
996 let item
= tcx
.associated_item(item_id
);
998 let self_ty
= match item
.container
{
999 ty
::TraitContainer
=> tcx
.types
.self_param
,
1000 ty
::ImplContainer
=> tcx
.type_of(item
.container_id(tcx
)),
1004 ty
::AssocKind
::Const
=> {
1005 let ty
= tcx
.type_of(item
.def_id
);
1006 let ty
= wfcx
.normalize(span
, Some(WellFormedLoc
::Ty(item_id
)), ty
);
1007 wfcx
.register_wf_obligation(span
, loc
, ty
.into());
1009 ty
::AssocKind
::Fn
=> {
1010 let sig
= tcx
.fn_sig(item
.def_id
);
1011 let hir_sig
= sig_if_method
.expect("bad signature for method");
1014 item
.ident(tcx
).span
,
1017 item
.def_id
.expect_local(),
1019 check_method_receiver(wfcx
, hir_sig
, item
, self_ty
);
1021 ty
::AssocKind
::Type
=> {
1022 if let ty
::AssocItemContainer
::TraitContainer
= item
.container
{
1023 check_associated_type_bounds(wfcx
, item
, span
)
1025 if item
.defaultness(tcx
).has_value() {
1026 let ty
= tcx
.type_of(item
.def_id
);
1027 let ty
= wfcx
.normalize(span
, Some(WellFormedLoc
::Ty(item_id
)), ty
);
1028 wfcx
.register_wf_obligation(span
, loc
, ty
.into());
1035 fn item_adt_kind(kind
: &ItemKind
<'_
>) -> Option
<AdtKind
> {
1037 ItemKind
::Struct(..) => Some(AdtKind
::Struct
),
1038 ItemKind
::Union(..) => Some(AdtKind
::Union
),
1039 ItemKind
::Enum(..) => Some(AdtKind
::Enum
),
1044 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
1045 fn check_type_defn
<'tcx
>(tcx
: TyCtxt
<'tcx
>, item
: &hir
::Item
<'tcx
>, all_sized
: bool
) {
1046 let _
= tcx
.representability(item
.owner_id
.def_id
);
1047 let adt_def
= tcx
.adt_def(item
.owner_id
);
1049 enter_wf_checking_ctxt(tcx
, item
.span
, item
.owner_id
.def_id
, |wfcx
| {
1050 let variants
= adt_def
.variants();
1051 let packed
= adt_def
.repr().packed();
1053 for variant
in variants
.iter() {
1054 // All field types must be well-formed.
1055 for field
in &variant
.fields
{
1056 let field_id
= field
.did
.expect_local();
1057 let hir
::Node
::Field(hir
::FieldDef { ty: hir_ty, .. }
) = tcx
.hir().get_by_def_id(field_id
)
1059 let ty
= wfcx
.normalize(hir_ty
.span
, None
, tcx
.type_of(field
.did
));
1060 wfcx
.register_wf_obligation(
1062 Some(WellFormedLoc
::Ty(field_id
)),
1067 // For DST, or when drop needs to copy things around, all
1068 // intermediate types must be sized.
1069 let needs_drop_copy
= || {
1071 let ty
= tcx
.type_of(variant
.fields
.last().unwrap().did
);
1072 let ty
= tcx
.erase_regions(ty
);
1073 if ty
.needs_infer() {
1075 .delay_span_bug(item
.span
, &format
!("inference variables in {:?}", ty
));
1076 // Just treat unresolved type expression as if it needs drop.
1079 ty
.needs_drop(tcx
, tcx
.param_env(item
.owner_id
))
1083 // All fields (except for possibly the last) should be sized.
1084 let all_sized
= all_sized
|| variant
.fields
.is_empty() || needs_drop_copy();
1085 let unsized_len
= if all_sized { 0 }
else { 1 }
;
1087 variant
.fields
[..variant
.fields
.len() - unsized_len
].iter().enumerate()
1089 let last
= idx
== variant
.fields
.len() - 1;
1090 let field_id
= field
.did
.expect_local();
1091 let hir
::Node
::Field(hir
::FieldDef { ty: hir_ty, .. }
) = tcx
.hir().get_by_def_id(field_id
)
1093 let ty
= wfcx
.normalize(hir_ty
.span
, None
, tcx
.type_of(field
.did
));
1094 wfcx
.register_bound(
1095 traits
::ObligationCause
::new(
1098 traits
::FieldSized
{
1099 adt_kind
: match item_adt_kind(&item
.kind
) {
1109 tcx
.require_lang_item(LangItem
::Sized
, None
),
1113 // Explicit `enum` discriminant values must const-evaluate successfully.
1114 if let ty
::VariantDiscr
::Explicit(discr_def_id
) = variant
.discr
{
1115 let cause
= traits
::ObligationCause
::new(
1116 tcx
.def_span(discr_def_id
),
1118 traits
::MiscObligation
,
1120 wfcx
.register_obligation(traits
::Obligation
::new(
1124 ty
::Binder
::dummy(ty
::PredicateKind
::ConstEvaluatable(
1125 ty
::Const
::from_anon_const(tcx
, discr_def_id
.expect_local()),
1131 check_where_clauses(wfcx
, item
.span
, item
.owner_id
.def_id
);
1135 #[instrument(skip(tcx, item))]
1136 fn check_trait(tcx
: TyCtxt
<'_
>, item
: &hir
::Item
<'_
>) {
1137 debug
!(?item
.owner_id
);
1139 let def_id
= item
.owner_id
.def_id
;
1140 let trait_def
= tcx
.trait_def(def_id
);
1141 if trait_def
.is_marker
1142 || matches
!(trait_def
.specialization_kind
, TraitSpecializationKind
::Marker
)
1144 for associated_def_id
in &*tcx
.associated_item_def_ids(def_id
) {
1147 tcx
.def_span(*associated_def_id
),
1149 "marker traits cannot have associated items",
1155 enter_wf_checking_ctxt(tcx
, item
.span
, def_id
, |wfcx
| {
1156 check_where_clauses(wfcx
, item
.span
, def_id
)
1159 // Only check traits, don't check trait aliases
1160 if let hir
::ItemKind
::Trait(_
, _
, _
, _
, items
) = item
.kind
{
1161 check_gat_where_clauses(tcx
, items
);
1165 /// Checks all associated type defaults of trait `trait_def_id`.
1167 /// Assuming the defaults are used, check that all predicates (bounds on the
1168 /// assoc type and where clauses on the trait) hold.
1169 fn check_associated_type_bounds(wfcx
: &WfCheckingCtxt
<'_
, '_
>, item
: &ty
::AssocItem
, span
: Span
) {
1170 let bounds
= wfcx
.tcx().explicit_item_bounds(item
.def_id
);
1172 debug
!("check_associated_type_bounds: bounds={:?}", bounds
);
1173 let wf_obligations
= bounds
.iter().flat_map(|&(bound
, bound_span
)| {
1174 let normalized_bound
= wfcx
.normalize(span
, None
, bound
);
1175 traits
::wf
::predicate_obligations(
1184 wfcx
.register_obligations(wf_obligations
);
1192 decl
: &hir
::FnDecl
<'_
>,
1194 enter_wf_checking_ctxt(tcx
, span
, def_id
, |wfcx
| {
1195 let sig
= tcx
.fn_sig(def_id
);
1196 check_fn_or_method(wfcx
, ident
.span
, sig
, decl
, def_id
);
1200 fn check_item_type(tcx
: TyCtxt
<'_
>, item_id
: LocalDefId
, ty_span
: Span
, allow_foreign_ty
: bool
) {
1201 debug
!("check_item_type: {:?}", item_id
);
1203 enter_wf_checking_ctxt(tcx
, ty_span
, item_id
, |wfcx
| {
1204 let ty
= tcx
.type_of(item_id
);
1205 let item_ty
= wfcx
.normalize(ty_span
, Some(WellFormedLoc
::Ty(item_id
)), ty
);
1207 let mut forbid_unsized
= true;
1208 if allow_foreign_ty
{
1209 let tail
= tcx
.struct_tail_erasing_lifetimes(item_ty
, wfcx
.param_env
);
1210 if let ty
::Foreign(_
) = tail
.kind() {
1211 forbid_unsized
= false;
1215 wfcx
.register_wf_obligation(ty_span
, Some(WellFormedLoc
::Ty(item_id
)), item_ty
.into());
1217 wfcx
.register_bound(
1218 traits
::ObligationCause
::new(ty_span
, wfcx
.body_id
, traits
::WellFormed(None
)),
1221 tcx
.require_lang_item(LangItem
::Sized
, None
),
1225 // Ensure that the end result is `Sync` in a non-thread local `static`.
1226 let should_check_for_sync
= tcx
.static_mutability(item_id
.to_def_id())
1227 == Some(hir
::Mutability
::Not
)
1228 && !tcx
.is_foreign_item(item_id
.to_def_id())
1229 && !tcx
.is_thread_local_static(item_id
.to_def_id());
1231 if should_check_for_sync
{
1232 wfcx
.register_bound(
1233 traits
::ObligationCause
::new(ty_span
, wfcx
.body_id
, traits
::SharedStatic
),
1236 tcx
.require_lang_item(LangItem
::Sync
, Some(ty_span
)),
1242 #[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
1243 fn check_impl
<'tcx
>(
1245 item
: &'tcx hir
::Item
<'tcx
>,
1246 ast_self_ty
: &hir
::Ty
<'_
>,
1247 ast_trait_ref
: &Option
<hir
::TraitRef
<'_
>>,
1248 constness
: hir
::Constness
,
1250 enter_wf_checking_ctxt(tcx
, item
.span
, item
.owner_id
.def_id
, |wfcx
| {
1251 match *ast_trait_ref
{
1252 Some(ref ast_trait_ref
) => {
1253 // `#[rustc_reservation_impl]` impls are not real impls and
1254 // therefore don't need to be WF (the trait's `Self: Trait` predicate
1256 let trait_ref
= tcx
.impl_trait_ref(item
.owner_id
).unwrap();
1257 let trait_ref
= wfcx
.normalize(ast_trait_ref
.path
.span
, None
, trait_ref
);
1258 let trait_pred
= ty
::TraitPredicate
{
1260 constness
: match constness
{
1261 hir
::Constness
::Const
=> ty
::BoundConstness
::ConstIfConst
,
1262 hir
::Constness
::NotConst
=> ty
::BoundConstness
::NotConst
,
1264 polarity
: ty
::ImplPolarity
::Positive
,
1266 let obligations
= traits
::wf
::trait_obligations(
1271 ast_trait_ref
.path
.span
,
1274 debug
!(?obligations
);
1275 wfcx
.register_obligations(obligations
);
1278 let self_ty
= tcx
.type_of(item
.owner_id
);
1279 let self_ty
= wfcx
.normalize(
1281 Some(WellFormedLoc
::Ty(item
.hir_id().expect_owner().def_id
)),
1284 wfcx
.register_wf_obligation(
1286 Some(WellFormedLoc
::Ty(item
.hir_id().expect_owner().def_id
)),
1292 check_where_clauses(wfcx
, item
.span
, item
.owner_id
.def_id
);
1296 /// Checks where-clauses and inline bounds that are declared on `def_id`.
1297 #[instrument(level = "debug", skip(wfcx))]
1298 fn check_where_clauses
<'tcx
>(wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>, span
: Span
, def_id
: LocalDefId
) {
1299 let infcx
= wfcx
.infcx
;
1300 let tcx
= wfcx
.tcx();
1302 let predicates
= tcx
.bound_predicates_of(def_id
.to_def_id());
1303 let generics
= tcx
.generics_of(def_id
);
1305 let is_our_default
= |def
: &ty
::GenericParamDef
| match def
.kind
{
1306 GenericParamDefKind
::Type { has_default, .. }
1307 | GenericParamDefKind
::Const { has_default }
=> {
1308 has_default
&& def
.index
>= generics
.parent_count
as u32
1310 GenericParamDefKind
::Lifetime
=> unreachable
!(),
1313 // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
1314 // For example, this forbids the declaration:
1316 // struct Foo<T = Vec<[u32]>> { .. }
1318 // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
1319 for param
in &generics
.params
{
1321 GenericParamDefKind
::Type { .. }
=> {
1322 if is_our_default(param
) {
1323 let ty
= tcx
.type_of(param
.def_id
);
1324 // Ignore dependent defaults -- that is, where the default of one type
1325 // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
1326 // be sure if it will error or not as user might always specify the other.
1327 if !ty
.needs_subst() {
1328 wfcx
.register_wf_obligation(
1329 tcx
.def_span(param
.def_id
),
1330 Some(WellFormedLoc
::Ty(param
.def_id
.expect_local())),
1336 GenericParamDefKind
::Const { .. }
=> {
1337 if is_our_default(param
) {
1338 // FIXME(const_generics_defaults): This
1339 // is incorrect when dealing with unused substs, for example
1340 // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
1341 // we should eagerly error.
1342 let default_ct
= tcx
.const_param_default(param
.def_id
);
1343 if !default_ct
.needs_subst() {
1344 wfcx
.register_wf_obligation(
1345 tcx
.def_span(param
.def_id
),
1352 // Doesn't have defaults.
1353 GenericParamDefKind
::Lifetime
=> {}
1357 // Check that trait predicates are WF when params are substituted by their defaults.
1358 // We don't want to overly constrain the predicates that may be written but we want to
1359 // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
1360 // Therefore we check if a predicate which contains a single type param
1361 // with a concrete default is WF with that default substituted.
1362 // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
1364 // First we build the defaulted substitution.
1365 let substs
= InternalSubsts
::for_item(tcx
, def_id
.to_def_id(), |param
, _
| {
1367 GenericParamDefKind
::Lifetime
=> {
1368 // All regions are identity.
1369 tcx
.mk_param_from_def(param
)
1372 GenericParamDefKind
::Type { .. }
=> {
1373 // If the param has a default, ...
1374 if is_our_default(param
) {
1375 let default_ty
= tcx
.type_of(param
.def_id
);
1376 // ... and it's not a dependent default, ...
1377 if !default_ty
.needs_subst() {
1378 // ... then substitute it with the default.
1379 return default_ty
.into();
1383 tcx
.mk_param_from_def(param
)
1385 GenericParamDefKind
::Const { .. }
=> {
1386 // If the param has a default, ...
1387 if is_our_default(param
) {
1388 let default_ct
= tcx
.const_param_default(param
.def_id
);
1389 // ... and it's not a dependent default, ...
1390 if !default_ct
.needs_subst() {
1391 // ... then substitute it with the default.
1392 return default_ct
.into();
1396 tcx
.mk_param_from_def(param
)
1401 // Now we build the substituted predicates.
1402 let default_obligations
= predicates
1406 .flat_map(|&(pred
, sp
)| {
1408 struct CountParams
{
1409 params
: FxHashSet
<u32>,
1411 impl<'tcx
> ty
::visit
::TypeVisitor
<'tcx
> for CountParams
{
1414 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
1415 if let ty
::Param(param
) = t
.kind() {
1416 self.params
.insert(param
.index
);
1418 t
.super_visit_with(self)
1421 fn visit_region(&mut self, _
: ty
::Region
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
1425 fn visit_const(&mut self, c
: ty
::Const
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
1426 if let ty
::ConstKind
::Param(param
) = c
.kind() {
1427 self.params
.insert(param
.index
);
1429 c
.super_visit_with(self)
1432 let mut param_count
= CountParams
::default();
1433 let has_region
= pred
.visit_with(&mut param_count
).is_break();
1434 let substituted_pred
= predicates
.rebind(pred
).subst(tcx
, substs
);
1435 // Don't check non-defaulted params, dependent defaults (including lifetimes)
1436 // or preds with multiple params.
1437 if substituted_pred
.has_non_region_param() || param_count
.params
.len() > 1 || has_region
1440 } else if predicates
.0.predicates
.iter().any(|&(p
, _
)| p
== substituted_pred
) {
1441 // Avoid duplication of predicates that contain no parameters, for example.
1444 Some((substituted_pred
, sp
))
1448 // Convert each of those into an obligation. So if you have
1449 // something like `struct Foo<T: Copy = String>`, we would
1450 // take that predicate `T: Copy`, substitute to `String: Copy`
1451 // (actually that happens in the previous `flat_map` call),
1452 // and then try to prove it (in this case, we'll fail).
1454 // Note the subtle difference from how we handle `predicates`
1455 // below: there, we are not trying to prove those predicates
1456 // to be *true* but merely *well-formed*.
1457 let pred
= wfcx
.normalize(sp
, None
, pred
);
1458 let cause
= traits
::ObligationCause
::new(
1461 traits
::ItemObligation(def_id
.to_def_id()),
1463 traits
::Obligation
::new(tcx
, cause
, wfcx
.param_env
, pred
)
1466 let predicates
= predicates
.0.instantiate_identity
(tcx
);
1468 let predicates
= wfcx
.normalize(span
, None
, predicates
);
1470 debug
!(?predicates
.predicates
);
1471 assert_eq
!(predicates
.predicates
.len(), predicates
.spans
.len());
1472 let wf_obligations
=
1473 iter
::zip(&predicates
.predicates
, &predicates
.spans
).flat_map(|(&p
, &sp
)| {
1474 traits
::wf
::predicate_obligations(
1476 wfcx
.param_env
.without_const(),
1483 let obligations
: Vec
<_
> = wf_obligations
.chain(default_obligations
).collect();
1484 wfcx
.register_obligations(obligations
);
1487 #[instrument(level = "debug", skip(wfcx, span, hir_decl))]
1488 fn check_fn_or_method
<'tcx
>(
1489 wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>,
1491 sig
: ty
::PolyFnSig
<'tcx
>,
1492 hir_decl
: &hir
::FnDecl
<'_
>,
1495 let tcx
= wfcx
.tcx();
1496 let sig
= tcx
.liberate_late_bound_regions(def_id
.to_def_id(), sig
);
1498 // Normalize the input and output types one at a time, using a different
1499 // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
1500 // on the entire `FnSig`, since this would use the same `WellFormedLoc`
1501 // for each type, preventing the HIR wf check from generating
1502 // a nice error message.
1503 let ty
::FnSig { mut inputs_and_output, c_variadic, unsafety, abi }
= sig
;
1504 inputs_and_output
= tcx
.mk_type_list(inputs_and_output
.iter().enumerate().map(|(i
, ty
)| {
1507 Some(WellFormedLoc
::Param
{
1509 // Note that the `param_idx` of the output type is
1510 // one greater than the index of the last input type.
1511 param_idx
: i
.try_into().unwrap(),
1516 // Manually call `normalize_associated_types_in` on the other types
1517 // in `FnSig`. This ensures that if the types of these fields
1518 // ever change to include projections, we will start normalizing
1519 // them automatically.
1520 let sig
= ty
::FnSig
{
1522 c_variadic
: wfcx
.normalize(span
, None
, c_variadic
),
1523 unsafety
: wfcx
.normalize(span
, None
, unsafety
),
1524 abi
: wfcx
.normalize(span
, None
, abi
),
1527 for (i
, (&input_ty
, ty
)) in iter
::zip(sig
.inputs(), hir_decl
.inputs
).enumerate() {
1528 wfcx
.register_wf_obligation(
1530 Some(WellFormedLoc
::Param { function: def_id, param_idx: i.try_into().unwrap() }
),
1535 wfcx
.register_wf_obligation(
1536 hir_decl
.output
.span(),
1537 Some(WellFormedLoc
::Param
{
1539 param_idx
: sig
.inputs().len().try_into().unwrap(),
1541 sig
.output().into(),
1544 check_where_clauses(wfcx
, span
, def_id
);
1546 check_return_position_impl_trait_in_trait_bounds(
1550 hir_decl
.output
.span(),
1553 if sig
.abi
== Abi
::RustCall
{
1554 let span
= tcx
.def_span(def_id
);
1555 let has_implicit_self
= hir_decl
.implicit_self
!= hir
::ImplicitSelfKind
::None
;
1556 let mut inputs
= sig
.inputs().iter().skip(if has_implicit_self { 1 }
else { 0 }
);
1557 // Check that the argument is a tuple
1558 if let Some(ty
) = inputs
.next() {
1559 wfcx
.register_bound(
1560 ObligationCause
::new(span
, wfcx
.body_id
, ObligationCauseCode
::RustCall
),
1563 tcx
.require_lang_item(hir
::LangItem
::Tuple
, Some(span
)),
1567 hir_decl
.inputs
.last().map_or(span
, |input
| input
.span
),
1568 "functions with the \"rust-call\" ABI must take a single non-self tuple argument",
1571 // No more inputs other than the `self` type and the tuple type
1572 if inputs
.next().is_some() {
1574 hir_decl
.inputs
.last().map_or(span
, |input
| input
.span
),
1575 "functions with the \"rust-call\" ABI must take a single non-self tuple argument",
1581 /// Basically `check_associated_type_bounds`, but separated for now and should be
1582 /// deduplicated when RPITITs get lowered into real associated items.
1583 #[tracing::instrument(level = "trace", skip(wfcx))]
1584 fn check_return_position_impl_trait_in_trait_bounds
<'tcx
>(
1585 wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>,
1586 fn_def_id
: LocalDefId
,
1587 fn_output
: Ty
<'tcx
>,
1590 let tcx
= wfcx
.tcx();
1591 if let Some(assoc_item
) = tcx
.opt_associated_item(fn_def_id
.to_def_id())
1592 && assoc_item
.container
== ty
::AssocItemContainer
::TraitContainer
1594 for arg
in fn_output
.walk() {
1595 if let ty
::GenericArgKind
::Type(ty
) = arg
.unpack()
1596 && let ty
::Projection(proj
) = ty
.kind()
1597 && tcx
.def_kind(proj
.item_def_id
) == DefKind
::ImplTraitPlaceholder
1598 && tcx
.impl_trait_in_trait_parent(proj
.item_def_id
) == fn_def_id
.to_def_id()
1600 let span
= tcx
.def_span(proj
.item_def_id
);
1601 let bounds
= wfcx
.tcx().explicit_item_bounds(proj
.item_def_id
);
1602 let wf_obligations
= bounds
.iter().flat_map(|&(bound
, bound_span
)| {
1603 let bound
= ty
::EarlyBinder(bound
).subst(tcx
, proj
.substs
);
1604 let normalized_bound
= wfcx
.normalize(span
, None
, bound
);
1605 traits
::wf
::predicate_obligations(
1613 wfcx
.register_obligations(wf_obligations
);
1619 const HELP_FOR_SELF_TYPE
: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
1620 `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
1621 of the previous types except `Self`)";
1623 #[instrument(level = "debug", skip(wfcx))]
1624 fn check_method_receiver
<'tcx
>(
1625 wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>,
1626 fn_sig
: &hir
::FnSig
<'_
>,
1627 method
: &ty
::AssocItem
,
1630 let tcx
= wfcx
.tcx();
1632 if !method
.fn_has_self_parameter
{
1636 let span
= fn_sig
.decl
.inputs
[0].span
;
1638 let sig
= tcx
.fn_sig(method
.def_id
);
1639 let sig
= tcx
.liberate_late_bound_regions(method
.def_id
, sig
);
1640 let sig
= wfcx
.normalize(span
, None
, sig
);
1642 debug
!("check_method_receiver: sig={:?}", sig
);
1644 let self_ty
= wfcx
.normalize(span
, None
, self_ty
);
1646 let receiver_ty
= sig
.inputs()[0];
1647 let receiver_ty
= wfcx
.normalize(span
, None
, receiver_ty
);
1649 if tcx
.features().arbitrary_self_types
{
1650 if !receiver_is_valid(wfcx
, span
, receiver_ty
, self_ty
, true) {
1651 // Report error; `arbitrary_self_types` was enabled.
1652 e0307(tcx
, span
, receiver_ty
);
1655 if !receiver_is_valid(wfcx
, span
, receiver_ty
, self_ty
, false) {
1656 if receiver_is_valid(wfcx
, span
, receiver_ty
, self_ty
, true) {
1657 // Report error; would have worked with `arbitrary_self_types`.
1659 &tcx
.sess
.parse_sess
,
1660 sym
::arbitrary_self_types
,
1663 "`{receiver_ty}` cannot be used as the type of `self` without \
1664 the `arbitrary_self_types` feature",
1667 .help(HELP_FOR_SELF_TYPE
)
1670 // Report error; would not have worked with `arbitrary_self_types`.
1671 e0307(tcx
, span
, receiver_ty
);
1677 fn e0307
<'tcx
>(tcx
: TyCtxt
<'tcx
>, span
: Span
, receiver_ty
: Ty
<'_
>) {
1679 tcx
.sess
.diagnostic(),
1682 "invalid `self` parameter type: {receiver_ty}"
1684 .note("type of `self` must be `Self` or a type that dereferences to it")
1685 .help(HELP_FOR_SELF_TYPE
)
1689 /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
1690 /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
1691 /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
1692 /// strict: `receiver_ty` must implement `Receiver` and directly implement
1693 /// `Deref<Target = self_ty>`.
1695 /// N.B., there are cases this function returns `true` but causes an error to be emitted,
1696 /// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
1697 /// wrong lifetime. Be careful of this if you are calling this function speculatively.
1698 fn receiver_is_valid
<'tcx
>(
1699 wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>,
1701 receiver_ty
: Ty
<'tcx
>,
1703 arbitrary_self_types_enabled
: bool
,
1705 let infcx
= wfcx
.infcx
;
1706 let tcx
= wfcx
.tcx();
1708 ObligationCause
::new(span
, wfcx
.body_id
, traits
::ObligationCauseCode
::MethodReceiver
);
1710 let can_eq_self
= |ty
| infcx
.can_eq(wfcx
.param_env
, self_ty
, ty
).is_ok();
1712 // `self: Self` is always valid.
1713 if can_eq_self(receiver_ty
) {
1714 if let Err(err
) = wfcx
.eq(&cause
, wfcx
.param_env
, self_ty
, receiver_ty
) {
1715 infcx
.err_ctxt().report_mismatched_types(&cause
, self_ty
, receiver_ty
, err
).emit();
1720 let mut autoderef
= Autoderef
::new(infcx
, wfcx
.param_env
, wfcx
.body_id
, span
, receiver_ty
);
1722 // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
1723 if arbitrary_self_types_enabled
{
1724 autoderef
= autoderef
.include_raw_pointers();
1727 // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1730 let receiver_trait_def_id
= tcx
.require_lang_item(LangItem
::Receiver
, Some(span
));
1732 // Keep dereferencing `receiver_ty` until we get to `self_ty`.
1734 if let Some((potential_self_ty
, _
)) = autoderef
.next() {
1736 "receiver_is_valid: potential self type `{:?}` to match `{:?}`",
1737 potential_self_ty
, self_ty
1740 if can_eq_self(potential_self_ty
) {
1741 wfcx
.register_obligations(autoderef
.into_obligations());
1743 if let Err(err
) = wfcx
.eq(&cause
, wfcx
.param_env
, self_ty
, potential_self_ty
) {
1746 .report_mismatched_types(&cause
, self_ty
, potential_self_ty
, err
)
1752 // Without `feature(arbitrary_self_types)`, we require that each step in the
1753 // deref chain implement `receiver`
1754 if !arbitrary_self_types_enabled
1755 && !receiver_is_implemented(
1757 receiver_trait_def_id
,
1766 debug
!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty
, self_ty
);
1767 // If the receiver already has errors reported due to it, consider it valid to avoid
1768 // unnecessary errors (#58712).
1769 return receiver_ty
.references_error();
1773 // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
1774 if !arbitrary_self_types_enabled
1775 && !receiver_is_implemented(wfcx
, receiver_trait_def_id
, cause
.clone(), receiver_ty
)
1783 fn receiver_is_implemented
<'tcx
>(
1784 wfcx
: &WfCheckingCtxt
<'_
, 'tcx
>,
1785 receiver_trait_def_id
: DefId
,
1786 cause
: ObligationCause
<'tcx
>,
1787 receiver_ty
: Ty
<'tcx
>,
1789 let tcx
= wfcx
.tcx();
1790 let trait_ref
= ty
::Binder
::dummy(tcx
.mk_trait_ref(receiver_trait_def_id
, [receiver_ty
]));
1792 let obligation
= traits
::Obligation
::new(tcx
, cause
, wfcx
.param_env
, trait_ref
);
1794 if wfcx
.infcx
.predicate_must_hold_modulo_regions(&obligation
) {
1798 "receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
1805 fn check_variances_for_type_defn
<'tcx
>(
1807 item
: &hir
::Item
<'tcx
>,
1808 hir_generics
: &hir
::Generics
<'_
>,
1810 let ty
= tcx
.type_of(item
.owner_id
);
1811 if tcx
.has_error_field(ty
) {
1815 let ty_predicates
= tcx
.predicates_of(item
.owner_id
);
1816 assert_eq
!(ty_predicates
.parent
, None
);
1817 let variances
= tcx
.variances_of(item
.owner_id
);
1819 let mut constrained_parameters
: FxHashSet
<_
> = variances
1822 .filter(|&(_
, &variance
)| variance
!= ty
::Bivariant
)
1823 .map(|(index
, _
)| Parameter(index
as u32))
1826 identify_constrained_generic_params(tcx
, ty_predicates
, None
, &mut constrained_parameters
);
1828 // Lazily calculated because it is only needed in case of an error.
1829 let explicitly_bounded_params
= LazyCell
::new(|| {
1830 let icx
= crate::collect
::ItemCtxt
::new(tcx
, item
.owner_id
.to_def_id());
1834 .filter_map(|predicate
| match predicate
{
1835 hir
::WherePredicate
::BoundPredicate(predicate
) => {
1836 match icx
.to_ty(predicate
.bounded_ty
).kind() {
1837 ty
::Param(data
) => Some(Parameter(data
.index
)),
1843 .collect
::<FxHashSet
<_
>>()
1846 for (index
, _
) in variances
.iter().enumerate() {
1847 let parameter
= Parameter(index
as u32);
1849 if constrained_parameters
.contains(¶meter
) {
1853 let param
= &hir_generics
.params
[index
];
1856 hir
::ParamName
::Error
=> {}
1858 let has_explicit_bounds
= explicitly_bounded_params
.contains(¶meter
);
1859 report_bivariance(tcx
, param
, has_explicit_bounds
);
1865 fn report_bivariance(
1867 param
: &rustc_hir
::GenericParam
<'_
>,
1868 has_explicit_bounds
: bool
,
1869 ) -> ErrorGuaranteed
{
1870 let span
= param
.span
;
1871 let param_name
= param
.name
.ident().name
;
1872 let mut err
= error_392(tcx
, span
, param_name
);
1874 let suggested_marker_id
= tcx
.lang_items().phantom_data();
1875 // Help is available only in presence of lang items.
1876 let msg
= if let Some(def_id
) = suggested_marker_id
{
1878 "consider removing `{}`, referring to it in a field, or using a marker such as `{}`",
1880 tcx
.def_path_str(def_id
),
1883 format
!("consider removing `{param_name}` or referring to it in a field")
1887 if matches
!(param
.kind
, hir
::GenericParamKind
::Type { .. }
) && !has_explicit_bounds
{
1889 "if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
1896 impl<'tcx
> WfCheckingCtxt
<'_
, 'tcx
> {
1897 /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
1899 #[instrument(level = "debug", skip(self))]
1900 fn check_false_global_bounds(&mut self) {
1901 let tcx
= self.ocx
.infcx
.tcx
;
1902 let mut span
= self.span
;
1903 let empty_env
= ty
::ParamEnv
::empty();
1905 let def_id
= tcx
.hir().local_def_id(self.body_id
);
1906 let predicates_with_span
= tcx
.predicates_of(def_id
).predicates
.iter().copied();
1907 // Check elaborated bounds.
1908 let implied_obligations
= traits
::elaborate_predicates_with_span(tcx
, predicates_with_span
);
1910 for obligation
in implied_obligations
{
1911 // We lower empty bounds like `Vec<dyn Copy>:` as
1912 // `WellFormed(Vec<dyn Copy>)`, which will later get checked by
1913 // regular WF checking
1914 if let ty
::PredicateKind
::WellFormed(..) = obligation
.predicate
.kind().skip_binder() {
1917 let pred
= obligation
.predicate
;
1918 // Match the existing behavior.
1919 if pred
.is_global() && !pred
.has_late_bound_regions() {
1920 let pred
= self.normalize(span
, None
, pred
);
1921 let hir_node
= tcx
.hir().find(self.body_id
);
1923 // only use the span of the predicate clause (#90869)
1925 if let Some(hir
::Generics { predicates, .. }
) =
1926 hir_node
.and_then(|node
| node
.generics())
1928 let obligation_span
= obligation
.cause
.span();
1932 // There seems to be no better way to find out which predicate we are in
1933 .find(|pred
| pred
.span().contains(obligation_span
))
1934 .map(|pred
| pred
.span())
1935 .unwrap_or(obligation_span
);
1938 let obligation
= traits
::Obligation
::new(
1940 traits
::ObligationCause
::new(span
, self.body_id
, traits
::TrivialBound
),
1944 self.ocx
.register_obligation(obligation
);
1950 fn check_mod_type_wf(tcx
: TyCtxt
<'_
>, module
: LocalDefId
) {
1951 let items
= tcx
.hir_module_items(module
);
1952 items
.par_items(|item
| tcx
.ensure().check_well_formed(item
.owner_id
));
1953 items
.par_impl_items(|item
| tcx
.ensure().check_well_formed(item
.owner_id
));
1954 items
.par_trait_items(|item
| tcx
.ensure().check_well_formed(item
.owner_id
));
1955 items
.par_foreign_items(|item
| tcx
.ensure().check_well_formed(item
.owner_id
));
1962 ) -> DiagnosticBuilder
<'_
, ErrorGuaranteed
> {
1963 let mut err
= struct_span_err
!(tcx
.sess
, span
, E0392
, "parameter `{param_name}` is never used");
1964 err
.span_label(span
, "unused parameter");
1968 pub fn provide(providers
: &mut Providers
) {
1969 *providers
= Providers { check_mod_type_wf, check_well_formed, ..*providers }
;