Implement #[rustc_skip_array_during_method_dispatch]
This commit is contained in:
parent
2faef12b65
commit
b79af2fcde
8 changed files with 38 additions and 1 deletions
|
@ -540,6 +540,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_main, Normal, template!(Word),
|
rustc_main, Normal, template!(Word),
|
||||||
"the `#[rustc_main]` attribute is used internally to specify test entry point function",
|
"the `#[rustc_main]` attribute is used internally to specify test entry point function",
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_skip_array_during_method_dispatch, Normal, template!(Word),
|
||||||
|
"the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \
|
||||||
|
from method dispatch when the receiver is an array, for compatibility in editions < 2021."
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes, Testing:
|
// Internal attributes, Testing:
|
||||||
|
|
|
@ -757,6 +757,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
data.paren_sugar,
|
data.paren_sugar,
|
||||||
data.has_auto_impl,
|
data.has_auto_impl,
|
||||||
data.is_marker,
|
data.is_marker,
|
||||||
|
data.skip_array_during_method_dispatch,
|
||||||
data.specialization_kind,
|
data.specialization_kind,
|
||||||
self.def_path_hash(item_id),
|
self.def_path_hash(item_id),
|
||||||
)
|
)
|
||||||
|
@ -767,6 +768,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
ty::trait_def::TraitSpecializationKind::None,
|
ty::trait_def::TraitSpecializationKind::None,
|
||||||
self.def_path_hash(item_id),
|
self.def_path_hash(item_id),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1422,6 +1422,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||||
paren_sugar: trait_def.paren_sugar,
|
paren_sugar: trait_def.paren_sugar,
|
||||||
has_auto_impl: self.tcx.trait_is_auto(def_id),
|
has_auto_impl: self.tcx.trait_is_auto(def_id),
|
||||||
is_marker: trait_def.is_marker,
|
is_marker: trait_def.is_marker,
|
||||||
|
skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch,
|
||||||
specialization_kind: trait_def.specialization_kind,
|
specialization_kind: trait_def.specialization_kind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -385,6 +385,7 @@ struct TraitData {
|
||||||
paren_sugar: bool,
|
paren_sugar: bool,
|
||||||
has_auto_impl: bool,
|
has_auto_impl: bool,
|
||||||
is_marker: bool,
|
is_marker: bool,
|
||||||
|
skip_array_during_method_dispatch: bool,
|
||||||
specialization_kind: ty::trait_def::TraitSpecializationKind,
|
specialization_kind: ty::trait_def::TraitSpecializationKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,11 @@ pub struct TraitDef {
|
||||||
/// and thus `impl`s of it are allowed to overlap.
|
/// and thus `impl`s of it are allowed to overlap.
|
||||||
pub is_marker: bool,
|
pub is_marker: bool,
|
||||||
|
|
||||||
|
/// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
|
||||||
|
/// attribute, indicating that editions before 2021 should not consider this trait
|
||||||
|
/// during method dispatch if the receiver is an array.
|
||||||
|
pub skip_array_during_method_dispatch: bool,
|
||||||
|
|
||||||
/// Used to determine whether the standard library is allowed to specialize
|
/// Used to determine whether the standard library is allowed to specialize
|
||||||
/// on this trait.
|
/// on this trait.
|
||||||
pub specialization_kind: TraitSpecializationKind,
|
pub specialization_kind: TraitSpecializationKind,
|
||||||
|
@ -82,6 +87,7 @@ impl<'tcx> TraitDef {
|
||||||
paren_sugar: bool,
|
paren_sugar: bool,
|
||||||
has_auto_impl: bool,
|
has_auto_impl: bool,
|
||||||
is_marker: bool,
|
is_marker: bool,
|
||||||
|
skip_array_during_method_dispatch: bool,
|
||||||
specialization_kind: TraitSpecializationKind,
|
specialization_kind: TraitSpecializationKind,
|
||||||
def_path_hash: DefPathHash,
|
def_path_hash: DefPathHash,
|
||||||
) -> TraitDef {
|
) -> TraitDef {
|
||||||
|
@ -91,6 +97,7 @@ impl<'tcx> TraitDef {
|
||||||
paren_sugar,
|
paren_sugar,
|
||||||
has_auto_impl,
|
has_auto_impl,
|
||||||
is_marker,
|
is_marker,
|
||||||
|
skip_array_during_method_dispatch,
|
||||||
specialization_kind,
|
specialization_kind,
|
||||||
def_path_hash,
|
def_path_hash,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1030,6 +1030,7 @@ symbols! {
|
||||||
rustc_regions,
|
rustc_regions,
|
||||||
rustc_reservation_impl,
|
rustc_reservation_impl,
|
||||||
rustc_serialize,
|
rustc_serialize,
|
||||||
|
rustc_skip_array_during_method_dispatch,
|
||||||
rustc_specialization_trait,
|
rustc_specialization_trait,
|
||||||
rustc_stable,
|
rustc_stable,
|
||||||
rustc_std_internal_symbol,
|
rustc_std_internal_symbol,
|
||||||
|
|
|
@ -1461,6 +1461,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TraitCandidate(trait_ref) => {
|
TraitCandidate(trait_ref) => {
|
||||||
|
if let Some(method_name) = self.method_name {
|
||||||
|
// Some trait methods are excluded for arrays before 2021.
|
||||||
|
if self_ty.is_array() && !method_name.span.rust_2021() {
|
||||||
|
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||||
|
if trait_def.skip_array_during_method_dispatch {
|
||||||
|
return ProbeResult::NoMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let predicate = trait_ref.without_const().to_predicate(self.tcx);
|
let predicate = trait_ref.without_const().to_predicate(self.tcx);
|
||||||
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
|
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
|
||||||
if !self.predicate_may_hold(&obligation) {
|
if !self.predicate_may_hold(&obligation) {
|
||||||
|
|
|
@ -1191,6 +1191,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_marker = tcx.has_attr(def_id, sym::marker);
|
let is_marker = tcx.has_attr(def_id, sym::marker);
|
||||||
|
let skip_array_during_method_dispatch =
|
||||||
|
tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch);
|
||||||
let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
|
let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
|
||||||
ty::trait_def::TraitSpecializationKind::Marker
|
ty::trait_def::TraitSpecializationKind::Marker
|
||||||
} else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
|
} else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
|
||||||
|
@ -1199,7 +1201,16 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
||||||
ty::trait_def::TraitSpecializationKind::None
|
ty::trait_def::TraitSpecializationKind::None
|
||||||
};
|
};
|
||||||
let def_path_hash = tcx.def_path_hash(def_id);
|
let def_path_hash = tcx.def_path_hash(def_id);
|
||||||
ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, spec_kind, def_path_hash)
|
ty::TraitDef::new(
|
||||||
|
def_id,
|
||||||
|
unsafety,
|
||||||
|
paren_sugar,
|
||||||
|
is_auto,
|
||||||
|
is_marker,
|
||||||
|
skip_array_during_method_dispatch,
|
||||||
|
spec_kind,
|
||||||
|
def_path_hash,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
|
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue