1
Fork 0

Auto merge of #118661 - fee1-dead-contrib:restore-const-partialEq, r=compiler-errors

Restore `const PartialEq`

And thus fixes a number of tests. There is a bug that still needs to be fixed, so WIP for now.

r? `@compiler-errors`
This commit is contained in:
bors 2023-12-11 10:34:51 +00:00
commit 6f40082313
38 changed files with 154 additions and 199 deletions

View file

@ -120,7 +120,6 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
print_prefix(self)?; print_prefix(self)?;
let args = let args =

View file

@ -641,7 +641,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
_args: &[GenericArg<'tcx>], _args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
print_prefix(self) print_prefix(self)
} }
@ -1237,9 +1236,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
let did1 = def1.did(); let did1 = def1.did();
let did2 = def2.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); 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); self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let path1 = self.tcx.def_path_str(did1); let path1 = self.tcx.def_path_str(did1);

View file

@ -757,7 +757,6 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
.tcx .tcx
.generics_of(def.did()) .generics_of(def.did())
.own_args_no_defaults(self.tcx, args) .own_args_no_defaults(self.tcx, args)
.0
.iter() .iter()
.map(|&arg| self.arg_cost(arg)) .map(|&arg| self.arg_cost(arg))
.sum::<usize>() .sum::<usize>()
@ -1186,7 +1185,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
} }
let args = self.infcx.resolve_vars_if_possible(args); let args = self.infcx.resolve_vars_if_possible(args);
let generic_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 { let span = match expr.kind {
ExprKind::MethodCall(path, ..) => path.ident.span, ExprKind::MethodCall(path, ..) => path.ident.span,
_ => expr.span, _ => expr.span,

View file

@ -116,7 +116,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// FIXME: extract this logic for use in other diagnostics. // FIXME: extract this logic for use in other diagnostics.
let (trait_ref, assoc_args) = proj.trait_ref_and_own_args(tcx); let (trait_ref, assoc_args) = proj.trait_ref_and_own_args(tcx);
let item_name = tcx.item_name(proj.def_id); 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 // Here, we try to see if there's an existing
// trait implementation that matches the one that // trait implementation that matches the one that
@ -775,7 +775,7 @@ fn foo(&self) -> Self::T { String::new() }
let span = Span::new(pos, pos, span.ctxt(), span.parent()); let span = Span::new(pos, pos, span.ctxt(), span.parent());
(span, format!(", {} = {}", assoc.ident(tcx), ty)) (span, format!(", {} = {}", assoc.ident(tcx), ty))
} else { } 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)) (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
}; };
diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect); diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
@ -784,13 +784,9 @@ fn foo(&self) -> Self::T { String::new() }
false false
} }
pub fn format_generic_args( pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
&self,
assoc_def_id: DefId,
args: &[ty::GenericArg<'tcx>],
) -> String {
FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |cx| { 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`.") .expect("could not write to `String`.")
} }

View file

@ -1285,7 +1285,6 @@ impl<'tcx> LateContext<'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
_args: &[GenericArg<'tcx>], _args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
print_prefix(self) print_prefix(self)
} }

View file

@ -336,7 +336,8 @@ impl<'hir> Map<'hir> {
/// Returns the `BodyOwnerKind` of this `LocalDefId`. /// Returns the `BodyOwnerKind` of this `LocalDefId`.
/// ///
/// Panics if `LocalDefId` does not have an associated body. /// 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) { match self.tcx.def_kind(def_id) {
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
BodyOwnerKind::Const { inline: false } BodyOwnerKind::Const { inline: false }
@ -356,20 +357,17 @@ impl<'hir> Map<'hir> {
/// This should only be used for determining the context of a body, a return /// 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`, /// 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. /// 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) { let ccx = match self.body_owner_kind(def_id) {
BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
BodyOwnerKind::Static(mt) => ConstContext::Static(mt), BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None, BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
BodyOwnerKind::Fn | BodyOwnerKind::Closure BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
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()) => {
ConstContext::ConstFn ConstContext::ConstFn
} }
BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None, BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
}; };

View file

