Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore const PartialEq #118661

Merged
merged 7 commits into from
Dec 11, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/rustc_const_eval/src/util/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
print_prefix(self)?;
let args =
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
_args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
print_prefix(self)
}
Expand Down Expand Up @@ -1237,9 +1236,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
let did1 = def1.did();
let did2 = def2.did();
let (sub_no_defaults_1, _) =
let sub_no_defaults_1 =
self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1);
let (sub_no_defaults_2, _) =
let sub_no_defaults_2 =
self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let path1 = self.tcx.def_path_str(did1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,6 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
.tcx
.generics_of(def.did())
.own_args_no_defaults(self.tcx, args)
.0
.iter()
.map(|&arg| self.arg_cost(arg))
.sum::<usize>()
Expand Down Expand Up @@ -1186,7 +1185,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
}
let args = self.infcx.resolve_vars_if_possible(args);
let generic_args =
&generics.own_args_no_defaults(tcx, args).0[generics.own_counts().lifetimes..];
&generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
let span = match expr.kind {
ExprKind::MethodCall(path, ..) => path.ident.span,
_ => expr.span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// FIXME: extract this logic for use in other diagnostics.
let (trait_ref, assoc_args) = proj.trait_ref_and_own_args(tcx);
let item_name = tcx.item_name(proj.def_id);
let item_args = self.format_generic_args(proj.def_id, assoc_args);
let item_args = self.format_generic_args(assoc_args);

// Here, we try to see if there's an existing
// trait implementation that matches the one that
Expand Down Expand Up @@ -775,7 +775,7 @@ fn foo(&self) -> Self::T { String::new() }
let span = Span::new(pos, pos, span.ctxt(), span.parent());
(span, format!(", {} = {}", assoc.ident(tcx), ty))
} else {
let item_args = self.format_generic_args(assoc.def_id, assoc_args);
let item_args = self.format_generic_args(assoc_args);
(span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
};
diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
Expand All @@ -784,13 +784,9 @@ fn foo(&self) -> Self::T { String::new() }
false
}

pub fn format_generic_args(
&self,
assoc_def_id: DefId,
args: &[ty::GenericArg<'tcx>],
) -> String {
pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |cx| {
cx.path_generic_args(|_| Ok(()), args, &self.infcx.tcx.generics_of(assoc_def_id).params)
cx.path_generic_args(|_| Ok(()), args)
})
.expect("could not write to `String`.")
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,6 @@ impl<'tcx> LateContext<'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
_args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
print_prefix(self)
}
Expand Down
16 changes: 7 additions & 9 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,8 @@ impl<'hir> Map<'hir> {
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
///
/// Panics if `LocalDefId` does not have an associated body.
pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind {
pub fn body_owner_kind(self, def_id: impl Into<DefId>) -> BodyOwnerKind {
let def_id = def_id.into();
match self.tcx.def_kind(def_id) {
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
BodyOwnerKind::Const { inline: false }
Expand All @@ -356,20 +357,17 @@ impl<'hir> Map<'hir> {
/// This should only be used for determining the context of a body, a return
/// value of `Some` does not always suggest that the owner of the body is `const`,
/// just that it has to be checked as if it were.
pub fn body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
pub fn body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstContext> {
let def_id = def_id.into();
let ccx = match self.body_owner_kind(def_id) {
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),

BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,
BodyOwnerKind::Fn | BodyOwnerKind::Closure
if self.tcx.is_const_fn_raw(def_id.to_def_id()) =>
{
ConstContext::ConstFn
}
BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => {
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
ConstContext::ConstFn
}
BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
};

Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,34 +320,34 @@ impl<'tcx> Generics {
&'tcx self,
tcx: TyCtxt<'tcx>,
args: &'tcx [ty::GenericArg<'tcx>],
) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericParamDef]) {
let mut own_args = self.parent_count..self.count();
let mut own_params = 0..self.params.len();
) -> &'tcx [ty::GenericArg<'tcx>] {
let mut own_params = self.parent_count..self.count();
if self.has_self && self.parent.is_none() {
own_args.start = 1;
own_params.start = 1;
}

let verbose = tcx.sess.verbose();

// Filter the default arguments.
//
// This currently uses structural equality instead
// of semantic equivalence. While not ideal, that's
// good enough for now as this should only be used
// for diagnostics anyways.
let num_default_params = self
own_params.end -= self
.params
.iter()
.rev()
.take_while(|param| {
param.default_value(tcx).is_some_and(|default| {
default.instantiate(tcx, args) == args[param.index as usize]
})
// filter out trailing effect params, if we're not in `-Zverbose`.
|| (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. }))
})
.count();
own_params.end -= num_default_params;
own_args.end -= num_default_params;

(&args[own_args], &self.params[own_params])
&args[own_params]
}

/// Returns the args corresponding to the generic parameters of this item, excluding `Self`.
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ pub trait Printer<'tcx>: Sized {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
params: &[ty::GenericParamDef],
) -> Result<(), PrintError>;

// Defaults (should not be overridden):
Expand Down Expand Up @@ -142,12 +141,10 @@ pub trait Printer<'tcx>: Sized {
// on top of the same path, but without its own generics.
_ => {
if !generics.params.is_empty() && args.len() >= generics.count() {
let (args, params) =
generics.own_args_no_defaults(self.tcx(), args);
let args = generics.own_args_no_defaults(self.tcx(), args);
return self.path_generic_args(
|cx| cx.print_def_path(def_id, parent_args),
args,
params,
);
}
}
Expand Down
26 changes: 7 additions & 19 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
define_scoped_cx!(cx);
// Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = tcx.generics_of(trait_ref.def_id);
let (own_args, _) = generics.own_args_no_defaults(tcx, trait_ref.args);
let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);

