Auto merge of #131988 - matthiaskrgr:rollup-tx173wn, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #126588 (Added more scenarios where comma to be removed in the function arg) - #131728 (bootstrap: extract builder cargo to its own module) - #131968 (Rip out old effects var handling code from traits) - #131981 (Remove the `BoundConstness::NotConst` variant) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
93742bd782
@ -6,13 +6,10 @@
|
|||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::traits::BuiltinImplSource;
|
|
||||||
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
|
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
|
||||||
use rustc_middle::{bug, mir};
|
use rustc_middle::{bug, mir};
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
||||||
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
|
use tracing::instrument;
|
||||||
};
|
|
||||||
use tracing::{instrument, trace};
|
|
||||||
|
|
||||||
use super::ConstCx;
|
use super::ConstCx;
|
||||||
|
|
||||||
@ -195,50 +192,8 @@ fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(effects): If `destruct` is not a `const_trait`,
|
// FIXME(effects): Reimplement const drop checking.
|
||||||
// or effects are disabled in this crate, then give up.
|
NeedsDrop::in_any_value_of_ty(cx, ty)
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_adt_inherently<'tcx>(
|
fn in_adt_inherently<'tcx>(
|
||||||
|
@ -51,7 +51,7 @@ pub(crate) fn push_trait_bound(
|
|||||||
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
polarity: ty::PredicatePolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
constness: ty::BoundConstness,
|
constness: Option<ty::BoundConstness>,
|
||||||
predicate_filter: PredicateFilter,
|
predicate_filter: PredicateFilter,
|
||||||
) {
|
) {
|
||||||
let clause = (
|
let clause = (
|
||||||
@ -88,19 +88,20 @@ pub(crate) fn push_trait_bound(
|
|||||||
// associated type of `<T as Tr>` and make sure that the effect is compatible.
|
// 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) {
|
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
|
||||||
// FIXME(effects): revisit the correctness of this
|
// 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
|
// 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()) {
|
if !tcx.is_const_trait(bound_trait_ref.def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcx.consts.true_
|
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:
|
// we are in a trait, where `bound_trait_ref` could be:
|
||||||
// (1) a super trait `trait Foo: ~const Bar`.
|
// (1) a super trait `trait Foo: ~const Bar`.
|
||||||
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
|
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
|
||||||
@ -138,7 +139,7 @@ pub(crate) fn push_trait_bound(
|
|||||||
return;
|
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.
|
// this is a where clause on an impl header.
|
||||||
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
// 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 {
|
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||||
@ -172,12 +173,12 @@ pub(crate) fn push_trait_bound(
|
|||||||
//
|
//
|
||||||
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
|
// 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.
|
// 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
|
// FIXME(effects): implement this
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// probably illegal in this position.
|
// probably illegal in this position.
|
||||||
(_, ty::BoundConstness::ConstIfConst) => {
|
(_, Some(ty::BoundConstness::ConstIfConst)) => {
|
||||||
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
|
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,16 +171,15 @@ pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<
|
|||||||
hir::GenericBound::Trait(poly_trait_ref) => {
|
hir::GenericBound::Trait(poly_trait_ref) => {
|
||||||
let (constness, polarity) = match poly_trait_ref.modifiers {
|
let (constness, polarity) = match poly_trait_ref.modifiers {
|
||||||
hir::TraitBoundModifier::Const => {
|
hir::TraitBoundModifier::Const => {
|
||||||
(ty::BoundConstness::Const, ty::PredicatePolarity::Positive)
|
(Some(ty::BoundConstness::Const), ty::PredicatePolarity::Positive)
|
||||||
}
|
|
||||||
hir::TraitBoundModifier::MaybeConst => {
|
|
||||||
(ty::BoundConstness::ConstIfConst, ty::PredicatePolarity::Positive)
|
|
||||||
}
|
|
||||||
hir::TraitBoundModifier::None => {
|
|
||||||
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Positive)
|
|
||||||
}
|
}
|
||||||
|
hir::TraitBoundModifier::MaybeConst => (
|
||||||
|
Some(ty::BoundConstness::ConstIfConst),
|
||||||
|
ty::PredicatePolarity::Positive,
|
||||||
|
),
|
||||||
|
hir::TraitBoundModifier::None => (None, ty::PredicatePolarity::Positive),
|
||||||
hir::TraitBoundModifier::Negative => {
|
hir::TraitBoundModifier::Negative => {
|
||||||
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Negative)
|
(None, ty::PredicatePolarity::Negative)
|
||||||
}
|
}
|
||||||
hir::TraitBoundModifier::Maybe => continue,
|
hir::TraitBoundModifier::Maybe => continue,
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,7 @@ pub(super) fn lower_trait_object_ty(
|
|||||||
} = self.lower_poly_trait_ref(
|
} = self.lower_poly_trait_ref(
|
||||||
&trait_bound.trait_ref,
|
&trait_bound.trait_ref,
|
||||||
trait_bound.span,
|
trait_bound.span,
|
||||||
ty::BoundConstness::NotConst,
|
None,
|
||||||
ty::PredicatePolarity::Positive,
|
ty::PredicatePolarity::Positive,
|
||||||
dummy_self,
|
dummy_self,
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
|
@ -652,7 +652,7 @@ pub(crate) fn lower_poly_trait_ref(
|
|||||||
&self,
|
&self,
|
||||||
trait_ref: &hir::TraitRef<'tcx>,
|
trait_ref: &hir::TraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
constness: ty::BoundConstness,
|
constness: Option<ty::BoundConstness>,
|
||||||
polarity: ty::PredicatePolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
bounds: &mut Bounds<'tcx>,
|
bounds: &mut Bounds<'tcx>,
|
||||||
@ -675,7 +675,7 @@ pub(crate) fn lower_poly_trait_ref(
|
|||||||
Some(self_ty),
|
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.tcx().is_const_trait(trait_def_id)
|
||||||
{
|
{
|
||||||
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
||||||
|
@ -537,40 +537,7 @@ fn confirm_builtin_call(
|
|||||||
//
|
//
|
||||||
// This check is here because there is currently no way to express a trait bound for `FnDef` types only.
|
// 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() {
|
if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
|
||||||
let fn_once_def_id =
|
if idx == 0 && !self.tcx.is_const_fn_raw(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) {
|
|
||||||
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
|
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1097,6 +1097,7 @@ enum SuggestionText {
|
|||||||
let mut only_extras_so_far = errors
|
let mut only_extras_so_far = errors
|
||||||
.peek()
|
.peek()
|
||||||
.is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
|
.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![];
|
let mut suggestions = vec![];
|
||||||
while let Some(error) = errors.next() {
|
while let Some(error) = errors.next() {
|
||||||
only_extras_so_far &= matches!(error, Error::Extra(_));
|
only_extras_so_far &= matches!(error, Error::Extra(_));
|
||||||
@ -1165,11 +1166,29 @@ enum SuggestionText {
|
|||||||
// fn f() {}
|
// fn f() {}
|
||||||
// - f(0, 1,)
|
// - f(0, 1,)
|
||||||
// + f()
|
// + f()
|
||||||
|
let trim_next_comma = match errors.peek() {
|
||||||
|
Some(Error::Extra(provided_idx))
|
||||||
if only_extras_so_far
|
if only_extras_so_far
|
||||||
&& !errors
|
&& provided_idx.index() > arg_idx.index() + 1 =>
|
||||||
.peek()
|
// If the next Error::Extra ("next") doesn't next to current ("current"),
|
||||||
.is_some_and(|next_error| matches!(next_error, Error::Extra(_)))
|
// 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
|
let next = provided_arg_tys
|
||||||
.get(arg_idx + 1)
|
.get(arg_idx + 1)
|
||||||
.map(|&(_, sp)| sp)
|
.map(|&(_, sp)| sp)
|
||||||
@ -1192,6 +1211,7 @@ enum SuggestionText {
|
|||||||
SuggestionText::Remove(_) => SuggestionText::Remove(true),
|
SuggestionText::Remove(_) => SuggestionText::Remove(true),
|
||||||
_ => SuggestionText::DidYouMean,
|
_ => SuggestionText::DidYouMean,
|
||||||
};
|
};
|
||||||
|
prev_extra_idx = Some(arg_idx.index())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Error::Missing(expected_idx) => {
|
Error::Missing(expected_idx) => {
|
||||||
|
@ -161,9 +161,7 @@ pub enum SelectionCandidate<'tcx> {
|
|||||||
|
|
||||||
/// Implementation of a `Fn`-family trait by one of the anonymous
|
/// Implementation of a `Fn`-family trait by one of the anonymous
|
||||||
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
|
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
|
||||||
FnPointerCandidate {
|
FnPointerCandidate,
|
||||||
fn_host_effect: ty::Const<'tcx>,
|
|
||||||
},
|
|
||||||
|
|
||||||
TraitAliasCandidate,
|
TraitAliasCandidate,
|
||||||
|
|
||||||
@ -180,9 +178,6 @@ pub enum SelectionCandidate<'tcx> {
|
|||||||
BuiltinObjectCandidate,
|
BuiltinObjectCandidate,
|
||||||
|
|
||||||
BuiltinUnsizeCandidate,
|
BuiltinUnsizeCandidate,
|
||||||
|
|
||||||
/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
|
|
||||||
ConstDestructCandidate(Option<DefId>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of trait evaluation. The order is important
|
/// The result of trait evaluation. The order is important
|
||||||
|
@ -1956,7 +1956,6 @@ fn pretty_print_bound_constness(
|
|||||||
define_scoped_cx!(self);
|
define_scoped_cx!(self);
|
||||||
|
|
||||||
match constness {
|
match constness {
|
||||||
ty::BoundConstness::NotConst => {}
|
|
||||||
ty::BoundConstness::Const => {
|
ty::BoundConstness::Const => {
|
||||||
p!("const ");
|
p!("const ");
|
||||||
}
|
}
|
||||||
@ -2948,7 +2947,10 @@ fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
#[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> {
|
impl<'tcx> fmt::Debug for TraitPredPrintWithBoundConstness<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
@ -2966,7 +2968,7 @@ fn print_modifiers_and_trait_path(
|
|||||||
|
|
||||||
fn print_with_bound_constness(
|
fn print_with_bound_constness(
|
||||||
self,
|
self,
|
||||||
constness: ty::BoundConstness,
|
constness: Option<ty::BoundConstness>,
|
||||||
) -> ty::Binder<'tcx, TraitPredPrintWithBoundConstness<'tcx>> {
|
) -> ty::Binder<'tcx, TraitPredPrintWithBoundConstness<'tcx>> {
|
||||||
self.map_bound(|trait_pred| TraitPredPrintWithBoundConstness(trait_pred, constness))
|
self.map_bound(|trait_pred| TraitPredPrintWithBoundConstness(trait_pred, constness))
|
||||||
}
|
}
|
||||||
@ -3206,7 +3208,9 @@ macro_rules! define_print_and_forward_display {
|
|||||||
|
|
||||||
TraitPredPrintWithBoundConstness<'tcx> {
|
TraitPredPrintWithBoundConstness<'tcx> {
|
||||||
p!(print(self.0.trait_ref.self_ty()), ": ");
|
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 {
|
if let ty::PredicatePolarity::Negative = self.0.polarity {
|
||||||
p!("!");
|
p!("!");
|
||||||
}
|
}
|
||||||
|
@ -907,24 +907,6 @@ pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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`.
|
/// Expand any [weak alias types][weak] contained within the given `value`.
|
||||||
///
|
///
|
||||||
/// This should be used over other normalization routines in situations where
|
/// This should be used over other normalization routines in situations where
|
||||||
|
@ -454,12 +454,7 @@ fn non_scalar_compare(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
|
let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
|
||||||
let method = trait_method(
|
let method = trait_method(self.tcx, eq_def_id, sym::eq, [compare_ty, compare_ty]);
|
||||||
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 bool_ty = self.tcx.types.bool;
|
let bool_ty = self.tcx.types.bool;
|
||||||
let eq_result = self.temp(bool_ty, source_info.span);
|
let eq_result = self.temp(bool_ty, source_info.span);
|
||||||
|
@ -43,7 +43,6 @@ pub(super) fn const_to_pat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ConstToPat<'tcx> {
|
struct ConstToPat<'tcx> {
|
||||||
id: hir::HirId,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
@ -62,7 +61,6 @@ fn new(
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
trace!(?pat_ctxt.typeck_results.hir_owner);
|
trace!(?pat_ctxt.typeck_results.hir_owner);
|
||||||
ConstToPat {
|
ConstToPat {
|
||||||
id,
|
|
||||||
span,
|
span,
|
||||||
infcx,
|
infcx,
|
||||||
param_env: pat_ctxt.param_env,
|
param_env: pat_ctxt.param_env,
|
||||||
@ -149,15 +147,7 @@ fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
|||||||
tcx,
|
tcx,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::TraitRef::new_from_args(
|
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
|
||||||
tcx,
|
|
||||||
partial_eq_trait_id,
|
|
||||||
tcx.with_opt_host_effect_param(
|
|
||||||
tcx.hir().enclosing_body_owner(self.id),
|
|
||||||
partial_eq_trait_id,
|
|
||||||
[ty, ty],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
|
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
|
||||||
|
@ -290,7 +290,7 @@ pub fn report_selection_error(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Drop)
|
if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Drop)
|
||||||
&& matches!(predicate_constness, ty::BoundConstness::ConstIfConst | ty::BoundConstness::Const)
|
&& matches!(predicate_constness, Some(ty::BoundConstness::ConstIfConst | ty::BoundConstness::Const))
|
||||||
{
|
{
|
||||||
err.note("`~const Drop` was renamed to `~const Destruct`");
|
err.note("`~const Drop` was renamed to `~const Destruct`");
|
||||||
err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
|
err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
|
||||||
@ -2192,7 +2192,7 @@ fn get_standard_error_message(
|
|||||||
&self,
|
&self,
|
||||||
trait_predicate: ty::PolyTraitPredicate<'tcx>,
|
trait_predicate: ty::PolyTraitPredicate<'tcx>,
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
predicate_constness: ty::BoundConstness,
|
predicate_constness: Option<ty::BoundConstness>,
|
||||||
append_const_msg: Option<AppendConstMessage>,
|
append_const_msg: Option<AppendConstMessage>,
|
||||||
post_message: String,
|
post_message: String,
|
||||||
) -> String {
|
) -> String {
|
||||||
@ -2200,19 +2200,21 @@ fn get_standard_error_message(
|
|||||||
.and_then(|cannot_do_this| {
|
.and_then(|cannot_do_this| {
|
||||||
match (predicate_constness, append_const_msg) {
|
match (predicate_constness, append_const_msg) {
|
||||||
// do nothing if predicate is not const
|
// do nothing if predicate is not const
|
||||||
(ty::BoundConstness::NotConst, _) => Some(cannot_do_this),
|
(None, _) => Some(cannot_do_this),
|
||||||
// suggested using default post message
|
// suggested using default post message
|
||||||
(
|
(
|
||||||
ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst,
|
Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst),
|
||||||
Some(AppendConstMessage::Default),
|
Some(AppendConstMessage::Default),
|
||||||
) => Some(format!("{cannot_do_this} in const contexts")),
|
) => Some(format!("{cannot_do_this} in const contexts")),
|
||||||
// overridden post message
|
// overridden post message
|
||||||
(
|
(
|
||||||
ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst,
|
Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst),
|
||||||
Some(AppendConstMessage::Custom(custom_msg, _)),
|
Some(AppendConstMessage::Custom(custom_msg, _)),
|
||||||
) => Some(format!("{cannot_do_this}{custom_msg}")),
|
) => Some(format!("{cannot_do_this}{custom_msg}")),
|
||||||
// fallback to generic message
|
// fallback to generic message
|
||||||
(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst, None) => None,
|
(Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst), None) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
@ -2377,26 +2379,27 @@ fn get_effects_trait_pred_override(
|
|||||||
p: ty::PolyTraitPredicate<'tcx>,
|
p: ty::PolyTraitPredicate<'tcx>,
|
||||||
leaf: ty::PolyTraitPredicate<'tcx>,
|
leaf: ty::PolyTraitPredicate<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, ty::BoundConstness) {
|
) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, Option<ty::BoundConstness>)
|
||||||
|
{
|
||||||
let trait_ref = p.to_poly_trait_ref();
|
let trait_ref = p.to_poly_trait_ref();
|
||||||
if !self.tcx.is_lang_item(trait_ref.def_id(), LangItem::EffectsCompat) {
|
if !self.tcx.is_lang_item(trait_ref.def_id(), LangItem::EffectsCompat) {
|
||||||
return (p, leaf, ty::BoundConstness::NotConst);
|
return (p, leaf, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(ty::Alias(ty::AliasTyKind::Projection, projection)) =
|
let Some(ty::Alias(ty::AliasTyKind::Projection, projection)) =
|
||||||
trait_ref.self_ty().no_bound_vars().map(Ty::kind)
|
trait_ref.self_ty().no_bound_vars().map(Ty::kind)
|
||||||
else {
|
else {
|
||||||
return (p, leaf, ty::BoundConstness::NotConst);
|
return (p, leaf, None);
|
||||||
};
|
};
|
||||||
|
|
||||||
let constness = trait_ref.skip_binder().args.const_at(1);
|
let constness = trait_ref.skip_binder().args.const_at(1);
|
||||||
|
|
||||||
let constness = if constness == self.tcx.consts.true_ || constness.is_ct_infer() {
|
let constness = if constness == self.tcx.consts.true_ || constness.is_ct_infer() {
|
||||||
ty::BoundConstness::NotConst
|
None
|
||||||
} else if constness == self.tcx.consts.false_ {
|
} else if constness == self.tcx.consts.false_ {
|
||||||
ty::BoundConstness::Const
|
Some(ty::BoundConstness::Const)
|
||||||
} else if matches!(constness.kind(), ty::ConstKind::Param(_)) {
|
} else if matches!(constness.kind(), ty::ConstKind::Param(_)) {
|
||||||
ty::BoundConstness::ConstIfConst
|
Some(ty::BoundConstness::ConstIfConst)
|
||||||
} else {
|
} else {
|
||||||
self.dcx().span_bug(span, format!("Unknown constness argument: {constness:?}"));
|
self.dcx().span_bug(span, format!("Unknown constness argument: {constness:?}"));
|
||||||
};
|
};
|
||||||
|
@ -3701,12 +3701,10 @@ pub fn suggest_derive(
|
|||||||
}
|
}
|
||||||
_ => 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).chain(host),
|
[field_ty].into_iter().chain(trait_args),
|
||||||
),
|
),
|
||||||
..*tr
|
..*tr
|
||||||
});
|
});
|
||||||
|
@ -1642,22 +1642,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
|||||||
sig,
|
sig,
|
||||||
);
|
);
|
||||||
|
|
||||||
let host_effect_param = match *fn_type.kind() {
|
confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
|
||||||
ty::FnDef(def_id, args) => tcx
|
|
||||||
.generics_of(def_id)
|
|
||||||
.host_effect_index
|
|
||||||
.map_or(tcx.consts.true_, |idx| args.const_at(idx)),
|
|
||||||
ty::FnPtr(..) => tcx.consts.true_,
|
|
||||||
_ => unreachable!("only expected FnPtr or FnDef in `confirm_fn_pointer_candidate`"),
|
|
||||||
};
|
|
||||||
|
|
||||||
confirm_callable_candidate(
|
|
||||||
selcx,
|
|
||||||
obligation,
|
|
||||||
sig,
|
|
||||||
util::TupleArgumentsFlag::Yes,
|
|
||||||
host_effect_param,
|
|
||||||
)
|
|
||||||
.with_addl_obligations(nested)
|
.with_addl_obligations(nested)
|
||||||
.with_addl_obligations(obligations)
|
.with_addl_obligations(obligations)
|
||||||
}
|
}
|
||||||
@ -1739,14 +1724,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
|
|||||||
|
|
||||||
debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
|
debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
|
||||||
|
|
||||||
confirm_callable_candidate(
|
confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
|
||||||
selcx,
|
|
||||||
obligation,
|
|
||||||
closure_sig,
|
|
||||||
util::TupleArgumentsFlag::No,
|
|
||||||
// FIXME(effects): This doesn't handle const closures correctly!
|
|
||||||
selcx.tcx().consts.true_,
|
|
||||||
)
|
|
||||||
.with_addl_obligations(nested)
|
.with_addl_obligations(nested)
|
||||||
.with_addl_obligations(obligations)
|
.with_addl_obligations(obligations)
|
||||||
}
|
}
|
||||||
@ -1756,7 +1734,6 @@ fn confirm_callable_candidate<'cx, 'tcx>(
|
|||||||
obligation: &ProjectionTermObligation<'tcx>,
|
obligation: &ProjectionTermObligation<'tcx>,
|
||||||
fn_sig: ty::PolyFnSig<'tcx>,
|
fn_sig: ty::PolyFnSig<'tcx>,
|
||||||
flag: util::TupleArgumentsFlag,
|
flag: util::TupleArgumentsFlag,
|
||||||
fn_host_effect: ty::Const<'tcx>,
|
|
||||||
) -> Progress<'tcx> {
|
) -> Progress<'tcx> {
|
||||||
let tcx = selcx.tcx();
|
let tcx = selcx.tcx();
|
||||||
|
|
||||||
@ -1771,7 +1748,6 @@ fn confirm_callable_candidate<'cx, 'tcx>(
|
|||||||
obligation.predicate.self_ty(),
|
obligation.predicate.self_ty(),
|
||||||
fn_sig,
|
fn_sig,
|
||||||
flag,
|
flag,
|
||||||
fn_host_effect,
|
|
||||||
)
|
)
|
||||||
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
|
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
|
||||||
projection_term: ty::AliasTerm::new_from_args(tcx, fn_once_output_def_id, trait_ref.args),
|
projection_term: ty::AliasTerm::new_from_args(tcx, fn_once_output_def_id, trait_ref.args),
|
||||||
|
@ -543,23 +543,16 @@ fn assemble_fn_pointer_candidates(
|
|||||||
// Provide an impl, but only for suitable `fn` pointers.
|
// Provide an impl, but only for suitable `fn` pointers.
|
||||||
ty::FnPtr(sig_tys, hdr) => {
|
ty::FnPtr(sig_tys, hdr) => {
|
||||||
if sig_tys.with(hdr).is_fn_trait_compatible() {
|
if sig_tys.with(hdr).is_fn_trait_compatible() {
|
||||||
candidates
|
candidates.vec.push(FnPointerCandidate);
|
||||||
.vec
|
|
||||||
.push(FnPointerCandidate { fn_host_effect: self.tcx().consts.true_ });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
||||||
ty::FnDef(def_id, args) => {
|
ty::FnDef(def_id, _args) => {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
||||||
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
{
|
{
|
||||||
candidates.vec.push(FnPointerCandidate {
|
candidates.vec.push(FnPointerCandidate);
|
||||||
fn_host_effect: tcx
|
|
||||||
.generics_of(def_id)
|
|
||||||
.host_effect_index
|
|
||||||
.map_or(tcx.consts.true_, |idx| args.const_at(idx)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -1170,103 +1163,12 @@ fn assemble_builtin_bound_candidates(
|
|||||||
|
|
||||||
fn assemble_const_destruct_candidates(
|
fn assemble_const_destruct_candidates(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
_obligation: &PolyTraitObligation<'tcx>,
|
||||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||||
) {
|
) {
|
||||||
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
|
// FIXME(effects): Destruct is not const yet, and it is implemented
|
||||||
// to check anything. We'll short-circuit checking any obligations in confirmation, too.
|
// by all types today in non-const setting.
|
||||||
let Some(host_effect_index) =
|
|
||||||
self.tcx().generics_of(obligation.predicate.def_id()).host_effect_index
|
|
||||||
else {
|
|
||||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||||
return;
|
|
||||||
};
|
|
||||||
// If the obligation has `host = true`, then the obligation is non-const and it's always
|
|
||||||
// trivially implemented.
|
|
||||||
if obligation.predicate.skip_binder().trait_ref.args.const_at(host_effect_index)
|
|
||||||
== self.tcx().consts.true_
|
|
||||||
{
|
|
||||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
|
|
||||||
match self_ty.kind() {
|
|
||||||
ty::Alias(..)
|
|
||||||
| ty::Dynamic(..)
|
|
||||||
| ty::Error(_)
|
|
||||||
| ty::Bound(..)
|
|
||||||
| ty::Param(_)
|
|
||||||
| ty::Placeholder(_) => {
|
|
||||||
// We don't know if these are `~const Destruct`, at least
|
|
||||||
// not structurally... so don't push a candidate.
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Bool
|
|
||||||
| ty::Char
|
|
||||||
| ty::Int(_)
|
|
||||||
| ty::Uint(_)
|
|
||||||
| ty::Float(_)
|
|
||||||
| ty::Infer(ty::IntVar(_))
|
|
||||||
| ty::Infer(ty::FloatVar(_))
|
|
||||||
| ty::Str
|
|
||||||
| ty::RawPtr(_, _)
|
|
||||||
| ty::Ref(..)
|
|
||||||
| ty::FnDef(..)
|
|
||||||
| ty::FnPtr(..)
|
|
||||||
| ty::Never
|
|
||||||
| ty::Foreign(_)
|
|
||||||
| ty::Array(..)
|
|
||||||
| ty::Pat(..)
|
|
||||||
| ty::Slice(_)
|
|
||||||
| ty::Closure(..)
|
|
||||||
| ty::CoroutineClosure(..)
|
|
||||||
| ty::Coroutine(..)
|
|
||||||
| ty::Tuple(_)
|
|
||||||
| ty::CoroutineWitness(..) => {
|
|
||||||
// These are built-in, and cannot have a custom `impl const Destruct`.
|
|
||||||
candidates.vec.push(ConstDestructCandidate(None));
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Adt(..) => {
|
|
||||||
let mut relevant_impl = None;
|
|
||||||
self.tcx().for_each_relevant_impl(
|
|
||||||
self.tcx().require_lang_item(LangItem::Drop, None),
|
|
||||||
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
|
||||||
|impl_def_id| {
|
|
||||||
if let Some(old_impl_def_id) = relevant_impl {
|
|
||||||
self.tcx()
|
|
||||||
.dcx()
|
|
||||||
.struct_span_err(
|
|
||||||
self.tcx().def_span(impl_def_id),
|
|
||||||
"multiple drop impls found",
|
|
||||||
)
|
|
||||||
.with_span_note(
|
|
||||||
self.tcx().def_span(old_impl_def_id),
|
|
||||||
"other impl here",
|
|
||||||
)
|
|
||||||
.delay_as_bug();
|
|
||||||
}
|
|
||||||
|
|
||||||
relevant_impl = Some(impl_def_id);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(impl_def_id) = relevant_impl {
|
|
||||||
// Check that `impl Drop` is actually const, if there is a custom impl
|
|
||||||
if self.tcx().constness(impl_def_id) == hir::Constness::Const {
|
|
||||||
candidates.vec.push(ConstDestructCandidate(Some(impl_def_id)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Otherwise check the ADT like a built-in type (structurally)
|
|
||||||
candidates.vec.push(ConstDestructCandidate(None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Infer(_) => {
|
|
||||||
candidates.ambiguous = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_candidate_for_tuple(
|
fn assemble_candidate_for_tuple(
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
|
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
|
||||||
use crate::traits::util::{self, closure_trait_ref_and_return_type};
|
use crate::traits::util::{self, closure_trait_ref_and_return_type};
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
ImplDerivedCause, ImplSource, ImplSourceUserDefinedData, Normalized, Obligation,
|
ImplSource, ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
|
||||||
ObligationCause, PolyTraitObligation, PredicateObligation, Selection, SelectionError,
|
PolyTraitObligation, PredicateObligation, Selection, SelectionError, SignatureMismatch,
|
||||||
SignatureMismatch, TraitDynIncompatible, TraitObligation, Unimplemented,
|
TraitDynIncompatible, TraitObligation, Unimplemented,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
@ -109,8 +109,8 @@ pub(super) fn confirm_candidate(
|
|||||||
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_iterator)
|
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_iterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
FnPointerCandidate { fn_host_effect } => {
|
FnPointerCandidate => {
|
||||||
let data = self.confirm_fn_pointer_candidate(obligation, fn_host_effect)?;
|
let data = self.confirm_fn_pointer_candidate(obligation)?;
|
||||||
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,11 +131,6 @@ pub(super) fn confirm_candidate(
|
|||||||
TraitUpcastingUnsizeCandidate(idx) => {
|
TraitUpcastingUnsizeCandidate(idx) => {
|
||||||
self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
|
self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstDestructCandidate(def_id) => {
|
|
||||||
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
|
|
||||||
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The obligations returned by confirmation are recursively evaluated
|
// The obligations returned by confirmation are recursively evaluated
|
||||||
@ -711,7 +706,6 @@ fn confirm_object_candidate(
|
|||||||
fn confirm_fn_pointer_candidate(
|
fn confirm_fn_pointer_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
obligation: &PolyTraitObligation<'tcx>,
|
||||||
fn_host_effect: ty::Const<'tcx>,
|
|
||||||
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
|
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
|
||||||
debug!(?obligation, "confirm_fn_pointer_candidate");
|
debug!(?obligation, "confirm_fn_pointer_candidate");
|
||||||
let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||||
@ -725,7 +719,6 @@ fn confirm_fn_pointer_candidate(
|
|||||||
self_ty,
|
self_ty,
|
||||||
sig,
|
sig,
|
||||||
util::TupleArgumentsFlag::Yes,
|
util::TupleArgumentsFlag::Yes,
|
||||||
fn_host_effect,
|
|
||||||
)
|
)
|
||||||
.map_bound(|(trait_ref, _)| trait_ref);
|
.map_bound(|(trait_ref, _)| trait_ref);
|
||||||
|
|
||||||
@ -907,11 +900,9 @@ fn confirm_closure_candidate(
|
|||||||
let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
|
let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
|
||||||
|
|
||||||
let trait_ref = match *self_ty.kind() {
|
let trait_ref = match *self_ty.kind() {
|
||||||
ty::Closure(..) => self.closure_trait_ref_unnormalized(
|
ty::Closure(..) => {
|
||||||
self_ty,
|
self.closure_trait_ref_unnormalized(self_ty, obligation.predicate.def_id())
|
||||||
obligation.predicate.def_id(),
|
}
|
||||||
self.tcx().consts.true_,
|
|
||||||
),
|
|
||||||
ty::CoroutineClosure(_, args) => {
|
ty::CoroutineClosure(_, args) => {
|
||||||
args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
|
args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
|
||||||
ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
|
ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
|
||||||
@ -1344,170 +1335,4 @@ fn confirm_builtin_unsize_candidate(
|
|||||||
_ => bug!("source: {source}, target: {target}"),
|
_ => bug!("source: {source}, target: {target}"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_const_destruct_candidate(
|
|
||||||
&mut self,
|
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
|
||||||
impl_def_id: Option<DefId>,
|
|
||||||
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
|
|
||||||
let Some(host_effect_index) =
|
|
||||||
self.tcx().generics_of(obligation.predicate.def_id()).host_effect_index
|
|
||||||
else {
|
|
||||||
bug!()
|
|
||||||
};
|
|
||||||
let host_effect_param: ty::GenericArg<'tcx> =
|
|
||||||
obligation.predicate.skip_binder().trait_ref.args.const_at(host_effect_index).into();
|
|
||||||
|
|
||||||
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
|
|
||||||
|
|
||||||
let tcx = self.tcx();
|
|
||||||
let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
|
|
||||||
|
|
||||||
let mut nested = PredicateObligations::new();
|
|
||||||
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
|
|
||||||
|
|
||||||
// If we have a custom `impl const Drop`, then
|
|
||||||
// first check it like a regular impl candidate.
|
|
||||||
// This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand.
|
|
||||||
if let Some(impl_def_id) = impl_def_id {
|
|
||||||
let mut new_obligation = obligation.clone();
|
|
||||||
new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| {
|
|
||||||
trait_pred.trait_ref.def_id = drop_trait;
|
|
||||||
trait_pred
|
|
||||||
});
|
|
||||||
let args = self.rematch_impl(impl_def_id, &new_obligation);
|
|
||||||
debug!(?args, "impl args");
|
|
||||||
|
|
||||||
let cause = obligation.derived_cause(|derived| {
|
|
||||||
ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
|
|
||||||
derived,
|
|
||||||
impl_or_alias_def_id: impl_def_id,
|
|
||||||
impl_def_predicate_index: None,
|
|
||||||
span: obligation.cause.span,
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
let obligations = ensure_sufficient_stack(|| {
|
|
||||||
self.vtable_impl(
|
|
||||||
impl_def_id,
|
|
||||||
args,
|
|
||||||
&cause,
|
|
||||||
new_obligation.recursion_depth + 1,
|
|
||||||
new_obligation.param_env,
|
|
||||||
obligation.predicate,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
nested.extend(obligations.nested);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to confirm the ADT's fields if we have an ADT
|
|
||||||
let mut stack = match *self_ty.skip_binder().kind() {
|
|
||||||
ty::Adt(def, args) => def.all_fields().map(|f| f.ty(tcx, args)).collect(),
|
|
||||||
_ => vec![self_ty.skip_binder()],
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(nested_ty) = stack.pop() {
|
|
||||||
match *nested_ty.kind() {
|
|
||||||
// We know these types are trivially drop
|
|
||||||
ty::Bool
|
|
||||||
| ty::Char
|
|
||||||
| ty::Int(_)
|
|
||||||
| ty::Uint(_)
|
|
||||||
| ty::Float(_)
|
|
||||||
| ty::Infer(ty::IntVar(_))
|
|
||||||
| ty::Infer(ty::FloatVar(_))
|
|
||||||
| ty::Str
|
|
||||||
| ty::RawPtr(_, _)
|
|
||||||
| ty::Ref(..)
|
|
||||||
| ty::FnDef(..)
|
|
||||||
| ty::FnPtr(..)
|
|
||||||
| ty::Never
|
|
||||||
| ty::Foreign(_) => {}
|
|
||||||
|
|
||||||
// `ManuallyDrop` is trivially drop
|
|
||||||
ty::Adt(def, _) if def.is_manually_drop() => {}
|
|
||||||
|
|
||||||
// These types are built-in, so we can fast-track by registering
|
|
||||||
// nested predicates for their constituent type(s)
|
|
||||||
ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => {
|
|
||||||
stack.push(ty);
|
|
||||||
}
|
|
||||||
ty::Tuple(tys) => {
|
|
||||||
stack.extend(tys.iter());
|
|
||||||
}
|
|
||||||
ty::Closure(_, args) => {
|
|
||||||
stack.push(args.as_closure().tupled_upvars_ty());
|
|
||||||
}
|
|
||||||
ty::Coroutine(_, args) => {
|
|
||||||
let coroutine = args.as_coroutine();
|
|
||||||
stack.extend([coroutine.tupled_upvars_ty(), coroutine.witness()]);
|
|
||||||
}
|
|
||||||
ty::CoroutineWitness(def_id, args) => {
|
|
||||||
let tcx = self.tcx();
|
|
||||||
stack.extend(tcx.bound_coroutine_hidden_types(def_id).map(|bty| {
|
|
||||||
self.infcx.enter_forall_and_leak_universe(bty.instantiate(tcx, args))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a projection type, make sure to normalize it so we replace it
|
|
||||||
// with a fresh infer variable
|
|
||||||
ty::Alias(ty::Projection | ty::Inherent, ..) => {
|
|
||||||
let predicate = normalize_with_depth_to(
|
|
||||||
self,
|
|
||||||
obligation.param_env,
|
|
||||||
cause.clone(),
|
|
||||||
obligation.recursion_depth + 1,
|
|
||||||
self_ty.rebind(ty::TraitPredicate {
|
|
||||||
trait_ref: ty::TraitRef::new(
|
|
||||||
self.tcx(),
|
|
||||||
self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
|
|
||||||
[nested_ty.into(), host_effect_param],
|
|
||||||
),
|
|
||||||
polarity: ty::PredicatePolarity::Positive,
|
|
||||||
}),
|
|
||||||
&mut nested,
|
|
||||||
);
|
|
||||||
|
|
||||||
nested.push(Obligation::with_depth(
|
|
||||||
tcx,
|
|
||||||
cause.clone(),
|
|
||||||
obligation.recursion_depth + 1,
|
|
||||||
obligation.param_env,
|
|
||||||
predicate,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have any other type (e.g. an ADT), just register a nested obligation
|
|
||||||
// since it's either not `const Drop` (and we raise an error during selection),
|
|
||||||
// or it's an ADT (and we need to check for a custom impl during selection)
|
|
||||||
ty::Error(_)
|
|
||||||
| ty::Dynamic(..)
|
|
||||||
| ty::CoroutineClosure(..)
|
|
||||||
| ty::Param(_)
|
|
||||||
| ty::Bound(..)
|
|
||||||
| ty::Adt(..)
|
|
||||||
| ty::Alias(ty::Opaque | ty::Weak, _)
|
|
||||||
| ty::Infer(_)
|
|
||||||
| ty::Placeholder(_) => {
|
|
||||||
let predicate = self_ty.rebind(ty::TraitPredicate {
|
|
||||||
trait_ref: ty::TraitRef::new(
|
|
||||||
self.tcx(),
|
|
||||||
self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
|
|
||||||
[nested_ty.into(), host_effect_param],
|
|
||||||
),
|
|
||||||
polarity: ty::PredicatePolarity::Positive,
|
|
||||||
});
|
|
||||||
|
|
||||||
nested.push(Obligation::with_depth(
|
|
||||||
tcx,
|
|
||||||
cause.clone(),
|
|
||||||
obligation.recursion_depth + 1,
|
|
||||||
obligation.param_env,
|
|
||||||
predicate,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(nested)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1831,12 +1831,8 @@ fn candidate_should_be_dropped_in_favor_of(
|
|||||||
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
|
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
|
||||||
|
|
||||||
// (*)
|
// (*)
|
||||||
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
|
(BuiltinCandidate { has_nested: false }, _) => DropVictim::Yes,
|
||||||
DropVictim::Yes
|
(_, BuiltinCandidate { has_nested: false }) => DropVictim::No,
|
||||||
}
|
|
||||||
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
|
|
||||||
DropVictim::No
|
|
||||||
}
|
|
||||||
|
|
||||||
(ParamCandidate(other), ParamCandidate(victim)) => {
|
(ParamCandidate(other), ParamCandidate(victim)) => {
|
||||||
let same_except_bound_vars = other.skip_binder().trait_ref
|
let same_except_bound_vars = other.skip_binder().trait_ref
|
||||||
@ -1855,11 +1851,6 @@ fn candidate_should_be_dropped_in_favor_of(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop otherwise equivalent non-const fn pointer candidates
|
|
||||||
(FnPointerCandidate { .. }, FnPointerCandidate { fn_host_effect }) => {
|
|
||||||
DropVictim::drop_if(*fn_host_effect == self.tcx().consts.true_)
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
(
|
||||||
ParamCandidate(other_cand),
|
ParamCandidate(other_cand),
|
||||||
ImplCandidate(..)
|
ImplCandidate(..)
|
||||||
@ -2766,7 +2757,6 @@ fn closure_trait_ref_unnormalized(
|
|||||||
&mut self,
|
&mut self,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
fn_trait_def_id: DefId,
|
fn_trait_def_id: DefId,
|
||||||
fn_host_effect: ty::Const<'tcx>,
|
|
||||||
) -> ty::PolyTraitRef<'tcx> {
|
) -> ty::PolyTraitRef<'tcx> {
|
||||||
let ty::Closure(_, args) = *self_ty.kind() else {
|
let ty::Closure(_, args) = *self_ty.kind() else {
|
||||||
bug!("expected closure, found {self_ty}");
|
bug!("expected closure, found {self_ty}");
|
||||||
@ -2779,7 +2769,6 @@ fn closure_trait_ref_unnormalized(
|
|||||||
self_ty,
|
self_ty,
|
||||||
closure_sig,
|
closure_sig,
|
||||||
util::TupleArgumentsFlag::No,
|
util::TupleArgumentsFlag::No,
|
||||||
fn_host_effect,
|
|
||||||
)
|
)
|
||||||
.map_bound(|(trait_ref, _)| trait_ref)
|
.map_bound(|(trait_ref, _)| trait_ref)
|
||||||
}
|
}
|
||||||
|
@ -215,22 +215,13 @@ pub(crate) fn closure_trait_ref_and_return_type<'tcx>(
|
|||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
sig: ty::PolyFnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
tuple_arguments: TupleArgumentsFlag,
|
tuple_arguments: TupleArgumentsFlag,
|
||||||
fn_host_effect: ty::Const<'tcx>,
|
|
||||||
) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
|
) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
|
||||||
assert!(!self_ty.has_escaping_bound_vars());
|
assert!(!self_ty.has_escaping_bound_vars());
|
||||||
let arguments_tuple = match tuple_arguments {
|
let arguments_tuple = match tuple_arguments {
|
||||||
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
|
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
|
||||||
TupleArgumentsFlag::Yes => Ty::new_tup(tcx, sig.skip_binder().inputs()),
|
TupleArgumentsFlag::Yes => Ty::new_tup(tcx, sig.skip_binder().inputs()),
|
||||||
};
|
};
|
||||||
let trait_ref = if tcx.has_host_param(fn_trait_def_id) {
|
let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, arguments_tuple]);
|
||||||
ty::TraitRef::new(tcx, fn_trait_def_id, [
|
|
||||||
ty::GenericArg::from(self_ty),
|
|
||||||
ty::GenericArg::from(arguments_tuple),
|
|
||||||
ty::GenericArg::from(fn_host_effect),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, arguments_tuple])
|
|
||||||
};
|
|
||||||
sig.map_bound(|sig| (trait_ref, sig.output()))
|
sig.map_bound(|sig| (trait_ref, sig.output()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,9 +726,9 @@ pub struct CoercePredicate<I: Interner> {
|
|||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
|
||||||
pub enum BoundConstness {
|
pub enum BoundConstness {
|
||||||
/// `Type: Trait`
|
|
||||||
NotConst,
|
|
||||||
/// `Type: const Trait`
|
/// `Type: const Trait`
|
||||||
|
///
|
||||||
|
/// A bound is required to be unconditionally const, even in a runtime function.
|
||||||
Const,
|
Const,
|
||||||
/// `Type: ~const Trait`
|
/// `Type: ~const Trait`
|
||||||
///
|
///
|
||||||
@ -739,7 +739,6 @@ pub enum BoundConstness {
|
|||||||
impl BoundConstness {
|
impl BoundConstness {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::NotConst => "",
|
|
||||||
Self::Const => "const",
|
Self::Const => "const",
|
||||||
Self::ConstIfConst => "~const",
|
Self::ConstIfConst => "~const",
|
||||||
}
|
}
|
||||||
@ -749,7 +748,6 @@ pub fn as_str(self) -> &'static str {
|
|||||||
impl fmt::Display for BoundConstness {
|
impl fmt::Display for BoundConstness {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::NotConst => f.write_str("normal"),
|
|
||||||
Self::Const => f.write_str("const"),
|
Self::Const => f.write_str("const"),
|
||||||
Self::ConstIfConst => f.write_str("~const"),
|
Self::ConstIfConst => f.write_str("~const"),
|
||||||
}
|
}
|
||||||
|
1220
src/bootstrap/src/core/builder/cargo.rs
Normal file
1220
src/bootstrap/src/core/builder/cargo.rs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -637,7 +637,7 @@ fn test_with_no_doc_stage0() {
|
|||||||
assert_eq!(first(builder.cache.all::<test::Crate>()), &[test::Crate {
|
assert_eq!(first(builder.cache.all::<test::Crate>()), &[test::Crate {
|
||||||
compiler: Compiler { host, stage: 0 },
|
compiler: Compiler { host, stage: 0 },
|
||||||
target: host,
|
target: host,
|
||||||
mode: Mode::Std,
|
mode: crate::Mode::Std,
|
||||||
crates: vec!["std".to_owned()],
|
crates: vec!["std".to_owned()],
|
||||||
},]);
|
},]);
|
||||||
}
|
}
|
||||||
|
@ -190,15 +190,6 @@ 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`,
|
||||||
|
@ -274,23 +274,10 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
|
|||||||
.map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
|
.map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
|
||||||
.collect::<Vec<_>>();
|
.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_or(tcx.consts.true_, |def_id| {
|
|
||||||
tcx.expected_host_effect_param_for_body(def_id)
|
|
||||||
})))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let trait_ref = TraitRef::new(
|
let trait_ref = TraitRef::new(
|
||||||
tcx,
|
tcx,
|
||||||
trait_id,
|
trait_id,
|
||||||
[GenericArg::from(ty)].into_iter().chain(args).chain(effect_arg),
|
[GenericArg::from(ty)].into_iter().chain(args),
|
||||||
);
|
);
|
||||||
|
|
||||||
debug_assert_matches!(
|
debug_assert_matches!(
|
||||||
|
@ -15,6 +15,10 @@ fn main() {
|
|||||||
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
||||||
is(0, ""); // is(0, "")
|
is(0, ""); // is(0, "")
|
||||||
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
|
is(1, "");
|
||||||
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
|
is(1, "");
|
||||||
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
s(""); // s("")
|
s(""); // s("")
|
||||||
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,10 @@ fn main() {
|
|||||||
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
||||||
is(0, 1, 2, ""); // is(0, "")
|
is(0, 1, 2, ""); // is(0, "")
|
||||||
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
|
is((), 1, "", ());
|
||||||
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
|
is(1, (), "", ());
|
||||||
|
//~^ error: this function takes 2 arguments but 4 arguments were supplied
|
||||||
s(0, 1, ""); // s("")
|
s(0, 1, ""); // s("")
|
||||||
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
//~^ error: this function takes 1 argument but 3 arguments were supplied
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,47 @@ LL - is(0, 1, 2, ""); // is(0, "")
|
|||||||
LL + is(0, ""); // is(0, "")
|
LL + is(0, ""); // is(0, "")
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0061]: this function takes 1 argument but 3 arguments were supplied
|
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
|
||||||
--> $DIR/issue-109425.rs:18:5
|
--> $DIR/issue-109425.rs:18:5
|
||||||
|
|
|
|
||||||
|
LL | is((), 1, "", ());
|
||||||
|
| ^^ -- -- unexpected argument #4 of type `()`
|
||||||
|
| |
|
||||||
|
| unexpected argument #1 of type `()`
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/issue-109425.rs:5:4
|
||||||
|
|
|
||||||
|
LL | fn is(_: u32, _: &str) {}
|
||||||
|
| ^^ ------ -------
|
||||||
|
help: remove the extra arguments
|
||||||
|
|
|
||||||
|
LL - is((), 1, "", ());
|
||||||
|
LL + is(1, "");
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
|
||||||
|
--> $DIR/issue-109425.rs:20:5
|
||||||
|
|
|
||||||
|
LL | is(1, (), "", ());
|
||||||
|
| ^^ -- -- unexpected argument #4 of type `()`
|
||||||
|
| |
|
||||||
|
| unexpected argument #2 of type `()`
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/issue-109425.rs:5:4
|
||||||
|
|
|
||||||
|
LL | fn is(_: u32, _: &str) {}
|
||||||
|
| ^^ ------ -------
|
||||||
|
help: remove the extra arguments
|
||||||
|
|
|
||||||
|
LL - is(1, (), "", ());
|
||||||
|
LL + is(1, "");
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0061]: this function takes 1 argument but 3 arguments were supplied
|
||||||
|
--> $DIR/issue-109425.rs:22:5
|
||||||
|
|
|
||||||
LL | s(0, 1, ""); // s("")
|
LL | s(0, 1, ""); // s("")
|
||||||
| ^ - - unexpected argument #2 of type `{integer}`
|
| ^ - - unexpected argument #2 of type `{integer}`
|
||||||
| |
|
| |
|
||||||
@ -93,6 +131,6 @@ LL - s(0, 1, ""); // s("")
|
|||||||
LL + s(""); // s("")
|
LL + s(""); // s("")
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0061`.
|
For more information about this error, try `rustc --explain E0061`.
|
||||||
|
@ -18,8 +18,9 @@ LL | Float(Option<f64>),
|
|||||||
| ^^^^^
|
| ^^^^^
|
||||||
help: remove the extra arguments
|
help: remove the extra arguments
|
||||||
|
|
|
|
||||||
LL ~ ,
|
LL - 0,
|
||||||
LL ~ None);
|
LL - None,
|
||||||
|
LL + None);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
Loading…
Reference in New Issue
Block a user