@ -320,21 +320,21 @@ impl<'tcx> Generics {
&'tcx self, &'tcx self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
args: &'tcx [ty::GenericArg<'tcx>], args: &'tcx [ty::GenericArg<'tcx>],
) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericParamDef]) { ) -> &'tcx [ty::GenericArg<'tcx>] {
let mut own_args = self.parent_count..self.count(); let mut own_params = self.parent_count..self.count();
let mut own_params = 0..self.params.len();
if self.has_self && self.parent.is_none() { if self.has_self && self.parent.is_none() {
own_args.start = 1;
own_params.start = 1; own_params.start = 1;
} }
let verbose = tcx.sess.verbose();
// Filter the default arguments. // Filter the default arguments.
// //
// This currently uses structural equality instead // This currently uses structural equality instead
// of semantic equivalence. While not ideal, that's // of semantic equivalence. While not ideal, that's
// good enough for now as this should only be used // good enough for now as this should only be used
// for diagnostics anyways. // for diagnostics anyways.
let num_default_params = self own_params.end -= self
.params .params
.iter() .iter()
.rev() .rev()
@ -342,12 +342,12 @@ impl<'tcx> Generics {
param.default_value(tcx).is_some_and(|default| { param.default_value(tcx).is_some_and(|default| {
default.instantiate(tcx, args) == args[param.index as usize] 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(); .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`. /// Returns the args corresponding to the generic parameters of this item, excluding `Self`.

View file

@ -83,7 +83,6 @@ pub trait Printer<'tcx>: Sized {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
params: &[ty::GenericParamDef],
) -> Result<(), PrintError>; ) -> Result<(), PrintError>;
// Defaults (should not be overridden): // Defaults (should not be overridden):
@ -142,12 +141,10 @@ pub trait Printer<'tcx>: Sized {
// on top of the same path, but without its own generics. // on top of the same path, but without its own generics.
_ => { _ => {
if !generics.params.is_empty() && args.len() >= generics.count() { if !generics.params.is_empty() && args.len() >= generics.count() {
let (args, params) = let args = generics.own_args_no_defaults(self.tcx(), args);
generics.own_args_no_defaults(self.tcx(), args);
return self.path_generic_args( return self.path_generic_args(
|cx| cx.print_def_path(def_id, parent_args), |cx| cx.print_def_path(def_id, parent_args),
args, args,
params,
); );
} }
} }

View file

@ -965,7 +965,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
define_scoped_cx!(cx); define_scoped_cx!(cx);
// Get the (single) generic ty (the args) of this FnOnce trait ref. // Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = tcx.generics_of(trait_ref.def_id); 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()) { 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 // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
@ -1031,7 +1031,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(print(trait_ref.print_only_trait_name())); p!(print(trait_ref.print_only_trait_name()));
let generics = tcx.generics_of(trait_ref.def_id); 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() { if !own_args.is_empty() || !assoc_items.is_empty() {
let mut first = true; let mut first = true;
@ -1183,7 +1183,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
) )
}, },
&alias_ty.args[1..], &alias_ty.args[1..],
&self.tcx().generics_of(alias_ty.def_id).params,
) )
} }
@ -1232,7 +1231,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
let dummy_cx = Ty::new_fresh(cx.tcx(), 0); let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx); let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let (args, _) = cx let args = cx
.tcx() .tcx()
.generics_of(principal.def_id) .generics_of(principal.def_id)
.own_args_no_defaults(cx.tcx(), principal.args); .own_args_no_defaults(cx.tcx(), principal.args);
@ -2030,26 +2029,14 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
print_prefix(self)?; print_prefix(self)?;
let tcx = self.tcx; if !args.is_empty() {
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 self.in_value { if self.in_value {
write!(self, "::")?; write!(self, "::")?;
} }
self.generic_delimiters(|cx| cx.comma_sep(args.map(|(arg, _)| arg))) self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
} else { } else {
Ok(()) Ok(())
} }
@ -2881,7 +2868,8 @@ define_print_and_forward_display! {
TraitPredPrintModifiersAndPath<'tcx> { TraitPredPrintModifiersAndPath<'tcx> {
if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index 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 "); p!("~const ");
} }
} }

View file

@ -782,7 +782,8 @@ impl<'tcx> TyCtxt<'tcx> {
|| self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct()) || 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, // FIXME(effects): This is suspicious and should probably not be done,
// especially now that we enforce host effects and then properly handle // especially now that we enforce host effects and then properly handle
// effect vars during fallback. // effect vars during fallback.

View file

@ -342,7 +342,6 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
print_prefix(self)?; print_prefix(self)?;

View file

@ -298,7 +298,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
) )
}, },
args, args,
&self.tcx.generics_of(impl_def_id).params,
)?; )?;
} else { } else {
self.push_disambiguator(key.disambiguated_data.disambiguator as u64); self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
@ -801,7 +800,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
&mut self, &mut self,
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
_params: &[ty::GenericParamDef],
) -> Result<(), PrintError> { ) -> Result<(), PrintError> {
// Don't print any regions if they're all erased. // Don't print any regions if they're all erased.
let print_regions = args.iter().any(|arg| match arg.unpack() { let print_regions = args.iter().any(|arg| match arg.unpack() {

View file

@ -3628,17 +3628,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
is_derivable_trait && is_derivable_trait &&
// Ensure all fields impl the trait. // Ensure all fields impl the trait.
adt.all_fields().all(|field| { 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 { let trait_args = match diagnostic_name {
sym::PartialEq | sym::PartialOrd => { sym::PartialEq | sym::PartialOrd => {
Some(field_ty) Some(field_ty)
} }
_ => None, _ => 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 { let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
trait_ref: ty::TraitRef::new(self.tcx, trait_ref: ty::TraitRef::new(self.tcx,
trait_pred.def_id(), trait_pred.def_id(),
[field_ty].into_iter().chain(trait_args), [field_ty].into_iter().chain(trait_args).chain(host),
), ),
..*tr ..*tr
}); });
@ -3659,6 +3661,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred.skip_binder().self_ty(), trait_pred.skip_binder().self_ty(),
diagnostic_name, diagnostic_name,
), ),
// FIXME(effects, const_trait_impl) derive_const as suggestion?
format!("#[derive({diagnostic_name})]\n"), format!("#[derive({diagnostic_name})]\n"),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View file

@ -224,6 +224,7 @@ use self::Ordering::*;
append_const_msg append_const_msg
)] )]
#[rustc_diagnostic_item = "PartialEq"] #[rustc_diagnostic_item = "PartialEq"]
#[cfg_attr(not(bootstrap), const_trait)]
pub trait PartialEq<Rhs: ?Sized = Self> { pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used /// This method tests for `self` and `other` values to be equal, and is used
/// by `==`. /// by `==`.
@ -1414,12 +1415,23 @@ mod impls {
macro_rules! partial_eq_impl { macro_rules! partial_eq_impl {
($($t:ty)*) => ($( ($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg(bootstrap)]
impl PartialEq for $t { impl PartialEq for $t {
#[inline] #[inline]
fn eq(&self, other: &$t) -> bool { (*self) == (*other) } fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
#[inline] #[inline]
fn ne(&self, other: &$t) -> bool { (*self) != (*other) } 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) }
}
)*) )*)
} }

View file

@ -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() && let Some(def_id) = trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::PartialEq, 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) && 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 // If all of our fields implement `Eq`, we can implement `Eq` too
&& adt && adt
.all_fields() .all_fields()
.map(|f| f.ty(cx.tcx, args)) .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( span_lint_and_sugg(
cx, cx,

View file

@ -194,6 +194,10 @@ fn is_same_generics<'tcx>(
.enumerate() .enumerate()
.skip(1) // skip `Self` implicit arg .skip(1) // skip `Self` implicit arg
.all(|(arg_index, 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 Some(ty) = arg.as_type() {
if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind() if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind()
// `index == 0` means that it's referring to `Self`, // `index == 0` means that it's referring to `Self`,

View file

@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) .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 &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
&& let param_env = cx.tcx.param_env(fn_id) && 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) = && let Some(into_iter_ty) =
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_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) && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)

View file

@ -186,6 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
cx.param_env, cx.param_env,
ty, ty,
t, t,
None,
[Option::<ty::GenericArg<'tcx>>::None], [Option::<ty::GenericArg<'tcx>>::None],
) )
}) })

View file

@ -214,7 +214,8 @@ pub fn implements_trait<'tcx>(
trait_id: DefId, trait_id: DefId,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
) -> bool { ) -> bool {
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, args.iter().map(|&x| Some(x))) let callee_id = cx.enclosing_body.map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id());
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x)))
} }
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
@ -223,9 +224,10 @@ pub fn implements_trait_with_env<'tcx>(
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
trait_id: DefId, trait_id: DefId,
callee_id: DefId,
args: &[GenericArg<'tcx>], args: &[GenericArg<'tcx>],
) -> bool { ) -> bool {
implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, args.iter().map(|&x| Some(x))) implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, Some(callee_id), args.iter().map(|&x| Some(x)))
} }
/// Same as `implements_trait_from_env` but takes the arguments as an iterator. /// Same as `implements_trait_from_env` but takes the arguments as an iterator.
@ -234,6 +236,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
trait_id: DefId, trait_id: DefId,
callee_id: Option<DefId>,
args: impl IntoIterator<Item = impl Into<Option<GenericArg<'tcx>>>>, args: impl IntoIterator<Item = impl Into<Option<GenericArg<'tcx>>>>,
) -> bool { ) -> bool {
// Clippy shouldn't have infer types // Clippy shouldn't have infer types
@ -245,12 +248,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
} }
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let trait_ref = TraitRef::new( let args = args.into_iter().map(|arg| {
tcx,
trait_id,
Some(GenericArg::from(ty))
.into_iter()
.chain(args.into_iter().map(|arg| {
arg.into().unwrap_or_else(|| { arg.into().unwrap_or_else(|| {
let orig = TypeVariableOrigin { let orig = TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable, kind: TypeVariableOriginKind::MiscVariable,
@ -258,7 +256,21 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
}; };
infcx.next_ty_var(orig).into() infcx.next_ty_var(orig).into()
}) })
})), }).collect::<Vec<_>>();
// If an effect arg was not specified, we need to specify it.
let effect_arg = if tcx.generics_of(trait_id).host_effect_index.is_some_and(|x| args.get(x - 1).is_none()) {
Some(GenericArg::from(callee_id.map(|def_id| tcx.expected_host_effect_param_for_body(def_id)).unwrap_or(tcx.consts.true_)))
} else {
None
};
let trait_ref = TraitRef::new(
tcx,
trait_id,
Some(GenericArg::from(ty))
.into_iter()
.chain(args).chain(effect_arg),
); );
debug_assert_matches!( debug_assert_matches!(

View file

@ -4,12 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls`
LL | #![feature(const_fn_trait_ref_impls)] LL | #![feature(const_fn_trait_ref_impls)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0635]: unknown feature `const_cmp`
--> $DIR/fn_trait_refs.rs:8:12
|
LL | #![feature(const_cmp)]
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:15 --> $DIR/fn_trait_refs.rs:15:15
| |
@ -80,6 +74,6 @@ LL | T: ~const FnMut<()> + ~const Destruct,
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 12 previous errors error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0635`. For more information about this error, try `rustc --explain E0635`.

View file

@ -1,4 +1,4 @@
// known-bug: #110395 // check-pass
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#[const_trait] #[const_trait]

View file

@ -1,8 +0,0 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-in-impl.rs:9:16
|
LL | impl<T: ~const PartialEq> const MyPartialEq for T {
| ^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -1,8 +1,8 @@
//! Basic test for calling methods on generic type parameters in `const fn`. //! Basic test for calling methods on generic type parameters in `const fn`.
// known-bug: #110395 // check-pass
#![feature(const_trait_impl)] #![feature(const_trait_impl, effects)]
struct S; struct S;

View file

@ -1,14 +0,0 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-chain.rs:18:32
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-chain.rs:22:40
|
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -1,6 +1,6 @@
// known-bug: #110395 // check-pass
#![feature(const_trait_impl)] #![feature(const_trait_impl, effects)]
struct S; struct S;

View file

@ -1,14 +0,0 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-dup-bound.rs:18:44
|
LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-dup-bound.rs:25:37
|
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -1,10 +1,9 @@
// FIXME(effects)
// check-pass
#![feature(const_trait_impl, effects)] #![feature(const_trait_impl, effects)]
pub const fn equals_self<T: PartialEq>(t: &T) -> bool { pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
*t == *t *t == *t
// (remove this) ~^ ERROR can't compare //~^ ERROR mismatched types
// FIXME(effects): diagnostic
} }
fn main() {} fn main() {}

View file

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/call-generic-method-fail.rs:4:5
|
LL | *t == *t
| ^^^^^^^^ expected `host`, found `true`
|
= note: expected constant `host`
found constant `true`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -21,7 +21,6 @@ const fn equals_self<T: ~const Foo>(t: &T) -> bool {
// it not using the impl. // it not using the impl.
pub const EQ: bool = equals_self(&S); pub const EQ: bool = equals_self(&S);
//~^ ERROR //~^ ERROR: the trait bound `S: ~const Foo` is not satisfied
// FIXME(effects) the diagnostics here isn't ideal, we shouldn't get `<false>`
fn main() {} fn main() {}

View file

@ -1,8 +1,8 @@
//! Basic test for calling methods on generic type parameters in `const fn`. //! Basic test for calling methods on generic type parameters in `const fn`.
// known-bug: #110395 // check-pass
#![feature(const_trait_impl)] #![feature(const_trait_impl, effects)]
struct S; struct S;

View file

@ -1,8 +0,0 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-pass.rs:18:32
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -3,6 +3,7 @@
#![feature( #![feature(
associated_type_bounds, associated_type_bounds,
const_trait_impl, const_trait_impl,
effects,
const_cmp, const_cmp,
)] )]

View file

@ -1,39 +1,28 @@
error[E0635]: unknown feature `const_cmp` error[E0277]: can't compare `impl PartialEq + Destruct + Copy` with `impl PartialEq + Destruct + Copy`
--> $DIR/const-impl-trait.rs:6:5 --> $DIR/const-impl-trait.rs:28:17
|
LL | const_cmp,
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:11:30
|
LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:15:30
|
LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:16:20
|
LL | -> impl ~const PartialEq + ~const Destruct
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:23:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:27:29
| |
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `impl PartialEq + Destruct + Copy == impl PartialEq + Destruct + Copy`
|
= help: the trait `~const PartialEq` is not implemented for `impl PartialEq + Destruct + Copy`
note: required by a bound in `Foo::{opaque#0}`
--> $DIR/const-impl-trait.rs:24:22
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
error: aborting due to 6 previous errors error[E0277]: can't drop `impl PartialEq + Destruct + Copy`
--> $DIR/const-impl-trait.rs:28:17
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `impl PartialEq + Destruct + Copy`
|
note: required by a bound in `Foo::{opaque#0}`
--> $DIR/const-impl-trait.rs:24:41
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
For more information about this error, try `rustc --explain E0635`. error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,5 +1,6 @@
// known-bug: #110395 // known-bug: #110395
#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
pub struct A; pub struct A;

View file

@ -1,15 +1,28 @@
error[E0635]: unknown feature `const_cmp`
--> $DIR/derive-const-use.rs:2:30
|
LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
| ^^^^^^^^^
error[E0635]: unknown feature `const_default_impls` error[E0635]: unknown feature `const_default_impls`
--> $DIR/derive-const-use.rs:2:41 --> $DIR/derive-const-use.rs:3:41
| |
LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:7:12
|
LL | impl const Default for A {
| ^^^^^^^
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:15:16
|
LL | #[derive_const(Default, PartialEq)]
| ^^^^^^^
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0635`. For more information about this error, try `rustc --explain E0635`.

View file

@ -1,7 +1,7 @@
// known-bug: #110395 // check-pass
#![feature(derive_const)] #![feature(derive_const)]
#![feature(const_trait_impl)] #![feature(const_trait_impl, effects)]
#[derive_const(PartialEq)] #[derive_const(PartialEq)]
pub struct Reverse<T>(T); pub struct Reverse<T>(T);

View file

@ -1,10 +0,0 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/derive-const-with-params.rs:6:16
|
LL | #[derive_const(PartialEq)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error

View file

@ -16,10 +16,6 @@ help: consider annotating `S<T>` with `#[derive(PartialEq)]`
LL + #[derive(PartialEq)] LL + #[derive(PartialEq)]
LL | struct S<T>(T); LL | struct S<T>(T);
| |
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | pub fn foo<T>(s: S<T>, t: S<T>) where S<T>: PartialEq {
| +++++++++++++++++++++
error: aborting due to 1 previous error error: aborting due to 1 previous error