Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions compiler/rustc_builtin_macros/src/deriving/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,43 +51,4 @@ pub(crate) fn expand_deriving_const_param_ty(
};

trait_def.expand(cx, mitem, item, push);

let trait_def = TraitDef {
span,
path: path_std!(marker::UnsizedConstParamTy),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
supports_unions: false,
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};

trait_def.expand(cx, mitem, item, push);
}

pub(crate) fn expand_deriving_unsized_const_param_ty(
cx: &ExtCtxt<'_>,
span: Span,
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
is_const: bool,
) {
let trait_def = TraitDef {
span,
path: path_std!(marker::UnsizedConstParamTy),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
supports_unions: false,
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};

trait_def.expand(cx, mitem, item, push);
}
1 change: 0 additions & 1 deletion compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
Clone: clone::expand_deriving_clone,
Copy: bounds::expand_deriving_copy,
ConstParamTy: bounds::expand_deriving_const_param_ty,
UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
Debug: debug::expand_deriving_debug,
Default: default::expand_deriving_default,
Eq: eq::expand_deriving_eq,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,6 @@ language_item_table! {
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);

ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
UnsizedConstParamTy, sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);

Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,17 +819,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
let span = tcx.def_span(param.def_id);
let def_id = param.def_id.expect_local();

if tcx.features().unsized_const_params() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
wfcx.param_env,
ty,
tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
);
Ok(())
})
} else if tcx.features().adt_const_params() {
if tcx.features().adt_const_params() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
Expand Down Expand Up @@ -880,7 +870,6 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
tcx,
tcx.param_env(param.def_id),
ty,
LangItem::ConstParamTy,
cause,
) {
// Can never implement `ConstParamTy`, don't suggest anything.
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Check properties that are required by built-in traits and set
//! up data structures required by type-checking/codegen.

use std::assert_matches::assert_matches;
use std::collections::BTreeMap;

use rustc_data_structures::fx::FxHashSet;
Expand Down Expand Up @@ -40,10 +39,7 @@ pub(super) fn check_trait<'tcx>(
checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
checker.check(lang_items.const_param_ty_trait(), |checker| {
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
})?;
checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
visit_implementation_of_const_param_ty(checker)
})?;
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
checker
Expand Down Expand Up @@ -138,12 +134,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
}
}

fn visit_implementation_of_const_param_ty(
checker: &Checker<'_>,
kind: LangItem,
) -> Result<(), ErrorGuaranteed> {
assert_matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);

fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
let tcx = checker.tcx;
let header = checker.impl_header;
let impl_did = checker.impl_def_id;
Expand All @@ -157,7 +148,7 @@ fn visit_implementation_of_const_param_ty(
}

let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
Ok(()) => Ok(()),
Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_infer/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,27 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
self.register_predicate_obligation(infcx, obligation);
}
}

/// Go over the list of pending obligations and try to evaluate them.
///
/// For each result:
/// Ok: remove the obligation from the list
/// Ambiguous: leave the obligation in the list to be evaluated later
/// Err: remove the obligation from the list and return an error
///
/// Returns a list of errors from obligations that evaluated to Err.
#[must_use]
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;

fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;

/// Evaluate all pending obligations, return error if they can't be evaluated.
///
/// For each result:
/// Ok: remove the obligation from the list
/// Ambiguous: remove the obligation from the list and return an error
/// Err: remove the obligation from the list and return an error
///
/// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
#[must_use]
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let errors = self.select_where_possible(infcx);
Expand Down
38 changes: 23 additions & 15 deletions compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.

use std::assert_matches::assert_matches;

use hir::LangItem;
use rustc_ast::Mutability;
use rustc_hir as hir;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_span::sym;

use crate::regions::InferCtxtRegionExt;
use crate::traits::{self, FulfillmentError, ObligationCause};
use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};

pub enum CopyImplementationError<'tcx> {
InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
Expand Down Expand Up @@ -98,10 +97,9 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
self_type: Ty<'tcx>,
lang_item: LangItem,
parent_cause: ObligationCause<'tcx>,
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
let mut need_unstable_feature_bound = false;

let inner_tys: Vec<_> = match *self_type.kind() {
// Trivially okay as these types are all:
Expand All @@ -112,18 +110,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(

// Handle types gated under `feature(unsized_const_params)`
// FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
if lang_item == LangItem::UnsizedConstParamTy =>
{
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not) => {
need_unstable_feature_bound = true;
vec![inner_ty]
}
ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
ty::Str => {
need_unstable_feature_bound = true;
vec![Ty::new_slice(tcx, tcx.types.u8)]
}
ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
}

ty::Array(inner_ty, _) => vec![inner_ty],

// `str` morally acts like a newtype around `[u8]`
Expand All @@ -137,7 +131,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
adt,
args,
parent_cause.clone(),
lang_item,
LangItem::ConstParamTy,
)
.map_err(ConstParamTyImplementationError::InfrigingFields)?;