match (entry.return_ty, own_args[0].expect_ty()) {
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
Expand Down Expand Up @@ -1032,7 +1032,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(print(trait_ref.print_only_trait_name()));

let generics = tcx.generics_of(trait_ref.def_id);
let (own_args, _) = generics.own_args_no_defaults(tcx, trait_ref.args);
let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);

if !own_args.is_empty() || !assoc_items.is_empty() {
let mut first = true;
Expand Down Expand Up @@ -1184,7 +1184,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
)
},
&alias_ty.args[1..],
&self.tcx().generics_of(alias_ty.def_id).params,
)
}

Expand Down Expand Up @@ -1233,7 +1232,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);

let (args, _) = cx
let args = cx
.tcx()
.generics_of(principal.def_id)
.own_args_no_defaults(cx.tcx(), principal.args);
Expand Down Expand Up @@ -2031,26 +2030,14 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
print_prefix(self)?;

let tcx = self.tcx;
let verbose = tcx.sess.verbose();
let mut args = args
.iter()
.copied()
.zip(params)
// If -Zverbose is passed, we should print the host parameter instead
// of eating it.
.filter(|(_, param)| verbose || !param.is_host_effect())
.peekable();

if args.peek().is_some() {
if !args.is_empty() {
if self.in_value {
write!(self, "::")?;
}
self.generic_delimiters(|cx| cx.comma_sep(args.map(|(arg, _)| arg)))
self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
} else {
Ok(())
}
Expand Down Expand Up @@ -2882,7 +2869,8 @@ define_print_and_forward_display! {
TraitPredPrintModifiersAndPath<'tcx> {
if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index
{
if self.0.trait_ref.args.const_at(idx) != cx.tcx().consts.true_ {
let arg = self.0.trait_ref.args.const_at(idx);
if arg != cx.tcx().consts.true_ && !arg.has_infer() {
p!("~const ");
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,8 @@ impl<'tcx> TyCtxt<'tcx> {
|| self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct())
}

pub fn expected_host_effect_param_for_body(self, def_id: LocalDefId) -> ty::Const<'tcx> {
pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> {
let def_id = def_id.into();
// FIXME(effects): This is suspicious and should probably not be done,
// especially now that we enforce host effects and then properly handle
// effect vars during fallback.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_symbol_mangling/src/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
print_prefix(self)?;

Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
)
},
args,
&self.tcx.generics_of(impl_def_id).params,
)?;
} else {
self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
Expand Down Expand Up @@ -801,7 +800,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
&mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> {
// Don't print any regions if they're all erased.
let print_regions = args.iter().any(|arg| match arg.unpack() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3628,17 +3628,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
is_derivable_trait &&
// Ensure all fields impl the trait.
adt.all_fields().all(|field| {
let field_ty = field.ty(self.tcx, args);
let field_ty = ty::GenericArg::from(field.ty(self.tcx, args));
let trait_args = match diagnostic_name {
sym::PartialEq | sym::PartialOrd => {
Some(field_ty)
}
_ => None,
};
// Also add host param, if present
let host = self.tcx.generics_of(trait_pred.def_id()).host_effect_index.map(|idx| trait_pred.skip_binder().trait_ref.args[idx]);
let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
trait_ref: ty::TraitRef::new(self.tcx,
trait_pred.def_id(),
[field_ty].into_iter().chain(trait_args),
[field_ty].into_iter().chain(trait_args).chain(host),
),
..*tr
});
Expand All @@ -3659,6 +3661,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred.skip_binder().self_ty(),
diagnostic_name,
),
// FIXME(effects, const_trait_impl) derive_const as suggestion?
format!("#[derive({diagnostic_name})]\n"),
Applicability::MaybeIncorrect,
);
Expand Down
12 changes: 12 additions & 0 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ use self::Ordering::*;
append_const_msg
)]
#[rustc_diagnostic_item = "PartialEq"]
#[cfg_attr(not(bootstrap), const_trait)]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// by `==`.
Expand Down Expand Up @@ -1414,12 +1415,23 @@ mod impls {
macro_rules! partial_eq_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(bootstrap)]
impl PartialEq for $t {
#[inline]
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
#[inline]
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
#[cfg(not(bootstrap))]
impl const PartialEq for $t {
#[inline]
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
#[inline]
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
}
)*)
}

Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,12 +450,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
&& let Some(def_id) = trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
// If all of our fields implement `Eq`, we can implement `Eq` too
&& adt
.all_fields()
.map(|f| f.ty(cx.tcx, args))
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]))
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
{
span_lint_and_sugg(
cx,
Expand Down
4 changes: 4 additions & 0 deletions src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ fn is_same_generics<'tcx>(
.enumerate()
.skip(1) // skip `Self` implicit arg
.all(|(arg_index, arg)| {
if [implied_by_generics.host_effect_index, implied_generics.host_effect_index].contains(&Some(arg_index)) {
// skip host effect params in determining whether generics are same
return true;
}
if let Some(ty) = arg.as_type() {
if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind()
// `index == 0` means that it's referring to `Self`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
&& let param_env = cx.tcx.param_env(fn_id)
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, &[])
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
&& let Some(into_iter_ty) =
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)
Expand Down