Auto merge of #112198 - compiler-errors:rollup-o2xe4of, r=compiler-errors

Rollup of 7 pull requests

Successful merges:

 - #111670 (Require that const param tys implement `ConstParamTy`)
 - #111914 (CFI: Fix cfi with async: transform_ty: unexpected GeneratorWitness(Bi…)
 - #112030 (Migrate `item_trait_alias` to Askama)
 - #112150 (Support 128-bit atomics on all x86_64 Apple targets)
 - #112174 (Fix broken link)
 - #112190 (Improve comments on `TyCtxt` and `GlobalCtxt`.)
 - #112193 (Check tuple elements are `Sized` in `offset_of`)

Failed merges:

 - #112071 (Group rfcs tests)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-02 07:57:21 +00:00
commit 8ebf04225d
78 changed files with 717 additions and 349 deletions

View file

@ -149,6 +149,12 @@ pub trait TypeErrCtxtExt<'tcx> {
root_obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>,
);
fn report_const_param_not_wf(
&self,
ty: Ty<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
}
impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
@ -641,6 +647,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span = obligation.cause.span;
}
}
if let ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id,
trait_item_def_id,
@ -657,6 +664,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return;
}
// Report a const-param specific error
if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
{
self.report_const_param_not_wf(ty, &obligation).emit();
return;
}
let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
@ -1163,6 +1177,102 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.point_at_returns_when_relevant(&mut err, &obligation);
err.emit();
}
fn report_const_param_not_wf(
&self,
ty: Ty<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let span = obligation.cause.span;
let mut diag = match ty.kind() {
_ if ty.has_param() => {
span_bug!(span, "const param tys cannot mention other generic parameters");
}
ty::Float(_) => {
struct_span_err!(
self.tcx.sess,
span,
E0741,
"`{ty}` is forbidden as the type of a const generic parameter",
)
}
ty::FnPtr(_) => {
struct_span_err!(
self.tcx.sess,
span,
E0741,
"using function pointers as const generic parameters is forbidden",
)
}
ty::RawPtr(_) => {
struct_span_err!(
self.tcx.sess,
span,
E0741,
"using raw pointers as const generic parameters is forbidden",
)
}
ty::Adt(def, _) => {
// We should probably see if we're *allowed* to derive `ConstParamTy` on the type...
let mut diag = struct_span_err!(
self.tcx.sess,
span,
E0741,
"`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
);
// Only suggest derive if this isn't a derived obligation,
// and the struct is local.
if let Some(span) = self.tcx.hir().span_if_local(def.did())
&& obligation.cause.code().parent().is_none()
{
if ty.is_structural_eq_shallow(self.tcx) {
diag.span_suggestion(
span,
"add `#[derive(ConstParamTy)]` to the struct",
"#[derive(ConstParamTy)]\n",
Applicability::MachineApplicable,
);
} else {
// FIXME(adt_const_params): We should check there's not already an
// overlapping `Eq`/`PartialEq` impl.
diag.span_suggestion(
span,
"add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct",
"#[derive(ConstParamTy, PartialEq, Eq)]\n",
Applicability::MachineApplicable,
);
}
}
diag
}
_ => {
struct_span_err!(
self.tcx.sess,
span,
E0741,
"`{ty}` can't be used as a const parameter type",
)
}
};
let mut code = obligation.cause.code();
let mut pred = obligation.predicate.to_opt_poly_trait_pred();
while let Some((next_code, next_pred)) = code.parent() {
if let Some(pred) = pred {
let pred = self.instantiate_binder_with_placeholders(pred);
diag.note(format!(
"`{}` must implement `{}`, but it does not",
pred.self_ty(),
pred.print_modifiers_and_trait_path()
));
}
code = next_code;
pred = next_pred;
}
diag
}
}
trait InferCtxtPrivExt<'tcx> {

View file

@ -2655,7 +2655,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::BinOp { .. }
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
| ObligationCauseCode::RustCall
| ObligationCauseCode::DropImpl => {}
| ObligationCauseCode::DropImpl
| ObligationCauseCode::ConstParam(_) => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
}

View file

@ -100,7 +100,8 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
| ty::Str
| ty::Array(..)
| ty::Slice(_)
| ty::Ref(.., hir::Mutability::Not) => return Ok(()),
| ty::Ref(.., hir::Mutability::Not)
| ty::Tuple(_) => return Ok(()),
&ty::Adt(adt, substs) => (adt, substs),

View file

@ -62,9 +62,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::specialize::{
specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
};
pub use self::structural_match::{
search_for_adt_const_param_violation, search_for_structural_match_violation,
};
pub use self::structural_match::search_for_structural_match_violation;
pub use self::structural_normalize::StructurallyNormalizeExt;
pub use self::util::elaborate;
pub use self::util::{expand_trait_aliases, TraitAliasExpander};

View file

@ -34,24 +34,7 @@ pub fn search_for_structural_match_violation<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
) -> Option<Ty<'tcx>> {
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: false })
.break_value()
}
/// This method traverses the structure of `ty`, trying to find any
/// types that are not allowed to be used in a const generic.
///
/// This is either because the type does not implement `StructuralEq`
/// and `StructuralPartialEq`, or because the type is intentionally
/// not supported in const generics (such as floats and raw pointers,
/// which are allowed in match blocks).
pub fn search_for_adt_const_param_violation<'tcx>(
span: Span,
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
) -> Option<Ty<'tcx>> {
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: true })
.break_value()
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value()
}
/// This implements the traversal over the structure of a given type to try to
@ -65,11 +48,6 @@ struct Search<'tcx> {
/// Tracks ADTs previously encountered during search, so that
/// we will not recur on them again.
seen: FxHashSet<hir::def_id::DefId>,
// Additionally deny things that have been allowed in patterns,
// but are not allowed in adt const params, such as floats and
// fn ptrs.
adt_const_param: bool,
}
impl<'tcx> Search<'tcx> {
@ -124,41 +102,29 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
}
ty::FnPtr(..) => {
if !self.adt_const_param {
return ControlFlow::Continue(());
} else {
return ControlFlow::Break(ty);
}
return ControlFlow::Continue(());
}
ty::RawPtr(..) => {
if !self.adt_const_param {
// structural-match ignores substructure of
// `*const _`/`*mut _`, so skip `super_visit_with`.
//
// For example, if you have:
// ```
// struct NonStructural;
// #[derive(PartialEq, Eq)]
// struct T(*const NonStructural);
// const C: T = T(std::ptr::null());
// ```
//
// Even though `NonStructural` does not implement `PartialEq`,
// structural equality on `T` does not recur into the raw
// pointer. Therefore, one can still use `C` in a pattern.
return ControlFlow::Continue(());
} else {
return ControlFlow::Break(ty);
}
// structural-match ignores substructure of
// `*const _`/`*mut _`, so skip `super_visit_with`.
//
// For example, if you have:
// ```
// struct NonStructural;
// #[derive(PartialEq, Eq)]
// struct T(*const NonStructural);
// const C: T = T(std::ptr::null());
// ```
//
// Even though `NonStructural` does not implement `PartialEq`,
// structural equality on `T` does not recur into the raw
// pointer. Therefore, one can still use `C` in a pattern.
return ControlFlow::Continue(());
}
ty::Float(_) => {
if !self.adt_const_param {
return ControlFlow::Continue(());
} else {
return ControlFlow::Break(ty);
}
return ControlFlow::Continue(());
}
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {