summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check/wfcheck.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check/wfcheck.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs278
1 files changed, 127 insertions, 151 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index b403ee96b..d4748b7ef 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -15,7 +15,7 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::query::Providers;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
- self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_middle::ty::{GenericArgKind, InternalSubsts};
@@ -81,7 +81,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.tcx(),
cause,
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
}
@@ -105,7 +105,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
}
f(&mut wfcx);
- let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
+ let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)
+ {
+ Ok(wf_types) => wf_types,
+ Err(_guar) => return,
+ };
+
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
let errors = wfcx.select_all_or_error();
@@ -217,10 +222,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
}
hir::ItemKind::Static(ty, ..) => {
- check_item_type(tcx, def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Const(ty, ..) => {
- check_item_type(tcx, def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Struct(_, ast_generics) => {
check_type_defn(tcx, item, false);
@@ -242,6 +247,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
+ hir::ItemKind::TyAlias(hir_ty, ..) => {
+ if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
+ // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
+ check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+ }
+ }
_ => {}
}
}
@@ -258,7 +269,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
hir::ForeignItemKind::Fn(decl, ..) => {
check_item_fn(tcx, def_id, item.ident, item.span, decl)
}
- hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
+ hir::ForeignItemKind::Static(ty, ..) => {
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
+ }
hir::ForeignItemKind::Type => (),
}
}
@@ -314,7 +327,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// Gather the bounds with which all other items inside of this trait constrain the GAT.
// This is calculated by taking the intersection of the bounds that each item
// constrains the GAT with individually.
- let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
+ let mut new_required_bounds: Option<FxHashSet<ty::Clause<'_>>> = None;
for item in associated_items {
let item_def_id = item.id.owner_id;
// Skip our own GAT, since it does not constrain itself at all.
@@ -411,21 +424,17 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let mut unsatisfied_bounds: Vec<_> = required_bounds
.into_iter()
.filter(|clause| match clause.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => !region_known_to_outlive(
- tcx,
- gat_def_id.def_id,
- param_env,
- &FxIndexSet::default(),
- a,
- b,
- ),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => !ty_known_to_outlive(
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+ !region_known_to_outlive(
+ tcx,
+ gat_def_id.def_id,
+ param_env,
+ &FxIndexSet::default(),
+ a,
+ b,
+ )
+ }
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => !ty_known_to_outlive(
tcx,
gat_def_id.def_id,
param_env,
@@ -433,7 +442,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
a,
b,
),
- _ => bug!("Unexpected PredicateKind"),
+ _ => bug!("Unexpected ClauseKind"),
})
.map(|clause| clause.to_string())
.collect();
@@ -481,7 +490,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
fn augment_param_env<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- new_predicates: Option<&FxHashSet<ty::Predicate<'tcx>>>,
+ new_predicates: Option<&FxHashSet<ty::Clause<'tcx>>>,
) -> ty::ParamEnv<'tcx> {
let Some(new_predicates) = new_predicates else {
return param_env;
@@ -491,7 +500,7 @@ fn augment_param_env<'tcx>(
return param_env;
}
- let bounds = tcx.mk_predicates_from_iter(
+ let bounds = tcx.mk_clauses_from_iter(
param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
@@ -517,7 +526,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
wf_tys: &FxIndexSet<Ty<'tcx>>,
gat_def_id: LocalDefId,
gat_generics: &'tcx ty::Generics,
-) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
+) -> Option<FxHashSet<ty::Clause<'tcx>>> {
// The bounds we that we would require from `to_check`
let mut bounds = FxHashSet::default();
@@ -552,22 +561,24 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// our example, the type was `Self`, which will also be
// `Self` in the GAT.
let ty_param = gat_generics.param_at(*ty_idx, tcx);
- let ty_param = tcx.mk_ty_param(ty_param.index, ty_param.name);
+ let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);
// Same for the region. In our example, 'a corresponds
// to the 'me parameter.
let region_param = gat_generics.param_at(*region_a_idx, tcx);
- let region_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_param.def_id,
- index: region_param.index,
- name: region_param.name,
- });
+ let region_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_param.def_id,
+ index: region_param.index,
+ name: region_param.name,
+ },
+ );
// The predicate we expect to see. (In our example,
// `Self: 'me`.)
- let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
- ty::OutlivesPredicate(ty_param, region_param),
- ));
- let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
- bounds.insert(clause);
+ bounds.insert(
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))
+ .to_predicate(tcx),
+ );
}
}
@@ -593,24 +604,32 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
debug!("required clause: {region_a} must outlive {region_b}");
// Translate into the generic parameters of the GAT.
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
- let region_a_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_a_param.def_id,
- index: region_a_param.index,
- name: region_a_param.name,
- });
+ let region_a_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_a_param.def_id,
+ index: region_a_param.index,
+ name: region_a_param.name,
+ },
+ );
// Same for the region.
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
- let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_b_param.def_id,
- index: region_b_param.index,
- name: region_b_param.name,
- });
+ let region_b_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_b_param.def_id,
+ index: region_b_param.index,
+ name: region_b_param.name,
+ },
+ );
// The predicate we expect to see.
- let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(region_a_param, region_b_param),
- ));
- let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
- bounds.insert(clause);
+ bounds.insert(
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ region_a_param,
+ region_b_param,
+ ))
+ .to_predicate(tcx),
+ );
}
}
}
@@ -820,83 +839,20 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
let ty = tcx.type_of(param.def_id).subst_identity();
if tcx.features().adt_const_params {
- if let Some(non_structural_match_ty) =
- traits::search_for_adt_const_param_violation(param.span, tcx, ty)
- {
- // We use the same error code in both branches, because this is really the same
- // issue: we just special-case the message for type parameters to make it
- // clearer.
- match non_structural_match_ty.kind() {
- ty::Param(_) => {
- // Const parameters may not have type parameters as their types,
- // because we cannot be sure that the type parameter derives `PartialEq`
- // and `Eq` (just implementing them is not enough for `structural_match`).
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
- used as the type of a const parameter",
- )
- .span_label(
- hir_ty.span,
- format!("`{ty}` may not derive both `PartialEq` and `Eq`"),
- )
- .note(
- "it is not currently possible to use a type parameter as the type of a \
- const parameter",
- )
- .emit();
- }
- ty::Float(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{ty}` is forbidden as the type of a const generic parameter",
- )
- .note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
- .emit();
- }
- ty::FnPtr(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "using function pointers as const generic parameters is forbidden",
- )
- .emit();
- }
- ty::RawPtr(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "using raw pointers as const generic parameters is forbidden",
- )
- .emit();
- }
- _ => {
- let mut diag = struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
- the type of a const parameter",
- non_structural_match_ty,
- );
-
- if ty == non_structural_match_ty {
- diag.span_label(
- hir_ty.span,
- format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
- );
- }
-
- diag.emit();
- }
- }
- }
+ enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
+ let trait_def_id =
+ tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span));
+ wfcx.register_bound(
+ ObligationCause::new(
+ hir_ty.span,
+ param.def_id,
+ ObligationCauseCode::ConstParam(ty),
+ ),
+ wfcx.param_env,
+ ty,
+ trait_def_id,
+ );
+ });
} else {
let err_ty_str;
let mut is_ptr = true;
@@ -1025,7 +981,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
+ let ty = tcx.type_of(variant.tail().did).subst_identity();
let ty = tcx.erase_regions(ty);
if ty.has_infer() {
tcx.sess
@@ -1078,9 +1034,9 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
tcx,
cause,
wfcx.param_env,
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
- )),
+ ))),
));
}
}
@@ -1133,7 +1089,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
wfcx.infcx,
wfcx.param_env,
wfcx.body_def_id,
- normalized_bound,
+ normalized_bound.as_predicate(),
bound_span,
)
});
@@ -1154,20 +1110,32 @@ fn check_item_fn(
})
}
-fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
+enum UnsizedHandling {
+ Forbid,
+ Allow,
+ AllowIfForeignTail,
+}
+
+fn check_item_type(
+ tcx: TyCtxt<'_>,
+ item_id: LocalDefId,
+ ty_span: Span,
+ unsized_handling: UnsizedHandling,
+) {
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id).subst_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
- let mut forbid_unsized = true;
- if allow_foreign_ty {
- let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
- if let ty::Foreign(_) = tail.kind() {
- forbid_unsized = false;
+ let forbid_unsized = match unsized_handling {
+ UnsizedHandling::Forbid => true,
+ UnsizedHandling::Allow => false,
+ UnsizedHandling::AllowIfForeignTail => {
+ let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
+ !matches!(tail.kind(), ty::Foreign(_))
}
- }
+ };
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {
@@ -1398,7 +1366,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
- let substituted_pred = ty::EarlyBinder(pred).subst(tcx, substs);
+ let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
@@ -1441,7 +1409,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
infcx,
wfcx.param_env.without_const(),
wfcx.body_def_id,
- p,
+ p.as_predicate(),
sp,
)
});
@@ -1503,7 +1471,7 @@ fn check_fn_or_method<'tcx>(
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
- // Check that the argument is a tuple
+ // Check that the argument is a tuple and is sized
if let Some(ty) = inputs.next() {
wfcx.register_bound(
ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
@@ -1511,6 +1479,12 @@ fn check_fn_or_method<'tcx>(
*ty,
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
);
+ wfcx.register_bound(
+ ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
+ wfcx.param_env,
+ *ty,
+ tcx.require_lang_item(hir::LangItem::Sized, Some(span)),
+ );
} else {
tcx.sess.span_err(
hir_decl.inputs.last().map_or(span, |input| input.span),
@@ -1572,13 +1546,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
&& self.seen.insert(unshifted_opaque_ty.def_id)
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
- && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
- && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+ && let origin = tcx.opaque_type_origin(opaque_def_id)
+ && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
match re.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re,
+ ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
r => bug!("unexpected region: {r:?}"),
}
});
@@ -1591,7 +1565,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
self.wfcx.infcx,
self.wfcx.param_env,
self.wfcx.body_def_id,
- bound,
+ bound.as_predicate(),
bound_span,
));
// Set the debruijn index back to innermost here, since we already eagerly
@@ -1799,9 +1773,11 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let ty = tcx.type_of(item.owner_id).subst_identity();
- if tcx.has_error_field(ty) {
- return;
+ let identity_substs = ty::InternalSubsts::identity_for_item(tcx, item.owner_id);
+ for field in tcx.adt_def(item.owner_id).all_fields() {
+ if field.ty(tcx, identity_substs).references_error() {
+ return;
+ }
}
let ty_predicates = tcx.predicates_of(item.owner_id);
@@ -1902,7 +1878,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// We lower empty bounds like `Vec<dyn Copy>:` as
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
// regular WF checking
- if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
+ if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() {
continue;
}
// Match the existing behavior.