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:
commit
8ebf04225d
78 changed files with 717 additions and 349 deletions
|
@ -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> {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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(..) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue