Skip to content

Rollup of 4 pull requests #131988

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

Merged
merged 10 commits into from
Oct 21, 2024
53 changes: 4 additions & 49 deletions compiler/rustc_const_eval/src/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::traits::BuiltinImplSource;
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
use rustc_middle::{bug, mir};
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
};
use tracing::{instrument, trace};
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
use tracing::instrument;

use super::ConstCx;

Expand Down Expand Up @@ -195,50 +192,8 @@ impl Qualif for NeedsNonConstDrop {
return false;
}

// FIXME(effects): If `destruct` is not a `const_trait`,
// or effects are disabled in this crate, then give up.
let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, Some(cx.body.span));
if !cx.tcx.has_host_param(destruct_def_id) || !cx.tcx.features().effects {
return NeedsDrop::in_any_value_of_ty(cx, ty);
}

let obligation = Obligation::new(
cx.tcx,
ObligationCause::dummy_with_span(cx.body.span),
cx.param_env,
ty::TraitRef::new(cx.tcx, destruct_def_id, [
ty::GenericArg::from(ty),
ty::GenericArg::from(cx.tcx.expected_host_effect_param_for_body(cx.def_id())),
]),
);

let infcx = cx.tcx.infer_ctxt().build();
let mut selcx = SelectionContext::new(&infcx);
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
// If we couldn't select a const destruct candidate, then it's bad
return true;
};

trace!(?impl_src);

if !matches!(
impl_src,
ImplSource::Builtin(BuiltinImplSource::Misc, _) | ImplSource::Param(_)
) {
// If our const destruct candidate is not ConstDestruct or implied by the param env,
// then it's bad
return true;
}

if impl_src.borrow_nested_obligations().is_empty() {
return false;
}

// If we had any errors, then it's bad
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligations(impl_src.nested_obligations());
let errors = ocx.select_all_or_error();
!errors.is_empty()
// FIXME(effects): Reimplement const drop checking.
NeedsDrop::in_any_value_of_ty(cx, ty)
}

fn in_adt_inherently<'tcx>(
Expand Down
21 changes: 11 additions & 10 deletions compiler/rustc_hir_analysis/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<'tcx> Bounds<'tcx> {
bound_trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
polarity: ty::PredicatePolarity,
constness: ty::BoundConstness,
constness: Option<ty::BoundConstness>,
predicate_filter: PredicateFilter,
) {
let clause = (
Expand Down Expand Up @@ -88,19 +88,20 @@ impl<'tcx> Bounds<'tcx> {
// associated type of `<T as Tr>` and make sure that the effect is compatible.
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
// FIXME(effects): revisit the correctness of this
(_, ty::BoundConstness::Const) => tcx.consts.false_,
(_, Some(ty::BoundConstness::Const)) => tcx.consts.false_,
// body owners that can have trait bounds
(DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => {
tcx.expected_host_effect_param_for_body(defining_def_id)
}
(
DefKind::Const | DefKind::Fn | DefKind::AssocFn,
Some(ty::BoundConstness::ConstIfConst),
) => tcx.expected_host_effect_param_for_body(defining_def_id),

(_, ty::BoundConstness::NotConst) => {
(_, None) => {
if !tcx.is_const_trait(bound_trait_ref.def_id()) {
return;
}
tcx.consts.true_
}
(DefKind::Trait, ty::BoundConstness::ConstIfConst) => {
(DefKind::Trait, Some(ty::BoundConstness::ConstIfConst)) => {
// we are in a trait, where `bound_trait_ref` could be:
// (1) a super trait `trait Foo: ~const Bar`.
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
Expand Down Expand Up @@ -138,7 +139,7 @@ impl<'tcx> Bounds<'tcx> {
return;
}

(DefKind::Impl { of_trait: true }, ty::BoundConstness::ConstIfConst) => {
(DefKind::Impl { of_trait: true }, Some(ty::BoundConstness::ConstIfConst)) => {
// this is a where clause on an impl header.
// push `<T as Tr>::Effects` into the set for the `Min` bound.
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
Expand Down Expand Up @@ -172,12 +173,12 @@ impl<'tcx> Bounds<'tcx> {
//
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
// that uses a `Bar` that implements `Trait` with `Maybe` effects.
(DefKind::AssocTy, ty::BoundConstness::ConstIfConst) => {
(DefKind::AssocTy, Some(ty::BoundConstness::ConstIfConst)) => {
// FIXME(effects): implement this
return;
}
// probably illegal in this position.
(_, ty::BoundConstness::ConstIfConst) => {
(_, Some(ty::BoundConstness::ConstIfConst)) => {
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
return;
}
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::GenericBound::Trait(poly_trait_ref) => {
let (constness, polarity) = match poly_trait_ref.modifiers {
hir::TraitBoundModifier::Const => {
(ty::BoundConstness::Const, ty::PredicatePolarity::Positive)
}
hir::TraitBoundModifier::MaybeConst => {
(ty::BoundConstness::ConstIfConst, ty::PredicatePolarity::Positive)
}
hir::TraitBoundModifier::None => {
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Positive)
(Some(ty::BoundConstness::Const), ty::PredicatePolarity::Positive)
}
hir::TraitBoundModifier::MaybeConst => (
Some(ty::BoundConstness::ConstIfConst),
ty::PredicatePolarity::Positive,
),
hir::TraitBoundModifier::None => (None, ty::PredicatePolarity::Positive),
hir::TraitBoundModifier::Negative => {
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Negative)
(None, ty::PredicatePolarity::Negative)
}
hir::TraitBoundModifier::Maybe => continue,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} = self.lower_poly_trait_ref(
&trait_bound.trait_ref,
trait_bound.span,
ty::BoundConstness::NotConst,
None,
ty::PredicatePolarity::Positive,
dummy_self,
&mut bounds,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
trait_ref: &hir::TraitRef<'tcx>,
span: Span,
constness: ty::BoundConstness,
constness: Option<ty::BoundConstness>,
polarity: ty::PredicatePolarity,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
Expand All @@ -675,7 +675,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some(self_ty),
);

if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
if let Some(constness) = constness
&& !self.tcx().is_const_trait(trait_def_id)
{
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
Expand Down
35 changes: 1 addition & 34 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,40 +537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// This check is here because there is currently no way to express a trait bound for `FnDef` types only.
if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
let fn_once_def_id =
self.tcx.require_lang_item(hir::LangItem::FnOnce, Some(span));
let fn_once_output_def_id =
self.tcx.require_lang_item(hir::LangItem::FnOnceOutput, Some(span));
if self.tcx.has_host_param(fn_once_def_id) {
let const_param: ty::GenericArg<'tcx> =
([self.tcx.consts.false_, self.tcx.consts.true_])[idx].into();
self.register_predicate(traits::Obligation::new(
self.tcx,
self.misc(span),
self.param_env,
ty::TraitRef::new(self.tcx, fn_once_def_id, [
arg_ty.into(),
fn_sig.inputs()[0].into(),
const_param,
]),
));

self.register_predicate(traits::Obligation::new(
self.tcx,
self.misc(span),
self.param_env,
ty::ProjectionPredicate {
projection_term: ty::AliasTerm::new(
self.tcx,
fn_once_output_def_id,
[arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
),
term: fn_sig.output().into(),
},
));

self.select_obligations_where_possible(|_| {});
} else if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
}
} else {
Expand Down
30 changes: 25 additions & 5 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut only_extras_so_far = errors
.peek()
.is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
let mut prev_extra_idx = None;
let mut suggestions = vec![];
while let Some(error) = errors.next() {
only_extras_so_far &= matches!(error, Error::Extra(_));
Expand Down Expand Up @@ -1165,11 +1166,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// fn f() {}
// - f(0, 1,)
// + f()
if only_extras_so_far
&& !errors
.peek()
.is_some_and(|next_error| matches!(next_error, Error::Extra(_)))
{
let trim_next_comma = match errors.peek() {
Some(Error::Extra(provided_idx))
if only_extras_so_far
&& provided_idx.index() > arg_idx.index() + 1 =>
// If the next Error::Extra ("next") doesn't next to current ("current"),
// fn foo(_: (), _: u32) {}
// - foo("current", (), 1u32, "next")
// + foo((), 1u32)
// If the previous error is not a `Error::Extra`, then do not trim the next comma
// - foo((), "current", 42u32, "next")
// + foo((), 42u32)
{
prev_extra_idx.map_or(true, |prev_extra_idx| {
prev_extra_idx + 1 == arg_idx.index()
})
}
// If no error left, we need to delete the next comma
None if only_extras_so_far => true,
// Not sure if other error type need to be handled as well
_ => false,
};

if trim_next_comma {
let next = provided_arg_tys
.get(arg_idx + 1)
.map(|&(_, sp)| sp)
Expand All @@ -1192,6 +1211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
SuggestionText::Remove(_) => SuggestionText::Remove(true),
_ => SuggestionText::DidYouMean,
};
prev_extra_idx = Some(arg_idx.index())
}
}
Error::Missing(expected_idx) => {
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,7 @@ pub enum SelectionCandidate<'tcx> {

/// Implementation of a `Fn`-family trait by one of the anonymous
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
FnPointerCandidate {
fn_host_effect: ty::Const<'tcx>,
},
FnPointerCandidate,

TraitAliasCandidate,

Expand All @@ -180,9 +178,6 @@ pub enum SelectionCandidate<'tcx> {
BuiltinObjectCandidate,

BuiltinUnsizeCandidate,

/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
ConstDestructCandidate(Option<DefId>),
}

/// The result of trait evaluation. The order is important
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1956,7 +1956,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
define_scoped_cx!(self);

match constness {
ty::BoundConstness::NotConst => {}
ty::BoundConstness::Const => {
p!("const ");
}
Expand Down Expand Up @@ -2948,7 +2947,10 @@ impl<'tcx> ty::TraitPredicate<'tcx> {
}

#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitPredPrintWithBoundConstness<'tcx>(ty::TraitPredicate<'tcx>, ty::BoundConstness);
pub struct TraitPredPrintWithBoundConstness<'tcx>(
ty::TraitPredicate<'tcx>,
Option<ty::BoundConstness>,
);

impl<'tcx> fmt::Debug for TraitPredPrintWithBoundConstness<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -2966,7 +2968,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> {

fn print_with_bound_constness(
self,
constness: ty::BoundConstness,
constness: Option<ty::BoundConstness>,
) -> ty::Binder<'tcx, TraitPredPrintWithBoundConstness<'tcx>> {
self.map_bound(|trait_pred| TraitPredPrintWithBoundConstness(trait_pred, constness))
}
Expand Down Expand Up @@ -3206,7 +3208,9 @@ define_print_and_forward_display! {

TraitPredPrintWithBoundConstness<'tcx> {
p!(print(self.0.trait_ref.self_ty()), ": ");
p!(pretty_print_bound_constness(self.1));
if let Some(constness) = self.1 {
p!(pretty_print_bound_constness(constness));
}
if let ty::PredicatePolarity::Negative = self.0.polarity {
p!("!");
}
Expand Down
18 changes: 0 additions & 18 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,24 +907,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

/// Constructs generic args for an item, optionally appending a const effect param type
pub fn with_opt_host_effect_param(
self,
caller_def_id: LocalDefId,
callee_def_id: DefId,
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
) -> ty::GenericArgsRef<'tcx> {
let generics = self.generics_of(callee_def_id);
assert_eq!(generics.parent, None);

let opt_const_param = generics
.host_effect_index
.is_some()
.then(|| ty::GenericArg::from(self.expected_host_effect_param_for_body(caller_def_id)));

self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
}

/// Expand any [weak alias types][weak] contained within the given `value`.
///
/// This should be used over other normalization routines in situations where
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_mir_build/src/build/matches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,12 +454,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
};

let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
let method = trait_method(
self.tcx,
eq_def_id,
sym::eq,
self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [compare_ty, compare_ty]),
);
let method = trait_method(self.tcx, eq_def_id, sym::eq, [compare_ty, compare_ty]);

let bool_ty = self.tcx.types.bool;
let eq_result = self.temp(bool_ty, source_info.span);
Expand Down
Loading
Loading