Expand All @@ -153,11 +147,25 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);

// Make sure impls certain types are gated with #[unstable_feature_bound(unsized_const_params)]
if need_unstable_feature_bound {
ocx.register_obligation(Obligation::new(
tcx,
parent_cause.clone(),
param_env,
ty::ClauseKind::UnstableFeature(sym::unsized_const_params),
));

if !ocx.select_all_or_error().is_empty() {
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
}
}

ocx.register_bound(
parent_cause.clone(),
param_env,
inner_ty,
tcx.require_lang_item(lang_item, parent_cause.span),
tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span),
);

let errors = ocx.select_all_or_error();
Expand Down
33 changes: 5 additions & 28 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ pub trait Tuple {}
// We name this differently than the derive macro so that the `adt_const_params` can
// be used independently of `unsized_const_params` without requiring a full path
// to the derive macro every time it is used. This should be renamed on stabilization.
pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
pub trait ConstParamTy_: StructuralPartialEq + Eq {}

/// Derive macro generating an impl of the trait `ConstParamTy`.
#[rustc_builtin_macro]
Expand All @@ -1093,23 +1093,6 @@ pub macro ConstParamTy($item:item) {
/* compiler built-in */
}

#[lang = "unsized_const_param_ty"]
#[unstable(feature = "unsized_const_params", issue = "95174")]
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
/// A marker for types which can be used as types of `const` generic parameters.
///
/// Equivalent to [`ConstParamTy_`] except that this is used by
/// the `unsized_const_params` to allow for fake unstable impls.
pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}

/// Derive macro generating an impl of the trait `ConstParamTy`.
#[rustc_builtin_macro]
#[allow_internal_unstable(unsized_const_params)]
#[unstable(feature = "unsized_const_params", issue = "95174")]
pub macro UnsizedConstParamTy($item:item) {
/* compiler built-in */
}

// FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure`
marker_impls! {
#[unstable(feature = "adt_const_params", issue = "95174")]
Expand All @@ -1124,17 +1107,11 @@ marker_impls! {

marker_impls! {
#[unstable(feature = "unsized_const_params", issue = "95174")]
UnsizedConstParamTy for
usize, u8, u16, u32, u64, u128,
isize, i8, i16, i32, i64, i128,
bool,
char,
(),
{T: UnsizedConstParamTy, const N: usize} [T; N],

#[unstable_feature_bound(unsized_const_params)]
ConstParamTy_ for
str,
{T: UnsizedConstParamTy} [T],
{T: UnsizedConstParamTy + ?Sized} &T,
{T: ConstParamTy_} [T],
{T: ConstParamTy_ + ?Sized} &T,
}

/// A common trait implemented by all function pointers.
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/mem/transmutability.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
use crate::marker::ConstParamTy_;

/// Marks that `Src` is transmutable into `Self`.
///
Expand Down Expand Up @@ -83,6 +83,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
/// Furthermore, stability does not imply portability. For example, the size of
/// `usize` is stable, but not portable.
#[unstable(feature = "transmutability", issue = "99571")]
#[unstable_feature_bound(transmutability)]
#[lang = "transmute_trait"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
Expand Down Expand Up @@ -288,9 +289,8 @@ pub struct Assume {
}

#[unstable(feature = "transmutability", issue = "99571")]
#[unstable_feature_bound(transmutability)]
impl ConstParamTy_ for Assume {}
#[unstable(feature = "transmutability", issue = "99571")]
impl UnsizedConstParamTy for Assume {}

impl Assume {
/// With this, [`TransmuteFrom`] does not assume you have ensured any safety
Expand Down
10 changes: 2 additions & 8 deletions library/core/src/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// See core/src/primitive_docs.rs for documentation.

use crate::cmp::Ordering::{self, *};
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
use crate::marker::{ConstParamTy_, StructuralPartialEq};
use crate::ops::ControlFlow::{self, Break, Continue};

// Recursive macro for implementing n-ary tuple functions and operations
Expand Down Expand Up @@ -47,17 +47,11 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[unstable(feature = "adt_const_params", issue = "95174")]
#[unstable_feature_bound(unsized_const_params)]
impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+)
{}
}

maybe_tuple_doc! {
$($T)+ @
#[unstable(feature = "unsized_const_params", issue = "95174")]
impl<$($T: UnsizedConstParamTy),+> UnsizedConstParamTy for ($($T,)+)
{}
}

maybe_tuple_doc! {
$($T)+ @
#[unstable(feature = "structural_match", issue = "31434")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(adt_const_params, unsized_const_params)]

#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
pub struct Foo([u8]);

#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(incomplete_features)]
#![feature(adt_const_params, unsized_const_params)]

fn check(_: impl std::marker::UnsizedConstParamTy) {}
fn check(_: impl std::marker::ConstParamTy_) {}

fn main() {
check(main); //~ error: `fn() {main}` can't be used as a const parameter type
Expand Down
Loading
Loading