Skip to content

Commit b79af2f

Browse files
committed
Implement #[rustc_skip_array_during_method_dispatch]
1 parent 2faef12 commit b79af2f

File tree

8 files changed

+38
-1
lines changed

8 files changed

+38
-1
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
540540
rustc_main, Normal, template!(Word),
541541
"the `#[rustc_main]` attribute is used internally to specify test entry point function",
542542
),
543+
rustc_attr!(
544+
rustc_skip_array_during_method_dispatch, Normal, template!(Word),
545+
"the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \
546+
from method dispatch when the receiver is an array, for compatibility in editions < 2021."
547+
),
543548

544549
// ==========================================================================
545550
// Internal attributes, Testing:

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
757757
data.paren_sugar,
758758
data.has_auto_impl,
759759
data.is_marker,
760+
data.skip_array_during_method_dispatch,
760761
data.specialization_kind,
761762
self.def_path_hash(item_id),
762763
)
@@ -767,6 +768,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
767768
false,
768769
false,
769770
false,
771+
false,
770772
ty::trait_def::TraitSpecializationKind::None,
771773
self.def_path_hash(item_id),
772774
),

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,7 @@ impl EncodeContext<'a, 'tcx> {
14221422
paren_sugar: trait_def.paren_sugar,
14231423
has_auto_impl: self.tcx.trait_is_auto(def_id),
14241424
is_marker: trait_def.is_marker,
1425+
skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch,
14251426
specialization_kind: trait_def.specialization_kind,
14261427
};
14271428

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ struct TraitData {
385385
paren_sugar: bool,
386386
has_auto_impl: bool,
387387
is_marker: bool,
388+
skip_array_during_method_dispatch: bool,
388389
specialization_kind: ty::trait_def::TraitSpecializationKind,
389390
}
390391

compiler/rustc_middle/src/ty/trait_def.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ pub struct TraitDef {
3535
/// and thus `impl`s of it are allowed to overlap.
3636
pub is_marker: bool,
3737

38+
/// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
39+
/// attribute, indicating that editions before 2021 should not consider this trait
40+
/// during method dispatch if the receiver is an array.
41+
pub skip_array_during_method_dispatch: bool,
42+
3843
/// Used to determine whether the standard library is allowed to specialize
3944
/// on this trait.
4045
pub specialization_kind: TraitSpecializationKind,
@@ -82,6 +87,7 @@ impl<'tcx> TraitDef {
8287
paren_sugar: bool,
8388
has_auto_impl: bool,
8489
is_marker: bool,
90+
skip_array_during_method_dispatch: bool,
8591
specialization_kind: TraitSpecializationKind,
8692
def_path_hash: DefPathHash,
8793
) -> TraitDef {
@@ -91,6 +97,7 @@ impl<'tcx> TraitDef {
9197
paren_sugar,
9298
has_auto_impl,
9399
is_marker,
100+
skip_array_during_method_dispatch,
94101
specialization_kind,
95102
def_path_hash,
96103
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,7 @@ symbols! {
10301030
rustc_regions,
10311031
rustc_reservation_impl,
10321032
rustc_serialize,
1033+
rustc_skip_array_during_method_dispatch,
10331034
rustc_specialization_trait,
10341035
rustc_stable,
10351036
rustc_std_internal_symbol,

compiler/rustc_typeck/src/check/method/probe.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14611461
}
14621462

14631463
TraitCandidate(trait_ref) => {
1464+
if let Some(method_name) = self.method_name {
1465+
// Some trait methods are excluded for arrays before 2021.
1466+
if self_ty.is_array() && !method_name.span.rust_2021() {
1467+
let trait_def = self.tcx.trait_def(trait_ref.def_id);
1468+
if trait_def.skip_array_during_method_dispatch {
1469+
return ProbeResult::NoMatch;
1470+
}
1471+
}
1472+
}
14641473
let predicate = trait_ref.without_const().to_predicate(self.tcx);
14651474
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
14661475
if !self.predicate_may_hold(&obligation) {

compiler/rustc_typeck/src/collect.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
11911191
}
11921192

11931193
let is_marker = tcx.has_attr(def_id, sym::marker);
1194+
let skip_array_during_method_dispatch =
1195+
tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch);
11941196
let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
11951197
ty::trait_def::TraitSpecializationKind::Marker
11961198
} 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 {
11991201
ty::trait_def::TraitSpecializationKind::None
12001202
};
12011203
let def_path_hash = tcx.def_path_hash(def_id);
1202-
ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, spec_kind, def_path_hash)
1204+
ty::TraitDef::new(
1205+
def_id,
1206+
unsafety,
1207+
paren_sugar,
1208+
is_auto,
1209+
is_marker,
1210+
skip_array_during_method_dispatch,
1211+
spec_kind,
1212+
def_path_hash,
1213+
)
12031214
}
12041215

12051216
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {

0 commit comments

Comments
 (0)